Skip to content

Commit 3bf40be

Browse files
authored
JIRA WDT-470 - Check for long secret names in generated script; use a template for script (#780)
1 parent f04471c commit 3bf40be

File tree

7 files changed

+109
-58
lines changed

7 files changed

+109
-58
lines changed

core/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
<include>oracle/**/*.json</include>
8787
<include>oracle/**/*.ldift</include>
8888
<include>oracle/**/*.properties</include>
89+
<include>oracle/**/*.sh</include>
8990
<include>oracle/**/*.yaml</include>
9091
</includes>
9192
<filtering>false</filtering>

core/src/main/python/discover.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,8 @@ def __check_and_customize_model(model, model_context, aliases, credential_inject
424424

425425
# Generate k8s create secret script
426426
if target_configuration.uses_credential_secrets():
427-
target_configuration_helper.generate_k8s_script(model_context, credential_cache, model.get_model())
427+
target_configuration_helper.generate_k8s_script(model_context, credential_cache, model.get_model(),
428+
ExceptionType.DISCOVER)
428429

429430
# create additional output after filtering, but before variables have been inserted
430431
if model_context.is_targetted_config():

core/src/main/python/prepare_model.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ def walk(self):
302302
if target_config.uses_credential_secrets():
303303
target_configuration_helper.generate_k8s_script(self.model_context,
304304
self.credential_injector.get_variable_cache(),
305-
full_model_dictionary)
305+
full_model_dictionary, ExceptionType.VALIDATE)
306306

307307
# create any additional outputs from full model dictionary
308308
target_configuration_helper.create_additional_output(Model(full_model_dictionary), self.model_context,

core/src/main/python/wlsdeploy/tool/util/targets/file_template_helper.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
__class_name = 'file_template_helper'
2020
__logger = PlatformLogger('wlsdeploy.tool.util')
2121

22-
_substitution_pattern = re.compile("({{{(.*)}}})")
22+
_substitution_pattern = re.compile("({{{([.-}]*)}}})")
2323
_block_start_pattern = re.compile("({{#(.*)}})")
2424
_block_end_pattern = re.compile("({{/(.*)}})")
2525

core/src/main/python/wlsdeploy/util/target_configuration_helper.py

Lines changed: 46 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
# Used by discoverDomain and prepareModel.
66
import re
77
import os
8+
from java.io import File
89

910
from oracle.weblogic.deploy.util import FileUtils
1011

@@ -18,6 +19,7 @@
1819
from wlsdeploy.tool.util import k8s_helper
1920
from wlsdeploy.tool.util import variable_injector_functions
2021
from wlsdeploy.tool.util.targets import additional_output_helper
22+
from wlsdeploy.tool.util.targets import file_template_helper
2123
from wlsdeploy.util import dictionary_utils
2224
from wlsdeploy.util.cla_utils import CommandLineArgUtil
2325

@@ -60,6 +62,9 @@
6062
SECURITY_NM_PATTERN = re.compile('^SecurityConfig.NodeManager')
6163
SECURITY_NM_REPLACEMENT = 'SecurityConfig.NodeManager.'
6264

65+
K8S_SCRIPT_NAME = 'create_k8s_secrets.sh'
66+
K8S_SCRIPT_RESOURCE_PATH = 'oracle/weblogic/deploy/k8s/' + K8S_SCRIPT_NAME
67+
6368

6469
def process_target_arguments(argument_map):
6570
"""
@@ -86,12 +91,13 @@ def process_target_arguments(argument_map):
8691
argument_map[CommandLineArgUtil.VARIABLE_FILE_SWITCH] = path
8792

8893

89-
def generate_k8s_script(model_context, token_dictionary, model_dictionary):
94+
def generate_k8s_script(model_context, token_dictionary, model_dictionary, exception_type):
9095
"""
9196
Generate a shell script for creating k8s secrets.
9297
:param model_context: used to determine output directory
9398
:param token_dictionary: contains every token
9499
:param model_dictionary: used to determine domain UID
100+
:param exception_type: type of exception to throw
95101
"""
96102

97103
# determine the domain name and UID
@@ -101,46 +107,8 @@ def generate_k8s_script(model_context, token_dictionary, model_dictionary):
101107
domain_name = DEFAULT_WLS_DOMAIN_NAME
102108

103109
domain_uid = k8s_helper.get_domain_uid(domain_name)
104-
105-
nl = '\n'
106-
file_location = model_context.get_output_dir()
107-
k8s_file = os.path.join(file_location, "create_k8s_secrets.sh")
108-
k8s_script = open(k8s_file, 'w')
109-
110-
k8s_script.write('#!/bin/bash' + nl)
111-
112-
k8s_script.write(nl)
113-
k8s_script.write('set -eu' + nl)
114-
115-
k8s_script.write(nl)
116-
message = exception_helper.get_message("WLSDPLY-01665", ADMIN_USER_TAG, ADMIN_PASSWORD_TAG)
117-
k8s_script.write("# " + message + nl)
118-
k8s_script.write('NAMESPACE=default' + nl)
119-
k8s_script.write('DOMAIN_UID=' + domain_uid + nl)
120-
121-
k8s_script.write(nl)
122-
k8s_script.write('function create_k8s_secret {' + nl)
123-
k8s_script.write(' kubectl -n $NAMESPACE delete secret ${DOMAIN_UID}-$1 --ignore-not-found' + nl)
124-
k8s_script.write(' kubectl -n $NAMESPACE create secret generic ${DOMAIN_UID}-$1 --from-literal=password=$2' + nl)
125-
k8s_script.write(' kubectl -n $NAMESPACE label secret ${DOMAIN_UID}-$1 weblogic.domainUID=${DOMAIN_UID}' + nl)
126-
k8s_script.write('}' + nl)
127-
128-
k8s_script.write(nl)
129-
k8s_script.write('function create_paired_k8s_secret {' + nl)
130-
k8s_script.write(' kubectl -n $NAMESPACE delete secret ${DOMAIN_UID}-$1 --ignore-not-found' + nl)
131-
k8s_script.write(' kubectl -n $NAMESPACE create secret generic ${DOMAIN_UID}-$1' +
132-
' --from-literal=username=$2 --from-literal=password=$3' + nl)
133-
k8s_script.write(' kubectl -n $NAMESPACE label secret ${DOMAIN_UID}-$1 weblogic.domainUID=${DOMAIN_UID}' + nl)
134-
k8s_script.write('}' + nl)
135-
136-
command_string = "create_paired_k8s_secret %s %s %s" \
137-
% (WEBLOGIC_CREDENTIALS_SECRET_NAME, ADMIN_USER_TAG, ADMIN_PASSWORD_TAG)
138-
139-
k8s_script.write(nl)
140-
message = exception_helper.get_message("WLSDPLY-01664", ADMIN_USER_TAG, ADMIN_PASSWORD_TAG,
141-
WEBLOGIC_CREDENTIALS_SECRET_NAME)
142-
k8s_script.write("# " + message + nl)
143-
k8s_script.write(command_string + nl)
110+
comment = exception_helper.get_message("WLSDPLY-01665")
111+
script_hash = {'domainUid': domain_uid, 'topComment': comment}
144112

145113
# build a map of secret names (jdbc-generic1) to keys (username, password)
146114
secret_map = {}
@@ -150,7 +118,7 @@ def generate_k8s_script(model_context, token_dictionary, model_dictionary):
150118
if len(halves) == 2:
151119
secret_name = halves[0]
152120

153-
# admin credentials are hard-coded in the script, to be first in the list
121+
# admin credentials are inserted later, at the top of the list
154122
if secret_name == WEBLOGIC_CREDENTIALS_SECRET_NAME:
155123
continue
156124

@@ -160,28 +128,35 @@ def generate_k8s_script(model_context, token_dictionary, model_dictionary):
160128
secret_keys = secret_map[secret_name]
161129
secret_keys[secret_key] = value
162130

131+
# update the hash with secrets and paired secrets
132+
secrets = []
133+
paired_secrets = [_build_secret_hash(WEBLOGIC_CREDENTIALS_SECRET_NAME, USER_TAG, PASSWORD_TAG)]
134+
163135
secret_names = secret_map.keys()
164136
secret_names.sort()
165-
166137
for secret_name in secret_names:
167138
secret_keys = secret_map[secret_name]
168139
user_name = dictionary_utils.get_element(secret_keys, SECRET_USERNAME_KEY)
169-
170140
if user_name is None:
171-
message = exception_helper.get_message("WLSDPLY-01663", PASSWORD_TAG, secret_name)
172-
command_string = "create_k8s_secret %s %s " \
173-
% (secret_name, PASSWORD_TAG)
141+
secrets.append(_build_secret_hash(secret_name, None, PASSWORD_TAG))
174142
else:
175-
message = exception_helper.get_message("WLSDPLY-01664", USER_TAG, PASSWORD_TAG, secret_name)
176-
command_string = "create_paired_k8s_secret %s %s %s " \
177-
% (secret_name, user_name, PASSWORD_TAG)
143+
paired_secrets.append(_build_secret_hash(secret_name, user_name, PASSWORD_TAG))
178144

179-
k8s_script.write(nl)
180-
k8s_script.write("# " + message + nl)
181-
k8s_script.write(command_string + nl)
145+
script_hash['secrets'] = secrets
146+
script_hash['pairedSecrets'] = paired_secrets
147+
script_hash['longMessage'] = exception_helper.get_message('WLSDPLY-01667', '${LONG_SECRETS_COUNT}')
182148

183-
k8s_script.close()
184-
FileUtils.chmod(k8s_file, 0750)
149+
long_messages = [
150+
{'text': exception_helper.get_message('WLSDPLY-01668')},
151+
{'text': exception_helper.get_message('WLSDPLY-01669')},
152+
{'text': exception_helper.get_message('WLSDPLY-01670')}
153+
]
154+
script_hash['longMessageDetails'] = long_messages
155+
156+
file_location = model_context.get_output_dir()
157+
k8s_file = File(file_location, K8S_SCRIPT_NAME)
158+
file_template_helper.create_file_from_resource(K8S_SCRIPT_RESOURCE_PATH, script_hash, k8s_file, exception_type)
159+
FileUtils.chmod(k8s_file.getPath(), 0750)
185160

186161

187162
def format_as_secret_token(secret_id, target_config):
@@ -285,3 +260,19 @@ def create_secret_name(variable_name, suffix=None):
285260
# if empty, just return "x".
286261
secret = '-'.join(secret_keys).strip('-')
287262
return secret or 'x'
263+
264+
265+
def _build_secret_hash(secret_name, user, password):
266+
"""
267+
Build a hash for a single secret, for use with the create secrets script template.
268+
:param secret_name: the name of the secret
269+
:param user: the associated user name, or None
270+
:param password: the associated password
271+
:return: a secret hash
272+
"""
273+
if user:
274+
message = exception_helper.get_message("WLSDPLY-01664", USER_TAG, PASSWORD_TAG, secret_name)
275+
return {'secretName': secret_name, 'user': user, 'password': password, 'comment': message}
276+
else:
277+
message = exception_helper.get_message("WLSDPLY-01663", PASSWORD_TAG, secret_name)
278+
return {'secretName': secret_name, 'password': password, 'comment': message}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#!/bin/bash
2+
3+
set -eu
4+
5+
# {{{topComment}}}
6+
NAMESPACE=default
7+
DOMAIN_UID={{{domainUid}}}
8+
9+
LONG_SECRETS=()
10+
11+
function check_secret_name {
12+
if [ ${#1} -gt 63 ]; then
13+
LONG_SECRETS+=($1)
14+
fi
15+
}
16+
17+
function create_k8s_secret {
18+
SECRET_NAME=${DOMAIN_UID}-$1
19+
check_secret_name ${SECRET_NAME}
20+
kubectl -n $NAMESPACE delete secret ${SECRET_NAME} --ignore-not-found
21+
kubectl -n $NAMESPACE create secret generic ${SECRET_NAME} --from-literal=password=$2
22+
kubectl -n $NAMESPACE label secret ${SECRET_NAME} weblogic.domainUID=${DOMAIN_UID}
23+
}
24+
25+
function create_paired_k8s_secret {
26+
SECRET_NAME=${DOMAIN_UID}-$1
27+
check_secret_name ${SECRET_NAME}
28+
kubectl -n $NAMESPACE delete secret ${SECRET_NAME} --ignore-not-found
29+
kubectl -n $NAMESPACE create secret generic ${SECRET_NAME} --from-literal=username=$2 --from-literal=password=$3
30+
kubectl -n $NAMESPACE label secret ${SECRET_NAME} weblogic.domainUID=${DOMAIN_UID}
31+
}
32+
{{#pairedSecrets}}
33+
34+
# {{{comment}}}
35+
create_paired_k8s_secret {{{secretName}}} {{{user}}} {{{password}}}
36+
{{/pairedSecrets}}
37+
{{#secrets}}
38+
39+
# {{{comment}}}
40+
create_k8s_secret {{{secretName}}} {{{password}}}
41+
{{/secrets}}
42+
43+
LONG_SECRETS_COUNT=${#LONG_SECRETS[@]}
44+
if [ ${LONG_SECRETS_COUNT} -gt 0 ]; then
45+
echo ""
46+
echo "{{{longMessage}}}"
47+
for NAME in "${LONG_SECRETS[@]}"; do
48+
echo " ${NAME}"
49+
done
50+
echo ""
51+
{{#longMessageDetails}}
52+
echo "{{{text}}}"
53+
{{/longMessageDetails}}
54+
fi

core/src/main/resources/oracle/weblogic/deploy/messages/wlsdeploy_rb.properties

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,10 @@ WLSDPLY-01663=Update {0} for {1}
303303
WLSDPLY-01664=Update {0} and {1} for {2}
304304
WLSDPLY-01665=Edit these values to change the namespace or domain UID
305305
WLSDPLY-01666=Unable to open file template {0}: {1}
306+
WLSDPLY-01667=WARNING: These {0} secret names are too long to be mounted in a Kubernetes pod:
307+
WLSDPLY-01668=Secret names to be mounted in a Kubernetes pod should be limited to 63 characters.
308+
WLSDPLY-01669=To correct this, shorten the DOMAIN_UID or the secret key(s) in this generated script and re-execute.
309+
WLSDPLY-01670=Update the corresponding secret references in the WDT model(s) to match these values before deployment.
306310

307311
# wlsdeploy/util/enum.py
308312
WLSDPLY-01700=The value {0} is not a valid value of the Enum type {1}

0 commit comments

Comments
 (0)