Repository: ambari Updated Branches: refs/heads/trunk 53c391541 -> b0e587e42
AMBARI-8487. Oozie 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/b0e587e4 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/b0e587e4 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/b0e587e4 Branch: refs/heads/trunk Commit: b0e587e42ad8e0c9acbbc9b643581e6a98e13652 Parents: 53c3915 Author: Robert Levas <[email protected]> Authored: Wed Jan 7 06:45:29 2015 -0500 Committer: Robert Levas <[email protected]> Committed: Wed Jan 7 06:45:29 2015 -0500 ---------------------------------------------------------------------- .../4.0.0.2.0/package/scripts/oozie_server.py | 70 +++++++++++- .../4.0.0.2.0/package/scripts/oozie_service.py | 10 +- .../OOZIE/4.0.0.2.0/package/scripts/params.py | 2 +- .../4.0.0.2.0/package/scripts/status_params.py | 7 ++ .../stacks/2.0.6/OOZIE/test_oozie_server.py | 111 +++++++++++++++++++ 5 files changed, 197 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/b0e587e4/ambari-server/src/main/resources/common-services/OOZIE/4.0.0.2.0/package/scripts/oozie_server.py ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/common-services/OOZIE/4.0.0.2.0/package/scripts/oozie_server.py b/ambari-server/src/main/resources/common-services/OOZIE/4.0.0.2.0/package/scripts/oozie_server.py index f07e36d..61615d2 100644 --- a/ambari-server/src/main/resources/common-services/OOZIE/4.0.0.2.0/package/scripts/oozie_server.py +++ b/ambari-server/src/main/resources/common-services/OOZIE/4.0.0.2.0/package/scripts/oozie_server.py @@ -20,6 +20,9 @@ limitations under the License. import sys from resource_management import * +from resource_management.libraries.functions.security_commons import build_expectations, \ + cached_kinit_executor, get_params_from_filesystem, validate_security_config_properties, \ + FILE_TYPE_XML from oozie import oozie from oozie_service import oozie_service @@ -51,6 +54,71 @@ class OozieServer(Script): import status_params env.set_params(status_params) check_process_status(status_params.pid_file) - + + + def security_status(self, env): + + import status_params + env.set_params(status_params) + + if status_params.security_enabled: + expectations = { + "oozie-site": + build_expectations('oozie-site', + { + "oozie.authentication.type": "kerberos", + "oozie.service.AuthorizationService.security.enabled": "true", + "oozie.service.HadoopAccessorService.kerberos.enabled": "true" + }, + [ + "local.realm", + "oozie.authentication.kerberos.principal", + "oozie.authentication.kerberos.keytab", + "oozie.service.HadoopAccessorService.kerberos.principal", + "oozie.service.HadoopAccessorService.keytab.file" + ], + None) + } + + security_params = get_params_from_filesystem(status_params.conf_dir, + {'oozie-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 ('oozie-site' not in security_params + or 'oozie.authentication.kerberos.principal' not in security_params['oozie-site'] + or 'oozie.authentication.kerberos.keytab' not in security_params['oozie-site'] + or 'oozie.service.HadoopAccessorService.kerberos.principal' not in security_params['oozie-site'] + or 'oozie.service.HadoopAccessorService.keytab.file' not in security_params['oozie-site']): + self.put_structured_out({"securityState": "UNSECURED"}) + self.put_structured_out({"securityIssuesFound": "Keytab file or principal are not set property."}) + return + + cached_kinit_executor(status_params.kinit_path_local, + status_params.oozie_user, + security_params['oozie-site']['oozie.authentication.kerberos.keytab'], + security_params['oozie-site']['oozie.authentication.kerberos.principal'], + status_params.hostname, + status_params.tmp_dir) + cached_kinit_executor(status_params.kinit_path_local, + status_params.oozie_user, + security_params['oozie-site']['oozie.service.HadoopAccessorService.keytab.file'], + security_params['oozie-site']['oozie.service.HadoopAccessorService.kerberos.principal'], + status_params.hostname, + status_params.tmp_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__": OozieServer().execute() http://git-wip-us.apache.org/repos/asf/ambari/blob/b0e587e4/ambari-server/src/main/resources/common-services/OOZIE/4.0.0.2.0/package/scripts/oozie_service.py ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/common-services/OOZIE/4.0.0.2.0/package/scripts/oozie_service.py b/ambari-server/src/main/resources/common-services/OOZIE/4.0.0.2.0/package/scripts/oozie_service.py index c03f944..59966fd 100644 --- a/ambari-server/src/main/resources/common-services/OOZIE/4.0.0.2.0/package/scripts/oozie_service.py +++ b/ambari-server/src/main/resources/common-services/OOZIE/4.0.0.2.0/package/scripts/oozie_service.py @@ -23,7 +23,15 @@ from resource_management import * def oozie_service(action = 'start'): # 'start' or 'stop' import params - kinit_if_needed = format("{kinit_path_local} -kt {oozie_keytab} {oozie_principal};") if params.security_enabled else "" + if params.security_enabled: + if params.oozie_principal is None: + oozie_principal_with_host = 'missing_principal' + else: + oozie_principal_with_host = params.oozie_principal.replace("_HOST", params.hostname) + kinit_if_needed = format("{kinit_path_local} -kt {oozie_keytab} {oozie_principal_with_host};") + else: + kinit_if_needed = "" + no_op_test = format("ls {pid_file} >/dev/null 2>&1 && ps -p `cat {pid_file}` >/dev/null 2>&1") if action == 'start': http://git-wip-us.apache.org/repos/asf/ambari/blob/b0e587e4/ambari-server/src/main/resources/common-services/OOZIE/4.0.0.2.0/package/scripts/params.py ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/common-services/OOZIE/4.0.0.2.0/package/scripts/params.py b/ambari-server/src/main/resources/common-services/OOZIE/4.0.0.2.0/package/scripts/params.py index 3755666..a3d3a2a 100644 --- a/ambari-server/src/main/resources/common-services/OOZIE/4.0.0.2.0/package/scripts/params.py +++ b/ambari-server/src/main/resources/common-services/OOZIE/4.0.0.2.0/package/scripts/params.py @@ -87,7 +87,7 @@ kinit_path_local = functions.get_kinit_path(["/usr/bin", "/usr/kerberos/bin", "/ oozie_service_keytab = config['configurations']['oozie-site']['oozie.service.HadoopAccessorService.keytab.file'] oozie_principal = config['configurations']['oozie-site']['oozie.service.HadoopAccessorService.kerberos.principal'] smokeuser_keytab = config['configurations']['cluster-env']['smokeuser_keytab'] -oozie_keytab = config['configurations']['oozie-env']['oozie_keytab'] +oozie_keytab = default("/configurations/oozie-env/oozie_keytab", oozie_service_keytab) oozie_env_sh_template = config['configurations']['oozie-env']['content'] oracle_driver_jar_name = "ojdbc6.jar" http://git-wip-us.apache.org/repos/asf/ambari/blob/b0e587e4/ambari-server/src/main/resources/common-services/OOZIE/4.0.0.2.0/package/scripts/status_params.py ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/common-services/OOZIE/4.0.0.2.0/package/scripts/status_params.py b/ambari-server/src/main/resources/common-services/OOZIE/4.0.0.2.0/package/scripts/status_params.py index a665449..f66448d 100644 --- a/ambari-server/src/main/resources/common-services/OOZIE/4.0.0.2.0/package/scripts/status_params.py +++ b/ambari-server/src/main/resources/common-services/OOZIE/4.0.0.2.0/package/scripts/status_params.py @@ -24,3 +24,10 @@ config = Script.get_config() oozie_pid_dir = config['configurations']['oozie-env']['oozie_pid_dir'] pid_file = format("{oozie_pid_dir}/oozie.pid") + +security_enabled = config['configurations']['cluster-env']['security_enabled'] +kinit_path_local = functions.get_kinit_path(["/usr/bin", "/usr/kerberos/bin", "/usr/sbin"]) +conf_dir = "/etc/oozie/conf" +tmp_dir = Script.get_tmp_dir() +oozie_user = config['configurations']['oozie-env']['oozie_user'] +hostname = config["hostname"] http://git-wip-us.apache.org/repos/asf/ambari/blob/b0e587e4/ambari-server/src/test/python/stacks/2.0.6/OOZIE/test_oozie_server.py ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/python/stacks/2.0.6/OOZIE/test_oozie_server.py b/ambari-server/src/test/python/stacks/2.0.6/OOZIE/test_oozie_server.py index 1fa2677..4324040 100644 --- a/ambari-server/src/test/python/stacks/2.0.6/OOZIE/test_oozie_server.py +++ b/ambari-server/src/test/python/stacks/2.0.6/OOZIE/test_oozie_server.py @@ -481,4 +481,115 @@ class TestOozieServer(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 = { + "oozie-site": { + "oozie.authentication.type": "kerberos", + "oozie.service.AuthorizationService.security.enabled": "true", + "oozie.service.HadoopAccessorService.kerberos.enabled": "true", + "local.realm": "EXAMPLE.COM", + "oozie.authentication.kerberos.principal": "principal", + "oozie.authentication.kerberos.keytab": "/path/to_keytab", + "oozie.service.HadoopAccessorService.kerberos.principal": "principal", + "oozie.service.HadoopAccessorService.keytab.file": "/path/to_keytab"} + } + result_issues = [] + props_value_check = {"oozie.authentication.type": "kerberos", + "oozie.service.AuthorizationService.security.enabled": "true", + "oozie.service.HadoopAccessorService.kerberos.enabled": "true"} + props_empty_check = [ "local.realm", + "oozie.authentication.kerberos.principal", + "oozie.authentication.kerberos.keytab", + "oozie.service.HadoopAccessorService.kerberos.principal", + "oozie.service.HadoopAccessorService.keytab.file"] + props_read_check = None + + get_params_mock.return_value = security_params + validate_security_config_mock.return_value = result_issues + + self.executeScript(self.COMMON_SERVICES_PACKAGE_DIR + "/scripts/oozie_server.py", + classname = "OozieServer", + command = "security_status", + config_file="secured.json", + hdp_stack_version = self.STACK_VERSION, + target = RMFTestCase.TARGET_COMMON_SERVICES + ) + + import status_params + + get_params_mock.assert_called_with(status_params.conf_dir, {'oozie-site.xml': 'XML'}) + build_exp_mock.assert_called_with('oozie-site', props_value_check, props_empty_check, props_read_check) + put_structured_out_mock.assert_called_with({"securityState": "SECURED_KERBEROS"}) + self.assertTrue(cached_kinit_executor_mock.call_count, 2) + cached_kinit_executor_mock.assert_called_with(status_params.kinit_path_local, + status_params.oozie_user, + security_params['oozie-site']['oozie.service.HadoopAccessorService.keytab.file'], + security_params['oozie-site']['oozie.service.HadoopAccessorService.kerberos.principal'], + status_params.hostname, + status_params.tmp_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/oozie_server.py", + classname = "OozieServer", + 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 oozie-site + empty_security_params = {} + 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/oozie_server.py", + classname = "OozieServer", + 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 or principal are not set property."}) + + # Testing with not empty result_issues + result_issues_with_params = {} + result_issues_with_params['oozie-site']="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/oozie_server.py", + classname = "OozieServer", + 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/oozie_server.py", + classname = "OozieServer", + 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"})
