This is an automated email from the ASF dual-hosted git repository.
dmitriusan 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 97a6bc8 AMBARI-24745. Enable encryption of sensitive data in Ambari
DB using … (#2755)
97a6bc8 is described below
commit 97a6bc8b389fa5cfb73c87392af91e2d4d405ae3
Author: Lisnichenko Dmitro <[email protected]>
AuthorDate: Fri Jan 18 17:07:53 2019 +0200
AMBARI-24745. Enable encryption of sensitive data in Ambari DB using …
(#2755)
AMBARI-24745. Enable encryption of sensitive data in Ambari DB using Ambari
CLI (dlysnichenko)
---
ambari-server/src/main/python/ambari-server.py | 6 +-
.../python/ambari_server/serverConfiguration.py | 8 +-
.../src/main/python/ambari_server/setupSecurity.py | 188 +++---
ambari-server/src/test/python/TestAmbariServer.py | 272 +--------
.../src/test/python/TestSensitiveDataEncryption.py | 667 +++++++++++++++++++++
5 files changed, 802 insertions(+), 339 deletions(-)
diff --git a/ambari-server/src/main/python/ambari-server.py
b/ambari-server/src/main/python/ambari-server.py
index 4539879..78d5405 100755
--- a/ambari-server/src/main/python/ambari-server.py
+++ b/ambari-server/src/main/python/ambari-server.py
@@ -54,7 +54,7 @@ from ambari_server.setupActions import BACKUP_ACTION,
LDAP_SETUP_ACTION, LDAP_SY
from ambari_server.setupHttps import setup_https, setup_truststore
from ambari_server.setupMpacks import install_mpack, uninstall_mpack,
upgrade_mpack, STACK_DEFINITIONS_RESOURCE_NAME, \
SERVICE_DEFINITIONS_RESOURCE_NAME, MPACKS_RESOURCE_NAME
-from ambari_server.setupSecurity import setup_ldap, sync_ldap,
setup_master_key, setup_ambari_krb5_jaas, setup_pam, \
+from ambari_server.setupSecurity import setup_ldap, sync_ldap,
setup_sensitive_data_encryption, setup_ambari_krb5_jaas, setup_pam, \
migrate_ldap_pam, LDAP_TYPES
from ambari_server.setupSso import setup_sso
from ambari_server.setupTrustedProxy import setup_trusted_proxy
@@ -253,7 +253,7 @@ def refresh_stack_hash_action():
def create_setup_security_actions(args):
action_list = [
['setup-https', 'Enable HTTPS for Ambari server.',
UserActionRestart(setup_https, args)],
- ['encrypt-passwords', 'Encrypt passwords stored in ambari.properties
file.', UserAction(setup_master_key, args)],
+ ['encrypt-passwords', 'Encrypt passwords managed by Ambari.',
UserAction(setup_sensitive_data_encryption, args)],
['setup-kerberos-jaas', 'Setup Ambari kerberos JAAS configuration.',
UserAction(setup_ambari_krb5_jaas, args)],
['setup-truststore', 'Setup truststore.',
UserActionRestart(setup_truststore, args)],
['import-certificate', 'Import certificate to truststore.',
UserActionRestart(setup_truststore, True, args)],
@@ -264,7 +264,7 @@ def create_setup_security_actions(args):
def create_setup_security_actions(args):
action_list = [
['setup-https', 'Enable HTTPS for Ambari server.',
UserActionRestart(setup_https, args)],
- ['encrypt-passwords', 'Encrypt passwords stored in ambari.properties
file.', UserAction(setup_master_key, args)],
+ ['encrypt-passwords', 'Encrypt passwords managed by Ambari.',
UserAction(setup_sensitive_data_encryption, args)],
['setup-kerberos-jaas', 'Setup Ambari kerberos JAAS configuration.',
UserAction(setup_ambari_krb5_jaas, args)],
['setup-truststore', 'Setup truststore.',
UserActionRestart(setup_truststore, args)],
['import-certificate', 'Import certificate to truststore.',
UserActionRestart(setup_truststore, args, True)],
diff --git a/ambari-server/src/main/python/ambari_server/serverConfiguration.py
b/ambari-server/src/main/python/ambari_server/serverConfiguration.py
index fb0e0a2..f340ff6 100644
--- a/ambari-server/src/main/python/ambari_server/serverConfiguration.py
+++ b/ambari-server/src/main/python/ambari_server/serverConfiguration.py
@@ -608,6 +608,7 @@ SECURITY_KEY_IS_PERSISTED =
"security.master.key.ispersisted"
SECURITY_KEY_ENV_VAR_NAME = "AMBARI_SECURITY_MASTER_KEY"
SECURITY_MASTER_KEY_FILENAME = "master"
SECURITY_IS_ENCRYPTION_ENABLED = "security.passwords.encryption.enabled"
+SECURITY_SENSITIVE_DATA_ENCRYPTON_ENABLED =
"security.server.encrypt_sensitive_data"
SECURITY_KERBEROS_JASS_FILENAME = "krb5JAASLogin.conf"
SECURITY_PROVIDER_GET_CMD = "{0} -cp {1} " + \
@@ -625,6 +626,11 @@ SECURITY_PROVIDER_KEY_CMD = "{0} -cp {1} " + \
".MasterKeyServiceImpl {2} {3} {4} " + \
"> " + configDefaults.SERVER_OUT_FILE + " 2>&1"
+SECURITY_SENSITIVE_DATA_ENCRYPTON_CMD = "{0} -cp {1} " + \
+
"org.apache.ambari.server.security.encryption.SensitiveDataEncryption" + \
+ " {2} " + \
+ "> " + configDefaults.SERVER_OUT_FILE + " 2>&1"
+
def read_ambari_user():
@@ -1045,7 +1051,7 @@ def get_original_master_key(properties, options = None):
masterKey = options.master_key
if not masterKey:
masterKey = get_validated_string_input('Enter current Master Key: ',
- "", ".*", "", True, False)
+ "", ".*", "", True, True)
if options is not None:
options.master_key = masterKey
except KeyboardInterrupt:
diff --git a/ambari-server/src/main/python/ambari_server/setupSecurity.py
b/ambari-server/src/main/python/ambari_server/setupSecurity.py
index 7952a07..460e147 100644
--- a/ambari-server/src/main/python/ambari_server/setupSecurity.py
+++ b/ambari-server/src/main/python/ambari_server/setupSecurity.py
@@ -47,8 +47,8 @@ from ambari_server.serverConfiguration import configDefaults,
parse_properties_f
BLIND_PASSWORD, BOOTSTRAP_DIR_PROPERTY, JDBC_PASSWORD_FILENAME,
JDBC_PASSWORD_PROPERTY, \
JDBC_RCA_PASSWORD_ALIAS, JDBC_RCA_PASSWORD_FILE_PROPERTY,
JDBC_USE_INTEGRATED_AUTH_PROPERTY, \
LDAP_MGR_PASSWORD_ALIAS, LDAP_MGR_PASSWORD_PROPERTY, CLIENT_SECURITY, \
- SECURITY_IS_ENCRYPTION_ENABLED, SECURITY_KEY_ENV_VAR_NAME,
SECURITY_KERBEROS_JASS_FILENAME, \
- SECURITY_PROVIDER_KEY_CMD, SECURITY_MASTER_KEY_FILENAME,
SSL_TRUSTSTORE_PASSWORD_ALIAS, \
+ SECURITY_IS_ENCRYPTION_ENABLED, SECURITY_SENSITIVE_DATA_ENCRYPTON_ENABLED,
SECURITY_KEY_ENV_VAR_NAME, SECURITY_KERBEROS_JASS_FILENAME, \
+ SECURITY_PROVIDER_KEY_CMD, SECURITY_SENSITIVE_DATA_ENCRYPTON_CMD,
SECURITY_MASTER_KEY_FILENAME, SSL_TRUSTSTORE_PASSWORD_ALIAS, \
SSL_TRUSTSTORE_PASSWORD_PROPERTY, SSL_TRUSTSTORE_PATH_PROPERTY,
SSL_TRUSTSTORE_TYPE_PROPERTY, \
JDK_NAME_PROPERTY, JCE_NAME_PROPERTY, JAVA_HOME_PROPERTY, \
get_resources_location, SECURITY_MASTER_KEY_LOCATION, SETUP_OR_UPGRADE_MSG, \
@@ -487,9 +487,24 @@ def sync_ldap(options):
sys.stdout.write('\n')
sys.stdout.flush()
-def setup_master_key(options):
+def sensitive_data_encryption(options, direction, masterKey=None):
+ environ = os.environ.copy()
+ if masterKey:
+ environ[SECURITY_KEY_ENV_VAR_NAME] = masterKey
+ jdk_path = find_jdk()
+ if jdk_path is None:
+ print_error_msg("No JDK found, please run the \"setup\" "
+ "command to install a JDK automatically or install any "
+ "JDK manually to " + configDefaults.JDK_INSTALL_DIR)
+ return 1
+ serverClassPath = ServerClassPath(get_ambari_properties(), options)
+ command = SECURITY_SENSITIVE_DATA_ENCRYPTON_CMD.format(get_java_exe_path(),
serverClassPath.get_full_ambari_classpath_escaped_for_shell(), direction)
+ (retcode, stdout, stderr) = run_os_command(command, environ)
+ pass
+
+def setup_sensitive_data_encryption(options):
if not is_root():
- warn = 'ambari-server setup-https is run as ' \
+ warn = 'ambari-server encrypt-passwords is run as ' \
'non-root user, some sudo privileges might be required'
print warn
@@ -516,76 +531,67 @@ def setup_master_key(options):
ts_password = properties.get_property(SSL_TRUSTSTORE_PASSWORD_PROPERTY)
resetKey = False
+ decrypt = False
masterKey = None
if isSecure:
print "Password encryption is enabled."
- resetKey = True if options.security_option is not None else
get_YN_input("Do you want to reset Master Key? [y/n] (n): ", False)
-
- # For encrypting of only unencrypted passwords without resetting the key ask
- # for master key if not persisted.
- if isSecure and not isPersisted and not resetKey:
- print "Master Key not persisted."
- masterKey = get_original_master_key(properties, options)
- pass
+ decrypt = get_YN_input("Do you want to decrypt passwords managed by
Ambari? [y/n] (n): ", False)
+ if not decrypt:
+ resetKey = get_YN_input("Do you want to reset Master Key? [y/n] (n): ",
False)
# Make sure both passwords are clear-text if master key is lost
- if resetKey:
- if not isPersisted:
+ if resetKey or decrypt:
+ if isPersisted:
+ sensitive_data_encryption(options, "decryption")
+ else:
print "Master Key not persisted."
masterKey = get_original_master_key(properties, options)
# Unable get the right master key or skipped question <enter>
if not masterKey:
- print "To disable encryption, do the following:"
- print "- Edit " + find_properties_file() + \
- " and set " + SECURITY_IS_ENCRYPTION_ENABLED + " = " + "false."
- err = "{0} is already encrypted. Please call {1} to store unencrypted"
\
- " password and call 'encrypt-passwords' again."
- if db_sql_auth and db_password and is_alias_string(db_password):
- print err.format('- Database password', "'" + SETUP_ACTION + "'")
- if ts_password and is_alias_string(ts_password):
- print err.format('TrustStore password', "'" + LDAP_SETUP_ACTION +
"'")
-
+ # todo fix unreachable code
+ printManualDecryptionWarning(db_password, db_sql_auth, ts_password)
return 1
- pass
- pass
- pass
+ sensitive_data_encryption(options, "decryption", masterKey)
# Read back any encrypted passwords
- if db_sql_auth and db_password and is_alias_string(db_password):
- db_password = read_passwd_for_alias(JDBC_RCA_PASSWORD_ALIAS, masterKey)
- if ts_password and is_alias_string(ts_password):
- ts_password = read_passwd_for_alias(SSL_TRUSTSTORE_PASSWORD_ALIAS,
masterKey)
- # Read master key, if non-secure or reset is true
- if resetKey or not isSecure:
- masterKey = read_master_key(resetKey, options)
- persist = get_YN_input("Do you want to persist master key. If you choose "
\
- "not to persist, you need to provide the Master " \
- "Key while starting the ambari server as an env " \
- "variable named " + SECURITY_KEY_ENV_VAR_NAME + \
- " or the start will prompt for the master key."
- " Persist [y/n] (y)? ", True,
options.master_key_persist)
- if persist:
- save_master_key(options, masterKey, get_master_key_location(properties)
+ os.sep +
- SECURITY_MASTER_KEY_FILENAME, persist)
- elif not persist and masterKeyFile:
- try:
- os.remove(masterKeyFile)
- print_info_msg("Deleting master key file at location: " + str(
- masterKeyFile))
- except Exception, e:
- print 'ERROR: Could not remove master key file. %s' % e
- # Blow up the credential store made with previous key, if any
- store_file = get_credential_store_location(properties)
- if os.path.exists(store_file):
- try:
- os.remove(store_file)
- except:
- print_warning_msg("Failed to remove credential store file.")
- pass
- pass
- pass
+ db_password, ts_password = deryptPasswordsConfigs(db_password, db_sql_auth,
masterKey, ts_password)
+ save_decrypted_ambari_properties(db_password, properties, ts_password)
+
+ if not decrypt:
+ if resetKey or not isSecure:
+ # Read master key and encrypt sensitive data, if non-secure or reset is
true
+ masterKey, isPersisted = setup_master_key(masterKeyFile, options,
properties, resetKey)
+ else:
+ if not isPersisted:
+ # For encrypting of only unencrypted passwords without resetting the
key ask
+ # for master key if not persisted.
+ print "Master Key not persisted."
+ masterKey = get_original_master_key(properties, options)
+ encrypt_sensitive_data(db_password, masterKey, options, isPersisted,
properties, ts_password)
+
+ # Since files for store and master are created we need to ensure correct
+ # permissions
+ ambari_user = read_ambari_user()
+ if ambari_user:
+ adjust_directory_permissions(ambari_user)
+ return 0
+
+
+def save_decrypted_ambari_properties(db_password, properties, ts_password):
+ propertyMap = {SECURITY_IS_ENCRYPTION_ENABLED: 'false'}
+ propertyMap[SECURITY_SENSITIVE_DATA_ENCRYPTON_ENABLED] = 'false'
+ if db_password:
+ propertyMap[JDBC_PASSWORD_PROPERTY] = db_password
+ if properties.get_property(JDBC_RCA_PASSWORD_FILE_PROPERTY):
+ propertyMap[JDBC_RCA_PASSWORD_FILE_PROPERTY] = db_password
+ if ts_password:
+ propertyMap[SSL_TRUSTSTORE_PASSWORD_PROPERTY] = ts_password
+ update_properties_2(properties, propertyMap)
+
+
+def encrypt_sensitive_data(db_password, masterKey, options, persist,
properties, ts_password):
propertyMap = {SECURITY_IS_ENCRYPTION_ENABLED: 'true'}
# Encrypt only un-encrypted passwords
if db_password and not is_alias_string(db_password):
@@ -597,7 +603,6 @@ def setup_master_key(options):
remove_password_file(JDBC_PASSWORD_FILENAME)
if properties.get_property(JDBC_RCA_PASSWORD_FILE_PROPERTY):
propertyMap[JDBC_RCA_PASSWORD_FILE_PROPERTY] =
get_alias_string(JDBC_RCA_PASSWORD_ALIAS)
- pass
if ts_password and not is_alias_string(ts_password):
retCode = save_passwd_for_alias(SSL_TRUSTSTORE_PASSWORD_ALIAS,
ts_password, masterKey)
@@ -605,17 +610,64 @@ def setup_master_key(options):
print 'Failed to save secure TrustStore password.'
else:
propertyMap[SSL_TRUSTSTORE_PASSWORD_PROPERTY] =
get_alias_string(SSL_TRUSTSTORE_PASSWORD_ALIAS)
- pass
+ propertyMap[SECURITY_SENSITIVE_DATA_ENCRYPTON_ENABLED] = 'true'
+ if persist:
+ sensitive_data_encryption(options, "encryption")
+ else:
+ sensitive_data_encryption(options, "encryption", masterKey)
update_properties_2(properties, propertyMap)
- # Since files for store and master are created we need to ensure correct
- # permissions
- ambari_user = read_ambari_user()
- if ambari_user:
- adjust_directory_permissions(ambari_user)
- return 0
+def setup_master_key(masterKeyFile, options, properties, resetKey):
+ masterKey = read_master_key(resetKey, options)
+ persist = get_YN_input("Do you want to persist master key. If you choose " \
+ "not to persist, you need to provide the Master " \
+ "Key while starting the ambari server as an env " \
+ "variable named " + SECURITY_KEY_ENV_VAR_NAME + \
+ " or the start will prompt for the master key."
+ " Persist [y/n] (y)? ", True,
options.master_key_persist)
+ if persist:
+ save_master_key(options, masterKey, get_master_key_location(properties) +
os.sep +
+ SECURITY_MASTER_KEY_FILENAME, persist)
+ elif not persist and masterKeyFile:
+ try:
+ os.remove(masterKeyFile)
+ print_info_msg("Deleting master key file at location: " + str(
+ masterKeyFile))
+ except Exception, e:
+ print 'ERROR: Could not remove master key file. %s' % e
+ # Blow up the credential store made with previous key, if any
+ store_file = get_credential_store_location(properties)
+ if os.path.exists(store_file):
+ try:
+ os.remove(store_file)
+ except:
+ print_warning_msg("Failed to remove credential store file.")
+ return masterKey, persist
+
+
+def deryptPasswordsConfigs(db_password, db_sql_auth, masterKey, ts_password):
+ if db_sql_auth and db_password and is_alias_string(db_password):
+ db_password = read_passwd_for_alias(JDBC_RCA_PASSWORD_ALIAS, masterKey)
+ if ts_password and is_alias_string(ts_password):
+ ts_password = read_passwd_for_alias(SSL_TRUSTSTORE_PASSWORD_ALIAS,
masterKey)
+ return db_password, ts_password
+
+
+def printManualDecryptionWarning(db_password, db_sql_auth, ts_password):
+ print "To disable encryption, do the following:"
+ print "- Edit " + find_properties_file() + \
+ " and set " + SECURITY_IS_ENCRYPTION_ENABLED + " = " + "false." + \
+ " and set " + SECURITY_SENSITIVE_DATA_ENCRYPTON_ENABLED + " = " +
"false." + \
+ " and set all passwords and sensitive data in service configs to right
value."
+ err = "{0} is already encrypted. Please call {1} to store unencrypted" \
+ " password and call 'encrypt-passwords' again."
+ if db_sql_auth and db_password and is_alias_string(db_password):
+ print err.format('- Database password', "'" + SETUP_ACTION + "'")
+ if ts_password and is_alias_string(ts_password):
+ print err.format('TrustStore password', "'" + LDAP_SETUP_ACTION + "'")
+
def setup_ambari_krb5_jaas(options):
jaas_conf_file = search_file(SECURITY_KERBEROS_JASS_FILENAME, get_conf_dir())
diff --git a/ambari-server/src/test/python/TestAmbariServer.py
b/ambari-server/src/test/python/TestAmbariServer.py
index ebf0a9d..7089ecf 100644
--- a/ambari-server/src/test/python/TestAmbariServer.py
+++ b/ambari-server/src/test/python/TestAmbariServer.py
@@ -92,7 +92,7 @@ with patch.object(platform, "linux_distribution",
return_value = MagicMock(retur
RESOURCES_DIR_PROPERTY, JDBC_RCA_PASSWORD_ALIAS,
JDBC_RCA_SCHEMA_PROPERTY, \
SSL_API, SSL_API_PORT, CLIENT_API_PORT_PROPERTY,\
JDBC_CONNECTION_POOL_TYPE, LDAP_MGR_PASSWORD_PROPERTY,
LDAP_MGR_PASSWORD_ALIAS, JDBC_PASSWORD_FILENAME, NR_USER_PROPERTY,
SECURITY_KEY_IS_PERSISTED, \
- SSL_TRUSTSTORE_PASSWORD_PROPERTY,
SECURITY_IS_ENCRYPTION_ENABLED, PID_DIR_PROPERTY,
SSL_TRUSTSTORE_PASSWORD_ALIAS, \
+ SECURITY_IS_ENCRYPTION_ENABLED, PID_DIR_PROPERTY, \
SECURITY_MASTER_KEY_LOCATION, SECURITY_KEYS_DIR,
store_password_file, \
get_pass_file_path, GET_FQDN_SERVICE_URL,
SECURITY_KEY_ENV_VAR_NAME, \
JAVA_HOME_PROPERTY, JDK_NAME_PROPERTY, JCE_NAME_PROPERTY,
STACK_LOCATION_KEY, SERVER_VERSION_FILE_PATH, \
@@ -108,7 +108,7 @@ with patch.object(platform, "linux_distribution",
return_value = MagicMock(retur
SSL_DATE_FORMAT, import_cert_and_key, is_valid_cert_host,
setup_truststore, \
SRVR_ONE_WAY_SSL_PORT_PROPERTY,
SRVR_TWO_WAY_SSL_PORT_PROPERTY
from ambari_server.setupSecurity import
adjust_directory_permissions, get_alias_string, get_ldap_event_spec_names,
sync_ldap, \
- configure_ldap_password, setup_ldap, REGEX_HOSTNAME_PORT,
REGEX_TRUE_FALSE, REGEX_ANYTHING, setup_master_key, \
+ configure_ldap_password, setup_ldap, REGEX_HOSTNAME_PORT,
REGEX_TRUE_FALSE, REGEX_ANYTHING,\
setup_ambari_krb5_jaas, LDAP_GENERIC,
should_query_ldap_type, LdapPropTemplate, LdapDefault, LdapDefaultMap
from ambari_server.userInput import get_YN_input,
get_choice_string_input, get_validated_string_input, \
read_password
@@ -313,13 +313,13 @@ class TestAmbariServer(TestCase):
@patch.object(OSCheck, "os_distribution", new = MagicMock(return_value =
os_distro_value))
@patch.object(_ambari_server_, "setup_ambari_krb5_jaas")
- @patch.object(_ambari_server_, "setup_master_key")
+ @patch.object(_ambari_server_, "setup_sensitive_data_encryption")
@patch.object(_ambari_server_, "setup_truststore")
@patch.object(_ambari_server_, "setup_https")
@patch.object(_ambari_server_, "get_validated_string_input")
@patch.object(_ambari_server_, "logger")
def test_setup_security(self, logger_mock, get_validated_string_input_mock,
setup_https_mock,
- setup_truststore_mock, setup_master_key_mock,
+ setup_truststore_mock,
setup_sensitive_data_encryption_mock,
setup_ambari_krb5_jaas_mock):
args = self._create_empty_options_mock()
@@ -329,7 +329,7 @@ class TestAmbariServer(TestCase):
get_validated_string_input_mock.return_value = '2'
_ambari_server_.setup_security(args)
- self.assertTrue(setup_master_key_mock.called)
+ self.assertTrue(setup_sensitive_data_encryption_mock.called)
get_validated_string_input_mock.return_value = '3'
_ambari_server_.setup_security(args)
@@ -6724,197 +6724,6 @@ class TestAmbariServer(TestCase):
sys.stdout = sys.__stdout__
pass
- @patch("os.path.exists")
- @patch("ambari_server.setupSecurity.get_is_secure")
- @patch("ambari_server.setupSecurity.get_is_persisted")
- @patch("ambari_server.setupSecurity.remove_password_file")
- @patch("ambari_server.setupSecurity.save_passwd_for_alias")
- @patch("ambari_server.setupSecurity.read_master_key")
- @patch("ambari_server.setupSecurity.read_ambari_user")
- @patch("ambari_server.setupSecurity.get_master_key_location")
- @patch("ambari_server.setupSecurity.update_properties_2")
- @patch("ambari_server.setupSecurity.save_master_key")
- @patch("ambari_server.setupSecurity.get_YN_input")
- @patch("ambari_server.setupSecurity.search_file")
- @patch("ambari_server.setupSecurity.get_ambari_properties")
- @patch("ambari_server.setupSecurity.is_root")
- def test_setup_master_key_not_persist(self, is_root_method,
- get_ambari_properties_method,
search_file_message,
- get_YN_input_method,
save_master_key_method,
- update_properties_method,
get_master_key_location_method,
- read_ambari_user_method,
read_master_key_method,
- save_passwd_for_alias_method,
remove_password_file_method,
- get_is_persisted_method,
get_is_secure_method, exists_mock):
-
- is_root_method.return_value = True
-
- p = Properties()
- FAKE_PWD_STRING = "fakepasswd"
- p.process_pair(JDBC_PASSWORD_PROPERTY, FAKE_PWD_STRING)
- p.process_pair(SSL_TRUSTSTORE_PASSWORD_PROPERTY, FAKE_PWD_STRING)
- p.process_pair(JDBC_RCA_PASSWORD_FILE_PROPERTY, FAKE_PWD_STRING)
- get_ambari_properties_method.return_value = p
-
- read_master_key_method.return_value = "aaa"
- get_YN_input_method.return_value = False
- read_ambari_user_method.return_value = None
- save_passwd_for_alias_method.return_value = 0
- get_is_persisted_method.return_value = (True, "filepath")
- get_is_secure_method.return_value = False
- exists_mock.return_value = False
-
- options = self._create_empty_options_mock()
- setup_master_key(options)
-
- self.assertTrue(get_YN_input_method.called)
- self.assertTrue(read_master_key_method.called)
- self.assertTrue(read_ambari_user_method.called)
- self.assertTrue(update_properties_method.called)
- self.assertFalse(save_master_key_method.called)
- self.assertTrue(save_passwd_for_alias_method.called)
- self.assertEquals(2, save_passwd_for_alias_method.call_count)
- self.assertTrue(remove_password_file_method.called)
-
- result_expected = {JDBC_PASSWORD_PROPERTY:
- get_alias_string(JDBC_RCA_PASSWORD_ALIAS),
- JDBC_RCA_PASSWORD_FILE_PROPERTY:
- get_alias_string(JDBC_RCA_PASSWORD_ALIAS),
- SSL_TRUSTSTORE_PASSWORD_PROPERTY:
- get_alias_string(SSL_TRUSTSTORE_PASSWORD_ALIAS),
- SECURITY_IS_ENCRYPTION_ENABLED: 'true'}
-
- sorted_x = sorted(result_expected.iteritems(), key=operator.itemgetter(0))
- sorted_y = sorted(update_properties_method.call_args[0][1].iteritems(),
- key=operator.itemgetter(0))
- self.assertEquals(sorted_x, sorted_y)
- pass
-
-
- @patch("ambari_server.setupSecurity.save_passwd_for_alias")
- @patch("os.path.exists")
- @patch("ambari_server.setupSecurity.get_is_secure")
- @patch("ambari_server.setupSecurity.get_is_persisted")
- @patch("ambari_server.setupSecurity.read_master_key")
- @patch("ambari_server.setupSecurity.read_ambari_user")
- @patch("ambari_server.setupSecurity.get_master_key_location")
- @patch("ambari_server.setupSecurity.update_properties_2")
- @patch("ambari_server.setupSecurity.save_master_key")
- @patch("ambari_server.setupSecurity.get_YN_input")
- @patch("ambari_server.serverConfiguration.search_file")
- @patch("ambari_server.setupSecurity.get_ambari_properties")
- @patch("ambari_server.setupSecurity.is_root")
- def test_setup_master_key_persist(self, is_root_method,
- get_ambari_properties_method,
search_file_message,
- get_YN_input_method,
save_master_key_method,
- update_properties_method,
get_master_key_location_method,
- read_ambari_user_method,
read_master_key_method,
- get_is_persisted_method,
get_is_secure_method, exists_mock,
- save_passwd_for_alias_method):
- is_root_method.return_value = True
-
- p = Properties()
- FAKE_PWD_STRING = "fakepasswd"
- p.process_pair(JDBC_PASSWORD_PROPERTY, FAKE_PWD_STRING)
- get_ambari_properties_method.return_value = p
-
- search_file_message.return_value = "propertiesfile"
-
- read_master_key_method.return_value = "aaa"
- get_YN_input_method.side_effect = [True, False]
- read_ambari_user_method.return_value = None
- get_is_persisted_method.return_value = (True, "filepath")
- get_is_secure_method.return_value = False
- exists_mock.return_value = False
- save_passwd_for_alias_method.return_value = 0
-
- options = self._create_empty_options_mock()
- setup_master_key(options)
-
- self.assertTrue(get_YN_input_method.called)
- self.assertTrue(read_master_key_method.called)
- self.assertTrue(read_ambari_user_method.called)
- self.assertTrue(update_properties_method.called)
- self.assertTrue(save_master_key_method.called)
-
- result_expected = {JDBC_PASSWORD_PROPERTY:
- get_alias_string(JDBC_RCA_PASSWORD_ALIAS),
- SECURITY_IS_ENCRYPTION_ENABLED: 'true'}
-
- sorted_x = sorted(result_expected.iteritems(), key=operator.itemgetter(0))
- sorted_y = sorted(update_properties_method.call_args[0][1].iteritems(),
- key=operator.itemgetter(0))
- self.assertEquals(sorted_x, sorted_y)
- pass
-
-
- @patch("ambari_server.setupSecurity.read_master_key")
- @patch("ambari_server.setupSecurity.remove_password_file")
- @patch("os.path.exists")
- @patch("ambari_server.setupSecurity.read_ambari_user")
- @patch("ambari_server.setupSecurity.get_master_key_location")
- @patch("ambari_server.setupSecurity.save_passwd_for_alias")
- @patch("ambari_server.setupSecurity.read_passwd_for_alias")
- @patch("ambari_server.setupSecurity.update_properties_2")
- @patch("ambari_server.setupSecurity.save_master_key")
- @patch("ambari_server.setupSecurity.get_validated_string_input")
- @patch("ambari_server.setupSecurity.get_YN_input")
- @patch("ambari_server.setupSecurity.search_file")
- @patch("ambari_server.setupSecurity.get_ambari_properties")
- @patch("ambari_server.setupSecurity.is_root")
- def test_reset_master_key_persisted(self, is_root_method,
- get_ambari_properties_method,
search_file_message,
- get_YN_input_method,
get_validated_string_input_method,
- save_master_key_method,
update_properties_method,
- read_passwd_for_alias_method,
save_passwd_for_alias_method,
- get_master_key_location_method,
- read_ambari_user_method, exists_mock,
- remove_password_file_method,
read_master_key_method):
-
- # Testing call under root
- is_root_method.return_value = True
-
- search_file_message.return_value = "filepath"
- read_ambari_user_method.return_value = None
-
- p = Properties()
- FAKE_PWD_STRING = '${alias=fakealias}'
- p.process_pair(JDBC_PASSWORD_PROPERTY, FAKE_PWD_STRING)
- p.process_pair(SSL_TRUSTSTORE_PASSWORD_PROPERTY, FAKE_PWD_STRING)
- p.process_pair(JDBC_RCA_PASSWORD_FILE_PROPERTY, FAKE_PWD_STRING)
- get_ambari_properties_method.return_value = p
-
- get_YN_input_method.side_effect = [True, True]
- read_master_key_method.return_value = "aaa"
- read_passwd_for_alias_method.return_value = "fakepassword"
- save_passwd_for_alias_method.return_value = 0
- exists_mock.return_value = False
-
-
- options = self._create_empty_options_mock()
- setup_master_key(options)
-
- self.assertTrue(save_master_key_method.called)
- self.assertTrue(get_YN_input_method.called)
- self.assertTrue(read_master_key_method.called)
- self.assertTrue(update_properties_method.called)
- self.assertTrue(read_passwd_for_alias_method.called)
- self.assertTrue(2, read_passwd_for_alias_method.call_count)
- self.assertTrue(2, save_passwd_for_alias_method.call_count)
-
- result_expected = {JDBC_PASSWORD_PROPERTY:
- get_alias_string(JDBC_RCA_PASSWORD_ALIAS),
- JDBC_RCA_PASSWORD_FILE_PROPERTY:
- get_alias_string(JDBC_RCA_PASSWORD_ALIAS),
- SSL_TRUSTSTORE_PASSWORD_PROPERTY:
- get_alias_string(SSL_TRUSTSTORE_PASSWORD_ALIAS),
- SECURITY_IS_ENCRYPTION_ENABLED: 'true'}
-
- sorted_x = sorted(result_expected.iteritems(), key=operator.itemgetter(0))
- sorted_y = sorted(update_properties_method.call_args[0][1].iteritems(),
- key=operator.itemgetter(0))
- self.assertEquals(sorted_x, sorted_y)
- pass
-
@patch("os.path.isdir", new = MagicMock(return_value=True))
@patch("os.access", new = MagicMock(return_value=True))
@patch.object(ServerClassPath,
"get_full_ambari_classpath_escaped_for_shell", new = MagicMock(return_value =
'test' + os.pathsep + 'path12'))
@@ -6953,77 +6762,6 @@ class TestAmbariServer(TestCase):
pass
- @patch("ambari_server.setupSecurity.get_is_persisted")
- @patch("ambari_server.setupSecurity.get_is_secure")
- @patch("ambari_server.setupSecurity.remove_password_file")
- @patch("os.path.exists")
- @patch("ambari_server.setupSecurity.read_ambari_user")
- @patch("ambari_server.setupSecurity.get_master_key_location")
- @patch("ambari_server.setupSecurity.save_passwd_for_alias")
- @patch("ambari_server.setupSecurity.read_passwd_for_alias")
- @patch("ambari_server.setupSecurity.update_properties_2")
- @patch("ambari_server.setupSecurity.save_master_key")
- @patch("ambari_server.setupSecurity.get_validated_string_input")
- @patch("ambari_server.setupSecurity.get_YN_input")
- @patch("ambari_server.setupSecurity.search_file")
- @patch("ambari_server.setupSecurity.get_ambari_properties")
- @patch("ambari_server.setupSecurity.is_root")
- def test_reset_master_key_not_persisted(self, is_root_method,
- get_ambari_properties_method,
- search_file_message,
get_YN_input_method,
- get_validated_string_input_method,
save_master_key_method,
- update_properties_method,
read_passwd_for_alias_method,
- save_passwd_for_alias_method,
- get_master_key_location_method,
read_ambari_user_method,
- exists_mock,
remove_password_file_method, get_is_secure_method,
- get_is_persisted_method):
-
- is_root_method.return_value = True
- search_file_message.return_value = False
- read_ambari_user_method.return_value = None
-
- p = Properties()
- FAKE_PWD_STRING = '${alias=fakealias}'
- p.process_pair(JDBC_PASSWORD_PROPERTY, FAKE_PWD_STRING)
- p.process_pair(SSL_TRUSTSTORE_PASSWORD_PROPERTY, FAKE_PWD_STRING)
- p.process_pair(JDBC_RCA_PASSWORD_FILE_PROPERTY, FAKE_PWD_STRING)
- get_ambari_properties_method.return_value = p
-
- get_YN_input_method.side_effect = [True, False]
- get_validated_string_input_method.return_value = "aaa"
- read_passwd_for_alias_method.return_value = "fakepassword"
- save_passwd_for_alias_method.return_value = 0
- exists_mock.return_value = False
- get_is_secure_method.return_value = True
- get_is_persisted_method.return_value = (True, "filePath")
-
- options = self._create_empty_options_mock()
- setup_master_key(options)
-
- self.assertFalse(save_master_key_method.called)
- self.assertTrue(get_YN_input_method.called)
- self.assertTrue(get_validated_string_input_method.called)
- self.assertTrue(update_properties_method.called)
- self.assertTrue(read_passwd_for_alias_method.called)
- self.assertTrue(2, read_passwd_for_alias_method.call_count)
- self.assertTrue(2, save_passwd_for_alias_method.call_count)
- self.assertFalse(save_master_key_method.called)
-
- result_expected = {JDBC_PASSWORD_PROPERTY:
- get_alias_string(JDBC_RCA_PASSWORD_ALIAS),
- JDBC_RCA_PASSWORD_FILE_PROPERTY:
- get_alias_string(JDBC_RCA_PASSWORD_ALIAS),
- SSL_TRUSTSTORE_PASSWORD_PROPERTY:
- get_alias_string(SSL_TRUSTSTORE_PASSWORD_ALIAS),
- SECURITY_IS_ENCRYPTION_ENABLED: 'true'}
-
- sorted_x = sorted(result_expected.iteritems(), key=operator.itemgetter(0))
- sorted_y = sorted(update_properties_method.call_args[0][1].iteritems(),
- key=operator.itemgetter(0))
- self.assertEquals(sorted_x, sorted_y)
- pass
-
-
@staticmethod
@OsFamilyFuncImpl(OSConst.WINSRV_FAMILY)
def _init_test_ldap_properties_map_invalid_input_1():
diff --git a/ambari-server/src/test/python/TestSensitiveDataEncryption.py
b/ambari-server/src/test/python/TestSensitiveDataEncryption.py
new file mode 100644
index 0000000..4e839c4
--- /dev/null
+++ b/ambari-server/src/test/python/TestSensitiveDataEncryption.py
@@ -0,0 +1,667 @@
+'''
+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 os
+import sys
+
+from ambari_commons.exceptions import FatalException
+from mock.mock import patch, MagicMock, call
+
+with patch.object(os, "geteuid", new=MagicMock(return_value=0)):
+ from resource_management.core import sudo
+ reload(sudo)
+
+import operator
+import platform
+import StringIO
+from unittest import TestCase
+os.environ["ROOT"] = ""
+
+from only_for_platform import get_platform, os_distro_value, PLATFORM_WINDOWS
+from ambari_commons import os_utils
+
+if get_platform() != PLATFORM_WINDOWS:
+ pass
+
+import shutil
+project_dir =
os.path.join(os.path.abspath(os.path.dirname(__file__)),os.path.normpath("../../../../"))
+shutil.copyfile(project_dir+"/ambari-server/conf/unix/ambari.properties",
"/tmp/ambari.properties")
+
+# We have to use this import HACK because the filename contains a dash
+_search_file = os_utils.search_file
+
+
+def search_file_proxy(filename, searchpatch, pathsep=os.pathsep):
+ global _search_file
+
+ if "ambari.properties" in filename:
+ return "/tmp/ambari.properties"
+
+ return _search_file(filename, searchpatch, pathsep)
+
+
+os_utils.search_file = search_file_proxy
+with patch.object(platform, "linux_distribution", return_value =
MagicMock(return_value=('Redhat', '6.4', 'Final'))):
+ with patch("os.path.isdir", return_value = MagicMock(return_value=True)):
+ with patch("os.access", return_value = MagicMock(return_value=True)):
+ with patch.object(os_utils, "parse_log4j_file",
return_value={'ambari.log.dir': '/var/log/ambari-server'}):
+ with patch("platform.linux_distribution", return_value =
os_distro_value):
+ with patch("os.symlink"):
+ with patch("glob.glob", return_value =
['/etc/init.d/postgresql-9.3']):
+ _ambari_server_ = __import__('ambari-server')
+ with patch("__builtin__.open"):
+ from ambari_server.properties import Properties
+ from ambari_server.serverConfiguration import configDefaults,
JDBC_RCA_PASSWORD_FILE_PROPERTY, JDBC_PASSWORD_PROPERTY, \
+ JDBC_RCA_PASSWORD_ALIAS, SSL_TRUSTSTORE_PASSWORD_PROPERTY,
SECURITY_IS_ENCRYPTION_ENABLED, \
+ SECURITY_SENSITIVE_DATA_ENCRYPTON_ENABLED, SSL_TRUSTSTORE_PASSWORD_ALIAS,
SECURITY_KEY_ENV_VAR_NAME
+ from ambari_server.setupSecurity import get_alias_string,
setup_sensitive_data_encryption, sensitive_data_encryption
+ from ambari_server.serverClassPath import ServerClassPath
+
+
[email protected](platform, "linux_distribution", new =
MagicMock(return_value=('Redhat', '6.4', 'Final')))
+@patch("ambari_server.dbConfiguration_linux.get_postgre_hba_dir", new =
MagicMock(return_value = "/var/lib/pgsql/data"))
+@patch("ambari_server.dbConfiguration_linux.get_postgre_running_status", new =
MagicMock(return_value = "running"))
+class TestSensitiveDataEncryption(TestCase):
+ def setUp(self):
+ out = StringIO.StringIO()
+ sys.stdout = out
+
+
+ def tearDown(self):
+ sys.stdout = sys.__stdout__
+
+ @patch("os.path.isdir", new = MagicMock(return_value=True))
+ @patch("os.access", new = MagicMock(return_value=True))
+ @patch.object(ServerClassPath,
"get_full_ambari_classpath_escaped_for_shell", new = MagicMock(return_value =
'test' + os.pathsep + 'path12'))
+ @patch("ambari_server.setupSecurity.find_jdk")
+ @patch("ambari_server.setupSecurity.get_ambari_properties")
+ @patch("ambari_server.setupSecurity.run_os_command")
+ def test_sensitive_data_encryption(self, run_os_command_mock,
get_ambari_properties_method, find_jdk_mock):
+ find_jdk_mock.return_value = "/"
+ environ = os.environ.copy()
+
+ run_os_command_mock.return_value = 0,"",""
+ properties = Properties()
+ get_ambari_properties_method.return_value = properties
+ options = self._create_empty_options_mock()
+ sensitive_data_encryption(options, "encription")
+ run_os_command_mock.assert_called_with('None -cp test:path12
org.apache.ambari.server.security.encryption.SensitiveDataEncryption encription
> /var/log/ambari-server/ambari-server.out 2>&1', environ)
+ pass
+
+ @patch("ambari_server.setupSecurity.print_error_msg")
+ @patch("ambari_server.setupSecurity.find_jdk")
+ def test_sensitive_data_encryption_nojdk(self, find_jdk_mock, print_mock):
+ find_jdk_mock.return_value = None
+
+ options = self._create_empty_options_mock()
+ code = sensitive_data_encryption(options, "encription")
+ self.assertEquals(code, 1)
+ print_mock.assert_called_with("No JDK found, please run the \"setup\" "
+ "command to install a JDK automatically or
install any "
+ "JDK manually to " +
configDefaults.JDK_INSTALL_DIR)
+ pass
+
+ @patch("os.path.isdir", new = MagicMock(return_value=True))
+ @patch("os.access", new = MagicMock(return_value=True))
+ @patch.object(ServerClassPath,
"get_full_ambari_classpath_escaped_for_shell", new = MagicMock(return_value =
'test' + os.pathsep + 'path12'))
+ @patch("ambari_server.setupSecurity.find_jdk")
+ @patch("ambari_server.setupSecurity.get_ambari_properties")
+ @patch("ambari_server.setupSecurity.run_os_command")
+ def test_sensitive_data_decryption_not_persisted(self, run_os_command_mock,
get_ambari_properties_method, find_jdk_mock):
+ find_jdk_mock.return_value = "/"
+ environ = os.environ.copy()
+ master = "master"
+ environ[SECURITY_KEY_ENV_VAR_NAME] = master
+
+ run_os_command_mock.return_value = 0,"",""
+ properties = Properties()
+ get_ambari_properties_method.return_value = properties
+ options = self._create_empty_options_mock()
+ sensitive_data_encryption(options, "decryption", master)
+ run_os_command_mock.assert_called_with('None -cp test:path12
org.apache.ambari.server.security.encryption.SensitiveDataEncryption decryption
> /var/log/ambari-server/ambari-server.out 2>&1', environ)
+ pass
+
+ @patch("ambari_server.setupSecurity.get_is_persisted")
+ @patch("ambari_server.setupSecurity.get_is_secure")
+ @patch("os.path.exists")
+ @patch("ambari_server.setupSecurity.read_ambari_user")
+ @patch("ambari_server.setupSecurity.save_passwd_for_alias")
+ @patch("ambari_server.setupSecurity.read_passwd_for_alias")
+ @patch("ambari_server.setupSecurity.update_properties_2")
+ @patch("ambari_server.setupSecurity.save_master_key")
+ @patch("ambari_server.setupSecurity.get_validated_string_input")
+ @patch("ambari_server.setupSecurity.get_YN_input")
+ @patch("ambari_server.setupSecurity.search_file")
+ @patch("ambari_server.setupSecurity.get_ambari_properties")
+ @patch("ambari_server.setupSecurity.is_root")
+ @patch("ambari_server.setupSecurity.sensitive_data_encryption")
+ @patch("ambari_server.setupSecurity.get_original_master_key")
+ def test_reset_master_key_not_persisted(self, get_original_master_key_mock,
sensitive_data_encryption_metod, is_root_method,
+ get_ambari_properties_method,
+ search_file_message,
get_YN_input_method,
+ get_validated_string_input_method,
save_master_key_method,
+ update_properties_method,
read_passwd_for_alias_method,
+ save_passwd_for_alias_method,
+ read_ambari_user_method,
+ exists_mock, get_is_secure_method,
+ get_is_persisted_method):
+
+ is_root_method.return_value = True
+ search_file_message.return_value = False
+ read_ambari_user_method.return_value = None
+
+ p = Properties()
+ FAKE_PWD_STRING = '${alias=fakealias}'
+ p.process_pair(JDBC_PASSWORD_PROPERTY, FAKE_PWD_STRING)
+ p.process_pair(SSL_TRUSTSTORE_PASSWORD_PROPERTY, FAKE_PWD_STRING)
+ p.process_pair(JDBC_RCA_PASSWORD_FILE_PROPERTY, FAKE_PWD_STRING)
+ get_ambari_properties_method.return_value = p
+
+ master_key = "aaa"
+ get_YN_input_method.side_effect = [False, True, False]
+ get_validated_string_input_method.return_value = master_key
+ get_original_master_key_mock.return_value = master_key
+ read_passwd_for_alias_method.return_value = "fakepassword"
+ save_passwd_for_alias_method.return_value = 0
+ exists_mock.return_value = False
+ get_is_secure_method.return_value = True
+ get_is_persisted_method.return_value = (False, "")
+
+ options = self._create_empty_options_mock()
+ setup_sensitive_data_encryption(options)
+ calls = [call(options, "decryption", master_key), call(options,
"encryption", master_key)]
+ sensitive_data_encryption_metod.assert_has_calls(calls)
+
+ self.assertFalse(save_master_key_method.called)
+ self.assertTrue(get_original_master_key_mock.called)
+ self.assertTrue(get_YN_input_method.called)
+ self.assertTrue(get_validated_string_input_method.called)
+ self.assertTrue(update_properties_method.called)
+ self.assertTrue(read_passwd_for_alias_method.called)
+ self.assertTrue(2, read_passwd_for_alias_method.call_count)
+ self.assertTrue(2, save_passwd_for_alias_method.call_count)
+ self.assertFalse(save_master_key_method.called)
+
+ result_expected = {JDBC_PASSWORD_PROPERTY:
+ get_alias_string(JDBC_RCA_PASSWORD_ALIAS),
+ JDBC_RCA_PASSWORD_FILE_PROPERTY:
+ get_alias_string(JDBC_RCA_PASSWORD_ALIAS),
+ SSL_TRUSTSTORE_PASSWORD_PROPERTY:
+ get_alias_string(SSL_TRUSTSTORE_PASSWORD_ALIAS),
+ SECURITY_IS_ENCRYPTION_ENABLED: 'true',
+ SECURITY_SENSITIVE_DATA_ENCRYPTON_ENABLED: 'true'}
+
+ sorted_x = sorted(result_expected.iteritems(), key=operator.itemgetter(0))
+ sorted_y = sorted(update_properties_method.call_args[0][1].iteritems(),
+ key=operator.itemgetter(0))
+ self.assertEquals(sorted_x, sorted_y)
+ pass
+
+ @patch("ambari_server.setupSecurity.get_is_persisted")
+ @patch("ambari_server.setupSecurity.get_is_secure")
+ @patch("os.path.exists")
+ @patch("ambari_server.setupSecurity.read_ambari_user")
+ @patch("ambari_server.setupSecurity.save_passwd_for_alias")
+ @patch("ambari_server.setupSecurity.read_passwd_for_alias")
+ @patch("ambari_server.setupSecurity.update_properties_2")
+ @patch("ambari_server.setupSecurity.save_master_key")
+ @patch("ambari_server.setupSecurity.get_YN_input")
+ @patch("ambari_server.setupSecurity.search_file")
+ @patch("ambari_server.setupSecurity.get_ambari_properties")
+ @patch("ambari_server.setupSecurity.is_root")
+ @patch("ambari_server.setupSecurity.sensitive_data_encryption")
+ @patch("ambari_server.setupSecurity.get_original_master_key")
+ def test_encrypt_part_not_persisted(self, get_original_master_key_mock,
sensitive_data_encryption_metod, is_root_method,
+ get_ambari_properties_method,
+ search_file_message,
get_YN_input_method,
+ save_master_key_method,
+ update_properties_method,
read_passwd_for_alias_method,
+ save_passwd_for_alias_method,
+ read_ambari_user_method,
+ exists_mock, get_is_secure_method,
+ get_is_persisted_method):
+
+ is_root_method.return_value = True
+ search_file_message.return_value = False
+ read_ambari_user_method.return_value = None
+
+ p = Properties()
+ FAKE_PWD_STRING = '${alias=fakealias}'
+ p.process_pair(JDBC_PASSWORD_PROPERTY,
get_alias_string(JDBC_RCA_PASSWORD_ALIAS))
+ p.process_pair(SSL_TRUSTSTORE_PASSWORD_PROPERTY, FAKE_PWD_STRING)
+ p.process_pair(JDBC_RCA_PASSWORD_FILE_PROPERTY, FAKE_PWD_STRING)
+ get_ambari_properties_method.return_value = p
+
+ master_key = "aaa"
+ get_YN_input_method.side_effect = [False, False, False]
+ get_original_master_key_mock.return_value = master_key
+ read_passwd_for_alias_method.return_value = "fakepassword"
+ save_passwd_for_alias_method.return_value = 0
+ exists_mock.return_value = False
+ get_is_secure_method.return_value = True
+ get_is_persisted_method.return_value = (False, "filePath")
+
+ options = self._create_empty_options_mock()
+ setup_sensitive_data_encryption(options)
+ calls = [call(options, "encryption", master_key)]
+ sensitive_data_encryption_metod.assert_has_calls(calls)
+
+ self.assertFalse(save_master_key_method.called)
+ self.assertTrue(get_YN_input_method.called)
+ self.assertTrue(get_original_master_key_mock.called)
+ self.assertTrue(update_properties_method.called)
+ self.assertTrue(read_passwd_for_alias_method.called)
+ self.assertTrue(2, read_passwd_for_alias_method.call_count)
+ self.assertTrue(2, save_passwd_for_alias_method.call_count)
+ self.assertFalse(save_master_key_method.called)
+
+ result_expected = {JDBC_PASSWORD_PROPERTY:
+ get_alias_string(JDBC_RCA_PASSWORD_ALIAS),
+ JDBC_RCA_PASSWORD_FILE_PROPERTY:
+ get_alias_string(JDBC_RCA_PASSWORD_ALIAS),
+ SSL_TRUSTSTORE_PASSWORD_PROPERTY:
+ get_alias_string(SSL_TRUSTSTORE_PASSWORD_ALIAS),
+ SECURITY_IS_ENCRYPTION_ENABLED: 'true',
+ SECURITY_SENSITIVE_DATA_ENCRYPTON_ENABLED: 'true'}
+
+ sorted_x = sorted(result_expected.iteritems(), key=operator.itemgetter(0))
+ sorted_y = sorted(update_properties_method.call_args[0][1].iteritems(),
+ key=operator.itemgetter(0))
+ self.assertEquals(sorted_x, sorted_y)
+ pass
+
+ @patch("ambari_server.setupSecurity.get_is_persisted")
+ @patch("ambari_server.setupSecurity.get_is_secure")
+ @patch("os.path.exists")
+ @patch("ambari_server.setupSecurity.read_ambari_user")
+ @patch("ambari_server.setupSecurity.save_passwd_for_alias")
+ @patch("ambari_server.setupSecurity.read_passwd_for_alias")
+ @patch("ambari_server.setupSecurity.save_master_key")
+ @patch("ambari_server.setupSecurity.get_YN_input")
+ @patch("ambari_server.setupSecurity.search_file")
+ @patch("ambari_server.setupSecurity.get_ambari_properties")
+ @patch("ambari_server.setupSecurity.is_root")
+ @patch("ambari_server.setupSecurity.get_original_master_key")
+ def test_decrypt_missed_masterkey_not_persisted(self,
get_original_master_key_mock, is_root_method,
+ get_ambari_properties_method,
+ search_file_message, get_YN_input_method,
+ save_master_key_method,
+ read_passwd_for_alias_method,
+ save_passwd_for_alias_method,
+ read_ambari_user_method,
+ exists_mock, get_is_secure_method,
+ get_is_persisted_method):
+
+ is_root_method.return_value = True
+ search_file_message.return_value = False
+ read_ambari_user_method.return_value = None
+
+ p = Properties()
+ FAKE_PWD_STRING = '${alias=fakealias}'
+ p.process_pair(JDBC_PASSWORD_PROPERTY,
get_alias_string(JDBC_RCA_PASSWORD_ALIAS))
+ p.process_pair(SSL_TRUSTSTORE_PASSWORD_PROPERTY, FAKE_PWD_STRING)
+ p.process_pair(JDBC_RCA_PASSWORD_FILE_PROPERTY, FAKE_PWD_STRING)
+ get_ambari_properties_method.return_value = p
+
+ get_YN_input_method.side_effect = [True, False]
+ get_original_master_key_mock.return_value = None
+ read_passwd_for_alias_method.return_value = "fakepassword"
+ save_passwd_for_alias_method.return_value = 0
+ exists_mock.return_value = False
+ get_is_secure_method.return_value = True
+ get_is_persisted_method.return_value = (False, "filePath")
+
+ options = self._create_empty_options_mock()
+ self.assertTrue(setup_sensitive_data_encryption(options) == 1)
+
+ self.assertFalse(save_master_key_method.called)
+ self.assertTrue(get_YN_input_method.called)
+ pass
+
+ @patch("ambari_server.setupSecurity.get_ambari_properties")
+ @patch("ambari_server.setupSecurity.is_root")
+ def test_setup_sensitive_data_encryption_no_ambari_prop_not_root(self,
is_root_method, get_ambari_properties_method):
+
+ is_root_method.return_value = False
+ get_ambari_properties_method.return_value = -1
+ options = self._create_empty_options_mock()
+
+ try:
+ setup_sensitive_data_encryption(options)
+ self.fail("Should throw exception")
+ except FatalException as fe:
+ self.assertTrue('Failed to read properties file.' == fe.reason)
+ pass
+ pass
+
+ @patch("os.path.exists")
+ @patch("ambari_server.setupSecurity.get_is_secure")
+ @patch("ambari_server.setupSecurity.get_is_persisted")
+ @patch("ambari_server.setupSecurity.remove_password_file")
+ @patch("ambari_server.setupSecurity.save_passwd_for_alias")
+ @patch("ambari_server.setupSecurity.read_master_key")
+ @patch("ambari_server.setupSecurity.read_ambari_user")
+ @patch("ambari_server.setupSecurity.update_properties_2")
+ @patch("ambari_server.setupSecurity.save_master_key")
+ @patch("ambari_server.setupSecurity.get_YN_input")
+ @patch("ambari_server.setupSecurity.get_ambari_properties")
+ @patch("ambari_server.setupSecurity.is_root")
+ @patch("ambari_server.setupSecurity.sensitive_data_encryption")
+ @patch("ambari_server.setupSecurity.adjust_directory_permissions")
+ def test_setup_sensitive_data_encryption_not_persist(self,
adjust_directory_permissions_mock, sensitive_data_encryption_metod,
is_root_method,
+
get_ambari_properties_method, get_YN_input_method, save_master_key_method,
+
update_properties_method,
+
read_ambari_user_method, read_master_key_method,
+
save_passwd_for_alias_method, remove_password_file_method,
+
get_is_persisted_method, get_is_secure_method, exists_mock):
+
+ is_root_method.return_value = True
+
+ p = Properties()
+ FAKE_PWD_STRING = "fakepasswd"
+ p.process_pair(JDBC_PASSWORD_PROPERTY, FAKE_PWD_STRING)
+ p.process_pair(SSL_TRUSTSTORE_PASSWORD_PROPERTY, FAKE_PWD_STRING)
+ p.process_pair(JDBC_RCA_PASSWORD_FILE_PROPERTY, FAKE_PWD_STRING)
+ get_ambari_properties_method.return_value = p
+
+ master_key = "aaa"
+ read_master_key_method.return_value = master_key
+ get_YN_input_method.return_value = False
+ read_ambari_user_method.return_value = "asd"
+ save_passwd_for_alias_method.return_value = 0
+ get_is_persisted_method.return_value = (True, "filepath")
+ get_is_secure_method.return_value = False
+ exists_mock.return_value = False
+
+ options = self._create_empty_options_mock()
+ setup_sensitive_data_encryption(options)
+
+ self.assertTrue(get_YN_input_method.called)
+ self.assertTrue(read_master_key_method.called)
+ self.assertTrue(read_ambari_user_method.called)
+ self.assertTrue(update_properties_method.called)
+ self.assertFalse(save_master_key_method.called)
+ self.assertTrue(save_passwd_for_alias_method.called)
+ self.assertEquals(2, save_passwd_for_alias_method.call_count)
+ self.assertTrue(remove_password_file_method.called)
+ self.assertTrue(adjust_directory_permissions_mock.called)
+ sensitive_data_encryption_metod.assert_called_with(options, "encryption",
master_key)
+
+ result_expected = {JDBC_PASSWORD_PROPERTY:
+ get_alias_string(JDBC_RCA_PASSWORD_ALIAS),
+ JDBC_RCA_PASSWORD_FILE_PROPERTY:
+ get_alias_string(JDBC_RCA_PASSWORD_ALIAS),
+ SSL_TRUSTSTORE_PASSWORD_PROPERTY:
+ get_alias_string(SSL_TRUSTSTORE_PASSWORD_ALIAS),
+ SECURITY_IS_ENCRYPTION_ENABLED: 'true',
+ SECURITY_SENSITIVE_DATA_ENCRYPTON_ENABLED: 'true'}
+
+ sorted_x = sorted(result_expected.iteritems(), key=operator.itemgetter(0))
+ sorted_y = sorted(update_properties_method.call_args[0][1].iteritems(),
+ key=operator.itemgetter(0))
+ self.assertEquals(sorted_x, sorted_y)
+ pass
+
+ @patch("ambari_server.setupSecurity.save_passwd_for_alias")
+ @patch("os.path.exists")
+ @patch("ambari_server.setupSecurity.get_is_secure")
+ @patch("ambari_server.setupSecurity.get_is_persisted")
+ @patch("ambari_server.setupSecurity.read_master_key")
+ @patch("ambari_server.setupSecurity.read_ambari_user")
+ @patch("ambari_server.setupSecurity.update_properties_2")
+ @patch("ambari_server.setupSecurity.save_master_key")
+ @patch("ambari_server.setupSecurity.get_YN_input")
+ @patch("ambari_server.serverConfiguration.search_file")
+ @patch("ambari_server.setupSecurity.get_ambari_properties")
+ @patch("ambari_server.setupSecurity.is_root")
+ @patch("ambari_server.setupSecurity.sensitive_data_encryption")
+ def test_setup_sensitive_data_encryption_persist(self,
sensitive_data_encryption_metod, is_root_method,
+
get_ambari_properties_method, search_file_message,
+ get_YN_input_method,
save_master_key_method,
+ update_properties_method,
+ read_ambari_user_method,
read_master_key_method,
+ get_is_persisted_method,
get_is_secure_method, exists_mock,
+
save_passwd_for_alias_method):
+ is_root_method.return_value = True
+
+ p = Properties()
+ FAKE_PWD_STRING = "fakepasswd"
+ p.process_pair(JDBC_PASSWORD_PROPERTY, FAKE_PWD_STRING)
+ get_ambari_properties_method.return_value = p
+
+ search_file_message.return_value = "propertiesfile"
+
+ master_key = "aaa"
+ read_master_key_method.return_value = master_key
+ get_YN_input_method.return_value = True
+ read_ambari_user_method.return_value = None
+ get_is_persisted_method.return_value = (True, "filepath")
+ get_is_secure_method.return_value = False
+ exists_mock.return_value = False
+ save_passwd_for_alias_method.return_value = 0
+
+ options = self._create_empty_options_mock()
+ setup_sensitive_data_encryption(options)
+
+ self.assertTrue(get_YN_input_method.called)
+ self.assertTrue(read_master_key_method.called)
+ self.assertTrue(read_ambari_user_method.called)
+ self.assertTrue(update_properties_method.called)
+ self.assertTrue(save_master_key_method.called)
+ sensitive_data_encryption_metod.assert_called_with(options, "encryption")
+
+ result_expected = {JDBC_PASSWORD_PROPERTY:
+ get_alias_string(JDBC_RCA_PASSWORD_ALIAS),
+ SECURITY_IS_ENCRYPTION_ENABLED: 'true',
+ SECURITY_SENSITIVE_DATA_ENCRYPTON_ENABLED: 'true'}
+
+ sorted_x = sorted(result_expected.iteritems(), key=operator.itemgetter(0))
+ sorted_y = sorted(update_properties_method.call_args[0][1].iteritems(),
+ key=operator.itemgetter(0))
+ self.assertEquals(sorted_x, sorted_y)
+ pass
+
+ @patch("ambari_server.setupSecurity.read_master_key")
+ @patch("os.path.exists")
+ @patch("ambari_server.setupSecurity.read_ambari_user")
+ @patch("ambari_server.setupSecurity.save_passwd_for_alias")
+ @patch("ambari_server.setupSecurity.read_passwd_for_alias")
+ @patch("ambari_server.setupSecurity.update_properties_2")
+ @patch("ambari_server.setupSecurity.save_master_key")
+ @patch("ambari_server.setupSecurity.get_YN_input")
+ @patch("ambari_server.setupSecurity.search_file")
+ @patch("ambari_server.setupSecurity.get_ambari_properties")
+ @patch("ambari_server.setupSecurity.is_root")
+ @patch("ambari_server.setupSecurity.sensitive_data_encryption")
+ @patch("ambari_server.setupSecurity.get_is_secure")
+ def test_reset_master_key_persisted(self, get_is_secure_method,
sensitive_data_encryption_metod, is_root_method,
+ get_ambari_properties_method,
search_file_message,
+ get_YN_input_method,
+ save_master_key_method,
update_properties_method,
+ read_passwd_for_alias_method,
save_passwd_for_alias_method,
+ read_ambari_user_method, exists_mock,
+ read_master_key_method):
+
+ # Testing call under root
+ is_root_method.return_value = True
+
+ search_file_message.return_value = "filepath"
+ read_ambari_user_method.return_value = None
+
+ p = Properties()
+ FAKE_PWD_STRING = '${alias=fakealias}'
+ p.process_pair(JDBC_PASSWORD_PROPERTY, FAKE_PWD_STRING)
+ p.process_pair(SSL_TRUSTSTORE_PASSWORD_PROPERTY, FAKE_PWD_STRING)
+ p.process_pair(JDBC_RCA_PASSWORD_FILE_PROPERTY, FAKE_PWD_STRING)
+ get_ambari_properties_method.return_value = p
+
+ master_key = "aaa"
+
+ get_is_secure_method.return_value = True
+ get_YN_input_method.side_effect = [False, True, True]
+ read_master_key_method.return_value = master_key
+ read_passwd_for_alias_method.return_value = "fakepassword"
+ save_passwd_for_alias_method.return_value = 0
+ exists_mock.return_value = False
+
+
+ options = self._create_empty_options_mock()
+ setup_sensitive_data_encryption(options)
+ calls = [call(options, "decryption"), call(options, "encryption")]
+ sensitive_data_encryption_metod.assert_has_calls(calls)
+
+ self.assertTrue(save_master_key_method.called)
+ self.assertTrue(get_YN_input_method.called)
+ self.assertTrue(read_master_key_method.called)
+ self.assertTrue(update_properties_method.called)
+ self.assertTrue(read_passwd_for_alias_method.called)
+ self.assertTrue(2, read_passwd_for_alias_method.call_count)
+ self.assertTrue(2, save_passwd_for_alias_method.call_count)
+
+ result_expected = {JDBC_PASSWORD_PROPERTY:
+ get_alias_string(JDBC_RCA_PASSWORD_ALIAS),
+ JDBC_RCA_PASSWORD_FILE_PROPERTY:
+ get_alias_string(JDBC_RCA_PASSWORD_ALIAS),
+ SSL_TRUSTSTORE_PASSWORD_PROPERTY:
+ get_alias_string(SSL_TRUSTSTORE_PASSWORD_ALIAS),
+ SECURITY_IS_ENCRYPTION_ENABLED: 'true',
+ SECURITY_SENSITIVE_DATA_ENCRYPTON_ENABLED: 'true'}
+
+ sorted_x = sorted(result_expected.iteritems(), key=operator.itemgetter(0))
+ sorted_y = sorted(update_properties_method.call_args[0][1].iteritems(),
+ key=operator.itemgetter(0))
+ self.assertEquals(sorted_x, sorted_y)
+ pass
+
+ @patch("ambari_server.setupSecurity.read_master_key")
+ @patch("os.path.exists")
+ @patch("ambari_server.setupSecurity.read_ambari_user")
+ @patch("ambari_server.setupSecurity.save_passwd_for_alias")
+ @patch("ambari_server.setupSecurity.read_passwd_for_alias")
+ @patch("ambari_server.setupSecurity.update_properties_2")
+ @patch("ambari_server.setupSecurity.get_YN_input")
+ @patch("ambari_server.setupSecurity.search_file")
+ @patch("ambari_server.setupSecurity.get_ambari_properties")
+ @patch("ambari_server.setupSecurity.is_root")
+ @patch("ambari_server.setupSecurity.sensitive_data_encryption")
+ @patch("ambari_server.setupSecurity.get_is_secure")
+ def test_decrypt_sensitive_data(self, get_is_secure_method,
sensitive_data_encryption_metod, is_root_method,
+ get_ambari_properties_method,
search_file_message,
+ get_YN_input_method,
+ update_properties_method,
+ read_passwd_for_alias_method,
save_passwd_for_alias_method,
+ read_ambari_user_method, exists_mock,
+ read_master_key_method):
+
+ # Testing call under root
+ is_root_method.return_value = True
+
+ search_file_message.return_value = "filepath"
+ read_ambari_user_method.return_value = None
+
+ p = Properties()
+ FAKE_PWD_STRING = '${alias=fakealias}'
+ p.process_pair(JDBC_PASSWORD_PROPERTY, FAKE_PWD_STRING)
+ p.process_pair(SSL_TRUSTSTORE_PASSWORD_PROPERTY, FAKE_PWD_STRING)
+ p.process_pair(JDBC_RCA_PASSWORD_FILE_PROPERTY, FAKE_PWD_STRING)
+ get_ambari_properties_method.return_value = p
+
+ master_key = "aaa"
+ get_is_secure_method.return_value = True
+ get_YN_input_method.side_effect = [True, False]
+ read_master_key_method.return_value = master_key
+ read_passwd_for_alias_method.return_value = "fakepassword"
+ save_passwd_for_alias_method.return_value = 0
+ exists_mock.return_value = False
+
+
+ options = self._create_empty_options_mock()
+ setup_sensitive_data_encryption(options)
+ calls = [call(options, "decryption")]
+ sensitive_data_encryption_metod.assert_has_calls(calls)
+
+ self.assertTrue(get_YN_input_method.called)
+ self.assertTrue(update_properties_method.called)
+ self.assertTrue(read_passwd_for_alias_method.called)
+ self.assertTrue(2, read_passwd_for_alias_method.call_count)
+ self.assertTrue(2, save_passwd_for_alias_method.call_count)
+
+ result_expected = {JDBC_PASSWORD_PROPERTY: "fakepassword",
+ JDBC_RCA_PASSWORD_FILE_PROPERTY: "fakepassword",
+ SSL_TRUSTSTORE_PASSWORD_PROPERTY: "fakepassword",
+ SECURITY_IS_ENCRYPTION_ENABLED: 'false',
+ SECURITY_SENSITIVE_DATA_ENCRYPTON_ENABLED: 'false'}
+
+ sorted_x = sorted(result_expected.iteritems(), key=operator.itemgetter(0))
+ sorted_y = sorted(update_properties_method.call_args[0][1].iteritems(),
+ key=operator.itemgetter(0))
+ self.assertEquals(sorted_x, sorted_y)
+ pass
+
+ def _create_empty_options_mock(self):
+ options = MagicMock()
+ options.ldap_enabled = None
+ options.ldap_enabled_ambari = None
+ options.ldap_manage_services = None
+ options.ldap_enabled_services = None
+ options.ldap_url = None
+ options.ldap_primary_host = None
+ options.ldap_primary_port = None
+ options.ldap_secondary_url = None
+ options.ldap_secondary_host = None
+ options.ldap_secondary_port = None
+ options.ldap_ssl = None
+ options.ldap_user_class = None
+ options.ldap_user_attr = None
+ options.ldap_user_group_member_attr = None
+ options.ldap_group_class = None
+ options.ldap_group_attr = None
+ options.ldap_member_attr = None
+ options.ldap_dn = None
+ options.ldap_base_dn = None
+ options.ldap_manager_dn = None
+ options.ldap_manager_password = None
+ options.ldap_save_settings = None
+ options.ldap_referral = None
+ options.ldap_bind_anonym = None
+ options.ldap_force_setup = None
+ options.ambari_admin_username = None
+ options.ambari_admin_password = None
+ options.ldap_sync_admin_name = None
+ options.ldap_sync_username_collisions_behavior = None
+ options.ldap_sync_disable_endpoint_identification = None
+ options.ldap_force_lowercase_usernames = None
+ options.ldap_pagination_enabled = None
+ options.ldap_sync_admin_password = None
+ options.custom_trust_store = None
+ options.trust_store_type = None
+ options.trust_store_path = None
+ options.trust_store_password = None
+ options.security_option = None
+ options.api_ssl = None
+ options.api_ssl_port = None
+ options.import_cert_path = None
+ options.import_cert_alias = None
+ options.pem_password = None
+ options.import_key_path = None
+ options.master_key = None
+ options.master_key_persist = None
+ options.jaas_principal = None
+ options.jaas_keytab = None
+ return options
+
+