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

Config revamp #110

Merged
merged 8 commits into from
Oct 22, 2024
Merged

Config revamp #110

merged 8 commits into from
Oct 22, 2024

Conversation

adam-cattermole
Copy link
Member

@adam-cattermole adam-cattermole commented Oct 15, 2024

Changes

This is moving towards a configuration based on the suggestion in #108.

Currently this is looking as follows:

services:
  auth-service:
    type: auth
    endpoint: auth-cluster
    failureMode: deny
    timeout: 10ms
  ratelimit-service:
    type: ratelimit
    endpoint: ratelimit-cluster
    failureMode: deny
actionSets:
  - name: rlp-ns-A/rlp-name-A
    routeRuleConditions:
      hostnames: [ "*.toystore.com" ]
      matches:
      - selector: request.url_path
        operator: startswith
        value: /get
      - selector: request.host
        operator: eq
        value: test.toystore.com
      - selector: request.method
        operator: eq
        value: GET
    actions:
    - service: ratelimit-service
      scope: rlp-ns-A/rlp-name-A
      conditions: []
      data:
      - selector:
          selector: request.headers.My-Custom-Header
      - static:
          key: admin
          value: "1"

I've separated all of the changes by commit to try make it easier to read the changes.

The primary change to non-config types is that we now have actions.conditions so we can conditionally perform an action - example provided in the envoy configuration that only calls the rate limiting service when user_id == 'alice':

make build && make local-setup

Port-forward envoy and watch the logs for all services:

kubectl port-forward --namespace default deployment/envoy 8000:8000
kubectl logs -f deployment/envoy
kubectl logs -f deployment/authorino
kubectl logs -f deployment/limitador

Test unauthenticated does not get rate limited:

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

Bob is not rate limited (note no calls to limitador in logs):

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

Alice has 5 requests per 10 seconds:

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

Outstanding

  • Tests for conditional actions
  • Retrieve the scope from action.data (won't do)

For a future PR:

  • Convert routeRuleConditions.matches and action.conditions from PatternExpression to CEL
  • "Merge" subsequent actions of the same type to only make a single call for ratelimit

guicassolato added a commit to Kuadrant/kuadrant-operator that referenced this pull request Oct 15, 2024
Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>
guicassolato added a commit to Kuadrant/kuadrant-operator that referenced this pull request Oct 15, 2024
Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>
guicassolato added a commit to Kuadrant/kuadrant-operator that referenced this pull request Oct 15, 2024
Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>
guicassolato added a commit to Kuadrant/kuadrant-operator that referenced this pull request Oct 16, 2024
Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>
Copy link
Contributor

@eguzki eguzki left a comment

Choose a reason for hiding this comment

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

Looking good

@eguzki
Copy link
Contributor

eguzki commented Oct 16, 2024

Verification steps working

@adam-cattermole
Copy link
Member Author

Latest commit removes action.scope and this information is retrieved from the data section now

@adam-cattermole adam-cattermole marked this pull request as ready for review October 16, 2024 12:52
@adam-cattermole
Copy link
Member Author

I'm still writing tests for conditional actions, and realise that we need a coordinated merge of this so potentially this should be reviewed/merged to a feature branch

@eguzki
Copy link
Contributor

eguzki commented Oct 16, 2024

Latest commit removes action.scope and this information is retrieved from the data section now

From data? This is unexpected. From a static data item with a key name (by convention) domain?

What if there are many, which one has preference?

@adam-cattermole
Copy link
Member Author

adam-cattermole commented Oct 16, 2024

From data? This is unexpected. From a static data item with a key name (by convention) domain?

I'm not tied to this change, and I can drop the commit. But I was working toward what we agreed in #108 where the data required to build the message was defined in the data of the action

- routeRuleConditions:
    hostnames:
    - "*.foo.com"
    - "users.bar.com"
    matches:
    - request.method == "GET"
    - request.path.startsWith('/bar')
  actions:
  - conditions:
    - "!['127.0.0.1', '192.168.1.1'].contains(source.ip)"
    action:
      service: limitador
      data:
        ip: source.ip
        magic_RL_name: "'1'"
  - conditions: []
    action:
      service: authorino
      data:
        authCfg: "'someIdentifier'"

@adam-cattermole
Copy link
Member Author

I've dropped that commit fwiw. I tend to agree that right now the purpose of the data and scope is different and the way (we currently) process the data items means we need some custom logic to process a specific keyed data item, which doesn't seem right

@guicassolato
Copy link
Contributor

Latest commit removes action.scope and this information is retrieved from the data section now

From data? This is unexpected. From a static data item with a key name (by convention) domain?

I agree with @eguzki. I don't like this change.

Whether as domain or as authCfg, in both cases this is a required piece of data and in both cases it has the meaning of “scope”. Inside of data, it feels out of place IMO. Unlike the rest of what goes there, scope is not as much "user-defined" data.

The way it was before, we could technically have an action without any data, which makes sense to me since we have default data that comes from the type of action (service) anyway. In fact, auth is an example of action that typically would involve zero user-defined data. And I could speculate with meaning to that for ratelimit as well (e.g. letting Limitador knows about request without activating any limit).

Anyway, I honestly liked more how it was before. Thanks for ditching the commit!

@adam-cattermole
Copy link
Member Author

Thanks both for the constructive feedback, will continue on tests for conditional actions

guicassolato added a commit to Kuadrant/kuadrant-operator that referenced this pull request Oct 16, 2024
Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>
guicassolato added a commit to Kuadrant/kuadrant-operator that referenced this pull request Oct 16, 2024
Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>
guicassolato added a commit to Kuadrant/kuadrant-operator that referenced this pull request Oct 18, 2024
Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>
Signed-off-by: Adam Cattermole <acatterm@redhat.com>
Rename conditions to matches - hoist all_of

Signed-off-by: Adam Cattermole <acatterm@redhat.com>
Signed-off-by: Adam Cattermole <acatterm@redhat.com>
Signed-off-by: Adam Cattermole <acatterm@redhat.com>
Signed-off-by: Adam Cattermole <acatterm@redhat.com>
Signed-off-by: Adam Cattermole <acatterm@redhat.com>
Signed-off-by: Adam Cattermole <acatterm@redhat.com>
Signed-off-by: Adam Cattermole <acatterm@redhat.com>
guicassolato added a commit to Kuadrant/kuadrant-operator that referenced this pull request Oct 18, 2024
Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>
Copy link
Member

@didierofrivia didierofrivia left a comment

Choose a reason for hiding this comment

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

💪🏼

guicassolato added a commit to Kuadrant/kuadrant-operator that referenced this pull request Oct 21, 2024
Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>
guicassolato added a commit to Kuadrant/kuadrant-operator that referenced this pull request Oct 22, 2024
Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>
guicassolato added a commit to Kuadrant/kuadrant-operator that referenced this pull request Oct 22, 2024
Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>
guicassolato added a commit to Kuadrant/kuadrant-operator that referenced this pull request Oct 22, 2024
* sotw: effective ratelimitpolicy

- ratelimit workflow
- ratelimitopolicies validator
- effective ratelimitpolicies reconciler
- limitador limits reconciler
- ratelimitpolicy status updater (accepted condition)

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* removed unused function to apply rlp overrides

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* istio extension (WasmPlugin) reconciler

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* fixup: unique limit definitions per scope

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* fixup: log error only when indeed there's an error to be logged

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* do not fail when missing kuadrant object

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* fixup: equality between wasmplugins and avoid rebuilding wasm config from struct when nil

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* fixup: error comparison

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* cleanup istio extension objects when it cannot calculate effective policies

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* refactor: removal of SortablePolicy for sorting policies objects by creation timestamp

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* remove no longer relevant integration test case

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* fixup: avoid updating invalid rate limit policies to 'accepted' on events that do not (re)validate policies

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* fixup: continue istio extension workflow when it fails for a given gateway

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* Remove unnused event recorder from base reconciler

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* Istio rate limit cluster reconciler

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* enable Istio-related rate limit tasks only when Istio is installed

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* ensure at least one hostname per wasm config policy

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* bump istio to 1.22

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* Use targetRefs to attach to gateways in the Istio EnvoyFilter and WasmPlugin resources

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* refactor: debug log messages for when Limitador, EnvoyFilter and WasmPlugins are up to date already and therefore nothing to be done

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* sort wasm 'policies' within the wasm plugin config by hostname from most specific to least specific

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* go fmt: refactor: debug log messages for when Limitador, EnvoyFilter and WasmPlugin

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* sort wasm 'policies' within the wasm plugin config by hostname and http route match from most specific to least specific

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* code style: remove unused parameter ctx

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* fix: unit test: sort wasm 'policies' within the wasm plugin config by hostname and http route match

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* Refactor WasmPlugin reconciliation to reduce repetition with EnvoyExtensionPolicy and ease the merge of auth

* Separate the code for building Wasm Configs from any logic specific to the Istio WasmPlugin resource
* Move all generic Wasm-related code either upwards to a common file of the workflow tasks (in the `controllers` package) into new package `pkg/wasm` (replacing `pkg/rlptools/wasm`)
  * Logic related to RL reconciliation →  controllers/ratelimit_workflow.go
  * Logic related to Wasm Config types →  pkg/wasm
* Rename `rlptools` package as `ratelimit` – only Limitador RateLimit index types remaining there

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* envoy gateway rate limit cluster reconciler

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* fix: wrong default GroupKind assumed on Istio policies TargetRefs

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* minor fixes to code comments and log messages

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* envoy gateway extension reconciler

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* code style: ratelimit.RateLimitIndex -> Index

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* code style: wasm.WasmExtensionName -> ExtensionName

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* code style: wasm.WasmRuleBuilderFunc -> RuleBuilderFunc

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* code style: fix grouping of go imports

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* new structure of the wasm config based on Kuadrant/wasm-shim#110

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* fix: envoy_gateway_extension_reconciler.go file name

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* fix: log messages of envoy patch policy reconciliation

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* rlp enforced condition and consistency in the message when target not found

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* tests: gateway extension reconciler tests resource comparison

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* more descriptive wasm actionset names

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* tests: fix integration tests - order of wasm action sets

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* fixup: should not increment twice on the index of http route match when building the wasm action set name

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* tests: fix integration tests - order of wasm action sets (again!)

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* back to opaque wasm action set names

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* remove duplicate GetKuadrantFromTopology func

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* do not isolate policy-machinery imports in a separate group

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* helper function to extract network objects in a request path

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* set owner reference directly when building the desired objects

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* only validate policies on create and update events

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* update policy status on all kinds of policy-releated event (deleting a policy may also affect the state of the resources status depends on)

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* use labels on the internal resources created to watch and select them from topology

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* policy not enforced due to 'not in the path to any existing routes' (formerly reported as 'no free routes to enforce policy')

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* tests: fix integration tests - Istio EnvoyFilter only created if RLP is in the path to a route

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* lint: removed unnused func arg in the tests

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* tests: fix integration tests - Istio WasmPlugin config with correct limit IDs and scopes

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* check state of the targeted resources to define the policy's enforced status condition

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* re-enable RateLimitPolicy discoverability (PolicyAffected status condition)

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* tests: fix integration tests - common ratelimit workflow tests

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* refactor: common.NamespacedNameFromLocator func

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

* hack to isolate test namespaces sharing the same limitador cr

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>

---------

Signed-off-by: Guilherme Cassolato <guicassolato@gmail.com>
@guicassolato guicassolato merged commit 980e647 into main Oct 22, 2024
9 checks passed
@guicassolato guicassolato deleted the config-revamp branch October 22, 2024 10:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

4 participants