Call hsm_validator on KRA installs and validate the HSM password

hsm_validator was validating that the token was available but
not that the provided password worked. Add that capability.

Also call it early in the CA and KRA installation cycle so that
it errors out early. This is particularly important for the KRA
because there is no uninstaller.

Bump the minimum PKI release to 11.5.0 as that contains important
fixes for the HSM.

Remove an unused arguments to hsm_version and hsm_validator.

Related: https://pagure.io/freeipa/issue/9273

Signed-off-by: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
This commit is contained in:
Rob Crittenden 2024-04-29 13:59:00 -04:00
parent 879a937ddd
commit 6b6c1879c5
3 changed files with 50 additions and 31 deletions

View File

@ -186,7 +186,9 @@ def install_replica(safe_options, options):
# Run ipa-certupdate to ensure we have the CA cert. This is
# necessary if the admin has just promoted the topology from
# CA-less to CA-ful, and ipa-certupdate has not been run yet.
print("Running ipa-certupdate...", end="", flush=True)
ipa_certupdate.run_with_args(api)
print("done")
# CertUpdate restarts DS causing broken pipe on the original
# connection, so reconnect the backend.

View File

@ -171,19 +171,17 @@ def lookup_hsm_configuration(api):
return (token_name, token_library_path)
def hsm_version(enabled):
def hsm_version():
"""Return True if PKI supports working HSM code
The caller is responsible for raising the exception.
"""
if not enabled:
return None, None
pki_version = pki.util.Version(pki.specification_version())
return pki_version >= pki.util.Version("11.3.0"), pki_version
return pki_version >= pki.util.Version("11.5.0"), pki_version
def hsm_validator(enabled, token_name, token_library):
val, pki_version = hsm_version(enabled)
def hsm_validator(token_name, token_library, token_password):
val, pki_version = hsm_version()
if val is False:
raise ValueError(
"HSM is not supported in PKI version %s" % pki_version
@ -231,6 +229,23 @@ def hsm_validator(enabled, token_name, token_library):
raise ValueError(
"Token named '%s' was not found" % token_name
)
pwdfile = ipautil.write_tmp_file(token_password)
args = [
paths.CERTUTIL,
"-d", '{}:{}'.format(tempnssdb.dbtype, tempnssdb.secdir),
"-K",
"-h", token_name,
"-f", pwdfile.name,
]
result = ipautil.run(args, cwd=tempnssdb.secdir,
capture_error=True, raiseonerr=False)
if result.returncode != 0 and len(result.error_output):
if 'SEC_ERROR_BAD_PASSWORD' in result.error_output:
raise ValueError('Invalid HSM token password')
else:
raise ValueError(
"Validating HSM password failed: %s" % result.error_output
)
def set_subject_base_in_config(subject_base):
@ -320,7 +335,8 @@ def install_check(standalone, replica_config, options):
if options.token_name:
try:
hsm_validator(
True, options.token_name, options.token_library_path)
options.token_name, options.token_library_path,
options.token_password)
except ValueError as e:
raise ScriptError(str(e))
options._subject_base = options.subject_base
@ -352,16 +368,6 @@ def install_check(standalone, replica_config, options):
# IPA version and dependency checking should prevent this but
# better to be safe and avoid a failed install.
if replica_config.setup_ca and token_name:
try:
hsm_validator(
True,
token_name,
options.token_library_path
if options.token_library_path
else token_library_path,
)
except ValueError as e:
raise ScriptError(str(e))
if not options.token_library_path:
options.token_library_path = token_library_path
if (
@ -371,13 +377,27 @@ def install_check(standalone, replica_config, options):
if options.unattended:
raise ScriptError("HSM token password required")
token_password = installutils.read_password(
f"{token_name}", confirm=False
f"HSM token '{token_name}'", confirm=False
)
if token_password is None:
raise ScriptError("HSM token password required")
else:
options.token_password = token_password
if options.token_password_file:
with open(options.token_password_file, "r") as fd:
options.token_password = fd.readline().strip()
try:
hsm_validator(
token_name,
options.token_library_path
if options.token_library_path
else token_library_path,
options.token_password,
)
except ValueError as e:
raise ScriptError(str(e))
if replica_config is not None and not replica_config.setup_ca:
return
@ -492,12 +512,6 @@ def install_step_0(standalone, replica_config, options, custodia):
subject_base = options._subject_base
external_ca_profile = None
if options.token_password_file:
with open(options.token_password_file, "r") as fd:
token_password = fd.readline().strip()
else:
token_password = options.token_password
if replica_config is None:
ca_signing_algorithm = options.ca_signing_algorithm
if options.external_ca:
@ -582,7 +596,7 @@ def install_step_0(standalone, replica_config, options, custodia):
random_serial_numbers=options._random_serial_numbers,
token_name=token_name,
token_library_path=options.token_library_path,
token_password=token_password,
token_password=options.token_password,
)

View File

@ -58,13 +58,16 @@ def install_check(api, replica_config, options):
"KRA can not be installed when 'ca_host' is overriden in "
"IPA configuration file.")
def install(api, replica_config, options, custodia):
if options.token_password_file:
with open(options.token_password_file, "r") as fd:
token_password = fd.readline().strip()
else:
token_password = options.token_password
options.token_password = fd.readline().strip()
if replica_config is not None:
(token_name, token_library) = ca.lookup_hsm_configuration(api)
ca.hsm_validator(token_name, token_library, options.token_password)
def install(api, replica_config, options, custodia):
if replica_config is None:
if not options.setup_kra:
return
@ -114,7 +117,7 @@ def install(api, replica_config, options, custodia):
master_host=master_host,
promote=promote,
pki_config_override=options.pki_config_override,
token_password=token_password
token_password=options.token_password
)
_service.print_msg("Restarting the directory server")