# pki

The `pki` command groups subcommands for interacting with Vault's PKI Secrets Engine.

### Syntax <a href="#syntax" id="syntax"></a>

Option flags for a given subcommand are provided after the subcommand, but before the arguments.

### Example health check <a href="#example-health-check" id="example-health-check"></a>

To health check a mount, use the `vault pki health-check <mount>` command:

```mdx-code-blocks_codeBlockMargin__TI7B4
$ vault pki health-check pki
ca_validity_period
------------------
status    endpoint                                            message
------    --------                                            -------
ok        /pki/issuer/da41ffb1-cc6d-5a5c-f147-e4d7beeb1b73    Issuer's validity (2032-12-17) is OK

... more output elided ...
```

### Example verify sign <a href="#example-verify-sign" id="example-verify-sign"></a>

To verify the signature between two issuer certificates, use the `vault pki verify-sign <parent> <child>` command:

```shell-session
$ vault pki verify-sign pki_root/issuer/root pki_int/issuer/FirstDepartment
issuer:pki_root/issuer/root
issued:pki_int/issuer/FirstDepartment

field              value
-----              -----
subject_match      true
path_match         true
trust_match        true
key_id_match       true
signature_match    true
```

### Example list child issuers <a href="#example-list-child-issuers" id="example-list-child-issuers"></a>

To list intermediate certificates potentially issued by a certificate inside vault, use the `vault pki list-intermediates <parent>` command:

```shell-session
$ vault pki list-intermediates /pki_root/issuer/default
intermediate                                             match?
------------                                             ------
pki_int_2/issuer/d4404ccc-3ad4-83a9-f5df-398637654b3b    true
pki_int_2/issuer/db0b0a6c-6641-ac15-363a-4e5261315581    true
pki_root/issuer/9464c4fe-e8a6-d96a-0566-021575e7382c     true
pki_int/issuer/2f958ec5-1838-336e-331b-07032379b958      true
pki_int/issuer/b8cc0b41-e0e9-1a92-12c4-6849c9d6f837      true
```

### Example issue <a href="#example-issue" id="example-issue"></a>

To issue a new issuer certificate, use the `vault pki issue <parent-certificate-path> <mount>` command:

```shell-session
$ vault pki issue -issuer_name="FirstDepartment" /pki_root/issuer/default /pki_int/ common_name="first-department.example.com"
Key                               Value
---                               -----
ca_chain                          [-----BEGIN CERTIFICATE-----
MIIDsDCCApigAwIBAgIULEPuHTW7UDtAQg+qcc18osNWgZIwDQYJKoZIhvcNAQEL...
```

### Example reissue <a href="#example-reissue" id="example-reissue"></a>

To reissue an issuer certificate, using the same fields as an existing issuer template, use the `vault pki reissue <parent-certificate-path> <template> <mount>` command:

```shell-session
$ vault pki reissue -issuer_name="SecondDepartment" /pki_root/issuer/default /pki_int/issuer/FirstDepartment /pki_int_2/ common_name="second-department.example.com"
Key                               Value
---                               -----
ca_chain                          [-----BEGIN CERTIFICATE-----
MIID0DCCArigAwIBAgIUdfRe05B5eRXsg3pvsJ/g94eYuWkwDQYJKoZIhvcNAQEL
```

## pki health-check <a href="#pki-health-check" id="pki-health-check"></a>

The `pki health-check` command verifies the health of the given PKI secrets engine mount against an optional configuration.

This runs with the permissions of the given token, reading various APIs from the mount and `/sys` against the given Vault server

Mounts need to be specified with any namespaces prefixed in the path, e.g., `ns1/pki`.

### Examples <a href="#examples" id="examples"></a>

Performs a basic health check against the `pki-root` mount:

```shell-session
$ vault pki health-check pki-root/
```

Configuration can be specified using the `-health-config` flag:

```shell-session
$ vault pki health-check -health-config=mycorp-root.json pki-root/
```

Using the `-list` flag will show the list of health checks and any known configuration values (with their defaults) that will be run against this mount:

```shell-session
$ vault pki health-check -list pki-root/
```

### Usage <a href="#usage" id="usage"></a>

The following flags are unique to this command:

* `-default-disabled` - When specified, results in all health checks being disabled by default unless enabled by the configuration file explicitly. The default is `false`, meaning all default-enabled health checks will run.
* `-health-config` `(string: "")` - Path to JSON configuration file to modify health check execution and parameters.
* `-list` - When specified, no health checks are run, but all known health checks are printed. Still requires a positional mount argument. The default is `false`, meaning no listing is printed and health checks will execute.
* `-return-indicator` `(string: "default")` - Behavior of the return value (exit code) of this command:
  * `permission`, for exiting with a non-zero code when the tool lacks permissions or has a version mismatch with the server;
  * `critical`, for exiting with a non-zero code when a check returns a critical status in addition to the above;
  * `warning`, for exiting with a non-zero status when a check returns a warning status in addition to the above;
  * `informational`, for exiting with a non-zero status when a check returns an informational status in addition to the above;
  * `default`, for the default behavior based on severity of message and only returning a zero exit status when all checks have passed and no execution errors have occurred.

This command respects the `-format` parameter to control the presentation of output sent to stdout. Fatal errors that prevent health checks from executing may not follow this formatting.

### Return status and output <a href="#return-status-and-output" id="return-status-and-output"></a>

This command returns the following exit codes:

* `0` - Everything is good.
* `1` - Usage error (check CLI parameters).
* `2` - Informational message from a health check.
* `3` - Warning message from a health check.
* `4` - Critical message from a health check.
* `5` - A version mismatch between health check and Vault Server occurred, preventing one or more health checks from being fully run.
* `6` - A permission denied message was returned from Vault Server for one or more health checks.

Note that an exit code of `5` (due to a version mismatch) is not necessarily fatal to the health check. For example, the `crl_validity_period` health check will return an invalid version warning when run against Vault 1.11 as no Delta CRL exists for this version of Vault, but this will not impact its ability to check the complete CRL.

Each health check outputs one or results in a list. This list contains a mapping of keys (`status`, `status_code`, `endpoint`, and `message`) to values returned by the health check. An endpoint may occur in more than one health check and is not necessarily guaranteed to exist on the server (e.g., using wildcards to indicate all matching paths have the same result). Tabular form elides the status code, as this is meant to be consumed programatically.

These correspond to the following health check status values:

* status `not_applicable` / status code `0`: exit code `0`.
* status `ok` / status code `1`: exit code `0`
* status `informational` / status code `2`: exit code `2`.
* status `warning` / status code `3`: exit code `3`.
* status `critical` / status code `4`: exit code `4`.
* status `invalid_version` / status code `5`: exit code `5`.
* status `insufficient_permissions` / status code `6`: exit code `6`.

### Health checks <a href="#health-checks" id="health-checks"></a>

The following health checks are currently implemented. More health checks may be added in future releases and may default to being enabled.

#### CA validity period <a href="#ca-validity-period" id="ca-validity-period"></a>

**Name**: `ca_validity_period`

**Accessed APIs**:

* `LIST /issuers` (unauthenticated)
* `READ /issuer/:issuer_ref/json` (unauthenticated)

**Config Parameters**:

* `root_expiry_critical` `(duration: 182d)` - for a duration within which the root's lifetime is considered critical
* `intermediate_expiry_critical` `(duration: 30d)` - for a duration within which the intermediate's lifetime is considered critical
* `root_expiry_warning` `(duration: 365d)` - for a duration within which the root's lifetime is considered warning
* `intermediate_expiry_warning` `(duration: 60d)` - for a duration within which the intermediate's lifetime is considered warning
* `root_expiry_informational` `(duration: 730d)` - for a duration within which the root's lifetime is considered informational
* `intermediate_expiry_informational` `(duration: 180d)` - for a duration within which the intermediate's lifetime is considered informational

This health check will check each issuer in the mount for validity status, returning a list. If a CA expires within the next 30 days, the result will be critical. If a root CA expires within the next 12 months or an intermediate CA within the next 2 months, the result will be a warning. If a root CA expires within 24 months or an intermediate CA within 6 months, the result will be informational.

**Remediation steps**:

1. Perform a CA rotation operation to check for CAs that are about to expire.
2. Migrate from expiring CAs to new CAs.
3. Delete any expired CAs with one of the following options:

* Run tidy manually with `vault write <mount>/tidy tidy_expired_issuers=true`.
* Use the Vault API to call delete issuer.

#### CRL validity period <a href="#crl-validity-period" id="crl-validity-period"></a>

**Name**: `crl_validity_period`

**Accessed APIs**:

* `LIST /issuers` (unauthenticated)
* `READ /config/crl` (optional)
* `READ /issuer/:issuer_ref/crl` (unauthenticated)
* `READ /issuer/:issuer_ref/crl/delta` (unauthenticated)

**Config Parameters**:

* `crl_expiry_pct_critical` `(int: 95)` - the percentage of validity period after which a CRL should be considered critically close to expiry
* `delta_crl_expiry_pct_critical` `(int: 95)` - the percentage of validity period after which a Delta CRL should be considered critically close to expiry

This health check checks each issuer's CRL for validity status, returning a list. Unlike CAs, where a date-based duration makes sense due to effort required to successfully rotate, rotating CRLs are much easier, so a percentage based approach makes sense. If the chosen percentage exceeds that of the `grace_period` from the CRL configuration, an informational message will be issued rather than OK.

For informational purposes, it reads the CRL config and suggests enabling auto-rebuild CRLs if not enabled.

**Remediation steps**:

Use `vault write` to enable CRL auto-rebuild:

```shell-session
$ vault write <mount>/config/crl auto_rebuild=true
```

#### Hardware-Backed root certificate <a href="#hardware-backed-root-certificate" id="hardware-backed-root-certificate"></a>

**Name**: `hardware_backed_root`

**APIs**:

* `LIST /issuers` (unauthenticated)
* `READ /issuer/:issuer_ref`
* `READ /key/:key_ref`

**Config Parameters**:

* `enabled` `(boolean: false)` - defaults to not being run.

This health check checks issuers for root CAs backed by software keys. While Vault is secure, for production root certificates, we'd recommend the additional integrity of KMS-backed keys. This is an informational check only. When all roots are KMS-backed, we'll return OK; when no issuers are roots, we'll return not applicable.

#### Root certificate issued Non-CA leaves <a href="#root-certificate-issued-non-ca-leaves" id="root-certificate-issued-non-ca-leaves"></a>

**Name**: `root_issued_leaves`

**APIs**:

* `LIST /issuers` (unauthenticated)
* `READ /issuer/:issuer_ref/pem` (unauthenticated)
* `LIST /certs`
* `READ /certs/:serial` (unauthenticated)

**Config Parameters**:

* `certs_to_fetch` `(int: 100)` - a quantity of leaf certificates to fetch to see if any leaves have been issued by a root directly.

This health check verifies whether a proper CA hierarchy is in use. We do this by fetching `certs_to_fetch` leaf certificates (configurable) and seeing if they are a non-issuer leaf and if they were signed by a root issuer in this mount. If one is found, we'll issue a warning about this, and recommend setting up an intermediate CA.

**Remediation steps**:

1. Restrict the use of `sign`, `sign-verbatim`, `issue`, and ACME APIs against the root issuer.
2. Create an intermediary issuer in a different mount.
3. Have the root issuer sign the new intermediary issuer.
4. Issue new leaf certificates using the intermediary issuer.

#### Role allows implicit localhost issuance <a href="#role-allows-implicit-localhost-issuance" id="role-allows-implicit-localhost-issuance"></a>

**Name**: `role_allows_localhost`

**APIs**:

* `LIST /roles`
* `READ /roles/:name`

**Config Parameters**: (none)

Checks whether any roles exist that allow implicit localhost based issuance (`allow_localhost=true`) with a non-empty `allowed_domains` value.

**Remediation steps**:

1. Set `allow_localhost` to `false` for all roles.
2. Update the `allowed_domains` field with an explicit list of allowed localhost-like domains.

#### Role allows Glob-Based wildcard issuance <a href="#role-allows-glob-based-wildcard-issuance" id="role-allows-glob-based-wildcard-issuance"></a>

**Name**: `role_allows_glob_wildcards`

**APIs**:

* `LIST /roles`
* `READ /roles/:name`

**Config Parameters**:

* `allowed_roles` `(list: nil)` - an allow-list of roles to ignore.

Check each role to see whether or not it allows wildcard issuance **and** glob domains. Wildcards and globs can interact and result in nested wildcards among other (potentially dangerous) quirks.

**Remediation steps**:

1. Split any role that need both of `allow_glob_domains` and `allow_wildcard_certificates` to be true into two roles.
2. Continue splitting roles until both of the following are true for all roles:
   * The role has `allow_glob_domains` **or** `allow_wildcard_certificates`, but not both.
   * Roles with `allow_glob_domains` **and** `allow_wildcard_certificates` are the only roles required for **all** SANs on the certificate.
3. Add the roles that allow glob domains and wildcards to `allowed_roles` so Vault ignores them in future checks.

#### Role sets `no_store=false` and performance <a href="#role-sets-no_store-false-and-performance" id="role-sets-no_store-false-and-performance"></a>

**Name**: `role_no_store_false`

**APIs**:

* `LIST /roles`
* `READ /roles/:name`
* `LIST /certs`
* `READ /config/crl`

**Config Parameters**:

* `allowed_roles` `(list: nil)` - an allow-list of roles to ignore.

Checks each role to see whether `no_store` is set to `false`.

Vault will provide warnings and performance will suffer if you have a large number of certificates without temporal CRL auto-rebuilding and set \`no\_store\` to \`true\`.

**Remediation steps**:

1. Update none-ACME roles with `no_store=false`. **NOTE**: Roles used for ACME issuance must have `no_store` set to `true`.
2. Set your certificate lifetimes as short as possible.
3. Use BYOC revocations to revoke certificates as needed.

#### Accessibility of audit information <a href="#accessibility-of-audit-information" id="accessibility-of-audit-information"></a>

**Name**: `audit_visibility`

**APIs**:

* `READ /sys/mounts/:mount/tune`

**Config Parameters**:

* `ignored_parameters` `(list: nil)` - a list of parameters to ignore their HMAC status.

This health check checks whether audit information is accessible to log consumers, validating whether our list of safe and unsafe audit parameters are generally followed. These are informational responses, if any are present.

**Remediation steps**:

Use `vault secrets tune` to set the desired audit parameters:

```shell-session
$ vault secrets tune \
  -audit-non-hmac-response-keys=certificate \
  -audit-non-hmac-response-keys=issuing_ca \
  -audit-non-hmac-response-keys=serial_number \
  -audit-non-hmac-response-keys=error \
  -audit-non-hmac-response-keys=ca_chain \
  -audit-non-hmac-request-keys=certificate \
  -audit-non-hmac-request-keys=issuer_ref \
  -audit-non-hmac-request-keys=common_name \
  -audit-non-hmac-request-keys=alt_names \
  -audit-non-hmac-request-keys=other_sans \
  -audit-non-hmac-request-keys=ip_sans \
  -audit-non-hmac-request-keys=uri_sans \
  -audit-non-hmac-request-keys=ttl \
  -audit-non-hmac-request-keys=not_after \
  -audit-non-hmac-request-keys=serial_number \
  -audit-non-hmac-request-keys=key_type \
  -audit-non-hmac-request-keys=private_key_format \
  -audit-non-hmac-request-keys=managed_key_name \
  -audit-non-hmac-request-keys=managed_key_id \
  -audit-non-hmac-request-keys=ou \
  -audit-non-hmac-request-keys=organization \
  -audit-non-hmac-request-keys=country \
  -audit-non-hmac-request-keys=locality \
  -audit-non-hmac-request-keys=province \
  -audit-non-hmac-request-keys=street_address \
  -audit-non-hmac-request-keys=postal_code \
  -audit-non-hmac-request-keys=permitted_dns_domains \
  -audit-non-hmac-request-keys=policy_identifiers \
  -audit-non-hmac-request-keys=ext_key_usage_oids \
  -audit-non-hmac-request-keys=csr \
   <mount>
```

#### ACL policies allow problematic endpoints <a href="#acl-policies-allow-problematic-endpoints" id="acl-policies-allow-problematic-endpoints"></a>

**Name**: `policy_allow_endpoints`

**APIs**:

* `LIST /sys/policy`
* `READ /sys/policy/:name`

**Config Parameters**:

* `allowed_policies` `(list: nil)` - a list of policies to allow-list for access to insecure APIs.

This health check checks whether unsafe access to APIs (such as `sign-intermediate`, `sign-verbatim`, and `sign-self-issued`) are allowed. Any findings are a critical result and should be rectified by the administrator or explicitly allowed.

#### Allow If-Modified-Since requests <a href="#allow-if-modified-since-requests" id="allow-if-modified-since-requests"></a>

**Name**: `allow_if_modified_since`

**APIs**:

* `READ /sys/internal/ui/mounts`

**Config Parameters**: (none)

This health check verifies if the `If-Modified-Since` header has been added to `passthrough_request_headers` and if `Last-Modified` header has been added to `allowed_response_headers`. This is an informational message if both haven't been configured, or a warning if only one has been configured.

**Remediation steps**:

1. Update `allowed_response_headers` and `passthrough_request_headers` for all policies with `vault secrets tune`:

   ```shell-session
   $ vault secrets tune \
       -passthrough-request-headers="If-Modified-Since" \
       -allowed-response-headers="Last-Modified" \
       <mount>
   ```
2. Update ACME-specific headers with `vault secrets tune` (if you are using ACME):

   ```shell-session
   $ vault secrets tune \
       -passthrough-request-headers="If-Modified-Since" \
       -allowed-response-headers="Last-Modified" \
       -allowed-response-headers="Replay-Nonce" \
       -allowed-response-headers="Link" \
       -allowed-response-headers="Location" \
       <mount>
   ```

#### Auto-Tidy disabled <a href="#auto-tidy-disabled" id="auto-tidy-disabled"></a>

**Name**: `enable_auto_tidy`

**APIs**:

* `READ /config/auto-tidy`

**Config Parameters**:

* `interval_duration_critical` `(duration: 7d)` - the maximum allowed interval\_duration to hit critical threshold.
* `interval_duration_warning` `(duration: 2d)` - the maximum allowed interval\_duration to hit a warning threshold.
* `pause_duration_critical` `(duration: 1s)` - the maximum allowed pause\_duration to hit a critical threshold.
* `pause_duration_warning` `(duration: 200ms)` - the maximum allowed pause\_duration to hit a warning threshold.

This health check verifies that auto-tidy is enabled, with sane defaults for interval\_duration and pause\_duration. Any disabled findings will be informational, as this is a best-practice but not strictly required, but other findings w\.r.t. `interval_duration` or `pause_duration` will be critical/warnings.

**Remediation steps**

Use `vault write` to enable auto-tidy with the recommended defaults:

```shell-session
$ vault write <mount>/config/auto-tidy \
    enabled=true \
    tidy_cert_store=true \
    tidy_revoked_certs=true \
    tidy_acme=true \
    tidy_revocation_queue=true \
    tidy_cross_cluster_revoked_certs=true \
    tidy_revoked_cert_issuer_associations=true
```

#### Tidy hasn't run <a href="#tidy-hasn-t-run" id="tidy-hasn-t-run"></a>

**Name**: `tidy_last_run`

**APIs**:

* `READ /tidy-status`

**Config Parameters**:

* `last_run_critical` `(duration: 7d)` - the critical delay threshold between when tidy should have last run.
* `last_run_warning` `(duration: 2d)` - the warning delay threshold between when tidy should have last run.

This health check verifies that tidy has run within the last run window. This can be critical/warning alerts as this can start to seriously impact Vault's performance.

**Remediation steps**:

1. Schedule a manual run of tidy with `vault write`:

   ```shell-session
   $ vault write <mount>/tidy \
       tidy_cert_store=true \
       tidy_revoked_certs=true \
       tidy_acme=true \
       tidy_revocation_queue=true \
       tidy_cross_cluster_revoked_certs=true \
       tidy_revoked_cert_issuer_associations=true
   ```
2. Review the tidy status endpoint, `vault read <mount>/tidy-status` for additional information.
3. Re-configure auto-tidy based on the log information and results of your manual run.

#### Too many certificates <a href="#too-many-certificates" id="too-many-certificates"></a>

**Name**: `too_many_certs`

**APIs**:

* `READ /tidy-status`
* `LIST /certs`

**Config Parameters**:

* `count_critical` `(int: 250000)` - the critical threshold at which there are too many certs.
* `count_warning` `(int: 50000)` - the warning threshold at which there are too many certs.

This health check verifies that this cluster has a reasonable number of certificates. Ideally this would be fetched from tidy's status or a new metric reporting format, but as a fallback when tidy hasn't run, a list operation will be performed instead.

**Remediation steps**:

1. Verify that tidy ran recently with `vault read`:

   ```shell-session
   $ vault read <mount>/tidy-status
   ```
2. Schedule a manual run of tidy with `vault write`:

   ```shell-session
   $ vault write <mount>/tidy \
     tidy_cert_store=true \
     tidy_revoked_certs=true \
     tidy_acme=true \
     tidy_revocation_queue=true \
     tidy_cross_cluster_revoked_certs=true \
     tidy_revoked_cert_issuer_associations=true
   ```
3. Enable `auto-tidy`.
4. Make sure that you are not renewing certificates too soon. Certificate lifetimes should reflect the expected usage of the certificate. If the TTL is set appropriately, most certificates renew at approximately 2/3 of their lifespan.
5. Consider setting the `no_store` field for all roles to `true` and use BYOC revocations to avoid storage.

#### Enable ACME issuance <a href="#enable-acme-issuance" id="enable-acme-issuance"></a>

**Name**: `enable_acme_issuance`

**APIs**:

* `READ /config/acme`
* `READ /config/cluster`
* `LIST /issuers` (unauthenticated)
* `READ /issuer/:issuer_ref/json` (unauthenticated)

**Config Parameters**: (none)

This health check verifies that ACME is enabled within a mount that contains an intermediary issuer, as this is considered a best-practice to support a self-rotating PKI infrastructure.

Review the ACME Certificate Issuance API documentation to learn about enabling ACME support in Vault.

#### ACME response headers <a href="#acme-response-headers" id="acme-response-headers"></a>

**Name**: `allow_acme_headers`

**APIs**:

* `READ /sys/internal/ui/mounts`

**Config Parameters**: (none)

This health check verifies if the `"Replay-Nonce`, `Link`, and `Location` headers have been added to `allowed_response_headers`, when the ACME feature is enabled. The ACME protocol will not work if these headers are not added to the mount.

**Remediation steps**:

Use `vault secrets tune` to add the missing headers to `allowed_response_headers`:

```shell-session
$ vault secrets tune \
  -allowed-response-headers="Last-Modified" \
  -allowed-response-headers="Replay-Nonce" \
  -allowed-response-headers="Link" \
  -allowed-response-headers="Location" \
  <mount>
```

## pki verify-sign <a href="#pki-verify-sign" id="pki-verify-sign"></a>

This command verifies whether the listed issuer has signed the listed issued certificate.

This command returns five fields of information:

* `signature_match`: was the key of the issuer used to sign the issued.
* `path_match`: the possible issuer appears in the valid certificate chain of the issued.
* `key_id_match`: does the key id of the issuer match the key\_id of the subject.
* `subject_match`: does the subject name of the issuer match the issuer subject of the issued.
* `trust_match`: if someone trusted the parent issuer, is the chain provided sufficient to trust the child issued.

### Usage <a href="#usage" id="usage"></a>

Usage: `vault pki verify-sign <parent> <child>`

* `<parent>` is the fully name-spaced path to the issuer certificate which will be used to verify the `<child>` certificate
* `<child>` is the fully name-spaced path to the potential child-certificate to be verified

A fully namespaced path looks like, for instance, 'ns1/mount1/issuer/issuerName/json'.

### Example <a href="#example" id="example"></a>

```shell-session
$ vault pki verify-sign pki_root/issuer/root pki_int/issuer/FirstDepartment
issuer:pki_root/issuer/root
issued:pki_int/issuer/FirstDepartment

field              value
-----              -----
subject_match      true
path_match         true
trust_match        true
key_id_match       true
signature_match    true
```

## pki list-intermediates <a href="#pki-list-intermediates" id="pki-list-intermediates"></a>

This command determines which of a list of certificates were issued by a given parent certificate.

### Usage <a href="#usage" id="usage"></a>

Usage: `vault pki list-intermediates [flags] <parent> [child] [child] [child...`

Lists the set of intermediate CAs issued by this parent issuer.

* `[flags]` listed below determine the type of match required between the `<parent>` and each potential child, and the type of output
* `<parent>` is the certificate that might be the issuer which everything is verified against.
* `[child]` is an optional path to a certificate to be compared to the `<parent>`, or pki mounts to look for certificates on. If `[child]` is omitted entirely, the list will be constructed from all accessible pki mounts.

This returns a list of issuing certificates and whether they are a match. By default, the type of match required is whether the `<parent>` has the expected subject, authority/subject key id match, and could have (directly) signed this issuer. The match criteria can be updated by changed the corresponding flag.

#### Flags <a href="#flags-1" id="flags-1"></a>

* `-use_names` `(bool: "false")` - this determines how issuers are referred to in the output, whether by issuer\_id (the default), or by their name, or status as default issuer (when use\_names is true)

The following flags determine what sorts of relationship between the parent and potential child issuers are considered a match.

* `-subject_match` `(bool: "true")` - determines whether the subject of the parent-issuer must match the issuer of the potential child for this to be considered a match
* `-key_id_match` `(bool: "true")` - determines whether the identifier of the parent-issuer must match the IUI of the potential child for this to be considered a match
* `-direct_verify` `(bool: "true")` - determines whether it is required for this to be a match that someone trusting the parent certificate would trust the potential-child certificate (without any more information)
* `-indirect-sign` `(bool: "true")` - determines whether it is required for this to be a match that if someone trusted the first certificate, they would trust the potential-child certificate (using the certificate chains available)
* `-path_contains` `(bool: "false")` - determines whether it is required for this to be a match for the ca\_chain of the potential child certificate to contain the parent certificate

#### Accessed APIs <a href="#accessed-apis" id="accessed-apis"></a>

Note that the vault user running this command will need to have access to the following API endpoints, each representing a step in the process:

* `READ /:parent`
* `LIST /sys/mounts` - when no `[child]` argument is provided, this is used to find a list of pki mounts
* `LIST /:child_mount/issuers/` - when no `[child]` argument is provided, or the `[child]` argument is a mount rather than an issuer, this is used to find a list of pki issuers on the mount
* `READ /:child` - each potential child issuer is read for comparison against the parent

### Examples <a href="#examples" id="examples"></a>

```shell-session
$ vault pki list-intermediates /pki_root/issuer/default
intermediate                                             match?
------------                                             ------
pki_int_2/issuer/d4404ccc-3ad4-83a9-f5df-398637654b3b    true
pki_int_2/issuer/db0b0a6c-6641-ac15-363a-4e5261315581    true
pki_root/issuer/9464c4fe-e8a6-d96a-0566-021575e7382c     true
pki_int/issuer/2f958ec5-1838-336e-331b-07032379b958      true
pki_int/issuer/b8cc0b41-e0e9-1a92-12c4-6849c9d6f837      true
```

## pki issue <a href="#pki-issue" id="pki-issue"></a>

This command creates a intermediate certificate authority certificate signed by the `<parent>` in the `<child_mount>`, using the options to determine the fields on that certificate.

### Usage <a href="#usage" id="usage"></a>

Usage: `vault pki issue [flags] <parent> <child_mount> [options]`

* `[flags]` are optional arguments described below
* `<parent>` is the fully qualified path of the Certificate Authority in vault which will issue the new intermediate certificate.
* `<child_mount>` is the path of the mount in vault where the new issuer is saved.
* `[options]` are the superset of the k=v options passed to generate-intermediate-csr and sign-intermediate commands. At least one option must be set. See below.

#### Flags <a href="#flags-1" id="flags-1"></a>

* `-type` `(string: "internal")` - This determines the type of key use for the newly created certificate. Valid types are `"existing"` - where we link to a key already present in the vault-backend to be used (and expect option arguments `"key_ref"`) - `"internal"` - to generate a new key for this certificate - or `"kms"` - to link to an external key. Exported keys are not available through this API.
* `-issuer_name` `(string: "")` - If present, the newly created issuer will be given this name.

#### Options <a href="#options-1" id="options-1"></a>

Other than `type` (which is passed as a flag, see above), this command accepts all options provided to the Generate CSR and Sign Intermediate endpoints.

#### Accessed APIs <a href="#accessed-apis" id="accessed-apis"></a>

Note that the vault user running this command will need to have access to the following API endpoints, each representing a step in the process:

* `READ /:parent` - used to check validity
* `WRITE /:child_mount/intermediate/generate/:type` - used to generate the csr
* `WRITE /:parent/sign-intermediate` - used to sign the csr
* `WRITE /:child_mount/issuers/import/cert` - used to import the new issuer, and the issuer chain
* `UPDATE /:child_mount/issuer/:issuer_refs` - used to both name the new issuer, and also set the name of the parent in the issuer chain
* `READ /:child_mount/issuer/:new_issuer_ref` - used to verify completion, generate the output

### Examples <a href="#examples" id="examples"></a>

```shell-session
$ vault pki issue -issuer_name="FirstDepartment" /pki_root/issuer/default /pki_int/ common_name="first-department.example.com"
Key                               Value
---                               -----
ca_chain                          [-----BEGIN CERTIFICATE-----
MIIDsDCCApigAwIBAgIULEPuHTW7UDtAQg+qcc18osNWgZIwDQYJKoZIhvcNAQEL...
```

## pki reissue <a href="#pki-reissue" id="pki-reissue"></a>

Frequently, a reissued CA certificate is to be very similar to another. This command enables reissuing a CA, using an existing issuer within Vault as a template, but allowing modifications to the desired attributes.

### Usage <a href="#usage" id="usage"></a>

Usage: `vault pki reissue [flags] <parent> <template> <child_mount> [options]`

* `[flags]` are optional arguments described below.
* `<parent>` is the fully qualified path of the Certificate Authority in vault which will issue the new intermediate certificate.
* `<template>` is the fully qualified path of an intermediate certificate in vault which will be used to populate certificate fields not overridden by `[options]`.

**Note**: not all possible certificate fields are supported by Vault, and this template reader covers only those vault generates as a best effort. If unknown fields are set, such as when an external CA was imported into Vault, there may not be a warning that those are missing from the new issuer.

* `<child_mount>` is the path of the mount in vault where the new issuer is saved.
* `[options]` are the superset of the k=v options passed to generate/intermediate and sign-intermediate commands. See below.

The output of this command when it is successful is to read the resulting new issuer entry.

#### Flags <a href="#flags-1" id="flags-1"></a>

* `-type` `(string: "internal")` - This determines the type of key use for the newly created certificate. Valid types are `"existing"` - where we link to a key already present in the vault-backend to be used - `"internal"` - to generate a new key for this certificate - or `"kms"` - to link to an external key. Exported keys are not available through this API.

**Note**: It is only possible to generate a new certificate with an existing key that exists in the same mount where that key-material exists. This command is expected to fail should the template exist on a different mount, `existing` is the selected type, and no `key_ref` for a key in the new issuer mount is provided.

* `-issuer_name` `(string: "")` - If present, the newly created issuer will be given this name.

#### Options <a href="#options-1" id="options-1"></a>

Other than `type` (which is passed as a flag, see above), this command accepts all options provided to the Generate CSR and Sign Intermediate endpoints.

#### Accessed APIs <a href="#accessed-apis" id="accessed-apis"></a>

Note that the vault user running this command will need to have access to the following API endpoints, each representing a step in the process:

* `READ /:parent` - used to check validity
* `READ /:template` - used to generate the options for the new certificate
* `WRITE /:child_mount/intermediate/generate/:type` - used to generate the csr
* `WRITE /:parent/sign-intermediate` - used to sign the csr
* `WRITE /:child_mount/issuers/import/cert` - used to import the new issuer, and the issuer chain
* `UPDATE /:child_mount/issuer/:issuer_refs` - used to both name the new issuer, and also set the name of the parent in the issuer chain
* `READ /:child_mount/issuer/:new_issuer_ref` - used to verify completion, generate the output

### Examples <a href="#examples" id="examples"></a>

````shell-session
$ vault pki reissue -issuer_name="SecondDepartment" /pki_root/issuer/default /pki_int/issuer/FirstDepartment /pki_int_2/ common_name="second-department.example.com"
Key                               Value
---                               -----
ca_chain                          [-----BEGIN CERTIFICATE-----
MIID0DCCArigAwIBAgIUdfRe05B5eRXsg3pvsJ/g94eYuWkwDQYJKoZIhvcNAQEL```
````


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.enclaive.cloud/vault/cli/pki.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
