Skip to content

fix password and user in jdbc standalone xml #1213

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

Closed
wants to merge 15 commits into from
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,7 @@ public static byte[] readInputStreamToByteArray(InputStream input) throws IOExce
}

public static File writeInputStreamToFile(InputStream input, String fileName) throws IOException {
File tmpdir = new File(System.getProperty("java.io.tmpdir"));
File tmpdir = getTmpDir();
File file = new File(tmpdir, fileName);
try (FileOutputStream fos = new FileOutputStream(file)) {
byte[] byteArray = FileUtils.readInputStreamToByteArray(input);
Expand All @@ -627,6 +627,9 @@ public static File writeInputStreamToFile(InputStream input, String fileName) th
return file;
}

public static File getTmpDir() {
return new File(System.getProperty("java.io.tmpdir"));
}

public static void extractZipFileContent(WLSDeployArchive archiveFile, String zipEntry, String extractPath) {
final String METHOD = "extractZipFileContent";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,15 @@ public String addApplication(String appPath) throws WLSDeployArchiveIOException
return newName;
}

public String replaceApplication(String appPath, String tempFile) throws WLSDeployArchiveIOException {
final String METHOD = "replaceApplication";
LOGGER.entering(CLASS, METHOD, appPath);
getZipFile().removeZipEntry(appPath);
String newName = addApplication(tempFile);
LOGGER.exiting(CLASS, METHOD, newName);
return newName;
}

public String addApplicationFolder(String appName, String appPath)
throws WLSDeployArchiveIOException {
final String METHOD = "addApplicationFolder";
Expand Down
18 changes: 12 additions & 6 deletions core/src/main/python/discover.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,21 +219,21 @@ def __process_domain_home(arg_map, wlst_mode):
arg_map[CommandLineArgUtil.DOMAIN_HOME_SWITCH] = full_path


def __discover(model_context, aliases, credential_injector, helper):
def __discover(model_context, aliases, credential_injector, helper, extra_tokens):
"""
Populate the model from the domain.
:param model_context: the model context
:param aliases: aliases instance for discover
:param credential_injector: credential injector instance
:param helper: wlst_helper instance
:param extra_tokens: dictionary to store non-credential tokens during credential search
:return: the fully-populated model
:raises DiscoverException: if an error occurred while discover the domain
"""
_method_name = '__discover'
model = Model()
base_location = LocationContext()
__connect_to_domain(model_context, helper)

try:
_add_domain_name(base_location, aliases, helper)
DomainInfoDiscoverer(model_context, model.get_model_domain_info(), base_location, wlst_mode=__wlst_mode,
Expand All @@ -243,7 +243,8 @@ def __discover(model_context, aliases, credential_injector, helper):
ResourcesDiscoverer(model_context, model.get_model_resources(), base_location, wlst_mode=__wlst_mode,
aliases=aliases, credential_injector=credential_injector).discover()
DeploymentsDiscoverer(model_context, model.get_model_app_deployments(), base_location, wlst_mode=__wlst_mode,
aliases=aliases, credential_injector=credential_injector).discover()
aliases=aliases, credential_injector=credential_injector,
extra_tokens=extra_tokens).discover()
__discover_multi_tenant(model, model_context, base_location, aliases, credential_injector)
except AliasException, ae:
wls_version = WebLogicHelper(__logger).get_actual_weblogic_version()
Expand Down Expand Up @@ -448,14 +449,15 @@ def __persist_model(model, model_context):
__logger.exiting(class_name=_class_name, method_name=_method_name)


def __check_and_customize_model(model, model_context, aliases, credential_injector):
def __check_and_customize_model(model, model_context, aliases, credential_injector, extra_tokens):
"""
Customize the model dictionary before persisting. Validate the model after customization for informational
purposes. Any validation errors will not stop the discovered model to be persisted.
:param model: completely discovered model, before any tokenization
:param model_context: configuration from command-line
:param aliases: used for validation if model changes are made
:param credential_injector: injector created to collect and tokenize credentials, possibly None
:param extra_tokens: dictionary to handle non-credential tokenized arguments
"""
_method_name = '__check_and_customize_model'
__logger.entering(class_name=_class_name, method_name=_method_name)
Expand Down Expand Up @@ -492,9 +494,12 @@ def __check_and_customize_model(model, model_context, aliases, credential_inject

# Apply the injectors specified in model_variable_injector.json, or in the target configuration.
# Include the variable mappings that were collected in credential_cache.

variable_injector = VariableInjector(_program_name, model.get_model(), model_context,
WebLogicHelper(__logger).get_actual_weblogic_version(), credential_cache)

variable_injector.add_to_cache(dictionary=extra_tokens)

inserted, variable_model, variable_file_name = variable_injector.inject_variables_keyword_file()

if inserted:
Expand Down Expand Up @@ -589,10 +594,11 @@ def main(model_context):
else:
__logger.info('WLSDPLY-06024', class_name=_class_name, method_name=_method_name)

extra_tokens = {}
try:
model = __discover(model_context, aliases, credential_injector, helper)
model = __discover(model_context, aliases, credential_injector, helper, extra_tokens)

model = __check_and_customize_model(model, model_context, aliases, credential_injector)
model = __check_and_customize_model(model, model_context, aliases, credential_injector, extra_tokens)

__remote_report(model_context)
except DiscoverException, ex:
Expand Down
1 change: 1 addition & 0 deletions core/src/main/python/wlsdeploy/aliases/model_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@
MESSAGE_LOGGING_PARAMS = 'MessageLoggingParams'
MESSAGING_BRIDGE = 'MessagingBridge'
METHOD = 'Method'
MODULE_TYPE = 'ModuleType'
MULTICAST = 'Multicast'
MULTICAST_ADDRESS = 'MulticastAddress'
MULTICAST_PORT = 'MulticastPort'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,30 @@
"""
import os

from java.io import BufferedReader
from java.io import BufferedWriter
from java.io import File
from java.io import FileReader
from java.io import FileWriter
from java.lang import IllegalArgumentException
from java.lang import StringBuilder
from java.util.regex import Pattern

from oracle.weblogic.deploy.util import PyOrderedDict as OrderedDict
from oracle.weblogic.deploy.util import FileUtils
from oracle.weblogic.deploy.util import StringUtils
from oracle.weblogic.deploy.util import WLSDeployArchiveIOException
from oracle.weblogic.deploy.util import WLSDeployArchive

from wlsdeploy.aliases.alias_constants import PASSWORD_TOKEN
from wlsdeploy.aliases import model_constants
from wlsdeploy.aliases.location_context import LocationContext
from wlsdeploy.aliases.wlst_modes import WlstModes
from wlsdeploy.exception import exception_helper
from wlsdeploy.logging.platform_logger import PlatformLogger
from wlsdeploy.tool.discover import discoverer
from wlsdeploy.tool.discover.discoverer import Discoverer
from wlsdeploy.util import dictionary_utils
from wlsdeploy.util import path_utils

_class_name = 'DeploymentsDiscoverer'
Expand All @@ -32,9 +41,10 @@ class DeploymentsDiscoverer(Discoverer):
"""

def __init__(self, model_context, deployments_dictionary, base_location,
wlst_mode=WlstModes.OFFLINE, aliases=None, credential_injector=None):
wlst_mode=WlstModes.OFFLINE, aliases=None, credential_injector=None, extra_tokens=None):
Discoverer.__init__(self, model_context, base_location, wlst_mode, aliases, credential_injector)
self._dictionary = deployments_dictionary
self._extra_tokens = extra_tokens

def discover(self):
"""
Expand Down Expand Up @@ -241,6 +251,7 @@ def _add_application_to_archive(self, application_name, application_dict):
"""
_method_name = 'add_application_to_archive'
_logger.entering(application_name, class_name=_class_name, method_name=_method_name)

archive_file = self._model_context.get_archive_file()
if model_constants.SOURCE_PATH in application_dict:
if model_constants.PLAN_DIR in application_dict and \
Expand All @@ -265,6 +276,11 @@ def _add_application_to_archive(self, application_name, application_dict):
method_name=_method_name)
try:
new_source_name = archive_file.addApplication(file_name_path)
module_type = dictionary_utils.get_dictionary_element(application_dict,
model_constants.MODULE_TYPE)
if module_type == 'jdbc':
self._jdbc_password_fix(new_source_name)

except IllegalArgumentException, iae:
self._disconnect_target(application_name, application_dict, iae.getLocalizedMessage())
except WLSDeployArchiveIOException, wioe:
Expand Down Expand Up @@ -325,6 +341,78 @@ def _create_app_folder(self, application_name, application_dict):

_logger.exiting(class_name=_class_name, method_name=_method_name)

def _jdbc_password_fix(self, source_name):
"""
This will look for password and userid in the jdbc standalone xml and
replace with either fix password token or a token in the xml and variable file.
It extracts the jdbc xml from the archive and then replaces it with the updated file.
:param source_name: Name of the path and file for the standalone xml file
"""
_method_name = '_jdbc_password_fix'
_logger.entering(source_name, class_name=_class_name, method_name=_method_name)
archive_file = self._model_context.get_archive_file()
tmp_dir = FileUtils.getTmpDir();
temp_file = FileUtils.createTempDirectory(tmp_dir, 'jdbc-xml')
jdbc_file = archive_file.extractFile(source_name, temp_file)
jdbc_out = FileUtils.createTempDirectory(tmp_dir, 'jdbc-out')
jdbc_out = archive_file.extractFile(source_name, jdbc_out)
bis = BufferedReader(FileReader(jdbc_file))
bos = BufferedWriter(FileWriter(jdbc_out))
cache = StringBuilder()
while bis.ready():
cache.append(bis.readLine()).append("\n")
bis.close()
pattern = Pattern.compile("<name>(\s?)user(\s?)</name>")
matcher = pattern.matcher(cache.toString())
end = -1
if matcher.find():
end = matcher.end()
result = cache.toString()
if end >= 0:
pattern = Pattern.compile("<value>(.+?)</value>")
matcher = pattern.matcher(result[end:])
matcher.find()
username = matcher.group()
username = username[len('<value>'):len(username) - len('</value>')]
pattern = Pattern.compile(matcher.group())
matcher = pattern.matcher(cache.toString())
result = matcher.replaceFirst(self._get_pass_replacement(jdbc_file, '-user:username',
'value', username=username))

pattern = Pattern.compile('<password-encrypted>(.+?)</password-encrypted>')
matcher = pattern.matcher(result)
result = matcher.replaceFirst(self._get_pass_replacement(jdbc_file, '-user:password', 'password-encrypted'))

pattern = Pattern.compile('<url>(\s*)(.+?)(\s*)</url>')
matcher = pattern.matcher(result)
matcher.find()
result = matcher.replaceFirst(self._get_pass_replacement(jdbc_file, '-url', 'url',
properties=matcher.group(2)))

pattern = Pattern.compile('<ons-wallet-password-encrypted>(.+?)</ons-wallet-password-encrypted>')
matcher = pattern.matcher(result)
result = matcher.replaceFirst(self._get_pass_replacement(jdbc_file, '-ons-pass-encrypt:password',
'ons-wallet-password-encrypted'))
bos.write(result)
bos.close()
archive_file.replaceApplication(source_name, jdbc_out)
_logger.exiting(class_name=_class_name, method_name=_method_name)

def _get_pass_replacement(self, jdbc_file, name, type, properties=None, username=''):
if self._credential_injector is not None:
head, tail = os.path.split(jdbc_file)
token = tail[:len(tail) - len('.xml')]
token = token + name
if properties is not None:
self._extra_tokens[token] = properties
result = self._credential_injector.get_property_token(None, token)
else:
result = self._credential_injector.injection_out_of_model(token, username)
else:
result = PASSWORD_TOKEN
result = '<' + type + '>' + result + '</' + type + '>'
return result

def _test_app_folder(self, source_path, plan_dir):
app_folder = False
app_dir = File(source_path).getParent()
Expand Down
23 changes: 22 additions & 1 deletion core/src/main/python/wlsdeploy/tool/util/credential_injector.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ def __init__(self, program_name, model, model_context, version=None, variable_di
VariableInjector.__init__(self, program_name, model, model_context, version=version,
variable_dictionary=variable_dictionary)
self._model_context = model_context
self._no_filter_keys_cache = []
self._no_filter_keys_cache.append(self.NO_FILTER_KEYS)

def check_and_tokenize(self, model_dict, attribute, location):
"""
Expand Down Expand Up @@ -138,6 +140,22 @@ def check_and_tokenize(self, model_dict, attribute, location):
assigns.append('%s=%s' % (key, properties[key]))
model_dict[attribute] = split_value.join(assigns)

def injection_out_of_model(self, token, username=''):
"""
This is for tokenizing variables that are not in the model but need to be in the variable file
:param token: name for cache to create a token for
:param username: usernames appear as part of property value
:return: tokenized name
"""
_method_name = 'injection_out_of_model'
_logger.entering(token, class_name=_class_name, method_name=_method_name)
result = self.get_variable_token(None, token)
self.add_to_cache(token_name=token, token_value=username)

self._no_filter_keys_cache.append(token)
_logger.exiting(class_name=_class_name, method_name=_method_name, result=result)
return result

def get_variable_name(self, attribute_location, attribute, suffix=None):
"""
Override method to possibly create secret token names instead of property names.
Expand Down Expand Up @@ -191,6 +209,9 @@ def get_variable_token(self, attribute, variable_name):
else:
return VariableInjector.get_variable_token(self, attribute, variable_name)

def get_property_token(self, attribute, variable_name):
return VariableInjector.get_variable_token(self, attribute, variable_name)

def _check_tokenized(self, attribute_value):
"""
Override to return true if target uses credentials and the value is formatted like @@SECRET:xyz:abc@@.
Expand Down Expand Up @@ -222,7 +243,7 @@ def filter_unused_credentials(self, model_dictionary):

cache_keys = self.get_variable_cache().keys()
for key in cache_keys:
if key in self.NO_FILTER_KEYS:
if key in self._no_filter_keys_cache:
continue

if credentials_method == SECRETS_METHOD:
Expand Down
10 changes: 10 additions & 0 deletions core/src/main/python/wlsdeploy/util/target_configuration_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@
WEBLOGIC_CREDENTIALS_SECRET_NAME = 'weblogic-credentials'
WEBLOGIC_CREDENTIALS_SECRET_SUFFIX = '-' + WEBLOGIC_CREDENTIALS_SECRET_NAME

JDBC_CREDENTIALS_SECRET_USER_NAME = 'standalone-jdbc.xml.user'
JDBC_CREDENTIALS_SECRET_USER_SUFFIX = '-' + JDBC_CREDENTIALS_SECRET_USER_NAME

JDBC_CREDENTIALS_SECRET_PASS_NAME = 'standalone-jdbc.xml.pass.encrypt'
JDBC_CREDENTIALS_SECRET_PASS_SUFFIX = '-' + JDBC_CREDENTIALS_SECRET_PASS_NAME

JDBC_CREDENTIALS_SECRET_ONS_PASS_NAME = 'standalone-jdbc.xml.ons.pass.encrypt'
JDBC_CREDENTIALS_SECRET_ONS_PASS_SUFFIX = '-' + JDBC_CREDENTIALS_SECRET_ONS_PASS_NAME

RUNTIME_ENCRYPTION_SECRET_NAME = 'runtime-encryption-secret'
RUNTIME_ENCRYPTION_SECRET_SUFFIX = '-' + RUNTIME_ENCRYPTION_SECRET_NAME

Expand Down Expand Up @@ -133,6 +142,7 @@ def _prepare_k8s_secrets(model_context, token_dictionary, model_dictionary):
for secret_name in secret_names:
secret_keys = secret_map[secret_name]
user_name = dictionary_utils.get_element(secret_keys, SECRET_USERNAME_KEY)

if user_name is None:
secrets.append(_build_secret_hash(secret_name, None, PASSWORD_TAG))
else:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function create_paired_k8s_secret {
{{#comments}}
# {{{comment}}}
{{/comments}}
create_paired_k8s_secret {{{secretName}}} {{{user}}} {{{password}}}
create_paired_k8s_secret {{{secretName}}} "{{{user}}}" {{{password}}}
{{/pairedSecrets}}
{{#secrets}}

Expand Down