New 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.
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.
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
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>.
The path the certificate should be present at.
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).
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.
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.
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
.
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.
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.
When copypath
is set, prepend the common name of the certificate to
the file name like so: <CN>-<serial_number>.crt
. Defaults to false.
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.
The private key corresponding to the public key in signing_cert
. Required.
If signing_private_key
is encrypted, the passphrase to decrypt it.
The CA certificate to be used for signing the issued certificate.
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.
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
.
If private_key
is specified and encrypted, the passphrase to decrypt it.
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)
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.
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.
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.
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.
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).
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.
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.
When encoding a certificate as pkcs12
, a name for the certificate can be included.
Embedded X.509v3 extensions and the subject's distinguished name can be
controlled via supplemental keyword arguments. See
x509.create_certificate
for an overview.
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>.
The path the certificate revocation list should be present at.
Your certificate authority's private key. It will be used to sign the CRL. Required.
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:
Identifies the certificate issuer associated with an entry in an indirect CRL. The format is the same as for subjectAltName.
Identifies the reason for certificate revocation.
Available choices are unspecified
, keyCompromise
, CACompromise
,
affiliationChanged
, superseded
, cessationOfOperation
,
certificateHold
, privilegeWithdrawn
, aACompromise
and
removeFromCRL
.
Provides the date on which the certificate became invalid.
The value should be a string in the same format as revocation_date
.
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.
The CA certificate to be used for signing the issued certificate.
If signing_private_key
is encrypted, the passphrase to decrypt it.
Also include already expired certificates in the CRL. Defaults to false.
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).
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.
Specify the encoding of the resulting certificate revocation list.
It can be serialized as a pem
text or binary der
file.
Defaults to pem
.
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
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
.
The path the certificate signing request should be present at.
The private key corresponding to the public key the certificate should be issued for. The CSR will be signed by it. Required.
If private_key
is encrypted, the passphrase to decrypt it.
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.
Specify the encoding of the resulting certificate revocation list.
It can be serialized as a pem
text or binary der
file.
Defaults to pem
.
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
).
Manage the contents of a PEM file directly with the content in text, ensuring correct formatting.
The path to the file to manage.
The PEM-formatted text to write.
Most arguments supported by file.managed
are passed through.
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
.
The path the private key should be present at.
The digital signature scheme the private key should be based on.
Available: rsa
, ec
, ed25519
, ed448
. Defaults to rsa
.
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.
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.
Specify the encoding of the resulting private key. It can be serialized
as a pem
text, binary der
or pkcs12
file.
Defaults to pem
.
Always create a new key. Defaults to false.
Combining new with prereq
can allow key rotation whenever a new certificate is generated.
Overwrite an existing private key if the provided passphrase cannot decrypt it. Defaults to false.
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 %}