diff --git a/acertmgr/__init__.py b/acertmgr/__init__.py index 367c7af..d5059df 100755 --- a/acertmgr/__init__.py +++ b/acertmgr/__init__.py @@ -118,14 +118,20 @@ def cert_put(settings): return crt_action -def cert_revoke(cert, configs, reason=None): +def cert_revoke(cert, configs, fallback_authority, reason=None): domains = set(tools.get_cert_domains(cert)) + acmeconfig = None for config in configs: if domains == set(config['domainlist']): - acme = authority(config['authority']) - acme.register_account() - acme.revoke_crt(cert, reason) - return + acmeconfig = config['authority'] + break + if not acmeconfig: + acmeconfig = fallback_authority + log("No matching authority found to revoke {}: {}, using globalconfig/defaults".format(tools.get_cert_cn(cert), + tools.get_cert_domains(cert)), warning=True) + acme = authority(acmeconfig) + acme.register_account() + acme.revoke_crt(cert, reason) def main(): @@ -134,7 +140,10 @@ def main(): if runtimeconfig.get('mode') == 'revoke': # Mode: revoke certificate log("Revoking {}".format(runtimeconfig['revoke'])) - cert_revoke(tools.read_pem_file(runtimeconfig['revoke']), domainconfigs, runtimeconfig['revoke_reason']) + cert_revoke(tools.read_pem_file(runtimeconfig['revoke']), + domainconfigs, + runtimeconfig['fallback_authority'], + runtimeconfig['revoke_reason']) else: # Mode: issue certificates (implicit) # post-update actions (run only once) @@ -190,7 +199,7 @@ def main(): log("Revoking '{}' valid until {} as superseded".format( tools.get_cert_cn(superseded_cert), tools.get_cert_valid_until(superseded_cert))) - cert_revoke(superseded_cert, domainconfigs, reason=4) # reason=4 is superseded + cert_revoke(superseded_cert, domainconfigs, runtimeconfig['fallback_authority'], reason=4) except Exception as e: log("Certificate supersede revoke failed", e, error=True) exceptions.append(e) diff --git a/acertmgr/configuration.py b/acertmgr/configuration.py index 7df0474..04897e0 100644 --- a/acertmgr/configuration.py +++ b/acertmgr/configuration.py @@ -86,6 +86,28 @@ def idna_convert(domainlist): return list() +# @brief parse authority from config +def parse_authority(localconfig, globalconfig, runtimeconfig): + authority = {} + # - API version + update_config_value(authority, 'api', localconfig, globalconfig, DEFAULT_API) + + # - Certificate authority + update_config_value(authority, 'authority', localconfig, globalconfig, DEFAULT_AUTHORITY) + + # - Certificate authority ToS agreement + update_config_value(authority, 'authority_tos_agreement', localconfig, globalconfig, + runtimeconfig['authority_tos_agreement']) + + # - Certificate authority contact email addresses + update_config_value(authority, 'authority_contact_email', localconfig, globalconfig, None) + + # - Account key path + update_config_value(authority, 'account_key', localconfig, globalconfig, + os.path.join(runtimeconfig['work_dir'], "account.key")) + return authority + + # @brief load the configuration from a file def parse_config_entry(entry, globalconfig, runtimeconfig): config = dict() @@ -104,24 +126,7 @@ def parse_config_entry(entry, globalconfig, runtimeconfig): config['defaults'] = globalconfig.get('defaults', {}) # Authority related config options - config['authority'] = {} - - # - API version - update_config_value(config['authority'], 'api', localconfig, globalconfig, DEFAULT_API) - - # - Certificate authority - update_config_value(config['authority'], 'authority', localconfig, globalconfig, DEFAULT_AUTHORITY) - - # - Certificate authority ToS agreement - update_config_value(config['authority'], 'authority_tos_agreement', localconfig, globalconfig, - runtimeconfig['authority_tos_agreement']) - - # - Certificate authority contact email addresses - update_config_value(config['authority'], 'authority_contact_email', localconfig, globalconfig, None) - - # - Account key path - update_config_value(config['authority'], 'account_key', localconfig, globalconfig, - os.path.join(runtimeconfig['work_dir'], "account.key")) + config['authority'] = parse_authority(localconfig, globalconfig, runtimeconfig) # Certificate directory update_config_value(config, 'cert_dir', localconfig, globalconfig, runtimeconfig['work_dir']) @@ -310,4 +315,7 @@ def load(): for entry in yaml.safe_load(config_fd).items(): domainconfigs.append(parse_config_entry(entry, globalconfig, runtimeconfig)) + # Define a fallback authority from global configuration / defaults + runtimeconfig['fallback_authority'] = parse_authority([], globalconfig, runtimeconfig) + return runtimeconfig, domainconfigs