Skip to content

Issue #484 - Use of model encryption with online update fails #485

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions core/src/main/python/wlsdeploy/aliases/aliases.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]):
Expand All @@ -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(),
Expand Down Expand Up @@ -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
Expand Down
77 changes: 77 additions & 0 deletions core/src/test/python/alias_encrypted_model_test.py
Original file line number Diff line number Diff line change
@@ -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)
14 changes: 6 additions & 8 deletions core/src/test/python/alias_password_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)

Expand Down Expand Up @@ -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 = \
Expand All @@ -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 = \
Expand Down
2 changes: 2 additions & 0 deletions site/encrypt.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down