API keys

Authenticate requests by using an API key.

This feature is available with a Gloo Mesh Gateway license only.

About API keys

API keys are secure, long-lived UUIDs that clients provide when they send a request to your service. You might use API keys in the following scenarios:

When you use API keys, your services are only as secure as the API keys. Storing and rotating the API key securely is up to the user.

How API keys work with Gloo Mesh

To secure your services with API keys, first provide Gloo Mesh with your API keys in the form of Kubernetes secrets. Then in the external auth policy, you refer to the secrets in one of two ways.

Gloo Mesh Gateway matches a request to a route that is secured by the external auth policy. The request must have a valid API key in a header. You can configure the name of the expected header. If the header is missing, or the API key is invalid, Gloo Mesh denies the request and returns a 401 response.

Internally, Gloo Mesh maps API keys to user identities for all API keys in the system. The user identity for an API key is the name of the secret that has the API key. Gloo Mesh adds the user identity to the request as a header, x-user-id by default. Gloo Mesh can use this header in subsequent filters. For security purposes, Gloo Mesh sanitizes the header from the response before the response leaves the gateway proxy.

Before you begin

  1. Complete the demo setup to install Gloo Mesh, Istio, and Bookinfo in your cluster.

  2. Make sure that you have the following CLI tools, or something comparable:

    • base64 to encode strings.
  3. Create the Gloo Mesh resources for this policy in the management and workload clusters.

    The following files are examples only for testing purposes. Your actual setup might vary. You can use the files as a reference for creating your own tests.

    1. Download the following Gloo Mesh resources:

    2. Apply the files to your management cluster.

      kubectl apply -f kubernetes-cluster_gloo-mesh_cluster-1.yaml --context ${MGMT_CONTEXT}
      kubectl apply -f kubernetes-cluster_gloo-mesh_cluster-2.yaml --context ${MGMT_CONTEXT}
      kubectl apply -f workspace_gloo-mesh_anything.yaml --context ${MGMT_CONTEXT}
      
    1. Download the following Gloo Mesh resources:

    2. Apply the files to your workload cluster.

      kubectl apply -f virtual-gateway_bookinfo_north-south-gw.yaml --context ${REMOTE_CONTEXT1}
      kubectl apply -f workspace-settings_bookinfo_anything.yaml --context ${REMOTE_CONTEXT1}
      
  4. Send a request to verify that you can reach the ratings app without authorization. By default, Gloo Mesh allows any request on routes that do not specify authentication.

    curl -v ${INGRESS_GW_IP}/ratings/1 -H "Host: www.example.com"
    

    Example output:

    {"id":1,"ratings":{"Reviewer1":5,"Reviewer2":4}}
    

Configure an external auth policy with an API key

Create the external auth policy that uses API keys to verify identity.

You can do the following steps in a different order, depending on when you want the policy to take effect. For example, you might want the policy to always take effect as soon as the route is created. To do so, you can create the policy before you add the route to the route table.
  1. From your API management tool such as Gloo Portal or Google Developer Portal, generate an API key to use for your app's domain. For example, your key might be N2YwMDIxZTEtNGUzNS1jNzgzLTRkYjAtYjE2YzRkZGVmNjcy.

  2. Encode the API key value so that you can store the API key in a Kubernetes secret. You can optionally encode other details that you want to pass in with the API key, such as a user ID

    echo N2YwMDIxZTEtNGUzNS1jNzgzLTRkYjAtYjE2YzRkZGVmNjcy | base64
    echo userID-12345 | base64
    

    Example output:

    TjJZd01ESXhaVEV0TkdVek5TMWpOemd6TFRSa1lqQXRZakUyWXpSa1pHVm1OamN5Cg==
    dXNlcklELTEyMzQ1Cg==
    
  3. Store the encoded API key and any additional data as a Kubernetes secret in the workload cluster that you want to create the external auth policy in. Make sure to use a label so that you can select the secret later.

    kubectl apply --context ${REMOTE_CONTEXT1} -f - <<EOF
    apiVersion: v1
    kind: Secret
    metadata:
      name: apikey-infrastructure
      namespace: bookinfo
      labels:
        team: infrastructure
    type: extauth.solo.io/apikey
    data:
      api-key: TjJZd01ESXhaVEV0TkdVek5TMWpOemd6TFRSa1lqQXRZakUyWXpSa1pHVm1OamN5Cg==
      user-id: dXNlcklELTEyMzQ1Cg==
    EOF
    
  4. Create an external auth server to use for your policy.

    kubectl --context ${REMOTE_CONTEXT1} apply -f - <<EOF
    apiVersion: admin.gloo.solo.io/v2
    kind: ExtAuthServer
    metadata:
      name: ext-auth-server
      namespace: bookinfo
    spec:
      destinationServer:
        ref:
          cluster: cluster-1
          name: ext-auth-service
          namespace: gloo-mesh
        port:
          name: http2
    EOF
    
  5. Create a route table for the ratings app and external auth policy. Note that the route table selects the virtual gateway that you created before you began, and routes to the ratings service.

    kubectl --context ${REMOTE_CONTEXT1} apply -f - <<EOF
    apiVersion: networking.gloo.solo.io/v2
    kind: RouteTable
    metadata:
      name: bookinfo
      namespace: bookinfo
      labels:
        expose: "true"
    spec:
      hosts:
        - '*'
      virtualGateways:
        - name: north-south-gw
          namespace: bookinfo
          cluster: cluster-1
      workloadSelectors: []
      http:
        - name: ratings
          labels:
            apikey: "true"
          matchers:
          - uri:
              exact: /ratings/1
          - uri:
              prefix: /callback
          forwardTo:
            destinations:
            - ref:
                name: ratings
                namespace: bookinfo
    EOF
    
  6. Create an external auth policy that uses the API key.

    kubectl --context ${REMOTE_CONTEXT1} apply -f - <<EOF
    apiVersion: security.policy.gloo.solo.io/v2
    kind: ExtAuthPolicy
    metadata:
      name: ratings-apikey
      namespace: bookinfo
    spec:
      applyToRoutes:
      - route:
          labels:
            apikey: "true"
      config:
        server:
          name: ext-auth-server
          namespace: bookinfo
          cluster: cluster-1
        glooAuth:
          configs:
          - apiKeyAuth:
              headerName: api-key
              headersFromMetadata:
                x-user-id: user-id
              labelSelector:
                team: infrastructure
    EOF
       

Review the following table to understand this configuration. For more information, see the API reference.

Setting Description
applyToRoutes Configure which routes to apply the policy to, by using labels. The label matches the app and the route from the route table. If omitted, the policy applies to all routes in the workspace.
server The external auth server to use for the policy.
apiKeyAuth Configure the API key authentication details.
headerName The header that the Gloo Mesh external auth server looks at to get the API key. If not set, the default api-key header name is used.
headersFromMetadata Additional headers from the secret metadata to add to the authenticated requests. For example, you might configure the API key secret to include extra data such as the user ID. The key in this field is the name of the header to add to the request. The value in this field is the key in the secret data field. That key's value is injected as the header value. In this example, Gloo Mesh adds an x-user-id header into authenticated requests, with the value of the user-id from the secret (dXNlcklELTEyMzQ1Cg==).
labelSelector The label to match the policy with valid API key secrets. Any secrets that match the label are selected and can be used to authenticate requests. The API key secrets must be in the same workspace as the external auth server.

Verify the external auth API key policy

  1. Send a request to the ratings app without authorization. Now, the request is blocked with a 401 response.

    curl -v ${INGRESS_GW_IP}/ratings/1 -H "Host: www.example.com"
    

    Example output:

       > GET /posts/1 HTTP/1.1
       > Host: foo
       > User-Agent: curl/7.54.0
       > Accept: */*
       >
       < HTTP/1.1 401 Unauthorized
       < www-authenticate: API key is missing or invalid
       < date: Mon, 07 Oct 2019 19:28:14 GMT
       < server: envoy
       < content-length: 0
       
  2. Send the request again, this time with a header that contains your API key data.

    curl -v ${INGRESS_GW_IP}/ratings/1 -H "Host: www.example.com" -H "api-key: N2YwMDIxZTEtNGUzNS1jNzgzLTRkYjAtYjE2YzRkZGVmNjcy"
    

    You can reach the ratings app again!

    {"id":1,"ratings":{"Reviewer1":5,"Reviewer2":4}}