Ensure proper handling of special password

Currently subcloud prestage would fail if the sysadmin password
that starts with a special character (e.g. @Password123). This
is because the inventory file is generated with the password as-is
which results in yaml parsing failure by ansible.

This commit ensures the sysadmin password that starts with
a special character is handled properly.

Test Plan:
  - Verify successful subcloud add with password that starts with
    or without a special character.
  - Verify successful subcloud reinstall with password that starts
    with or without a special character.
  - Verify successful subcloud reconfigure with password that starts
    with or without a special character.
  - Verify successfull subcloud backup and restore with password
    that starts with or without a special character.
  - Verify successful subcloud prestage with password that starts
    with or without a special character.

Closes-Bug: 2015116
Signed-off-by: Tee Ngo <tee.ngo@windriver.com>
Change-Id: Ieedaee16ed0489c801cd56b1891daf71a26f1e74
This commit is contained in:
Tee Ngo 2023-04-03 13:17:31 -04:00
parent 3d7cb75e22
commit 73c64fc242
6 changed files with 27 additions and 13 deletions

View File

@ -14,7 +14,6 @@
#
from eventlet.green import subprocess
import json
import netaddr
import os
from oslo_log import log as logging
@ -234,7 +233,7 @@ class SubcloudInstall(object):
+ '\n'
)
for k, v in payload.items():
f_out_override_file.write("%s: %s\n" % (k, json.dumps(v)))
f_out_override_file.write("%s: %s\n" % (k, v))
def create_ks_conf_file(self, filename, values):
try:

View File

@ -7,7 +7,6 @@ import json
from collections import namedtuple
import base64
import os
from oslo_config import cfg
from oslo_log import log as logging
@ -135,8 +134,8 @@ class SubcloudBackupController(object):
if not sysadmin_password:
pecan.abort(400, _('subcloud sysadmin_password required'))
try:
payload['sysadmin_password'] = base64.b64decode(
sysadmin_password).decode('utf-8')
payload['sysadmin_password'] = \
utils.decode_and_normalize_passwd(sysadmin_password)
except Exception:
msg = _('Failed to decode subcloud sysadmin_password, '
'verify the password is base64 encoded')

View File

@ -1198,8 +1198,8 @@ class SubcloudsController(object):
if not sysadmin_password:
pecan.abort(400, _('subcloud sysadmin_password required'))
try:
payload['sysadmin_password'] = base64.b64decode(
sysadmin_password).decode('utf-8')
payload['sysadmin_password'] = \
utils.decode_and_normalize_passwd(sysadmin_password)
except Exception:
msg = _('Failed to decode subcloud sysadmin_password, '
'verify the password is base64 encoded')
@ -1401,8 +1401,8 @@ class SubcloudsController(object):
pecan.abort(400, _('subcloud sysadmin_password required'))
try:
payload['sysadmin_password'] = base64.b64decode(
sysadmin_password).decode('utf-8')
payload['sysadmin_password'] = \
utils.decode_and_normalize_passwd(sysadmin_password)
except Exception:
msg = _('Failed to decode subcloud sysadmin_password, '
'verify the password is base64 encoded')
@ -1499,8 +1499,8 @@ class SubcloudsController(object):
pecan.abort(400, _('subcloud sysadmin_password required'))
try:
payload['sysadmin_password'] = base64.b64decode(
sysadmin_password).decode('utf-8')
payload['sysadmin_password'] = \
utils.decode_and_normalize_passwd(sysadmin_password)
except Exception:
msg = _('Failed to decode subcloud sysadmin_password, '
'verify the password is base64 encoded')

View File

@ -408,7 +408,8 @@ def _run_ansible(context, prestage_command, phase,
subcloud.name,
ansible_subcloud_inventory_file,
oam_floating_ip,
ansible_pass=base64.b64decode(sysadmin_password).decode('utf-8'))
ansible_pass=utils.decode_and_normalize_passwd(sysadmin_password))
try:
run_playbook(log_file, prestage_command,
timeout=timeout_seconds, register_cleanup=True)

View File

@ -24,6 +24,7 @@ import pwd
import re
import resource as sys_resource
import six.moves
import string
import subprocess
import tsconfig.tsconfig as tsc
import yaml
@ -942,3 +943,17 @@ def get_value_from_yaml_file(filename, key):
data = yaml.load(data, Loader=yaml.SafeLoader)
value = data.get(key)
return value
def decode_and_normalize_passwd(input_passwd):
pattern = r'^[' + string.punctuation + ']'
passwd = base64.decode_as_text(input_passwd)
# Ensure that sysadmin password which starts with a special
# character will be enclosed in quotes so that the generated
# inventory file will be parsable by Ansible.
if not passwd.startswith('"') and re.search(pattern, passwd):
passwd = '"' + passwd + '"'
elif passwd.startswith('"') and not passwd.endswith('"'):
passwd = "'" + passwd + "'"
return passwd

View File

@ -1107,7 +1107,7 @@ class SubcloudManager(manager.Manager):
'---\n'
)
for k, v in payload['override_values'].items():
f_out.write("%s: %s\n" % (k, json.dumps(v)))
f_out.write("%s: %s\n" % (k, v))
return backup_overrides_file