Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/guicassolato/kuadrant-data-privacy-appsec

Kuadrant Demo: Data Privacy and Application Security
https://github.com/guicassolato/kuadrant-data-privacy-appsec

Last synced: 15 days ago
JSON representation

Kuadrant Demo: Data Privacy and Application Security

Awesome Lists containing this project

README

        

# Demo: Data Privacy and Application Security using Kuadrant

## Intro

Data Privacy and App Security are two major concerns related to system engineering and software applications often expressed by companies.

Data Privacy for global operations usually translates to multi-AZ/multi-region (multi-cluster architecture) at some point, and to the requirement of being more conscious about Personal Identifiable Information (PII) flying across regions overall. As for App Security, currently the top-1 concern is protecting/mitigating against Denial of Service (DoS) attacks.

To help tackle these issues, each of a set of solutions play an important part. Sometimes, the solutions for one problem overlap with another, allowing leveraging the economies of scale of applying one well thought-out software architecture that fits and solves for multiple problems at once.

This guide walks you through the steps of deploying an example system architecture, that is cloud-based, mainly composed of open source technologies, that combines a series of capabilities to address two main goals:



Goal
Capability
Reasoning





Reduce client's PII exposure on E/W service communication across regions

Track: Data Privacy

Geo
Data isolation, compliance with regional regulations


Token exchange
For cross-cluster authentication – more limited scope and less-to-zero PII propagation



Mitigate DoS risks

Track: App Security

Flexible scaling
Kubernetes superpower – first horizontally, sometimes vertically as well, if possible


IP-RL
First layer of protection


Public Key Authentication methods
E.g. OpenId Connect, mTLS – to avoid user/client ID exposure, avoid ID lookup bottleneck


Efficient “offline” signature validation
To avoid token lookup bottleneck


Short-lived authentication tokens and/or support for immediate revocation
To mitigate/remediate attacks that pass authentication; trade-offs between the two options to be considered


Limited scope
Isulation – to mitigate the impact of attacks that pass authentication


Authenticated-RL
Isulation – to mitigate the impact of attacks that pass authentication


Geo
Isulation – to mitigate the impact of attacks that pass authentication

### User story

The back story behind this use case is an enterprise that provides a simple HTTP service, and that now has to open a new cloud-based infrastructure at another region due to local data privacy regulations. Even though the service does not store personal data, the very association of HTTP requests to PII is considered a violation. Due to characteristics of how the service was designed as well as cost constraints, the company is not ready to run the main workload at all regions. Nevertheless, the company cannot give up on the users living across the globe where the regulations now impose more restrictive data privacy requirements.

Additionally, the company also wants to seize this opportunity of reviewing their cloud architecture to strengthen their measures to counter and mitigate against Denial of Service (DoS) threats, including the more specialized form Distributed Denial of Service (DDoS.)

### Stack

- [Kuadrant](https://kuadrant.io)
- [Keycloak](https://www.keycloak.org/) ⭐️
- [Istio](https://istio.io) ⭐️
- [cert-manager](https://cert-manager.io/) ⭐️
- [Kubernetes Gateway API](https://gateway-api.sigs.k8s.io)
- [Skupper](https://skupper.io)
- [MetalLB](https://metallb.org/) ⭐️
- [AWS Route53](https://aws.amazon.com/route53)
- [Open Cluster Management](https://open-cluster-management.io/) ⭐️
- [Operator Lifecycle Manager](https://olm.operatorframework.io/) ⭐️
- [Kubernetes](https://kubernetes.io/) ⭐️

⭐️ CNCF projects

### Architecture

![Architecture](images/data-privacy-and-app-sec.jpg)


High-level description of the components (manifest):
- 2 Kuberentes clusters – both connected through the cloud DNS service (AWS Route53) and distributing the incoming traffic directed to the workload service, according to the geolocation of the client:
- **kind-mgc-control-plane**: control plane for the multi-cluster orchestration and host of the application service workload.
- **kind-mgc-workload-1**: entrypoint cluster introduced to receive the traffic originated in the EU region, connected via E/W Skupper network to the main cluster that runs the service workload.

- 1 application service workload ("**echo**"): stateless single-instance application service that runs in the **kind-mgc-control-plane** cluster and can be consumed via HTTP at the `echo.MGC_ZONE_ROOT_DOMAIN` hostname from either region; requires E/W authentication tokens known as "Festival Wristbands" and it is rate-limited per user/client.

- 2 North-South (N/S) ingress gateways – managed by the multi-cluster orchestration and implemented in each cluster by Istio; listen to HTTP requests at the `*.MGC_ZONE_ROOT_DOMAIN` wildcard (exposed to the internet with support by MetalLB), with TLS enabled by attachment of a Kuadrant policy (certificates handled by cert-manager), as well as first-layer authentication enforced, with a configured token exchange step (for Festival Wristbands), before handing the traffic over to backend services; connected in the backend to the East-West (E/W) gateway via local route or Skupper network.

- 1 East-West (E/W) gateway – deployed to the **kind-mgc-control-plane** cluster, connected to the North-South (N/S) ingress gateways via local route and Skupper network, handles the traffic internally to the application service.

- Kuadrant Multi-Cluster Gateways ("**multi-cluster-gateways**"): handles the DNS policy and configuration with the cloud DNS service (AWS Route53), and leverages Open Cluster Management to orchestrate the propagation of ingress gateways and configuration across clusters.

- Kuadrant Service Protection ("**kuadrant-system**"): enforces the auth and rate-limit policies in the data plane, leveraging Authorino external authorization service and Limitador global rate-limiting service.

### Personas

3 personas (described below) will be represented in the tasks involved in deploying and consuming the system architecture described above.

- **👷🏾‍♀️ Platform Engineer**

Responsible for creating the clusters and configuring the N/S and E/W gateways, as well as applying the 1st-layer security policies. In more complex scenarios, these responsibilities can be refined into the rather specialized roles of: Infrastructure Provider, Cluster Operator, Network Administrator, and Gateway Administrator.

- **🧑🏻‍💻 Application Developer**

Responsible for building and deploying the application service, as well as connecting the service to gateways via specialized routes, and applying the policies that protect the service. In more complex scenarios, these responsibilities can be refined into the rather specialized roles of: Application Developer, and Policy Manager.

- **👩🏿‍💼 Client**

Consumes the application service from either of the available regions, by authenticating with the authentication server first, then sending requests to the service via `curl`.

Other responsibilities abstracted in this guide include:
- Management of user/client identities in the Identity and Access Managament (IAM) system

Each group of tasks below is identified with the corresponding persona responsible for executing the tasks.

## Run the demo

### Requirements

Components you probably already have available in your local environment (minimum required versions indicated):
- [Docker](https://docker.io) (v24.0.6)
- [Kind](https://kind.sigs.k8s.io/) (v0.17.0)
- [kubectl](https://kubernetes.io/docs/reference/kubectl/) (v1.27.2)
- [curl](https://curl.se) (v8.1.2)
- [docker-mac-net-connect](https://github.com/chipmk/docker-mac-net-connect) (v0.1.2, macos only)
- [jq](https://stedolan.github.io/jq) (v1.6)

Make sure to prepare in advance as well:
- AWS account with a root domain and public Hosted Zone configured in Route53
- [Skupper CLI](https://skupper.io/start/index.html#step-1-install-the-skupper-commandline-tool-in-your-environment) (v1.4.3)

Certify your Docker environment is clean and with enough space to pull several container images.


### ❶ Create the clusters ⋅ 👷🏾‍♀️ Platform Engineer

Export the shell variables that will be used across this demo:

```sh
export MGC_ZONE_ROOT_DOMAIN=example.net \
MGC_AWS_DNS_PUBLIC_ZONE_ID= \
MGC_AWS_ACCESS_KEY_ID= \
MGC_AWS_SECRET_ACCESS_KEY= \
MGC_AWS_REGION=eu-west-1 \
MGC_BRANCH=release-0.1
```

Create the hub and spoke clusters, with the latest version of Kuadrant Multicluster Gateway Controller and Service Protection installed and ready to use in both clusters:

```sh
curl "https://raw.githubusercontent.com/kuadrant/multicluster-gateway-controller/${MGC_BRANCH}/hack/quickstart-setup.sh" | bash
```

The following Kubernetes clusters will be create and installed with Kuadrant:

| Cluster | Capacity | Workload cluster | Ingress cluster | Echo Service |
|----------------------------|:----------------:|:----------------:|:----------------:|:------------:|
| **kind-mgc-control-plane** | Multicluster Hub | Yes | Yes (US traffic) | Yes |
| **kind-mgc-workload-1** | Spoke | Yes | Yes (EU traffic) | No |


### ❷ Connect the hub cluster ⋅ 👷🏾‍♀️ Platform Engineer

Create the base definition for your managed N/S ingress gateways:

```sh
kubectl --context kind-mgc-control-plane apply -f - <

### ❸ Setup E/W plumbing ⋅ 👷🏾‍♀️ Platform Engineer

Create the E/W gateway:

```sh
kubectl --context kind-mgc-control-plane apply -f - <

### ❹ Setup authentication for N/S ⋅ 👷🏾‍♀️ Platform Engineer

Install Keycloak:

```sh
kubectl --context kind-mgc-control-plane create namespace keycloak
kubectl --context kind-mgc-control-plane apply -f https://raw.githubusercontent.com/kuadrant/authorino-examples/main/keycloak/keycloak-deploy.yaml -n keycloak
kubectl --context kind-mgc-control-plane apply -f - <

### ❺ Deploy the application ⋅ 🧑🏻‍💻 Application Developer

Deploy the application service onto the **kind-mgc-control-plane** cluster. The application attaches directly to the E/W gateway and indirectly to N/S:

```sh
kubectl create namespace echo
kubectl --context kind-mgc-control-plane apply -f - <

### ❻ Connect the spoke cluster ⋅ 👷🏾‍♀️ Platform Engineer

Introduce the **kind-mgc-workload-1** cluster as a second ingress cluster:

```sh
kubectl --context kind-mgc-control-plane label managedcluster kind-mgc-workload-1 ingress-cluster=true
kubectl --context kind-mgc-control-plane patch placement http-gateway -n multi-cluster-gateways --type='json' -p='[{"op": "replace", "path": "/spec/numberOfClusters", "value": 2}]'
kubectl --context kind-mgc-control-plane label --overwrite managedcluster kind-mgc-control-plane kuadrant.io/lb-attribute-geo-code=US
kubectl --context kind-mgc-control-plane label --overwrite managedcluster kind-mgc-workload-1 kuadrant.io/lb-attribute-geo-code=EU
```

Create the multi-cluster E/W plumbing:

```sh
skupper --context kind-mgc-control-plane --namespace kuadrant-multi-cluster-gateways init
skupper --context kind-mgc-control-plane --namespace kuadrant-multi-cluster-gateways token create /tmp/mgc-control-plane.token
skupper --context kind-mgc-control-plane --namespace kuadrant-multi-cluster-gateways service create east-west-skupper 80
skupper --context kind-mgc-control-plane --namespace kuadrant-multi-cluster-gateways service bind east-west-skupper service east-west-istio
skupper --context kind-mgc-workload-1 --namespace kuadrant-multi-cluster-gateways init
skupper --context kind-mgc-workload-1 --namespace kuadrant-multi-cluster-gateways link create /tmp/mgc-control-plane.token
```

Attach a HTTPRoute to the N/S gateway, pointing to the `east-west-istio` service in the **kind-mgc-control-plane** cluster (via Skupper proxy):

```sh
kubectl --context kind-mgc-workload-1 apply -f - <

### ❼ Consume the service | 👩🏿‍💼 Client

#### From the default (US) region

```sh
export ACCESS_TOKEN=$(curl -k https://auth.$MGC_ZONE_ROOT_DOMAIN/realms/kuadrant/protocol/openid-connect/token --resolve auth.$MGC_ZONE_ROOT_DOMAIN:443:172.31.200.0 -s -d 'grant_type=password' -d 'client_id=demo' -d 'username=john' -d 'password=p' -d 'scope=openid' | jq -r .access_token); echo $ACCESS_TOKEN
```

```sh
curl -k https://echo.$MGC_ZONE_ROOT_DOMAIN --resolve echo.$MGC_ZONE_ROOT_DOMAIN:443:172.31.200.0 -H "Authorization: Bearer $ACCESS_TOKEN" -i
```

Inspect the tokens:

```sh
echo "-- N/S --"; jq -R 'split(".") | .[1] | @base64d | fromjson' <<< "$ACCESS_TOKEN"
echo "-- E/W --"; jq -R 'split(".") | .[1] | @base64d | fromjson' <<< "$(curl -k https://echo.$MGC_ZONE_ROOT_DOMAIN --resolve echo.$MGC_ZONE_ROOT_DOMAIN:443:172.31.200.0 -H "Authorization: Bearer $ACCESS_TOKEN" -i -s | grep Wristband | awk '{print $3}')"
```

#### From the EU region

```sh
export ACCESS_TOKEN=$(curl -k https://auth.$MGC_ZONE_ROOT_DOMAIN/realms/kuadrant/protocol/openid-connect/token --resolve auth.$MGC_ZONE_ROOT_DOMAIN:443:172.31.201.0 -s -d 'grant_type=password' -d 'client_id=demo' -d 'username=jane' -d 'password=p' -d 'scope=openid' | jq -r .access_token); echo $ACCESS_TOKEN
```

```sh
curl -k https://echo.$MGC_ZONE_ROOT_DOMAIN --resolve echo.$MGC_ZONE_ROOT_DOMAIN:443:172.31.201.0 -H "Authorization: Bearer $ACCESS_TOKEN" -i
```

Inspect the tokens:

```sh
echo "-- N/S --"; jq -R 'split(".") | .[1] | @base64d | fromjson' <<< "$ACCESS_TOKEN"
echo "-- E/W --"; jq -R 'split(".") | .[1] | @base64d | fromjson' <<< "$(curl -k https://echo.$MGC_ZONE_ROOT_DOMAIN --resolve echo.$MGC_ZONE_ROOT_DOMAIN:443:172.31.201.0 -H "Authorization: Bearer $ACCESS_TOKEN" -i -s | grep Wristband | awk '{print $3}')"
```


## Cleanup

```sh
kind delete cluster --name mgc-control-plane
kind delete cluster --name mgc-workload-1
```