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 <rle...@hortonworks.com> Authored: Tue Jan 6 21:08:16 2015 -0500 Committer: Robert Levas <rle...@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": {},