You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@slider.apache.org by jm...@apache.org on 2014/07/09 21:38:19 UTC

[2/2] git commit: SLIDER-131 enabling agent to AM one way and two way SSL

SLIDER-131 enabling agent to AM one way and two way SSL


Project: http://git-wip-us.apache.org/repos/asf/incubator-slider/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-slider/commit/859ca521
Tree: http://git-wip-us.apache.org/repos/asf/incubator-slider/tree/859ca521
Diff: http://git-wip-us.apache.org/repos/asf/incubator-slider/diff/859ca521

Branch: refs/heads/develop
Commit: 859ca521214c63c4d0956f98d001920705760bd0
Parents: 55aa2b1
Author: Jon Maron <jm...@hortonworks.com>
Authored: Wed Jul 9 15:36:59 2014 -0400
Committer: Jon Maron <jm...@hortonworks.com>
Committed: Wed Jul 9 15:36:59 2014 -0400

----------------------------------------------------------------------
 pom.xml                                         |  17 +-
 .../src/main/python/agent/AgentConfig.py        |   3 +
 .../src/main/python/agent/Controller.py         |  32 ++-
 slider-agent/src/main/python/agent/NetUtil.py   |   8 +-
 slider-agent/src/main/python/agent/main.py      |  15 +-
 slider-agent/src/main/python/agent/security.py  |   7 +-
 .../src/test/python/agent/TestController.py     |   4 +-
 slider-agent/src/test/python/agent/TestMain.py  |   8 +-
 .../src/test/python/agent/TestNetUtil.py        |   2 +-
 slider-core/pom.xml                             |   7 +
 .../java/org/apache/slider/api/StatusKeys.java  |   3 +
 .../org/apache/slider/common/SliderKeys.java    |  14 +
 .../apache/slider/common/tools/SliderUtils.java |   2 +-
 .../core/launch/ClasspathConstructor.java       |   1 -
 .../registry/info/CustomRegistryConstants.java  |   2 +-
 .../providers/AbstractProviderService.java      |   7 +-
 .../slider/providers/ProviderService.java       |   8 +-
 .../slider/providers/agent/AgentKeys.java       |   1 +
 .../providers/agent/AgentProviderService.java   |  16 +-
 .../slideram/SliderAMClientProvider.java        |   7 +-
 .../slideram/SliderAMProviderService.java       |  18 +-
 .../server/appmaster/SliderAppMaster.java       |  68 ++++-
 .../server/appmaster/web/AgentService.java      |  53 ++++
 .../server/appmaster/web/SliderAmIpFilter.java  |  18 +-
 .../slider/server/appmaster/web/WebAppApi.java  |   9 +-
 .../server/appmaster/web/WebAppApiImpl.java     |  16 +-
 .../appmaster/web/rest/AMWebServices.java       |   7 +-
 .../server/appmaster/web/rest/RestPaths.java    |   5 +-
 .../appmaster/web/rest/agent/AgentResource.java |  25 +-
 .../appmaster/web/rest/agent/AgentWebApp.java   | 203 +++++++++++++++
 .../web/rest/agent/AgentWebServices.java        |  40 +++
 .../services/security/CertificateManager.java   | 257 +++++++++++++++++++
 .../server/services/security/SecurityUtils.java | 209 +++++++++++++++
 .../services/security/SignCertResponse.java     |  67 +++++
 .../server/services/security/SignMessage.java   |  54 ++++
 .../providers/slideram/instance/appconf.json    |   5 +-
 .../main/resources/webapps/slideragent/.keep    |   0
 .../agent/TestAgentAMManagementWS.groovy        |  46 +++-
 .../model/mock/MockProviderService.groovy       |  12 +-
 .../view/TestClusterSpecificationBlock.groovy   |   2 +-
 .../web/view/TestContainerStatsBlock.groovy     |   2 +-
 .../appmaster/web/view/TestIndexBlock.groovy    |   2 +-
 .../agent/TestAgentProviderService.java         |   6 +-
 .../web/rest/agent/TestAMAgentWebServices.java  | 217 ++++++++--------
 .../management/TestAMManagementWebServices.java |   2 +-
 .../security/TestCertificateManager.java        |  60 +++++
 slider-core/src/test/python/agent/main.py       |   2 +
 .../providers/hbase/HBaseProviderService.java   |   5 +-
 48 files changed, 1381 insertions(+), 193 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 1ee78fe..a4489bb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -303,6 +303,7 @@
             <exclude>**/dfs.exclude</exclude>
             <exclude>**/*.iml</exclude>
             <exclude>**/rat.txt</exclude>
+            <exclude>**/get-hbase-site.sh</exclude>
             <exclude>DISCLAIMER</exclude>
             <exclude>app-packages/hbase/target/**</exclude>
           </excludes>
@@ -1140,9 +1141,9 @@
       </dependency>
 
 
-  <!-- ======================================================== -->
-  <!-- Mocking -->
-  <!-- ======================================================== -->
+      <!-- ======================================================== -->
+      <!-- Mocking -->
+      <!-- ======================================================== -->
 
       <dependency>
         <groupId>org.mockito</groupId>
@@ -1156,6 +1157,16 @@
         <version>${easymock.version}</version>
       </dependency>
 
+      <!-- ======================================================== -->
+      <!-- Jetty -->
+      <!-- ======================================================== -->
+
+      <dependency>
+	      <groupId>org.mortbay.jetty</groupId>
+	      <artifactId>jetty-sslengine</artifactId>
+        <version>6.1.26</version>
+      </dependency>
+
     </dependencies>
   </dependencyManagement>
 

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-agent/src/main/python/agent/AgentConfig.py
----------------------------------------------------------------------
diff --git a/slider-agent/src/main/python/agent/AgentConfig.py b/slider-agent/src/main/python/agent/AgentConfig.py
index 91adfdd..16b924c 100644
--- a/slider-agent/src/main/python/agent/AgentConfig.py
+++ b/slider-agent/src/main/python/agent/AgentConfig.py
@@ -60,6 +60,9 @@ max_retries=2
 sleep_between_retries=1
 
 [security]
+keysdir=security/keys
+server_crt=ca.crt
+passphrase_env_var_name=SLIDER_PASSPHRASE
 
 [heartbeat]
 state_interval=6

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-agent/src/main/python/agent/Controller.py
----------------------------------------------------------------------
diff --git a/slider-agent/src/main/python/agent/Controller.py b/slider-agent/src/main/python/agent/Controller.py
index b5dca92..92e9086 100644
--- a/slider-agent/src/main/python/agent/Controller.py
+++ b/slider-agent/src/main/python/agent/Controller.py
@@ -37,6 +37,7 @@ from NetUtil import NetUtil
 import ssl
 import ProcessHelper
 import Constants
+import security
 
 
 logger = logging.getLogger()
@@ -57,10 +58,10 @@ class Controller(threading.Thread):
     self.credential = None
     self.config = config
     self.hostname = config.getLabel()
-    server_url = 'http://' + config.get(AgentConfig.SERVER_SECTION,
+    server_url = 'https://' + config.get(AgentConfig.SERVER_SECTION,
                                         'hostname') + \
                  ':' + config.get(AgentConfig.SERVER_SECTION,
-                                  'port')
+                                  'secured_port')
     self.registerUrl = server_url + '/ws/v1/slider/agents/' + self.hostname + '/register'
     self.heartbeatUrl = server_url + '/ws/v1/slider/agents/' + self.hostname + '/heartbeat'
     self.netutil = NetUtil()
@@ -111,7 +112,8 @@ class Controller(threading.Thread):
     while not self.isRegistered:
       try:
         data = json.dumps(self.register.build(id))
-        logger.info("Registering with the server " + pprint.pformat(data))
+        logger.info("Registering with the server at " + self.registerUrl +
+                    " with data " + pprint.pformat(data))
         response = self.sendRequest(self.registerUrl, data)
         ret = json.loads(response)
         exitstatus = 0
@@ -395,11 +397,25 @@ class Controller(threading.Thread):
     pass
 
   def sendRequest(self, url, data):
-    req = urllib2.Request(url, data, {'Content-Type': 'application/json'})
-    f = urllib2.urlopen(req)
-    response = f.read()
-    f.close()
-    return response
+    response = None
+    try:
+        if self.cachedconnect is None: # Lazy initialization
+            self.cachedconnect = security.CachedHTTPSConnection(self.config)
+        req = urllib2.Request(url, data, {'Content-Type': 'application/json'})
+        response = self.cachedconnect.request(req)
+        return response
+    except Exception:
+        exc_type, exc_value, exc_traceback = sys.exc_info()
+        logger.error("Exception raised", exc_info=(exc_type, exc_value, exc_traceback))
+        if response is None:
+            err_msg = 'Request failed! Data: ' + str(data)
+            logger.warn(err_msg)
+            return {'exitstatus': 1, 'log': err_msg}
+        else:
+            err_msg = ('Response parsing failed! Request data: ' + str(data)
+                       + '; Response: ' + str(response))
+            logger.warn(err_msg)
+            return {'exitstatus': 1, 'log': err_msg}
 
 
 def main(argv=None):

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-agent/src/main/python/agent/NetUtil.py
----------------------------------------------------------------------
diff --git a/slider-agent/src/main/python/agent/NetUtil.py b/slider-agent/src/main/python/agent/NetUtil.py
index ed8e687..eb658f7 100644
--- a/slider-agent/src/main/python/agent/NetUtil.py
+++ b/slider-agent/src/main/python/agent/NetUtil.py
@@ -18,6 +18,7 @@ from urlparse import urlparse
 import time
 import logging
 import httplib
+from ssl import SSLError
 
 logger = logging.getLogger()
 
@@ -37,7 +38,7 @@ class NetUtil:
     logger.info("Connecting to the following url " + url);
     try:
       parsedurl = urlparse(url)
-      ca_connection = httplib.HTTPConnection(parsedurl[1])
+      ca_connection = httplib.HTTPSConnection(parsedurl[1])
       ca_connection.request("GET", parsedurl[2])
       response = ca_connection.getresponse()  
       status = response.status    
@@ -47,6 +48,11 @@ class NetUtil:
         return True
       else: 
         return False
+    except SSLError as slerror:
+        logger.error(str(slerror))
+        logger.error("SSLError: Failed to connect. Please check openssl library versions. \n" +
+                     "Refer to: https://bugzilla.redhat.com/show_bug.cgi?id=1022468 for more details.")
+        return False
     except Exception, e:
       logger.info("Failed to connect to " + str(url) + " due to " + str(e))
       return False

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-agent/src/main/python/agent/main.py
----------------------------------------------------------------------
diff --git a/slider-agent/src/main/python/agent/main.py b/slider-agent/src/main/python/agent/main.py
index 3632157..12e07ba 100644
--- a/slider-agent/src/main/python/agent/main.py
+++ b/slider-agent/src/main/python/agent/main.py
@@ -27,7 +27,6 @@ import traceback
 import os
 import time
 import errno
-import ConfigParser
 import ProcessHelper
 from Controller import Controller
 from AgentConfig import AgentConfig
@@ -40,7 +39,7 @@ agentPid = os.getpid()
 configFileRelPath = "infra/conf/agent.ini"
 logFileName = "agent.log"
 
-SERVER_STATUS_URL="http://{0}:{1}{2}"
+SERVER_STATUS_URL="https://{0}:{1}{2}"
 
 
 def signal_handler(signum, frame):
@@ -176,6 +175,7 @@ def main():
   parser.add_option("-l", "--label", dest="label", help="label of the agent", default=None)
   parser.add_option("--host", dest="host", help="AppMaster host", default=None)
   parser.add_option("--port", dest="port", help="AppMaster port", default=None)
+  parser.add_option("--secured_port", dest="secured_port", help="AppMaster 2 Way port", default=None)
   parser.add_option("--debug", dest="debug", help="Agent debug hint", default="")
   (options, args) = parser.parse_args()
 
@@ -201,12 +201,23 @@ def main():
   if options.port:
       agentConfig.set(AgentConfig.SERVER_SECTION, "port", options.port)
 
+  if options.secured_port:
+      agentConfig.set(AgentConfig.SERVER_SECTION, "secured_port", options.secured_port)
+
   if options.debug:
     agentConfig.set(AgentConfig.AGENT_SECTION, AgentConfig.APP_DBG_CMD, options.debug)
 
+  # set the security directory to a subdirectory of the run dir
+  secDir = os.path.join(agentConfig.getResolvedPath(AgentConfig.RUN_DIR), "security")
+  logger.info("Security/Keys directory: " + secDir)
+  agentConfig.set(AgentConfig.SECURITY_SECTION, "keysdir", secDir)
+
   logFile = os.path.join(agentConfig.getResolvedPath(AgentConfig.LOG_DIR), logFileName)
+
   perform_prestart_checks(agentConfig)
   ensure_folder_layout(agentConfig)
+  # create security dir if necessary
+  ensure_path_exists(secDir)
 
   setup_logging(options.verbose, logFile)
   update_log_level(agentConfig, logFile)

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-agent/src/main/python/agent/security.py
----------------------------------------------------------------------
diff --git a/slider-agent/src/main/python/agent/security.py b/slider-agent/src/main/python/agent/security.py
index 4037733..76671dc 100644
--- a/slider-agent/src/main/python/agent/security.py
+++ b/slider-agent/src/main/python/agent/security.py
@@ -140,7 +140,7 @@ class CertificateManager():
     self.keysdir = self.config.get('security', 'keysdir')
     self.server_crt=self.config.get('security', 'server_crt')
     self.server_url = 'https://' + self.config.get('server', 'hostname') + ':' \
-       + self.config.get('server', 'url_port')
+       + self.config.get('server', 'port')
     
   def getAgentKeyName(self):
     keysdir = self.config.get('security', 'keysdir')
@@ -187,7 +187,7 @@ class CertificateManager():
       logger.info("Agent certificate exists, ok")
             
   def loadSrvrCrt(self):
-    get_ca_url = self.server_url + '/cert/ca/'
+    get_ca_url = self.server_url + '/ws/v1/slider/agents/cert/ca/'
     logger.info("Downloading server cert from " + get_ca_url)
     stream = urllib2.urlopen(get_ca_url)
     response = stream.read()
@@ -196,7 +196,8 @@ class CertificateManager():
     srvr_crt_f.write(response)
       
   def reqSignCrt(self):
-    sign_crt_req_url = self.server_url + '/certs/' + hostname.hostname()
+    sign_crt_req_url = self.server_url + '/ws/v1/slider/agents/certs/' + \
+                       hostname.hostname()
     agent_crt_req_f = open(self.getAgentCrtReqName())
     agent_crt_req_content = agent_crt_req_f.read()
     passphrase_env_var = self.config.get('security', 'passphrase_env_var_name')

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-agent/src/test/python/agent/TestController.py
----------------------------------------------------------------------
diff --git a/slider-agent/src/test/python/agent/TestController.py b/slider-agent/src/test/python/agent/TestController.py
index 8c671da..939e63f 100644
--- a/slider-agent/src/test/python/agent/TestController.py
+++ b/slider-agent/src/test/python/agent/TestController.py
@@ -262,7 +262,9 @@ class TestController(unittest.TestCase):
     data = "data"
     requestMock.return_value = conMock
 
-    self.assertEqual("response", self.controller.sendRequest(url, data))
+    expected = {'exitstatus': 1, 'log': 'Request failed! Data: ' + data}
+
+    self.assertEqual(expected, self.controller.sendRequest(url, data))
     requestMock.called_once_with(url, data,
       {'Content-Type': 'application/json'})
 

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-agent/src/test/python/agent/TestMain.py
----------------------------------------------------------------------
diff --git a/slider-agent/src/test/python/agent/TestMain.py b/slider-agent/src/test/python/agent/TestMain.py
index 179d1b4..9ef1cad 100644
--- a/slider-agent/src/test/python/agent/TestMain.py
+++ b/slider-agent/src/test/python/agent/TestMain.py
@@ -259,10 +259,11 @@ class TestMain(unittest.TestCase):
     self.assertTrue(start_mock.called)
 
   class AgentOptions:
-      def __init__(self, label, host, port, verbose, debug):
+      def __init__(self, label, host, port, secured_port, verbose, debug):
           self.label = label
           self.host = host
           self.port = port
+          self.secured_port = secured_port
           self.verbose = verbose
           self.debug = debug
 
@@ -290,16 +291,17 @@ class TestMain(unittest.TestCase):
       Controller_init_mock.return_value = None
       isAlive_mock.return_value = False
       parse_args_mock.return_value = (
-          TestMain.AgentOptions("agent", "host1", "8080", True, ""), [])
+          TestMain.AgentOptions("agent", "host1", "8080", "8081", True, ""), [])
       tmpdir = tempfile.gettempdir()
 
       #testing call without command-line arguments
       os.environ["AGENT_WORK_ROOT"] = os.path.join(tmpdir, "work")
       os.environ["AGENT_LOG_ROOT"] = os.path.join(tmpdir, "log")
       main.main()
-      self.assertTrue(AgentConfig_set_mock.call_count == 2)
+      self.assertTrue(AgentConfig_set_mock.call_count == 4)
       AgentConfig_set_mock.assert_any_call("server", "hostname", "host1")
       AgentConfig_set_mock.assert_any_call("server", "port", "8080")
+      AgentConfig_set_mock.assert_any_call("server", "secured_port", "8081")
 
 
 if __name__ == "__main__":

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-agent/src/test/python/agent/TestNetUtil.py
----------------------------------------------------------------------
diff --git a/slider-agent/src/test/python/agent/TestNetUtil.py b/slider-agent/src/test/python/agent/TestNetUtil.py
index c19ec19..550e148 100644
--- a/slider-agent/src/test/python/agent/TestNetUtil.py
+++ b/slider-agent/src/test/python/agent/TestNetUtil.py
@@ -25,7 +25,7 @@ import unittest
 class TestNetUtil(unittest.TestCase):
 
   @patch("urlparse.urlparse")
-  @patch("httplib.HTTPConnection")
+  @patch("httplib.HTTPSConnection")
   def test_checkURL(self, httpsConMock, parseMock):
 
     NetUtil.logger = MagicMock()

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-core/pom.xml
----------------------------------------------------------------------
diff --git a/slider-core/pom.xml b/slider-core/pom.xml
index ca09541..b6120fb 100644
--- a/slider-core/pom.xml
+++ b/slider-core/pom.xml
@@ -215,6 +215,7 @@
             <exclude>src/test/python/agent.ini</exclude>
             <exclude>src/test/python/version</exclude>
             <exclude>src/main/resources/webapps/slideram/.keep</exclude>
+            <exclude>src/main/resources/webapps/slideragent/.keep</exclude>
             <exclude>src/main/resources/webapps/static/yarn.dt.plugins.js</exclude>
             <!-- jQuery DataTables files (BSD license) -->
             <exclude>src/main/resources/webapps/static/dt-1.9.4/**</exclude>
@@ -507,6 +508,12 @@
       <scope>test</scope>
     </dependency>
 
+    <dependency>
+      <groupId>org.mortbay.jetty</groupId>
+      <artifactId>jetty-sslengine</artifactId>
+      <scope>compile</scope>
+    </dependency>
+
   </dependencies>
 
 

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-core/src/main/java/org/apache/slider/api/StatusKeys.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/api/StatusKeys.java b/slider-core/src/main/java/org/apache/slider/api/StatusKeys.java
index 709c137..4bfcf41 100644
--- a/slider-core/src/main/java/org/apache/slider/api/StatusKeys.java
+++ b/slider-core/src/main/java/org/apache/slider/api/StatusKeys.java
@@ -67,4 +67,7 @@ public interface StatusKeys {
   String INFO_AM_RPC_PORT = "info.am.rpc.port";
   String INFO_AM_WEB_PORT = "info.am.web.port";
   String INFO_AM_WEB_URL = "info.am.web.url";
+  String INFO_AM_AGENT_PORT = "info.am.agent.port";
+  String INFO_AM_AGENT_URL = "info.am.agent.url";
+  String INFO_AM_SECURED_AGENT_PORT = "info.am.agent.secured.port";
 }

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-core/src/main/java/org/apache/slider/common/SliderKeys.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/common/SliderKeys.java b/slider-core/src/main/java/org/apache/slider/common/SliderKeys.java
index a0e29c9..0ba562a 100644
--- a/slider-core/src/main/java/org/apache/slider/common/SliderKeys.java
+++ b/slider-core/src/main/java/org/apache/slider/common/SliderKeys.java
@@ -151,6 +151,20 @@ public interface SliderKeys extends SliderXmlConfKeys {
 
   String HADOOP_USER_NAME = "HADOOP_USER_NAME";
   String HADOOP_PROXY_USER = "HADOOP_PROXY_USER";
+  String SLIDER_PASSPHRASE = "SLIDER_PASSPHRASE";
 
   boolean PROPAGATE_RESOURCE_OPTION = true;
+
+  /**
+   * Security associated keys.
+   */
+  String SECURITY_DIR = "security";
+  String CRT_FILE_NAME = "ca.crt";
+  String CSR_FILE_NAME = "ca.csr";
+  String KEY_FILE_NAME = "ca.key";
+  String KEYSTORE_FILE_NAME = "keystore.p12";
+  String CRT_PASS_FILE_NAME = "pass.txt";
+  String PASSPHRASE = "DEV";
+  String PASS_LEN = "50";
+  String KEYSTORE_LOCATION = "ssl.server.keystore.location";
 }

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-core/src/main/java/org/apache/slider/common/tools/SliderUtils.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/common/tools/SliderUtils.java b/slider-core/src/main/java/org/apache/slider/common/tools/SliderUtils.java
index 7c89321..17f8b70 100644
--- a/slider-core/src/main/java/org/apache/slider/common/tools/SliderUtils.java
+++ b/slider-core/src/main/java/org/apache/slider/common/tools/SliderUtils.java
@@ -473,7 +473,7 @@ public final class SliderUtils {
     }
     return trailing? 
            b.toString()
-           : (b.substring(0, b.length() - 1));
+           : (b.substring(0, b.length() - separator.length()));
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-core/src/main/java/org/apache/slider/core/launch/ClasspathConstructor.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/core/launch/ClasspathConstructor.java b/slider-core/src/main/java/org/apache/slider/core/launch/ClasspathConstructor.java
index 5b74c03..3527149 100644
--- a/slider-core/src/main/java/org/apache/slider/core/launch/ClasspathConstructor.java
+++ b/slider-core/src/main/java/org/apache/slider/core/launch/ClasspathConstructor.java
@@ -24,7 +24,6 @@ import org.apache.hadoop.yarn.api.ApplicationConstants;
 import org.apache.hadoop.yarn.conf.YarnConfiguration;
 import org.apache.slider.common.tools.SliderUtils;
 
-import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-core/src/main/java/org/apache/slider/core/registry/info/CustomRegistryConstants.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/core/registry/info/CustomRegistryConstants.java b/slider-core/src/main/java/org/apache/slider/core/registry/info/CustomRegistryConstants.java
index 1eb87c6..38fb4a5 100644
--- a/slider-core/src/main/java/org/apache/slider/core/registry/info/CustomRegistryConstants.java
+++ b/slider-core/src/main/java/org/apache/slider/core/registry/info/CustomRegistryConstants.java
@@ -32,7 +32,7 @@ public class CustomRegistryConstants {
       "org.apache.slider.publisher";
   
   public static final String AGENT_REST_API =
-      "org.apache.slider.publisher";
+      "org.apache.slider.agents";
 
   public static final String AM_IPC_PROTOCOL =
       "org.apache.slider.appmaster";

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-core/src/main/java/org/apache/slider/providers/AbstractProviderService.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/providers/AbstractProviderService.java b/slider-core/src/main/java/org/apache/slider/providers/AbstractProviderService.java
index a1940dd..e35227c 100644
--- a/slider-core/src/main/java/org/apache/slider/providers/AbstractProviderService.java
+++ b/slider-core/src/main/java/org/apache/slider/providers/AbstractProviderService.java
@@ -312,11 +312,12 @@ public abstract class AbstractProviderService
     }
   }
   @Override
-  public void applyInitialRegistryDefinitions(URL amWebAPI,
-      ServiceInstanceData registryInstanceData) throws MalformedURLException,
+  public void applyInitialRegistryDefinitions(URL unsecureWebAPI,
+                                              URL secureWebAPI,
+                                              ServiceInstanceData registryInstanceData) throws MalformedURLException,
       IOException {
 
-      this.amWebAPI = amWebAPI;
+      this.amWebAPI = unsecureWebAPI;
     this.registryInstanceData = registryInstanceData;
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-core/src/main/java/org/apache/slider/providers/ProviderService.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/providers/ProviderService.java b/slider-core/src/main/java/org/apache/slider/providers/ProviderService.java
index 1778197..56e24e9 100644
--- a/slider-core/src/main/java/org/apache/slider/providers/ProviderService.java
+++ b/slider-core/src/main/java/org/apache/slider/providers/ProviderService.java
@@ -159,10 +159,12 @@ public interface ProviderService extends ProviderCore, Service,
 
   /**
    * Prior to going live -register the initial service registry data
-   * @param amWebAPI
+   * @param unsecureWebAPI
+   * @param secureWebAPI
    * @param registryInstanceData
    */
-  void applyInitialRegistryDefinitions(URL amWebAPI,
-      ServiceInstanceData registryInstanceData) throws MalformedURLException,
+  void applyInitialRegistryDefinitions(URL unsecureWebAPI,
+                                       URL secureWebAPI,
+                                       ServiceInstanceData registryInstanceData) throws MalformedURLException,
       IOException;
 }

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-core/src/main/java/org/apache/slider/providers/agent/AgentKeys.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/providers/agent/AgentKeys.java b/slider-core/src/main/java/org/apache/slider/providers/agent/AgentKeys.java
index 96acd41..31d09c4 100644
--- a/slider-core/src/main/java/org/apache/slider/providers/agent/AgentKeys.java
+++ b/slider-core/src/main/java/org/apache/slider/providers/agent/AgentKeys.java
@@ -67,6 +67,7 @@ public interface AgentKeys {
   String ARG_LABEL = "--label";
   String ARG_HOST = "--host";
   String ARG_PORT = "--port";
+  String ARG_SECURED_PORT = "--secured_port";
   String ARG_DEBUG = "--debug";
   String AGENT_MAIN_SCRIPT_ROOT = "./infra/agent/slider-agent/";
   String AGENT_MAIN_SCRIPT = "agent/main.py";

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-core/src/main/java/org/apache/slider/providers/agent/AgentProviderService.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/providers/agent/AgentProviderService.java b/slider-core/src/main/java/org/apache/slider/providers/agent/AgentProviderService.java
index 3430baf..c1719b7 100644
--- a/slider-core/src/main/java/org/apache/slider/providers/agent/AgentProviderService.java
+++ b/slider-core/src/main/java/org/apache/slider/providers/agent/AgentProviderService.java
@@ -209,6 +209,8 @@ public class AgentProviderService extends AbstractProviderService implements
     launcher.setEnv("AGENT_LOG_ROOT", logDir);
     log.info("AGENT_LOG_ROOT set to {}", logDir);
     launcher.setEnv(HADOOP_USER_NAME, System.getenv(HADOOP_USER_NAME));
+    // for 2-Way SSL
+    launcher.setEnv(SLIDER_PASSPHRASE, SliderKeys.PASSPHRASE);
 
     //local resources
 
@@ -261,7 +263,9 @@ public class AgentProviderService extends AbstractProviderService implements
     operation.add(ARG_HOST);
     operation.add(getClusterInfoPropertyValue(StatusKeys.INFO_AM_HOSTNAME));
     operation.add(ARG_PORT);
-    operation.add(getClusterInfoPropertyValue(StatusKeys.INFO_AM_WEB_PORT));
+    operation.add(getClusterInfoPropertyValue(StatusKeys.INFO_AM_AGENT_PORT));
+    operation.add(ARG_SECURED_PORT);
+    operation.add(getClusterInfoPropertyValue(StatusKeys.INFO_AM_SECURED_AGENT_PORT));
 
     String debugCmd = agentLaunchParameter.getNextLaunchParameter(role);
     if (debugCmd != null && debugCmd.length() != 0) {
@@ -986,15 +990,19 @@ public class AgentProviderService extends AbstractProviderService implements
   }
 
   @Override
-  public void applyInitialRegistryDefinitions(URL amWebAPI,
+  public void applyInitialRegistryDefinitions(URL unsecureWebAPI,
+                                              URL secureWebAPI,
                                               ServiceInstanceData instanceData) throws IOException {
-    super.applyInitialRegistryDefinitions(amWebAPI, instanceData);
+    super.applyInitialRegistryDefinitions(unsecureWebAPI,
+                                          secureWebAPI,
+                                          instanceData
+    );
 
     try {
       instanceData.internalView.endpoints.put(
           CustomRegistryConstants.AGENT_REST_API,
           new RegisteredEndpoint(
-              new URL(amWebAPI, SLIDER_PATH_AGENTS),
+              new URL(secureWebAPI, SLIDER_PATH_AGENTS),
               "Agent REST API"));
     } catch (URISyntaxException e) {
       throw new IOException(e);

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-core/src/main/java/org/apache/slider/providers/slideram/SliderAMClientProvider.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/providers/slideram/SliderAMClientProvider.java b/slider-core/src/main/java/org/apache/slider/providers/slideram/SliderAMClientProvider.java
index 6b40856..6aeb801 100644
--- a/slider-core/src/main/java/org/apache/slider/providers/slideram/SliderAMClientProvider.java
+++ b/slider-core/src/main/java/org/apache/slider/providers/slideram/SliderAMClientProvider.java
@@ -44,6 +44,7 @@ import org.apache.slider.providers.AbstractClientProvider;
 import org.apache.slider.providers.PlacementPolicy;
 import org.apache.slider.providers.ProviderRole;
 import org.apache.slider.providers.ProviderUtils;
+import org.mortbay.jetty.security.SslSelectChannelConnector;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -160,7 +161,8 @@ public class SliderAMClientProvider extends AbstractClientProvider implements
     Class<?>[] classes = {
       JCommander.class,
       GsonBuilder.class,
-      
+      SslSelectChannelConnector.class,
+
       CuratorFramework.class,
       CuratorZookeeperClient.class,
       ServiceInstance.class,
@@ -171,7 +173,8 @@ public class SliderAMClientProvider extends AbstractClientProvider implements
       {
         JCOMMANDER_JAR,
         GSON_JAR,
-        
+        "jetty-sslengine.jar",
+
         "curator-framework.jar",
         "curator-client.jar",
         "curator-x-discovery.jar",

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-core/src/main/java/org/apache/slider/providers/slideram/SliderAMProviderService.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/providers/slideram/SliderAMProviderService.java b/slider-core/src/main/java/org/apache/slider/providers/slideram/SliderAMProviderService.java
index 1610954..184c25a 100644
--- a/slider-core/src/main/java/org/apache/slider/providers/slideram/SliderAMProviderService.java
+++ b/slider-core/src/main/java/org/apache/slider/providers/slideram/SliderAMProviderService.java
@@ -110,9 +110,13 @@ public class SliderAMProviderService extends AbstractProviderService implements
   }
 
   @Override
-  public void applyInitialRegistryDefinitions(URL amWebAPI,
-      ServiceInstanceData instanceData) throws IOException {
-    super.applyInitialRegistryDefinitions(amWebAPI, instanceData);
+  public void applyInitialRegistryDefinitions(URL unsecureWebAPI,
+                                              URL secureWebAPI,
+                                              ServiceInstanceData instanceData) throws IOException {
+    super.applyInitialRegistryDefinitions(unsecureWebAPI,
+                                          secureWebAPI,
+                                          instanceData
+    );
 
     // now publish site.xml files
     YarnConfiguration defaultYarnConfig = new YarnConfiguration();
@@ -146,24 +150,24 @@ public class SliderAMProviderService extends AbstractProviderService implements
     try {
       RegistryView externalView = instanceData.externalView;
       RegisteredEndpoint webUI =
-          new RegisteredEndpoint(amWebAPI, "Application Master Web UI");
+          new RegisteredEndpoint(unsecureWebAPI, "Application Master Web UI");
 
       externalView.endpoints.put(CommonRegistryConstants.WEB_UI, webUI);
 
       externalView.endpoints.put(
           CustomRegistryConstants.MANAGEMENT_REST_API,
           new RegisteredEndpoint(
-              new URL(amWebAPI, SLIDER_PATH_MANAGEMENT),
+              new URL(unsecureWebAPI, SLIDER_PATH_MANAGEMENT),
               "Management REST API") );
 
       externalView.endpoints.put(
           CustomRegistryConstants.REGISTRY_REST_API,
           new RegisteredEndpoint(
-              new URL(amWebAPI, RestPaths.SLIDER_PATH_REGISTRY + "/" +
+              new URL(unsecureWebAPI, RestPaths.SLIDER_PATH_REGISTRY + "/" +
                                 RestPaths.REGISTRY_SERVICE),
               "Registry Web Service" ) );
 
-      URL publisherURL = new URL(amWebAPI, SLIDER_PATH_PUBLISHER);
+      URL publisherURL = new URL(unsecureWebAPI, SLIDER_PATH_PUBLISHER);
       externalView.endpoints.put(
           CustomRegistryConstants.PUBLISHER_REST_API,
           new RegisteredEndpoint(

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-core/src/main/java/org/apache/slider/server/appmaster/SliderAppMaster.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/SliderAppMaster.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/SliderAppMaster.java
index 739d22c..0b22910 100644
--- a/slider-core/src/main/java/org/apache/slider/server/appmaster/SliderAppMaster.java
+++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/SliderAppMaster.java
@@ -105,6 +105,8 @@ import org.apache.slider.server.appmaster.state.ProviderAppState;
 import org.apache.slider.server.appmaster.state.RMOperationHandler;
 import org.apache.slider.server.appmaster.state.RoleInstance;
 import org.apache.slider.server.appmaster.state.RoleStatus;
+import org.apache.slider.server.appmaster.web.AgentService;
+import org.apache.slider.server.appmaster.web.rest.agent.AgentWebApp;
 import org.apache.slider.server.appmaster.web.SliderAMWebApp;
 import org.apache.slider.server.appmaster.web.SliderAmFilterInitializer;
 import org.apache.slider.server.appmaster.web.SliderAmIpFilter;
@@ -112,9 +114,10 @@ import org.apache.slider.server.appmaster.web.WebAppApi;
 import org.apache.slider.server.appmaster.web.WebAppApiImpl;
 import org.apache.slider.server.appmaster.web.rest.RestPaths;
 import org.apache.slider.server.services.registry.SliderRegistryService;
+import org.apache.slider.server.services.security.CertificateManager;
 import org.apache.slider.server.services.utility.AbstractSliderLaunchedService;
-import org.apache.slider.server.services.workflow.WorkflowRpcService;
 import org.apache.slider.server.services.utility.WebAppService;
+import org.apache.slider.server.services.workflow.WorkflowRpcService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -123,6 +126,7 @@ import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.net.URI;
 import java.net.URL;
+import java.net.URLClassLoader;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -135,6 +139,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
 
+import static org.apache.slider.server.appmaster.web.rest.RestPaths.WS_AGENT_CONTEXT_ROOT;
 import static org.apache.slider.server.appmaster.web.rest.RestPaths.WS_CONTEXT_ROOT;
 
 /**
@@ -307,6 +312,8 @@ public class SliderAppMaster extends AbstractSliderLaunchedService
   @SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized")
   private InetSocketAddress rpcServiceAddress;
   private ProviderService sliderAMProvider;
+  private String agentAccessUrl;
+  private CertificateManager certificateManager;
 
   /**
    * Service Constructor
@@ -473,7 +480,7 @@ public class SliderAppMaster extends AbstractSliderLaunchedService
     // Try to get the proper filtering of static resources through the yarn proxy working
     serviceConf.set(HADOOP_HTTP_FILTER_INITIALIZERS,
                     SliderAmFilterInitializer.NAME);
-    serviceConf.set(SliderAmIpFilter.WS_CONTEXT_ROOT, WS_CONTEXT_ROOT);
+    serviceConf.set(SliderAmIpFilter.WS_CONTEXT_ROOT, WS_CONTEXT_ROOT + "|" + WS_AGENT_CONTEXT_ROOT);
     
     //get our provider
     MapOperations globalInternalOptions =
@@ -590,10 +597,20 @@ public class SliderAppMaster extends AbstractSliderLaunchedService
       providerRoles.addAll(SliderAMClientProvider.ROLES);
 
       // Start up the WebApp and track the URL for it
+      certificateManager = new CertificateManager();
+      certificateManager.initRootCert(
+          instanceDefinition.getAppConfOperations()
+              .getComponent(SliderKeys.COMPONENT_AM));
+
+      startAgentWebApp(appInformation, serviceConf);
+
       webApp = new SliderAMWebApp(registry);
       WebApps.$for(SliderAMWebApp.BASE_PATH, WebAppApi.class,
-          new WebAppApiImpl(this, stateForProviders, providerService),
-          RestPaths.WS_CONTEXT)
+                   new WebAppApiImpl(this,
+                                     stateForProviders,
+                                     providerService,
+                                     certificateManager),
+                   RestPaths.WS_CONTEXT)
                       .with(serviceConf)
                       .start(webApp);
       appMasterTrackingUrl = "http://" + appMasterHostname + ":" + webApp.port();
@@ -605,7 +622,7 @@ public class SliderAppMaster extends AbstractSliderLaunchedService
       addService(webAppService);
 
       appInformation.put(StatusKeys.INFO_AM_WEB_URL, appMasterTrackingUrl + "/");
-      appInformation.set(StatusKeys.INFO_AM_WEB_PORT, webApp.port());      
+      appInformation.set(StatusKeys.INFO_AM_WEB_PORT, webApp.port());
 
       // Register self with ResourceManager
       // This will start heartbeating to the RM
@@ -723,6 +740,32 @@ public class SliderAppMaster extends AbstractSliderLaunchedService
     return amExitCode;
   }
 
+  private void startAgentWebApp(MapOperations appInformation,
+                                Configuration serviceConf) {
+    LOG_YARN.info("AM classpath:" + ((URLClassLoader) AgentWebApp.class.getClassLoader() ).getURLs());
+    // Start up the agent web app and track the URL for it
+    AgentWebApp agentWebApp = AgentWebApp.$for(AgentWebApp.BASE_PATH,
+                     new WebAppApiImpl(this,
+                                       stateForProviders,
+                                       providerService,
+                                       certificateManager),
+                     RestPaths.AGENT_WS_CONTEXT)
+        .withComponentConfig(getInstanceDefinition().getAppConfOperations()
+                                 .getComponent(SliderKeys.COMPONENT_AM))
+        .start();
+    agentAccessUrl = "https://" + appMasterHostname + ":" + agentWebApp.getSecuredPort();
+    AgentService agentService =
+      new AgentService("slider-agent", agentWebApp);
+
+    agentService.init(serviceConf);
+    agentService.start();
+    addService(agentService);
+
+    appInformation.put(StatusKeys.INFO_AM_AGENT_URL, agentAccessUrl + "/");
+    appInformation.set(StatusKeys.INFO_AM_AGENT_PORT, agentWebApp.getPort());
+    appInformation.set(StatusKeys.INFO_AM_SECURED_AGENT_PORT,
+                       agentWebApp.getSecuredPort());
+  }
 
   /**
    * This registers the service instance and its external values
@@ -733,7 +776,8 @@ public class SliderAppMaster extends AbstractSliderLaunchedService
   private void registerServiceInstance(String instanceName,
       ApplicationId appid) throws Exception {
     // the registry is running, so register services
-    URL amWebAPI = new URL(appMasterTrackingUrl);
+    URL unsecureWebAPI = new URL(appMasterTrackingUrl);
+    URL secureWebAPI = new URL(agentAccessUrl);
     String serviceName = SliderKeys.APP_TYPE;
     int id = appid.getId();
     String appServiceType = RegistryNaming.createRegistryServiceType(
@@ -762,16 +806,22 @@ public class SliderAppMaster extends AbstractSliderLaunchedService
 
     // internal services
    
-    sliderAMProvider.applyInitialRegistryDefinitions(amWebAPI, instanceData);
+    sliderAMProvider.applyInitialRegistryDefinitions(unsecureWebAPI,
+                                                     secureWebAPI,
+                                                     instanceData
+    );
 
     // provider service dynamic definitions.
-    providerService.applyInitialRegistryDefinitions(amWebAPI, instanceData);
+    providerService.applyInitialRegistryDefinitions(unsecureWebAPI,
+                                                    secureWebAPI,
+                                                    instanceData
+    );
 
 
     // push the registration info to ZK
 
     registry.registerSelf(
-        instanceData, amWebAPI
+        instanceData, unsecureWebAPI
     );
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-core/src/main/java/org/apache/slider/server/appmaster/web/AgentService.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/web/AgentService.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/AgentService.java
new file mode 100644
index 0000000..08338e8
--- /dev/null
+++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/AgentService.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.slider.server.appmaster.web;
+
+import org.apache.hadoop.service.AbstractService;
+import org.apache.slider.server.appmaster.web.rest.agent.AgentWebApp;
+
+/**
+ *
+ */
+public class AgentService extends AbstractService {
+  private volatile AgentWebApp webApp;
+
+  public AgentService(String name) {
+    super(name);
+  }
+
+  public AgentService(String name, AgentWebApp app) {
+    super(name);
+    webApp = app;
+  }
+
+  @Override
+  protected void serviceStart() throws Exception {
+
+  }
+
+  /**
+   * Stop operation stops the webapp; sets the reference to null
+   * @throws Exception
+   */
+  @Override
+  protected void serviceStop() throws Exception {
+    if (webApp != null) {
+      webApp.stop();
+      webApp = null;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-core/src/main/java/org/apache/slider/server/appmaster/web/SliderAmIpFilter.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/web/SliderAmIpFilter.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/SliderAmIpFilter.java
index aba344e..ad5e219 100644
--- a/slider-core/src/main/java/org/apache/slider/server/appmaster/web/SliderAmIpFilter.java
+++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/SliderAmIpFilter.java
@@ -36,7 +36,9 @@ import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
+import java.util.Arrays;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 
 public class SliderAmIpFilter implements Filter {
@@ -54,13 +56,13 @@ public class SliderAmIpFilter implements Filter {
   private Set<String> proxyAddresses = null;
   private long lastUpdate;
   private String proxyUriBase;
-  private String wsContextRoot;
+  private List<String> wsContextRoots;
   
   @Override
   public void init(FilterConfig conf) throws ServletException {
     proxyHost = conf.getInitParameter(PROXY_HOST);
     proxyUriBase = conf.getInitParameter(PROXY_URI_BASE);
-    wsContextRoot = conf.getInitParameter(WS_CONTEXT_ROOT);
+    wsContextRoots = Arrays.asList(conf.getInitParameter(WS_CONTEXT_ROOT).split("\\|"));
   }
   
   protected Set<String> getProxyAddresses() throws ServletException {
@@ -102,7 +104,7 @@ public class SliderAmIpFilter implements Filter {
       log.debug("Remote address for request is: " + httpReq.getRemoteAddr());
     }
     String requestURI = httpReq.getRequestURI();
-    if(!requestURI.startsWith(wsContextRoot) &&
+      if(!isWsRequest(requestURI) &&
        !getProxyAddresses().contains(httpReq.getRemoteAddr())) {
       String redirectUrl = httpResp.encodeRedirectURL(proxyUriBase +
                                                       requestURI);
@@ -136,4 +138,14 @@ public class SliderAmIpFilter implements Filter {
       throw e;
     }
   }
+
+  private boolean isWsRequest(String requestURI) {
+    boolean isWsReq = false;
+    for (String wsContext : wsContextRoots) {
+      isWsReq = requestURI.startsWith(wsContext);
+      if (isWsReq) break;
+    }
+
+    return isWsReq;
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-core/src/main/java/org/apache/slider/server/appmaster/web/WebAppApi.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/web/WebAppApi.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/WebAppApi.java
index 4fac962..aa20baa 100644
--- a/slider-core/src/main/java/org/apache/slider/server/appmaster/web/WebAppApi.java
+++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/WebAppApi.java
@@ -22,6 +22,7 @@ import org.apache.slider.server.appmaster.state.AppState;
 import org.apache.slider.server.appmaster.state.RoleStatus;
 import org.apache.slider.server.appmaster.state.StateAccessForProviders;
 import org.apache.slider.server.appmaster.web.rest.agent.AgentRestOperations;
+import org.apache.slider.server.services.security.CertificateManager;
 
 import java.util.Map;
 
@@ -39,7 +40,13 @@ public interface WebAppApi {
    * The {@link ProviderService} for the current cluster
    */
   public ProviderService getProviderService();
-  
+
+
+  /**
+   * The {@link CertificateManager} for the current cluster
+   */
+  public CertificateManager getCertificateManager();
+
   /**
    * The {@link SliderClusterProtocol} for the current cluster
    */

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-core/src/main/java/org/apache/slider/server/appmaster/web/WebAppApiImpl.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/web/WebAppApiImpl.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/WebAppApiImpl.java
index 9a5a628..4eebd45 100644
--- a/slider-core/src/main/java/org/apache/slider/server/appmaster/web/WebAppApiImpl.java
+++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/WebAppApiImpl.java
@@ -23,6 +23,7 @@ import org.apache.slider.providers.ProviderService;
 import org.apache.slider.server.appmaster.state.RoleStatus;
 import org.apache.slider.server.appmaster.state.StateAccessForProviders;
 import org.apache.slider.server.appmaster.web.rest.agent.AgentRestOperations;
+import org.apache.slider.server.services.security.CertificateManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -45,9 +46,12 @@ public class WebAppApiImpl implements WebAppApi {
   protected final SliderClusterProtocol clusterProto;
   protected final StateAccessForProviders appState;
   protected final ProviderService provider;
+  protected final CertificateManager certificateManager;
   
   public WebAppApiImpl(SliderClusterProtocol clusterProto,
-                       StateAccessForProviders appState, ProviderService provider) {
+                       StateAccessForProviders appState,
+                       ProviderService provider,
+                       CertificateManager certificateManager) {
     checkNotNull(clusterProto);
     checkNotNull(appState);
     checkNotNull(provider);
@@ -55,6 +59,7 @@ public class WebAppApiImpl implements WebAppApi {
     this.clusterProto = clusterProto;
     this.appState = appState;
     this.provider = provider;
+    this.certificateManager = certificateManager;
   }
 
   /* (non-Javadoc)
@@ -73,9 +78,14 @@ public class WebAppApiImpl implements WebAppApi {
     return provider;
   }
 
+  @Override
+  public CertificateManager getCertificateManager() {
+    return certificateManager;
+  }
+
   /* (non-Javadoc)
-   * @see org.apache.slider.server.appmaster.web.WebAppApi#getClusterProtocol()
-   */
+     * @see org.apache.slider.server.appmaster.web.WebAppApi#getClusterProtocol()
+     */
   @Override
   public SliderClusterProtocol getClusterProtocol() {
     return clusterProto;

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/AMWebServices.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/AMWebServices.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/AMWebServices.java
index 91c83f2..4f068f3 100644
--- a/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/AMWebServices.java
+++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/AMWebServices.java
@@ -42,12 +42,7 @@ public class AMWebServices {
     return new ManagementResource(slider);
   }
 
-  @Path(RestPaths.SLIDER_SUBPATH_AGENTS)
-  public AgentResource getAgentResource () {
-    return new AgentResource(slider);
-  }
-
-  @Path(RestPaths.SLIDER_SUBPATH_PUBLISHER) 
+  @Path(RestPaths.SLIDER_SUBPATH_PUBLISHER)
   public PublisherResource getPublisherResource() {
     return new PublisherResource(slider);
   }

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/RestPaths.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/RestPaths.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/RestPaths.java
index d55635f..0571ca1 100644
--- a/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/RestPaths.java
+++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/RestPaths.java
@@ -24,15 +24,18 @@ package org.apache.slider.server.appmaster.web.rest;
 public class RestPaths {
 
   public static final String WS_CONTEXT = "ws";
+  public static final String AGENT_WS_CONTEXT = "ws";
   public static final String WS_CONTEXT_ROOT = "/" + WS_CONTEXT;
+  public static final String WS_AGENT_CONTEXT_ROOT = "/" + AGENT_WS_CONTEXT;
   public static final String SLIDER_CONTEXT_ROOT = WS_CONTEXT_ROOT +"/v1/slider";
+  public static final String SLIDER_AGENT_CONTEXT_ROOT = WS_AGENT_CONTEXT_ROOT +"/v1/slider";
   public static final String SLIDER_SUBPATH_MANAGEMENT = "/mgmt";
   public static final String SLIDER_SUBPATH_AGENTS = "/agents";
   public static final String SLIDER_SUBPATH_PUBLISHER = "/publisher";
 
   public static final String SLIDER_PATH_MANAGEMENT = SLIDER_CONTEXT_ROOT
                                       + SLIDER_SUBPATH_MANAGEMENT;
-  public static final String SLIDER_PATH_AGENTS = SLIDER_CONTEXT_ROOT
+  public static final String SLIDER_PATH_AGENTS = SLIDER_AGENT_CONTEXT_ROOT
                                       + SLIDER_SUBPATH_AGENTS;
   
   public static final String SLIDER_PATH_PUBLISHER = SLIDER_CONTEXT_ROOT

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/agent/AgentResource.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/agent/AgentResource.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/agent/AgentResource.java
index 96b7b47..9d1e840 100644
--- a/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/agent/AgentResource.java
+++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/agent/AgentResource.java
@@ -17,9 +17,12 @@
 package org.apache.slider.server.appmaster.web.rest.agent;
 
 import org.apache.slider.server.appmaster.web.WebAppApi;
+import org.apache.slider.server.services.security.SignCertResponse;
+import org.apache.slider.server.services.security.SignMessage;
 import org.codehaus.jackson.annotate.JsonIgnoreProperties;
 import org.codehaus.jackson.map.annotate.JsonSerialize;
 
+import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.GET;
@@ -50,14 +53,14 @@ public class AgentResource {
   }
 
   @GET
-  @Path("/agents/register")
+  @Path("/agent/register")
   public Response endpointAgentRegister() {
     Response response = Response.status(200).entity("/agent/register").build();
     return response;
   }
 
   @GET
-  @Path("/agents")
+  @Path("/agent")
   public Response endpointAgent() {
     Response response = Response.status(200).entity("/agent").build();
     return response;
@@ -94,4 +97,22 @@ public class AgentResource {
     AgentRestOperations ops = slider.getAgentRestOperations();
     return ops.handleHeartBeat(message);
   }
+
+  @GET
+  @Path("/cert/ca")
+  @Produces({MediaType.TEXT_PLAIN})
+  public String downloadSrvrCrt() {
+    return slider.getCertificateManager().getServerCert();
+  }
+
+  @Path("/certs/{hostName}")
+  @POST
+  @Consumes(MediaType.APPLICATION_JSON)
+  @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+  public SignCertResponse signAgentCrt(@PathParam("hostName") String hostname,
+                                       SignMessage message, @Context HttpServletRequest req) {
+    return slider.getCertificateManager().signAgentCrt(hostname,
+                                                       message.getCsr(),
+                                                       message.getPassphrase());
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/agent/AgentWebApp.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/agent/AgentWebApp.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/agent/AgentWebApp.java
new file mode 100644
index 0000000..54d2b1f
--- /dev/null
+++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/agent/AgentWebApp.java
@@ -0,0 +1,203 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.slider.server.appmaster.web.rest.agent;
+
+import com.google.common.base.Preconditions;
+import com.sun.jersey.api.core.ResourceConfig;
+import com.sun.jersey.spi.container.WebApplication;
+import com.sun.jersey.spi.container.servlet.ServletContainer;
+import com.sun.jersey.spi.container.servlet.WebConfig;
+import com.sun.jersey.spi.inject.SingletonTypeInjectableProvider;
+import org.apache.slider.core.conf.MapOperations;
+import org.apache.slider.server.appmaster.web.WebAppApi;
+import org.apache.slider.server.appmaster.web.rest.RestPaths;
+import org.apache.slider.server.services.security.SecurityUtils;
+import org.mortbay.jetty.Connector;
+import org.mortbay.jetty.Server;
+import org.mortbay.jetty.security.SslSelectChannelConnector;
+import org.mortbay.jetty.servlet.Context;
+import org.mortbay.jetty.servlet.ServletHolder;
+import org.mortbay.thread.QueuedThreadPool;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.ext.Provider;
+import java.io.File;
+import java.util.Set;
+
+/**
+ *
+ */
+public class AgentWebApp {
+  protected static final Logger LOG = LoggerFactory.getLogger(AgentWebApp.class);
+  private int port;
+  private int securedPort;
+  private static Server agentServer;
+  public static final String BASE_PATH = "slideragent";
+
+  public static class Builder {
+    final String name;
+    final String wsName;
+    final WebAppApi application;
+    MapOperations configsMap;
+
+    public Builder(String name, String wsName, WebAppApi application) {
+      this.name = name;
+      this.wsName = wsName;
+      this.application = application;
+    }
+
+    public Builder withComponentConfig(MapOperations appMasterConfig) {
+      this.configsMap = appMasterConfig;
+      return this;
+    }
+
+    public AgentWebApp start() {
+      if (configsMap == null) {
+        throw new IllegalStateException("No SSL Configuration Available");
+      }
+
+      agentServer = new Server();
+      agentServer.setThreadPool(
+          new QueuedThreadPool(
+              configsMap.getOptionInt("agent.threadpool.size.max", 25)));
+      agentServer.setStopAtShutdown(true);
+
+      SslSelectChannelConnector ssl1WayConnector = createSSLConnector(false);
+      SslSelectChannelConnector ssl2WayConnector =
+          createSSLConnector(Boolean.valueOf(
+              configsMap.getOption("ssl.server.client.auth","false")));
+      agentServer.setConnectors(new Connector[]{ssl1WayConnector,
+          ssl2WayConnector});
+
+      ServletHolder agent = new ServletHolder(new AgentServletContainer());
+      Context agentRoot = new Context(agentServer, "/", Context.SESSIONS);
+
+      agent.setInitParameter("com.sun.jersey.config.property.resourceConfigClass",
+                             "com.sun.jersey.api.core.PackagesResourceConfig");
+      agent.setInitParameter("com.sun.jersey.config.property.packages",
+                             "org.apache.slider.server.appmaster.web.rest.agent");
+      agent.setInitParameter("com.sun.jersey.api.json.POJOMappingFeature",
+                             "true");
+//      agent.setInitParameter("com.sun.jersey.spi.container.ContainerRequestFilters", "com.sun.jersey.api.container.filter.LoggingFilter");
+//      agent.setInitParameter("com.sun.jersey.spi.container.ContainerResponseFilters", "com.sun.jersey.api.container.filter.LoggingFilter");
+//      agent.setInitParameter("com.sun.jersey.config.feature.Trace", "true");
+      agentRoot.addServlet(agent, "/*");
+
+      try {
+        agentServer.start();
+      } catch (Exception e) {
+        LOG.error("Unable to start agent server", e);
+      }
+
+      AgentWebApp webApp = new AgentWebApp();
+      webApp.setPort(getConnectorPort(agentServer, 0));
+      webApp.setSecuredPort(getConnectorPort(agentServer, 1));
+
+      return webApp;
+
+    }
+
+    private SslSelectChannelConnector createSSLConnector(boolean needClientAuth) {
+      SslSelectChannelConnector sslConnector = new
+          SslSelectChannelConnector();
+
+      String keystore = SecurityUtils.getSecurityDir() +
+                        File.separator + "keystore.p12";
+      String srvrCrtPass = SecurityUtils.getKeystorePass();
+      sslConnector.setKeystore(keystore);
+      sslConnector.setTruststore(keystore);
+      sslConnector.setPassword(srvrCrtPass);
+      sslConnector.setKeyPassword(srvrCrtPass);
+      sslConnector.setTrustPassword(srvrCrtPass);
+      sslConnector.setKeystoreType("PKCS12");
+      sslConnector.setTruststoreType("PKCS12");
+      sslConnector.setNeedClientAuth(needClientAuth);
+
+      sslConnector.setAcceptors(2);
+      return sslConnector;
+    }
+
+    @Provider
+    public class WebAppApiProvider extends
+        SingletonTypeInjectableProvider<javax.ws.rs.core.Context, WebAppApi> {
+
+      public WebAppApiProvider () {
+        super(WebAppApi.class, application);
+      }
+    }
+
+    public class AgentServletContainer extends ServletContainer {
+      public AgentServletContainer() {
+        super();
+      }
+
+      @Override
+      protected void configure(WebConfig wc,
+                               ResourceConfig rc,
+                               WebApplication wa) {
+        super.configure(wc, rc, wa);
+        Set<Object> singletons = rc.getSingletons();
+        singletons.add(new WebAppApiProvider());
+      }
+    }
+
+    private int getConnectorPort(Server webServer, int index) {
+      Preconditions.checkArgument(index >= 0);
+      if (index > webServer.getConnectors().length)
+        throw new IllegalStateException("Illegal connect index requested");
+
+      Connector c = webServer.getConnectors()[index];
+      if (c.getLocalPort() == -1) {
+        // The connector is not bounded
+        throw new IllegalStateException("The connector is not bound to a port");
+      }
+
+      return c.getLocalPort();
+    }
+  }
+
+  public static Builder $for(String name, WebAppApi app, String wsPrefix) {
+    return new Builder(name, wsPrefix, app);
+  }
+
+  public int getPort() {
+    return port;
+  }
+
+  public void setPort(int port) {
+    this.port = port;
+  }
+
+  public void setSecuredPort(int securedPort) {
+    this.securedPort = securedPort;
+  }
+
+  public int getSecuredPort() {
+    return securedPort;
+  }
+
+  public void stop() {
+    //need to stop server and reset injector
+    try {
+      agentServer.stop();
+    } catch (Exception e) {
+      LOG.warn("Unable to stop agent server", e);
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/agent/AgentWebServices.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/agent/AgentWebServices.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/agent/AgentWebServices.java
new file mode 100644
index 0000000..684ce6f
--- /dev/null
+++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/web/rest/agent/AgentWebServices.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.slider.server.appmaster.web.rest.agent;
+
+import org.apache.slider.server.appmaster.web.WebAppApi;
+import org.apache.slider.server.appmaster.web.rest.RestPaths;
+
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+
+/** The available agent REST services exposed by a slider AM. */
+@Path(RestPaths.SLIDER_AGENT_CONTEXT_ROOT)
+public class AgentWebServices {
+  /** AM/WebApp info object */
+  @Context
+  private WebAppApi slider;
+
+  public AgentWebServices() {
+  }
+
+  @Path(RestPaths.SLIDER_SUBPATH_AGENTS)
+  public AgentResource getAgentResource () {
+    return new AgentResource(slider);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-core/src/main/java/org/apache/slider/server/services/security/CertificateManager.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/services/security/CertificateManager.java b/slider-core/src/main/java/org/apache/slider/server/services/security/CertificateManager.java
new file mode 100644
index 0000000..3771208
--- /dev/null
+++ b/slider-core/src/main/java/org/apache/slider/server/services/security/CertificateManager.java
@@ -0,0 +1,257 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.slider.server.services.security;
+
+import com.google.inject.Singleton;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.RandomStringUtils;
+import org.apache.hadoop.yarn.api.ApplicationConstants;
+import org.apache.slider.common.SliderKeys;
+import org.apache.slider.core.conf.MapOperations;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.Charset;
+import java.text.MessageFormat;
+
+@Singleton
+public class CertificateManager {
+
+  private static final Logger LOG =
+      LoggerFactory.getLogger(CertificateManager.class);
+
+  private static final String GEN_SRVR_KEY = "openssl genrsa -des3 " +
+      "-passout pass:{0} -out {1}/{2} 4096 ";
+  private static final String GEN_SRVR_REQ = "openssl req -passin pass:{0} " +
+      "-new -key {1}/{2} -out {1}/{5} -batch";
+  private static final String SIGN_SRVR_CRT = "openssl ca -create_serial " +
+    "-out {1}/{3} -days 365 -keyfile {1}/{2} -key {0} -selfsign " +
+    "-extensions jdk7_ca -config {1}/ca.config -batch " +
+    "-infiles {1}/{5}";
+  private static final String EXPRT_KSTR = "openssl pkcs12 -export" +
+      " -in {1}/{3} -inkey {1}/{2} -certfile {1}/{3} -out {1}/{4} " +
+      "-password pass:{0} -passin pass:{0} \n";
+  private static final String REVOKE_AGENT_CRT = "openssl ca " +
+      "-config {0}/ca.config -keyfile {0}/{4} -revoke {0}/{2} -batch " +
+      "-passin pass:{3} -cert {0}/{5}";
+  private static final String SIGN_AGENT_CRT = "openssl ca -config " +
+      "{0}/ca.config -in {0}/{1} -out {0}/{2} -batch -passin pass:{3} " +
+      "-keyfile {0}/{4} -cert {0}/{5}"; /**
+       * Verify that root certificate exists, generate it otherwise.
+       */
+  public void initRootCert(MapOperations compOperations) {
+    SecurityUtils.initializeSecurityParameters(compOperations);
+
+    LOG.info("Initialization of root certificate");
+    boolean certExists = isCertExists();
+    LOG.info("Certificate exists:" + certExists);
+
+    if (!certExists) {
+      generateServerCertificate();
+    }
+
+  }
+
+  /**
+   * Checks root certificate state.
+   * @return "true" if certificate exists
+   */
+  private boolean isCertExists() {
+
+    String srvrKstrDir = SecurityUtils.getSecurityDir();
+    String srvrCrtName = SliderKeys.CRT_FILE_NAME;
+    File certFile = new File(srvrKstrDir + File.separator + srvrCrtName);
+    LOG.debug("srvrKstrDir = " + srvrKstrDir);
+    LOG.debug("srvrCrtName = " + srvrCrtName);
+    LOG.debug("certFile = " + certFile.getAbsolutePath());
+
+    return certFile.exists();
+  }
+
+  /**
+   * Runs os command
+   *
+   * @return command execution exit code
+   */
+  private int runCommand(String command) {
+    String line = null;
+    Process process = null;
+    BufferedReader br= null;
+    try {
+      process = Runtime.getRuntime().exec(command);
+      br = new BufferedReader(new InputStreamReader(
+          process.getInputStream(), Charset.forName("UTF8")));
+
+      while ((line = br.readLine()) != null) {
+        LOG.info(line);
+      }
+
+      try {
+        process.waitFor();
+        SecurityUtils.logOpenSslExitCode(command, process.exitValue());
+        return process.exitValue(); //command is executed
+      } catch (InterruptedException e) {
+        e.printStackTrace();
+      }
+    } catch (IOException e) {
+      e.printStackTrace();
+    } finally {
+      if (br != null) {
+        try {
+          br.close();
+        } catch (IOException ioe) {
+          ioe.printStackTrace();
+        }
+      }
+    }
+
+    return -1;//some exception occurred
+
+  }
+
+  private void generateServerCertificate() {
+    LOG.info("Generation of server certificate");
+
+    String srvrKstrDir = SecurityUtils.getSecurityDir();
+    String srvrCrtName = SliderKeys.CRT_FILE_NAME;
+    String srvrCsrName = SliderKeys.CSR_FILE_NAME;
+    String srvrKeyName = SliderKeys.KEY_FILE_NAME;
+    String kstrName = SliderKeys.KEYSTORE_FILE_NAME;
+    String srvrCrtPass = SecurityUtils.getKeystorePass();
+
+    Object[] scriptArgs = {srvrCrtPass, srvrKstrDir, srvrKeyName,
+        srvrCrtName, kstrName, srvrCsrName};
+
+    String command = MessageFormat.format(GEN_SRVR_KEY,scriptArgs);
+    runCommand(command);
+
+    command = MessageFormat.format(GEN_SRVR_REQ,scriptArgs);
+    runCommand(command);
+
+    command = MessageFormat.format(SIGN_SRVR_CRT,scriptArgs);
+    runCommand(command);
+
+    command = MessageFormat.format(EXPRT_KSTR,scriptArgs);
+    runCommand(command);
+
+  }
+
+  /**
+   * Returns server certificate content
+   * @return string with server certificate content
+   */
+  public String getServerCert() {
+    File certFile = new File(SecurityUtils.getSecurityDir() +
+        File.separator + SliderKeys.CRT_FILE_NAME);
+    String srvrCrtContent = null;
+    try {
+      srvrCrtContent = FileUtils.readFileToString(certFile);
+    } catch (IOException e) {
+      LOG.error(e.getMessage());
+    }
+    return srvrCrtContent;
+  }
+
+  /**
+   * Signs agent certificate
+   * Adds agent certificate to server keystore
+   * @return string with agent signed certificate content
+   */
+  public synchronized SignCertResponse signAgentCrt(String agentHostname,
+                                                    String agentCrtReqContent,
+                                                    String passphraseAgent) {
+    SignCertResponse response = new SignCertResponse();
+    LOG.info("Signing of agent certificate");
+    LOG.info("Verifying passphrase");
+
+    String passphraseSrvr = SliderKeys.PASSPHRASE;
+
+    if (!passphraseSrvr.equals(passphraseAgent.trim())) {
+      LOG.warn("Incorrect passphrase from the agent");
+      response.setResult(SignCertResponse.ERROR_STATUS);
+      response.setMessage("Incorrect passphrase from the agent");
+      return response;
+    }
+
+    String srvrKstrDir = SecurityUtils.getSecurityDir();
+    String srvrCrtPass = SecurityUtils.getKeystorePass();
+    String srvrCrtName = SliderKeys.CRT_FILE_NAME;
+    String srvrKeyName = SliderKeys.KEY_FILE_NAME;
+    String agentCrtReqName = agentHostname + ".csr";
+    String agentCrtName = agentHostname + ".crt";
+
+    Object[] scriptArgs = {srvrKstrDir, agentCrtReqName, agentCrtName,
+        srvrCrtPass, srvrKeyName, srvrCrtName};
+
+    //Revoke previous agent certificate if exists
+    File agentCrtFile = new File(srvrKstrDir + File.separator + agentCrtName);
+
+    if (agentCrtFile.exists()) {
+      LOG.info("Revoking of " + agentHostname + " certificate.");
+      String command = MessageFormat.format(REVOKE_AGENT_CRT, scriptArgs);
+      int commandExitCode = runCommand(command);
+      if (commandExitCode != 0) {
+        response.setResult(SignCertResponse.ERROR_STATUS);
+        response.setMessage(
+            SecurityUtils.getOpenSslCommandResult(command, commandExitCode));
+        return response;
+      }
+    }
+
+    File agentCrtReqFile = new File(srvrKstrDir + File.separator +
+        agentCrtReqName);
+    try {
+      FileUtils.writeStringToFile(agentCrtReqFile, agentCrtReqContent);
+    } catch (IOException e1) {
+      // TODO Auto-generated catch block
+      e1.printStackTrace();
+    }
+
+    String command = MessageFormat.format(SIGN_AGENT_CRT, scriptArgs);
+
+    LOG.debug(SecurityUtils.hideOpenSslPassword(command));
+
+    int commandExitCode = runCommand(command); // ssl command execution
+    if (commandExitCode != 0) {
+      response.setResult(SignCertResponse.ERROR_STATUS);
+      response.setMessage(
+          SecurityUtils.getOpenSslCommandResult(command, commandExitCode));
+      //LOG.warn(ShellCommandUtil.getOpenSslCommandResult(command, commandExitCode));
+      return response;
+    }
+
+    String agentCrtContent = "";
+    try {
+      agentCrtContent = FileUtils.readFileToString(agentCrtFile);
+    } catch (IOException e) {
+      e.printStackTrace();
+      LOG.error("Error reading signed agent certificate");
+      response.setResult(SignCertResponse.ERROR_STATUS);
+      response.setMessage("Error reading signed agent certificate");
+      return response;
+    }
+    response.setResult(SignCertResponse.OK_STATUS);
+    response.setSignedCa(agentCrtContent);
+    //LOG.info(ShellCommandUtil.getOpenSslCommandResult(command, commandExitCode));
+    return response;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-core/src/main/java/org/apache/slider/server/services/security/SecurityUtils.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/services/security/SecurityUtils.java b/slider-core/src/main/java/org/apache/slider/server/services/security/SecurityUtils.java
new file mode 100644
index 0000000..5238d90
--- /dev/null
+++ b/slider-core/src/main/java/org/apache/slider/server/services/security/SecurityUtils.java
@@ -0,0 +1,209 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.slider.server.services.security;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.RandomStringUtils;
+import org.apache.slider.common.SliderKeys;
+import org.apache.slider.core.conf.MapOperations;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.PosixFilePermission;
+import java.nio.file.attribute.PosixFilePermissions;
+import java.util.Set;
+
+/**
+ *
+ */
+public class SecurityUtils {
+  private static final Logger LOG =
+      LoggerFactory.getLogger(SecurityUtils.class);
+
+  private static String CA_CONFIG_CONTENTS ="[ ca ]\n"
+                                            + "default_ca             = CA_CLIENT\n"
+                                            + "[ CA_CLIENT ]\n"
+                                            + "dir\t\t       = ${SEC_DIR}/db\n"
+                                            + "certs                  = $dir/certs\n"
+                                            + "new_certs_dir          = $dir/newcerts\n"
+                                            + "\n"
+                                            + "database               = $dir/index.txt\n"
+                                            + "serial                 = $dir/serial\n"
+                                            + "default_days           = 365    \n"
+                                            + "\n"
+                                            + "default_crl_days       = 7  \n"
+                                            + "default_md             = md5 \n"
+                                            + "\n"
+                                            + "policy                 = policy_anything \n"
+                                            + "\n"
+                                            + "[ policy_anything ]\n"
+                                            + "countryName            = optional\n"
+                                            + "stateOrProvinceName    = optional \n"
+                                            + "localityName           = optional\n"
+                                            + "organizationName       = optional\n"
+                                            + "organizationalUnitName = optional\n"
+                                            + "commonName             = optional   \n"
+                                            + "emailAddress           = optional       \n"
+                                            + "\n"
+                                            + "[ jdk7_ca ]\n"
+                                            + "subjectKeyIdentifier = hash\n"
+                                            + "authorityKeyIdentifier = keyid:always,issuer:always\n"
+                                            + "basicConstraints = CA:true";
+
+  private static final String PASS_TOKEN = "pass:";
+  private static String keystorePass;
+  private static String securityDir;
+
+  public static void logOpenSslExitCode(String command, int exitCode) {
+    if (exitCode == 0) {
+      LOG.info(getOpenSslCommandResult(command, exitCode));
+    } else {
+      LOG.warn(getOpenSslCommandResult(command, exitCode));
+    }
+
+  }
+
+  public static String hideOpenSslPassword(String command){
+    int start = command.indexOf(PASS_TOKEN)+PASS_TOKEN.length();
+    CharSequence cs = command.subSequence(start, command.indexOf(" ", start));
+    return command.replace(cs, "****");
+  }
+
+  public static String getOpenSslCommandResult(String command, int exitCode) {
+    return new StringBuilder().append("Command ").append(hideOpenSslPassword(command)).append(" was finished with exit code: ")
+        .append(exitCode).append(" - ").append(getOpenSslExitCodeDescription(exitCode)).toString();
+  }
+
+  private static String getOpenSslExitCodeDescription(int exitCode) {
+    switch (exitCode) {
+      case 0: {
+        return "the operation was completed successfully.";
+      }
+      case 1: {
+        return "an error occurred parsing the command options.";
+      }
+      case 2: {
+        return "one of the input files could not be read.";
+      }
+      case 3: {
+        return "an error occurred creating the PKCS#7 file or when reading the MIME message.";
+      }
+      case 4: {
+        return "an error occurred decrypting or verifying the message.";
+      }
+      case 5: {
+        return "the message was verified correctly but an error occurred writing out the signers certificates.";
+      }
+      default:
+        return "unsupported code";
+    }
+  }
+
+  public static void writeCaConfigFile(String path) throws IOException {
+    String contents = CA_CONFIG_CONTENTS.replace("${SEC_DIR}", path);
+    FileUtils.writeStringToFile(new File(path, "ca.config"), contents);
+  }
+
+  public static String getKeystorePass() {
+    return keystorePass;
+  }
+
+  public static String getSecurityDir() {
+    return securityDir;
+  }
+
+  public static void initializeSecurityParameters(MapOperations configMap) {
+    String keyStoreLocation = configMap.getOption(
+        SliderKeys.KEYSTORE_LOCATION, getDefaultKeystoreLocation());
+    File secDirFile = new File(keyStoreLocation).getParentFile();
+    if (!secDirFile.exists()) {
+      // create entire required directory structure
+      File dbDir = new File(secDirFile, "db");
+      File newCertsDir = new File(dbDir, "newcerts");
+      newCertsDir.mkdirs();
+      try {
+        Set<PosixFilePermission> perms =
+            PosixFilePermissions.fromString("rwx------");
+        Files.setPosixFilePermissions(Paths.get(secDirFile.toURI()), perms);
+        Files.setPosixFilePermissions(Paths.get(dbDir.toURI()), perms);
+        Files.setPosixFilePermissions(Paths.get(newCertsDir.toURI()), perms);
+        File indexFile = new File(dbDir, "index.txt");
+        indexFile.createNewFile();
+
+        SecurityUtils.writeCaConfigFile(secDirFile.getAbsolutePath());
+
+      } catch (IOException e) {
+        LOG.error("Unable to create SSL configuration directories/files", e);
+      }
+      // need to create the password
+    }
+    keystorePass = getKeystorePassword(secDirFile);
+    securityDir = secDirFile.getAbsolutePath();
+  }
+
+  private static String getKeystorePassword(File secDirFile) {
+    File passFile = new File(secDirFile, SliderKeys.CRT_PASS_FILE_NAME);
+    String password = null;
+
+    if (!passFile.exists()) {
+      LOG.info("Generation of file with password");
+      try {
+        password = RandomStringUtils.randomAlphanumeric(
+            Integer.valueOf(SliderKeys.PASS_LEN));
+        FileUtils.writeStringToFile(passFile, password);
+        passFile.setWritable(true);
+        passFile.setReadable(true);
+      } catch (IOException e) {
+        e.printStackTrace();
+        throw new RuntimeException(
+            "Error creating certificate password file");
+      }
+    } else {
+      LOG.info("Reading password from existing file");
+      try {
+        password = FileUtils.readFileToString(passFile);
+        password = password.replaceAll("\\p{Cntrl}", "");
+      } catch (IOException e) {
+        e.printStackTrace();
+      }
+    }
+
+    return password;
+  }
+
+  private static String getDefaultKeystoreLocation() {
+    Path workDir = null;
+    try {
+      workDir = Files.createTempDirectory("sec");
+    } catch (IOException e) {
+      LOG.warn("Unable to create security directory");
+      return null;
+    }
+
+    return new StringBuilder().append(workDir.toAbsolutePath())
+        .append(File.separator)
+        .append(SliderKeys.SECURITY_DIR)
+        .append(File.separator)
+        .append(SliderKeys.KEYSTORE_FILE_NAME).toString();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/859ca521/slider-core/src/main/java/org/apache/slider/server/services/security/SignCertResponse.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/server/services/security/SignCertResponse.java b/slider-core/src/main/java/org/apache/slider/server/services/security/SignCertResponse.java
new file mode 100644
index 0000000..8437d88
--- /dev/null
+++ b/slider-core/src/main/java/org/apache/slider/server/services/security/SignCertResponse.java
@@ -0,0 +1,67 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.slider.server.services.security;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ *
+ * Sign certificate response data model.
+ *
+ */
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {})
+public class SignCertResponse {
+	
+  public static final String ERROR_STATUS = "ERROR";
+  public static final String OK_STATUS = "OK";
+
+  @XmlElement
+  private String result;
+  @XmlElement
+  private String signedCa;
+  @XmlElement
+  private String message;
+
+  public String getResult() {
+    return result;
+  }
+  public void setResult(String result) {
+    this.result = result;
+  }
+  public String getSignedCa() {
+    return signedCa;
+  }
+  public void setSignedCa(String signedCa) {
+    this.signedCa = signedCa;
+  }
+
+  public String getMessage() {
+    return message;
+  }
+  public void setMessage(String message) {
+    this.message = message;
+  }
+}
+