Configure API key management

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.

API Keys configuration requirements

In order to activate API key management, you need to follow these steps:

  1. Configure SSO

  2. Configure your Vault instance

  3. Set API key values making sure that the flag apiKey.enabled is set to true

Note: 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.

Deploy Vault to Kubernetes [Optional]

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

Customizing your Vault and Vault Agent properties

Depending on the usage of your Vault instance, you might want to customize (or tune-in) its properties accordingly. You can find a list of every configurable parameter of your Vault helm installation by visiting this link.

One interesting 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 to perform the next set of configurations.

Configure Your Vault instance

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
  1. Create a dedicated path for API portal to manage API keys:

    vault secrets enable -path=api-portal-for-vmware-tanzu kv-v2
    

    The sample command above uses api-portal-for-vmware-tanzu 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.

  2. Create a Vault access policy to that path:

    (
    cat << EOF
      path "api-portal-for-vmware-tanzu/data/*" {
        capabilities = ["create", "read", "update", "delete", "list"]
      }
      path "api-portal-for-vmware-tanzu/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 role in the next step.

  3. Enable the Kubernetes Auth Method

    vault auth enable kubernetes
    
  4. 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> \
        kubernetes_ca_cert=@ca.crt
    

    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
    
  5. 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-for-vmware-tanzu # 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

Note: 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 Keys configuration for gateways other than Spring Cloud Gateway for K8s

API key validation can be configured with applications and other gateway solutions as long as the following conditions met:

  1. the application or gateway adopts group ID as an extension in the OpenAPI spec
  2. the application or the gateway uses vault as the secret management solution and this vault instance is shared with API Portal
  3. the application or the gateway is able to extract a value from the x-api-key HTTP header and validate as per instructions below

Adopting group ID as OpenAPI spec extension

The OpenAPI spec allows for the addition of information to the official spec. 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"
}

Validating provided API key

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:

  1. Split the provided header value in half to get the selector (first 32 characters) and the value (last 32 characters).
  2. Look for hashed key value under /<vaultPath>/<API group id>/<selector>.
  3. If there is no hashed key value, then the key is invalid.
  4. SHA256 hash the provided key value.
  5. If the hashed value from #2 matches the hashed value from #4, then the API key is valid.
  6. If not, then the key is invalid.
check-circle-line exclamation-circle-line close-line
Scroll to top icon