Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -344,8 +344,8 @@ private static File findLoggingDirectory(String programName) {

if (!found && tmpDir.canWrite()) {
try {
File parentDir = tmpDir.getCanonicalFile().getParentFile();
logDir = FileUtils.createTempDirectory(parentDir, "jcslcm-logs");
File parentDir = tmpDir.getCanonicalFile();
logDir = FileUtils.createTempDirectory(parentDir, "wdt-logs");
found = true;
} catch (IOException ioe) {
String message = MessageFormat.format("{0} failed to create temporary logs directory in {1}: {2}",
Expand Down
52 changes: 51 additions & 1 deletion core/src/main/java/oracle/weblogic/deploy/util/FileUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,17 @@
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import javax.xml.bind.DatatypeConverter;

import oracle.weblogic.deploy.exception.ExceptionHelper;
Expand Down Expand Up @@ -783,4 +785,52 @@ public boolean accept(File dir, String name) {
}


/**
* Convert an octal number into Posix File Permisions.
* @param octals 3 octal digits representing posix file permissions rwxrwxrwx
* @return a set of Posix file permissions
*/
@SuppressWarnings("OctalInteger")
static Set<PosixFilePermission> getPermissions(int octals) {
Set<PosixFilePermission> result = new HashSet<>();
if ( (0400 & octals) > 0) {
result.add(PosixFilePermission.OWNER_READ);
}
if ( (0200 & octals) > 0) {
result.add(PosixFilePermission.OWNER_WRITE);
}
if ( (0100 & octals) > 0) {
result.add(PosixFilePermission.OWNER_EXECUTE);
}
if ( (0040 & octals) > 0) {
result.add(PosixFilePermission.GROUP_READ);
}
if ( (0020 & octals) > 0) {
result.add(PosixFilePermission.GROUP_WRITE);
}
if ( (0010 & octals) > 0) {
result.add(PosixFilePermission.GROUP_EXECUTE);
}
if ( (0004 & octals) > 0) {
result.add(PosixFilePermission.OTHERS_READ);
}
if ( (0002 & octals) > 0) {
result.add(PosixFilePermission.OTHERS_WRITE);
}
if ( (0001 & octals) > 0) {
result.add(PosixFilePermission.OTHERS_EXECUTE);
}
return result;
}

/**
* Set OS file permissions given an Octal permission set.
* Needed due to Jython 2.2 did not offer a os.chmod function.
* @param path file name to be changed
* @param octals octal number set like OS chmod permissions
* @throws IOException if permissions update fails
*/
public static void chmod(String path, int octals) throws IOException {
Files.setPosixFilePermissions(Paths.get(path), getPermissions(octals));
}
}
3 changes: 2 additions & 1 deletion core/src/main/python/prepare_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,8 @@ def __substitute_password_with_token(self, model_path, attribute_name, validatio

# for normal secrets, assign the secret name to the attribute
if credentials_method == SECRETS_METHOD:
model_value = target_configuration_helper.format_as_secret_token(cache_key)
model_value = target_configuration_helper.format_as_secret_token(cache_key,
self.model_context.get_target_configuration())
self.cache[cache_key] = ''

# for config override secrets, assign a placeholder password to the attribute.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,8 @@ def _process_attribute(self, model, attribute, location, injector_values):
# for credentials_method: secrets, assign a secret token to the attribute
if credentials_method == SECRETS_METHOD \
and variable_value == alias_constants.PASSWORD_TOKEN:
model[attribute] = target_configuration_helper.format_as_secret_token(variable_name)
model[attribute] = target_configuration_helper.format_as_secret_token(variable_name,
self.__model_context.get_target_configuration())

# for config_override_secrets, assign a placeholder value to the attribute
elif credentials_method == CONFIG_OVERRIDES_SECRETS_METHOD \
Expand Down
10 changes: 10 additions & 0 deletions core/src/main/python/wlsdeploy/util/target_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
# types for credential method
CREDENTIALS_METHOD = "credentials_method"

# Overrides the Kubernetes secret name for the WebLogic admin user credential
WLS_CREDENTIALS_NAME = "wls_credentials_name"

# put secret tokens in the model, and build a script to create the secrets.
SECRETS_METHOD = 'secrets'

Expand Down Expand Up @@ -43,6 +46,13 @@ def get_credentials_method(self):
"""
return dictionary_utils.get_element(self.config_dictionary, CREDENTIALS_METHOD)

def get_wls_credentials_name(self):
"""
Returns the method for handling credentials in the model.
:return: the method for handling credentials
"""
return dictionary_utils.get_element(self.config_dictionary, WLS_CREDENTIALS_NAME)

def get_additional_output_types(self):
"""
Return the additional output types for this target environment.
Expand Down
30 changes: 13 additions & 17 deletions core/src/main/python/wlsdeploy/util/target_configuration_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
# Shared methods for using target environments (-target abc).
# Used by discoverDomain and prepareModel.
import re

import os

from oracle.weblogic.deploy.util import FileUtils

from wlsdeploy.aliases.model_constants import DEFAULT_WLS_DOMAIN_NAME
from wlsdeploy.aliases.model_constants import JDBC_DRIVER_PARAMS
from wlsdeploy.aliases.model_constants import JDBC_RESOURCE
Expand Down Expand Up @@ -152,36 +153,31 @@ def generate_k8s_script(model_context, token_dictionary, model_dictionary):
k8s_script.write(command_string + nl)

k8s_script.close()
FileUtils.chmod(k8s_file, 0750)


def format_as_secret_token(variable_name):
def format_as_secret_token(variable_name, target_config):
"""
Format the variable as a secret name token for use in a model.
:param variable_name: variable name in dot separated format
:return: formatted name
"""
normal_secret_format = '@@SECRET:@@ENV:DOMAIN_UID@@-%s:%s@@'
name_lower_tokens = variable_name.lower().split('.')
if len(name_lower_tokens) == 1:
admin_lower_token = name_lower_tokens[0]
if admin_lower_token in ['adminusername', 'adminpassword']:
# these should just be 'username' and 'password', to match secrets script
# substring removes "admin" and keeps just 'username' or 'password', to match secrets script
admin_token = admin_lower_token[5:]
return get_secret_model_token(WEBLOGIC_CREDENTIALS_SECRET_NAME, admin_token)
secret_name = target_config.get_wls_credentials_name()
if secret_name == None:
return normal_secret_format % (WEBLOGIC_CREDENTIALS_SECRET_NAME, admin_token)
else:
# if the target configuration declares a special name for the WebLogic credential secret
return '@@SECRET:%s:%s@@' % (secret_name, admin_token)

# for paired and single secrets, password key is always named "password"
secret_name = "password"

return get_secret_model_token('-'.join(name_lower_tokens[:-1]), secret_name)


def get_secret_model_token(name, key):
"""
Returns the substitution string to be put in the model for a secret value.
:param name: the name of the secret
:param key: the key of the secret
:return: the substitution string
"""
return '@@SECRET:@@ENV:DOMAIN_UID@@-%s:%s@@' % (name, key)
return normal_secret_format % ('-'.join(name_lower_tokens[:-1]), secret_name)


def get_secret_name_for_location(location, domain_uid, aliases):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ spec:
placement:
- name: local
namespaces:
- name: default
- name: "{{{domainUid}}}-ns"
components:
- name: {{{domainName}}}
ingressBindings:
- name: "{{{domainPrefix}}}-ingress"
dnsName: "todo.vz.oracledx.com"
dnsName: "*"
{{#hasDatabases}}
databaseBindings:
{{/hasDatabases}}
Expand Down
3 changes: 2 additions & 1 deletion core/src/main/targetconfigs/vz/target.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
},
"variable_injectors" : {"PORT": {},"HOST": {},"URL": {}},
"validation_method" : "lax",
"credentials_method" : "config_override_secrets",
"credentials_method" : "secrets",
"wls_credentials_name" : "__weblogic-credentials__",
"additional_output" : "vz"
}
11 changes: 11 additions & 0 deletions core/src/main/targetconfigs/wko/target.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"model_filters" : {
"discover": [
{ "name": "wko_prep", "path": "@@TARGET_CONFIG_DIR@@/wko_operator_filter.py" }
]
},
"variable_injectors" : {"PORT": {},"HOST": {},"URL": {}},
"validation_method" : "lax",
"credentials_method" : "secrets",
"wls_credentials_name" : "__weblogic-credentials__"
}
67 changes: 67 additions & 0 deletions core/src/main/targetconfigs/wko/wko_operator_filter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Copyright (c) 2020, Oracle Corporation and/or its affiliates.
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
#
# ------------
# Description:
# ------------
# This is a WDT filter for primordial domain creation. It filters out all resources and
# apps deployments, leaving only the domainInfo and admin server in topology.
#
def filter_model(model):
__cleanup_topology(model)
__cleanup_resources(model)

def __cleanup_resources(model):
if model and 'resources' in model:
resources = model['resources']

for delthis in [ 'PartitionWorkManager', 'Partition', 'ResourceGroup', 'ResourceGroupTemplate', 'VirtualHost',
'ResourceManager', 'ResourceManagement' ]:
if resources.has_key(delthis):
del resources[delthis]

def __cleanup_topology(model):
if model and 'topology' in model:
topology = model['topology']
for delthis in [ 'NMProperties', 'VirtualTarget', 'Machine']:
if topology.has_key(delthis):
del topology[delthis]

if topology.has_key('Cluster'):
clusters = topology['Cluster']
for cluster in clusters:
for delthis in ['MigrationBasis', 'CandidateMachinesForMigratableServer', 'DatabaseLessLeasingBasis',
'ClusterMessagingMode']:
if clusters[cluster].has_key(delthis):
del clusters[cluster][delthis]

if topology.has_key('Server'):
servers = topology['Server']
for server in servers:
for delthis in ['Machine', 'CandidateMachine', 'AutoMigrationEnabled']:
if servers[server].has_key(delthis):
del servers[server][delthis]

if topology.has_key('SecurityConfiguration'):
for delthis in ['NodeManagerPasswordEncrypted', 'NodeManagerUsername' ]:
if topology['SecurityConfiguration'].has_key(delthis):
del topology['SecurityConfiguration'][delthis]
if len(topology['SecurityConfiguration'].keys()) == 0:
del topology['SecurityConfiguration']

if topology.has_key('ServerTemplate'):
server_templates = topology['ServerTemplate']
for server_template in server_templates:
server_templates[server_template]['AutoMigrationEnabled'] = False
else:
topology['ServerTemplate'] = {}
server_templates = topology['ServerTemplate']
if topology.has_key('Cluster'):
clusters = topology['Cluster']
for cluster in clusters:
server_templates[cluster] = {}
server_template = server_templates[cluster]
server_template['Cluster'] = cluster
server_template['AutoMigrationEnabled'] = False


15 changes: 15 additions & 0 deletions core/src/test/java/oracle/weblogic/deploy/util/FileUtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.attribute.PosixFilePermission;
import java.text.MessageFormat;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

Expand Down Expand Up @@ -174,4 +177,16 @@ private void assertMatch(String name, String got, String expected) {
Assert.assertTrue(MessageFormat.format(FILE_ERR_FORMAT, name, got, expected),
got.equals(expected));
}

@Test
public void posixPermissions() throws IOException {
Set<PosixFilePermission> perms = FileUtils.getPermissions(0700);
Assert.assertTrue(perms.contains(PosixFilePermission.OWNER_READ));
Assert.assertTrue(perms.contains(PosixFilePermission.OWNER_WRITE));
Assert.assertTrue(perms.contains(PosixFilePermission.OWNER_EXECUTE));

Set<PosixFilePermission> perms2 = FileUtils.getPermissions(0006);
Assert.assertTrue(perms2.contains(PosixFilePermission.OTHERS_READ));
Assert.assertTrue(perms2.contains(PosixFilePermission.OTHERS_WRITE));
}
}
56 changes: 56 additions & 0 deletions core/src/test/python/target_configuration_helper_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"""
Copyright (c) 2020, Oracle Corporation and/or its affiliates. All rights reserved.
The Universal Permissive License (UPL), Version 1.0
"""

import unittest

import wlsdeploy.util.target_configuration_helper as HELPER
import wlsdeploy.util.target_configuration as CONFIG

from wlsdeploy.util.target_configuration import TargetConfiguration


class TargetConfigurationTests(unittest.TestCase):
"""
Test the target configuration and helper methods.
"""

target_with_cred_name = None
target_without_cred_name = None

def setUp(self):
config = dict()
config[CONFIG.CREDENTIALS_METHOD] = 'secrets'
config[CONFIG.WLS_CREDENTIALS_NAME] = '__weblogic-credentials__'
self.target_with_cred_name = TargetConfiguration(config)

config2 = dict()
config2[CONFIG.CREDENTIALS_METHOD] = 'secrets'
self.target_without_cred_name = TargetConfiguration(config2)


def testSecretWithWlsCredName(self):
self.assertEqual('@@SECRET:__weblogic-credentials__:username@@',
HELPER.format_as_secret_token('AdminUsername', self.target_with_cred_name))

self.assertEqual('@@SECRET:__weblogic-credentials__:password@@',
HELPER.format_as_secret_token('AdminPassword', self.target_with_cred_name))

self.assertEqual('@@SECRET:@@ENV:DOMAIN_UID@@-something:password@@',
HELPER.format_as_secret_token('something.else', self.target_with_cred_name))


def testSecretWithoutWlsCredName(self):
self.assertEqual('@@SECRET:@@ENV:DOMAIN_UID@@-weblogic-credentials:username@@',
HELPER.format_as_secret_token('AdminUsername', self.target_without_cred_name))

self.assertEqual('@@SECRET:@@ENV:DOMAIN_UID@@-weblogic-credentials:password@@',
HELPER.format_as_secret_token('AdminPassword', self.target_without_cred_name))

self.assertEqual('@@SECRET:@@ENV:DOMAIN_UID@@-something:password@@',
HELPER.format_as_secret_token('something.else', self.target_with_cred_name))

if __name__ == '__main__':
unittest.main()
Loading