diff --git a/core/src/main/python/wlsdeploy/aliases/aliases.py b/core/src/main/python/wlsdeploy/aliases/aliases.py index 68ed378b0..2aa1e4243 100644 --- a/core/src/main/python/wlsdeploy/aliases/aliases.py +++ b/core/src/main/python/wlsdeploy/aliases/aliases.py @@ -397,13 +397,7 @@ def get_wlst_attribute_name_and_value(self, location, model_attribute_name, mode attribute_info = module_folder[ATTRIBUTES][model_attribute_name] if attribute_info and not self.__is_model_attribute_read_only(location, attribute_info): - password_attribute_name = \ - password_utils.get_wlst_attribute_name(attribute_info, model_attribute_value, self._wlst_mode) - - if password_attribute_name is not None: - wlst_attribute_name = password_attribute_name - else: - wlst_attribute_name = attribute_info[WLST_NAME] + wlst_attribute_name = attribute_info[WLST_NAME] if self._model_context and USES_PATH_TOKENS in attribute_info and \ string_utils.to_boolean(attribute_info[USES_PATH_TOKENS]): @@ -413,6 +407,14 @@ def get_wlst_attribute_name_and_value(self, location, model_attribute_name, mode if data_type == 'password': try: wlst_attribute_value = self.decrypt_password(model_attribute_value) + + # the attribute name may change for special cases, check against decrypted value + password_attribute_name = \ + password_utils.get_wlst_attribute_name(attribute_info, wlst_attribute_value, self._wlst_mode) + + if password_attribute_name is not None: + wlst_attribute_name = password_attribute_name + except EncryptionException, ee: ex = exception_helper.create_alias_exception('WLSDPLY-08402', model_attribute_name, location.get_folder_path(), @@ -1200,7 +1202,7 @@ def get_wlst_read_type(self, location, model_attribute_name): def decrypt_password(self, text): """ - Encrypt the specified password if encryption is used and the password is encrypted. + Decrypt the specified password if model encryption is used and the password is encrypted. :param text: the text to check and decrypt, if needed :return: the clear text :raises EncryptionException: if an error occurs while decrypting the password diff --git a/core/src/test/python/alias_encrypted_model_test.py b/core/src/test/python/alias_encrypted_model_test.py new file mode 100644 index 000000000..4b5ce9e49 --- /dev/null +++ b/core/src/test/python/alias_encrypted_model_test.py @@ -0,0 +1,77 @@ +""" +Copyright (c) 2019, Oracle Corporation and/or its affiliates. All rights reserved. +Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. +""" +import unittest + +from wlsdeploy.aliases.aliases import Aliases +from wlsdeploy.aliases.location_context import LocationContext +from wlsdeploy.aliases.model_constants import JDBC_DRIVER_PARAMS +from wlsdeploy.aliases.model_constants import JDBC_RESOURCE +from wlsdeploy.aliases.model_constants import JDBC_SYSTEM_RESOURCE +from wlsdeploy.aliases.model_constants import PASSWORD_ENCRYPTED +from wlsdeploy.aliases.wlst_modes import WlstModes +from wlsdeploy.logging.platform_logger import PlatformLogger +from wlsdeploy.util.cla_utils import CommandLineArgUtil +from wlsdeploy.util.model_context import ModelContext + + +class AliasEncryptedModelTestCase(unittest.TestCase): + """ + Test cases for a the -use_encryption feature. + """ + + _logger = PlatformLogger('wlsdeploy.aliases') + _wls_version = '12.2.1.3' + _wlst_password_name = "Password" + _wlst_password_encrypted_name = "PasswordEncrypted" + + _passphrase = 'RE a drop of golden sun' + _password = 'welcome1' + _encrypted_password = '{AES}UC9rZld3blZFUnMraW12cHkydmtmdmpSZmNNMWVHajA6VERPYlJoeWxXU09IaHVrQzpBeWsrd2ZacVkyVT0=' + + def setUp(self): + # construct aliases as if the -use_encryption and -passphrase switches were used + model_context = ModelContext("test", {CommandLineArgUtil.USE_ENCRYPTION_SWITCH: 'true', + CommandLineArgUtil.PASSPHRASE_SWITCH: self._passphrase}) + self.aliases = Aliases(model_context, wlst_mode=WlstModes.OFFLINE, wls_version=self._wls_version) + self.online_aliases = Aliases(model_context, wlst_mode=WlstModes.ONLINE, wls_version=self._wls_version) + + self.location = LocationContext() + self.location.append_location(JDBC_SYSTEM_RESOURCE) + self.location.add_name_token(self.aliases.get_name_token(self.location), "Mine") + self.location.append_location(JDBC_RESOURCE) + self.location.append_location(JDBC_DRIVER_PARAMS) + + def testOfflineWlstNames(self): + # Using offline WLST, the PasswordEncrypted model attribute should translate to the PasswordEncrypted WLST + # attribute, regardless of whether the password is encrypted. The password value should be plain text. + + # using encrypted password + wlst_name, wlst_value = \ + self.aliases.get_wlst_attribute_name_and_value(self.location, PASSWORD_ENCRYPTED, self._encrypted_password) + self.assertEqual(wlst_name, self._wlst_password_encrypted_name) + self.assertEqual(wlst_value, self._password) + + # using unencrypted password + wlst_name, wlst_value = \ + self.aliases.get_wlst_attribute_name_and_value(self.location, PASSWORD_ENCRYPTED, self._password) + self.assertEquals(wlst_name, self._wlst_password_encrypted_name) + self.assertEqual(wlst_value, self._password) + + def testOnlineWlstNames(self): + # Using online WLST, the PasswordEncrypted model attribute should always translate to the Password WLST + # attribute, and the value should translate to the unencrypted value. + + # using encrypted password + wlst_name, wlst_value = \ + self.online_aliases.get_wlst_attribute_name_and_value(self.location, PASSWORD_ENCRYPTED, + self._encrypted_password) + self.assertEqual(wlst_name, self._wlst_password_name) + self.assertEqual(wlst_value, self._password) + + # using unencrypted password + wlst_name, wlst_value = \ + self.online_aliases.get_wlst_attribute_name_and_value(self.location, PASSWORD_ENCRYPTED, self._password) + self.assertEquals(wlst_name, self._wlst_password_name) + self.assertEqual(wlst_value, self._password) diff --git a/core/src/test/python/alias_password_test.py b/core/src/test/python/alias_password_test.py index 8b4de0b75..7fead9412 100644 --- a/core/src/test/python/alias_password_test.py +++ b/core/src/test/python/alias_password_test.py @@ -2,7 +2,6 @@ Copyright (c) 2018, 2019, Oracle Corporation and/or its affiliates. All rights reserved. Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. """ -import jarray import unittest from wlsdeploy.aliases.aliases import Aliases @@ -13,25 +12,24 @@ from wlsdeploy.aliases.model_constants import PASSWORD_ENCRYPTED from wlsdeploy.aliases.wlst_modes import WlstModes from wlsdeploy.logging.platform_logger import PlatformLogger -from wlsdeploy.util.cla_utils import CommandLineArgUtil from wlsdeploy.util.model_context import ModelContext class AliasPasswordTestCase(unittest.TestCase): + """ + Test domain-encrypted passwords in a model. + """ _logger = PlatformLogger('wlsdeploy.aliases') _wls_version = '12.2.1.3' _wlst_password_name = "Password" _wlst_password_encrypted_name = "PasswordEncrypted" - _passphrase = 'RE a drop of golden sun' _password = 'welcome1' _encrypted_password = '{AES}UC9rZld3blZFUnMraW12cHkydmtmdmpSZmNNMWVHajA6VERPYlJoeWxXU09IaHVrQzpBeWsrd2ZacVkyVT0=' - _encrypted_password_bytes = jarray.array(_encrypted_password, 'b') def setUp(self): - model_context = ModelContext("test", {CommandLineArgUtil.USE_ENCRYPTION_SWITCH: 'true', - CommandLineArgUtil.PASSPHRASE_SWITCH: self._passphrase}) + model_context = ModelContext("test", {}) self.aliases = Aliases(model_context, wlst_mode=WlstModes.OFFLINE, wls_version=self._wls_version) self.online_aliases = Aliases(model_context, wlst_mode=WlstModes.ONLINE, wls_version=self._wls_version) @@ -73,7 +71,7 @@ def testOfflineWlstNames(self): wlst_name, wlst_value = \ self.aliases.get_wlst_attribute_name_and_value(self.location, PASSWORD_ENCRYPTED, self._encrypted_password) self.assertEqual(wlst_name, self._wlst_password_encrypted_name) - self.assertEqual(wlst_value, self._password) + self.assertEqual(wlst_value, self._encrypted_password) # using unencrypted password wlst_name, wlst_value = \ @@ -89,7 +87,7 @@ def testOnlineWlstNames(self): self.online_aliases.get_wlst_attribute_name_and_value(self.location, PASSWORD_ENCRYPTED, self._encrypted_password) self.assertEqual(wlst_name, self._wlst_password_encrypted_name) - self.assertEqual(wlst_value, self._password) + self.assertEqual(wlst_value, self._encrypted_password) # using unencrypted password wlst_name, wlst_value = \ diff --git a/site/encrypt.md b/site/encrypt.md index 3152ead73..8ae3706b6 100644 --- a/site/encrypt.md +++ b/site/encrypt.md @@ -4,6 +4,8 @@ Models contain WebLogic Server domain configuration. Certain types of resources and other configurations require passwords; for example, a JDBC data source requires the password for the user establishing the database connection. When creating or configuring a resource that requires a password, that password must be specified either in the model directly or in the variable file. Clear-text passwords are not conducive to storing configurations as source, so the Encrypt Model Tool gives the model author the ability to encrypt the passwords in the model and variable file using passphrase-based, reversible encryption. When using a tool with a model containing encrypted passwords, the encryption passphrase must be provided, so that the tool can decrypt the password in memory to set the necessary WebLogic Server configuration (which supports its own encryption mechanism based on a domain-specific key). While there is no requirement to use the Oracle WebLogic Server Deploy Tooling encryption mechanism, it is highly recommended because storing clear text passwords on disk is never a good idea. +**NOTE: WebLogic Server Deploy Tooling also supports the use of domain-encrypted passwords directly in the model. The Encrypt Model Tool should not be used in tandem with this method.** + Start with the following example model: ```yaml