You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by rl...@apache.org on 2015/01/07 03:08:20 UTC

ambari git commit: AMBARI-8899. Knox service components should indicate security state (rlevas)

Repository: ambari
Updated Branches:
  refs/heads/trunk db3b306d8 -> 7159bdc40


AMBARI-8899. Knox service components should indicate security state (rlevas)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/7159bdc4
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/7159bdc4
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/7159bdc4

Branch: refs/heads/trunk
Commit: 7159bdc40f440b0d5fd38a72f15faaab02a8740d
Parents: db3b306
Author: Robert Levas <rl...@hortonworks.com>
Authored: Tue Jan 6 21:08:16 2015 -0500
Committer: Robert Levas <rl...@hortonworks.com>
Committed: Tue Jan 6 21:08:16 2015 -0500

----------------------------------------------------------------------
 .../0.5.0.2.2/package/scripts/knox_gateway.py   |  64 ++++++++++++
 .../0.5.0.2.2/package/scripts/status_params.py  |  13 +++
 .../stacks/HDP/2.2/services/KNOX/kerberos.json  |   4 +-
 .../python/stacks/2.2/KNOX/test_knox_gateway.py | 104 +++++++++++++++++++
 .../test/python/stacks/2.2/configs/secured.json |   6 ++
 5 files changed, 190 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/7159bdc4/ambari-server/src/main/resources/common-services/KNOX/0.5.0.2.2/package/scripts/knox_gateway.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/common-services/KNOX/0.5.0.2.2/package/scripts/knox_gateway.py b/ambari-server/src/main/resources/common-services/KNOX/0.5.0.2.2/package/scripts/knox_gateway.py
index f578926..cb966e4 100644
--- a/ambari-server/src/main/resources/common-services/KNOX/0.5.0.2.2/package/scripts/knox_gateway.py
+++ b/ambari-server/src/main/resources/common-services/KNOX/0.5.0.2.2/package/scripts/knox_gateway.py
@@ -18,6 +18,9 @@ limitations under the License.
 """
 
 from resource_management import *
+from resource_management.libraries.functions.security_commons import build_expectations, \
+  cached_kinit_executor, validate_security_config_properties, get_params_from_filesystem, \
+  FILE_TYPE_XML
 import sys
 
 from knox import knox
@@ -97,6 +100,67 @@ class KnoxGateway(Script):
             )
     Execute (format("rm -f {ldap_pid_file}"))
 
+  def security_status(self, env):
+    import status_params
+
+    env.set_params(status_params)
+
+    if status_params.security_enabled:
+      expectations = {}
+      expectations.update(build_expectations(
+        'krb5JAASLogin',
+        None,
+        ['keytab', 'principal'],
+        None
+      ))
+      expectations.update(build_expectations(
+        'gateway-site',
+        {
+          "gateway.hadoop.kerberos.secured" : "true"
+        },
+        None,
+        None
+      ))
+
+      security_params = {
+        "krb5JAASLogin":
+          {
+            'keytab': status_params.knox_keytab_path,
+            'principal': status_params.knox_principal_name
+          }
+      }
+      security_params.update(get_params_from_filesystem(status_params.knox_conf_dir,
+        {"gateway-site.xml" : FILE_TYPE_XML}))
+
+      result_issues = validate_security_config_properties(security_params, expectations)
+      if not result_issues:  # If all validations passed successfully
+        try:
+          # Double check the dict before calling execute
+          if ( 'krb5JAASLogin' not in security_params
+               or 'keytab' not in security_params['krb5JAASLogin']
+               or 'principal' not in security_params['krb5JAASLogin']):
+            self.put_structured_out({"securityState": "UNSECURED"})
+            self.put_structured_out({"securityIssuesFound": "Keytab file and principal are not set."})
+            return
+
+          cached_kinit_executor(status_params.kinit_path_local,
+                                status_params.knox_user,
+                                security_params['krb5JAASLogin']['keytab'],
+                                security_params['krb5JAASLogin']['principal'],
+                                status_params.hostname,
+                                status_params.temp_dir)
+          self.put_structured_out({"securityState": "SECURED_KERBEROS"})
+        except Exception as e:
+          self.put_structured_out({"securityState": "ERROR"})
+          self.put_structured_out({"securityStateErrorInfo": str(e)})
+      else:
+        issues = []
+        for cf in result_issues:
+          issues.append("Configuration file %s did not pass the validation. Reason: %s" % (cf, result_issues[cf]))
+        self.put_structured_out({"securityIssuesFound": ". ".join(issues)})
+        self.put_structured_out({"securityState": "UNSECURED"})
+    else:
+      self.put_structured_out({"securityState": "UNSECURED"})
 
 
 if __name__ == "__main__":

http://git-wip-us.apache.org/repos/asf/ambari/blob/7159bdc4/ambari-server/src/main/resources/common-services/KNOX/0.5.0.2.2/package/scripts/status_params.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/common-services/KNOX/0.5.0.2.2/package/scripts/status_params.py b/ambari-server/src/main/resources/common-services/KNOX/0.5.0.2.2/package/scripts/status_params.py
index 880c617..1bf7427 100644
--- a/ambari-server/src/main/resources/common-services/KNOX/0.5.0.2.2/package/scripts/status_params.py
+++ b/ambari-server/src/main/resources/common-services/KNOX/0.5.0.2.2/package/scripts/status_params.py
@@ -22,6 +22,19 @@ from resource_management import *
 
 config = Script.get_config()
 
+knox_conf_dir = '/etc/knox/conf'
 knox_pid_dir = config['configurations']['knox-env']['knox_pid_dir']
 knox_pid_file = format("{knox_pid_dir}/gateway.pid")
 ldap_pid_file = format("{knox_pid_dir}/ldap.pid")
+
+security_enabled = config['configurations']['cluster-env']['security_enabled']
+if security_enabled:
+    knox_keytab_path = config['configurations']['knox-env']['knox_keytab_path']
+    knox_principal_name = config['configurations']['knox-env']['knox_principal_name']
+else:
+    knox_keytab_path = None
+    knox_principal_name = None
+hostname = config['hostname'].lower()
+knox_user = default("/configurations/knox-env/knox_user", "knox")
+kinit_path_local = functions.get_kinit_path(["/usr/bin", "/usr/kerberos/bin", "/usr/sbin"])
+temp_dir = Script.get_tmp_dir()

http://git-wip-us.apache.org/repos/asf/ambari/blob/7159bdc4/ambari-server/src/main/resources/stacks/HDP/2.2/services/KNOX/kerberos.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.2/services/KNOX/kerberos.json b/ambari-server/src/main/resources/stacks/HDP/2.2/services/KNOX/kerberos.json
index 760f826..5db86cd 100644
--- a/ambari-server/src/main/resources/stacks/HDP/2.2/services/KNOX/kerberos.json
+++ b/ambari-server/src/main/resources/stacks/HDP/2.2/services/KNOX/kerberos.json
@@ -10,7 +10,9 @@
               "name": "knox_principal",
               "principal": {
                 "value": "${knox-env/knox_user}/_HOST@${realm}",
-                "configuration": "knox-env/knox_principal_name"
+                "configuration": "knox-env/knox_principal_name",
+                "local_username": "${knox-env/knox_user}"
+
               },
               "keytab": {
                 "file": "${keytab_dir}/knox.service.keytab",

http://git-wip-us.apache.org/repos/asf/ambari/blob/7159bdc4/ambari-server/src/test/python/stacks/2.2/KNOX/test_knox_gateway.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/python/stacks/2.2/KNOX/test_knox_gateway.py b/ambari-server/src/test/python/stacks/2.2/KNOX/test_knox_gateway.py
index be423fa..debd77e 100644
--- a/ambari-server/src/test/python/stacks/2.2/KNOX/test_knox_gateway.py
+++ b/ambari-server/src/test/python/stacks/2.2/KNOX/test_knox_gateway.py
@@ -17,7 +17,9 @@ 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.
 '''
+from resource_management import *
 from stacks.utils.RMFTestCase import *
+from mock.mock import patch
 
 class TestKnoxGateway(RMFTestCase):
   COMMON_SERVICES_PACKAGE_DIR = "KNOX/0.5.0.2.2/package"
@@ -93,3 +95,105 @@ class TestKnoxGateway(RMFTestCase):
     self.assertNoMoreResources()
 
 
+  @patch("resource_management.libraries.functions.security_commons.build_expectations")
+  @patch("resource_management.libraries.functions.security_commons.get_params_from_filesystem")
+  @patch("resource_management.libraries.functions.security_commons.validate_security_config_properties")
+  @patch("resource_management.libraries.functions.security_commons.cached_kinit_executor")
+  @patch("resource_management.libraries.script.Script.put_structured_out")
+  def test_security_status(self, put_structured_out_mock, cached_kinit_executor_mock,
+                           validate_security_config_mock, get_params_mock, build_exp_mock):
+    # Test that function works when is called with correct parameters
+
+    security_params = {
+      "krb5JAASLogin":
+        {
+          'keytab': "/path/to/keytab",
+          'principal': "principal"
+        },
+      "gateway-site" : {
+        "gateway.hadoop.kerberos.secured" : "true"
+      }
+    }
+
+    result_issues = []
+
+    get_params_mock.return_value = security_params
+    validate_security_config_mock.return_value = result_issues
+
+    self.executeScript(self.COMMON_SERVICES_PACKAGE_DIR + "/scripts/knox_gateway.py",
+                       classname = "KnoxGateway",
+                       command="security_status",
+                       config_file="secured.json",
+                       hdp_stack_version = self.STACK_VERSION,
+                       target = RMFTestCase.TARGET_COMMON_SERVICES
+    )
+
+    import status_params
+
+    self.assertTrue(build_exp_mock.call_count, 2)
+    build_exp_mock.assert_called_with('gateway-site', {"gateway.hadoop.kerberos.secured": "true"}, None, None)
+    put_structured_out_mock.assert_called_with({"securityState": "SECURED_KERBEROS"})
+    self.assertTrue(cached_kinit_executor_mock.call_count, 1)
+    cached_kinit_executor_mock.assert_called_with(status_params.kinit_path_local,
+                                                  status_params.knox_user,
+                                                  security_params['krb5JAASLogin']['keytab'],
+                                                  security_params['krb5JAASLogin']['principal'],
+                                                  status_params.hostname,
+                                                  status_params.temp_dir)
+
+    # Testing that the exception throw by cached_executor is caught
+    cached_kinit_executor_mock.reset_mock()
+    cached_kinit_executor_mock.side_effect = Exception("Invalid command")
+
+    try:
+      self.executeScript(self.COMMON_SERVICES_PACKAGE_DIR + "/scripts/knox_gateway.py",
+                         classname = "KnoxGateway",
+                         command="security_status",
+                         config_file="secured.json",
+                         hdp_stack_version = self.STACK_VERSION,
+                         target = RMFTestCase.TARGET_COMMON_SERVICES
+      )
+    except:
+      self.assertTrue(True)
+
+    # Testing with a security_params which doesn't contains krb5JAASLogin
+    empty_security_params = {"krb5JAASLogin" : {}}
+    cached_kinit_executor_mock.reset_mock()
+    get_params_mock.reset_mock()
+    put_structured_out_mock.reset_mock()
+    get_params_mock.return_value = empty_security_params
+
+    self.executeScript(self.COMMON_SERVICES_PACKAGE_DIR + "/scripts/knox_gateway.py",
+                       classname = "KnoxGateway",
+                       command="security_status",
+                       config_file="secured.json",
+                       hdp_stack_version = self.STACK_VERSION,
+                       target = RMFTestCase.TARGET_COMMON_SERVICES
+    )
+    put_structured_out_mock.assert_called_with({"securityIssuesFound": "Keytab file and principal are not set."})
+
+    # Testing with not empty result_issues
+    result_issues_with_params = {'krb5JAASLogin': "Something bad happened"}
+    validate_security_config_mock.reset_mock()
+    get_params_mock.reset_mock()
+    validate_security_config_mock.return_value = result_issues_with_params
+    get_params_mock.return_value = security_params
+
+    self.executeScript(self.COMMON_SERVICES_PACKAGE_DIR + "/scripts/knox_gateway.py",
+                       classname = "KnoxGateway",
+                       command="security_status",
+                       config_file="secured.json",
+                       hdp_stack_version = self.STACK_VERSION,
+                       target = RMFTestCase.TARGET_COMMON_SERVICES
+    )
+    put_structured_out_mock.assert_called_with({"securityState": "UNSECURED"})
+
+    # Testing with security_enable = false
+    self.executeScript(self.COMMON_SERVICES_PACKAGE_DIR + "/scripts/knox_gateway.py",
+                       classname = "KnoxGateway",
+                       command="security_status",
+                       config_file="default.json",
+                       hdp_stack_version = self.STACK_VERSION,
+                       target = RMFTestCase.TARGET_COMMON_SERVICES
+    )
+    put_structured_out_mock.assert_called_with({"securityState": "UNSECURED"})

http://git-wip-us.apache.org/repos/asf/ambari/blob/7159bdc4/ambari-server/src/test/python/stacks/2.2/configs/secured.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/python/stacks/2.2/configs/secured.json b/ambari-server/src/test/python/stacks/2.2/configs/secured.json
index deea45f..2d020f6 100644
--- a/ambari-server/src/test/python/stacks/2.2/configs/secured.json
+++ b/ambari-server/src/test/python/stacks/2.2/configs/secured.json
@@ -58,6 +58,12 @@
         },
         "slider-env": {
             "content": "envproperties\nline2"
+        },
+        "knox-env": {
+            "knox_master_secret": "sa",
+            "knox_group": "knox",
+            "knox_pid_dir": "/var/run/knox",
+            "knox_user": "knox"
         }
     },
     "configuration_attributes": {},