Protecting APIs on Kusk Gateway
Learn how to apply access control to protect APIs deployed behind Kusk API Gateway. Deploy SecureAuth'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.
SecureAuth integration with Kusk Gateway is based on the SecureAuth Standalone Authorizer acting as an externalized authorization engine for Kusk Gateway.
If you wish to learn more about SecureAuth 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
Prepare Kusk Gateway and APIs
Install Kusk Gateway
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.
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 installkusk-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
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: cloudentity: host: hostname: cloudentity-authorizer-standalone-authorizer.kusk-system # default authorizer service, change in case your authorizer is installed differently 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
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 -
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 Authorization > Gateways, 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
In the workspace of your choice, go to Authorization > Gateways > CREATE GATEWAY.
Select Kusk, enter the name and the description for your authorizer.
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 SecureAuth service list automatically when the Kusk authorizer is connected to SecureAuth. Otherwise, you need to add them manually.
Select Next.
Your authorizer is created within the SecureAuth platform. Now, you can either follow the instructions from the Quickstart tab of your authorizer or follow the article further.
Deploy Authorizer
In the Gateway Management view, go to the QUICK START tab and proceed as follows:
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
, andissuerURL
parameters are used in the client credentials OAuth grant type to authenticate your authorizer's requests to, for example, fetch authorization policies from SecureAuth. TheclientCredentials.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. TheclientCredentials.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 SecureAuth tenant and it is impossible to retrieve the tenant's and server's identifier from the URL, provide values for thetenantID
andserverID
parameters in yourvalues.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:
Forward a local port to a port on the Kubernetes Pod where you should forward any available local port to the port of your gateway.
Within you cluster, execute into one of your deployed pod's shell and call the APIs using the cluster's IP address.
Once you have successfully called your APIs, within the SecureAuth 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
Tip
Your authorizer fetches assigned authorization policies from the SecureAuth 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 SecureAuth platform.