Configuration¶
In this section, we describe the necessary configuration of HashiCorp Vault such that it can be used as a SCION CPPKI Certificate Authority backend by the Anapaya appliance. We also list deployment considerations that an operator should be aware of.
Vault cluster¶
The Vault cluster is an integral part of the CA architecture. It should be deployed with support for individual Vault node failure. This can be achieved by deploying multiple Vault instances in a cluster. (see: High Availability Mode)
Vault can be run on top of various different databases that provide the storage layer. However, for simplicity, we suggest that Vault is run using the integrated storage.
Note
A Vault setup with a single Vault instance can also work. However, in general we recommend a redundant setup.
Authentication Setup¶
The Anapaya appliance (via the CA adapter) needs to authenticate itself with
Vault to gain access to the target endpoints. For this, the AppRole
authentication method must be
enabled, and the appropriate roles need to be provisioned. Each CA adapter
should get its own individual identity and role_id
, such that access to
individual Anapaya appliances can be revoked without affecting the remaining
appliances.
Each CA adapter should get the right policy assigned, such that it can access the correct Vault PKI Engine and the Key/Value Engine.
To take advantage of the policies that are listed in Policies, the Vault
identity for the CA adapter needs to have the isd_as
with the ISD-AS number
in its metadata. To do this, execute the following steps:
Create a Vault identity for the CA adapter, one identity per adapter instance.
The suggested name pattern is of the form
ca-adapter_<isd-as>-<instance-id>
. The metadata should include the keyisd_as
with the ISD-AS number as the value and the identity should have the CA Adapter Policy attached to it. Use the /identity/entity endpoint to create the identities.Create a Vault AppRole for each CA adapter instance.
The suggested name pattern is
ca-adapter_<isd-as>-<instance-id>
. Use the /auth/approle/role/:role_name endpoint.Create a Vault entity alias that links the AppRole and the identity together.
Create an alias so that once you log in with the AppRole you are automatically assigned the entity. For this, you will need the following information:
role ID of the CA adapter. Get this with the /auth/approle/role/:role_name/role-id endpoint. (
data.role_id
in the response body)identity ID of the CA adapter identity. Get this with the /identity/entity/name/:name endpoint. (
data.id
in the response body)accessor ID of the AppRole authentication engine. Get this with the /sys/auth endpoint. (
.["approle/"].accessor
in the response body)
Then, link the AppRole to the identity by creating an alias using the /identity/entity-alias endpoint. The
name
is set to the role ID, thecanonical_id
is set to the identity ID, and themount_accessor
is set to the accessor ID.Extract the
role_id
andsecret_id
of the created AppRole(s) to configure the Anapaya appliance where the instance of the CA adapter should run. To read thesecret_id
, you can use the /auth/approle/role/:role_name/secret-id endpoint.
Secrets Engine Setup¶
In this section, we describe the different Vault Secrets Engines that are required for the Vault to act as a CA backend.
PKI Engine¶
Docs: https://www.vaultproject.io/docs/secrets/pki
The PKI engine is the core of the CA backend. It stores the currently active SCION CPPKI CA certificate and the associated private key, and is used to issue the renewed certificates.
Create one active PKI engine per SCION CA AS that is backed by the Vault
backend. Each CA adapter only has access to the PKI engine for their respective
ISD-AS. The currently active PKI engine is mounted at /ca/<isd-as>/pki
. The
CA adapter will use the /ca/<isd-as>/sign-verbatim
endpoint to request the
certificate issuance based on the CSR that it received from the customer AS. For
example, the PKI engine for AS 1-ff00:0:110
is mounted at
/ca/1-ff00:0:110/pki
and the CA adapter will use the endpoint
/ca/1-ff00:0:110/pki/sign-verbatim
to request the certificate issuance.
We suggest that each PKI engine is only ever associated with exactly one CA certificate. This allows for a clean history of what SCION CPPKI AS certificates were issued with any given SCION CPPKI CA certificate. To achieve this, we recommend the Rolling CA Provision Strategy.
Key/Value Engine¶
Docs: https://www.vaultproject.io/docs/secrets/kv/kv-v2
The key/value engine is used to keep the state for our CA adapter. For verification of the request, the CA adapter needs the currently active TRC (and potentially the TRC that is currently in the grace period). Furthermore, the CA adapter needs access to the blocklist that allows operators to manually block certain ASes, and prevent them from renewing their certificate.
Again, mount one instance per SCION CPPKI CA AS at /ca/<isd-as>/kv
. For
example, the key/value engine for AS 1-ff00:0:110
is mounted at
/ca/1-ff00:0:110/kv
. When enabling the Vault storage mount at
ca/<isd-as>/kv
, version 2 must be selected.
Note
We require version 2 of the key/value engine in vault. Follow the vault setup documentation and ensure you are using the right version.
/ca/<isd-as>/kv/data/trcs
hosts the TRCs for the local ISD.The TRCs are keyed by the following pattern
ISD<isd>-B<base>-S<serial>
. The value must be a PEM encoded TRC. For example, the TRC ISD1-B1-S1 is expected to be located at/ca/<isd-as>/kv/data/trcs/ISD1-B1-S1
. Additionally, the latest TRC must be located at/ca/<isd-as>/kv/data/trcs/latest
.The CA adapter uses the TRCs to verify the signatures on the CSRs that are received from the customer AS. It will first look up the latest TRC. If the latest TRC implies that the predecessor TRC is still in the grace period, it will additionally look up that predecessor TRC at the keyed path.
/ca/<isd-as>/kv/data/blocklist
hosts the blocklist.For each AS that is on the blocklist, an entry in the KV storage is required. The data of the entry can be empty, the presence is enough to block an AS. For example to put
1-ff00:0:111
into the blocklist, it suffices to post on the pathca/<isd-as>/kv/data/blocklist/1-ff00:0:111
. To check if1-ff00:0:111
is on the blocklist, read from the same path. If the status code is404
the item is not on the blocklist, if the status code is200
, the item is blocked.The CA adapter uses this blocklist every time it gets a CSR to decide whether a certificate should be issued, or whether the request should be denied.
Policies¶
Each role gets its individual policy. Each policy should grant the role the minimal set of capabilities for proper operation.
CA Adapter Policy¶
The CA adapter should only get access to the endpoints belonging to its own
ISD-AS. We can leverage identity.entity.metadata.isd_as
to ensure this. The
metadata is set as part of the AppRole creation for the CA adapter. The CA
adapter should get the following policy associated with its role:
# The sign-verbatim endpoint is required to sign new AS certificates.
path "ca/{{identity.entity.metadata.isd_as}}/pki/sign-verbatim" {
capabilities = ["create", "update"]
}
# TRCs are required in the CA adapter to verify requests.
path "ca/{{identity.entity.metadata.isd_as}}/kv/data/trcs/+" {
capabilities = ["read"]
}
# Blocklist is required in the CA adapter to validate requests.
path "ca/{{identity.entity.metadata.isd_as}}/kv/data/blocklist/+" {
capabilities = ["read"]
}
# The CA adapter needs to login via approle to get a token for the other endpoints.
path "auth/approle/login" {
capabilities = ["create", "update"]
}
CA Provisioning Policy¶
The exact policy for the CA provisioning is dependent on its implementation. To support the Rolling CA Provision Strategy, the following should be part of the policy:
# The CA provision task needs to be able to configure the CA certificate.
path "ca/+/+/config/ca" {
capabilities = ["create", "update"]
}
# The CA provision task needs to be able to create new mounts.
path "sys/mounts/ca/+/+" {
capabilities = ["create", "update", "delete"]
}
# The CA provision task needs to be able to remount old CAs.
path "sys/remount" {
capabilities = ["create", "update", "sudo"]
allowed_parameters = {
"from" = ["ca/*"]
"to" = ["ca/*"]
}
}
# The CA provision task needs to be able to tune the newly create PKI engine
path "sys/mounts/ca/+/+/tune" {
capabilities = ["create", "update"]
allowed_parameters = {
"default_lease_ttl" = []
"max_lease_ttl" = []
"force_no_cache" = [false]
"options" = []
}
}
Manual intervention¶
The exact policy for manual intervention depends on the capabilities an operator should have in order to intervene. The following is a suggestion with a potentially useful capability set for an operator.
# Provision, list and read TRCs.
patch "ca/+/kv/data/trcs/+" {
capabilities = ["read", "create", "update"]
}
# Add, list, and delete entities from the blocklist.
patch "ca/+/kv/data/blocklist/+" {
capabilities = ["read", "create", "update", "delete"]
}
# Manually sign certificates.
path "ca/+/pki/sign-verbatim" {
capabilities = ["create", "update"]
}
# Manually provision CA certificate.
path "ca/+/pki/config/ca" {
capabilities = ["create", "update"]
}
# Manually run garbage collection
path "ca/+/pki/tidy" {
capabilities = ["create", "update"]
}