-
Notifications
You must be signed in to change notification settings - Fork 34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update tutorials to reference 'Getting Started' as prereq #1129
Changes from all commits
9746aae
98b2ba2
130ada9
8f81327
4c2fb8a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
# Enforcing authentication & authorization with Kuadrant AuthPolicy | ||
|
||
This guide walks you through the process of setting up a local Kubernetes cluster with Kuadrant where you will protect [Gateway API](https://gateway-api.sigs.k8s.io/) endpoints by declaring Kuadrant AuthPolicy custom resources. | ||
This tutorial walks you through the process of setting up a local Kubernetes cluster with Kuadrant where you will protect [Gateway API](https://gateway-api.sigs.k8s.io/) endpoints by declaring Kuadrant AuthPolicy custom resources. | ||
|
||
Three AuthPolicies will be declared: | ||
|
||
|
@@ -14,7 +14,7 @@ Topology: | |
``` | ||
┌─────────────────────────┐ | ||
│ (Gateway) │ ┌───────────────┐ | ||
│ kuadrant-ingressgateway │◄──│ (AuthPolicy) │ | ||
│ external │◄──│ (AuthPolicy) │ | ||
│ │ │ gw-auth │ | ||
│ * │ └───────────────┘ | ||
└─────────────────────────┘ | ||
|
@@ -35,24 +35,87 @@ Topology: | |
└─────────────────┘ | ||
``` | ||
|
||
## Setup the environment | ||
## Prerequisites | ||
|
||
Follow this [setup doc](https://github.com/Kuadrant/kuadrant-operator/blob/main/doc/install/install-make.md) to set up your environment before continuing with this doc. | ||
- Kubernetes cluster with Kuadrant operator installed. See our [Getting Started](/getting-started) guide for more information. | ||
- [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl) command line tool. | ||
|
||
### Setup environment variables | ||
|
||
Set the following environment variables used for convenience in this tutorial: | ||
|
||
```bash | ||
export KUADRANT_GATEWAY_NS=api-gateway # Namespace for the example Gateway | ||
export KUADRANT_GATEWAY_NAME=external # Name for the example Gateway | ||
export KUADRANT_DEVELOPER_NS=toystore # Namespace for an example toystore app | ||
|
||
``` | ||
|
||
### Create an Ingress Gateway | ||
|
||
Create the namespace the Gateway will be deployed in: | ||
|
||
```bash | ||
kubectl create ns ${KUADRANT_GATEWAY_NS} | ||
``` | ||
|
||
Create a gateway using toystore as the listener hostname: | ||
|
||
```bash | ||
kubectl apply -f - <<EOF | ||
apiVersion: gateway.networking.k8s.io/v1 | ||
kind: Gateway | ||
metadata: | ||
name: ${KUADRANT_GATEWAY_NAME} | ||
namespace: ${KUADRANT_GATEWAY_NS} | ||
labels: | ||
kuadrant.io/gateway: "true" | ||
spec: | ||
gatewayClassName: istio | ||
listeners: | ||
- name: http | ||
protocol: HTTP | ||
port: 80 | ||
allowedRoutes: | ||
namespaces: | ||
from: All | ||
EOF | ||
``` | ||
|
||
Check the status of the `Gateway` ensuring the gateway is Accepted and Programmed: | ||
|
||
```bash | ||
kubectl get gateway ${KUADRANT_GATEWAY_NAME} -n ${KUADRANT_GATEWAY_NS} -o=jsonpath='{.status.conditions[?(@.type=="Accepted")].message}{"\n"}{.status.conditions[?(@.type=="Programmed")].message}{"\n"}' | ||
``` | ||
|
||
### Deploy the Toy Store sample application (Persona: _App developer_) | ||
|
||
|
||
Create the namespace for the toystore API: | ||
|
||
```bash | ||
kubectl create ns ${KUADRANT_DEVELOPER_NS} | ||
``` | ||
Deploy the Toy store | ||
```sh | ||
kubectl apply -f examples/toystore/toystore.yaml | ||
kubectl apply -f https://raw.githubusercontent.com/Kuadrant/kuadrant-operator/refs/heads/main/examples/toystore/toystore.yaml -n ${KUADRANT_DEVELOPER_NS} | ||
``` | ||
|
||
Create the Toy Store HTTPRoute | ||
```bash | ||
|
||
kubectl apply -f - <<EOF | ||
apiVersion: gateway.networking.k8s.io/v1 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. w/ helm guide, GW API v1.1 is installed kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: toystore
namespace: ${KUADRANT_DEVELOPER_NS}
labels:
app: toystore
spec:
parentRefs:
- name: ${KUADRANT_GATEWAY_NAME}
namespace: ${KUADRANT_GATEWAY_NS}
hostnames:
- api.toystore.com
rules:
- name: rule-1
matches:
- method: GET
path:
type: PathPrefix
value: "/cars"
- method: GET
path:
type: PathPrefix
value: "/dolls"
backendRefs:
- name: toystore
port: 80
- name: rule-2
matches:
- path:
type: PathPrefix
value: "/admin"
backendRefs: <....
Error from server (BadRequest): error when creating "STDIN": HTTPRoute in version "v1" cannot be handled as a HTTPRoute: strict decoding error: unknown field "spec.rules[0].name", unknown field "spec.rules[1].name" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. will continue tomorrow There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @david-martin did you install your stack with helm (via the guide on https://artifacthub.io/packages/helm/kuadrant/kuadrant-operator) + There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IIRC, named rules are in 1.2[1], I guess this won't work as the helm guide currently installs the v1.1 CRDs [1] https://kubernetes.io/blog/2024/11/21/gateway-api-v1-2/#new-additions-to-experimental-channel went without to push forward: kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: toystore
namespace: ${KUADRANT_DEVELOPER_NS}
labels:
app: toystore
spec:
parentRefs:
- name: ${KUADRANT_GATEWAY_NAME}
namespace: ${KUADRANT_GATEWAY_NS}
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 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I haven't tried the tutorials where I made the updates to add rule names. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, just looks bad ootb as the helm guide steers you towards 1.1 if we're not highlighting sectionNames, perhaps we don't need right now There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Both the helm install and olm install reference 1.1.0 of the gateway api CRDs.
The reason for this was to support sectionNames in a policy targetRef if gateway api 1.1 is used (which is the case with OSSM support at present on OpenShift). I'll back out the changes There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated |
||
kind: HTTPRoute | ||
metadata: | ||
name: toystore | ||
namespace: ${KUADRANT_DEVELOPER_NS} | ||
labels: | ||
app: toystore | ||
spec: | ||
parentRefs: | ||
- name: kuadrant-ingressgateway | ||
namespace: gateway-system | ||
- name: ${KUADRANT_GATEWAY_NAME} | ||
namespace: ${KUADRANT_GATEWAY_NS} | ||
hostnames: | ||
- api.toystore.com | ||
rules: | ||
|
@@ -81,25 +144,25 @@ EOF | |
Export the gateway hostname and port: | ||
|
||
```sh | ||
export INGRESS_HOST=$(kubectl get gtw kuadrant-ingressgateway -n gateway-system -o jsonpath='{.status.addresses[0].value}') | ||
export INGRESS_PORT=$(kubectl get gtw kuadrant-ingressgateway -n gateway-system -o jsonpath='{.spec.listeners[?(@.name=="http")].port}') | ||
export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT | ||
export KUADRANT_INGRESS_HOST=$(kubectl get gtw ${KUADRANT_GATEWAY_NAME} -n ${KUADRANT_GATEWAY_NS} -o jsonpath='{.status.addresses[0].value}') | ||
export KUADRANT_INGRESS_PORT=$(kubectl get gtw ${KUADRANT_GATEWAY_NAME} -n ${KUADRANT_GATEWAY_NS} -o jsonpath='{.spec.listeners[?(@.name=="http")].port}') | ||
export KUADRANT_GATEWAY_URL=${KUADRANT_INGRESS_HOST}:${KUADRANT_INGRESS_PORT} | ||
``` | ||
|
||
Send requests to the application unprotected: | ||
|
||
```sh | ||
curl -H 'Host: api.toystore.com' http://$GATEWAY_URL/cars -i | ||
curl -H 'Host: api.toystore.com' http://$KUADRANT_GATEWAY_URL/cars -i | ||
# HTTP/1.1 200 OK | ||
``` | ||
|
||
```sh | ||
curl -H 'Host: api.toystore.com' http://$GATEWAY_URL/dolls -i | ||
curl -H 'Host: api.toystore.com' http://$KUADRANT_GATEWAY_URL/dolls -i | ||
# HTTP/1.1 200 OK | ||
``` | ||
|
||
```sh | ||
curl -H 'Host: api.toystore.com' http://$GATEWAY_URL/admin -i | ||
curl -H 'Host: api.toystore.com' http://$KUADRANT_GATEWAY_URL/admin -i | ||
# HTTP/1.1 200 OK | ||
``` | ||
|
||
|
@@ -118,6 +181,7 @@ apiVersion: kuadrant.io/v1 | |
kind: AuthPolicy | ||
metadata: | ||
name: toystore-authn | ||
namespace: ${KUADRANT_DEVELOPER_NS} | ||
spec: | ||
targetRef: | ||
group: gateway.networking.k8s.io | ||
|
@@ -140,6 +204,7 @@ apiVersion: kuadrant.io/v1 | |
kind: AuthPolicy | ||
metadata: | ||
name: toystore-admins | ||
namespace: ${KUADRANT_DEVELOPER_NS} | ||
spec: | ||
targetRef: | ||
group: gateway.networking.k8s.io | ||
|
@@ -189,25 +254,25 @@ EOF | |
Send requests to the application protected by Kuadrant: | ||
|
||
```sh | ||
curl -H 'Host: api.toystore.com' http://$GATEWAY_URL/cars -i | ||
curl -H 'Host: api.toystore.com' http://$KUADRANT_GATEWAY_URL/cars -i | ||
# HTTP/1.1 401 Unauthorized | ||
# www-authenticate: APIKEY realm="api-key-authn" | ||
# x-ext-auth-reason: credential not found | ||
``` | ||
|
||
```sh | ||
curl -H 'Host: api.toystore.com' -H 'Authorization: APIKEY iamaregularuser' http://$GATEWAY_URL/cars -i | ||
curl -H 'Host: api.toystore.com' -H 'Authorization: APIKEY iamaregularuser' http://$KUADRANT_GATEWAY_URL/cars -i | ||
# HTTP/1.1 200 OK | ||
``` | ||
|
||
```sh | ||
curl -H 'Host: api.toystore.com' -H 'Authorization: APIKEY iamaregularuser' http://$GATEWAY_URL/admin -i | ||
curl -H 'Host: api.toystore.com' -H 'Authorization: APIKEY iamaregularuser' http://$KUADRANT_GATEWAY_URL/admin -i | ||
# HTTP/1.1 403 Forbidden | ||
# x-ext-auth-reason: Unauthorized | ||
``` | ||
|
||
```sh | ||
curl -H 'Host: api.toystore.com' -H 'Authorization: APIKEY iamanadmin' http://$GATEWAY_URL/admin -i | ||
curl -H 'Host: api.toystore.com' -H 'Authorization: APIKEY iamanadmin' http://$KUADRANT_GATEWAY_URL/admin -i | ||
# HTTP/1.1 200 OK | ||
``` | ||
|
||
|
@@ -216,16 +281,17 @@ curl -H 'Host: api.toystore.com' -H 'Authorization: APIKEY iamanadmin' http://$G | |
Create the policy: | ||
|
||
```sh | ||
kubectl -n gateway-system apply -f - <<EOF | ||
kubectl apply -f - <<EOF | ||
apiVersion: kuadrant.io/v1 | ||
kind: AuthPolicy | ||
metadata: | ||
name: gw-auth | ||
namespace: ${KUADRANT_GATEWAY_NS} | ||
spec: | ||
targetRef: | ||
group: gateway.networking.k8s.io | ||
kind: Gateway | ||
name: kuadrant-ingressgateway | ||
name: ${KUADRANT_GATEWAY_NAME} | ||
defaults: | ||
strategy: atomic | ||
rules: | ||
|
@@ -257,10 +323,11 @@ apiVersion: gateway.networking.k8s.io/v1 | |
kind: HTTPRoute | ||
metadata: | ||
name: other | ||
namespace: ${KUADRANT_DEVELOPER_NS} | ||
spec: | ||
parentRefs: | ||
- name: kuadrant-ingressgateway | ||
namespace: gateway-system | ||
- name: ${KUADRANT_GATEWAY_NAME} | ||
namespace: ${KUADRANT_GATEWAY_NS} | ||
hostnames: | ||
- "*.other-apps.com" | ||
EOF | ||
|
@@ -269,7 +336,7 @@ EOF | |
Send requests to the route protected by the default policy set at the level of the gateway: | ||
|
||
```sh | ||
curl -H 'Host: foo.other-apps.com' http://$GATEWAY_URL/ -i | ||
curl -H 'Host: foo.other-apps.com' http://$KUADRANT_GATEWAY_URL/ -i | ||
# HTTP/1.1 403 Forbidden | ||
# content-type: application/json | ||
# x-ext-auth-reason: Unauthorized | ||
|
@@ -280,9 +347,3 @@ curl -H 'Host: foo.other-apps.com' http://$GATEWAY_URL/ -i | |
# "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." | ||
# } | ||
``` | ||
jasonmadigan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
## Cleanup | ||
|
||
```sh | ||
make local-cleanup | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just because this will 404 on GH, maybe we include an absolute link?
https://docs.kuadrant.io/latest/getting-started
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(I realise this will 404 too right now until we do our next stable release)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jasonmadigan summarising some options discussed offline:
The links 404ing are a symptom of how these docs are being used for the docs site by mkdocs.
The dual target is not ideal, given this limitation around relative links if referencing a doc from another repo.
I'm not keen on having the absolute url as that gets treated as an external url by the mkdocs tooling and potentially bypasses some CI checks (like detecting 404s)
If you're in agreement, how about we go with 3 (as that's already the case potentially for other docs),
with an agreement to investigate 4 as a long term option, at least for these docs in the kuadrant operator site.
I wonder if there's a need to have these docs in this repo as well, if we have them in the docs repo and site, and link to the site from the main README.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems like the most pragmatic option to me. can work on 4 longer term.