This is an automated email from the ASF dual-hosted git repository.
echekanskiy pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git
The following commit(s) were added to refs/heads/trunk by this push:
new 1a6548a AMBARI-22792. Refactor agent-side kerberos code (echekanskiy)
1a6548a is described below
commit 1a6548a69970446bda994e89b76cc9cee92860c6
Author: Eugene Chekanskiy <[email protected]>
AuthorDate: Mon Jan 15 16:29:49 2018 +0200
AMBARI-22792. Refactor agent-side kerberos code (echekanskiy)
---
.../python/ambari_commons/kerberos/__init__.py | 19 +
.../ambari_commons/kerberos/kerberos_common.py | 168 +++++++
.../main/python/ambari_commons/kerberos}/utils.py | 4 +
.../ambari/server/agent/HeartbeatProcessor.java | 13 +-
.../ConfigureAmbariIdentitiesServerAction.java | 2 +
.../1.10.3-10/package/scripts/kerberos_client.py | 57 ++-
.../1.10.3-10/package/scripts/kerberos_common.py | 493 ---------------------
.../KERBEROS/1.10.3-10/package/scripts/params.py | 4 +-
.../1.10.3-10/package/scripts/service_check.py | 32 +-
.../1.10.3-30/package/scripts/kerberos_client.py | 57 ++-
.../1.10.3-30/package/scripts/kerberos_common.py | 493 ---------------------
.../KERBEROS/1.10.3-30/package/scripts/params.py | 5 +-
.../1.10.3-30/package/scripts/service_check.py | 32 +-
.../KERBEROS/1.10.3-30/package/scripts/utils.py | 105 -----
.../stacks/2.2/KERBEROS/test_kerberos_client.py | 2 +-
15 files changed, 334 insertions(+), 1152 deletions(-)
diff --git a/ambari-common/src/main/python/ambari_commons/kerberos/__init__.py
b/ambari-common/src/main/python/ambari_commons/kerberos/__init__.py
new file mode 100644
index 0000000..3cb6ecf
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_commons/kerberos/__init__.py
@@ -0,0 +1,19 @@
+#!/usr/bin/env python2.6
+
+'''
+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.
+'''
diff --git
a/ambari-common/src/main/python/ambari_commons/kerberos/kerberos_common.py
b/ambari-common/src/main/python/ambari_commons/kerberos/kerberos_common.py
new file mode 100644
index 0000000..c0ac580
--- /dev/null
+++ b/ambari-common/src/main/python/ambari_commons/kerberos/kerberos_common.py
@@ -0,0 +1,168 @@
+"""
+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.
+
+"""
+
+import base64
+import getpass
+import os
+import stat
+from ambari_agent import Constants
+from collections import namedtuple
+from resource_management.core import sudo
+from resource_management.core.logger import Logger
+from resource_management.core.resources.klist import Klist
+from resource_management.core.resources.system import Directory, File
+from resource_management.core.source import InlineTemplate
+from tempfile import gettempdir
+from .utils import get_property_value
+
+KRB5_REALM_PROPERTIES = [
+ 'kdc',
+ 'admin_server',
+ 'default_domain',
+ 'master_kdc'
+]
+
+
+class MissingKeytabs(object):
+ class Identity(namedtuple('Identity', ['principal', 'keytab_file_path'])):
+ @staticmethod
+ def from_kerberos_record(item, hostname):
+ return MissingKeytabs.Identity(
+ get_property_value(item, 'principal').replace("_HOST", hostname),
+ get_property_value(item, 'keytab_file_path'))
+
+ def __str__(self):
+ return "Keytab: %s Principal: %s" % (self.keytab_file_path,
self.principal)
+
+ @classmethod
+ def from_kerberos_records(self, kerberos_record, hostname):
+ with_missing_keytab = (each for each in kerberos_record \
+ if not self.keytab_exists(each) or not
self.keytab_has_principal(each, hostname))
+ return MissingKeytabs(
+ set(MissingKeytabs.Identity.from_kerberos_record(each, hostname) for
each in with_missing_keytab))
+
+ @staticmethod
+ def keytab_exists(kerberos_record):
+ return sudo.path_exists(get_property_value(kerberos_record,
'keytab_file_path'))
+
+ @staticmethod
+ def keytab_has_principal(kerberos_record, hostname):
+ principal = get_property_value(kerberos_record,
'principal').replace("_HOST", hostname)
+ keytab = get_property_value(kerberos_record, 'keytab_file_path')
+ klist = Klist.find_in_search_path()
+ return principal in klist.list_principals(keytab)
+
+ def __init__(self, items):
+ self.items = items
+
+ def as_dict(self):
+ return [each._asdict() for each in self.items]
+
+ def __str__(self):
+ return "Missing keytabs:\n%s" % ("\n".join(map(str, self.items))) if
self.items else 'No missing keytabs'
+
+
+def write_krb5_conf(params):
+ Directory(params.krb5_conf_dir,
+ owner='root',
+ create_parents=True,
+ group='root',
+ mode=0755
+ )
+
+ content = InlineTemplate(params.krb5_conf_template)
+
+ File(params.krb5_conf_path,
+ content=content,
+ owner='root',
+ group='root',
+ mode=0644
+ )
+
+
+def clear_tmp_cache():
+ tmp_dir = Constants.AGENT_TMP_DIR
+ if tmp_dir is None:
+ tmp_dir = gettempdir()
+ curl_krb_cache_path = os.path.join(tmp_dir, "curl_krb_cache")
+ Directory(curl_krb_cache_path, action="delete")
+
+
+def write_keytab_file(params, output_hook=lambda principal, keytab_file_path:
None):
+ if params.kerberos_command_params is not None:
+ for item in params.kerberos_command_params:
+ keytab_content_base64 = get_property_value(item, 'keytab_content_base64')
+ if (keytab_content_base64 is not None) and (len(keytab_content_base64) >
0):
+ keytab_file_path = get_property_value(item, 'keytab_file_path')
+ if (keytab_file_path is not None) and (len(keytab_file_path) > 0):
+ head, tail = os.path.split(keytab_file_path)
+ if head:
+ Directory(head, create_parents=True, mode=0755, owner="root",
group="root")
+
+ owner = get_property_value(item, 'keytab_file_owner_name')
+ if not owner:
+ owner = getpass.getuser()
+ owner_access = get_property_value(item, 'keytab_file_owner_access')
+ group = get_property_value(item, 'keytab_file_group_name')
+ group_access = get_property_value(item, 'keytab_file_group_access')
+ mode = 0
+
+ if owner_access == 'rw':
+ mode |= stat.S_IREAD | stat.S_IWRITE
+ else:
+ mode |= stat.S_IREAD
+
+ if group_access == 'rw':
+ mode |= stat.S_IRGRP | stat.S_IWGRP
+ elif group_access == 'r':
+ mode |= stat.S_IRGRP
+
+ keytab_content = base64.b64decode(keytab_content_base64)
+
+ # to hide content in command output
+ def make_lambda(data):
+ return lambda: data
+
+ File(keytab_file_path,
+ content=make_lambda(keytab_content),
+ mode=mode,
+ owner=owner,
+ group=group)
+
+ principal = get_property_value(item, 'principal')
+
+ output_hook(principal, keytab_file_path)
+
+
+def delete_keytab_file(params, output_hook=lambda principal, keytab_file_path:
None):
+ if params.kerberos_command_params is not None:
+ for item in params.kerberos_command_params:
+ keytab_file_path = get_property_value(item, 'keytab_file_path')
+ if (keytab_file_path is not None) and (len(keytab_file_path) > 0):
+ # Delete the keytab file
+ File(keytab_file_path, action="delete")
+
+ principal = get_property_value(item, 'principal')
+ output_hook(principal, keytab_file_path)
+
+
+def find_missing_keytabs(params, output_hook=lambda missing_keytabs: None):
+ missing_keytabs =
MissingKeytabs.from_kerberos_records(params.kerberos_command_params,
params.hostname)
+ Logger.info(str(missing_keytabs))
+ output_hook(missing_keytabs.as_dict())
diff --git
a/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/package/scripts/utils.py
b/ambari-common/src/main/python/ambari_commons/kerberos/utils.py
similarity index 99%
rename from
ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/package/scripts/utils.py
rename to ambari-common/src/main/python/ambari_commons/kerberos/utils.py
index 199e6d7..00b2638 100644
---
a/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/package/scripts/utils.py
+++ b/ambari-common/src/main/python/ambari_commons/kerberos/utils.py
@@ -17,6 +17,7 @@ limitations under the License.
"""
+
def get_property_value(dictionary, property_name, default_value=None,
trim_string=False,
empty_value=""):
"""
@@ -56,11 +57,13 @@ def get_property_value(dictionary, property_name,
default_value=None, trim_strin
return value
+
def get_unstructured_data(dictionary, property_name):
prefix = property_name + '/'
prefix_len = len(prefix)
return dict((k[prefix_len:], v) for k, v in dictionary.iteritems() if
k.startswith(prefix))
+
def split_host_and_port(host):
"""
Splits a string into its host and port components
@@ -86,6 +89,7 @@ def split_host_and_port(host):
return host_and_port
+
def set_port(host, port):
"""
Sets the port for a host specification, potentially replacing an existing
port declaration
diff --git
a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatProcessor.java
b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatProcessor.java
index 1374a3d..5c14ab1 100644
---
a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatProcessor.java
+++
b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatProcessor.java
@@ -429,7 +429,7 @@ public class HeartbeatProcessor extends AbstractService{
String customCommand = report.getCustomCommand();
- if (SET_KEYTAB.equalsIgnoreCase(customCommand) ||
REMOVE_KEYTAB.equalsIgnoreCase(customCommand)) {
+ if (SET_KEYTAB.equalsIgnoreCase(customCommand)) {
WriteKeytabsStructuredOut writeKeytabsStructuredOut;
try {
writeKeytabsStructuredOut =
gson.fromJson(report.getStructuredOut(), WriteKeytabsStructuredOut.class);
@@ -439,7 +439,6 @@ public class HeartbeatProcessor extends AbstractService{
}
if (writeKeytabsStructuredOut != null) {
- // TODO rework this. Make sure that keytab check and write
commands returns principal list for each keytab
if (SET_KEYTAB.equalsIgnoreCase(customCommand)) {
Map<String, String> keytabs =
writeKeytabsStructuredOut.getKeytabs();
if (keytabs != null) {
@@ -452,19 +451,15 @@ public class HeartbeatProcessor extends AbstractService{
}
}
}
- } else if (REMOVE_KEYTAB.equalsIgnoreCase(customCommand)) {
- // TODO check if additional processing of removed
records(besides existent in DestroyPrincipalsServerAction)
- // TODO is required
}
}
} else if (CHECK_KEYTABS.equalsIgnoreCase(customCommand)) {
ListKeytabsStructuredOut structuredOut =
gson.fromJson(report.getStructuredOut(), ListKeytabsStructuredOut.class);
for (MissingKeytab each : structuredOut.missingKeytabs) {
LOG.info("Missing principal: {} for keytab: {} on host: {}",
each.principal, each.keytabFilePath, hostname);
- for (KerberosKeytabPrincipalEntity kkpe:
kerberosKeytabPrincipalDAO.findByHostAndKeytab(host.getHostId(),
each.keytabFilePath)) {
- kkpe.setDistributed(false);
- kerberosKeytabPrincipalDAO.merge(kkpe);
- }
+ KerberosKeytabPrincipalEntity kkpe =
kerberosKeytabPrincipalDAO.findByHostKeytabAndPrincipal(host.getHostId(),
each.keytabFilePath, each.principal);
+ kkpe.setDistributed(false);
+ kerberosKeytabPrincipalDAO.merge(kkpe);
}
}
}
diff --git
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/ConfigureAmbariIdentitiesServerAction.java
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/ConfigureAmbariIdentitiesServerAction.java
index f6fdecd..2e626d2 100644
---
a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/ConfigureAmbariIdentitiesServerAction.java
+++
b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/ConfigureAmbariIdentitiesServerAction.java
@@ -214,6 +214,8 @@ public class ConfigureAmbariIdentitiesServerAction extends
KerberosServerAction
entity.setDistributed(true);
entity.putServiceMapping(serviceName, componentName);
kerberosKeytabPrincipalDAO.merge(entity);
+ kke.addKerberosKeytabPrincipal(entity);
+ kerberosKeytabDAO.merge(kke);
}
if (actionLog != null) {
diff --git
a/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/package/scripts/kerberos_client.py
b/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/package/scripts/kerberos_client.py
index 691c4b8..202d48a 100644
---
a/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/package/scripts/kerberos_client.py
+++
b/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/package/scripts/kerberos_client.py
@@ -17,11 +17,14 @@ limitations under the License.
"""
-from kerberos_common import *
-from resource_management.libraries.functions.security_commons import
cached_kinit_executor
from resource_management.core.exceptions import ClientComponentHasNoStatus
+from resource_management.libraries.script.script import Script
+from resource_management.libraries.functions import default
+from ambari_commons.kerberos.kerberos_common import write_krb5_conf,
clear_tmp_cache, write_keytab_file, \
+ delete_keytab_file, find_missing_keytabs
-class KerberosClient(KerberosScript):
+
+class KerberosClient(Script):
def install(self, env):
install_packages =
default('/configurations/kerberos-env/install_packages', "true")
if install_packages:
@@ -31,26 +34,58 @@ class KerberosClient(KerberosScript):
self.configure(env)
-
- def configure(self, env):
+ def configure(self, env, upgrade_type=None, config_dir=None):
import params
env.set_params(params)
if params.manage_krb5_conf:
- self.write_krb5_conf()
- #delete krb cache to prevent using old krb tickets on fresh kerberos setup
- self.clear_tmp_cache()
+ write_krb5_conf(params)
+ # delete krb cache to prevent using old krb tickets on fresh kerberos setup
+ clear_tmp_cache()
def status(self, env):
raise ClientComponentHasNoStatus()
def set_keytab(self, env):
- self.write_keytab_file()
+ import params
+
+ def output_hook(principal, keytab_file_path):
+ if principal is not None:
+ curr_content = Script.structuredOut
+
+ if "keytabs" not in curr_content:
+ curr_content['keytabs'] = {}
+
+ curr_content['keytabs'][principal.replace("_HOST", params.hostname)] =
keytab_file_path
+
+ self.put_structured_out(curr_content)
+
+ write_keytab_file(params, output_hook)
def remove_keytab(self, env):
- self.delete_keytab_file()
+ import params
+
+ def output_hook(principal, keytab_file_path):
+ if principal is not None:
+ curr_content = Script.structuredOut
+
+ if "removedKeytabs" not in curr_content:
+ curr_content['removedKeytabs'] = {}
+ curr_content['removedKeytabs'][principal.replace("_HOST",
params.hostname)] = keytab_file_path
+
+ self.put_structured_out(curr_content)
+
+ delete_keytab_file(params, output_hook)
def check_keytabs(self, env):
- self.find_missing_keytabs()
+ import params
+
+ def output_hook(missing_keytabs):
+ curr_content = Script.structuredOut
+ curr_content['missing_keytabs'] = missing_keytabs
+ self.put_structured_out(curr_content)
+
+ find_missing_keytabs(params, output_hook)
+
if __name__ == "__main__":
KerberosClient().execute()
diff --git
a/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/package/scripts/kerberos_common.py
b/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/package/scripts/kerberos_common.py
deleted file mode 100644
index fcaa547..0000000
---
a/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/package/scripts/kerberos_common.py
+++ /dev/null
@@ -1,493 +0,0 @@
-"""
-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.
-
-"""
-
-import base64
-import getpass
-import os
-import string
-import subprocess
-import sys
-import tempfile
-from tempfile import gettempdir
-
-from resource_management.libraries.script.script import Script
-from resource_management.libraries.functions.format import format
-from resource_management.libraries.functions.default import default
-from resource_management.core.exceptions import Fail
-from resource_management.core.logger import Logger
-from resource_management.core.resources.system import Directory, Execute, File
-from resource_management.core.source import InlineTemplate, Template,
DownloadSource
-from utils import get_property_value
-from ambari_commons.os_utils import remove_file
-from ambari_agent import Constants
-from collections import namedtuple
-from resource_management.core import sudo
-from resource_management.core.resources.klist import Klist
-
-class KerberosScript(Script):
- KRB5_REALM_PROPERTIES = [
- 'kdc',
- 'admin_server',
- 'default_domain',
- 'master_kdc'
- ]
-
- KRB5_SECTION_NAMES = [
- 'libdefaults',
- 'logging',
- 'realms',
- 'domain_realm',
- 'capaths',
- 'ca_paths',
- 'appdefaults',
- 'plugins'
- ]
-
- @staticmethod
- def create_random_password():
- import random
-
- chars = string.digits + string.ascii_letters
- return ''.join(random.choice(chars) for x in range(13))
-
- @staticmethod
- def write_conf_section(output_file, section_name, section_data):
- if section_name is not None:
- output_file.write('[%s]\n' % section_name)
-
- if section_data is not None:
- for key, value in section_data.iteritems():
- output_file.write(" %s = %s\n" % (key, value))
-
-
- @staticmethod
- def _write_conf_realm(output_file, realm_name, realm_data):
- """ Writes out realm details
-
- Example:
-
- EXAMPLE.COM = {
- kdc = kerberos.example.com
- admin_server = kerberos.example.com
- }
-
- """
- if realm_name is not None:
- output_file.write(" %s = {\n" % realm_name)
-
- if realm_data is not None:
- for key, value in realm_data.iteritems():
- if key in KerberosScript.KRB5_REALM_PROPERTIES:
- output_file.write(" %s = %s\n" % (key, value))
-
- output_file.write(" }\n")
-
- @staticmethod
- def write_conf_realms_section(output_file, section_name, realms_data):
- if section_name is not None:
- output_file.write('[%s]\n' % section_name)
-
- if realms_data is not None:
- for realm, realm_data in realms_data.iteritems():
- KerberosScript._write_conf_realm(output_file, realm, realm_data)
- output_file.write('\n')
-
- @staticmethod
- def write_krb5_conf():
- import params
-
- Directory(params.krb5_conf_dir,
- owner='root',
- create_parents = True,
- group='root',
- mode=0755
- )
-
- content = InlineTemplate(params.krb5_conf_template)
-
- File(params.krb5_conf_path,
- content=content,
- owner='root',
- group='root',
- mode=0644
- )
-
- @staticmethod
- def invoke_kadmin(query, admin_identity=None, default_realm=None):
- """
- Executes the kadmin or kadmin.local command (depending on whether
auth_identity is set or not
- and returns command result code and standard out data.
-
- :param query: the kadmin query to execute
- :param admin_identity: the identity for the administrative user (optional)
- :param default_realm: the default realm to assume
- :return: return_code, out
- """
- if (query is not None) and (len(query) > 0):
- auth_principal = None
- auth_keytab_file = None
-
- if admin_identity is not None:
- auth_principal = get_property_value(admin_identity, 'principal')
-
- if auth_principal is None:
- kadmin = 'kadmin.local'
- credential = ''
- else:
- kadmin = 'kadmin -p "%s"' % auth_principal
-
- auth_password = get_property_value(admin_identity, 'password')
-
- if auth_password is None:
- auth_keytab = get_property_value(admin_identity, 'keytab')
-
- if auth_keytab is not None:
- (fd, auth_keytab_file) = tempfile.mkstemp()
- os.write(fd, base64.b64decode(auth_keytab))
- os.close(fd)
-
- credential = '-k -t %s' % auth_keytab_file
- else:
- credential = '-w "%s"' % auth_password
-
- if (default_realm is not None) and (len(default_realm) > 0):
- realm = '-r %s' % default_realm
- else:
- realm = ''
-
- try:
- command = '%s %s %s -q "%s"' % (kadmin, credential, realm,
query.replace('"', '\\"'))
- return shell.checked_call(command)
- except:
- raise
- finally:
- if auth_keytab_file is not None:
- os.remove(auth_keytab_file)
-
- @staticmethod
- def create_keytab_file(principal, path, auth_identity=None):
- success = False
-
- if (principal is not None) and (len(principal) > 0):
- if (auth_identity is None) or (len(auth_identity) == 0):
- norandkey = '-norandkey'
- else:
- norandkey = ''
-
- if (path is not None) and (len(path) > 0):
- keytab_file = '-k %s' % path
- else:
- keytab_file = ''
-
- try:
- result_code, output = KerberosScript.invoke_kadmin(
- 'ktadd %s %s %s' % (keytab_file, norandkey, principal),
- auth_identity)
-
- success = (result_code == 0)
- except:
- raise Fail("Failed to create keytab for principal: %s (in %s)" %
(principal, path))
-
- return success
-
- @staticmethod
- def create_keytab(principal, auth_identity=None):
- keytab = None
-
- (fd, temp_path) = tempfile.mkstemp()
- os.remove(temp_path)
-
- try:
- if KerberosScript.create_keytab_file(principal, temp_path,
auth_identity):
- with open(temp_path, 'r') as f:
- keytab = base64.b64encode(f.read())
- finally:
- if os.path.isfile(temp_path):
- os.remove(temp_path)
-
- return keytab
-
- @staticmethod
- def principal_exists(identity, auth_identity=None):
- exists = False
-
- if identity is not None:
- principal = get_property_value(identity, 'principal')
-
- if (principal is not None) and (len(principal) > 0):
- try:
- result_code, output = KerberosScript.invoke_kadmin('getprinc %s' %
principal,
- auth_identity)
- exists = (output is not None) and (("Principal: %s" % principal) in
output)
- except:
- raise Fail("Failed to determine if principal exists: %s" % principal)
-
- return exists
-
- @staticmethod
- def change_principal_password(identity, auth_identity=None):
- success = False
-
- if identity is not None:
- principal = get_property_value(identity, 'principal')
-
- if (principal is not None) and (len(principal) > 0):
- password = get_property_value(identity, 'password')
-
- if password is None:
- credentials = '-randkey'
- else:
- credentials = '-pw "%s"' % password
-
- try:
- result_code, output = KerberosScript.invoke_kadmin(
- 'change_password %s %s' % (credentials, principal),
- auth_identity)
-
- success = (result_code == 0)
- except:
- raise Fail("Failed to create principal: %s" % principal)
-
- return success
-
- @staticmethod
- def create_principal(identity, auth_identity=None):
- success = False
-
- if identity is not None:
- principal = get_property_value(identity, 'principal')
-
- if (principal is not None) and (len(principal) > 0):
- password = get_property_value(identity, 'password')
-
- if password is None:
- credentials = '-randkey'
- else:
- credentials = '-pw "%s"' % password
-
- try:
- result_code, out = KerberosScript.invoke_kadmin(
- 'addprinc %s %s' % (credentials, principal),
- auth_identity)
-
- success = (result_code == 0)
- except:
- raise Fail("Failed to create principal: %s" % principal)
-
- return success
-
- @staticmethod
- def clear_tmp_cache():
- tmp_dir = Constants.AGENT_TMP_DIR
- if tmp_dir is None:
- tmp_dir = gettempdir()
- curl_krb_cache_path = os.path.join(tmp_dir, "curl_krb_cache")
- Directory(curl_krb_cache_path, action="delete")
-
- @staticmethod
- def create_principals(identities, auth_identity=None):
- if identities is not None:
- for identity in identities:
- KerberosScript.create_principal(identity, auth_identity)
-
- @staticmethod
- def create_or_update_administrator_identity():
- import params
-
- if params.realm is not None:
- admin_identity = params.get_property_value(params.realm,
'admin_identity')
-
- if KerberosScript.principal_exists(admin_identity):
- KerberosScript.change_principal_password(admin_identity)
- else:
- KerberosScript.create_principal(admin_identity)
-
- @staticmethod
- def test_kinit(identity, user=None):
- principal = get_property_value(identity, 'principal')
- kinit_path_local =
functions.get_kinit_path(default('/configurations/kerberos-env/executable_search_paths',
None))
- kdestroy_path_local =
functions.get_kdestroy_path(default('/configurations/kerberos-env/executable_search_paths',
None))
-
- if principal is not None:
- keytab_file = get_property_value(identity, 'keytab_file')
- keytab = get_property_value(identity, 'keytab')
- password = get_property_value(identity, 'password')
-
- # If a test keytab file is available, simply use it
- if (keytab_file is not None) and (os.path.isfile(keytab_file)):
- command = '%s -k -t %s %s' % (kinit_path_local, keytab_file, principal)
- Execute(command,
- user = user,
- )
- return shell.checked_call(kdestroy_path_local)
-
- # If base64-encoded test keytab data is available; then decode it, write
it to a temporary file
- # use it, and then remove the temporary file
- elif keytab is not None:
- (fd, test_keytab_file) = tempfile.mkstemp()
- os.write(fd, base64.b64decode(keytab))
- os.close(fd)
-
- try:
- command = '%s -k -t %s %s' % (kinit_path_local, test_keytab_file,
principal)
- Execute(command,
- user = user,
- )
- return shell.checked_call(kdestroy_path_local)
- except:
- raise
- finally:
- if test_keytab_file is not None:
- os.remove(test_keytab_file)
-
- # If no keytab data is available and a password was supplied, simply use
it.
- elif password is not None:
- process = subprocess.Popen([kinit_path_local, principal],
stdin=subprocess.PIPE)
- stdout, stderr = process.communicate(password)
- if process.returncode:
- err_msg = Logger.filter_text("Execution of kinit returned %d. %s" %
(process.returncode, stderr))
- raise Fail(err_msg)
- else:
- return shell.checked_call(kdestroy_path_local)
- else:
- return 0, ''
- else:
- return 0, ''
-
-
- def write_keytab_file(self):
- import params
- import stat
-
- if params.kerberos_command_params is not None:
- for item in params.kerberos_command_params:
- keytab_content_base64 = get_property_value(item,
'keytab_content_base64')
- if (keytab_content_base64 is not None) and (len(keytab_content_base64)
> 0):
- keytab_file_path = get_property_value(item, 'keytab_file_path')
- if (keytab_file_path is not None) and (len(keytab_file_path) > 0):
- head, tail = os.path.split(keytab_file_path)
- if head:
- Directory(head, create_parents = True, mode=0755, owner="root",
group="root")
-
- owner = get_property_value(item, 'keytab_file_owner_name')
- if not owner:
- owner = getpass.getuser()
- owner_access = get_property_value(item, 'keytab_file_owner_access')
- group = get_property_value(item, 'keytab_file_group_name')
- group_access = get_property_value(item, 'keytab_file_group_access')
- mode = 0
-
- if owner_access == 'rw':
- mode |= stat.S_IREAD | stat.S_IWRITE
- else:
- mode |= stat.S_IREAD
-
- if group_access == 'rw':
- mode |= stat.S_IRGRP | stat.S_IWGRP
- elif group_access == 'r':
- mode |= stat.S_IRGRP
-
- keytab_content = base64.b64decode(keytab_content_base64)
-
- # to hide content in command output
- def make_lambda(data):
- return lambda: data
-
- File(keytab_file_path,
- content=make_lambda(keytab_content),
- mode=mode,
- owner=owner,
- group=group)
-
- principal = get_property_value(item, 'principal')
- if principal is not None:
- curr_content = Script.structuredOut
-
- if "keytabs" not in curr_content:
- curr_content['keytabs'] = {}
-
- curr_content['keytabs'][principal.replace("_HOST",
params.hostname)] = keytab_file_path
-
- self.put_structured_out(curr_content)
-
- def delete_keytab_file(self):
- import params
-
- if params.kerberos_command_params is not None:
- for item in params.kerberos_command_params:
- keytab_file_path = get_property_value(item, 'keytab_file_path')
- if (keytab_file_path is not None) and (len(keytab_file_path) > 0):
-
- # Delete the keytab file
- File(keytab_file_path, action="delete")
-
- principal = get_property_value(item, 'principal')
- if principal is not None:
- curr_content = Script.structuredOut
-
- if "removedKeytabs" not in curr_content:
- curr_content['removedKeytabs'] = {}
- curr_content['removedKeytabs'][principal.replace("_HOST",
params.hostname)] = keytab_file_path
-
- self.put_structured_out(curr_content)
-
- def find_missing_keytabs(self):
- import params
- missing_keytabs =
MissingKeytabs.fromKerberosRecords(params.kerberos_command_params,
params.hostname)
- Logger.info(str(missing_keytabs))
- curr_content = Script.structuredOut
- curr_content['missing_keytabs'] = missing_keytabs.as_dict()
- self.put_structured_out(curr_content)
-
-class MissingKeytabs:
- class Identity(namedtuple('Identity', ['principal', 'keytab_file_path'])):
- @staticmethod
- def fromKerberosRecord(item, hostname):
- return MissingKeytabs.Identity(
- get_property_value(item, 'principal').replace("_HOST", hostname),
- get_property_value(item, 'keytab_file_path'))
-
- def __str__(self):
- return "Keytab: %s Principal: %s" % (self.keytab_file_path,
self.principal)
-
- @classmethod
- def fromKerberosRecords(self, kerberos_record, hostname):
- with_missing_keytab = (each for each in kerberos_record \
- if not self.keytab_exists(each) or not
self.keytab_has_principal(each, hostname))
- return MissingKeytabs(set(MissingKeytabs.Identity.fromKerberosRecord(each,
hostname) for each in with_missing_keytab))
-
- @staticmethod
- def keytab_exists(kerberos_record):
- return sudo.path_exists(get_property_value(kerberos_record,
'keytab_file_path'))
-
- @staticmethod
- def keytab_has_principal(kerberos_record, hostname):
- principal = get_property_value(kerberos_record,
'principal').replace("_HOST", hostname)
- keytab = get_property_value(kerberos_record, 'keytab_file_path')
- klist = Klist.find_in_search_path()
- return principal in klist.list_principals(keytab)
-
- def __init__(self, items):
- self.items = items
-
- def as_dict(self):
- return [each._asdict() for each in self.items]
-
- def __str__(self):
- return "Missing keytabs:\n%s" % ("\n".join(map(str, self.items))) if
self.items else 'No missing keytabs'
diff --git
a/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/package/scripts/params.py
b/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/package/scripts/params.py
index 5b1fafe..4c55a4d 100644
---
a/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/package/scripts/params.py
+++
b/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/package/scripts/params.py
@@ -17,12 +17,12 @@ limitations under the License.
"""
-from resource_management.libraries.script.script import Script
-from utils import get_property_value, get_unstructured_data
+from ambari_commons.kerberos.utils import get_property_value,
get_unstructured_data
from ambari_commons.os_check import OSCheck
from resource_management.libraries.functions.default import default
from resource_management.libraries.functions.expect import expect
from resource_management.libraries.functions.format import format
+from resource_management.libraries.script.script import Script
krb5_conf_dir = '/etc'
diff --git
a/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/package/scripts/service_check.py
b/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/package/scripts/service_check.py
index 1c042a7..e6a5ab3 100644
---
a/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/package/scripts/service_check.py
+++
b/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-10/package/scripts/service_check.py
@@ -18,13 +18,15 @@ limitations under the License.
Ambari Agent
"""
-from resource_management.libraries import functions
-from resource_management.libraries.functions.format import format
-from resource_management.core.resources.system import Execute, File
-from resource_management.core.logger import Logger
-from kerberos_common import *
+import os
+from resource_management.core.exceptions import Fail
+from resource_management.core.logger import Logger
+from resource_management.core.resources.system import Execute, File
+from resource_management.libraries import functions
+from resource_management.libraries.functions import default
+from resource_management.libraries.script.script import Script
# hashlib is supplied as of Python 2.5 as the replacement interface for md5
# and other secure hashes. In 2.6, md5 is deprecated. Import hashlib if
@@ -32,12 +34,15 @@ from kerberos_common import *
# preserving 2.4 compatibility.
try:
import hashlib
+
_md5 = hashlib.md5
except ImportError:
import md5
+
_md5 = md5.new
-class KerberosServiceCheck(KerberosScript):
+
+class KerberosServiceCheck(Script):
def service_check(self, env):
import params
@@ -56,21 +61,23 @@ class KerberosServiceCheck(KerberosScript):
os.path.isfile(params.smoke_test_keytab_file)):
print "Performing kinit using %s" % params.smoke_test_principal
- ccache_file_name =
_md5("{0}|{1}".format(params.smoke_test_principal,params.smoke_test_keytab_file)).hexdigest()
+ ccache_file_name = _md5("{0}|{1}".format(params.smoke_test_principal,
params.smoke_test_keytab_file)).hexdigest()
ccache_file_path =
"{0}{1}kerberos_service_check_cc_{2}".format(params.tmp_dir, os.sep,
ccache_file_name)
kinit_path_local =
functions.get_kinit_path(default('/configurations/kerberos-env/executable_search_paths',
None))
- kinit_command = "{0} -c {1} -kt {2} {3}".format(kinit_path_local,
ccache_file_path, params.smoke_test_keytab_file, params.smoke_test_principal)
+ kinit_command = "{0} -c {1} -kt {2} {3}".format(kinit_path_local,
ccache_file_path, params.smoke_test_keytab_file,
+
params.smoke_test_principal)
try:
# kinit
Execute(kinit_command,
user=params.smoke_user
- )
+ )
finally:
- File(ccache_file_path, # Since kinit might fail to write to the cache
file for various reasons, an existence check should be done before cleanup
- action = "delete",
- )
+ File(ccache_file_path,
+ # Since kinit might fail to write to the cache file for various
reasons, an existence check should be done before cleanup
+ action="delete",
+ )
elif params.manage_identities:
err_msg = Logger.filter_text("Failed to execute kinit test due to
principal or keytab not found or available")
raise Fail(err_msg)
@@ -81,5 +88,6 @@ class KerberosServiceCheck(KerberosScript):
"and keytab file location must be set in the cluster_env and the
smoke user's keytab file must" \
"exist in the configured location."
+
if __name__ == "__main__":
KerberosServiceCheck().execute()
diff --git
a/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-30/package/scripts/kerberos_client.py
b/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-30/package/scripts/kerberos_client.py
index 691c4b8..202d48a 100644
---
a/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-30/package/scripts/kerberos_client.py
+++
b/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-30/package/scripts/kerberos_client.py
@@ -17,11 +17,14 @@ limitations under the License.
"""
-from kerberos_common import *
-from resource_management.libraries.functions.security_commons import
cached_kinit_executor
from resource_management.core.exceptions import ClientComponentHasNoStatus
+from resource_management.libraries.script.script import Script
+from resource_management.libraries.functions import default
+from ambari_commons.kerberos.kerberos_common import write_krb5_conf,
clear_tmp_cache, write_keytab_file, \
+ delete_keytab_file, find_missing_keytabs
-class KerberosClient(KerberosScript):
+
+class KerberosClient(Script):
def install(self, env):
install_packages =
default('/configurations/kerberos-env/install_packages', "true")
if install_packages:
@@ -31,26 +34,58 @@ class KerberosClient(KerberosScript):
self.configure(env)
-
- def configure(self, env):
+ def configure(self, env, upgrade_type=None, config_dir=None):
import params
env.set_params(params)
if params.manage_krb5_conf:
- self.write_krb5_conf()
- #delete krb cache to prevent using old krb tickets on fresh kerberos setup
- self.clear_tmp_cache()
+ write_krb5_conf(params)
+ # delete krb cache to prevent using old krb tickets on fresh kerberos setup
+ clear_tmp_cache()
def status(self, env):
raise ClientComponentHasNoStatus()
def set_keytab(self, env):
- self.write_keytab_file()
+ import params
+
+ def output_hook(principal, keytab_file_path):
+ if principal is not None:
+ curr_content = Script.structuredOut
+
+ if "keytabs" not in curr_content:
+ curr_content['keytabs'] = {}
+
+ curr_content['keytabs'][principal.replace("_HOST", params.hostname)] =
keytab_file_path
+
+ self.put_structured_out(curr_content)
+
+ write_keytab_file(params, output_hook)
def remove_keytab(self, env):
- self.delete_keytab_file()
+ import params
+
+ def output_hook(principal, keytab_file_path):
+ if principal is not None:
+ curr_content = Script.structuredOut
+
+ if "removedKeytabs" not in curr_content:
+ curr_content['removedKeytabs'] = {}
+ curr_content['removedKeytabs'][principal.replace("_HOST",
params.hostname)] = keytab_file_path
+
+ self.put_structured_out(curr_content)
+
+ delete_keytab_file(params, output_hook)
def check_keytabs(self, env):
- self.find_missing_keytabs()
+ import params
+
+ def output_hook(missing_keytabs):
+ curr_content = Script.structuredOut
+ curr_content['missing_keytabs'] = missing_keytabs
+ self.put_structured_out(curr_content)
+
+ find_missing_keytabs(params, output_hook)
+
if __name__ == "__main__":
KerberosClient().execute()
diff --git
a/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-30/package/scripts/kerberos_common.py
b/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-30/package/scripts/kerberos_common.py
deleted file mode 100644
index fcaa547..0000000
---
a/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-30/package/scripts/kerberos_common.py
+++ /dev/null
@@ -1,493 +0,0 @@
-"""
-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.
-
-"""
-
-import base64
-import getpass
-import os
-import string
-import subprocess
-import sys
-import tempfile
-from tempfile import gettempdir
-
-from resource_management.libraries.script.script import Script
-from resource_management.libraries.functions.format import format
-from resource_management.libraries.functions.default import default
-from resource_management.core.exceptions import Fail
-from resource_management.core.logger import Logger
-from resource_management.core.resources.system import Directory, Execute, File
-from resource_management.core.source import InlineTemplate, Template,
DownloadSource
-from utils import get_property_value
-from ambari_commons.os_utils import remove_file
-from ambari_agent import Constants
-from collections import namedtuple
-from resource_management.core import sudo
-from resource_management.core.resources.klist import Klist
-
-class KerberosScript(Script):
- KRB5_REALM_PROPERTIES = [
- 'kdc',
- 'admin_server',
- 'default_domain',
- 'master_kdc'
- ]
-
- KRB5_SECTION_NAMES = [
- 'libdefaults',
- 'logging',
- 'realms',
- 'domain_realm',
- 'capaths',
- 'ca_paths',
- 'appdefaults',
- 'plugins'
- ]
-
- @staticmethod
- def create_random_password():
- import random
-
- chars = string.digits + string.ascii_letters
- return ''.join(random.choice(chars) for x in range(13))
-
- @staticmethod
- def write_conf_section(output_file, section_name, section_data):
- if section_name is not None:
- output_file.write('[%s]\n' % section_name)
-
- if section_data is not None:
- for key, value in section_data.iteritems():
- output_file.write(" %s = %s\n" % (key, value))
-
-
- @staticmethod
- def _write_conf_realm(output_file, realm_name, realm_data):
- """ Writes out realm details
-
- Example:
-
- EXAMPLE.COM = {
- kdc = kerberos.example.com
- admin_server = kerberos.example.com
- }
-
- """
- if realm_name is not None:
- output_file.write(" %s = {\n" % realm_name)
-
- if realm_data is not None:
- for key, value in realm_data.iteritems():
- if key in KerberosScript.KRB5_REALM_PROPERTIES:
- output_file.write(" %s = %s\n" % (key, value))
-
- output_file.write(" }\n")
-
- @staticmethod
- def write_conf_realms_section(output_file, section_name, realms_data):
- if section_name is not None:
- output_file.write('[%s]\n' % section_name)
-
- if realms_data is not None:
- for realm, realm_data in realms_data.iteritems():
- KerberosScript._write_conf_realm(output_file, realm, realm_data)
- output_file.write('\n')
-
- @staticmethod
- def write_krb5_conf():
- import params
-
- Directory(params.krb5_conf_dir,
- owner='root',
- create_parents = True,
- group='root',
- mode=0755
- )
-
- content = InlineTemplate(params.krb5_conf_template)
-
- File(params.krb5_conf_path,
- content=content,
- owner='root',
- group='root',
- mode=0644
- )
-
- @staticmethod
- def invoke_kadmin(query, admin_identity=None, default_realm=None):
- """
- Executes the kadmin or kadmin.local command (depending on whether
auth_identity is set or not
- and returns command result code and standard out data.
-
- :param query: the kadmin query to execute
- :param admin_identity: the identity for the administrative user (optional)
- :param default_realm: the default realm to assume
- :return: return_code, out
- """
- if (query is not None) and (len(query) > 0):
- auth_principal = None
- auth_keytab_file = None
-
- if admin_identity is not None:
- auth_principal = get_property_value(admin_identity, 'principal')
-
- if auth_principal is None:
- kadmin = 'kadmin.local'
- credential = ''
- else:
- kadmin = 'kadmin -p "%s"' % auth_principal
-
- auth_password = get_property_value(admin_identity, 'password')
-
- if auth_password is None:
- auth_keytab = get_property_value(admin_identity, 'keytab')
-
- if auth_keytab is not None:
- (fd, auth_keytab_file) = tempfile.mkstemp()
- os.write(fd, base64.b64decode(auth_keytab))
- os.close(fd)
-
- credential = '-k -t %s' % auth_keytab_file
- else:
- credential = '-w "%s"' % auth_password
-
- if (default_realm is not None) and (len(default_realm) > 0):
- realm = '-r %s' % default_realm
- else:
- realm = ''
-
- try:
- command = '%s %s %s -q "%s"' % (kadmin, credential, realm,
query.replace('"', '\\"'))
- return shell.checked_call(command)
- except:
- raise
- finally:
- if auth_keytab_file is not None:
- os.remove(auth_keytab_file)
-
- @staticmethod
- def create_keytab_file(principal, path, auth_identity=None):
- success = False
-
- if (principal is not None) and (len(principal) > 0):
- if (auth_identity is None) or (len(auth_identity) == 0):
- norandkey = '-norandkey'
- else:
- norandkey = ''
-
- if (path is not None) and (len(path) > 0):
- keytab_file = '-k %s' % path
- else:
- keytab_file = ''
-
- try:
- result_code, output = KerberosScript.invoke_kadmin(
- 'ktadd %s %s %s' % (keytab_file, norandkey, principal),
- auth_identity)
-
- success = (result_code == 0)
- except:
- raise Fail("Failed to create keytab for principal: %s (in %s)" %
(principal, path))
-
- return success
-
- @staticmethod
- def create_keytab(principal, auth_identity=None):
- keytab = None
-
- (fd, temp_path) = tempfile.mkstemp()
- os.remove(temp_path)
-
- try:
- if KerberosScript.create_keytab_file(principal, temp_path,
auth_identity):
- with open(temp_path, 'r') as f:
- keytab = base64.b64encode(f.read())
- finally:
- if os.path.isfile(temp_path):
- os.remove(temp_path)
-
- return keytab
-
- @staticmethod
- def principal_exists(identity, auth_identity=None):
- exists = False
-
- if identity is not None:
- principal = get_property_value(identity, 'principal')
-
- if (principal is not None) and (len(principal) > 0):
- try:
- result_code, output = KerberosScript.invoke_kadmin('getprinc %s' %
principal,
- auth_identity)
- exists = (output is not None) and (("Principal: %s" % principal) in
output)
- except:
- raise Fail("Failed to determine if principal exists: %s" % principal)
-
- return exists
-
- @staticmethod
- def change_principal_password(identity, auth_identity=None):
- success = False
-
- if identity is not None:
- principal = get_property_value(identity, 'principal')
-
- if (principal is not None) and (len(principal) > 0):
- password = get_property_value(identity, 'password')
-
- if password is None:
- credentials = '-randkey'
- else:
- credentials = '-pw "%s"' % password
-
- try:
- result_code, output = KerberosScript.invoke_kadmin(
- 'change_password %s %s' % (credentials, principal),
- auth_identity)
-
- success = (result_code == 0)
- except:
- raise Fail("Failed to create principal: %s" % principal)
-
- return success
-
- @staticmethod
- def create_principal(identity, auth_identity=None):
- success = False
-
- if identity is not None:
- principal = get_property_value(identity, 'principal')
-
- if (principal is not None) and (len(principal) > 0):
- password = get_property_value(identity, 'password')
-
- if password is None:
- credentials = '-randkey'
- else:
- credentials = '-pw "%s"' % password
-
- try:
- result_code, out = KerberosScript.invoke_kadmin(
- 'addprinc %s %s' % (credentials, principal),
- auth_identity)
-
- success = (result_code == 0)
- except:
- raise Fail("Failed to create principal: %s" % principal)
-
- return success
-
- @staticmethod
- def clear_tmp_cache():
- tmp_dir = Constants.AGENT_TMP_DIR
- if tmp_dir is None:
- tmp_dir = gettempdir()
- curl_krb_cache_path = os.path.join(tmp_dir, "curl_krb_cache")
- Directory(curl_krb_cache_path, action="delete")
-
- @staticmethod
- def create_principals(identities, auth_identity=None):
- if identities is not None:
- for identity in identities:
- KerberosScript.create_principal(identity, auth_identity)
-
- @staticmethod
- def create_or_update_administrator_identity():
- import params
-
- if params.realm is not None:
- admin_identity = params.get_property_value(params.realm,
'admin_identity')
-
- if KerberosScript.principal_exists(admin_identity):
- KerberosScript.change_principal_password(admin_identity)
- else:
- KerberosScript.create_principal(admin_identity)
-
- @staticmethod
- def test_kinit(identity, user=None):
- principal = get_property_value(identity, 'principal')
- kinit_path_local =
functions.get_kinit_path(default('/configurations/kerberos-env/executable_search_paths',
None))
- kdestroy_path_local =
functions.get_kdestroy_path(default('/configurations/kerberos-env/executable_search_paths',
None))
-
- if principal is not None:
- keytab_file = get_property_value(identity, 'keytab_file')
- keytab = get_property_value(identity, 'keytab')
- password = get_property_value(identity, 'password')
-
- # If a test keytab file is available, simply use it
- if (keytab_file is not None) and (os.path.isfile(keytab_file)):
- command = '%s -k -t %s %s' % (kinit_path_local, keytab_file, principal)
- Execute(command,
- user = user,
- )
- return shell.checked_call(kdestroy_path_local)
-
- # If base64-encoded test keytab data is available; then decode it, write
it to a temporary file
- # use it, and then remove the temporary file
- elif keytab is not None:
- (fd, test_keytab_file) = tempfile.mkstemp()
- os.write(fd, base64.b64decode(keytab))
- os.close(fd)
-
- try:
- command = '%s -k -t %s %s' % (kinit_path_local, test_keytab_file,
principal)
- Execute(command,
- user = user,
- )
- return shell.checked_call(kdestroy_path_local)
- except:
- raise
- finally:
- if test_keytab_file is not None:
- os.remove(test_keytab_file)
-
- # If no keytab data is available and a password was supplied, simply use
it.
- elif password is not None:
- process = subprocess.Popen([kinit_path_local, principal],
stdin=subprocess.PIPE)
- stdout, stderr = process.communicate(password)
- if process.returncode:
- err_msg = Logger.filter_text("Execution of kinit returned %d. %s" %
(process.returncode, stderr))
- raise Fail(err_msg)
- else:
- return shell.checked_call(kdestroy_path_local)
- else:
- return 0, ''
- else:
- return 0, ''
-
-
- def write_keytab_file(self):
- import params
- import stat
-
- if params.kerberos_command_params is not None:
- for item in params.kerberos_command_params:
- keytab_content_base64 = get_property_value(item,
'keytab_content_base64')
- if (keytab_content_base64 is not None) and (len(keytab_content_base64)
> 0):
- keytab_file_path = get_property_value(item, 'keytab_file_path')
- if (keytab_file_path is not None) and (len(keytab_file_path) > 0):
- head, tail = os.path.split(keytab_file_path)
- if head:
- Directory(head, create_parents = True, mode=0755, owner="root",
group="root")
-
- owner = get_property_value(item, 'keytab_file_owner_name')
- if not owner:
- owner = getpass.getuser()
- owner_access = get_property_value(item, 'keytab_file_owner_access')
- group = get_property_value(item, 'keytab_file_group_name')
- group_access = get_property_value(item, 'keytab_file_group_access')
- mode = 0
-
- if owner_access == 'rw':
- mode |= stat.S_IREAD | stat.S_IWRITE
- else:
- mode |= stat.S_IREAD
-
- if group_access == 'rw':
- mode |= stat.S_IRGRP | stat.S_IWGRP
- elif group_access == 'r':
- mode |= stat.S_IRGRP
-
- keytab_content = base64.b64decode(keytab_content_base64)
-
- # to hide content in command output
- def make_lambda(data):
- return lambda: data
-
- File(keytab_file_path,
- content=make_lambda(keytab_content),
- mode=mode,
- owner=owner,
- group=group)
-
- principal = get_property_value(item, 'principal')
- if principal is not None:
- curr_content = Script.structuredOut
-
- if "keytabs" not in curr_content:
- curr_content['keytabs'] = {}
-
- curr_content['keytabs'][principal.replace("_HOST",
params.hostname)] = keytab_file_path
-
- self.put_structured_out(curr_content)
-
- def delete_keytab_file(self):
- import params
-
- if params.kerberos_command_params is not None:
- for item in params.kerberos_command_params:
- keytab_file_path = get_property_value(item, 'keytab_file_path')
- if (keytab_file_path is not None) and (len(keytab_file_path) > 0):
-
- # Delete the keytab file
- File(keytab_file_path, action="delete")
-
- principal = get_property_value(item, 'principal')
- if principal is not None:
- curr_content = Script.structuredOut
-
- if "removedKeytabs" not in curr_content:
- curr_content['removedKeytabs'] = {}
- curr_content['removedKeytabs'][principal.replace("_HOST",
params.hostname)] = keytab_file_path
-
- self.put_structured_out(curr_content)
-
- def find_missing_keytabs(self):
- import params
- missing_keytabs =
MissingKeytabs.fromKerberosRecords(params.kerberos_command_params,
params.hostname)
- Logger.info(str(missing_keytabs))
- curr_content = Script.structuredOut
- curr_content['missing_keytabs'] = missing_keytabs.as_dict()
- self.put_structured_out(curr_content)
-
-class MissingKeytabs:
- class Identity(namedtuple('Identity', ['principal', 'keytab_file_path'])):
- @staticmethod
- def fromKerberosRecord(item, hostname):
- return MissingKeytabs.Identity(
- get_property_value(item, 'principal').replace("_HOST", hostname),
- get_property_value(item, 'keytab_file_path'))
-
- def __str__(self):
- return "Keytab: %s Principal: %s" % (self.keytab_file_path,
self.principal)
-
- @classmethod
- def fromKerberosRecords(self, kerberos_record, hostname):
- with_missing_keytab = (each for each in kerberos_record \
- if not self.keytab_exists(each) or not
self.keytab_has_principal(each, hostname))
- return MissingKeytabs(set(MissingKeytabs.Identity.fromKerberosRecord(each,
hostname) for each in with_missing_keytab))
-
- @staticmethod
- def keytab_exists(kerberos_record):
- return sudo.path_exists(get_property_value(kerberos_record,
'keytab_file_path'))
-
- @staticmethod
- def keytab_has_principal(kerberos_record, hostname):
- principal = get_property_value(kerberos_record,
'principal').replace("_HOST", hostname)
- keytab = get_property_value(kerberos_record, 'keytab_file_path')
- klist = Klist.find_in_search_path()
- return principal in klist.list_principals(keytab)
-
- def __init__(self, items):
- self.items = items
-
- def as_dict(self):
- return [each._asdict() for each in self.items]
-
- def __str__(self):
- return "Missing keytabs:\n%s" % ("\n".join(map(str, self.items))) if
self.items else 'No missing keytabs'
diff --git
a/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-30/package/scripts/params.py
b/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-30/package/scripts/params.py
index 5b1fafe..3b47626 100644
---
a/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-30/package/scripts/params.py
+++
b/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-30/package/scripts/params.py
@@ -17,13 +17,12 @@ limitations under the License.
"""
-from resource_management.libraries.script.script import Script
-from utils import get_property_value, get_unstructured_data
+from ambari_commons.kerberos.utils import get_property_value,
get_unstructured_data
from ambari_commons.os_check import OSCheck
from resource_management.libraries.functions.default import default
from resource_management.libraries.functions.expect import expect
from resource_management.libraries.functions.format import format
-
+from resource_management.libraries.script.script import Script
krb5_conf_dir = '/etc'
krb5_conf_file = 'krb5.conf'
diff --git
a/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-30/package/scripts/service_check.py
b/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-30/package/scripts/service_check.py
index 1c042a7..e6a5ab3 100644
---
a/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-30/package/scripts/service_check.py
+++
b/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-30/package/scripts/service_check.py
@@ -18,13 +18,15 @@ limitations under the License.
Ambari Agent
"""
-from resource_management.libraries import functions
-from resource_management.libraries.functions.format import format
-from resource_management.core.resources.system import Execute, File
-from resource_management.core.logger import Logger
-from kerberos_common import *
+import os
+from resource_management.core.exceptions import Fail
+from resource_management.core.logger import Logger
+from resource_management.core.resources.system import Execute, File
+from resource_management.libraries import functions
+from resource_management.libraries.functions import default
+from resource_management.libraries.script.script import Script
# hashlib is supplied as of Python 2.5 as the replacement interface for md5
# and other secure hashes. In 2.6, md5 is deprecated. Import hashlib if
@@ -32,12 +34,15 @@ from kerberos_common import *
# preserving 2.4 compatibility.
try:
import hashlib
+
_md5 = hashlib.md5
except ImportError:
import md5
+
_md5 = md5.new
-class KerberosServiceCheck(KerberosScript):
+
+class KerberosServiceCheck(Script):
def service_check(self, env):
import params
@@ -56,21 +61,23 @@ class KerberosServiceCheck(KerberosScript):
os.path.isfile(params.smoke_test_keytab_file)):
print "Performing kinit using %s" % params.smoke_test_principal
- ccache_file_name =
_md5("{0}|{1}".format(params.smoke_test_principal,params.smoke_test_keytab_file)).hexdigest()
+ ccache_file_name = _md5("{0}|{1}".format(params.smoke_test_principal,
params.smoke_test_keytab_file)).hexdigest()
ccache_file_path =
"{0}{1}kerberos_service_check_cc_{2}".format(params.tmp_dir, os.sep,
ccache_file_name)
kinit_path_local =
functions.get_kinit_path(default('/configurations/kerberos-env/executable_search_paths',
None))
- kinit_command = "{0} -c {1} -kt {2} {3}".format(kinit_path_local,
ccache_file_path, params.smoke_test_keytab_file, params.smoke_test_principal)
+ kinit_command = "{0} -c {1} -kt {2} {3}".format(kinit_path_local,
ccache_file_path, params.smoke_test_keytab_file,
+
params.smoke_test_principal)
try:
# kinit
Execute(kinit_command,
user=params.smoke_user
- )
+ )
finally:
- File(ccache_file_path, # Since kinit might fail to write to the cache
file for various reasons, an existence check should be done before cleanup
- action = "delete",
- )
+ File(ccache_file_path,
+ # Since kinit might fail to write to the cache file for various
reasons, an existence check should be done before cleanup
+ action="delete",
+ )
elif params.manage_identities:
err_msg = Logger.filter_text("Failed to execute kinit test due to
principal or keytab not found or available")
raise Fail(err_msg)
@@ -81,5 +88,6 @@ class KerberosServiceCheck(KerberosScript):
"and keytab file location must be set in the cluster_env and the
smoke user's keytab file must" \
"exist in the configured location."
+
if __name__ == "__main__":
KerberosServiceCheck().execute()
diff --git
a/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-30/package/scripts/utils.py
b/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-30/package/scripts/utils.py
deleted file mode 100644
index 199e6d7..0000000
---
a/ambari-server/src/main/resources/common-services/KERBEROS/1.10.3-30/package/scripts/utils.py
+++ /dev/null
@@ -1,105 +0,0 @@
-"""
-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.
-
-"""
-
-def get_property_value(dictionary, property_name, default_value=None,
trim_string=False,
- empty_value=""):
- """
- Get a property value from a dictionary, applying applying rules as necessary.
-
- If dictionary does not contain a value for property_name or the value for
property_name is None,
- null_value is used as the value to return. Then, if trim_string is True and
the value is None
- or the value is an empty string, empty_value will be return else the
(current) value is returned.
-
- Note: the property value will most likely be a string or a unicode string,
however in the event
- it is not (for example a number), this method will behave properly and
return the value as is.
-
- :param dictionary: a dictionary of values
- :param property_name: the name of a dictionary item to retrieve
- :param default_value: the value to use if the item is not in the dictionary
or the value of the item is None
- :param trim_string: a Boolean value indicating whether to strip whitespace
from the value (True) or not (False)
- :param empty_value: the value to use if the (current) value is None or an
empty string, if trim_string is True
- :return: the requested property value with rules applied
- """
- # If property_name is not in the dictionary, set value to null_value
- if property_name in dictionary:
- value = dictionary[property_name]
- if value is None:
- value = default_value
- else:
- value = default_value
-
- if trim_string:
- # If the value is none, consider it empty...
- if value is None:
- value = empty_value
- elif (type(value) == str) or (type(value) == unicode):
- value = value.strip()
-
- if len(value) == 0:
- value = empty_value
-
- return value
-
-def get_unstructured_data(dictionary, property_name):
- prefix = property_name + '/'
- prefix_len = len(prefix)
- return dict((k[prefix_len:], v) for k, v in dictionary.iteritems() if
k.startswith(prefix))
-
-def split_host_and_port(host):
- """
- Splits a string into its host and port components
-
- :param host: a string matching the following pattern: <host name | ip
address>[:port]
- :return: a Dictionary containing 'host' and 'port' entries for the input
value
- """
-
- if host is None:
- host_and_port = None
- else:
- host_and_port = {}
- parts = host.split(":")
-
- if parts is not None:
- length = len(parts)
-
- if length > 0:
- host_and_port['host'] = parts[0]
-
- if length > 1:
- host_and_port['port'] = int(parts[1])
-
- return host_and_port
-
-def set_port(host, port):
- """
- Sets the port for a host specification, potentially replacing an existing
port declaration
-
- :param host: a string matching the following pattern: <host name | ip
address>[:port]
- :param port: a string or integer declaring the (new) port
- :return: a string declaring the new host/port specification
- """
- if port is None:
- return host
- else:
- host_and_port = split_host_and_port(host)
-
- if (host_and_port is not None) and ('host' in host_and_port):
- return "%s:%s" % (host_and_port['host'], port)
- else:
- return host
diff --git
a/ambari-server/src/test/python/stacks/2.2/KERBEROS/test_kerberos_client.py
b/ambari-server/src/test/python/stacks/2.2/KERBEROS/test_kerberos_client.py
index cb2db3a..8d96707 100644
--- a/ambari-server/src/test/python/stacks/2.2/KERBEROS/test_kerberos_client.py
+++ b/ambari-server/src/test/python/stacks/2.2/KERBEROS/test_kerberos_client.py
@@ -142,7 +142,7 @@ class TestKerberosClient(RMFTestCase):
package_dir = os.path.join(RMFTestCase._getCommonServicesFolder(),
self.COMMON_SERVICES_PACKAGE_DIR)
scripts_dir = os.path.join(package_dir, "scripts")
sys.path += [scripts_dir]
- from utils import get_property_value
+ from ambari_commons.kerberos.utils import get_property_value
d = {
'non_empty' : "Nonempty value",
--
To stop receiving notification emails like this one, please contact
['"[email protected]" <[email protected]>'].