# Vault

# Resource Paths

Everything in Vault is path-based. Most path identifiers can utilize forward-slash (/) separators to create hierarchy.

For example, the KV secrets engine is mounted at the /secret top-level path. Any access to a secret resource in the vault must begin with the /secret top-level path, followed by lower-specificity path sections to identify the resource.

The most basic secret is a one-level path, such as recipes. The recipes secret can be accessed with a path of: /secret/data/recipes. Thus, a full HTTP API URL to read the recipes secret is https://vault.example.com:8200/v1/secret/data/recipes:

curl --insecure --header "X-Vault-Token: <TOKEN>" https://vault.example.com:8200/v1/secret/data/recipes

While working with secrets is the most common task in Vault, everything else is also path-based, including policies, auth methods, and so forth.

# Vault Secret Paths

Solarix Vault adopts a naming scheme similar to Solarix Resource Names (SRN), modified to meet the conventions of Vault's path-based structure and usability. A quick reminder that a SRN is a unique identifier using tags in a lowest-to-highest order of specificity:

srn:service:org[:project][:app][:environment]::resource-type[/resource-id]

Since Vault secrets are much more dynamic than the resources represented by SRNs, naming conventions in Vault can be less strict, but it is strongly recommended to follow some basic conventions:

  • Drop the srn and service tags. Vault secrets are inherently associated with a org/project/app/environment, which is already tied to a specific service within the Solarix architecture.
  • Use forward-slash (/) path tag separators instead of SRN colons (:).
  • Explicit resource-ids can typically be left out of the secret path and defined as a key value in the secret data object.

Thus, a Vault Secret Path (VSP) should have the following format, with optional tags shown in brackets ([]):

org[/project][/app][/environment][/resource-type]

Here are the basic definitions of each tag type with a few examples:

  • org Required - Organizational entity. Typically, this is an internal org name, a client name, or individual user name (e.g. solarix, voyager, wcasg, raritan, gabe, kyle, etc).
  • project Optional - Name of the overall project or internal grouping (e.g. widget, core, etc).
  • app Optional - Specific application or repository (e.g. domains, dashboard, tracker, connector, etc).
  • environment Optional - Environment in which this resource resides (e.g. development, testing, staging, or production).
  • resource-type Optional - Represents the Type of resource (e.g. instance, security group, vpc, subnet, pem, cert, db, cache, etc).

Any further tag specificity can typically be defined as a JSON object key attached to this secret path.

For example, consider adding a private SSH key for this Hermes documentation project. It belongs to the solarix organization, is a core project, and is called the hermes app. It also has only a single environment of production. Therefore, the full VSP to store secrets for this resource would be: solarix/core/hermes/production

In the JSON data we can define our private SSH key value:

{
  "ssh-private-key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQs8ghShDnbjlcFSQuPBrjAlg+aAxTfaIuQQL6Bz0eqi\nv9LAh9GvYwonJrfYkvU+CR50xhoNlkrZk87zUDNeLrTAZO9y6SwgYnoAyUFmX96\n8+FmoETIUCjoUgAa1A58AAYL4LtwgAv6HGanu3ogyYvl55j9YJCR2BDFKGuyYI\nyzHhzuHO7+eTbaQywpqNqFNaVGXY4HDGwhHtqnAHrz2niEiQi6Dpk+YJDdwQeHIg\n...\n-----END RSA PRIVATE KEY-----"
}

# Policies

Vault Policies are used to define authorization to specified paths.

# Policy Names

A policy should generally assign capabilities to the most specific paths possible. Thus, it should be common practice to name Policies using the Vault Secret Path (VSP) format.

For example, consider a policy that should allow access to READ the private SSH key used in the Hermes production environment. Its VSP is solarix/core/hermes/production. Therefore, an associated policy might be named solarix/core/hermes/production as well, and it provides the capability to read the secret at that same VSP:

vault policy write solarix/core/hermes/production - <<EOF
path "secret/solarix/core/hermes/production" {
  capabilities = ["read"]
}
EOF

# JWT/OIDC Roles

# Role Names

Role names cannot use forward-slash (/) path separators since the Vault engine assumes a role will be a single tag entry within an API path. Therefore, role names should use underscore (_), period (.), or dash (-) path separator characters.

WARNING

It is strongly recommended you use period (.) path separators for role names.

For example, consider a role that is attached to the Hermes production policy defined above (solarix/core/hermes/production). The role name should typically follow the same conventions, while replacing forward-slash (/) separators with periods (.):

vault write auth/jwt/role/solarix.core.hermes.production - <<EOF
{
  "role_type": "jwt",
  "policies": ["solarix/core/hermes/production"],
  "token_explicit_max_ttl": 60,
  "user_claim": "user_email",
  "bound_claims": {
    "project_id": "65",
    "ref": "master",
    "ref_type": "branch"
  }
}
EOF

# Usage

# Update Local TLS Certificate Stored in Vault

The following illustrates a series of shell commands used to update a local server TLS certificate. The Vault auth method used is userpass. These commands can be combined into a bash script as part of a cron job or issued manually:

USERNAME="certifier"
PASSWORD="1234567890"
SECRET_PATH="certificate/tls/solarix.dev"
VAULT_TOKEN=$(curl --request POST --data "{ \"password\": \"$PASSWORD\" }" https://vault.example.com:8200/v1/auth/userpass/login/$USERNAME | python3 -c "import sys, json; print(json.load(sys.stdin)['auth']['client_token']);")
SECRET=$(curl --location --request GET "https://vault.example.com:8200/v1/secret/data/$SECRET_PATH" --header "X-Vault-Token: $VAULT_TOKEN")
CERTIFICATE=$(echo "$SECRET" | python3 -c "import json, sys; print(json.load(sys.stdin)['data']['data']['cer']);")
KEY=$(echo "$SECRET" | python3 -c "import json, sys; print(json.load(sys.stdin)['data']['data']['key']);")
echo "$CERTIFICATE" > /home/ubuntu/.acme.sh/solarix.dev/fullchain.cer
echo "$KEY" > /home/ubuntu/.acme.sh/solarix.dev/solarix.dev.key
sudo systemctl restart nginx