Ignacio Lozano, Karine Pires, and Chris Sterling contributed to this blog post.
In today’s world of digital transformation, APIs are present in almost every software product. Many teams are responsible for deploying and managing a large portfolio of APIs. However, that scale and complexity of APIs also makes it complicated to control and manage access. Specifically, understanding granular usages and uncovering insights and utilization can be difficult. Enter API key management with API portal for VMware Tanzu and Spring Cloud Gateway for Kubernetes, designed to solve this problem and more. This post primarily explores the features for API key management. For information about other features, check out the latest documentation.
API key management features
As an API Consumer, you can generate API keys for single or multiple API groups configured with your API portal for VMware Tanzu. You can view the list of keys that are currently active and revoke them once they are no longer needed. Any generated key is stored in a secret store from which the configured Spring Cloud Gateway for Kubernetes can read and verify any incoming requests. HashiCorp Vault is a leading provider in secret management and hence was chosen as the inaugural integration for API key management.
Create API Key modal view
As an API Manager, in addition to all of the above features, you can also see a detailed view of all the keys generated by all users in your instance of the API portal. For each key, you can view the key name, issued on date, owner, and the API groups accessible with that key. You can also revoke keys created by any user within the API portal. A user is identified as an API Manager by inspecting a claim within the ID token from the OIDC Identity Provider. For more details on configuring API portal to inspect the right claim, see the API Manager section in the documentation.
API Keys list view for API Managers
Getting started with API Management
Prerequisites:
-
API portal for VMware Tanzu v1.1.x or newer with SSO enabled (Download | Install instructions)
-
Spring Cloud Gateway for Kubernetes v1.1.x or newer (Download | Install instructions)
-
Access to a HashiCorp Vault instance (If you don’t already have access to an instance, follow these instructions to create one.)
Note: The rest of this guide will assume that API portal is installed in the “api-portal” namespace, Spring Cloud Gateway for Kubernetes is installed in “spring-cloud-gateway” namespace, and Vault is installed in the “vault” namespace. Please substitute your custom namespace wherever needed.
Configuring Vault access
Here is a bird’s-eye view of the different pieces needed for Vault to integrate with API portal and Spring Cloud Gateway for Kubernetes. You will need to create Vault access policies for each of the two products, create service accounts in their respective namespaces, and attach those service accounts to the Vault access policies.
The next set of commands can also be set using the Vault UI if you prefer. Start by accessing the Vault instance from the command line and configuring a dedicated path for API keys to be stored.
vault secrets enable -path=api-portal-keys kv-v2
Next, configure access policies for this exact path. API portal needs complete access to this path, whereas Spring Cloud Gateway for Kubernetes only needs the read and list permissions in this path. Create your “api-portal-policy”.
(
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 -
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 -
Connecting Vault to your Kubernetes cluster
In order for your deployments to access the Vault, you need the Kubernetes auth method that uses the Kubernetes Service Account Token.
vault auth enable 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>
If your Vault instance is in the same cluster as API portal and Spring Cloud Gateways, then you can run:
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
Next, you need to create the roles that bind namespaced service accounts to the policies you’ve created. You can create the “api-portal-role” in Vault that allows a service account named “api-portal-sa” in the “api-portal” namespace attached to the “api-portal-policy” in Vault.
vault write auth/kubernetes/role/api-portal-role
bound_service_account_names=api-portal-sa
bound_service_account_namespaces=api-portal
policies=api-portal-policy
ttl=24h
Similarly, you can create the “gateway-role” for a service account named ”gateway-sa” in the “spring-cloud-gateway” namespace.
vault write auth/kubernetes/role/gateway-role
bound_service_account_names=gateway-sa
bound_service_account_namespaces=spring-cloud-gateway
policies=gateway-policy
ttl=24h
You can create the aforementioned service accounts in their respective namespaces. API portal can also automatically create service accounts during installation.
kubectl -n api-portal create serviceaccount api-portal-sa
Configure API portal to enable API key management
In the values.yml file used in conjunction with the installation script for API portal, add the following properties to enable and configure API keys:
apiKey:
enabled: true
vault:
url: "<Your vault url or http://vault.vault.svc:8200/ if Vault is installed in the same cluster>"
role: api-portal-role
path: api-portal-keys
serviceAccount:
create: true # Note: This will automatically create the service account
name: api-portal-sa
apiPortalServer:
sourceUrls: "<Your scg-operator url>/openapi"
sso:
enabled: true
secretName: <Your sso secret name>
Create an Spring Cloud Gateway with API key enabled
The last step is to create a gateway with the Vault details to allow the gateway to read and list the stored API keys. Create an scg.yaml with the below details and apply it. If you add a “serverUrl”, you will also need to create an ingress to route traffic to my-gateway service from that host.
---
apiVersion: "tanzu.vmware.com/v1"
kind: SpringCloudGateway
metadata:
name: my-gateway
spec:
api:
groupId: my-group-id
serverUrl: my-gateway.my-example-domain.com # Optional but recommended for testing the gateway
cors: # Optional but needed for API portal’s “Try it out” feature
allowedOrigins:
- "<My API portal’s domain>"
allowedMethods:
- "GET"
allowedHeaders:
- "*"
serviceAccount:
name: gateway-sa
extensions:
secretsProviders:
- name: vault-api-keys
vault:
roleName: gateway-role
path: api-portal-keys
filters:
apiKey:
enabled: true
secretsProviderName: vault-api-keys
---
apiVersion: "tanzu.vmware.com/v1"
kind: SpringCloudGatewayRouteConfig
metadata:
name: my-routes
spec:
routes:
- predicates:
- Path=/github/
uri: https://github.com
---
apiVersion: "tanzu.vmware.com/v1"
kind: SpringCloudGatewayMapping
metadata:
name: my-mapping
spec:
gatewayRef:
name: my-gateway
routeConfigRef:
name: my-routes
Now, any route like “my-routes” mapped to “my-gateway” will require an additional header “X-API-Key: <API Key Value>” to be passed in.
Create an API key using API portal
In order for API portal to recognize “my-gateway” and its routes, you’ll need to expose the Spring Cloud Gateway operator’s OpenAPI endpoint and, optionally, the my-gateway service too. You can create an ingress using instructions here, or use other methods to expose the operator and gateway.
Then, you can modify the source URLs configured in API portal’s values.yml and rerun the installation script. In case you would like the API portal to trust self-signed or unsecured TLS certificates, you can set the “trustInsecureSourceUrls” property.
apiPortalServer:
sourceUrls: "https://<my-scg-operator-url>/openapi”
trustInsecureSourceUrls: true # false by default
Finally, log in to the API portal user interface, navigate to the API Keys tab and click the + API Key button. Give your key a name, select the group, generate the key, and copy the token. Keep the token safe since you can only copy it once.
Try it out
From the list of APIs on the API portal home page, click on the group card that will take you to the Swagger UI page. There, click the Authorize button and paste the API key in the header value field.
Authorization modal for passing the API key with requests
Next, click on the Try it out button and hit Execute to see a 200 OK response.
Response with 200 OK after executing the API with authorization
You can also use an HTTP client like cURL, HTTP, or Postman to test the route.
curl -X GET my-gateway.my-example-domain.com/github --header "X-API-Key:<my-api-key>”
< HTTP/1.1 200 OK
...
You can also see that, without the header present, the request fails:
curl -X GET my-gateway.my-example-domain.com/github
< HTTP/1.1 401 Unauthorized
...
Explore other features
To explore all other features for both Spring Cloud Gateway for Kubernetes and API portal for VMware Tanzu, view the respective documentation.