Skip to content

Commit

Permalink
[feat] log enrollment config in various ca_handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
grindsa committed Dec 16, 2024
1 parent 2fc2198 commit 7260522
Show file tree
Hide file tree
Showing 31 changed files with 484 additions and 187 deletions.
45 changes: 35 additions & 10 deletions acme_srv/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,28 @@ def config_headerinfo_load(logger: logging.Logger, config_dic: Dict[str, str]):
logger.debug('config_headerinfo_load() ended')
return header_info_field

def config_enroll_config_log_load(logger: logging.Logger, config_dic: Dict[str, str]):
""" load parameters """
logger.debug('Helper.config_enroll_config_log_load()')

enrollment_config_log = False
enrollment_config_log_skip_list = []

if 'CAhandler' in config_dic:
try:
enrollment_config_log = config_dic.getboolean('CAhandler', 'enrollment_config_log', fallback=False)
except Exception as err_:
logger.warning('CAhandler._config_load() enrollment_config_log failed with error: %s', err_)

if 'enrollment_config_log_skip_list' in config_dic['CAhandler']:
try:
enrollment_config_log_skip_list = json.loads(config_dic['CAhandler']['enrollment_config_log_skip_list'])
except Exception as err_:
logger.warning('CAhandler._config_load() enrollment_config_log_skip_list failed with error: %s', err_)
enrollment_config_log_skip_list = 'ECLSLFAILURE'

logger.debug('config_enroll_config_log_load() ended with: %s', enrollment_config_log)
return enrollment_config_log, enrollment_config_log_skip_list

def eab_handler_load(logger: logging.Logger, config_dic: Dict) -> importlib.import_module:
""" load and return eab_handler """
Expand Down Expand Up @@ -1920,18 +1942,21 @@ def csr_cn_lookup(logger: logging.Logger, csr: str) -> str:
return csr_cn


def enrollment_config_log(logger: logging.Logger, obj: object, skiplist: List[str] = None):
def enrollment_config_log(logger: logging.Logger, obj: object, handler_skiplist: List[str] = None):
""" log enrollment configuration """
logger.debug('Helper.enrollment_config_log()')

skip_list = ['logger', 'session', 'password', 'api_key', 'key', 'secret', 'token']
skiplist = ['logger', 'session', 'password', 'api_key', 'api_password', 'key', 'secret', 'token']

if skiplist:
skip_list.extend(skiplist)
if handler_skiplist and isinstance(handler_skiplist, list):
skiplist.extend(handler_skiplist)

enroll_parameter_list = []
for key, value in obj.__dict__.items():
if key.startswith('__') or key in skip_list:
continue
enroll_parameter_list.append(f'{key}: {value}')
logger.info('Enrollment configuration: %s', enroll_parameter_list)
if handler_skiplist and 'ECLSLFAILURE' in handler_skiplist:
logger.error('Enrollment configuration won\'t get logged due to a configuration error.')
else:
enroll_parameter_list = []
for key, value in obj.__dict__.items():
if key.startswith('__') or key in skiplist:
continue
enroll_parameter_list.append(f'{key}: {value}')
logger.info('Enrollment configuration: %s', enroll_parameter_list)
4 changes: 3 additions & 1 deletion docs/acme_ca.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ The handler must be configured via `acme_srv`.
| acme_account_email | email address used to register a new account | no | None |
| allowed_domainlist | list of domain-names allowed for enrollment in json format example: ["bar.local$, bar.foo.local] | no | [] |
| directory_path | path to directory ressource on ca server | no | '/directory' |
| eab_profiling | enable eab-profiling | None | False |
| eab_profiling | enable eab-profiling | no | False |
| enrollment_config_log | log enrollment parameters | no | False |
| enrollment_config_log_skip_list | list enrollment parameters not to be logged in json format example: [ "parameter1", "parameter2" ] | no | [] |
| ssl_verify | verify certificates on SSL connections | no | True |

- modify the server configuration (`acme_srv/acme_srv.cfg`) and add at least the following parameters.
Expand Down
3 changes: 3 additions & 0 deletions docs/asa.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ cert_validity_days: <days>
- ca_name - name of the CA used to enroll certificates
- profile_name - profile name
- cert_validity_days - optional - polling timeout (default: 60s)
- eab_profiling - optional - [activate eab profiling](eab_profiling.md) (default: False)
- enrollment_config_log - optional - log enrollment parameters (default False)
- enrollment_config_log_skip_list - optional - list enrollment parameters not to be logged in json format example: [ "parameter1", "parameter2" ] (default: [])

It is also recommended to increase the enrollment timeout to avoid that acme2certifier is closing the connection to early.

Expand Down
4 changes: 3 additions & 1 deletion docs/certifier.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ eab_profiling: <True|False>
- api_password_variable - *optional* - name of the environment variable containing the password for the REST user (a configured `api_password` parameter in acme_srv.cfg takes precedence)
- ca_bundle - optional - certificate bundle needed to validate the server certificate - can be True/False or a filename (default: True)
- ca_name - name of the CA used to enroll certificates
- eab_profiling - optional - [activate eab profiling](eab_profiling.md) (default: False)
- enrollment_config_log - optional - log enrollment parameters (default False)
- enrollment_config_log_skip_list - optional - list enrollment parameters not to be logged in json format example: [ "parameter1", "parameter2" ] (default: [])
- profile_id - optional - profileId
- polling_timeout - optional - polling timeout (default: 60s)
- eab_profiling - optional - [activate eab profiling](eab_profiling.md) (default: False)

Depending on CA policy configuration a CSR may require approval. In such a situation acme2certfier will poll the CA server to check the CSR status. The polling interval can be configured in acme.server.cfg.

Expand Down
2 changes: 2 additions & 0 deletions docs/digicert.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ eab_profiling: <True|False>
- order_validity - optional - oder validity (default: 1 year)
- request_timeout - optional - requests timeout in seconds for requests (default: 5s)
- eab_profiling - optional - [activate eab profiling](eab_profiling.md) (default: False)
- enrollment_config_log - optional - log enrollment parameters (default False)
- enrollment_config_log_skip_list - optional - list enrollment parameters not to be logged in json format example: [ "parameter1", "parameter2" ] (default: [])

Use your favorite acme client for certificate enrollment. A list of clients used in our regression can be found in the [disclaimer section of our README file](../README.md)

Expand Down
4 changes: 3 additions & 1 deletion docs/ejbca.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@ eab_profiling: <True|False>
- cert_profile_name - name of the certificate profile
- ee_profile_name - name of the end entity profile
- ca_name - name of the CA used to enroll certificates
- request_timeout - optional - requests timeout in seconds for requests (default: 5s)
- eab_profiling - optional - [activate eab profiling](eab_profiling.md) (default: False)
- enrollment_config_log - optional - log enrollment parameters (default False)
- enrollment_config_log_skip_list - optional - list enrollment parameters not to be logged in json format example: [ "parameter1", "parameter2" ] (default: [])
- request_timeout - optional - requests timeout in seconds for requests (default: 5s)

You can test the connection by running the following curl command against your EJBCA server.

Expand Down
2 changes: 2 additions & 0 deletions docs/entrust.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ eab_profiling: <True|False>
- allowed_domainlist: list of domain-names allowed for enrollment in json format (example: ["bar.local$, bar.foo.local])
- request_timeout - optional - requests timeout in seconds for requests (default: 5s)
- eab_profiling - optional - [activate eab profiling](eab_profiling.md) (default: False)
- enrollment_config_log - optional - log enrollment parameters (default False)
- enrollment_config_log_skip_list - optional - list enrollment parameters not to be logged in json format example: [ "parameter1", "parameter2" ] (default: [])

Use your favorite acme client for certificate enrollment. A list of clients used in our regression can be found in the [disclaimer section of our README file](../README.md)

Expand Down
2 changes: 2 additions & 0 deletions docs/mscertsrv.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ eab_profiling: False
- template - certificate template used for enrollment
- allowed_domainlist - *optional* - list of domain-names allowed for enrollment in json format example: ["bar.local$, bar.foo.local]
- eab_profiling - optional - [activate eab profiling](eab_profiling.md) (default: False)
- enrollment_config_log - optional - log enrollment parameters (default False)
- enrollment_config_log_skip_list - optional - list enrollment parameters not to be logged in json format example: [ "parameter1", "parameter2" ] (default: [])

## Passing a template from client to server

Expand Down
2 changes: 2 additions & 0 deletions docs/mswcce.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ eab_profiling: False
- use_kerberos - use kerboros for authentication; if set to `False` authentication will be done via NTLM. Considering a [Microsoft accouncement from October 2023](https://techcommunity.microsoft.com/t5/windows-it-pro-blog/the-evolution-of-windows-authentication/ba-p/3926848) the usage of Kerberos should be preferred. Nevertheless, for backwards compatibility reasons the default setting is `False`
- allowed_domainlist - *optional* - list of domain-names allowed for enrollment in json format example: ["bar.local$, bar.foo.local]
- eab_profiling - optional - [activate eab profiling](eab_profiling.md) (default: False)
- enrollment_config_log - optional - log enrollment parameters (default False)
- enrollment_config_log_skip_list - optional - list enrollment parameters not to be logged in json format example: [ "parameter1", "parameter2" ] (default: [])

## Passing a template from client to server

Expand Down
3 changes: 3 additions & 0 deletions docs/nclm.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,6 @@ template_name: <template_name>
- ca_name - name of the CA used to enroll certificates
- tsg_name - name of the target system group to store the certificates
- template_name - optional - name of the template to be applied to CSR
- eab_profiling - optional - [activate eab profiling](eab_profiling.md) (default: False)
- enrollment_config_log - optional - log enrollment parameters (default False)
- enrollment_config_log_skip_list - optional - list enrollment parameters not to be logged in json format example: [ "parameter1", "parameter2" ] (default: [])
2 changes: 2 additions & 0 deletions docs/xca.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ template_name: XCA template to be applied to CSRs
- `ca_cert_chain_list` - *optional* - List of root and intermediate CA certificates to be added to the bundle return to an ACME-client (the issuing CA cert must not be included)
- `template_name` - *optional* - name of the XCA template to be applied during certificate issuance
- eab_profiling - optional - [activate eab profiling](eab_profiling.md) (default: False)
- enrollment_config_log - optional - log enrollment parameters (default False)
- enrollment_config_log_skip_list - optional - list enrollment parameters not to be logged in json format example: [ "parameter1", "parameter2" ] (default: [])

Template support has been introduced starting from v0.13. Support is limited to the below parameters which can be applied during certificate issuance:

Expand Down
10 changes: 9 additions & 1 deletion examples/ca_handler/acme_ca_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from acme import client, messages
from acme import errors
from acme_srv.db_handler import DBstore
from acme_srv.helper import load_config, b64_url_recode, parse_url, allowed_domainlist_check, config_eab_profile_load, config_headerinfo_load, header_info_field_validate, eab_profile_header_info_check
from acme_srv.helper import load_config, b64_url_recode, parse_url, allowed_domainlist_check, config_eab_profile_load, config_headerinfo_load, header_info_field_validate, eab_profile_header_info_check, config_enroll_config_log_load, enrollment_config_log

"""
Config file section:
Expand Down Expand Up @@ -50,6 +50,8 @@ def __init__(self, _debug: bool = False, logger: object = None):
self.eab_profiling = False
self.acme_keypath = None
self.ssl_verify = True
self.enrollment_config_log = False
self.enrollment_config_log_skip_list = []

def __enter__(self):
""" Makes CAhandler a Context Manager """
Expand Down Expand Up @@ -121,6 +123,8 @@ def _config_load(self):
self.eab_profiling, self.eab_handler = config_eab_profile_load(self.logger, config_dic)
# load header info
self.header_info_field = config_headerinfo_load(self.logger, config_dic)
# load enrollment config log
self.enrollment_config_log, self.enrollment_config_log_skip_list = config_enroll_config_log_load(self.logger, config_dic)

def _challenge_filter(self, authzr: messages.AuthorizationResource, chall_type: str = 'http-01') -> messages.ChallengeBody:
""" filter authorization for challenge """
Expand Down Expand Up @@ -504,6 +508,10 @@ def enroll(self, csr: str) -> Tuple[str, str, str, str]:
if not error:
error = eab_profile_header_info_check(self.logger, self, csr, 'acme_url')

if self.enrollment_config_log:
self.enrollment_config_log_skip_list.extend(['dbstore', 'eab_mack_key'])
enrollment_config_log(self.logger, self, self.enrollment_config_log_skip_list)

if not error:
try:
user_key = self._user_key_load()
Expand Down
16 changes: 13 additions & 3 deletions examples/ca_handler/asa_ca_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import requests
from requests.auth import HTTPBasicAuth
# pylint: disable=e0401
from acme_srv.helper import load_config, encode_url, csr_pubkey_get, csr_cn_get, csr_san_get, uts_now, uts_to_date_utc, b64_decode, cert_der2pem, convert_byte_to_string, cert_ski_get, config_eab_profile_load, config_headerinfo_load, eab_profile_header_info_check
from acme_srv.helper import load_config, encode_url, csr_pubkey_get, csr_cn_get, csr_san_get, uts_now, uts_to_date_utc, b64_decode, cert_der2pem, convert_byte_to_string, cert_ski_get, config_eab_profile_load, config_headerinfo_load, eab_profile_header_info_check, config_enroll_config_log_load, enrollment_config_log


class CAhandler(object):
Expand All @@ -28,6 +28,8 @@ def __init__(self, _debug: bool = None, logger: object = None):
self.header_info_field = False
self.eab_handler = None
self.eab_profiling = False
self.enrollment_config_log = False
self.enrollment_config_log_skip_list = []

def __enter__(self):
""" Makes CAhandler a Context Manager """
Expand Down Expand Up @@ -205,13 +207,17 @@ def _config_load(self):
if not getattr(self, ele):
self.logger.error('CAhandler._config_load(): %s not set', ele)

self._auth_set()

# load profiling
self.eab_profiling, self.eab_handler = config_eab_profile_load(self.logger, config_dic)

self._auth_set()

# load header info
self.header_info_field = config_headerinfo_load(self.logger, config_dic)

# load enrollment config log
self.enrollment_config_log, self.enrollment_config_log_skip_list = config_enroll_config_log_load(self.logger, config_dic)

self.logger.debug('CAhandler._config_load() ended')

def _csr_cn_get(self, csr: str) -> str:
Expand Down Expand Up @@ -393,6 +399,10 @@ def enroll(self, csr: str) -> Tuple[str, str, str, str]:
# check for eab profiling and header_info
error = eab_profile_header_info_check(self.logger, self, csr, 'profile_name')

if self.enrollment_config_log:
self.enrollment_config_log_skip_list.extend(['api_password', 'auth'])
enrollment_config_log(self.logger, self, self.enrollment_config_log_skip_list)

if not error:
# verify issuer
error = self._issuer_verify()
Expand Down
11 changes: 10 additions & 1 deletion examples/ca_handler/certifier_ca_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import requests
from requests.auth import HTTPBasicAuth
# pylint: disable=e0401
from acme_srv.helper import load_config, cert_serial_get, uts_now, uts_to_date_utc, b64_decode, b64_encode, cert_pem2der, parse_url, proxy_check, error_dic_get, config_eab_profile_load, config_headerinfo_load, eab_profile_header_info_check
from acme_srv.helper import load_config, cert_serial_get, uts_now, uts_to_date_utc, b64_decode, b64_encode, cert_pem2der, parse_url, proxy_check, error_dic_get, config_eab_profile_load, config_headerinfo_load, eab_profile_header_info_check, config_enroll_config_log_load, enrollment_config_log


class CAhandler(object):
Expand All @@ -32,6 +32,8 @@ def __init__(self, debug: bool = False, logger: object = None):
self.header_info_field = False
self.eab_handler = None
self.eab_profiling = False
self.enrollment_config_log = False
self.enrollment_config_log_skip_list = []

def __enter__(self):
""" Makes ACMEHandler a Context Manager """
Expand Down Expand Up @@ -136,6 +138,10 @@ def _cert_get(self, csr: str) -> Dict[str, str]:
ca_dic = self._ca_get_properties('name', self.ca_name)
cert_dic = {}

if self.enrollment_config_log:
self.enrollment_config_log_skip_list.extend(['auth', 'api_password'])
enrollment_config_log(self.logger, self, self.enrollment_config_log_skip_list)

if 'href' in ca_dic:
data = {'ca': ca_dic['href'], 'pkcs10': csr}

Expand Down Expand Up @@ -258,6 +264,9 @@ def _config_parameter_load(self, config_dic: Dict[str, str]):
except Exception:
self.request_timeout = 20

# load enrollment config log
self.enrollment_config_log, self.enrollment_config_log_skip_list = config_enroll_config_log_load(self.logger, config_dic)

# load profile_id
self.profile_id = config_dic['CAhandler'].get('profile_id', None)

Expand Down
9 changes: 8 additions & 1 deletion examples/ca_handler/digicert_ca_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import json
import requests
# pylint: disable=e0401
from acme_srv.helper import load_config, cert_pem2der, b64_encode, allowed_domainlist_check, eab_profile_header_info_check, uts_now, uts_to_date_utc, cert_serial_get, config_eab_profile_load, config_headerinfo_load, request_operation, csr_cn_lookup
from acme_srv.helper import load_config, cert_pem2der, b64_encode, allowed_domainlist_check, eab_profile_header_info_check, uts_now, uts_to_date_utc, cert_serial_get, config_eab_profile_load, config_headerinfo_load, request_operation, csr_cn_lookup, config_enroll_config_log_load, enrollment_config_log


CONTENT_TYPE = 'application/json'
Expand All @@ -29,6 +29,8 @@ def __init__(self, _debug: bool = None, logger: object = None):
self.header_info_field = False
self.eab_handler = None
self.eab_profiling = False
self.enrollment_config_log = False
self.enrollment_config_log_skip_list = []

def __enter__(self):
""" Makes CAhandler a Context Manager """
Expand Down Expand Up @@ -131,6 +133,8 @@ def _config_load(self):
self.eab_profiling, self.eab_handler = config_eab_profile_load(self.logger, config_dic)
# load header info
self.header_info_field = config_headerinfo_load(self.logger, config_dic)
# load enrollment config log
self.enrollment_config_log, self.enrollment_config_log_skip_list = config_enroll_config_log_load(self.logger, config_dic)

self.logger.debug('CAhandler._config_load() ended')

Expand All @@ -139,6 +143,9 @@ def _order_send(self, csr: str, csr_cn) -> Tuple[str, str]:
self.logger.debug('CAhandler._order_send()')
order_url = f'{self.api_url}order/certificate/{self.cert_type}'

if self.enrollment_config_log:
enrollment_config_log(self.logger, self, self.enrollment_config_log_skip_list)

if not csr.endswith('='):
# padding if needed
csr = csr + '=' * (-len(csr) % 4)
Expand Down
Loading

0 comments on commit 7260522

Please sign in to comment.