Automating the API Lifecycle with APIOps banner
Claudio Acquaviva

By on September 26, 2022

Securing your Services and Applications with Styra Declarative Authorization Service (DAS) & Kong Gateway Enterprise

Jeff Broberg, William Seaton and Peter Sullivan from Styra also contributed to this post

API Gateway Authentication (AuthN) and Authorization (AuthZ) are important ways to control the data that is allowed to be transmitted using your APIs. Basically, it checks that a particular identity has permission to access the API, using a predefined set of credentials.

This blog post describes how to use Kong Gateway Enterprise, Styra Declarative Authorization Service (DAS) and an external Identity Provider to implement Authentication and Authorization flows for the Gateway layer.

API Consumer AuthN vs AuthZ?

  • Authentication (AuthN): process of recognizing a consumer (user or application) by the API Gateway. A credential is provided by the consumer for authentication: username/password pair, digital certificate, password “tokens”, biometric data, OTP, client_id/client_secrets, etc.
  • Authorization (AuthZ): process of controlling access to protected resources, in our context APIs. The authorization process takes place after user authentication. Often contextual information about the consumer and request being made is used to help refine the decision process.

These processes, together, enable very fine-grained, context-rich authorization requests for your API Gateways. By consuming the information and context presented by the consumer provisioning processes (the user’s identity, their entitlements, and other context), these processes allow for distributed authorization decisions based on centralized authentication, which would not be possible to be performed by a single user or consumer database. Only within this context is it possible to have context-based authentication (eg., considering date and time, IP address, etc.), multi-factor authentication, and the like. 

AuthN and AuthZ Distributed Implementation

Applications basically solve these issues in two ways:

  1. The AuthN and AuthZ logics are part of the application itself: in this case, to obtain context on the user’s groups and entitlements, the application makes contact with some user databases such as LDAP, X.500, MS Active Directory, etc.
  2. AuthN and AuthZ logics are implemented by specific servers. In this case, both processes are externalized from the applications perspective.

The first option is clearly not recommended for a microservice, hybrid multi-cloud deployment scenario. It’d quickly become a very difficult infrastructure to support and evolve. Embedding AuthN or AuthZ logic in your application will act as a negative influence towards a cloud-native services architecture.

In fact, Separation of Concerns, one of the main principles in Computer Sciences, should be pursued at all costs. The principle, formalized by Edsger Dijkstra in his seminal white paper “On the Role of Scientific Thought”, states the following:

“…It is what I sometimes have called “the separation of concerns”, which is yet the only available technique for effective ordering of one’s thoughts, that I know of.

This is what I mean by “focusing one’s attention upon some aspect”: it does not mean ignoring the other aspects, it is just doing justice to the fact that from this aspect’s point of view, the other is irrelevant ….”

AuthN and AuthZ are two of these types of aspects or separation of concerns.

Microservice based Authentication and Authorization Process

While the Authentication processes tend to be implemented in a centralized environment, Microservices Authorization processes are inherently distributed. Typically there are two levels of abstraction for access control policies:

  • Low granularity: focused on generic security policies. For example, access time, Service required, IP address of the request, etc. This Authorization level is handled by API Gateway layer.
  • High granularity: access control performed by Microservices in relation to their specific resources. For example: operation within a Service (read or write). This Authorization level is typically implemented by the Service Mesh Architecture Pattern.

API Gateway Authentication and Authorization Reference Architecture

Practically speaking, the Reference Architecture for both AuthN and AuthZ process should be something similar to the following:

Kong + Styra blog image 4

As depicted in the diagram, the Authentication and Authorization processes are distributed. Note that one of the main benefits provided by an architecture like this is to follow the Separation of Concerns principle:

  • API Gateway: responsible for exposing the Upstream Services and controlling their consumption through an extensive list of policies besides Authentication and Authorization including Rate Limiting, Caching, Log Processing, etc.
  • Authentication Server (aka, Identity Provider, IdP): responsible for User and Application Authentication, Tokenization, MFA, multiple User Databases abstraction, etc.
  • Authorization Server: responsible for enforcing specific policies to make sure the Consumer can access the resources sitting behind the Gateway (microservices, applications, etc.). The Authorization Server also enforces access control policies related to microservice-to-microservice communication inside the Service Mesh.

Kong Gateway Enterprise

Kong Gateway has a library of plugins that provide simple ways to implement the best known and most widely used methods of API gateway authentication. Here are some of the commonly used ones:

  • Basic Authentication
  • Key Authentication
  • OAuth 2.0 Authentication
  • LDAP Authentication Advanced
  • OpenID Connect

Please, refer to the following link to read more about API Gateway authentication: 

At the same time, Kong Gateway also utilizes OPA (Open Policy Agent) plugin to implement Access Control policies. OPA, developed by Styra, is an open-source project donated to the Cloud Native Computing Foundation (CNCF), where it is a graduated project, alongside tools like Kubernetes..

Styra Declarative Authorization Service (DAS)

Styra DAS is the enterprise-grade control plane for OPA, the industry first and only. With OPA and Styra DAS, teams have a single, consistent way to implement authorization across all their API gateways and more, including Kubernetes deployments, microservices and apps.

Not only does this mean teams can learn a single paradigm, and then apply it everywhere to save time, it also means that new tools, services, APIs or infrastructure can all be more easily governed and secured.

Styra solutions let developers, DevOps and security teams mitigate risks, reduce human error and accelerate application development. The combination of OPA and Styra DAS ensures that authorization in today’s complex environments can be controlled and audited across teams, clusters and clouds 

OpenID Connect and JWT

Of all authentication mechanisms listed before, OpenID Connect (OIDC) is the preferred one for advanced requirements. In fact, when applying OIDC to secure the APIs, we’re delegating the Authentication process to an external entity, called an Identity Provider (IdP).

OIDC is a standard built on top of OAuth and JWT (JSON Web Token). Please, refer to the official OpenID Connect documentation to learn more about OAuth/OIDC and its Flows.

Kong Gateway Enterprise and OPA

There are so many different variations to describe an API consumption process. Here’s an example:

Kong + Styra image 1

  1. Consumer provides a credential to the IdP. If the Consumer sends a request to the API Gateway, since it doesn’t include any token, the Gateway should redirect the Consumer to the IdP, again, to provide credentials.
  2. IdP issues a Token
  3. IdP redirects the Consumer back to the API Gateway.
  4. The API Gateway validates the token and passes it to the local OPA Engine
  5. If OPA accepts the request, the Gateway routes it to the Upstream Services.

Styra DAS plays the Authorization Control Plane role and, as such, pushes policies to OPA, which is the Data Plane. All request authorization happens in OPA

Authorization Framework and Styra

Authorization is the process that takes place after Authentication. It should control what kind of operation the authenticated user can perform. The rules that describe allowed or denied access control are called Policies.

An Authorization Framework has these components, as described in the XACML model:

  • PAP – “Policy Administration Point”: component responsible for managing access policies. Styra Declarative Authorization Service (DAS) of course being the control plane of choice for OPA.
  • PDP – “Policy Decision Point”: component responsible for evaluating access policies at the time of the request. This would be OPA.
  • PEP – “Policy Enforcement Point”: point where the user’s request is intercepted for access policy evaluation. Makes contact with the PDP to obtain the access decision. Kong Gateway OPA plugin plays that role.
  • PIP – “Policy Information Point”: information source system (resources to be accessed, identities, etc.). The distributed nature of modem systems generally favors provisioning data asynchronously via the same distribution channel (i.e. Styra DAS) as the policies.

With the components described above, the Authorization flow should go through the following steps:

  1. Client sends a request. The PEP intercepts it for access evaluation.
  2. The PEP makes a query to the PDP.
  3. The PDP evaluates the request considering the policies described. Any additional information is obtained from the PIP. PIP is managed by PAP.
  4. The PDP finalizes the access decision (allow/deny) and returns it to the PEP.
  5. The PEP forwards the request or returns an error, depending on the PDP’s response.

The following post describes how OPA implements the Authorization Framework.

Styra DAS Configuration

There are a variety of options for enabling API authorization using Kong Gateway, Open Policy Agent (OPA) and Styra DAS. Fortunately, there are a number of best practices that can help you quickly and easily deploy this functionality, while customizing the authorization deployment for the particulars of your environment. For instance, Styra best practice tutorials show you how to deploy a sample application using Styra DAS Quick Start and Kong Gateway Enterprise.

The example deployment is shown below. In this proposed application flow, an HTTP web server allows employees of a sample organization to obtain salary details, while exposing an enterprise HR dashboard.

The diagram depicts Kong Ingress Controller, which manages external access to HTTP services in a Kubernetes cluster using the Kong API Gateway. It configures Kong using Ingress resources created inside the Kubernetes cluster. Check the official Kong Ingress Controller documentation to get it installed.

As you can see, requests are authorized using the Kong Ingress Controller and OPA authorization policy — which, for instance, might include a users’ authentication details (including their role in LDAP or Active Directory, for example), as well as more fine-grained policy detail, such as their location, time of log in, or even their seniority or level of budget controlled within the organization. Each of these latter details can be easily configured using OPA. This sample application demonstrates not only the ease of deployment for combined authentication and authorization decisions, but the flexibility provided by OPA, Kong, and Styra DAS.

For more information, please see our tutorial guide for enabling OPA authorization with Kong Gateway Enterprise. 

 

Kong + Styra blog image 3

Kong Ingress Controller & Styra DAS example

To exercise a little bit the topology we have described so far here are some Kubernetes declarations to define an Ingress and Authentication and Authorization policies.

The environment, as described in the previous section, comprehends Kong’s Kubernetes Ingress Controller and OPA, both running on a Kubernetes Cluster, and Styra DAS. The Kubernetes Ingress Controller configures Kong Enterprise Gateway using Ingress resources created inside the Kubernetes cluster.

The Authentication policy is responsible for integrating with an external Identity Provider (IdP) to (1) authenticate the API Consumer and (2) issue an JWT-based token. The Gateway will take care of the IdP integration as well as the token validation. The example below is used for the OAuth 2.0 Client Credentials Grant.

The Authorization policy, on the other hand, takes the JWT to evaluate if the API Consumer is capable of accessing the existing Kubernetes Service exposed by the Ingress.

Kubernetes External Service

This is a very simple Kubernetes Service definition based on the external and public httpbin.org service.

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  name: ext-service
  namespace: default
spec:
  type: ExternalName
  externalName: httpbin.org
EOF

Kubernetes Ingress Creation

Kong for Kubernetes Ingress Controller exposes the Kubernetes Service with the path “/route1”

cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: route1
  namespace: default
  annotations:
    konghq.com/strip-path: "true"
spec:
  ingressClassName: kong
  rules:
  - http:
      paths:
      - path: /route1
        pathType: ImplementationSpecific
        backend:
          service:
            name: ext-service
            port:
              number: 80
EOF

OIDC-based Authentication Process

The Ingress will be protected by an OIDC Authentication process. That is, the API Consumer has to present previously created credentials to get a token from the Identity Provider and then consume the Ingress.

First of all, we instantiate the Kong OIDC plugin.

cat <<EOF | kubectl apply -f -
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: oidc
  namespace: default
config:
  issuer: "<YOUR_IDP_ISSUER_ENDPOINT>"
  scopes:
    - scope1
  cache_ttl: 10
plugin: openid-connect
EOF

Now, we can apply the plugin to the Ingress with a Kubernetes annotation:

kubectl patch ingress route1 -p '{"metadata":{"annotations":{"konghq.com/plugins":"oidc"}}}'

JWT-based Authorization Policy

The policy, written in Rego, will allow the Ingress consumption only by a specific Client Id. The API Consumer receives an error if it submits a request with a token issued for a different Client Id. Please refer to the OPA documentation for more information about Policies and declarative language Rego.

Below is the policy you will create within Styra DAS:

package policy.ingress

default allow = false

allow = true {
  is_cid
}

is_cid { token.payload.cid == "clientid_xyz" }

headers["header-from-opa"] = "accepted" { allow }
headers["header-from-opa"] = "rejected" { not allow }

bearer_token := t {
v := input.input.request.http.headers.authorization
startswith(v, "Bearer ")
t := substring(v, count("Bearer "), -1)
}

token = {"payload": payload} {
    [header, payload, signature] := io.jwt.decode(bearer_token)
}

Kong Ingress Controller OPA plugin

To configure the Ingress for our OPA Authorization Policy, we will use Styra DAS. Within the Styra DAS workspace, you will need to Create System for Kong Enterprise Gateway and then add the above Rego policy to your system. To configure Styra DAS, navigate to System name (the name you choose for the system) >> Settings >> Install, before copying and running the three listed commands in kubectl. These commands will (1) Configure Kong plugin for OPA authorization, (2) Configure OPA, and (3) Install Styra Local Plane (SLP). 

(Note: this process is described in detail in the Styra DAS Quick Start, as well as in the Styra DAS tutorials. To create a new Quick Start within Styra DAS, select Getting Started from the help menu, shown as a question mark in the top-left corner, before choosing Take a tutorial and selecting Kong Enterprise Gateway.)

Now, add the Rego policy for your system. Navigate to System name >> policy >> ingress >> rules.rego where you will input the above JWT-based rule. In the editor top-left corner, select Code, shown as left-right arrows, and simply copy and paste the above Rego to replace the sample policy. Now, Publish the rule. With this policy configured, we can call the Ingress and receive an authorization decision. For more detail on this process within Styra DAS, see the free Styra Academy course on Microservices Authorization.

Note that, this time, the Ingress has two plugins enabled:

kubectl patch ingress route1 -p '{"metadata":{"annotations":{"konghq.com/plugins":"oidc, opa"}}}'

Calling the Ingress

The Ingress is consumable only with the clientid_xyz Client Id:

# http <KONG_GATEWAY_ADDRESS>/route1/get -a clientid_xyz:clientsecret_xyz
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 1493
Content-Type: application/json
Date: Mon, 18 Jul 2022 19:31:05 GMT
Server: gunicorn/19.9.0
Set-Cookie: session=U7mi9fXuwlfumxX_Y9eOkQ|1658176265|VwOoxOYtd63-ki7CYT7OGZWiXW5xLcBw7qVKp03Xc7qYQvXtsiHrMHlu9zDk6ZaF1SYaQQKBiJQsPn4HG_fhe8TaBtqbKzjMRDQ8RFykkK7VmBoYkQer28kwa7YxvcCT0GV3vUH1E4HyOGHRA7kpAQJrDkPk18EE-47OgKGuHYgA_wJaEoHzsZapzTw3BBqnzIIHlrM6KtXdg31DTanqIoYfk6FWPWokTOXePFyEE-Rx5MUwu5DuSz8WrSTggy1K0n82_NykGcyLLKheP55Kdl_-5NNshxmTPdz_TOOYr12iegI5omT6Lx0Vde9J5MFTeqBdKUuISREL1DV-K7qm6eLHgTNxVNpvzM9WZ1jiKWpwbNQafKhkMo-zXl6Dz_p9PVSnN3cvHqUL8Iar_xrAbjPPwxCwNesVkYT-zIS60ndijnEN1_EN6Zz45bEHRdvqkqDQ-wuJlQMTzLWUFYttcq8Y1mGmpwGD46MaUOup_USNUl9axDU1yNM63teES7107Y424nQWX-d4QplssJw0rZXIVdZiCgV7mWj4y69uqBIQukcEo6KpXRN-BIqFe0CURGDrNad_sX7yAYU56pDWuUOhJbeI-08R_Fyuz8nqOhwkCyeglKa93GjD5nxFtqm5wmxY7KX9CePmAubni8b1SdnIbPrGIGxwOCnx3mrIMsXMcQ74I4AAeaPstuKaXXiHCcK7nkGEj_xH-m8GgXFjKYRRAVEmR9CWAGvfmZRzJCZ3LWa3GQrWfY7qCgMCVUKE2dsJ2bvhMtpWjCIHabrDe9AHdebqo7Oe_OpGMETryPUVVfH8Hi3v1NObZnWfoONXkL6CRgo-Q9U7w_4drfWsrAxlRg0L7NKW4QQ5bNhI7IaQlGVWnP9XWIry4sAKvYWBbjK-lvyD2vVB2Z0aibAV1mJSB6QVT5NGUcQ7HWa_9jvQdhA5p3qQyYv9n1PdD78bSZuKytE-96E0u2jLhrdTqveRAMEJhuqTynr1jf3dTM0cWWAkWYu0iprA9U2Se2Ut8ooybv_cZOxiTalGShasrPs412rTO_Diktc55Ub1ru58BwOYw70aWZceTOu_oiA8s1o6rkQCpPqMkHmzRhfc9TwA4AKjoJJ781MpmGbEFzk06bzClqef2w7TjQ0QpsL1OOdMJ8tA6TeBrnJ8e2Ae3MzEGvwPmDj5ViRntRQ5IhbexRATUNLJURf3ZeD6Exibb4F5-PMz-vK23_o49Lu5mQQ_L9DrWU6EdUFhg-61Y_I|tPbO5RmEuMW7OqCClHU8oguttLE; Path=/; SameSite=Lax; HttpOnly
Via: kong/2.8.1.2-enterprise-edition
X-Kong-Proxy-Latency: 135
X-Kong-Upstream-Latency: 166

{
    "args": {},
    "headers": {
        "Accept": "*/*",
        "Accept-Encoding": "gzip, deflate",
        "Authorization": "Bearer eyJraWQiOiJoRVNaOXN3cThRUkRlUDZBclZZZHo5S0VQWWlQX2E3a3FhQ3JCcEpjMVpZIiwiYWxnIjoiUlMyNTYifQ.eyJ2ZXIiOjEsImp0aSI6IkFULjZWdHZIUUROUXVOR3ZiemRLMFZ0b3FYOUZneU5mVjhKeEhYQ05pS2pZbVEiLCJpc3MiOiJodHRwczovL2Rldi01NjkwMDUub2t0YS5jb20vb2F1dGgyL2RlZmF1bHQiLCJhdWQiOiJhcGk6Ly9kZWZhdWx0IiwiaWF0IjoxNjU4MTcyNjM2LCJleHAiOjE2NTgxNzI5MzYsImNpZCI6IjBvYTNjN2dua2Zkekc3RjA3NHg3Iiwic2NwIjpbInNjb3BlMSJdLCJzdWIiOiIwb2EzYzdnbmtmZHpHN0YwNzR4NyIsImFwcGxpY2F0aW9uX2lkIjoiMG9hM2M3Z25rZmR6RzdGMDc0eDcifQ.LLnaFmYTJNXxJIh3qBcF8bCNJNr_cWoOInxS9QQnwTzqjdIAaOZEXrNHVLpdAsasEBAllKs2b6UN-r3PohzWi653uY6c1URWcRs683ugWmt9XARXJIl0OqHRDcQ4tmuDzOvH12Usb1TrcaQJ-PbeP43YyxN_9bQUADaX0LbUQxNMIh7QndFRu_0FLzj_EMDR3xV1s03MtFkrWrzq9Hl6ar7QUic46hcX7TZW7tPbWjbrw7ZqiG2_Wepja5J6yjc-spL7ZqvGeZCVbz3bsS8sb8vcsD6iWzyIF3N87fHh6aHmn4rPN0WbsYR2nq56Px73iYIVchk_bWNip2kgCEr_HQ",
        "Header-From-Opa": "accepted",
        "Host": "abbfaa58fae70437fbf0cb5219c8163f-422507362.eu-west-3.elb.amazonaws.com",
        "User-Agent": "HTTPie/3.2.1",
        "X-Amzn-Trace-Id": "Root=1-62d5b4f9-3191e4c76348117a589e833e",
        "X-Forwarded-Host": "abbfaa58fae70437fbf0cb5219c8163f-422507362.eu-west-3.elb.amazonaws.com",
        "X-Forwarded-Path": "/route1/get",
        "X-Forwarded-Prefix": "/route1"
    },
    "origin": "192.168.95.142, 35.180.136.165",
    "url": "http://abbfaa58fae70437fbf0cb5219c8163f-422507362.eu-west-3.elb.amazonaws.com/get"
}

If we use a different Client Id, even submitting valid credentials, we get an error:

# http <KONG_GATEWAY_ADDRESS>/route1/get -a clientid_abc:clientsecret_abc
HTTP/1.1 418 
Connection: keep-alive
Content-Length: 26
Content-Type: application/json; charset=utf-8
Date: Mon, 18 Jul 2022 19:30:59 GMT
Server: kong/2.8.1.2-enterprise-edition
Set-Cookie: session=4yrNrmut7x64SO9xKLlDyQ|1658176259|2FD5k8uNIv0MfVW1b64K2rYtYZ3ws97MSMG_rP__COD3q-UTS34AK-HYVbS6cWmxTHA5B7ayz98KX8B-8RNDP_2qgdStz8482HWbkXEkCvBpZ3Ynyq_9zXQWwrHLCdqAKqCWk20VAnkS6JD-G-FMD7bbX-Bkm1PjvchVkhWIl7f0wmK4R8YTuCdSxm43Jut617VVLf9vHNwP9L5olHXn2v4QAv7Ml_Id7WZhaYLIc232N-hEQPYU6x-jcTkJQF3q7FlSJqbyEza8IVZvm3KLQLNaNeI9_qg5-C-nSJwH8QU65yBRVcVGiSUQ2Nuc8wSjhN9RDRcWxTn3T1Wgcoz5Ze1NUFCzImD56ZpFuTm3_OzJKOzeMhh31uyZflzDLdEAx3DWIdL3_OTHAPx4TyW4YPm9mMPw0uHLn9bJLdOhySnNEEeVIFXjkUVmm9crupf_Y_yJUj8MHzr4oP1bGpECXhMLUopDfrkI_pruuedJk5ObEOBgzlG_aQSQZ51qslyBOHUaDEULk2pK1Mu2QljPod74vKJJYPpfogtlAscQQZLD5R_qcvQd4AIBeVPgh3Z4qxt_QZOqOjuLaMZuHAlXRoPNOc0TVNsHgffZBbtflldUh0gqHyLAEA1eXkFUl7ySVcyRSXMYDO1T0cL9lp4uld6w0NbtmdTS6B4CqmvaGqj6dht1LQGMr2EXP75BpkdDa3rBbkmo3-g5dIF-d7tpzMvoRbLKkl156pUG0oqq83ReW-zB_Z2l34dwKeIpSWxs6xFzVJoL66ircaJndyZUHYShFMATAScmHcnpEzqOJE3x6bzpHgLVz3io84TWf3G25zGkQzAbCUMt_WFGzQvq8evH9R42oRIFyJCeI5pBlJcZrUmw6JkCVver692Yj7DQnarQjqgz0ZKFv8vPmTLON8je_ju6zkbn7vZVQs_MkODWJQr-VdzGO15hpFqkkjLPJOxa-BkmOaml42Ozd0hw4vLBp8Z2brRBU7aQxjVhyz0TtEXORSGzFRydJGRfPSUXPLT0SbaX7jO3tS5v4rrsz8uXG6Jgsh7gBlWNefBv_P2UyJRmeS4M8MWEXt4pBrcX_NhMwdHldvwHKp66g2y1U4UikQSMmpheQQHoqS6jT3o8CZLIKbsMihY2gKMUHC8RUID-25Pk84vru0C8G8u_i21iyZeWruXscx6wra-75QxxiiM9jmkYSM8Ty1EmIiLChbFauHoWg-BwmDC_pRr7i7r2nXcemBCtU0PE2ga3I-A|vDK91l_SzR0L0mZS33u15ZVjp4c; Path=/; SameSite=Lax; HttpOnly
X-Kong-Response-Latency: 125
header-from-opa: rejected

{
    "message": "unauthorized"
}

Conclusion

This document has described some of the main use cases to implement Authorization processes. Several other use cases are also feasible and supported by both products.

Using Kong Gateway Enterprise and Styra make it easy to run services by providing consistent security and control for services and multiple use cases and scenarios.

You can learn more about the official documentation of both products here: Styra and Kong Gateway Enterprise.

 

Share Post

Tags: