In the current world, a myriad of different businesses are going digital, increasing largely the number of services, applications, data and workloads that are reaching cloud computing platforms. With the crescent availability of distributed services and business facilities geographically distributed that need to access corporate applications and data, defining a security perimeter has become an unfeasible task. Zero trust  security does not rely on perimeters to define trust but instead requires that every client originating a request needs to be authenticated and authorized before having granted access to corporate workloads. This granular security control that came to help on the reduction of attack surfaces, assuring the minimal necessary privilege for the consuming actors and avoiding unauthorized lateral movements, is defined as Micro-Segmentation model. In this post, we are going to explain how Accuknox implements an identity-based micro-segmentation model that provides secure access to workloads using JWT tokens managed by an external identity provider.

Conceptual Model

In a common scenario, an enterprise asset can be exposed to be remotely accessed by external actors like end users, other applications or any other entity that needs to request information from workloads. To perform that with a reduced attack surface, the ZTA (Zero Trust Architecture) points out that the enterprise may choose to implement host-based micro-segmentation using software agents [1]. In this model, each individual request that has a secured endpoint as a destination needs to be dynamically scrutinized in order to grant or deny access based on the identity provided by the source.

Cilium Network Policies

At AccuKnox, Cilium has helped us to implement a micro-segmentation model  based on network policies [2]. In order to establish trust and authorize access to specific endpoints, we  extended the Cilium Network Policy (CNP) in a way that through policy manifests, any individual workload can be secured by making use of requests authorization powered with JSON Web Tokens (JWT) [8].

As Cilium makes use  of Envoy as it’s host proxy for enforcing HTTP and other L7 policies [3] we leveraged the Envoy’s JWT Authentication filter [4] to implement requests authorization based on identities generated by third party identity providers.

Figure 1 - Architecture

Let’s say that a client (e.g. web browser) wants to access a web server inside a secured cluster, the life of the request starts when the client requests from a supported identity provider, one JWT token for a set of audiences [9]. This token is then used by the client to issue the actual request. With the correct policy enforced, Cilium will redirect the incoming request to Envoy where the JWT Authentication filter will fetch JSON Web Key Set (JWKS) [10] from the identity provider to authenticate JWT tokens and finally allow or deny the access (authorization) to the intended endpoint.

The restrictions imposed by implementing micro-segmentation for a particular k8s cluster can be now enforced by applying an ingress security policy. The policy is crafted based on the matchJWT object's specification, which was introduced as an extension to the already existing HTTP L7 policy rule.  The following fragment shows an example:

ingress:
- toPorts:
    - ports:
        - port: "8080"
          protocol: TCP
      rules:
          http:
          - matchJWT:
              - provider: AUTH0
                issuer: "https://client-identity-provider-url/"
                audiences:
                  - '1stAudience'
                  - '2ndAudience'
                jwks_Uri: "https://client-identity-provider-url/jwks.json"
                forward: true
CNP fragment showing matchJWT objec

This policy configures Envoy’s filter to authorize requests destined to port 8080 of any selected endpoint and contains a valid JWT token provided by Auth0 provider [6] for a couple  of audiences.

Client Identity

As a belief that identity is a foundational element to provide authentication and authorization on a zero trust platform, the use of the micro-segmentation solution in addition with a robust identity management plays an important role on the challenge of constantly reduce attack surfaces while keeping the Principle of Least Privilege [7]. While using an identity provider that permits authenticate JWT tokens with signing algorithms is definitively a strong approach, this model used by Accuknox also enables the usage SPIRE/SPIFFE identity solution [5] as identity provider, offering then a complete microservices aware solution for cloud native applications built over Zero Trust platforms.

How To

To give you a  glimpse  about how  this model works in practice, we are  going to  guide you through this tutorial that will expose a simple test scenario to evaluate the micro-segmentation feature.

Create Target Workload

The first step to test a micro-segmentation basic scenario is to create the workload that will be secured with cilium network policy.

kubectl apply -f test/k8sT/manifests/simple-http-test-server.yaml

apiVersion: v1
kind: Pod
metadata:
  name: simple-http-test-server
  labels:
    component: webserver
spec:
  containers:
  - name: simple-http-test-server
    image: python:3
    command: [ "/bin/bash", "-c", "--" ]
    args: [ "python3 -m http.server 7070" ]
simple-http-test-server.yaml

kubectl get pod -A -o wide

Figure 4 - workload created

Now we  have a   running server  lets poke it:

curl -I 10.11.0.232:7070;echo

Figure 5 - Testing web server

After this step we have created a functional web server that is accepting requests from any client. Now we want to  secure this  workload making  it trust only requests received from a recognized client identity.

Micro-Segmentation Policy

In the policy sample below, we are specifying a Cilium Network Policy that selects the target endpoint using the label component: webserver, the same used to create the web server POD. We also want the specified rules to be applied to network traffic destined to TCP port 7070. We created a  test account on Auth0 [6] and used that in the policy as can be noted when we select  the supported identity provider with provider: AUTH0 attribute, set the provider URI with  issuer: "https://dev-8as2ijf5.us.auth0.com/" and also configure the URL for the JWKS fetching in jwksUrl: "https://dev-8as2ijf5.us.auth0.com/.well-known/jwks.json". For  last, we will authorize only requests that contain JWT tokens issued for 2 audiences only, thales-accuknox-1st and thales-accuknox-2nd.

apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
    name: "test-client-identity"
specs:
    - description: Simple policy for authorizing requests by means of Jwt token authentication.
      endpointSelector:
        matchLabels:
          component: webserver
      ingress:
      - toPorts:
        - ports:
          - port: "7070"
            protocol: TCP
          rules:
            http:
            - matchJWT:
              - provider: AUTH0
                issuer: "https://dev-8as2ijf5.us.auth0.com/"
                audiences:
                  - 'thales-accuknox-1st'
                  - 'thales-accuknox-2nd'
                jwksUrl: "https://dev-8as2ijf5.us.auth0.com/.well-known/jwks.json"
                forward: true
                fromHeaders: false
                fromParams: false
client-identity.yaml

Figure 6 - Let's now apply the policy and get it enforced:

Kubectl apply -f test/k8sT/manifests/client-identity-yaml

Figure  7 - micro-segmentation cliente-identity policy enforced

Now, with the policy enforced, we repeat the same test  as before. As expected, the request is NOT AUTHORIZED (Status 401), because we don’t use a required JWT token on the request. Note that the response is  sent to the client by the Envoy proxy:

Figure 8 - Jwt is missing response sent by Envoy

Finally, we want try using a valid token generated by Auth0 API:

Figure 9 - Request authorized with valid JWT token

Cool! The request was received by Envoy filter, the token was then authenticated using the fetched JWKS and the audience verified and finally the request was delivered to the actual workload running the web server while the client got its expected response.

PoC

The practical usage of the policy is as straightforward as shown in the HowTo above, but also on this feature video. The objective here is to demonstrate how the authorization mechanism acts on an arbitrary cluster enabling the desired  micro-segmentation discussed in this post.

Conclusion

It would now be possible for Accuknox customers to put Authorization rules such that only certain clients/users would be allowed access to a service bringing granular security to cloud native applications. In practical  terms, we are enabling the fundamental pillar for Zero Trust Architecture which is the Micro-Segmentation model.

References

[1]https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-207.pdf

[2]https://docs.cilium.io/en/latest/concepts/kubernetes/policy/#k8s-policy

[3]https://github.com/cilium/proxy

[4]https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/jwt_authn/v3/config.proto#jwt-authentication

[5]https://accuknox.com/blogs/workload-identity-for-network-security-with-spiffe/

[6]https://auth0.com/

[7]https://accuknox.com/blogs/kubernetes-workload-identity/

[8]https://jwt.io/introduction

[9]https://www.rfc-editor.org/rfc/rfc7519#section-4.1.3

[10]https://auth0.com/docs/security/tokens/json-web-tokens/json-web-key-sets