How-tos

Protecting APIs on Kusk Gateway

Learn how to apply access control to protect APIs deployed behind Kusk API Gateway. Deploy Cloudentity's Kusk Authorizer to enforce policies applied to your discovered APIs.

About Kusk Gateway

Kusk Gateway is a self-service API gateway that enables developers to design and configure APIs from a single OpenAPI manifest and develop REST APIs running in Kubernetes.

Cloudentity integration with Kusk Gateway is based on the Cloudentity Standalone Authorizer acting as an externalized authorization engine for Kusk Gateway.

If you wish to learn more about Cloudentity authorizers, see the API Gateway Authorization article.

Prerequisites

  • Kubernetes version 1.19 or subsequent

  • Kubernetes cluster is set up.

    Setting Up K8s Cluster

    You can set up a Kubernetes cluster locally using kind.

    GO111MODULE="on" go get sigs.k8s.io/kind@v0.9.0 && kind create cluster
    

    Optionally, you can clone use the acp-on-k8s Github project and its make prepare command to quickly spin up a local K8s cluster.

  • Helm version 3.0 or subsequent

  • Cloudentity tenant

If you don't have a Cloudentity tenant yet, register for free and start protecting your APIs right away!

Prepare Kusk Gateway and APIs

Install Kusk Gateway

  1. Install Kusk CLI.

    The Kusk CLI is a tool designed to help developers manage tasks required when running Kusk Gateway.

    • macOS users can install the Kusk CLI using Homebrew - package manager for macOS.

      brew install kubeshop/kusk/kusk
      
    • Linux users can install the Kusk CLI using the following command:

      curl -sSLf https://raw.githubusercontent.com/kubeshop/kusk-gateway/main/cmd/kusk/scripts/install.sh | bash
      
    • Users of other platforms need to download a preferred binary from the Kusk Gateway GitHub repository.

  2. Install Kusk Gateway.

    For the purposes of this article, you can use the below command to install the Kusk Gateway within your cluster. By default, using the kusk install command would install kusk-gateway, envoy-fleet, Kusk API server, and Kusk Dashboard. Since the API server and the dashboard are not required for this tutorial, they are disabled via the command options.

    kusk install --no-dashboard --no-api
    

Deploy APIs

  1. In a directory of your choice, create a api.yaml file with the below content and save it:

    openapi: 3.0.0
    info:
      title: simple-api
      version: 0.1.0
    x-kusk:
      cors:
        origins:
          - "*"
        methods:
          - GET
          - POST
      mocking:
        enabled: true
      auth:
        scheme: cloudentity
        auth-upstream:
          host:
            hostname: cloudentity-authorizer-standalone-authorizer.kusk-system
            port: 9004
    paths:
      /hello:
        get:
          responses:
            "200":
              description: "A simple hello world"
              content:
                application/json:
                  schema:
                    type: object
                    properties:
                      message:
                        type: string
                  example:
                    message: Hello from a mocked response!
      /validated:
        post:
          requestBody:
            description: ""
            required: true
            content:
              application/json:
                schema:
                  required:
                    - name
                  type: object
                  properties:
                    name:
                      type: string
          responses:
            "200":
              description: ""
              content:
                text/plain:
                  schema:
                    type: string
                  example: Hello mocked Kusk
    
    
  2. In terminal, navigate to the directory where you had saved the api.yaml file and execute the below command to deploy the APIs:

    kusk api generate -i api.yaml | kubectl apply -f -
    

    Result

    If your APIs are successfully deployed, you should see the following message in your terminal:

    api.gateway.kusk.io/simple-api created
    

    If you enabled the Create and bind services automatically option when creating the Authorizer, you will see the discovered APIs in the Enforcement > APIs view. If you did not enable this particular option, go to Enforcement > Authorizers, select your authorizer for the Kusk Gateway, and connect a service to the discovered APIs in the APIs tab.

Create and Deploy Authorizer

Create Authorizer

  1. In the workspace of your choice, go to ENFORCEMENT > AUTHORIZERS > CREATE GATEWAY.

  2. Select Kusk, enter the name and the description for your authorizer.

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

    Tip

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

  4. Select Next.

    Result

    Your authorizer is created within the Cloudentity platform. Now, you can either follow the instructions from the Quickstart tab of your authorizer or follow the article further.

Deploy Authorizer

  1. In the Gateway Management view, go to the QUICK START tab and proceed as follows:

    1. Install authorizer using Helm chart:

      helm repo add acp https://charts.cloudentity.io
      helm repo update
      helm upgrade --install cloudentity-authorizer acp/standalone-authorizer \
      --set clientCredentials.clientID={client-id} \
      --set clientCredentials.clientSecret={client-secret} \
      --set issuerURL=https://{tid}.authz.cloudentity.io/{tid}/{aid} \
      --namespace kusk-system
      

      You can find this command with the arguments filled for you in the QUICKSTART view for your authorizer instance. The clientCredentials.clientID, clientCredentials.clientSecret, and issuerURL parameters are used in the client credentials OAuth grant type to authenticate your authorizer’s requests to, for example, fetch authorization policies from Cloudentity. The clientCredentials.clientID argument should point to the client identifier of the client application created for your authorizer in the System workspace of your tenant. You can find the client identifier in the Settings view for your authorizer. The clientCredentials.clientSecret argument should point to the client secret of the client application created for your authorizer in the System workspace of your tenant. You can find the client secret in the Settings view for your authorizer.

      Credentials security

      For production environments, you should create Kubernetes secrets manually that are responsible for storing your credentials values.

      To increase security of secrets stored in your repository, it is recommended to encrypt your Kubernetes secrets. You can use tools like Mozilla SOPS or Bitnami Sealed Secrets to encrypt your secrets.

      When the secrets are applied to your Kubernetes deployment, the secrets are visible as plain text. Anyone who is authorized to create a Pod in a namespace can read any secret in that namespace; this includes indirect access such as the ability to create a Deployment. To mitigate the risks, Kubernetes recommends to:

      • Enable encryption at Rest for secrets.

      • Enable or configure RBAC rules that restrict reading data in secrets.

      • Where appropriate, use mechanisms such as RBAC to limit which principals are allowed to create or replace secrets.

      To learn more, visit Kubernetes secrets documentation.

      The issuerURL argument should point to the issuer URL of your Kusk Authorizer client application created within the System workspace of your tenant. You can find the issuer URL in the Settings view for your authorizer. If you are using a vanity domain for your Cloudentity tenant and it is impossible to retrieve the tenant’s and server’s identifier from the URL, provide values for the tenantID and serverID parameters in your values.yaml file.

Enforce Authorization Policies

Now that you have your gateway, APIs, and the authorizer deployed, we can assign authorization policies to your APIs and start enforcing access control.

If you wish to test calling deployed APIs, there are a couple of ways to do so:

  • If you are using any kind of load balancer, you can get your gateway IP address and test the API as described in the Kusk documentation.

  • If you used kind to set up your cluster, it does not provide you with any load balancer by default (therefore you won’t be able to know the external IP address of your gateway). In this case, you may:

Once you have successfully called your APIs, within the Cloudentity platform (ENFORCEMENT > APIs), assign an authorization policy (for example, Block API policy) to your API and call it once again. If you assigned the Block API policy, access to your API should be blocked and your call should return the HTTP 403 Forbidden status.

Example:

curl 10.0.0.1/hello -v
*   Trying 10.0.0.1:80...
* Connected to 10.0.0.1 (10.0.0.1) port 80 (#0)
> GET /hello HTTP/1.1
> Host: 10.0.0.1
> User-Agent: curl/7.85.0-DEV
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 403 Forbidden
< date: Mon, 05 Sep 2022 07:49:15 GMT
< x-envoy-upstream-service-time: 6
< server: envoy
< content-length: 0
<
* Connection #0 to host 10.0.0.1 left intact

Propagating Policies

Your authorizer fetches assigned authorization policies from the Cloudentity tenant at an interval defined in your authorizer configuration (reload_interval setting).

If you assigned a policy that, for example, blocks all incoming API calls, your authorizer may still allow API calls until the configuration is fetched from the Cloudentity platform.