salt.states.ssh_pki#
Manage OpenSSH certificates#
New in version 3008.0.
- depends:
cryptography
Configuration instructions and general remarks are documented in the execution module docs.
About#
This module can enable managing a complete SSH PKI infrastructure, including creating private keys, CAs and certificates. 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.
Note
In addition to the native Salt backend (the ssh_pki execution module),
you can have the state module call a different (compatible) execution module
using the backend parameter.
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 using the native Salt backend 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 and signing policy. It also publishes the public key to the mine, where it can be easily retrieved by other minions.
# /srv/salt/ca.sls
Ensure SSH PKI directories exist:
file.directory:
- name: /etc/pki/ssh/issued_certs
- makedirs: true
Create CA private key:
ssh_pki.private_key_managed:
- name: /etc/pki/ssh/ca.key
- algo: ed25519
- backup: true
- require:
- file: /etc/pki/ssh/issued_certs
Write CA public key:
ssh_pki.public_key_managed:
- name: /etc/pki/ssh/ca.pub
- public_key_source: /etc/pki/ssh/ca.key
- require:
- ssh_pki: /etc/pki/ssh/ca.key
# /srv/salt/ssh_pki.conf
# publish the CA certificate to the mine
mine_functions:
ssh_ca:
- mine_function: ssh_pki.get_public_key
- /etc/pki/ssh/ca.key
# define at least one signing policy for remote signing
ssh_signing_policies:
www_host:
- minions: 'www'
- signing_private_key: /etc/pki/ssh/ca.key
- cert_type: host
- ttl: 7d
- copypath: /etc/pki/ssh/issued_certs/
This example state will instruct minion SSH servers to trust certificates signed by our new CA. Mind that the specifics depend on the OS.
# /srv/salt/cert.sls
Write the trusted CA file:
file.managed:
- name: /etc/ssh/trusted-user-ca-keys.pem
- contents: {{ salt["mine.get"]("ca", "ssh_ca")["ca"] | json }}
- user: root
- group: root
Ensure SSH is configured to trust the CA:
file.managed:
- name: /etc/ssh/sshd_config.d/salt_ca_trust.conf
- contents: |
TrustedUserCAKeys /etc/ssh/trusted-user-ca-keys.pem
- require:
- file: /etc/ssh/trusted-user-ca-keys.pem
This state creates a private key to use as the host key, then requests
a certificate signed by our CA according to the www_host policy and configures
the SSH server to use it.
# /srv/salt/www.sls
Create host private key:
ssh_pki.private_key_managed:
- name: /etc/ssh/ssh_host_rsa_key
- algo: ed25519
- backup: true
Request certificate:
ssh_pki.certificate_managed:
- name: /etc/ssh/ssh_host_rsa_key.pub
- ca_server: ca
- signing_policy: www_host
- private_key: /etc/ssh/ssh_host_rsa_key
- backup: true
- require:
- ssh_pki: /etc/ssh/ssh_host_rsa_key
Ensure SSH is configured to use the certificate:
file.managed:
- name: /etc/ssh/sshd_config.d/host_cert.conf
- contents: |
HostKey /etc/ssh/ssh_host_rsa_key
HostCertificate /etc/ssh/ssh_host_rsa_key-cert.pub
- require:
- ssh_pki: /etc/ssh/ssh_host_rsa_key
- ssh_pki: /etc/ssh/ssh_host_rsa_key.pub
- salt.states.ssh_pki.certificate_managed(name, ttl_remaining=None, ca_server=None, backend=None, backend_args=None, signing_policy=None, copypath=None, cert_type=None, signing_private_key=None, signing_private_key_passphrase=None, public_key=None, private_key=None, private_key_passphrase=None, serial_number=None, not_before=None, not_after=None, ttl=None, critical_options=None, extensions=None, valid_principals=None, all_principals=False, key_id=None, **kwargs)#
Ensure an OpenSSH certificate is present as specified.
This function accepts the same arguments as
ssh_pki.create_certificate, as well as most ones for :py:func:`file.managed <salt.states.file.managed>.Note
Since
file.managedalso has anencodingparam, it can be passed asfile_encodinginstead.- name
The path the certificate should be present at.
- ttl_remaining
The certificate will be recreated once the remaining certificate validity period is less than this number of seconds. Can also be specified as a time string like
12dor1.5h. Defaults to7dfor host keys and1hfor user keys.- ca_server
Request a remotely signed certificate from another minion acting as a CA server via the
ssh_pkiexecution module. For this to work, asigning_policymust be specified, and that same policy must be configured on the ca_server. Also, the Salt master must permit peers to call thessh_pki.sign_remote_certificatefunction. See the execution module docs for details.- backend
Instead of using the
ssh_pkiexecution module for certificate creation, use this backend. It must provide a compatible API forcreate_certificateandget_signing_policy.- backend_args
If
backendis specified, pass these additional keyword arguments to it. Must be a mapping (dict).- 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.
- copypath
Create a copy of the issued certificate in this directory. The file will be named
<serial_number>.crt.- cert_type
The certificate type to generate. Either
userorhost. Required if not specified in the signing policy.- private_key
The private key corresponding to the public key the certificate should be issued for. Either this or
public_keyis required.- private_key_passphrase
If
private_keyis specified and encrypted, the passphrase to decrypt it.- public_key
The public key the certificate should be issued for. Either this or
private_keyis required.- signing_private_key
The private key of the CA that should be used to sign the certificate. Required.
- signing_private_key_passphrase
If
signing_private_keyis encrypted, the passphrase to decrypt it.- 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:%Sand 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:%Sand will be interpreted as GMT/UTC. If unspecified, defaults to the current time plusttl.- ttl
If
not_afteris unspecified, a time string (like30dor12h) or the number of seconds from the time of issuance the certificate should be valid for. Defaults to30dfor host certificates and24hfor client certificates.- critical_options
A mapping of critical option name to option value to set on the certificate. If an option does not take a value, specify it as
true.- extensions
A mapping of extension name to extension value to set on the certificate. If an extension does not take a value, specify it as
true.- valid_principals
A list of valid principals.
- all_principals
Allow any principals. Defaults to false.
- key_id
Specify a string-valued key ID for the signed public key. When the certificate is used for authentication, this value will be logged in plaintext.
- salt.states.ssh_pki.certificate_managed_ssh(name, result, comment, changes, contents=None, **kwargs)#
Helper for the SSH wrapper module. This receives a certificate and dumps the data to the target. A
file.managedsub-state run will be performed.
- salt.states.ssh_pki.private_key_managed(name, algo='rsa', keysize=None, passphrase=None, new=False, overwrite=False, **kwargs)#
Ensure a private key is present as specified.
This function accepts the same arguments as
ssh_pki.create_private_key, as well as most ones forfile.managed.Note
If
modeis unspecified, it will default to0400.- 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. Defaults torsa.- keysize
For
rsa, specifies the bitlength of the private key (2048, 3072, 4096). Forec, specifies the NIST curve to use (256, 384, 521). Irrelevant fored25519. 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.
- new
Always create a new key. Defaults to false. Combining new with
prereqcan 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.
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: ssh_pki.private_key_managed: - name: /root/.ssh/www - keysize: 4096 - new: true {%- if salt["file.file_exists"]("/root/.ssh/www") %} - prereq: - ssh_pki: /root/.ssh/www.crt {%- endif %}
- salt.states.ssh_pki.private_key_managed_ssh(name, result, comment, changes, tempfile=None, **kwargs)#
Helper for the SSH wrapper module to report the correct return and perform a
file.managedsub-state run.
- salt.states.ssh_pki.public_key_managed(name, public_key_source, passphrase=None, **kwargs)#
Ensure a public key is present as specified.
This function accepts most arguments for
file.managed.Note
If
modeis unspecified, it will default to0400.- name
The path the public key should be present at.
- public_key_source
The certificate (or any reference that can be passed to
get_public_key) to retrieve the public key from.- passphrase
If
public_key_sourceis an encrypted private key, specify its passphrase here.