Re-organize HSM validation to be more consistent/less duplication

hsm_validator() was more or less bolted in place late in the
development cycle in in order to catch some of the more common
problems: bad token name, bad password, etc.

There was a fair bit of duplication and had the side-effect of not
reading in the token password from the --token-password-file option
in some cases.

This patch also re-adds a lost feature where an exception is raised if
both the --token-password and --token-password-file options are passed
in.

This also needs to be enforced on initial server, replica and when
called by ipa-kra-install. Given that each has a unique subject of
options some duplication remains.

Fixes: https://pagure.io/freeipa/issue/9603

Signed-off-by: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
This commit is contained in:
Rob Crittenden
2024-07-05 15:00:59 -04:00
parent 1b278de4ab
commit 7ab1bcb2d3
3 changed files with 92 additions and 36 deletions

View File

@@ -193,6 +193,8 @@ def hsm_validator(token_name, token_library, token_password):
if not token_name:
logger.debug("No token name, assuming not an HSM install")
return
if not token_password:
raise ValueError("No token password provided")
val, pki_version = hsm_version()
if val is False:
raise ValueError(
@@ -361,17 +363,16 @@ def install_check(standalone, replica_config, options):
host_name = options.host_name
if replica_config is None:
if options.token_name:
try:
hsm_validator(
options.token_name, options.token_library_path,
options.token_password)
except ValueError as e:
raise ScriptError(str(e))
options._subject_base = options.subject_base
options._ca_subject = options.ca_subject
options._random_serial_numbers = options.random_serial_numbers
token_name = options.token_name
token_library_path = options.token_library_path
if "setup_ca" in options.__dict__:
setup_ca = options.setup_ca
else:
# We got here through ipa-ca-install
setup_ca = True
else:
# during replica install, this gets invoked before local DS is
# available, so use the remote api.
@@ -399,33 +400,36 @@ def install_check(standalone, replica_config, options):
if replica_config.setup_ca and token_name:
if not options.token_library_path:
options.token_library_path = token_library_path
if (
not options.token_password_file
and not options.token_password
):
if options.unattended:
raise ScriptError("HSM token password required")
token_password = installutils.read_password(
f"HSM token '{token_name}'", confirm=False
)
if token_password is None:
raise ScriptError("HSM token password required")
else:
options.token_password = token_password
setup_ca = replica_config.setup_ca
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 setup_ca and token_name:
if (options.token_password_file and options.token_password):
raise ScriptError(
"token-password and token-password-file are mutually exclusive"
)
if options.token_password_file:
with open(options.token_password_file, "r") as fd:
options.token_password = fd.readline().strip()
if (
not options.token_password_file
and not options.token_password
):
if options.unattended:
raise ScriptError("HSM token password required")
token_password = installutils.read_password(
f"HSM token '{token_name}'", confirm=False
)
if token_password is None:
raise ScriptError("HSM token password required")
else:
options.token_password = token_password
try:
hsm_validator(
token_name, 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

View File

@@ -16,10 +16,12 @@ from ipalib.kinit import kinit_keytab
from ipaplatform import services
from ipaplatform.paths import paths
from ipapython import ipautil
from ipapython.admintool import ScriptError
from ipapython.install.core import group
from ipaserver.install import ca, cainstance
from ipaserver.install import krainstance
from ipaserver.install import dsinstance
from ipaserver.install import installutils
from ipaserver.install import service as _service
from . import dogtag
@@ -58,13 +60,61 @@ def install_check(api, replica_config, options):
"KRA can not be installed when 'ca_host' is overriden in "
"IPA configuration file.")
# There are three scenarios for installing a KRA
# 1. At install time of the initial server
# 2. Using ipa-kra-install
# 3. At install time of a replica
#
# These tests are done in reverse order. If we are doing a
# replica install we can check the remote CA.
#
# If we are running ipa-kra-install then there must be a CA
# use that.
#
# If initial install we either have the token options or we don't.
cai = cainstance.CAInstance()
if replica_config is not None:
(token_name, token_library_path) = ca.lookup_hsm_configuration(api)
elif cai.is_configured() and cai.hsm_enabled:
(token_name, token_library_path) = ca.lookup_hsm_configuration(api)
elif 'token_name' in options.__dict__:
token_name = options.token_name
token_library_path = options.token_library_path
else:
token_name = None
if replica_config is not None:
if (
token_name
and options.token_password_file
and options.token_password
):
raise ScriptError(
"token-password and token-password-file are mutually exclusive"
)
if options.token_password_file:
with open(options.token_password_file, "r") as fd:
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)
if (
token_name
and not options.token_password_file
and not options.token_password
):
if options.unattended:
raise ScriptError("HSM token password required")
token_password = installutils.read_password(
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 token_name:
ca.hsm_validator(token_name, token_library_path, options.token_password)
def install(api, replica_config, options, custodia):

View File

@@ -663,6 +663,8 @@ def install_check(installer):
options.token_name is not None
)
):
if options.unattended:
raise ScriptError("HSM token password required")
token_password = read_password(
f"HSM token '{options.token_name}'" , confirm=False)
if token_password is None: