Skip to content

Instantly share code, notes, and snippets.

@guicassolato
Last active October 16, 2023 15:21
Show Gist options
  • Save guicassolato/7dc98df842a89657050514d31daadaa3 to your computer and use it in GitHub Desktop.
Save guicassolato/7dc98df842a89657050514d31daadaa3 to your computer and use it in GitHub Desktop.
Demo: AuthPolicy v1beta2

Demo: AuthPolicy v1beta2

This demo walks you through the process of setting up a local Kubernetes cluster with Kuadrant, where you will protect Gateway API endpoints by declaring Kuadrant AuthPolicy custom resources.

Requisites

Run the demo

① Setup

Clone the repo:

git clone -b authpolicy-v2 [email protected]:Kuadrant/kuadrant-operator.git && cd kuadrant-operator

Run the following command to create a local Kubernetes cluster with Kind, install & deploy Kuadrant:

make local-setup

Request an instance of Kuadrant:

kubectl -n kuadrant-system apply -f - <<EOF
apiVersion: kuadrant.io/v1beta1
kind: Kuadrant
metadata:
  name: kuadrant
spec: {}
EOF

② Deploy a sample API

kubectl apply -f examples/toystore/toystore.yaml

kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: toystore
spec:
  parentRefs:
  - name: istio-ingressgateway
    namespace: istio-system
  hostnames:
  - api.toystore.com
  rules:
  - matches:
    - method: GET
      path:
        type: PathPrefix
        value: "/cars"
    - method: GET
      path:
        type: PathPrefix
        value: "/dolls"
    backendRefs:
    - name: toystore
      port: 80
  - matches:
    - path:
        type: PathPrefix
        value: "/admin"
    backendRefs:
    - name: toystore
      port: 80
EOF

Send requests to the API unprotected:

curl -H 'Host: api.toystore.com' http://localhost:9080/cars -i
# HTTP/1.1 200 OK
curl -H 'Host: api.toystore.com' http://localhost:9080/dolls -i
# HTTP/1.1 200 OK
curl -H 'Host: api.toystore.com' http://localhost:9080/admin -i
# HTTP/1.1 200 OK

③ Protect the API

Create an AuthPolicy to enforce the following auth rules:

  • Authentication:
    • All users must present a valid API key
  • Authorization:
    • /admin* routes require user mapped to the admins group (kuadrant.io/groups=admins annotation added to the Kubernetes API key Secret)
kubectl apply -f - <<EOF
apiVersion: kuadrant.io/v1beta2
kind: AuthPolicy
metadata:
  name: toystore
spec:
  targetRef:
    group: gateway.networking.k8s.io
    kind: HTTPRoute
    name: toystore
  rules:
    authentication:
      "api-key-authn":
        apiKey:
          selector: {}
        credentials:
          authorizationHeader:
            prefix: APIKEY
    authorization:
      "only-admins":
        opa:
          rego: |
            groups := split(object.get(input.auth.identity.metadata.annotations, "kuadrant.io/groups", ""), ",")
            allow { groups[_] == "admins" }
        routeSelectors:
        - matches:
          - path:
              type: PathPrefix
              value: "/admin"
EOF
(Optional) Verify internal custom resources reconciled by Kuadrant

Verify the Istio AuthorizationPolicy created in association with the policy:

kubectl get authorizationpolicy/on-istio-ingressgateway-using-toystore -n istio-system -o yaml

Verify the Authorino AuthConfig created in association with the policy:

kubectl get authconfig/ap-default-toystore -o yaml

Create the API keys:

kubectl apply -f -<<EOF
apiVersion: v1
kind: Secret
metadata:
  name: api-key-regular-user
  labels:
    authorino.kuadrant.io/managed-by: authorino
stringData:
  api_key: iamaregularuser
type: Opaque
---
apiVersion: v1
kind: Secret
metadata:
  name: api-key-admin-user
  labels:
    authorino.kuadrant.io/managed-by: authorino
  annotations:
    kuadrant.io/groups: admins
stringData:
  api_key: iamanadmin
type: Opaque
EOF

Send requests to the API protected by Kuadrant:

curl -H 'Host: api.toystore.com' http://localhost:9080/cars -i
# HTTP/1.1 401 Unauthorized
curl -H 'Host: api.toystore.com' -H 'Authorization: APIKEY iamaregularuser' http://localhost:9080/cars -i
# HTTP/1.1 200 OK
curl -H 'Host: api.toystore.com' -H 'Authorization: APIKEY iamaregularuser' http://localhost:9080/admin -i
# HTTP/1.1 403 Forbidden
curl -H 'Host: api.toystore.com' -H 'Authorization: APIKEY iamanadmin' http://localhost:9080/admin -i
# HTTP/1.1 200 OK

④ Create a default "deny-all" policy at the level of the gateway

Create the policy:

kubectl -n istio-system apply -f - <<EOF
apiVersion: kuadrant.io/v1beta2
kind: AuthPolicy
metadata:
  name: gw-auth
spec:
  targetRef:
    group: gateway.networking.k8s.io
    kind: Gateway
    name: istio-ingressgateway
  rules:
    authorization:
      deny-all:
        opa:
          rego: "allow = false"
    response:
      unauthorized:
        headers:
          "content-type":
            value: application/json
        body:
          value: |
            {
              "error": "Forbidden",
              "message": "Access denied by default by the gateway operator. If you are the administrator of the service, create a specific auth policy for the route."
            }
EOF

The policy won't be effective until there is at least one accepted route not yet protected by another more specific policy attached to it.

Create a route that will inherit the default policy attached to the gateway:

kubectl apply -f -<<EOF
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: other
spec:
  parentRefs:
  - name: istio-ingressgateway
    namespace: istio-system
  hostnames:
  - "*.other-apps.com"
EOF
(Optional) Verify internal custom resources reconciled by Kuadrant

Verify the Istio AuthorizationPolicy created in association with the policy:

kubectl get authorizationpolicy/on-istio-ingressgateway -n istio-system -o yaml

Verify the Authorino AuthConfig created in association with the policy:

kubectl get authconfig/ap-istio-system-gw-auth -n istio-system -o yaml

Send requests to the route protected by the default policy set at the level of the gateway:

curl -H 'Host: foo.other-apps.com' http://localhost:9080/ -i
# HTTP/1.1 403 Forbidden

Cleanup

make local-cleanup
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment