Skip to content

Commit

Permalink
Add documentation on CIEPS protocol (#22398)
Browse files Browse the repository at this point in the history
* Add documentation on CIEPS protocol

Signed-off-by: Alexander Scheel <[email protected]>

* Update website/content/docs/secrets/pki/cieps.mdx

Co-authored-by: Steven Clark <[email protected]>

* Update website/content/docs/secrets/pki/cieps.mdx

Co-authored-by: Steven Clark <[email protected]>

* Fix indentation, link to Vault SDK

Signed-off-by: Alexander Scheel <[email protected]>

---------

Signed-off-by: Alexander Scheel <[email protected]>
Co-authored-by: Steven Clark <[email protected]>
  • Loading branch information
cipherboy and stevendpclark authored Aug 17, 2023
1 parent 5ab5369 commit 7d361ee
Show file tree
Hide file tree
Showing 3 changed files with 327 additions and 0 deletions.
314 changes: 314 additions & 0 deletions website/content/docs/secrets/pki/cieps.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,314 @@
---
layout: docs
page_title: Certificate Issuance External Policy (CIEPS) | PKI - Secrets Engines
description: An overview of the Certificate Issuance External Policy (CIEPS) protocol
---

# PKI secrets engine - Certificate Issuance External Policy Service (CIEPS) <EnterpriseAlert inline="true" />

This document covers high-level architecture and service APIs used by the
Vault PKI Secrets Engine when communicating with the Certificate Issuance
External Policy Service (CIEPS) <EnterpriseAlert inline="true" />.

## What is Certificate Issuance External Policy Service (CIEPS)?

Hashicorp Vault's PKI Secrets Engine has a mechanism for issuing leaf
certificates with arbitrary structure: [`/pki/sign-verbatim`](/vault/api-docs/secret/pki#sign-verbatim).
This requires an organization to run an application/user-accessible service
for authenticating, authorizing, and validating certificate issuance requests
(potentially handling key pair generation as well), before asking PKI to sign
the resulting CSR and leaf certificate with its own highly-privileged Vault
token. If any attribute is missing from the original requester's CSR, the
original service must reject the request as `sign-verbatim` does not give the
controlling service the ability to modify the request.

The Certificate Issuance External Policy Service (CIEPS) <EnterpriseAlert inline="true" />
protocol solves this by placing the validation and certificate templating
gated behind the PKI, solving:

1. **Auditing**, so the original requester is still identified and both the
original request and subsequent response are tracked.
2. **Central access**, so applications only need to use a new URL for
requesting certificates.
3. **Certificate modification**, so customization of the requester's
submission can be exposed to this external service.
4. **External validation**, when compared to the Role-based system, as the
CIEPS implementation can reach out to customer-defined external systems
for validation.

Either of these two mechanisms allow an organization to leverage the Vault
PKI Secrets Engine to build their own flexible issuance control architecture,
leveraging Vault as a PKI-as-a-Service platform. However, CIEPS grants far
greater control to the organization than the `sign-verbatim` approach.

### Custom policy with `sign-verbatim`

With `sign-verbatim`, the policy validation service must sit in front of
Vault, processing requests from the user (which cannot use Vault
authentication and needs to authenticate themselves separately to this
service). This RA service then handles its own authentication to Vault,
which provides the signing capabilities via the PKI plugin.

When the application retains control over its own key material by providing
a CSR, the policy service cannot modify the requested CSR and thus cannot
modify the resulting certificate. It can only approve or deny requests
without allowing operators to hide implementation details from calling
applications. This is because PKI's `sign-verbatim` endpoint lacks the
ability for the Vault API caller (in this case, the fronting policy service)
to modify the certificate independent of the provided CSR.

If, however, the policy service can control key material (and this is an
acceptable risk to the organization), the policy service could modify requests
on behalf of the calling application. However, this still requires the
external application to know how to authenticate to this external policy
service.

Additionally, to ensure compatibility with Vault, this policy service (and its
developers) would need to add support for the ACME protocol. For any new
protocols Vault supports in the future, this service would also need to
implement support to retain compatibility.

### Custom policy with Certificate Issuance External Policy Service (CIEPS)

With CIEPS, users still authenticate to Vault and use the normal request
workflow to sign and issue certificates, including via ACME. However,
Vault's PKI Engine reaches out to the configured CIEPS implementation to
validate and template the requested certificate, transparently from the
calling application.

Notably, the application can opt to either retain full control over its key
material or delegate key creation to the trusted Vault service, with no impact
on the functionality CIEPS can provide. The CIEPS service can be scoped to
respond to requests from either a single PKI mount or multiple, getting
information about the requesting user and the Vault PKI instance from the
CIEPS messages.

Because the CIEPS service only needs knowledge of validating requests and
templating the final certificate structure, its developers need only be
concerned with the business policy logic and not broader PKI concerns (such
as generating key material or re-implementing support for other issuance
protocols).

## Certificate Issuance External Policy Service (CIEPS) webhook format

The CIEPS protocol is a REST-based, optionally mTLS protected webhook. The
external service configuration specifies the single URL that Vault will POST
the formatted CIEPS request to. When the CIEPS service is unavailable (either
due to misconfiguration or outage), Vault will reject the request and it is
up to the client to retry the request at a later time.

For convenience, Go versions of these structs are available [from the Vault
SDK](https://github.com/hashicorp/vault/blob/main/sdk/helper/certutil/cieps.go).

### Vault to CIEPS request format

This document outlines CIEPS request/response version 1.

Using the `application/json` content type, Vault will post the following
request body as a JSON object:

- `request_version` `(int: 1)` - The version of the CIEPS request sent by
Vault; a compatible response format is expected.

- `request_uuid` `(string)` - A random UUID which serves to identify this
request. This value must be sent in the response.

- `synchronous` `(bool: true)` - A boolean indicating whether the request is
synchronous or not. Presently set to true; no asynchronous response is
understood.

- `user_request_key_values` `(map[string]interface{})` - The unvalidated
request parameters sent by the user. It is up to the CIEPS service to
validate these prior to using them. The following fields may be present,
including any other fields submitted by the user:

- `csr` `(string)` - A PEM format CSR submitted either by the client (
in the case of `/sign` or ACME requests) or on the client's behalf
(in the case of `/issue` requests, where key material is generated
by Vault).

- `identity_request_key_values` `(map[string]interface{})` - Values related
to the user's identity. When the request type is ACME, this value is not
populated. These are:

- `entity_id` `(string)` - The entity identifier from the request after
authentication.

- `entity` `(map[string]interface{})` - The entire resolved `logical.Entity`
of the user after authentication; subject to change by the
`entity_jmsepath` parameter in the configuration.

- `groups` `([]map[string]interface{})` - The set of resolved
`logical.Groups` of the user after authentication; subject to change by
the `group_jmsepath` parameter in the configuration.

~> **Note**: in the event that the direct token backend or a root token is
used, entity information may not exist. In either case,
`identity_request_key_values` will be omitted.

- `acme_request_key_values` `(map[string]interface{})` - Values related to
ACME authorizations challenges attached to the finished order. Only present
when the request type is ACME. These are:

- `authorizations` `(map[string]interface{})` - Authorizations and
challenges solved by the client to move this order to the finalization
state.

- `account` `(map[string]interface{})` - Information related to the ACME
account issuing the request. These are:

- `id` `(string)` - The UUID of the ACME account.

- `directory` `(string)` - The path to the ACME directory requested by
this account.

- `contact` `([]string)` - Unverified contact information submitted by
the requesting ACME account on creation.

- `created_date` `(string: RFC 3999 format)` - Timestamp when the account
was created.

- `eab` `(map[string]interface{}, optional)` - When present, the details
of the EAB used to authorize this account via Vault authentication. If
not present, this ACME account was created without EAB bindings.

- `key_id` `(string)` - Identifier of the EAB binding used by this
account.

- `key_type` `(string)` - Key type of the EAB binding used by this
account.

- `created_date` `(string: RFC 3999 format)` - Timestamp when the
account was created.

- `vault_request_values` `(map[string]interface{})` - Request value validated
or created by Vault. These have higher trust than the unvalidated
`user_request_key_values`. These are:

- `policy_name` `(string: "")` - The optional policy name specified by the
requester. When the issuance mode is not ACME (or if it was ACME and EAB
was enforced), this has been validated by Vault's ACL system.

- `mount` `(string)` - The request's mount path as known by the PKI plugin.

- `namespace` `(string)` - The request's namespace the mount path exists
within as known by the PKI plugin.

- `vault_is_performance_standby` `(bool)` - Asserted when this requesting
node is a standby node. When the service indicates storage is required in
its response, Vault will forward the user's HTTP request up to an active
node, requiring it to re-submit the CIEPS request. In this case, if the
service knows it must always store certificates and sees a request from
a standby node, it can skip policy and template evaluation or cache the
results for a second pass.

- `vault_is_performance_secondary` `(bool)` - Asserted when this requesting
node is from a performance secondary versus the primary cluster.

- `issuance_mode` `(string: "sign", "issue", "ica", or "acme")` - The type
of the request: whether a REST call to `/external-policy/sign(/:policy)`,
to `/external-policy/issue(/:policy)`, `/external-policy/sign-intermediate(/:policy)`,
or an ACME request, respectively.

- `vault_generated_private_key` `(bool)` - Whether or not Vault generated
the key material behind this request. Set to true when
`issuance_mode="issue"` only presently.

- `requested_issuer_name` `(string)` - Name of the user's requested issuer;
can be changed by modifying the response `issuer_ref` value.

- `requested_issuer_id` `(string)` - UUID of the user's requested issuer;
can be changed by modifying the response `issuer_ref` value.

- `requested_issuer_cert` `(string)` - PEM format certificate of the user's
requested issuer; can be changed by modifying the response `issuer_ref`
value.

- `requested_issuance_config` `(map[string]interface{})` - Configuration
used for leaf certificate issuance. These are:

- `aia_values` `(map[string]interface{})` - AIA values (CA, CRL, and
OCSP) for the suggested issuer. These may differ from the actual values
used for issuance of this request if `issuer_ref` is set on the response.

- `leaf_not_after_behavior` `(string: "err", "truncate", or "permit")` - leaf
validity period behavior for the suggested issuer.

- `mount_default_ttl` `(string)` - Suggested default TTL set on mount tuning.

- `mount_max_ttl` `(string)` - Suggested maximum TTL set on the mount tuning.

### CIEPS to Vault response format

The CIEPS engine must reply to this POST response with a `200 OK` status,
regardless of whether a certificate should be issued or not. Redirects will
not be followed by Vault; any proxy or load balancing functionality should be
strictly transparent to the caller. Any verbatim message returned by a non-200
status code will not be returned, either in Vault server logs or to the user.

In the response to the above request, only one of the `certificate` or `error`
fields should be specified. In the event both `certificate` and `error` are
present, the `error` will be appended to the returned `warnings` and the
`certificate` will be issued.

Using the `application/json` content type, the server should reply with the
following JSON object:

- `request_uuid` `(string)` - The random UUID which the server used to
identify this request.

- `error` `(string, optional)` - The error message to be returned to the
user about why their request failed. Only one of the `error` or
`certificate` response parameters should be specified.

- `warnings` `([]string, optional)` - Optional warnings to be returned to the user
about minor issues with their request.

- `certificate` `(string, optional)` - A PEM format certificate to be signed
by the Vault service. Only one of the `error` or `certificate` response
parameters should be specified.

- `issuer_ref` `(string)` - The issuer reference to use to sign this request.
If the user's issuer choice (in `requested_issuer_id`) is OK, this must
be set in this field.

- `store_certificate` `(bool: false)` - Whether or not to store the signed
certificate.

- `generate_lease` `(bool: false)` - Whether or not Vault should generate an
associated lease for the certificate. Note that to generate a lease,
`store_certificate` also needs to be set to `true`, otherwise no lease
will be generated.

The certificate's signature will be ignored and replaced by a signature created
by the specified issuer. If a signature algorithm compatible with this issuer
is specified on the certificate, it will be preserved; otherwise, the default
signature algorithm for this issuer's key type will be used.

The certificate's AIA information will be replaced by the information from the
specified issuer, if present, else the global AIA URLs will be set, replacing
the AIA URIs and CRL distribution point extensions. Additionally, the
Authority Key Identifier extension will be replaced by the issuer's Subject
Key Identifier extension value as mandated by RFC 5280.

## Tutorial

Refer to the following tutorials for PKI secrets engine usage examples:

- [Build Your Own Certificate Authority (CA)](/vault/tutorials/secrets-management/pki-engine)
- [Build Certificate Authority (CA) in Vault with an offline Root](/vault/tutorials/secrets-management/pki-engine-external-ca)
- [Enable ACME with PKI secrets engine](/vault/tutorials/secrets-management/pki-acme-caddy)
- [PKI Secrets Engine with Managed Keys](/vault/tutorials/enterprise/managed-key-pki)
- [PKI Unified CRL and OCSP With Cross Cluster
Revocation](/vault/tutorials/secrets-management/pki-unified-crl-ocsp-cross-cluster)
- [Configure Vault as a Certificate Manager in Kubernetes with
Helm](/vault/tutorials/kubernetes/kubernetes-cert-manager)
- [Generate mTLS Certificates for Nomad using
Vault](/vault/tutorials/secrets-management/vault-pki-nomad)


## API

The PKI secrets engine has a full HTTP API. Please see the
[PKI secrets engine API](/vault/api-docs/secret/pki) for more
details.
4 changes: 4 additions & 0 deletions website/content/docs/secrets/pki/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ The PKI Secrets Engine documentation is split into the following pieces:
Engine.
- [Rotation Primitives](/vault/docs/secrets/pki/rotation-primitives) - A document
which explains different types of certificates used to achieve rotation.
- [CIEPS Protocol <EnterpriseAlert inline="true" />](/vault/docs/secrets/pki/cieps) - A
document which explains the Certificate Issuance External Policy Service (CIEPS)
protocol (request and response structure), along with an overview of the difference
between it and `/pki/sign-verbatim`.

## Tutorial

Expand Down
9 changes: 9 additions & 0 deletions website/data/docs-nav-data.json
Original file line number Diff line number Diff line change
Expand Up @@ -1385,6 +1385,15 @@
{
"title": "Rotation Primitives",
"path": "secrets/pki/rotation-primitives"
},
{
"title": "Certificate Issuance External Policy Service (CIEPS)",
"badge": {
"text": "ENTERPRISE",
"type": "outlined",
"color": "neutral"
},
"path": "secrets/pki/cieps"
}
]
},
Expand Down

0 comments on commit 7d361ee

Please sign in to comment.