Operations guide

About the API Product configuration

Upon startup, the Apigee adapter downloads API Product definitions from your Edge organization/environment. The adapter uses this information to apply policies (for example, to perform API key validation) on any Istio services that you bound to an API Product in your Edge environment, as explained in Create an API Product.

Here's what else you need to know about the Product configuration:

  • If the target service name is not bound with an API Product, no policies will be applied. See also Binding commands.
  • Path matching is done against the Istio request path.
  • Path matching is similar to wildcard semantics described in the Apigee product documentation, however as there is no base path it is simplified as follows:
    • A single slash (/) by itself matches any path.
    • * is valid anywhere and matches within a segment (between slashes).
    • ** is valid at the end and matches anything to the end of line.
  • For any target service that is mapped to an API Product:
    • Requests that don't match any request paths will be denied.
    • Requests that match the request paths will apply authentication.
    • Authenticated requests will apply to any associated quotas.

About analytics logging

Any request may log analytics, regardless of authentication or mapping to an API product. Any request sent to the Apigee analytics handler in Mixer will be set to Edge Analytics and be accessible through the Edge Analytics UI.

Using JWT-based authentication

Instead of using an API key, you can configure the Apigee adapter to accept a valid JSON Web Token (JWT). This section explains how to configure the Adapter to accept a JWT.

  1. cd to the directory where the Apigee adapter is installed: apigee-istio-adapter.
  2. Open the file samples/apigee/authentication-policy.yaml.
  3. In the spec section, edit the JWT configuration URLs with your own organization and environment values. For example:

    issuer: https://org-env.apigee.net/istio-auth/token
    jwks_uri: https://org-env.apigee.net/istio-auth/certs
    

    For example:

    spec:
      origins:
      - jwt:
          issuer: https://jdoe-test.apigee.net/istio-auth/token
          jwks_uri: https://jdoe-test.apigee.net/istio-auth/certs
    

    If you're using Apigee Edge Private Cloud, you will need to point to values that are appropriate for your Private Cloud installation. For example, you would replace apigee.net with the virtual host alias for your organization-environment. See the Edge documentation to learn about virtual hosts.

  4. Configure the policy correctly for mutual TLS (mTLS).

    The mTLS authentication settings for your Istio mesh and your authentication policy must match. If you set up Istio to use mTLS (that is, you applied istio-demo-auth.yaml when you installed Istio), you must explicitly enable mTLS in your authentication-policy.yaml. To do this, uncomment the mtls line in the authentication-policy.yaml as follows:

    peers:
    - mtls:   # uncomment if you're using mTLS between services (eg. istio-demo-auth.yaml)
    

    If you did not enable mTLS for your mesh, do not enable it in your authentication policy. Simply commout out the mtls line. If the policies do not match, you will see errors similar to: upstream connect error or disconnect/reset before headers.

  5. Save your changes and apply your Istio authentication policy:

    kubectl apply -f samples/apigee/authentication-policy.yaml

  6. Call the /hello API (with or without the API key header). It will fail with the following error message:

    curl http://$HELLOWORLD_URL/hello
    Origin authentication failed.
    

    Now, get a JWT token from Apigee Edge:

    apigee-istio token create -o [your org] -e [your environment] -i [consumer_key] -s [consumer_secret]
    

    where you specify your Edge org, environment, and the consumer key and consumer secret from the Developer App you created, as explained in Get an API key.

    For example:

    apigee-istio token create -o myorg -e test -i c8516b0faa10d7db48d1198fa86e0dfbad7645b0d064354619a3bf0cfa34ac3d -s ce6c9a03c2b70059be626dd349a74e52ca44593539229f350410f0010419eb9f
      {"token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjIifQ.eyJhcGlfcHJvZHVjdF9saXN0IjpbImlzdGlvLWhlbGxvIl0sImF1ZGllbmNlIoibWljcm9nYXRld2F5IiwianRpIjoiNDRhNzhhcQtMDVmMC00MTM5LTNjctOWIxZWFkZTA2N2Q2IiwiaXNzIjoiaHR0cHM6Ly93aWxsd2l0bWFuLXc3QuYXBpZ2VlLm5ldC9lZGdlbWljcm8tYXV0aC92ZXJpZnlBcLZXkiLCJhY2Nlc3NfdG9rZW4iOm51bGwsImNsaWVudF9pZCI6IjZVN2kyS0dyaEc4d0FHNkdZMWZ67WtEYmNtdU9RQ3hBIiwibmJmIjoxNTIyNDE4MTY2LA4CdyCJpYXQiOjE1MjI0MTgxNjYsImFwcGxpY2FaW9uX25hbWUiOiJoWxsby1pc3Rpby1hcHAiLCJleHAiOjE1MjI0MTg0Nj9.f9F0w0Z8MYXkKuSIY3UKN2-GyZnEtuz0pV0CNIoc7Op4GKkNN_nvcTmKXe3cadERBULozumfzMGAnjmrazDFkq90ADa2mv78yIBBQeDdMo2STPPIHPEsxre3Ll0mUeE7vvLBv1LC6_PtR79dYzQYGOExGL0hvihLmOLSFDy_qrljO9oR1XbMWGLTNGComYweujqzgHi0ZimgAkPf8Z84ADt07wmJ3N_j1SYmVp38InDrb9361kZIYGs-bz99BKMsEgxlhy5TEr8W7g8auLDbKdcBDTA96kSwihWTEdYJ3r5j2_mBdZxZ9WOxqb_CmIAZPl6Dgtm6xtc4w4EZ8iA"
    
  7. Try calling the /helloAPI again with the JWT Bearer token presented in the Authorization header. For example:

    curl http://$HELLOWORLD_URL/hello -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjIifQ.eyJhcGlfcHJvZHVjdF9saXN0IjpbImlzdGlvLWhlbGxvIl0sImF1ZGllbmNlIoibWljcm9nYXRld2F5IiwianRpIjoiNDRhNzhhcQtMDVmMC00MTM5LTNjctOWIxZWFkZTA2N2Q2IiwiaXNzIjoiaHR0cHM6Ly93aWxsd2l0bWFuLXc3QuYXBpZ2VlLm5ldC9lZGdlbWljcm8tYXV0aC92ZXJpZnlBcLZXkiLCJhY2Nlc3NfdG9rZW4iOm51bGwsImNsaWVudF9pZCI6IjZVN2kyS0dyaEc4d0FHNkdZMWZ67WtEYmNtdU9RQ3hBIiwibmJmIjoxNTIyNDE4MTY2LA4CdyCJpYXQiOjE1MjI0MTgxNjYsImFwcGxpY2FaW9uX25hbWUiOiJoWxsby1pc3Rpby1hcHAiLCJleHAiOjE1MjI0MTg0Nj9.f9F0w0Z8MYXkKuSIY3UKN2-GyZnEtuz0pV0CNIoc7Op4GKkNN_nvcTmKXe3cadERBULozumfzMGAnjmrazDFkq90ADa2mv78yIBBQeDdMo2STPPIHPEsxre3Ll0mUeE7vvLBv1LC6_PtR79dYzQYGOExGL0hvihLmOLSFDy_qrljO9oR1XbMWGLTNGComYweujqzgHi0ZimgAkPf8Z84ADt07wmJ3N_j1SYmVp38InDrb9361kZIYGs-bz99BKMsEgxlhy5TEr8W7g8auLDbKdcBDTA96kSwihWTEdYJ3r5j2_mBdZxZ9WOxqb_CmIAZPl6Dgtm6xtc4w4EZ"
    Hello version: v2, instance: helloworld-v2-6755887594-bnf6q
    

See also Inspect a JWT token and Rotate a JWT token.

Passing an Apigee API key in a JWT claim

You can configure the Apigee adapter to validate an Apigee API key that is passed in a JWT claim. A claim is information added to a JWT that consists of a name and a value. This information typically asserts something about the subject of the JWT and can be used to perform additional validation of the API request. See also Using JWT-based authentication.

Configuring the adapter

You need to tell the adapter the name of the JWT claim that has an Apigee API key:

  1. Open the file samples/apigee/handler.yaml.
  2. Add the following configuration attribute to the in the spec section of the handler file:

    api_key_claim: my_apigee_apikey_claim_name

    Where my_apigee_apikey_claim_name is any string that is valid for a JWT claim name, as described in the JSON Web Token RFC.

    For example:

    # istio handler configuration for apigee adapter
    # generated by apigee-istio provision on 2018-08-01 16:15:36
    apiVersion: config.istio.io/v1alpha2
    kind: apigee
    metadata:
      name: apigee-handler
      namespace: istio-system
    spec:
      apigee_base: https://istioservices.apigee.net/edgemicro
      customer_base: https://myorg-test.apigee.net/istio-auth
      org_name: apigeesearch
      env_name: test
      key: 93b9ba790045250b1949b15731d6e565117ed8dd63afbd461974acaf404771e4
      secret: 5635f82c78af54f52df157d3023edbd3658437b0ca43cef19a988b475257ab0a
      api_key_claim: my_apigee_apikey_claim_name
    
  3. Apply the handler file to Istio:

    kubectl apply -f samples/apigee/handler.yaml
    

When a request comes in, the adapter will check to see if any valid JWTs have this claim. If the adapter finds a claim with this name in a valid JWT, it will attempt to validate the API key. If the key is valid, the call proceeds. If it is invalid, the call is rejected.

Precedence rules

The adapter follows these rules of precedence when evaluating JWTs and API keys:

  1. If a valid JWT contains a claim name that matches the value of api_key_claim as specified in the handler.yaml file, and the claim contains an Apigee API key, the adapter validates the key. No other JWT claims are considered.
  2. If the request just includes an API key, then the adapter validates it.
  3. If the adapter cannot find a JWT claim name that matches the value of api_key_claim, then the adapter follows it's normal JWT validation behavior, as explained in Using JWT-based authentication

Understanding Quotas

A quota specifies the number of request messages that an app is allowed to submit to an API over the course of an hour, day, week, or month. When an app reaches its quota limit, subsequent API calls are rejected.

Quota use cases

Quotas allow you to enforce the number of requests a client can make to a service in a given amount of time. Quotas are often used to enforce business contracts or SLAs with developers and partners, rather than for operational traffic management. For example, a quota might be used to limit traffic for a free service, while allowing full access for paying customers.

Quota is defined in an API Product

Quota parameters are configured in API Products. For example, when you create an API Product, you can optionally set the allowed quota limit, time unit, and interval.

alt_text

Because API keys map back to API Products, each time an API key is verified the appropriate quota counter can be deprecated (if a Quota is defined in the associated Product).

Where the quota count is maintained

When it starts up, the Apigee adapter obtains configuration information, including Product configurations, from Apigee Edge. For performance reasons, the Apigee adapter maintains a locally cached counter that it checks and decrements. Periodically, the Adapter synchronizes its quota count with the quota state maintained on Apigee Edge.

Masking sensitive information

Requests made to services deployed on Istio may contain sensitive data. You may wish to mask this data when it is sent to the Apigee Analytics platform. This section explains how to mask:

  • Data that appears in the request path, such as query parameters
  • The Client IP

To mask sensitive path and client IP data, do the following:

  1. Open the Apigee-specific definitions.yaml file. This is the file supplied by Apigee that defines the base structures and behaviors for the Apigee adapter. For example, in the Apigee adapter distribution: samples/apigee/definitions.yaml.
  2. Locate these attributes in the kind: analytics section:

    client_ip: source.ip | ip("0.0.0.0")
    request_uri: request.path | ""
    request_path: request.path | ""
    
  3. Change these attributes to constants to "mask" them. For example:

    client_ip: ip("0.0.0.0")
    request_uri: ""
    request_path: ""
    

In some cases, you may have a mix of some services that require masking, and others that are less sensitive and do not. In this case, you can create two definitions. For example, you could create one called:

kind: analytics

and another called:

kind: maskedanalytics

Then, create and apply rules to invoke the correct analytics or maskedanalytics instances.

About the sample files

Sample configuration files are provided in the samples/apigee directory. These files are used to configure Apigee-specific rules and definitions that you apply to the Mixer.

File Description
handler.yaml Defines the Apigee adapter for a specific Apigee tenant. You must edit this file to add values that are returned by the provision command. These values include a key and secret, organization name, environment name, and base URI. See also Handlers.
rule.yaml Defines rules to apply the Apigee mixer adapter to requests. You can add additional rules to this file. See also Rules.
definitions.yaml Defines the base structures and data map for the Apigee mixer adapter. In general, there is no need to edit this file.
authentication-policy.yaml Creates an Authentication policy and binds it to service. Configure and apply this file if you are using JWT authentication.
httpapispec.yaml Defines an "API" in Istio. An API identifies specific requests to services and binds API attributes and behavior to that request. In general, you do not need to edit or apply this file.

Handler configuration

The handler file includes several configurable attributes. You can find example settings in the file samples/apigee/handler.yaml.

Attribute Description
temp_dir A directory where the adapter stores. temporary files. Currently, this directory is used to store buffered analytics records before they are uploaded.
server_timeout_secs The HTTP timeout for client requests made to the Apigee Edge server.
refresh_rate_mins The interval that the adapter polls Apigee Edge for changes made to API Products. Default: 1
legacy_endpoint If you are using Edge Private Cloud, set this to true to ensure the correct implementation for analytics is used. Default: false
file_limit The number of analytics record files that can be stored locally. If the files cannot be uploaded, and this number is exceeded, then the oldest records are deleted. Default: 1024

Disabling the Apigee adapter

To disable the Apigee adapter, simply delete any configurations you applied. For example:

kubectl delete -f samples/apigee/definitions.yaml
kubectl delete -f samples/apigee/handler.yaml
kubectl delete -f samples/apigee/rule.yaml

To enable the adapter, you can always re-apply these same configurations.

Uninstalling Istio

See Uninstalling Istio core components in the Istio documentation.