CERTGRINDER(8)

NAME
certgrinder - Manpage for certgrinder

The certgrinder client is responsible for generating a keypair and a CSR, which it uses to contact the Certgrinder server certgrinderd over SSH to get a signed certificate. The following section explains how to install and configure it to get certificates from the Certgrinder server.

INSTALLATION

This section explains the steps to install a Certgrinder client. Repeat these steps on each server in need of certificates!

  Install certgrinder

You can install certgrinder from pip with pip install certgrinder. This will install the latest certgrinder release. It will pull in the dependencies it needs automatically.

You can also checkout the Github repo and install the deps from requirements.txt by hand if you prefer. If you want to install with pip directly from Git the following may help: pip install "git+https://github.com/tykling/certgrinder/#egg=certgrinder&subdirectory=client"

  Create Certgrinder User

Since certgrinder is designed to be run under a separate system user one should be created. The user needs sudo access if (and only if) it is to be able to reload/restart services after renewing certificates. Sometimes it is also necessary to add some system users to the certgrinder group so they can read certificates. More on that later.

The user also needs to run ssh-keygen and the SSH key needs to be added to the authorized_keys file on the Certgrinder server. Make sure to test the SSH access works (hint: check firewalls, v4 vs v6 etc).

  Configuration

Configuration of certgrinder can be done using command-line options, or a configuration file, or a combination of the two.

The certgrinder configuration file is in YAML format. An example config named certgrinder.conf.dist can be found in the distribution. use --config-file or -f to specify the config file location.

Each config item can be specified either in the YAML config file as a key: value pair, or on the commandline as --key value - the latter overriding the former if both are present. For example, if the configfile has log-level: INFO and the command-line has --log-level: DEBUG then the effective log-level would be DEBUG.

This is an alphabetical list of the configurable options:

certgrinderd
    The command to run as certgrinderd. Usually this will be something like ssh certgrinderd@certgrinder.example.com -T, possibly also with a --config-file for certgrinderd if needed.

    Default: None

cert-renew-threshold-days
    A certificate will be renewed when it has less than this many days of lifetime left.

    Default: 30

domain-list
    Comma-separated lists of domains for the certificates. Can be specified multiple times on the command-line, --domain-list example.com,www.example.com --domain-list example.net means two certificates, the first with two names, the second with one name.

    Default: None

invalid-ca-cn-list
    List of CommonName of certificate issuers to consider invalid. This is not a regular CA certificate validity check, it is used to detect certificates issued by LetsEncrypt staging servers as invalid.

    Default: ["Fake LE Intermediate X1", "Fake LE Intermediate X2"]

log-level
    Sets the verbosity level for console and syslog logging. One of DEBUG, INFO, WARNING, ERROR, CRITICAL.

    Default: INFO

key-type-list
    List of key types to enable. Supported choices are rsa and ecdsa. Files for each keytype will be suffixed with .rsa.ext and ecdsa.ext, respectively.

    Default: ["rsa", "ecdsa"]

name-server
    Set this to a DNS server IP (v4 or v6, no hostnames) to use that DNS server instead of the system resolver.

    Default: None

ocsp-renew-threshold-percent
    The amount of time in percent between produced_at and next_update that must have passed before an OCSP response is considered too old. As of January 2021 LetsEncrypt has 7 days between produced_at and next_update in OCSP responses, so the default of 50% means OCSP responses will be renewed after 3.5 days (half of the validity period) has passed.

    As of January 2021 LetsEncrypt produces new OCSP responses after half of the validity period has passed, so any setting lower than that will be pointless. Setting this lower than 50 will just result in Certgrinder fetching the same OCSP response over and over.

    Set to 0 to always renew OCSP responses regardless of their age.

    Default: 50

path
    The directory used for keys, CSRs and certificates. Must exist and be writable by the user running Certgrinder.

    Default: None

periodic-sleep-minutes
    Certgrinder will pick a random number of minutes between 0 and this number and sleep for that long before doing periodic actions. Set to 0 to disable sleeping.

    Default: 60

pid-dir
    The directory to place the certgrinderd PID file in.

    Default: /tmp

post-renew-hooks
    A list of commands which certgrinder must run after renewing one or more certificates or OCSP responses. Use this to reload/restart services which need to be poked after the certificate changes. Can be specified multiple times on the command-line. Remember to include sudo or whatever if needed. Wrap complex commands in a small shell script to avoid quoting issues.

    Default: None

post-renew-hooks-dir
    A path to a hooks.d style directory containing files to be executed after renewing one or more certificates or OCSP responses. Each executable file in this path will be run in the order returned by os.listdir(). Set post-renew-hooks-dir-runner if something like sudo is needed to elevate privileges before running the hooks.

    Default: None

post-renew-hooks-dir-runner
    When this is set it will be executed in place of each executable in post-renew-hooks-dir with the executable as argument.

    Example: If post-renew-hooks-dir contains two executable files hook1 and hook2 and post-renew-hooks-dir-runner is set to /usr/local/bin/sudo then certgrinder will execute /usr/local/bin/sudo /path/to/hooks/dir/hook1 and then /usr/local/bin/sudo /path/to/hooks/dir/hook2 instead of executing the two hooks directly.

    Default: None

staging
    Enable staging mode. Adds --staging to the certgrinderd command, and considers certificates issued by LE staging servers as valid.

    Default: False

syslog-facility
    Set this and syslog-socket to enable logging to syslog. Must be a value supported by logging.handlers.SysLogHandler like LOG_USER or LOG_LOCAL0.

    Default: None

syslog-socket
    Set this and syslog-facility to enable logging to syslog.

    Default: None

tlsa-port
    Set this to the port (like 443) when using show tlsa or check tlsa subcommands.

    Default: None

tlsa-protocol
    Set this to the protocol (like tcp) when using show tlsa or check tlsa subcommands.

    Default: None

tlsa-type-list
    Set this to enable a TLSA type (can be specified multiple times). The TLSA type must be specified as three integers, one of: 310, 311 or 312. Default: is all three pubkey types.

    Default: ["310", "311", "312"]

  ACME Challenges

Finally you need to choose which challenge type to use for this certgrinder client. If DNS-01 you need to create one or more CNAME record pointing somewhere. If HTTP-01 you need to create an HTTP redirect. See the section on challenges for more info.

  Testing

At this point you should be ready to test! Start by checking with SSH manually to see that the SSH key is installed properly on the Certgrinder server, and firewalls are open. Certgrinder has a --staging switch which makes certgrinderd use the LetsEncrypt staging environment. Use this until everything works! certgrinder outputs some info on what happens, and can output more with -d / --debug, but sometimes you need to check syslog on the Certgrinder server.

  Crontab job

I run Certgrinder daily, although by default it only attempts certificate renewal when less than 30 days validity remains, and OCSP response renewal when half the validity period has passed.

When everything above works it is time to automate it by adding it to crontab. The following line works for me (the periodic command sleeps a random number of minutes before doing its thing, so all the clients don't contact the Certgrinder server at once):

    0 2 * * * certgrinder /usr/home/certgrinder/virtualenv/bin/certgrinder -c /usr/home/certgrinder/certgrinder.conf periodic

CLIENT COMMANDS

All the functionality in Certgrinder can be accessed by using commands and subcommands. The following commands are available:

•   check certificate command

•   check connection command

•   check ocsp command

•   check tlsa command

•   get certificate command

•   get ocsp command

•   help command

•   periodic command

•   show certificate command

•   show configuration command

•   show ocsp command

•   show paths command

•   show spki command

•   show tlsa command

•   version command

  check commands

All the subcommands for the check commands return exit code 1 if a problem is found and 0 if everything is fine.

  check certificate command

The check certificate subcommand loops over the configured domainsets and checks the validity of the certificate for each. If a problem is found certgrinder will exit with exit code 1, if all is well the exit code will be 0.

  check connection command

The check connection subcommand simply checks that the connection to the certgrinderd server works as expected. It calls the ping command on the certgrinderd server and expects to see the string pong on stdout. If the expected string is found the exit code will be 0, if a problem is found the exit code will be 1.

  check ocsp command

The check ocsp subcommand loops over the configured domainsets and checks for the existance of an OCSP response for each. If an OCSP response for a certificate is missing or too old certgrinder will exit with exit code 1, if all is well the exit code will be 0.

An OCSP response is considered too old when more than ocsp-renew-threshold-percent percent of the time between producedAt and nextUpdate has passed. As of January 2021 LetsEncrypt has 7 days (one week) between producedAt and nextUpdate which means OCSP responses will be renewed after 3.5 days with the default ocsp-renew-threshold-percent setting of 50.

  check tlsa command

The check tlsa subcommand is like the show tlsa subcommand but it goes one step further and actually checks in the DNS if the records could be found, and prints some output accordingly. The following example shows two runs of check tlsa mode. The first run finds no TLSA records and outputs what needs to be added:

    [certgrinder@znc ~]$ ./virtualenv/bin/certgrinder -f certgrinder.conf check tlsa 443 tcp
    2018-02-16 08:59:39 +0000 INFO: Processing domains: znc.tyknet.dk
    2018-02-16 08:59:39 +0000 INFO: Looking up TLSA records for _443._tcp.znc.tyknet.dk
    2018-02-16 08:59:39 +0000 WARNING: No TLSA records for name _443._tcp.znc.tyknet.dk of type 3 1 0 was found in DNS. This record needs to be added:
    2018-02-16 08:59:39 +0000 WARNING: _443._tcp.znc.tyknet.dk 3 1 0
    2018-02-16 08:59:39 +0000 WARNING: No TLSA records for name _443._tcp.znc.tyknet.dk of type 3 1 1 was found in DNS. This record needs to be added:
    2018-02-16 08:59:39 +0000 WARNING: _443._tcp.znc.tyknet.dk 3 1 1 5b95cb6ea387570f1f3dc4508794ca13a17a665733bab5f76b1e330f2fa13361
    2018-02-16 08:59:39 +0000 WARNING: No TLSA records for name _443._tcp.znc.tyknet.dk of type 3 1 2 was found in DNS. This record needs to be added:
    2018-02-16 08:59:39 +0000 WARNING: _443._tcp.znc.tyknet.dk 3 1 2 24d49f3c974129b9c28b5e6213892a404d8e9777c5a2e977333b88442d4e16ac0bc732001ec783df795c194704149bd18bbca21087111b33fa79e84dab05e760
    2018-02-16 08:59:39 +0000 INFO: Done processing domains: znc.tyknet.dk
    [certgrinder@znc ~]$

The second run is after adding the suggested records to DNS:

    [certgrinder@znc ~]$ ./virtualenv/bin/certgrinder -f certgrinder.conf check tlsa 443 tcp
    2018-02-16 09:16:27 +0000 INFO: Processing domains: znc.tyknet.dk
    2018-02-16 09:16:27 +0000 INFO: Looking up TLSA records for _443._tcp.znc.tyknet.dk
    2018-02-16 09:16:27 +0000 INFO: TLSA record for name _443._tcp.znc.tyknet.dk type 3 1 0 found in DNS matches the local key, good.
    2018-02-16 09:16:27 +0000 INFO: TLSA record for name _443._tcp.znc.tyknet.dk type 3 1 1 found in DNS matches the local key, good.
    2018-02-16 09:16:27 +0000 INFO: TLSA record for name _443._tcp.znc.tyknet.dk type 3 1 2 found in DNS matches the local key, good.
    2018-02-16 09:16:27 +0000 INFO: Done processing domains: znc.tyknet.dk
    [certgrinder@znc ~]$

All TLSA records for this public key can now be found in the DNS.

NOTE: As there might be additional records for the same name which do not belong to this server/key (for example in a loadbalanced or anycast setup), no attempts are made to warn about wrong/old/superfluous TLSA records. This might be added in a future version as a switch to tell Certgrinder that the local public key is the only one in existence for this service.

  get commands

The get subcommands do all the real work.

  get certificate command

The get certificate subcommand loops over the configured domainsets and gets a new certificate for each, regardless of the current status of existing certificates. Use with care, only for troubleshooting. Do not use from cron. Use the periodic command instead.

  get ocsp command

The get ocsp subcommand loops over the configured domainsets and gets a new OCSP response for each, regardless of the current status of existing OCSP responses. Do not use from cron. Use the periodic command instead.

  help command

The help command is just a shortcut for -h which shows commandline usage and help.

  periodic command

The periodic command sleeps for a random number of minutes between 0 and the config setting periodic-sleep-minutes before doing anything. Set this setting to 0 to disable sleeping.

After sleeping the certificates and OCSP responses are checked and renewed as needed. This command is meant to be run daily from cron or similar.

  show commands

The show subcommands show information but never change anything.

  show certificate command

The show certificate subcommand loops over configured domainsets and outputs information about each certificate (if any).

  show configuration command

The show configuration subcommand just dumps the active configuration as a pretty printed JSON object and exits. Useful for testing or debugging configuration issues.

  show ocsp command

The show ocsp subcommand loops over the configured domainsets and shows info about each OCSP response.

  show paths command

The show paths subcommand loops over the configured domainsets and outputs the paths used for keys, certificates and OCSP responses.

  show spki command

The show spki subcommand outputs pin-sha256 spki pins for the public keys. The HPKP standard https://en.wikipedia.org/wiki/HTTP_Public_Key_Pinning defined the pin-sha256 format for public key pins. While the HPKP standard didn't get much traction the pinning format is used in various places now, so certgrinder can generate them.

The operation is pretty simple:

    [certgrinder@znc ~]$ ./virtualenv/bin/certgrinder -f certgrinder.conf show spki
    2018-02-16 09:28:37 +0000 INFO: Processing domains: znc.tyknet.dk
    2018-02-16 09:28:37 +0000 INFO: pin-sha256="W5XLbqOHVw8fPcRQh5TKE6F6ZlczurX3ax4zDy+hM2E="
    2018-02-16 09:28:37 +0000 INFO: Done processing domains: znc.tyknet.dk
    [certgrinder@znc ~]$

  show tlsa command

The show tlsa subcommand loops over the configured domainsets and generates TLSA records for the public keys. The result is printed to the terminal in a format suitable for putting in the DNS. It looks something like this:

    [certgrinder@znc ~]$ ./virtualenv/bin/certgrinder -f certgrinder.conf show tlsa 443 tcp
    2018-02-16 08:42:18 +0000 INFO: Processing domains: znc.tyknet.dk
    2018-02-16 08:42:18 +0000 INFO: TLSA records for _443._tcp.znc.tyknet.dk:
    2018-02-16 08:42:18 +0000 INFO: _443._tcp.znc.tyknet.dk 3 1 0
    2018-02-16 08:42:18 +0000 INFO: _443._tcp.znc.tyknet.dk 3 1 1 5b95cb6ea387570f1f3dc4508794ca13a17a665733bab5f76b1e330f2fa13361
    2018-02-16 08:42:18 +0000 INFO: _443._tcp.znc.tyknet.dk 3 1 2 24d49f3c974129b9c28b5e6213892a404d8e9777c5a2e977333b88442d4e16ac0bc732001ec783df795c194704149bd18bbca21087111b33fa79e84dab05e760
    [certgrinder@znc ~]$

Shown above is the show tlsa subcommand in action. The value supplied should be the port and protocol of the service, in the example above it is a HTTPS service, so the TLSA record is the service hostname prefixed with _443._tcp.

  version command

The version command is just a shortcut for -v which shows the Certgrinder version and exits.

COMMAND LINE USAGE

Certgrinder version 0.20.1.dev0+g86b074d.d20250126. See the manpage or ReadTheDocs for more info.

    usage: certgrinder
           [-h]
           [--certgrinderd CERTGRINDERD]
           [--caa-validation-methods CAA-VALIDATION-METHODS]
           [--cert-renew-threshold-days CERT-RENEW-THRESHOLD-DAYS]
           [-c CONFIG-FILE]
           [-d]
           [-D DOMAIN-LIST]
           [--invalid-ca-cn-list INVALID-CA-CN-LIST]
           [-l {DEBUG,INFO,WARNING,ERROR,CRITICAL}]
           [-k {rsa,ecdsa}]
           [-n NAME-SERVER]
           [--now]
           [--path PATH]
           [--periodic-sleep-minutes PERIODIC-SLEEP-MINUTES]
           [-p PID-DIR]
           [--post-renew-hooks POST-RENEW-HOOKS]
           [--post-renew-hooks-dir POST-RENEW-HOOKS-DIR]
           [--post-renew-hooks-dir-runner POST-RENEW-HOOKS-DIR-RUNNER]
           [-q]
           [-s]
           [--syslog-facility SYSLOG-FACILITY]
           [--syslog-socket SYSLOG-SOCKET]
           [--tlsa-port TLSA-PORT]
           [--tlsa-protocol TLSA-PROTOCOL]
           [--tlsa-type-list {310,311,312}]
           [-v]
           {check,get,help,periodic,show,version}
           ...

  Positional Arguments

command
    Possible choices: check, get, help, periodic, show, version

    Command (required)

  Named Arguments

--certgrinderd
    The command to reach the certgrinderd server, will get the input (CSR or cert chain) on stdin. Usually something like 'ssh certgrinderd@server -T'

--caa-validation-methods
    The ACME validation methods to include when outputting CAA records. Default: dns-01,http-01

--cert-renew-threshold-days
    A certificate is renewed when it has less than this many days of lifetime left. Default: 30

-c, --config-file
    The path to the certgrinder.yml config file to use

-d, --debug
    Debug mode. Equal to setting --log-level=DEBUG.

-D, --domain-list
    Comma separated list of domains for a certificate. Can be specified multiple times.

--invalid-ca-cn-list
    The CommonName of an issuer (CA intermediate) to consider invalid. Can be specified multiple times.

-l, --log-level
    Possible choices: DEBUG, INFO, WARNING, ERROR, CRITICAL

    Logging level. One of DEBUG, INFO, WARNING, ERROR, CRITICAL. Defaults to INFO.

-k, --key-type-list
    Possible choices: rsa, ecdsa

    The keytypes to enable. Valid values are 'rsa' and 'ecdsa'. Can be specified multiple times. Defaults to both rsa and ecdsa.

-n, --name-server
    Tell certgrinder to use this DNS server IP to lookup TLSA records. Only relevant with -c / --checktlsa. Only v4/v6 IPs, no hostnames.

--now
    Run periodic command without delay. Equal to setting --periodic-sleep-minutes 0.

--path
    Tell certgrinder to use the specified directory for keys, CSRs and certificates. The directory must exist and be writeable by the user running certgrinder.

--periodic-sleep-minutes
    Tell certgrinder to sleep for a random number of minutes between 0 and this number before doing anything when the periodic command is used. Set to 0 to disable sleeping.

-p, --pid-dir
    The directory to store the PID file in

--post-renew-hooks
    The list of commands to run after one or more certificates are renewed. Most such commands will need root access to run, remember to prefix the command with 'sudo' as needed. Can be specified multiple times. Default: None

--post-renew-hooks-dir
    Path to a folder containing executables to run after one or more certificates are renewed. These will execute under the regular certgrinder user uid, so make sure to use sudo/doas in scripts or suid executables as needed. Default: None

--post-renew-hooks-dir-runner
    Path to an executable like sudo to be used to run each of the executables in the post renew hooks dir. Default: None

-q, --quiet
    Quiet mode. No output at all if there is nothing to do, and no errors are encountered. Equal to setting --log-level=WARNING.

-s, --staging
    Staging mode. Sets --acme-server-url https://acme-staging-v02.api.letsencrypt.org/directory and --invalid-ca-cn-list empty. Use this while playing around to avoid hitting rate limits!

--syslog-facility
    The syslog facility to use. Set this and syslog-socket to enable logging to syslog.

--syslog-socket
    The syslog socket to connect to. Set this and syslog-facility to enable logging to syslog.

--tlsa-port
    The service port number (like 443) for TLSA operations.

--tlsa-protocol
    The service protocol (like tcp) for TLSA operations.

--tlsa-type-list
    Possible choices: 310, 311, 312

    Enables a TLSA type for TLSA operations. Can be specified multiple times.

-v, --version
    Show version and exit.

  Sub-commands

  check

Use the "check" command to check certificates and TLSA records. Returns exit code 0 if all is well, and 1 if something needs attention.

    certgrinder check
    [-h]
    {certificate,connection,tlsa}
    ...

  Positional Arguments

subcommand
    Possible choices: certificate, connection, tlsa

    Specify what to check using one of the available check sub-commands.

  Sub-commands

  certificate

Tell certgrinder to check certificate validity for all configured domainsets. Returns exit code 1 if any problem is found, exit code 0 if all is well.

    certgrinder check certificate
    [-h]

  connection

Tell certgrinder to check the connection to the certgrinderd server by calling the certgrinderd 'ping' command which should return the string 'pong' if all is well.

    certgrinder check connection
    [-h]

  tlsa

Tell certgrinder to lookup TLSA records for the given port and protocol in the DNS and compare with what we have locally, for example: 'certgrinder check tlsa 853 tcp'

    certgrinder check tlsa
    [-h]
    tlsa-port
    tlsa-protocol

  Positional Arguments

tlsa-port
    The port of the service, for example 443

tlsa-protocol
    The protocol of the service, for example tcp

  get

Use the "get" command to get certificates

    certgrinder get
    [-h]
    {certificate}
    ...

  Positional Arguments

subcommand
    Possible choices: certificate

    Specify what to get using one of the available get sub-commands

  Sub-commands

  certificate

Tell certgrinder to get new certificate(s), regardless of their current state. Rarely needed, use 'periodic' command instead.

    certgrinder get certificate
    [-h]

  help

The "help" command just outputs the usage help

    certgrinder help
    [-h]

  periodic

The "periodic" command checks certificates and renews them as needed. Meant to be run from cron or similar daily.

    certgrinder periodic
    [-h]

  show

Use the "show" command to show certificates, TLSA records, SPKI pins or configuration.

    certgrinder show
    [-h]
    {certificate,configuration,paths,spki,tlsa,caa}
    ...

  Positional Arguments

subcommand
    Possible choices: certificate, configuration, paths, spki, tlsa, caa

    Specify what to show using one of the available show sub-commands

  Sub-commands

  certificate

Tell certgrinder to output information about certificates.

    certgrinder show certificate
    [-h]

  configuration

Tell certgrinder to output the current configuration

    certgrinder show configuration
    [-h]

  paths

Tell certgrinder to output the paths used

    certgrinder show paths
    [-h]

  spki

Tell certgrinder to generate and print the pin-sha256 spki pins for the public keys it manages.

    certgrinder show spki
    [-h]

  tlsa

Use the 'show tlsa' sub-command to tell certgrinder to generate and print TLSA records for the given service, for example: 'certgrinder show tlsa 443 tcp'

    certgrinder show tlsa
    [-h]
    tlsa-port
    tlsa-protocol

  Positional Arguments

tlsa-port
    The port of the service, for example 443

tlsa-protocol
    The protocol of the service, for example tcp

  caa

Use the 'show caa' sub-command to tell certgrinder to output a CAA record suitable for the specified domainset(s).

    certgrinder show caa
    [-h]

  version

The "version" command just outputs the version of Certgrinder

    certgrinder version
    [-h]

CLASS METHODS

class certgrinder.Certgrinder
    The Certgrinder client class.

__init__() -> None
    Initialise the Certgrinder object.

check_certificate(certificate: Certificate | None = None, public_key: RSAPublicKey | Ed25519PublicKey | EllipticCurvePublicKey | None = None) -> bool
    Check certificate validity and returns True or False.

    This method is called by self.grind() once per domainset when the "check certificate" subcommand is invoked. It reads the certificate from self.certificate_path if there is no certificate arg

Parameters

•   certificate -- The certificate to be checked

•   public_key -- The keypair the certificate is based on

Returns
    True if everything is OK, False otherwise

static check_certificate_expiry(certificate: Certificate, threshold_days: int) -> bool
    Check the remaining validity of the certificate.

Parameters

•   certificate -- The certificate to check

•   threshold_days -- The lowest number of remaining days of validity that is considered valid

Returns
    True if remaining certificate lifetime is >= threshold_days, False if not

static check_certificate_issuer(certificate: Certificate, invalid_ca_cn_list: list[str]) -> bool
    Check the issuer of the certificate.

Parameters

•   certificate -- The certificate to check

•   invalid_ca_cn_list -- The list of CA CommonName strings to consider invalid

Returns
    True if the certificate issuer CN is not in invalid_ca_cn_list

static check_certificate_public_key(certificate: Certificate, public_key: RSAPublicKey | Ed25519PublicKey | EllipticCurvePublicKey) -> bool
    Make sure certificate has the specified public key.

Parameters

•   certificate -- The certificate to check

•   public_key -- The public key

Returns
    True if the public key matches, False if not

static check_certificate_san_names(certificate: Certificate, san_names: list[str]) -> bool
    Make sure the certificate has the provided list of names as SAN.

Parameters

•   certificate -- The certificate to check

•   san_names -- A list of the names to expect

Returns
    True if all san_names were found in the cert, and no others.

static check_certificate_subject(certificate: Certificate, subject: Name) -> bool
    Make sure the certificate has the specified subject.

Parameters

•   certificate -- The certificate to check

•   subject -- The subject to expect

Returns
    True if the subject matches the cert, False if not

classmethod check_certificate_validity(certificate: Certificate, invalid_ca_cn_list: list[str], threshold_days: int, san_names: list[str], public_key: RSAPublicKey | Ed25519PublicKey | EllipticCurvePublicKey | None = None, subject: Name | None = None) -> bool
    Perform a few sanity checks of the certificate.

•   Check that the issuer is valid

•   Check that the certificate expiry is not exceeded

•   Check that the public key is correct (if provided)

•   Check that the subject is correct (if provided)

•   Check that the SubjectAltName data is correct

Parameters

•   certificate -- The certificate to check

•   invalid_ca_cn_list -- A list of CA CommonNames to consider invalid

•   threshold_days -- The minimum number of remaining days lifetime to considered valid.

•   san_names -- A list of domain names to expect in SubjectAltName of the certificate.

•   public_key -- The pubkey the certificate is for.

•   subject -- The expected subject of the certificate

Returns
    False if a problem is found, True if all is well.

check_connection(stdout: bytes | None = None) -> bool
    The check connection subcommand method.

Parameters
    stdout -- The certgrinderd response to use instead of calling certgrinderd (optional)

Returns
    None

check_tlsa() -> None
    The 'check tlsa' subcommand method, called for each domainset by self.grind().

    Loops over the configured TLSA types and calls self.verify_tlsa_record() which does the heavy lifting.

Returns
    None

configure(userconfig: Mapping[str, str | int | bool | list[str] | Path]) -> None
    Merge and check configuration and configure logging.

    Merge the supplied userconfig dict with the default config, checks for missing required settings, and configures logging and syslog.

Parameters
    userconfig -- dict of the config to be merged with the default config

Returns
    None

static generate_csr(keypair: RSAPrivateKey | Ed25519PrivateKey | EllipticCurvePrivateKey, domains: list[str]) -> CertificateSigningRequest
    Generate and return a new CSR based on the public key and list of domains.

    Only set CN since everything else is removed by LetsEncrypt in the certificate anyway. Add all domains in subjectAltName, including the one put into CN.

Parameters

•   keypair -- The keypair to base the CSR on

•   domains -- A list of domains to put in the CSR. First in the list will be cert CN.

Returns
    The CSR object

static generate_private_key(keytype: str) -> RSAPrivateKey | EllipticCurvePrivateKey | Ed25519PrivateKey
    Generate and returns a private key.

Parameters
    keytype -- "rsa" for RSA key, "ecdsa" for ECDSA and "ed25519" for ed25519

Returns
    The keypair object

Raises
    ValueError -- For unsupported keytypes

static generate_spki(derkey: bytes) -> str
    Generate and return a pin-sha256 spki hpkp style pin for the provided public key.

OpenSSL equivalent command is:
    openssl x509 -in example.com.crt -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl base64

Parameters
    derkey -- The bytes representing the public key in DER format

Returns
    A string of the SPKI pin

static generate_tlsa_record(derkey: bytes, tlsatype: str) -> str
    Generate and return the data part of a TLSA record of the requested type.

    TLSA record is generated from the DER formatted public key supplied. Returns an uppercase hex string.

Parameters

•   derkey -- The bytes representing the public key in DER format

•   tlsatype -- The TLSA type (like "310")

Returns
    String of the TLSA data

Raises
    ValueError -- If an unknown TLSA type is passed

get_certgrinderd_command(subcommand: list[str]) -> list[str]
    Return the certgrinderd command to run.

    Adds --log-level with the current self.conf.log_level. Also adds --acme-server-url if configured, and --preferred-chain.

Parameters
    subcommand -- The certgrinderd subcommand to run as a list, like ["get", "certificate"]

Returns
    A list of the elements which make up the certgrinderd command

get_certificate(csr: CertificateSigningRequest | None = None, stdout: bytes | None = None) -> bool
    Get a new certificate for self.domainset.

    This method gets a new certificate regardless of the status of any existing certificate. It is called by self.periodic() as needed. It can also be called by the get certificate subcommand.

Parameters

•   csr -- The CSR to use instead of generating one

•   stdout -- The stdout bytes to use instead of calling self.run_certgrinderd(csr)

Returns
    False something goes wrong, True if all is well

static get_der_pubkey(keypair: RSAPrivateKey | Ed25519PrivateKey | EllipticCurvePrivateKey) -> bytes
    Return the DER formatted publickey.

Parameters
    keypair -- The keypair which contains the public key

Returns
    The bytes representing the DER formatted public key

get_filename(hostname: str) -> str
    Calculate the hostname string to be used for filenames.

    Files are named after the ascii idna representation of the first hostname in the list (which is also the CN in the subject of the CSR and certificate).

    Max filename length on some platforms is 255 bytes, but a hostname could be up to 253 bytes (RFC 1035 section 2.3.4), and we need some room for the usage and keytype and extension, so we only use the last 230 bytes of the ascii idna representation of the hostname for the filename, leaving 25 bytes for metadata.

Parameters
    hostname -- The hostname to use

Returns
    The string to use in filenames

grind(args: Namespace) -> None
    Loop over enabled keytypes and domainsets in self.conf.domain_list and call args.method for each.

load_certificates(path: Path) -> list[Certificate]
    Reads PEM certificate data from the path, parses the certificate(s), and returns them in a list.

Parameters
    path -- The path to read the PEM certificate(s) from

Returns
    A list of cryptography.x509.Certificate objects

load_domainset(domainset: list[str], keytype: str) -> None
    Prepare paths and create/load private key.

Parameters

•   domainset -- The list of hostnames to load

•   keytype -- The keytype to use, "rsa" or "ecdsa".

Returns
    None

static load_keypair(path: Path) -> RSAPrivateKey | Ed25519PrivateKey | EllipticCurvePrivateKey
    Load keypair bytes from disk, load key and return the object.

    Fixes keypair permissions to 640 if they are not 640.

Parameters
    path -- The path to load the keypair from

Returns
    The keypair object

static lookup_tlsa_record(domain: str, port: int, protocol: str, tlsatype: str | None = None, nameserver: str = '') -> list[str] | None
    Lookup TLSA records in DNS for the configured domain, port, and protocol.

    Loop over any responses and look for the requested tlsatype. Return a list of results, optionally limited to the specified tlsatype, or None. Use system resolver unless nameserver is specified.

Parameters

•   domain -- The service domain name (like mail.example.com)

•   port -- The service port (like 443)

•   protocol -- The service protocol (like tcp)

•   tlsatype -- The TLSA type (like 312)

•   nameserver -- The DNS server IP to use instead of system resolver (optional)

Returns
    A list of records or None

classmethod output_spki(derkey: bytes) -> None
    Get and print the spki pin for the supplied DER public key.

Parameters
    derkey -- The bytes representation of the DER formatted public key

Returns
    None

classmethod output_tlsa_record(*, derkey: bytes, domain: str, port: int, protocol: str, tlsatype: str, warning: bool = False) -> None
    Output the TLSA record for the given DER key, domain, port, protocol and tlsatype.

    Call self.generate_tlsa() and output the result formatted as a DNS record

Parameters

•   derkey -- The bytes representation the public key in DER format

•   domain -- The service domain name (like mail.example.com)

•   port -- The service port (like 443)

•   protocol -- The service protocol (like tcp)

•   tlsatype -- The TLSA type (like 312)

•   warning -- Set True to output at level WARNING (default INFO)

Returns
    None

static parse_certificate(certificate_bytes: bytes) -> Certificate | None
    Parse a bunch of bytes representing a PEM certificate and return.

Parameters
    certificate_bytes -- The PEM certificate

Returns
    The parsed cryptography.x509.Certificate object or None

parse_certificate_chain(certificate_chain: bytes, csr: CertificateSigningRequest) -> list[Certificate] | None
    Split a PEM chain into a list of certificates.

Parameters

•   certificate_chain -- The bytes representing the PEM formatted certificate chain

•   csr -- The CSR this certificate was issued from

Returns
    A list of certificates with the leaf certificate first, or None if an error happens

periodic() -> bool
    The periodic method performs periodic maintenance tasks.

    This method is called by the 'periodic' command, from cron or similar. It starts out by sleeping for a random period and then checks certificates and renews as needed.

run_certgrinderd(stdin: bytes, command: list[str], certgrinderd_stdout: bytes = b'', certgrinderd_stderr: bytes = b'') -> bytes
    Run the configured self.conf.certgrinderd command.

    The stdin argument will be passed to stdin of the command. A CSR is needed for the "get certificate" certgrinderd command.

Parameters

•   stdin -- bytes representing CSR or cert chain to pass to the certgrinderd command

•   command -- The certgrinderd command and subcommand to call

•   certgrinderd_stdout -- Mocked certgrinderd stdout to use instead of calling the command

•   certgrinderd_stderr -- Mocked certgrinderd stderr to use instead of calling the command

Returns
    The bytes representing the stdout from the subprocess call

static run_post_renew_hook(hook: Sequence[Path | str]) -> bool
    Run a specific post renew hook.

Parameters
    hook -- A list of string components of the command and arguments

    Returns: True if exit code was 0, False otherwise.

run_post_renew_hooks() -> bool
    Loops over configured post_renew_hooks and executables in post_renew_hooks_dir and runs them.

Returns
    None

static save_certificate(certificate: Certificate, path: Path, issuers: list[Certificate] | None = None) -> None
    Save the PEM certificate to the path, optionally with an issuer chain.

Parameters

•   certificate -- The certificate to save

•   path -- The path to save the certificate in

•   issuers -- The list of issuer certificates to write after the certificate (if any)

Returns
    None

classmethod save_concat_certkey(keypair: RSAPrivateKey | Ed25519PrivateKey | EllipticCurvePrivateKey, certificate: Certificate, issuers: list[Certificate], path: Path) -> None
    Create a single file with the private key, the cert and the issuer(s), in that order.

Parameters

•   keypair -- The keypair to save in the concat file

•   certificate -- The certificate to save in the concat file

•   issuers -- The list of issuer(s) to save in the concat file

•   path -- The path to save the concat file in

Returns
    None

static save_csr(csr: CertificateSigningRequest, path: Path) -> None
    Save the PEM version of the CSR to the path.

    chmods the file 644 after writing.

Parameters

•   csr -- The CSR to be saved

•   path -- The path to save the CSR to

Returns
    None

static save_keypair(keypair: RSAPrivateKey | Ed25519PrivateKey | EllipticCurvePrivateKey, path: Path) -> None
    Save keypair to disk.

Parameters

•   keypair -- The keypair to save

•   path -- The path to save the keypair in

Returns
    None

Raises
    TypeError -- For unsupported keytypes

show_caa() -> None
    The show caa subcommand method, called for each domainset by self.grind().

Returns
    None

show_certificate() -> None
    The show certificate subcommand method, called for each domainset by self.grind().

Returns
    None

show_paths() -> None
    The show paths subcommand method, called for each domainset by self.grind().

Returns
    None

show_spki() -> None
    The show spki subcommand method, called for each domainset by self.grind().

    Call self.output_spki() with the DER formatted public key and output the result.

Returns
    None

show_tlsa() -> None
    The 'show tlsa' subcommand method, called for each domainset by self.grind().

Returns
    None

static split_pem_chain(pem_chain_bytes: bytes) -> list[bytes]
    Split a PEM chain into a list of bytes of the individual PEM certificates.

Parameters
    pem_chain_bytes -- The bytes representing the PEM chain

Returns
    A list of 0 or more bytes chunks representing each certificate

classmethod verify_tlsa_record(derkey: bytes, domain: str, port: int, protocol: str, tlsatype: str, nameserver: str = '') -> bool
    Check the TLSA records for the port/protocol/domain and DER key in the DNS.

    Output the info needed to fix things when missing records are found.

Parameters

•   derkey -- The bytes representation the public key in DER format

•   domain -- The service domain name (like mail.example.com)

•   port -- The service port (like 443)

•   protocol -- The service protocol (like tcp)

•   tlsatype -- The TLSA type (like 312)

•   nameserver -- The DNS server IP to use instead of system resolver (optional)

Returns
    True if all is well, False if one or more problems are found

AUTHOR
Thomas Steen Rasmussen

COPYRIGHT
2020, Thomas Steen Rasmussen