API portal for VMware Tanzu supports API key management integrating with HashiCorp Vault.
You create API keys for API key enabled Spring Cloud Gateway for Kubernetes instances. You can also configure API key validation for other applications and gateways.
In order to activate API key management, you need to follow these steps:
Set API key values making sure that the flag apiKey.enabled
is set to true
Each created API key will be hashed and stored only within the configured Vault instance. Associated with the hashed key value, the creator's subject id retrieved from the ID token will be stored too in order to track the owner of the key. This information is not stored in API portal. It is only used to ensure that the specific API key owner or API Manager can view/delete keys.
If you don't already have a HashiCorp Vault instance for API portal to integrate with, you may install one in your k8s cluster following the corresponding guide for your k8s distribution. The sample commands below demonstrate installing with the Helm chart:
helm repo add hashicorp https://helm.releases.hashicorp.com
helm upgrade --install vault hashicorp/vault --atomic --namespace vault --create-namespace --wait
Depending on the usage of your Vault instance, you might want to customize or tune-in its properties. You can find a list of every configurable parameter of your Vault helm installation by visiting this link.
A relevant parameter is staticSecretRenderInterval
which allows you to control the frequency with which the Vault Agent Template renders our KV v2 secrets. You may want to shorten the interval if you want any newly created or deleted API keys to take effect sooner. The sample instructions below show which parameters are defined to customize the secret render interval used by the Vault Agent Injector:
helm repo update
helm upgrade --install vault hashicorp/vault --atomic --namespace vault --create-namespace \
--set "injector.agentDefaults.templateConfig.staticSecretRenderInterval=16s" --wait
Additionally, you may need to unseal your vault. See the following topics in the Vault documentation:
You need to allocate a dedicated path in your HashiCorp Vault instance for your API keys to be securely stored. You also need to configure the instance so that API portal can access and make changes within that path.
In order to run the following vault commands you will need to be in an environment with access to the vault CLI. If you installed vault using helm chart mentioned in this guide you can access the vault CLI by opening a shell to the vault pod using the following command:
kubectl -n vault exec -it vault-0 -- /bin/sh
Create a dedicated path for API portal to manage API keys:
vault secrets enable -path=api-portal-keys kv-v2
The sample command above uses api-portal-keys
as the path. You may use a different path and configure it at installation time, just make sure you use your path when creating policy in the next step.
Create a Vault access policy to that path:
(
cat << EOF
path "api-portal-keys/data/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
path "api-portal-keys/metadata/*" {
capabilities = ["list", "delete"]
}
EOF
) | vault policy write api-portal-policy -
Example response:
Success! Uploaded policy: api-portal-policy
The sample command above uses api-portal-policy
as the name. You may use a different name for the policy, just make sure you use your policy name when creating the role in the next step.
Next, create the gateway-policy
to read all API keys.
(
cat << EOF
path "api-portal-keys/data/*" {
capabilities = ["read"]
}
path "api-portal-keys/metadata/*" {
capabilities = ["list"]
}
EOF
) | vault policy write gateway-policy -
Alternatively, you can create the gateway-policy
to only read API keys belonging to a specific API group ID.
(
cat << EOF
path "api-portal-keys/data/my-group-id*" {
capabilities = ["read"]
}
path "api-portal-keys/metadata/my-group-id*" {
capabilities = ["list"]
}
EOF
) | vault policy write gateway-policy -
Enable the Kubernetes Auth Method
vault auth enable kubernetes
Configure Vault to talk to Kubernetes:
vault write auth/kubernetes/config \
token_reviewer_jwt="<your reviewer service account JWT>" \
kubernetes_host=https://192.168.99.100:<your TCP port or blank for 443> \
[email protected]
If your Vault instance was installed in the same k8s cluster as API portal, you may run the following command instead (assuming it's installed in namespace vault
):
vault write auth/kubernetes/config \
token_reviewer_jwt="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
kubernetes_host="https://$KUBERNETES_PORT_443_TCP_ADDR:443" \
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
Example response:
Success! Data written to: auth/kubernetes/config
Create a role that binds a namespaced service account to a policy:
vault write auth/kubernetes/role/api-portal-role \
bound_service_account_names=<Your api portal service account> \
bound_service_account_namespaces=<Your api portal namespace> \
policies=api-portal-policy \
ttl=24h
Example response:
Success! Data written to: auth/kubernetes/role/api-portal-role
The bound_service_account_namespaces
above needs to be set to the namespace where you install your API portal, and the bound_service_account_names
should match the serviceAccount.name
property set in the installation yaml file. The sample command above uses api-portal-role
as the role name. You may use a different name for the role, and that should be the value set in apiKey.vault.role
in the installation yaml file.
Add the following properties to the installation yaml file:
apiKey:
enabled: true
vault:
url: <Your vault url> # Required: You may use "http://vault.vault.svc:8200/" if Vault is installed in the same cluster as API portal
role: api-portal-role # Required: Same as the role name you created in the previous step
path: api-portal-keys # Optional: defaults to `api-portal-for-vmware-tanzu` if not specified. Make sure to use the same path you created and configured in the previous steps
serviceAccount:
create: true # You may set it to false if you'd like to create the service account manually
name: api-portal-service-account # Defaults to `default` if not specified
If apiKey.enabled
is true
the installation process will require you to provide non-empty values for apiKey.vault.url
and apiKey.vault.role
. Otherwise, the installation will fail before any deployment.
Then you may run installer:
./scripts/install-api-portal.sh --namespace api-portal-namespace --values /path/to/that/yaml/file.yaml
API key validation can be configured with applications and other gateway solutions as long as the following conditions met:
x-api-key
HTTP header and validate as per instructions belowThe OpenAPI spec allows for the addition of information to the official spec. API portal uses this group ID to mark a collection of APIs. With specific group ID, users can ensure that multiple versions of the same API can appear together in API portal. The application or gateway must add a field named groupId
to the root of the document:
{
"openapi":"3.0.1",
"info":{},
"externalDocs":{},
"servers":[],
"paths":{},
"components":{},
"groupId":"animal-rescue-api"
}
Generated API keys are 64 characters long. An example key:
57b81d89804a48128f3bf3e73307a3e6c2c90e8ed1b34cd7a3073f3198d406da
The first 32 characters of the key is the selector for the key and the last 32 characters are the value for the key.
The SHA256 hashed key values are stored in Vault under the path /<vaultPath>/<API group id>/<selector>
, where <vaultPath>
is the configured path, <API group id>
is the group ID adopted for this API (see #1 above), <selector>
is the first 32 characters of the API key.
To validate the key:
/<vaultPath>/<API group id>/<selector>
.