162 lines
5.2 KiB
Python

from typing import Iterable, Optional, TypeVar, Union
import click
from pyhanko_certvalidator import ValidationContext
from pyhanko.cli.config import CLIConfig
from pyhanko.cli.utils import logger, readable_file
from pyhanko.config.errors import ConfigurationError
from pyhanko.config.trust import init_validation_context_kwargs
from pyhanko.keys import load_certs_from_pemder
def build_vc_kwargs(
cli_config: Optional[CLIConfig],
validation_context: Optional[str],
trust: Union[Iterable[str], str],
trust_replace: bool,
other_certs: Union[Iterable[str], str],
retroactive_revinfo: bool,
allow_fetching: Optional[bool] = None,
):
try:
if validation_context is not None:
if any((trust, other_certs)):
raise click.ClickException(
"--validation-context is incompatible with --trust "
"and --other-certs"
)
# load the desired context from config
if cli_config is None:
raise click.ClickException("No config file specified.")
try:
result = cli_config.get_validation_context(
validation_context, as_dict=True
)
except ConfigurationError as e:
msg = (
"Configuration problem. Are you sure that the validation "
f"context '{validation_context}' is properly defined in the"
" configuration file?"
)
logger.error(msg, exc_info=e)
raise click.ClickException(msg)
elif trust or other_certs:
# load a validation profile using command line kwargs
result = init_validation_context_kwargs(
trust=trust,
trust_replace=trust_replace,
other_certs=other_certs,
retroactive_revinfo=retroactive_revinfo,
)
elif cli_config is not None:
# load the default settings from the CLI config
try:
result = cli_config.get_validation_context(as_dict=True)
except ConfigurationError as e:
msg = "Failed to load default validation context."
logger.error(msg, exc_info=e)
raise click.ClickException(msg)
else:
result = {}
if allow_fetching is not None:
result['allow_fetching'] = allow_fetching
else:
result.setdefault('allow_fetching', True)
# allow CLI --retroactive-revinfo flag to override settings
# if necessary
if retroactive_revinfo:
result['retroactive_revinfo'] = True
return result
except click.ClickException:
raise
except IOError as e:
msg = "I/O problem while reading validation config"
logger.error(msg, exc_info=e)
raise click.ClickException(msg)
except Exception as e:
msg = "Generic processing problem while reading validation config"
logger.error(msg, exc_info=e)
raise click.ClickException(msg)
def _get_key_usage_settings(ctx: click.Context, validation_context: str):
cli_config: Optional[CLIConfig] = ctx.obj.config
if cli_config is None:
return None
# note: validation_context can be None, this triggers fallback to the
# default validation context specified in the configuration file
# If we add support for specifying key usage settings as CLI arguments,
# using the same fallbacks as _build_cli_kwargs would probably be cleaner
return cli_config.get_signer_key_usages(name=validation_context)
TRUST_OPTIONS = [
click.Option(
('--validation-context',),
help='use validation context from config',
required=False,
type=str,
),
click.Option(
('--trust',),
help='list trust roots (multiple allowed)',
required=False,
multiple=True,
type=readable_file,
),
click.Option(
('--trust-replace',),
help='listed trust roots supersede OS-provided trust store',
required=False,
type=bool,
is_flag=True,
default=False,
show_default=True,
),
click.Option(
('--other-certs',),
help='other certs relevant for validation',
required=False,
multiple=True,
type=readable_file,
),
]
FC = TypeVar('FC', bound=click.Command)
def trust_options(f: FC) -> FC:
f.params.extend(TRUST_OPTIONS)
return f
def _prepare_vc(vc_kwargs, soft_revocation_check, force_revinfo):
if soft_revocation_check and force_revinfo:
raise click.ClickException(
"--soft-revocation-check is incompatible with " "--force-revinfo"
)
if force_revinfo:
rev_mode = 'require'
elif soft_revocation_check:
rev_mode = 'soft-fail'
else:
rev_mode = 'hard-fail'
vc_kwargs['revocation_mode'] = rev_mode
return vc_kwargs
def grab_certs(files):
if not files:
return None
try:
return list(load_certs_from_pemder(files))
except (IOError, ValueError) as e:
raise click.ClickException(
f'Could not load certificates from {files}'
) from e