Skip to content
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

External Auth ~ish #92

Merged
merged 73 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
839e329
Remove use of filter in get_attribute
adam-cattermole Aug 16, 2024
2428cb0
Minor refactor of rate-limit service
adam-cattermole Aug 16, 2024
4e59d17
Add initial implementation of auth service
adam-cattermole Aug 16, 2024
3eb9974
Pass in the host to set in context_extensions
adam-cattermole Aug 16, 2024
5a2e2b1
Genericise the service to send any type of M
adam-cattermole Aug 21, 2024
ebfa96e
Use new header resolver in the service
adam-cattermole Aug 22, 2024
d5d6ad7
Fix tests using header resolver
adam-cattermole Aug 22, 2024
db504ba
Ignore authservice until used
adam-cattermole Aug 28, 2024
cb114c8
Create service at configuration level
adam-cattermole Aug 29, 2024
b9f979a
Add and use extensions from configuration
adam-cattermole Aug 29, 2024
6a6f6cb
Update tests to use new config
adam-cattermole Aug 29, 2024
3fa4ddd
[feat] Action dispatcher state machine, naive impl
didierofrivia Aug 27, 2024
2aacc89
[feat] A simplistic approach, agnostic to extension type
didierofrivia Aug 30, 2024
65786d5
[tmp] Allowing dead code
didierofrivia Sep 2, 2024
8d4ee0e
[refactor] Changing name to `Operation` instead of `Action`
didierofrivia Sep 2, 2024
94d006b
[refactor] Configuration, adding Actions
didierofrivia Sep 3, 2024
914b1d8
[wip, refactor] GrpcServiceHandler builds message
didierofrivia Sep 3, 2024
c938e6b
[clean] Removing obsolete code
didierofrivia Sep 3, 2024
e6460e7
[refactor] OperationDispatcher triggering procedures
didierofrivia Sep 3, 2024
888e983
[refactor] Wiring up altogether
didierofrivia Sep 3, 2024
5f73f05
[refactor] Implementing own Message for GrpcMessage
didierofrivia Sep 4, 2024
87afee3
[refactor] Inlucing Extension within Service and Operation as Rc
didierofrivia Sep 4, 2024
bec2faa
[refactor] OperationDispatcher.next() returns Option<Operation>
didierofrivia Sep 4, 2024
ea028ab
[refactor] Wiring up with the new API
didierofrivia Sep 4, 2024
edc0ef9
[refactor] grpc_call function delegated to the caller
didierofrivia Sep 4, 2024
502d62b
[refactor] Operation responsible of providing hostcalls fns
didierofrivia Sep 4, 2024
312710e
[refactor] Fix `OperationDispatcher.next()` behaviour
didierofrivia Sep 6, 2024
9293e03
Local auth dev environment
adam-cattermole Aug 1, 2024
ee3997d
Deploy limitador as part of the kind cluster
adam-cattermole Aug 8, 2024
5f0ff7c
Add tls and notls envoy configuration files
adam-cattermole Aug 8, 2024
8dd4c97
Add simple authconfig to local environment
adam-cattermole Aug 9, 2024
a43f393
Rename make/auth.mk to make/deploy.mk
adam-cattermole Aug 15, 2024
7be2e29
Set the host in authconfig to an arbitrary string
adam-cattermole Aug 16, 2024
7ad0a00
Update plugin config for envoy
adam-cattermole Sep 16, 2024
b78bbc9
Add original limitador examples to plugin config
adam-cattermole Sep 16, 2024
cb74375
Add some documentation for auth development
adam-cattermole Sep 16, 2024
40ce002
Merge pull request #67 from Kuadrant/auth-dev-env
adam-cattermole Sep 18, 2024
625b205
[feat] Action dispatcher state machine, naive impl
didierofrivia Aug 27, 2024
360c967
[refactor] Changing name to `Operation` instead of `Action`
didierofrivia Sep 2, 2024
1fc0e1a
[refactor] OperationDispatcher triggering procedures
didierofrivia Sep 3, 2024
190b597
[refactor] Specifying that it's about request messages
didierofrivia Sep 9, 2024
dbba0f5
[refactor, feature] Adding a new GrpcResponse type
didierofrivia Sep 10, 2024
d70d038
[refactor] Indexing waiting operations by `token_id`
didierofrivia Sep 12, 2024
93c980d
[refactor] Wiring filter with dispatcher
didierofrivia Sep 13, 2024
98d3754
[refactor] Passing by references instead of cloning
didierofrivia Sep 13, 2024
49e4fec
[refactor] Using action `failure_mode` when processing grpc error
didierofrivia Sep 13, 2024
b0329d4
[fix] Changed behaviour, removing and triggering next op at same step
didierofrivia Sep 18, 2024
c262342
[refactor] Renaming rlp to policy for consistency
didierofrivia Sep 18, 2024
4272ff7
[refactor] Explicit testing
didierofrivia Sep 18, 2024
7125754
[fix] Indexing waiting operations only when triggered Pending => Waiting
didierofrivia Sep 19, 2024
a852236
Merge pull request #81 from Kuadrant/on_grpc_response_flow
didierofrivia Sep 19, 2024
6675cab
Process auth CheckResponse
adam-cattermole Sep 20, 2024
41f85ea
Add auth examples to the doc
adam-cattermole Sep 20, 2024
a2977fd
Update debug logs
adam-cattermole Sep 20, 2024
efa4b90
Update test expected logs
adam-cattermole Sep 20, 2024
1265852
Merge pull request #86 from Kuadrant/auth-response
adam-cattermole Sep 23, 2024
80cde65
Rename domain -> scope and move to action
adam-cattermole Sep 20, 2024
ab2eed0
Move data from rules to actions
adam-cattermole Sep 20, 2024
91da443
Update examples to include authenticated rate limiting
adam-cattermole Sep 24, 2024
9f82574
Store dynamic metadata in filter_state
adam-cattermole Sep 24, 2024
57cb6d6
Refactor actions into rules
adam-cattermole Sep 26, 2024
68c25af
Match on all conditions not any
adam-cattermole Sep 30, 2024
2dc5d1b
Re-order test expectations to follow exactly the execution order
adam-cattermole Sep 30, 2024
a5c47e0
Move building of descriptors to action time
adam-cattermole Sep 30, 2024
88cb14b
Merge pull request #87 from Kuadrant/cleanup-pluginconfig
adam-cattermole Sep 30, 2024
ea58e1d
Revert removal of allOf within conditions
adam-cattermole Oct 1, 2024
cf8d790
Merge pull request #89 from Kuadrant/return-of-allof
adam-cattermole Oct 1, 2024
76c9bea
[refactor] OperationDispatcher not using RefCell for storing operations
didierofrivia Oct 1, 2024
249d3cd
[refactor] OperationDispatcher within a RefCell for interior mut
didierofrivia Oct 1, 2024
944a4a9
Merge pull request #90 from Kuadrant/refactoring-operation-dispatcher
didierofrivia Oct 1, 2024
5434eb9
[refactor] Simplifying Operation state transtion and exec of req msg
didierofrivia Oct 1, 2024
70eb303
Merge pull request #91 from Kuadrant/refactoring-operation-dispatcher…
didierofrivia Oct 1, 2024
4222ffb
[readme] Updating new sample config
didierofrivia Oct 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,21 @@ chmod a+x $(1)/bin/protoc ;\
rm -rf $$TMP_DIR ;\
}
endef

##@ Util

# go-install-tool will 'go install' any package $2 and install it to $1.
PROJECT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST))))
define go-install-tool
@[ -f $(1) ] || { \
set -e ;\
TMP_DIR=$$(mktemp -d) ;\
cd $$TMP_DIR ;\
go mod init tmp ;\
echo "Downloading $(2)" ;\
GOBIN=$(PROJECT_DIR)/bin go install $(2) ;\
rm -rf $$TMP_DIR ;\
}
endef

include ./make/*.mk
148 changes: 132 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,23 @@
A Proxy-Wasm module written in Rust, acting as a shim between Envoy and Limitador.

## Sample configuration

Following is a sample configuration used by the shim.

```yaml
failureMode: deny
rateLimitPolicies:
extensions:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example is outdated

auth-ext:
type: auth
endpoint: auth-cluster
failureMode: deny
ratelimit-ext:
type: ratelimit
endpoint: ratelimit-cluster
failureMode: deny
policies:
- name: rlp-ns-A/rlp-name-A
domain: rlp-ns-A/rlp-name-A
service: rate-limit-cluster
hostnames: ["*.toystore.com"]
hostnames: [ "*.toystore.com" ]
rules:
- conditions:
- allOf:
Expand All @@ -27,12 +35,15 @@ rateLimitPolicies:
- selector: request.method
operator: eq
value: GET
data:
- selector:
selector: request.headers.My-Custom-Header
- static:
key: admin
value: "1"
actions:
- extension: ratelimit-ext
scope: rlp-ns-A/rlp-name-A
data:
- selector:
selector: request.headers.My-Custom-Header
- static:
key: admin
value: "1"
```

## Features
Expand All @@ -57,6 +68,7 @@ pub enum WhenConditionOperator {

The `matches` operator is a a simple globbing pattern implementation based on regular expressions.
The only characters taken into account are:

* `?`: 0 or 1 characters
* `*`: 0 or more characters
* `+`: 1 or more characters
Expand Down Expand Up @@ -95,10 +107,10 @@ Example:
Input: this.is.a.exam\.ple -> Retuns: ["this", "is", "a", "exam.ple"].
```

Some path segments include dot `.` char in them. For instance envoy filter names: `envoy.filters.http.header_to_metadata`.
Some path segments include dot `.` char in them. For instance envoy filter
names: `envoy.filters.http.header_to_metadata`.
In that particular cases, the dot chat (separator), needs to be escaped.


## Building

Prerequisites:
Expand Down Expand Up @@ -127,7 +139,108 @@ make build BUILD=release
cargo test
```

## Running local development environment
## Running local development environment (kind)

`docker` is required.

Run local development environment

```sh
make local-setup
```

This deploys a local kubernetes cluster using kind, with the local build of wasm-shim mapped to the envoy container. An
echo API as well as limitador, authorino, and some test policies are configured.

To expose the envoy endpoint run the following:

```sh
kubectl port-forward --namespace default deployment/envoy 8000:8000
```

There is then a single auth policy defined for e2e testing:

* `auth-a` which defines auth is required for requests to `/get` for the `AuthConfig` with `effective-route-1`

```sh
curl -H "Host: test.a.auth.com" http://127.0.0.1:8000/get -i
# HTTP/1.1 401 Unauthorized
```

```sh
curl -H "Host: test.a.auth.com" -H "Authorization: APIKEY IAMALICE" http://127.0.0.1:8000/get -i
# HTTP/1.1 200 OK
```

And three rate limit policies defined for e2e testing:

* `rlp-a`: Only one data item. Data selector should not generate return any value. Thus, descriptor should be empty and
rate limiting service should **not** be called.

```sh
curl -H "Host: test.a.rlp.com" http://127.0.0.1:8000/get -i
```

* `rlp-b`: Conditions do not match. Hence, rate limiting service should **not** be called.

```sh
curl -H "Host: test.b.rlp.com" http://127.0.0.1:8000/get -i
```

* `rlp-c`: Four descriptors from multiple rules should be generated. Hence, rate limiting service should be called.

```sh
curl -H "Host: test.c.rlp.com" -H "x-forwarded-for: 127.0.0.1" -H "My-Custom-Header-01: my-custom-header-value-01" -H "x-dyn-user-id: bob" http://127.0.0.1:8000/get -i
```

* `multi-a` which defines two actions for authenticated ratelimiting.

```sh
curl -H "Host: test.a.multi.com" http://127.0.0.1:8000/get -i
# HTTP/1.1 401 Unauthorized
```

Alice has 5 requests per 10 seconds:
```sh
while :; do curl --write-out '%{http_code}\n' --silent --output /dev/null -H "Authorization: APIKEY IAMALICE" -H "Host: test.a.multi.com" http://127.0.0.1:8000/get | grep -E --color "\b(429)\b|$"; sleep 1; done
```

Bob has 2 requests per 10 seconds:
```sh
while :; do curl --write-out '%{http_code}\n' --silent --output /dev/null -H "Authorization: APIKEY IAMBOB" -H "Host: test.a.multi.com" http://127.0.0.1:8000/get | grep -E --color "\b(429)\b|$"; sleep 1; done
```

The expected descriptors:

```
RateLimitDescriptor { entries: [Entry { key: "limit_to_be_activated", value: "1" }], limit: None }
```

```
RateLimitDescriptor { entries: [Entry { key: "source.address", value: "127.0.0.1:0" }], limit: None }
```

```
RateLimitDescriptor { entries: [Entry { key: "request.headers.My-Custom-Header-01", value: "my-custom-header-value-01" }], limit: None }
```

```
RateLimitDescriptor { entries: [Entry { key: "user_id", value: "bob" }], limit: None }
```

To rebuild and deploy to the cluster:

```sh
make build local-rollout
```

Stop and clean up resources:

```sh
make local-cleanup
```

## Running local development environment (docker-compose legacy)

`docker` and `docker-compose` required.

Expand All @@ -139,7 +252,8 @@ make development

Three rate limit policies defined for e2e testing:

* `rlp-a`: Only one data item. Data selector should not generate return any value. Thus, descriptor should be empty and rate limiting service should **not** be called.
* `rlp-a`: Only one data item. Data selector should not generate return any value. Thus, descriptor should be empty and
rate limiting service should **not** be called.

```
curl -H "Host: test.a.com" http://127.0.0.1:18000/get
Expand Down Expand Up @@ -175,7 +289,9 @@ RateLimitDescriptor { entries: [Entry { key: "request.headers.My-Custom-Header-0
RateLimitDescriptor { entries: [Entry { key: "user_id", value: "bob" }], limit: None }
```

**Note:** Using [Header-To-Metadata filter](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/header_to_metadata_filter#config-http-filters-header-to-metadata), `x-dyn-user-id` header value is available in the metadata struct with the `user-id` key.
**Note:**
Using [Header-To-Metadata filter](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/header_to_metadata_filter#config-http-filters-header-to-metadata), `x-dyn-user-id`
header value is available in the metadata struct with the `user-id` key.

According to the defined limits:

Expand All @@ -187,7 +303,7 @@ According to the defined limits:
conditions:
- "limit_to_be_activated == '1'"
- "user_id == 'bob'"
variables: []
variables: [ ]
```

The third request in less than 10 seconds should return `429 Too Many Requests`.
Expand Down
126 changes: 126 additions & 0 deletions make/deploy.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
##@ Kind

.PHONY: kind kind-create-cluster kind-delete-cluster

KIND = $(PROJECT_PATH)/bin/kind
KIND_VERSION = v0.23.0
$(KIND):
$(call go-install-tool,$(KIND),sigs.k8s.io/kind@$(KIND_VERSION))

kind: $(KIND) ## Download kind locally if necessary.

KIND_CLUSTER_NAME ?= wasm-auth-local

kind-create-cluster: BUILD?=debug
kind-create-cluster: WASM_PATH=$(subst /,\/,$(PROJECT_PATH)/target/wasm32-unknown-unknown/$(BUILD))
kind-create-cluster: kind ## Create the "wasm-auth-local" kind cluster.
@{ \
TEMP_FILE=/tmp/kind-cluster-$$(openssl rand -hex 4).yaml ;\
cp $(PROJECT_PATH)/utils/kind/cluster.yaml $$TEMP_FILE ;\
$(SED) -i "s/\$$(WASM_PATH)/$(WASM_PATH)/g" $$TEMP_FILE ;\
KIND_EXPERIMENTAL_PROVIDER=$(CONTAINER_ENGINE) $(KIND) create cluster --name $(KIND_CLUSTER_NAME) --config $$TEMP_FILE ;\
rm -rf $$TEMP_FILE ;\
}

kind-delete-cluster: ## Delete the "wasm-auth-local" kind cluster.
- KIND_EXPERIMENTAL_PROVIDER=$(CONTAINER_ENGINE) $(KIND) delete cluster --name $(KIND_CLUSTER_NAME)


##@ Authorino

.PHONY: install-authorino-operator certs deploy-authorino

AUTHORINO_IMAGE ?= quay.io/kuadrant/authorino:latest
AUTHORINO_OPERATOR_NAMESPACE ?= authorino-operator
install-authorino-operator: ## Installs Authorino Operator and dependencies into the Kubernetes cluster configured in ~/.kube/config
curl -sL https://raw.githubusercontent.com/Kuadrant/authorino-operator/main/utils/install.sh | bash -s -- --git-ref main
kubectl patch deployment/authorino-webhooks -n $(AUTHORINO_OPERATOR_NAMESPACE) -p '{"spec":{"template":{"spec":{"containers":[{"name":"webhooks","image":"$(AUTHORINO_IMAGE)","imagePullPolicy":"IfNotPresent"}]}}}}'
kubectl -n $(AUTHORINO_OPERATOR_NAMESPACE) wait --timeout=300s --for=condition=Available deployments --all

TLS_ENABLED ?= true
AUTHORINO_INSTANCE ?= authorino
NAMESPACE ?= default
certs: sed ## Requests TLS certificates for the Authorino instance if TLS is enabled, cert-manager.io is installed, and the secret is not already present
ifeq (true,$(TLS_ENABLED))
ifeq (,$(shell kubectl -n $(NAMESPACE) get secret/authorino-oidc-server-cert 2>/dev/null))
curl -sl https://raw.githubusercontent.com/kuadrant/authorino/main/deploy/certs.yaml | $(SED) "s/\$$(AUTHORINO_INSTANCE)/$(AUTHORINO_INSTANCE)/g;s/\$$(NAMESPACE)/$(NAMESPACE)/g" | kubectl -n $(NAMESPACE) apply -f -
else
echo "tls cert secret found."
endif
else
echo "tls disabled."
endif

deploy-authorino: certs sed ## Deploys an instance of Authorino into the Kubernetes cluster configured in ~/.kube/config
@{ \
set -e ;\
TEMP_FILE=/tmp/authorino-deploy-$$(openssl rand -hex 4).yaml ;\
curl -sl https://raw.githubusercontent.com/kuadrant/authorino/main/deploy/authorino.yaml > $$TEMP_FILE ;\
$(SED) -i "s/\$$(AUTHORINO_INSTANCE)/$(AUTHORINO_INSTANCE)/g;s/\$$(TLS_ENABLED)/$(TLS_ENABLED)/g" $$TEMP_FILE ;\
kubectl -n $(NAMESPACE) apply -f $$TEMP_FILE ;\
kubectl patch -n $(NAMESPACE) authorino/$(AUTHORINO_INSTANCE) --type='merge' -p '{"spec":{"image": "$(AUTHORINO_IMAGE)"}}' ;\
rm -rf $$TEMP_FILE ;\
}


##@ Limitador

deploy-limitador:
kubectl create configmap limits --from-file=$(PROJECT_PATH)/utils/docker-compose/limits.yaml
kubectl -n $(NAMESPACE) apply -f $(PROJECT_PATH)/utils/deploy/limitador.yaml


##@ User Apps

.PHONY: user-apps


ifeq (true,$(TLS_ENABLED))
ENVOY_OVERLAY = tls
else
ENVOY_OVERLAY = notls
endif
user-apps: ## Deploys talker API and envoy
kubectl -n $(NAMESPACE) apply -f https://raw.githubusercontent.com/kuadrant/authorino-examples/main/talker-api/talker-api-deploy.yaml
kubectl -n $(NAMESPACE) apply -f $(PROJECT_PATH)/utils/deploy/envoy-$(ENVOY_OVERLAY).yaml
kubectl -n $(NAMESPACE) apply -f $(PROJECT_PATH)/utils/deploy/authconfig.yaml


##@ Util

.PHONY: local-setup local-env-setup local-cleanup local-rollout sed

local-setup: local-env-setup
kubectl -n $(NAMESPACE) wait --timeout=300s --for=condition=Available deployments --all
@{ \
echo "Now you can export the envoy service by doing:"; \
echo "kubectl port-forward --namespace $(NAMESPACE) deployment/envoy 8000:8000"; \
echo "After that, you can curl -H \"Host: myhost.com\" localhost:8000"; \
}

local-env-setup:
$(MAKE) kind-delete-cluster
$(MAKE) kind-create-cluster
$(MAKE) install-authorino-operator
$(MAKE) deploy-authorino
$(MAKE) deploy-limitador
$(MAKE) user-apps

local-cleanup: kind ## Delete the "wasm-auth-local" kind cluster.
$(MAKE) kind-delete-cluster

local-rollout:
$(MAKE) user-apps
kubectl rollout restart -n $(NAMESPACE) deployment/envoy
kubectl -n $(NAMESPACE) wait --timeout=300s --for=condition=Available deployments --all

ifeq ($(shell uname),Darwin)
SED=$(shell which gsed)
else
SED=$(shell which sed)
endif
sed: ## Checks if GNU sed is installed
ifeq ($(SED),)
@echo "Cannot find GNU sed installed."
exit 1
endif
Loading
Loading