Generate database URI for ed25519 passwords

In addition to generating base64-encoded passwords when
EnableMysqlAuthEd25519 is set [1], we need to encode the
password part of the database URI in a way that can be
decoded by oslo.db. This is then used by tripleo heat
templates [2] to generate appropriate hiera keys.

Let tripleo-common generate a pair of keys
<service>Password and <service>PasswordDatabase to
generate base64-encoded passwords, and RFC-1738-encoded
passwords for URI. The former is still used as before
to create users in the database, and the latter is used
by oslo.db for connection to the database.

Tested by deploying a standalone, undercloud and HA overcloud
with and without EnableMysqlAuthEd25519. Password rotation
with tripleo_passwords_rotate is also supported.

[1] I00d3d2a43d08d3d317a25c7ecb54d197e36a8f93
[2] I2e2cd7256700b728453e2b5857967893996cf552

Related-Bug: #1960271

Change-Id: Ic7ff36a5f3f4eceeb6c8a338093e956b7db00533
This commit is contained in:
Damien Ciabrini 2022-03-14 12:15:05 +01:00
parent af78a763f8
commit 0cf9c12702
1 changed files with 19 additions and 2 deletions

View File

@ -24,6 +24,7 @@ import os
import struct
import time
import uuid
import urllib.parse
import passlib.pwd
import yaml
@ -60,7 +61,11 @@ def generate_passwords(stack_env=None,
if no_rotate and (
stack_env and name in stack_env.get(
'parameter_defaults', {})):
passwords[name] = stack_env['parameter_defaults'][name]
current_password = stack_env['parameter_defaults'][name]
passwords[name] = current_password
if name in constants.DB_PASSWORD_PARAMETER_NAMES and db_ed25519:
db_uri = db_uri_from_ed25519_password(current_password)
passwords[name + 'Database'] = db_uri
elif (name == 'KeystonePassword' and stack_env and
'AdminToken' in stack_env.get('parameter_defaults', {})):
# NOTE(tkajinam): AdminToken was renamed to KeystonePassword
@ -101,7 +106,10 @@ def generate_passwords(stack_env=None,
skip_bytes = [0, ord(' '), ord('\t'), ord('\n')]
passwords[name] = create_ed25519_password(skip_bytes)
else:
passwords[name] = create_ed25519_password()
ed25519_password = create_ed25519_password()
db_uri = db_uri_from_ed25519_password(ed25519_password)
passwords[name] = ed25519_password
passwords[name + 'Database'] = db_uri
elif name.startswith("MysqlRootPassword"):
passwords[name] = passlib.pwd.genword(length=10)
elif name.startswith("RabbitCookie"):
@ -211,3 +219,12 @@ def create_ed25519_password(skip_bytes=[]):
)
generate_new_key = any(x in skip_bytes for x in private_bytes)
return base64.b64encode(private_bytes).decode('utf-8')
def db_uri_from_ed25519_password(b64_password):
decoded = base64.b64decode(b64_password).decode("latin-1")
# A database URI is unquoted by oslo.db as per RFC 1738,
# but we also need to quote '/' because that is a valid
# character in ed25519 passwords
db_uri = urllib.parse.quote(decoded.encode("utf-8")).replace('/', '%2F')
return db_uri