saltext.vault.utils.vault.pki

Vault PKI helpers

Added in version 1.1.0.

saltext.vault.utils.vault.pki.check_cert_for_changes(current: str, issuer: str, private_key: str | None, csr: str | None, encoding: Literal['pem', 'pkcs7_pem', 'der', 'pkcs7_der'] = 'pem', sign_verbatim: bool = False, *, alt_names: dict[str, str | list[str]] | list[str] | None, append_chain: list[Certificate] | None, common_name: str | None, exclude_cn_from_sans: bool, expire_tolerance: int | str | None, ext_key_usage: list[str] | str | None, ext_key_usage_oids: list[str] | str | None, key_usage: list[str] | str | None, not_after: str | None, private_key_passphrase: str | None, role_info: dict[str, Any] | None, serial_number: str | None, ttl: int, urls: Mapping[Literal['issuing_certificates', 'crl_distribution_points', 'delta_crl_distribution_points', 'ocsp_servers'], list[str]] | None, user_ids: list[str] | str | None, **kwargs) tuple[dict[str, Any], dict[str, Any], dict[str, Any]][source]

Check whether an existing on-disk leaf certificate matches expected parameters.

Returns a tuple of (changes, unverified_url_exts, unverified_role_attrs). The second item is only populated when urls is None and contains changes to URL-derived extensions, which cannot be verified without access to the URL configuration. The third item is only populated when role_info is None and contains changes to role-derived subject attributes/extensions, which cannot be verified without access to the role configuration.

current

Path of the existing certificate on disk.

issuer

Issuer certificate.

private_key

Path of the private key on disk/encoded private key.

csr

Path of the CSR on disk/encoded CSR.

encoding

Requested certificate encoding. Defaults to pem.

sign_verbatim

Whether the sign-verbatim endpoint is used. Defaults to false.

alt_names

Requested Subject Alternative Names.

append_chain

List of certificates to append. Fails with der encoding.

common_name

Subject CN name attribute.

exclude_cn_from_sans

Whether the subject CN should be included in the SANs (either as email or dns type). Has no effect when sign_verbatim is true.

expire_tolerance

Otherwise called ttl_remaining, minimum TTL to allow before requesting a fresh certificate.

ext_key_usage

When sign_verbatim is true, default Extended Key Usages if the CSR carries none.

ext_key_usage_oids

When sign_verbatim is true, additional OIDs for the default Extended Key Usages if the CSR carries none.

key_usage

When sign_verbatim is true, default Key Usages if the CSR carries none.

not_after

Absolute value of the Not After field of the certificate in UTC format YYYY-MM-ddTHH:MM:SSZ. When set, ttl is ignored.

private_key_passphrase

Passphrase for private_key

role_info

Return value of read_role. Pass None if a role is used, but its configuration could not be read, in which case role-derived subject attributes and extensions are not verified and their drift is reported separately instead of triggering a reissuance.

serial_number

Single value for the subject SERIALNUMBER (OID: 2.5.4.5) name attribute (NOT the certificate’s serial number!).

ttl

Requested Time To Live, already normalized to integer-valued seconds.

urls

Dictionary of issuer/mount-default authority URLs, which end up in the AuthorityInformationAccess, CRLDistributionPoints and FreshestCRL extensions. Pass None if the URL configuration could not be read, in which case the corresponding extensions are not verified and their drift is reported separately instead of triggering a reissuance.

user_ids

List of User ID (UID) subject attributes. Each one is added to the generated CSR’s subject Name as a distinct RDN.

kwargs

All other kwargs passed to the cert signing endpoint or as CSR generation params.

saltext.vault.utils.vault.pki.check_root_issuer_for_changes(current, *, alt_names: dict[str, str | list[str]] | list[str] | None, common_name: str, country: list[str] | str | None, days_remaining: int, days_valid: int, exclude_cn_from_sans: bool, excluded_alt_names: dict[str, str | list[str]] | list[str] | None, key_usage: list[str] | str | None, locality: list[str] | str | None, max_path_length: int, not_after: str | None, not_before_duration: str | int, organization: list[str] | str | None, ou: list[str] | str | None, permitted_alt_names: dict[str, str | list[str]] | list[str] | None, postal_code: list[str] | str | None, province: list[str] | str | None, replace_key: bool, rotate_key: bool, signature_bits: int, street_address: list[str] | str | None, serial_number: str | None, urls: Mapping[Literal['issuing_certificates', 'crl_distribution_points', 'delta_crl_distribution_points', 'ocsp_servers'], list[str]] | None) tuple[dict[str, Any], dict[str, Any]][source]

Check whether an existing root CA issuer certificate matches expected parameters.

Returns a tuple of (changes, url_ext_drift). Only changes in the first item warrant a rotation by themselves since URL-derived extensions are functionally irrelevant on a self-signed certificate.

When a rotation is triggered otherwise, the drift is included in changes since the reissued certificate picks up the current URL configuration.

current

Existing certificate text.

alt_names

Requested Subject Alternative Names.

common_name

Subject CN (commonName) name attribute.

country

Subject C (countryName) name attribute(s).

days_remaining

Minimum TTL in days to allow before requesting a fresh certificate.

days_valid

Requested Time To Live in integer days.

exclude_cn_from_sans

Whether the subject CN should be included in the SANs (either as email or dns type).

excluded_alt_names

List of alternative names for which certificates are not allowed to be issued or signed by this CA certificate.

key_usage

List of key usages to add to the existing set of key usages (CRLSign,CertSign).

locality

Subject L (localityName) name attribute(s).

max_path_length

Basic Constraints pathlen parameter.

not_after

Absolute value of the Not After field of the certificate in UTC format YYYY-MM-ddTHH:MM:SSZ. When set, days_valid is ignored.

not_before_duration

Duration by which to backdate the NotBefore property.

organization

Subject O (organizationName) name attribute(s).

ou

Subject OU (organizationalUnitName) name attribute(s).

permitted_alt_names

List of alternative names for which certificates are allowed to be issued or signed by this CA certificate.

postal_code

Subject postalCode name attribute(s).

province

Subject ST (stateOrProvinceName) name attribute(s).

signature_bits

Number of bits to use in the signature algorithm. Valid: 256 (SHA-2-256), 384 (SHA-2-384), 512 (SHA-2-512).

street_address

Subject street (streetAddress) name attribute(s).

serial_number

Single value for the subject SERIALNUMBER (OID: 2.5.4.5) name attribute (NOT the certificate’s serial number!).

urls

Dictionary of issuer/mount-default authority URLs, which end up in the AuthorityInformationAccess, CRLDistributionPoints and FreshestCRL extensions. Pass None if the mount’s URL configuration could not be read, in which case the corresponding extensions are not verified.

saltext.vault.utils.vault.pki.check_ca_cert_for_changes(current: str, issuer: str, private_key: str | None, private_key_passphrase: str | None, csr: str | None, sign_verbatim: bool, *, alt_names: dict[str, str | list[str]] | list[str] | None, append_chain: list[Certificate] | None, common_name: str | None, country: list[str] | str | None, encoding: Literal['pem', 'pkcs7_pem', 'der', 'pkcs7_der'], exclude_cn_from_sans: bool, excluded_alt_names: dict[str, str | list[str]] | list[str] | None, key_usage: list[str] | str | None, locality: list[str] | str | None, max_path_length: int | None, not_after: str | None, not_before_duration: str | int, organization: list[str] | str | None, ou: list[str] | str | None, permitted_alt_names: dict[str, str | list[str]] | list[str] | None, postal_code: list[str] | str | None, province: list[str] | str | None, serial_number: str | None, signature_bits: int, street_address: list[str] | str | None, ttl: int, ttl_remaining: str | int, urls: Mapping[Literal['issuing_certificates', 'crl_distribution_points', 'delta_crl_distribution_points', 'ocsp_servers'], list[str]] | None, **kwargs) tuple[dict[str, Any], dict[str, Any]][source]

Check whether an existing on-disk CA certificate matches expected parameters.

Returns a tuple of (changes, unverified_url_exts). The second item is only populated when urls is None and contains changes to URL-derived extensions, which cannot be verified without access to the URL configuration.

current

Path of the existing certificate on disk.

issuer

Issuer certificate.

private_key

Path of the private key on disk/encoded private key.

private_key_passphrase

Passphrase for private_key

csr

Path of the CSR on disk/encoded CSR.

sign_verbatim

Whether the sign-verbatim endpoint is used. Defaults to false.

alt_names

Requested Subject Alternative Names.

append_chain

List of certificates to append. Fails with der encoding.

common_name

Subject CN name attribute.

country

Subject C (countryName) name attribute(s).

encoding

Requested certificate encoding. Defaults to pem.

exclude_cn_from_sans

Whether the subject CN should be included in the SANs (either as email or dns type). Has no effect when sign_verbatim is true.

excluded_alt_names

List of alternative names for which certificates are not allowed to be issued or signed by this CA certificate.

key_usage

List of key usages to add to the existing set of key usages (CRLSign,CertSign).

locality

Subject L (localityName) name attribute(s).

max_path_length

Basic Constraints pathlen parameter.

not_after

Absolute value of the Not After field of the certificate in UTC format YYYY-MM-ddTHH:MM:SSZ. When set, ttl is ignored.

not_before_duration

Duration by which to backdate the NotBefore property.

organization

Subject O (organizationName) name attribute(s).

ou

Subject OU (organizationalUnitName) name attribute(s).

permitted_alt_names

List of alternative names for which certificates are allowed to be issued or signed by this CA certificate.

postal_code

Subject postalCode name attribute(s).

province

Subject ST (stateOrProvinceName) name attribute(s).

serial_number

Single value for the subject SERIALNUMBER (OID: 2.5.4.5) name attribute (NOT the certificate’s serial number!).

signature_bits

Number of bits to use in the signature algorithm. Valid: 256 (SHA-2-256), 384 (SHA-2-384), 512 (SHA-2-512).

street_address

Subject street (streetAddress) name attribute(s).

ttl

Requested Time To Live, already normalized to integer-valued seconds.

ttl_remaining

Minimum TTL to allow before requesting a fresh certificate.

urls

Dictionary of issuer/mount-default authority URLs, which end up in the AuthorityInformationAccess, CRLDistributionPoints and FreshestCRL extensions. Pass None if the URL configuration could not be read, in which case the corresponding extensions are not verified and their drift is reported separately instead of triggering a reissuance.

kwargs

All other kwargs passed to the cert signing endpoint or as CSR generation params.

saltext.vault.utils.vault.pki.check_int_issuer_cert_for_changes_vault_ca(current: str, issuer: str, *, days_remaining: str | int, rotate_key: bool, replace_key: bool, days_valid: int, common_name: str | None, country: list[str] | str | None, exclude_cn_from_sans: bool, key_usage: list[str] | str | None, locality: list[str] | str | None, max_path_length: int | None, normalized_sans: dict[str, list[str]] | None, norm_excluded_nc: dict[str, list[str]] | None, norm_permitted_nc: dict[str, list[str]] | None, not_after: str | None, not_before_duration: str | int, organization: list[str] | str | None, ou: list[str] | str | None, postal_code: list[str] | str | None, province: list[str] | str | None, serial_number: str | None, signature_bits: int, street_address: list[str] | str | None, urls: Mapping[Literal['issuing_certificates', 'crl_distribution_points', 'delta_crl_distribution_points', 'ocsp_servers'], list[str]] | None) tuple[dict[str, Any], dict[str, Any]][source]

Check whether an existing intermediate CA issuer certificate matches expected parameters.

Returns a tuple of (changes, unverified_url_exts). The second item is only populated when urls is None and contains changes to URL-derived extensions, which cannot be verified without access to the URL configuration.

current

Existing certificate text.

issuer

Issuer certificate.

days_remaining

Minimum TTL in days to allow before requesting a fresh certificate.

rotate_key

Whether issuing a modified certificate should cause the key to be replaced.

replace_key

Whether the key is going to change for sure.

days_valid

Requested Time To Live in integer days.

common_name

Subject CN name attribute.

country

Subject C (countryName) name attribute(s).

exclude_cn_from_sans

Whether the subject CN should be included in the SANs (either as email or dns type). Has no effect when sign_verbatim is true.

key_usage

List of key usages to add to the existing set of key usages (CRLSign,CertSign).

locality

Subject L (localityName) name attribute(s).

max_path_length

Basic Constraints pathlen parameter.

normalized_sans

Requested Subject Alternative Names, already normalized.

norm_excluded_nc

List of alternative names for which certificates are not allowed to be issued or signed by this CA certificate.

norm_permitted_nc

List of alternative names for which certificates are allowed to be issued or signed by this CA certificate, already normalized..

not_after

Absolute value of the Not After field of the certificate in UTC format YYYY-MM-ddTHH:MM:SSZ. When set, ttl is ignored.

not_before_duration

Duration by which to backdate the NotBefore property.

organization

Subject O (organizationName) name attribute(s).

ou

Subject OU (organizationalUnitName) name attribute(s).

postal_code

Subject postalCode name attribute(s).

province

Subject ST (stateOrProvinceName) name attribute(s).

serial_number

Single value for the subject SERIALNUMBER (OID: 2.5.4.5) name attribute (NOT the certificate’s serial number!).

signature_bits

Number of bits to use in the signature algorithm. Valid: 256 (SHA-2-256), 384 (SHA-2-384), 512 (SHA-2-512).

street_address

Subject street (streetAddress) name attribute(s).

urls

Dictionary of issuer/mount-default authority URLs, which end up in the AuthorityInformationAccess, CRLDistributionPoints and FreshestCRL extensions. Pass None if the URL configuration could not be read, in which case the corresponding extensions are not verified and their drift is reported separately instead of triggering a rotation.

saltext.vault.utils.vault.pki.check_int_issuer_cert_for_changes_salt_ca(current: str, *, rotate_key: bool, replace_key: bool, signing_policy_contents: dict[str, Any], days_remaining: int, not_after: str | None, **kwargs) dict[str, Any][source]

Check whether an existing Vault intermediate issuer certificate that should be issued via x509_v2 matches expected parameters.

Note that this function expects that norm_generate_intermediate_params() has already parsed the inputs.

current

Path of the existing certificate on disk.

rotate_key

Whether issuing a modified certificate should cause the key to be replaced.

replace_key

Whether the key is going to change for sure.

signing_policy_contents

Pass the result of calling x509.get_signing_policy with the received values for ca_server and signing_policy, if any.

days_remaining

Minimum TTL in days to allow before requesting a fresh certificate.

kwargs

All passed/rendered arguments for x509.create_certificate.

saltext.vault.utils.vault.pki.not_valid_after(cert: Certificate) datetime[source]

Return a certificate’s not_valid_after property as a timezone-aware datetime, accounting for older versions of cryptography.

saltext.vault.utils.vault.pki.norm_sans(sans: dict[str, list[str]] | dict[str, str | list[str]] | list[str], *, allow_other_name: bool = True) dict[str, list[str]][source]

Normalize all allowed input structures for SubjectAlternativeNames (alt_names parameter) or NameConstraints (permitted_alt_names, excluded_alt_names) into a dict of lists with uppercase keys.

sans

User input. Can be specified either as dict ({ "<type>": "<value>" }), a dict of lists ({ "<type>": ["<value1>", "<value2>", ...] }) or list of SAN strings (["<type1>:<value1>", ...]).

<type> can be dns, email, uri, ip or any OID for otherName SANs (unless allow_other_name is false). <value> is the corresponding value. Note that otherName SANs need to omit UTF8:.

allow_other_name

Whether to parse unknown <type> values as otherName SAN OIDs. When false, raises an exception for types other than dns, email, uri and ip. Intended to parse General Names for the NameConstraints extension.

saltext.vault.utils.vault.pki.split_sans(sans: dict[str, list[str]]) tuple[list[str], list[str], list[str], list[str]][source]

Render a normalized dict of lists of GeneralNames for the subjectAltName extension into a format Vault understands and return each type separately. Returns a tuple of (dns_or_email_sans, ip_sans, uri_sans, other_sans).

sans

Normalized dict of lists ({"<type>": ["<value>", ...]}) as output by norm_sans().

saltext.vault.utils.vault.pki.split_name_constraints(sans: dict[str, list[str]]) tuple[list[str], list[str], list[str], list[str]][source]

Render a normalized dict of lists of GeneralNames for the nameConstraints extension into a format Vault understands and return each type separately. Returns a tuple of (dns_nc, email_nc, ip_nc, uri_nc).

sans

Normalized dict of lists ({"<type>": ["<value>", ...]}) as output by norm_sans() with allow_other_name being false.

saltext.vault.utils.vault.pki.split_csr_kwargs(kwargs: dict[str, Any], allow: Sequence[str] | None = None) tuple[dict[str, Any], dict[str, Any]][source]

Split known parameters for x509.create_csr from a dict of passed keyword arguments. Returns a tuple of (csr_args, extra_args).

kwargs

Keyword arguments passed to the function.

allow

List of additional keyword arguments to allow for CSR kwargs. Most are allowed by default, but e.g. subject is not.

saltext.vault.utils.vault.pki.sync_verbatim_csr_subject(csr_args: dict[str, Any], *, serial_number: str | None, user_ids: list[str] | str | None) dict[str, Any][source]

Ensure user_ids and serial_number work when signing a leaf certificate verbatim.

saltext.vault.utils.vault.pki.norm_intermediate_params(csr_args: dict[str, ~typing.Any], *, csr: str | ~cryptography.hazmat.bindings._rust.x509.CertificateSigningRequest | None, sign_verbatim: bool, country: list[str] | str | None, province: list[str] | str | None, locality: list[str] | str | None, street_address: list[str] | str | None, postal_code: list[str] | str | None, organization: list[str] | str | None, ou: list[str] | str | None, common_name: str | None, serial_number: str | None, alt_names: dict[str, list[str]] | dict[str, str | list[str]] | list[str] | None, key_usage: list[str] | str | None, permitted_alt_names: dict[str, list[str]] | dict[str, str | list[str]] | list[str] | None, excluded_alt_names: dict[str, list[str]] | dict[str, str | list[str]] | list[str] | None, subject_format: type[str] | type[dict] | type[list] = <class 'str'>) tuple[dict[str, Any], dict[str, list[str]], dict[str, list[str]], dict[str, list[str]]][source]

Synchronize parameters for the sign-intermediate endpoint with those for the x509_v2 modules, normalize them and warn about ignored ones.

Returns CSR/cert generation arguments, normalized alt_names/permitted_alt_names/excluded_alt_names.

subject_format

By default, we normalize subject parameters into a string that exactly replicates what Vault would have created. This works well for CSR generation, which is used in sign_intermediate.

This function is also utilized for generate_intermediate, which creates certificates that might be subject to signing policies that define parts of the subject. The internal merging completely overwrites a string-valued subject parameter in that case.

Set this to dict to create a subject dictionary that is merged with a dict from the signing policy, but does not support multiple values for a single OID, postal_code or a custom, Vault-like order.

Set this to list to create an ordered list of RDN strings, which is also understood by the x509_v2 modules. If the signing_policy defines a list of RDN strings itself, they are prepended to this list (i.e. appended when visualizing the rfc4514 string representation of the DN). (unused at the moment since it’s a bit unintuitive, but could recreate Vault subjects much more faithfully)

saltext.vault.utils.vault.pki.norm_generate_intermediate_params(kwargs: dict[str, Any], vault_signed: bool, *, country: list[str] | str | None, province: list[str] | str | None, locality: list[str] | str | None, street_address: list[str] | str | None, postal_code: list[str] | str | None, organization: list[str] | str | None, ou: list[str] | str | None, common_name: str | None, serial_number: str | None, alt_names: dict[str, list[str]] | dict[str, str | list[str]] | list[str] | None, key_usage: list[str] | str | None, permitted_alt_names: dict[str, list[str]] | dict[str, str | list[str]] | list[str] | None, excluded_alt_names: dict[str, list[str]] | dict[str, str | list[str]] | list[str] | None, max_path_length: int | None, not_after: str | None) tuple[dict[str, Any], str | None, dict[str, list[str]] | None, dict[str, list[str]] | None, dict[str, list[str]] | None][source]

Normalize/synchronize parameters for our custom generate_intermediate function and warn about ignored ones. Returns certificate generation arguments, normalized not_after/alt_names/permitted_alt_names/excluded_alt_names.

saltext.vault.utils.vault.pki.get_ski(cert: str | bytes | Certificate) str | None[source]

Get a certificate’s subjectKeyIdentifier in pretty hex.