# salt.states.x509_v2

## Manage X.509 certificates

Added in version 3006.0: This module represents a complete rewrite of the original `x509` modules and is named `x509_v2` since it introduces breaking changes.

depends:

  cryptography

Note

All parameters that take a public key, private key, certificate, CSR or CRL can be specified either as a PEM/hex/base64 string or a path to a local file encoded in all supported formats for the type.

Configuration instructions and general remarks are documented in the execution module docs.

For the list of breaking changes versus the previous `x509` modules, please also refer to the execution module docs.

### About

This module can enable managing a complete PKI infrastructure, including creating private keys, CAs, certificates and CRLs. It includes the ability to generate a private key on a server, and have the corresponding public key sent to a remote CA to create a CA signed certificate. This can be done in a secure manner, where private keys are always generated locally and never moved across the network.

Example

Here is a simple example scenario. In this example `ca` is the ca server, and `www` is a web server that needs a certificate signed by `ca`.

Note

Remote signing requires the setup of Peer Communication and signing policies. Please see the execution module docs.

/srv/salt/top.sls

    base:
      '*':
        - cert
      'ca':
        - ca
      'www':
        - www

This state creates the CA key, certificate and signing policy. It also publishes the certificate to the mine, where it can be easily retrieved by other minions.

    # /srv/salt/ca.sls

    Configure the x509 module:
      file.managed:
        - name: /etc/salt/minion.d/x509.conf
        - source: salt://x509.conf

    Restart Salt minion:
      cmd.run:
        - name: 'salt-call service.restart salt-minion'
        - bg: true
        - onchanges:
          - file: /etc/salt/minion.d/x509.conf

    Ensure PKI directories exist:
      file.directory:
        - name: /etc/pki/issued_certs
        - makedirs: true

    Create CA private key:
      x509.private_key_managed:
        - name: /etc/pki/ca.key
        - keysize: 4096
        - backup: true
        - require:
          - file: /etc/pki/issued_certs

    Create self-signed CA certificate:
      x509.certificate_managed:
        - name: /etc/pki/ca.crt
        - signing_private_key: /etc/pki/ca.key
        - CN: ca.example.com
        - C: US
        - ST: Utah
        - L: Salt Lake City
        - basicConstraints: "critical, CA:true"
        - keyUsage: "critical, cRLSign, keyCertSign"
        - subjectKeyIdentifier: hash
        - authorityKeyIdentifier: keyid:always,issuer
        - days_valid: 3650
        - days_remaining: 0
        - backup: true
        - require:
          - x509: /etc/pki/ca.key

    # /srv/salt/x509.conf

    # enable x509_v2
    features:
      x509_v2: true

    # publish the CA certificate to the mine
    mine_functions:
      x509.get_pem_entries: [/etc/pki/ca.crt]

    # define at least one signing policy for remote signing
    x509_signing_policies:
      www:
        - minions: 'www'
        - signing_private_key: /etc/pki/ca.key
        - signing_cert: /etc/pki/ca.crt
        - C: US
        - ST: Utah
        - L: Salt Lake City
        - basicConstraints: "critical CA:false"
        - keyUsage: "critical keyEncipherment"
        - subjectKeyIdentifier: hash
        - authorityKeyIdentifier: keyid:always,issuer
        - days_valid: 30
        - copypath: /etc/pki/issued_certs/

This example state will instruct all minions to trust certificates signed by our new CA. Mind that this example works for Debian-based OS only. Also note the Jinja call to encode the string to JSON, which will avoid YAML issues with newline characters.

    # /srv/salt/cert.sls

    Ensure the CA trust bundle exists:
      file.directory:
        - name: /usr/local/share/ca-certificates

    Ensure our self-signed CA certificate is included:
      x509.pem_managed:
        - name: /usr/local/share/ca-certificates/myca.crt
        - text: {{ salt["mine.get"]("ca", "x509.get_pem_entries")["ca"]["/etc/pki/ca.crt"] | json }}

This state creates a private key, then requests a certificate signed by our CA according to the www policy.

    # /srv/salt/www.sls

    Ensure PKI directory exists:
      file.directory:
        - name: /etc/pki

    Create private key for the certificate:
      x509.private_key_managed:
        - name: /etc/pki/www.key
        - keysize: 4096
        - backup: true
        - require:
          - file: /etc/pki

    Request certificate:
      x509.certificate_managed:
        - name: /etc/pki/www.crt
        - ca_server: ca
        - signing_policy: www
        - private_key: /etc/pki/www.key
        - CN: www.example.com
        - days_remaining: 7
        - backup: true
        - require:
          - x509: /etc/pki/www.key

salt.states.x509_v2.certificate_managed(name, days_remaining=None, ca_server=None, signing_policy=None, encoding='pem', append_certs=None, copypath=None, prepend_cn=False, digest='sha256', signing_private_key=None, signing_private_key_passphrase=None, signing_cert=None, public_key=None, private_key=None, private_key_passphrase=None, csr=None, subject=None, serial_number=None, not_before=None, not_after=None, days_valid=None, pkcs12_passphrase=None, pkcs12_encryption_compat=False, pkcs12_friendlyname=None, **kwargs)

  Ensure an X.509 certificate is present as specified.

  This function accepts the same arguments as `x509.create_certificate`, as well as most ones for :py:func:`file.managed <salt.states.file.managed>.

  name

    The path the certificate should be present at.

  days_remaining

    The certificate will be recreated once the remaining certificate validity period is less than this number of days. Defaults to `90` (until v3009) or `7` (from v3009 onwards).

  ca_server

    Request a remotely signed certificate from ca_server. For this to work, a `signing_policy` must be specified, and that same policy must be configured on the ca_server. Also, the Salt master must permit peers to call the `x509.sign_remote_certificate` function. See the execution module docs for details.

  signing_policy

    The name of a configured signing policy. Parameters specified in there are hardcoded and cannot be overridden. This is required for remote signing, otherwise optional.

  encoding

    Specify the encoding of the resulting certificate. It can be serialized as a `pem` (or `pkcs7_pem`) text file or in several binary formats (`der`, `pkcs7_der`, `pkcs12`). Defaults to `pem`.

  append_certs

    A list of additional certificates to append to the new one, e.g. to create a CA chain.

    Note

    Mind that when `der` encoding is in use, appending certificatees is prohibited.

  copypath

    Create a copy of the issued certificate in PEM format in this directory. The file will be named `<serial_number>.crt` if prepend_cn is false.

  prepend_cn

    When `copypath` is set, prepend the common name of the certificate to the file name like so: `<CN>-<serial_number>.crt`. Defaults to false.

  digest

    The hashing algorithm to use for the signature. Valid values are: sha1, sha224, sha256, sha384, sha512, sha512_224, sha512_256, sha3_224, sha3_256, sha3_384, sha3_512. Defaults to `sha256`. This will be ignored for `ed25519` and `ed448` key types.

  signing_private_key

    The private key corresponding to the public key in `signing_cert`. Required.

  signing_private_key_passphrase

    If `signing_private_key` is encrypted, the passphrase to decrypt it.

  signing_cert

    The CA certificate to be used for signing the issued certificate.

  public_key

    The public key the certificate should be issued for. Other ways of passing the required information are `private_key` and `csr`. If neither are set, the public key of the `signing_private_key` will be included, i.e. a self-signed certificate is generated.

  private_key

    The private key corresponding to the public key the certificate should be issued for. This is one way of specifying the public key that will be included in the certificate, the other ones being `public_key` and `csr`.

  private_key_passphrase

    If `private_key` is specified and encrypted, the passphrase to decrypt it.

  csr

    A certificate signing request to use as a base for generating the certificate. The following information will be respected, depending on configuration:

    - public key

    - extensions, if not otherwise specified (arguments, signing_policy)

  subject

    The subject's distinguished name embedded in the certificate. This is one way of passing this information (see `kwargs` below for the other). This argument will be preferred and allows to control the order of RDNs in the DN as well as to embed RDNs with multiple attributes. This can be specified as a RFC4514-encoded string (`CN=example.com,O=Example Inc,C=US`, mind that the rendered order is reversed from what is embedded), a list of RDNs encoded as in RFC4514 (`["C=US", "O=Example Inc", "CN=example.com"]`) or a dictionary (`{"CN": "example.com", "C": "US", "O": "Example Inc"}`, default ordering). Multiple name attributes per RDN are concatenated with a `+`.

    Note

    Parsing of RFC4514 strings requires at least cryptography release 37.

  serial_number

    A serial number to be embedded in the certificate. If unspecified, will autogenerate one. This should be an integer, either in decimal or hexadecimal notation.

  not_before

    Set a specific date the certificate should not be valid before. The format should follow `%Y-%m-%d %H:%M:%S` and will be interpreted as GMT/UTC. Defaults to the time of issuance.

  not_after

    Set a specific date the certificate should not be valid after. The format should follow `%Y-%m-%d %H:%M:%S` and will be interpreted as GMT/UTC. If unspecified, defaults to the current time plus `days_valid` days.

  days_valid

    If `not_after` is unspecified, the number of days from the time of issuance the certificate should be valid for. Defaults to `365` (until v3009) or `30` (from v3009 onwards).

  pkcs12_passphrase

    When encoding a certificate as `pkcs12`, encrypt it with this passphrase.

    Note

    PKCS12 encryption is very weak and should not be relied on for security.

  pkcs12_encryption_compat

    OpenSSL 3 and cryptography v37 switched to a much more secure default encryption for PKCS12, which might be incompatible with some systems. This forces the legacy encryption. Defaults to False.

  pkcs12_friendlyname

    When encoding a certificate as `pkcs12`, a name for the certificate can be included.

  kwargs

    Embedded X.509v3 extensions and the subject's distinguished name can be controlled via supplemental keyword arguments. See `x509.create_certificate` for an overview.

salt.states.x509_v2.crl_managed(name, signing_private_key, revoked, days_remaining=None, signing_cert=None, signing_private_key_passphrase=None, include_expired=False, days_valid=None, digest='sha256', encoding='pem', extensions=None, **kwargs)

  Ensure a certificate revocation list is present as specified.

  This function accepts the same arguments as `x509.create_crl`, as well as most ones for :py:func:`file.managed <salt.states.file.managed>.

  name

    The path the certificate revocation list should be present at.

  signing_private_key

    Your certificate authority's private key. It will be used to sign the CRL. Required.

  revoked

    A list of dicts containing all the certificates to revoke. Each dict represents one certificate. A dict must contain either the key `serial_number` with the value of the serial number to revoke, or `certificate` with some reference to the certificate to revoke.

    The dict can optionally contain the `revocation_date` key. If this key is omitted, the revocation date will be set to now. It should be a string in the format `%Y-%m-%d %H:%M:%S`.

    The dict can also optionally contain the `not_after` key. This is redundant if the `certificate` key is included. If the `certificate` key is not included, this can be used for the logic behind the `include_expired` parameter. It should be a string in the format `%Y-%m-%d %H:%M:%S`.

    The dict can also optionally contain the `extensions` key, which allows to set CRL entry-specific extensions. The following extensions are supported:

    certificateIssuer

      Identifies the certificate issuer associated with an entry in an indirect CRL. The format is the same as for subjectAltName.

    CRLReason

      Identifies the reason for certificate revocation. Available choices are `unspecified`, `keyCompromise`, `CACompromise`, `affiliationChanged`, `superseded`, `cessationOfOperation`, `certificateHold`, `privilegeWithdrawn`, `aACompromise` and `removeFromCRL`.

    invalidityDate

      Provides the date on which the certificate became invalid. The value should be a string in the same format as `revocation_date`.

  days_remaining

    The certificate revocation list will be recreated once the remaining CRL validity period is less than this number of days. Defaults to `30` (until v3009) or `3` (from v3009 onwards). Set to 0 to disable automatic renewal without anything changing.

  signing_cert

    The CA certificate to be used for signing the issued certificate.

  signing_private_key_passphrase

    If `signing_private_key` is encrypted, the passphrase to decrypt it.

  include_expired

    Also include already expired certificates in the CRL. Defaults to false.

  days_valid

    The number of days that the CRL should be valid for. This sets the `Next Update` field in the CRL. Defaults to `100` (until v3009) or `7` (from v3009 onwards).

  digest

    The hashing algorithm to use for the signature. Valid values are: sha1, sha224, sha256, sha384, sha512, sha512_224, sha512_256, sha3_224, sha3_256, sha3_384, sha3_512. Defaults to `sha256`. This will be ignored for `ed25519` and `ed448` key types.

  encoding

    Specify the encoding of the resulting certificate revocation list. It can be serialized as a `pem` text or binary `der` file. Defaults to `pem`.

  extensions

    Add CRL extensions. See `x509.create_crl` for details.

    Note

    For `cRLNumber`, in addition the value `auto` is supported, which automatically increases the counter every time a new CRL is issued.

  Example:

      Manage CRL:
        x509.crl_managed:
          - name: /etc/pki/ca.crl
          - signing_private_key: /etc/pki/myca.key
          - signing_cert: /etc/pki/myca.crt
          - revoked:
            - certificate: /etc/pki/certs/badweb.crt
              revocation_date: 2022-11-01 00:00:00
              extensions:
                CRLReason: keyCompromise
            - serial_number: D6:D2:DC:D8:4D:5C:C0:F4
              not_after: 2023-03-14 00:00:00
              revocation_date: 2022-10-25 00:00:00
              extensions:
                CRLReason: cessationOfOperation
          - extensions:
              cRLNumber: auto

salt.states.x509_v2.csr_managed(name, private_key, private_key_passphrase=None, digest='sha256', encoding='pem', subject=None, **kwargs)

  Ensure a certificate signing request is present as specified.

  This function accepts the same arguments as `x509.create_csr`, as well as most ones for `file.managed`.

  name

    The path the certificate signing request should be present at.

  private_key

    The private key corresponding to the public key the certificate should be issued for. The CSR will be signed by it. Required.

  private_key_passphrase

    If `private_key` is encrypted, the passphrase to decrypt it.

  digest

    The hashing algorithm to use for the signature. Valid values are: sha1, sha224, sha256, sha384, sha512, sha512_224, sha512_256, sha3_224, sha3_256, sha3_384, sha3_512. Defaults to `sha256`. This will be ignored for `ed25519` and `ed448` key types.

  encoding

    Specify the encoding of the resulting certificate revocation list. It can be serialized as a `pem` text or binary `der` file. Defaults to `pem`.

  kwargs

    Embedded X.509v3 extensions and the subject's distinguished name can be controlled via supplemental keyword arguments. See `x509.create_certificate` for an overview. Mind that some extensions are not available for CSR (`authorityInfoAccess`, `authorityKeyIdentifier`, `issuerAltName`, `crlDistributionPoints`).

salt.states.x509_v2.pem_managed(name, text, **kwargs)

  Manage the contents of a PEM file directly with the content in text, ensuring correct formatting.

  name

    The path to the file to manage.

  text

    The PEM-formatted text to write.

  kwargs

    Most arguments supported by `file.managed` are passed through.

salt.states.x509_v2.private_key_managed(name, algo='rsa', keysize=None, passphrase=None, encoding='pem', new=False, overwrite=False, pkcs12_encryption_compat=False, **kwargs)

  Ensure a private key is present as specified.

  This function accepts the same arguments as `x509.create_private_key`, as well as most ones for `file.managed`.

  Note

  If `mode` is unspecified, it will default to `0400`.

  name

    The path the private key should be present at.

  algo

    The digital signature scheme the private key should be based on. Available: `rsa`, `ec`, `ed25519`, `ed448`. Defaults to `rsa`.

  keysize

    For `rsa`, specifies the bitlength of the private key (2048, 3072, 4096). For `ec`, specifies the NIST curve to use (256, 384, 521). Irrelevant for Edwards-curve schemes (`ed25519`, `ed448`). Defaults to 2048 for RSA and 256 for EC.

  passphrase

    If this is specified, the private key will be encrypted using this passphrase. The encryption algorithm cannot be selected, it will be determined automatically as the best available one.

  encoding

    Specify the encoding of the resulting private key. It can be serialized as a `pem` text, binary `der` or `pkcs12` file. Defaults to `pem`.

  new

    Always create a new key. Defaults to false. Combining new with `prereq` can allow key rotation whenever a new certificate is generated.

  overwrite

    Overwrite an existing private key if the provided passphrase cannot decrypt it. Defaults to false.

  pkcs12_encryption_compat

    Some operating systems are incompatible with the encryption defaults for PKCS12 used since OpenSSL v3. This switch triggers a fallback to `PBESv1SHA1And3KeyTripleDESCBC`. Please consider the notes on PKCS12 encryption.

  Example:

  The Jinja templating in this example ensures a new private key is generated if the file does not exist and whenever the associated certificate is to be renewed.

      Manage www private key:
        x509.private_key_managed:
          - name: /etc/pki/www.key
          - keysize: 4096
          - new: true
      {%- if salt["file.file_exists"]("/etc/pki/www.key") %}
          - prereq:
            - x509: /etc/pki/www.crt
      {%- endif %}