Protecting APIs exposed on Kong API Gateways

Learn how to apply access control to protect APIs deployed behind Kong API Gateways. Install necessary plugins in your Gateway. Deploy ACP's Kong Authorizer to enforce policies applied to your discovered APIs.

About Kong Gateways

KongHQ provides you with two versions of a self-hosted Kong Gateway: Kong Gateway (Enterprise) and Kong Gateway (Open-sourced). Both gateways are designed to be a part of decentralized architectures that leverage automation and modern GitOps practices. With their features, you can:

  • Decentralize applications/services and transition to microservices

  • Identify API-related anomalies and threats

  • Secure and govern your APIs and services

With Authorization Control Plane and its Kong Authorizer and plugin, you can successfully integrate your Kong Gateway with Cloudentity solutions for authorization no matter whether it is an Enterprise or Open-Sourced Kong Gateway or which deployment type you chose for your gateway.

Learn more

You can learn more about ACP integration with Kong Gateways by checking out the Dynamic Authorization and API Discovery for Kong documentation.

Integration components

Kong integration components

In the diagram above, you can see that ACP is responsible for OAuth authorization for client applications and providing them with access tokens. It also provides policies and keys to the Kong Authorizer. Behind the Kong Gateway, you can have a number of services deployed that are protected by the Kong Authorizer. You need to have the ACP Kong Plugin attached to the service that you wish to protect. The plugin is responsible for calling the /authorize endpoint of the Kong Authorizer. It also allows the authorizer to fetch Kong Gateway services that can be later on passed to ACP so that you are able to assign authorization policies to the APIs of your choice.

When a client application calls a protected service and its request contains an access token dervied from ACP, Kong Gateway invokes the ACP Kong Plugin so that it can communicate with the Kong Authorizer to authorize the client’s request. The authorizer validates all authorization policies that it fetched from ACP for the given API. After a successful authorization, the Kong Gateway executes the API from the protected service.

ACP Kong Plugin

ACP Kong plugin is a LuaRocks plugin that is executed during the HTTP request/response lifecycle.

This plugin, in particular, is responsible for authorizing access to an upstream service. When you add the ACP Kong plugin to your service, every request made by a client application to this service runs the plugin. The plugin assembles the request data and sends a query to ACP’s Kong Authorizer that is responsible for comparing the request against an authorization policy defined for a given endpoint. After policy validation, the authorizer can respond whether the request should be allowed or denied.

Plugin naming

For Kong, plugins follow the kong-plugin-* naming convention. Both the acp-kong-plugin repository and this article use Cloudentity’s naming convention. You may notice that both names are used interchangeably, but when installing the plugins for the gateway you must use the Kong’s naming convention.

Integration with Kong Gateways

KongHQ provides several possibilities for deployment of their gateway, but you can integrate ACP and its Kong Authorizer with Kong Gateway no matter which deployment type you chose for your gateway. The requirement is that your Kong Authorizer deployment can communicate successfully with your Kong Gateway, whether it is, for example, deployed in a Docker container or in Kubernetes with Helm Charts.

This article is based on Docker container deployment both for the Kong Gateway and the Kong Authorizer. Your ACP instance, however, can be deployed anywhere. It can be, for example, ACP SaaS solution, Docker deployment, or kubernetes deployment with Helm Charts.

Kong Authorizer Helm Chart

You can find a Helm Chart for the Kong Authorizer in a dedicated ACP Helm Charts GitHub repository.

To integrate your Kong Gateway with ACP and Kong Authorizer, you will install the ACP Kong plugin for your Kong Gateway and assign it to your service or a particular route. Then, you will create a Kong Authorizer in your ACP instance and deploy it to a Docker container. Once the authorizer successfully discover your services exposed by your gateway, you will be able to apply access control to your APIs.

Prerequisites

  1. Docker v1.19+ and Docker Compose installed.

  2. Kong API Gateway installed and configured. kong/kong-gateway:2.6.0.0-alpine image or subsequent is recommended for the Enterprise Edition. Kong Release 2.6.0 or later is recommended for the Open-source Edition.

  3. ACP Kong plugin is installed for your Kong Gateway.

    Installing ACP Kong plugin

    The methods on how to add LuaRocks plugins to Kong Gateways differ between deployment types. Choose a method suitable for your deployment.

    For instructions on how to add the plugin for Kong Docker deployments, see the Install and enable the plugin for Kong in Docker section.

    For the purpose of this article, in order to successfully install the ACP Kong Plugin in your gateway, you will use the docker-kong repository and you will modify the Dockerfile for your Kong Gateway docker deployment. If you do not have a Kong Gateway up and running and you have not yet added the plugin, you can find a guide for that in the Installing and enabling the plugin example section.

  4. Services exposed and with routes defined for your Gateway.

    Services

    For the purpose of this article, the httpbin.org service is exposed, but you can use other mock services for testing purposes.

  5. Access to an ACP SaaS tenant

Install and enable the plugin for Kong in Docker

To install the ACP Kong plugin, add the following steps to your Kong Gateway’s Dockerfile.

USER root

RUN  luarocks install kong-plugin-acp

With the Dockerfile steps above, you install the plugin within your Docker image for Kong Gateway. Once you have installed the plugin in your docker image, deploy your container and add the acp plugin to the list of plugins in kong.conf file for your Docker deployment. Choose the method suitable for your deployment. You can find an example on how to do that in the section below.

Docker Kong

For more resources on Docker images for Kong Gateway, visit:

Installing and enabling the plugin example

This section provides an example on how to prepare a Dockerfile for your Kong Gateway deployment so that it installs the kong-plugin-acp within your image. In the second step, you can also find an example of how to build your image so that the acp plugin is included in the list of plugins in the kong.conf file. The following example is based on the kong/kong-gateway:2.6.0.0-alpine image for Kong Gateway.

  1. Clone the docker-kong project.

  2. In the cloned project, change the content in the customize/Dockerfile file to the following:

    FROM kong/kong-gateway:2.6.0.0-alpine AS build
    
    ARG PLUGINS
    ENV INJECTED_PLUGINS=${PLUGINS}
    
    ARG TEMPLATE=empty_file
    ENV TEMPLATE=${TEMPLATE}
    
    ARG ROCKS_DIR=empty_file
    ENV ROCKS_DIR=${ROCKS_DIR}
    
    ARG KONG_LICENSE_DATA
    ENV KONG_LICENSE_DATA=${KONG_LICENSE_DATA}
    
    COPY $TEMPLATE /plugins/custom_nginx.conf
    COPY $ROCKS_DIR /rocks-server
    COPY packer.lua /packer.lua
    
    USER root
    
    RUN /usr/local/openresty/luajit/bin/luajit /packer.lua -- "$INJECTED_PLUGINS"
    
    
    FROM kong/kong-gateway:2.6.0.0-alpine
    
    COPY --from=build /plugins /plugins
    
    USER root
    
    RUN  luarocks install kong-plugin-acp
    
    RUN /plugins/install_plugins.sh
    
    HEALTHCHECK --interval=10s --timeout=10s --retries=10 CMD kong health
    
    USER kong
    
  3. In terminal, navigate to the /customize directory within your cloned project and build your image with the following command:

    docker build \
    --build-arg PLUGINS="kong-http-to-https,kong-upstream-jwt,kong-plugin-acp" \
    --build-arg "KONG_LICENSE_DATA=$KONG_LICENSE_DATA" \
    --tag "kong-acp" .
    

    Tip

    As you can see in the command above, the kong-plugin-acp is included in the PLUGINS build argument for your image. You can, of course, define more plugins for your deployment here. After the scripts from the Dockerfile are done with their execution, the kong-plugin-acp is installed within your image and the acp plugin is in the list of your plugins in the kong.conf file for your Docker deployment.

Once you have your image ready and built, you can deploy it to your container and expose services and add routes to them.

Learn more

  • For detailed instructions on how to run Docker images for Kong Gateway working with a PostgreSQL database, visit Install Kong Gateway on Docker

    If you chose to build your image as shown in the examples above, skip the first and the second step of the KongHQ article. Note that, the image from the example above is tagged kong-acp and not kong-ee as in the article from KongHQ. Also, with the instructions from KongHQ you create a network for your docker containers. Whatever name you choose, it will be later on needed for your Kong Authorizer to work.

  • To learn how to expose services and add routes, see the Expose your Services with Kong Gateway documentation

Assign ACP Kong Plugin to your service

To assign the ACP Kong Plugin to your service, use the Kong Gateway Admin API:

curl -sSk -X POST https://{ADMIN-URL}/services/{NAME-OF-YOUR-SERVICE}/plugins \
     --data 'name=acp' \
     --data 'config.api_group_id={ID-OF-YOUR-API-GROUP}' \
     --data 'config.auth_url=http://kong-authorizer:9003/authorize'

As you can see, the curl request contains the following variables:

  • {ADMIN-URL} which should point to the URL of your Kong Gateway Admin APIs

  • {NAME-OF-YOUR-SERVICE} which should point to the name of the service to which you wish to assign the plugin

  • {ID-OF-YOUR-API-GROUP} which should point to the identifier of your API group in Kong Gateway

The request also contains the --data 'name=acp' argument, which is assigns the acp plugin to the service. Additionally, it contains also the --data 'config.auth_url=http://kong-authorizer:9003/authorize' argument which points to the URL under which your Kong Authorizer will be running.

Below, you can find an example of a request that assigns the acp plugin to an httpbin service exposed by a locally deployed Kong Gateway:

curl -sSk -X POST httpa://localhost:8001/services/httpbin-service/plugins \
     --data 'name=acp' \
     --data 'config.api_group_id=httpbin-service' \
     --data 'config.auth_url=http://kong-authorizer:9003/authorize'

Declarative configuration

If your Kong Gateway is running without a database, you can use declarative configuration for your service to assign the acp plugin to your service as illustrated below:

services:
- name: httpbin-service
   url: https://httpbin.org
   routes:
   - name: anything
      hosts: [ "httpbin.org" ]
      paths: [ "/anything" ]
      methods: [ "GET", "PATCH", "PUT", "POST", "DELETE" ]
      strip_path: false
   plugins:
   - name: acp
      config:
      api_group_id: httpbin-service
      auth_url: http://kong-authorizer:9003/authorize

Create Kong Authorizer

  1. In your ACP tenant, go to the workspace of your choice.

  2. Select APIs > Gateways > ADD GATEWAY > Kong.

  3. Provide a name and a description for your Kong Authorizer.

  4. Optionally, enable the Create and bind services automatically check box.

    Tip

    When enabled, all services protected by your Kong Authorizer instance are discovered and added to the ACP service list automatically when the Kong authorizer is connected to ACP. Otherwise, you need to add them manually.

  5. Follow the Quick Start instruction. Download the package for your Authorizer and check the instructions in the section below.

Deploy Kong Authorizer

  1. Unzip the package with the downloaded Kong Authorizer.

  2. In the .env file, set the KONG_ADMIN_URL to the URL of your Kong Admin APIs.

    Tip

    If you are testing it locally in your Docker deployment, the URL contains the name of the container where your Kong Gateway is running and the port number like shown below:

    KONG_ADMIN_URL=http://kong-acp:8001

    Note that, by default, the port for Kong Gateway HTTPS connection is 8444.

  3. In the terminal, navigate to the directory with your Kong Authorizer and execute the following commands:

    cat credentials.txt | docker login docker.cloudentity.io --username acp --password-stdin
    

    and

    docker-compose up
    

    The first command logins to Cloudentity docker with the credentials provided in the credentials.txt file in your Kong Authorizer package.

    The docker-compose up spins up a Docker container with the Kong Authorizer for you. In the logs for the Kong Authorizer, you should see that it starts the authorizer reload. At this point, however, your authorizer is not yet running in the same network as your Kong Gateway, so it is not possible for the authorizer to communicate with the gateway.

  4. Connect your authorizer to the same network that your Kong Gateway uses.

    In general, you can use a method of your choice to connect your authorizer to the network. You can, for example, execute the following command when the container with your Kong Authorizer is running:

    docker network connect {network} {container}
    

    For example: docker network kong-network 1babdf8b72a6

    Result

    Once the authorizer is successfully assigned to the same network as your gateway, you can see in the authorizer’s logs that the authorization configuration was reloaded.

    In ACP APIs Management View, you can see APIs that were discovered by your Kong Authorizer. You can now apply access control to them.

Apply a sample policy

  1. In ACP, create a policy.

  2. Select APIs from the left sidebar and go to the AUTHORIZATION tab.

  3. Select a service protected by the Kong Authorizer and any API with authorization status Unrestricted.

  4. In the Edit API popup window, select Policy from the list and click Update to proceed.

Result

You have successfully assigned a policy to your API.

Test integration

To test if your integration was successful and that your APIs are protected, you can, for example, create a simple Cloudentity or REGO policy that will always pass. Call your protected endpoint and check if the response contains the successful status. If yes, change your policy so that it blocks APIs. The next request to your protected endpoint should end with the unauthorized access error.

Configuring the Kong Authorizer

The Kong Authorizer can be configured with a file in YAML format, or via environment variables. To generate a template configuration file that is populated with default settings, you can use a Docker image and pipe the output to a configuration file:

docker run --rm docker.cloudentity.io/kong-authorizer reference > reference_config.yaml

The configuration file reference_config.yaml contains the following content:

acp_client_id: ""
acp_client_secret: ""
acp_issuer_url: ""
acp_tenant_id: ""
acp_server_id: ""
acp_reload_interval: 10s
acp_tls_client:
    timeout: 0s # http client timeout
    retry_wait_min: 0s # minimum time to wait between retries
    retry_wait_max: 0s # maximum time to wait between retries
    retry_max: 0 # maximum number of retries
    root_ca: "" # root ca that this client should trust (defaults to system root ca)
    insecure_skip_verify: false # disable cert verification
    disable_follow_redirects: false # disable follow redirects
    disable_retry: false # disable retry
kong_admin_url: ""
kong_tls_client:
    timeout: 0s # http client timeout
    retry_wait_min: 0s # minimum time to wait between retries
    retry_wait_max: 0s # maximum time to wait between retries
    retry_max: 0 # maximum number of retries
    root_ca: "" # root ca that this client should trust (defaults to system root ca)
    insecure_skip_verify: false # disable cert verification
    disable_follow_redirects: false # disable follow redirects
    disable_retry: false # disable retry
analytics:
    probability: 1
    batchinterval: 1s
    batchlimit: 100
    limit: 5
    timeout: 5s
    workers: 8
disable_analytics: false
do_not_fail_on_non_matching_requests: false
server:
    certificate:
        password: "" # key passphrase
        cert_path: "" # path to the certificate PEM file
        key_path: "" # path to the key PEM file
        cert: "" # base64 encoded cert PEM
        key: "" # base64 encoded key PEM
        generated_key_type: ecdsa # type for generated key if cert and key are not provided (rsa or ecda)
    client_auth_type: 0
    dangerous_disable_tls: false
    listener_port: 9003

You can use this reference configuration as a basis for your customization. You can omit settings for which the default configuration is satisfactory, specifying only the required values, which are the client ID, client secret, issuer URL, and Kong admin URL parameters.

acp_client_id: {your_client_id}
acp_client_secret: {your_client_secret}
acp_issuer_url: https://{tid}.us.authz.stage.cloudentity.io/{tid}/system
kong_admin_url: http://kong-acp:8001

Environment variables can also be used to set these configuration values. The environment variable’s name are the uppercase version of the YAML name. For example, in the docker-compose.yml that you downloaded, you can set the acp_client_id via the environment variable ACP_CLIENT_ID:

    environment:
      - ACP_CLIENT_ID=${CLIENT_ID}
      - ACP_CLIENT_SECRET=${CLIENT_SECRET}
      - ACP_ISSUER_URL=${ISSUER_URL}
      - ACP_TLS_CLIENT.INSECURE_SKIP_VERIFY=TRUE
      - KONG_ADMIN_URL=${KONG_ADMIN_URL}
      - KONG_TLS_CLIENT.INSECURE_SKIP_VERIFY=TRUE
      - SERVER.LISTENER_PORT=9003

Tip

Note that nested YAML settings can be accessed by joining uppercased names with periods, as shown in the example above, where the SERVER.LISTENER_PORT=9003 parameter is set.

To run the kong authorizer with a configuration file, use the --config option to specify the YAML file with your configuration. For example, assuming that you have created a kong_config.yaml file in your current directory your docker run command would look like the following:

docker run --rm --volume `pwd`:/config:ro docker.cloudentity.io/kong-authorizer --config /config/kong_config.yaml