From 57cb6d6a8f347a25a509785300891761bd555955 Mon Sep 17 00:00:00 2001 From: Adam Cattermole Date: Thu, 26 Sep 2024 16:19:17 +0100 Subject: [PATCH] Refactor actions into rules Co-authored-by: dd di cesare Signed-off-by: Adam Cattermole --- src/configuration.rs | 225 ++++++++++++++-------------------- src/filter/http_context.rs | 12 +- src/operation_dispatcher.rs | 14 +-- src/policy.rs | 52 ++++++-- src/policy_index.rs | 2 +- tests/rate_limited.rs | 77 +++++------- utils/deploy/envoy-notls.yaml | 150 +++++++++++------------ utils/deploy/envoy-tls.yaml | 150 +++++++++++------------ 8 files changed, 327 insertions(+), 355 deletions(-) diff --git a/src/configuration.rs b/src/configuration.rs index 4eee9b3a..78a7f8e8 100644 --- a/src/configuration.rs +++ b/src/configuration.rs @@ -8,13 +8,13 @@ use cel_interpreter::objects::ValueType; use cel_interpreter::{Context, Expression, Value}; use cel_parser::{Atom, RelationOp}; use log::debug; -use proxy_wasm::traits::Context as _; +use protobuf::RepeatedField; +use proxy_wasm::hostcalls; use serde::Deserialize; use crate::attribute::Attribute; use crate::envoy::{RateLimitDescriptor, RateLimitDescriptor_Entry}; -use crate::filter::http_context::Filter; -use crate::policy::{Policy, Rule}; +use crate::policy::Policy; use crate::policy_index::PolicyIndex; use crate::service::GrpcService; @@ -472,15 +472,16 @@ impl TryFrom for FilterConfig { return Err(result.err().unwrap()); } } - } - for action in &rlp.actions { - for datum in &action.data { - let result = datum.item.compile(); - if result.is_err() { - return Err(result.err().unwrap()); + for action in &rule.actions { + for datum in &action.data { + let result = datum.item.compile(); + if result.is_err() { + return Err(result.err().unwrap()); + } } } } + for hostname in rlp.hostnames.iter() { index.insert(hostname, rlp.clone()); } @@ -543,68 +544,19 @@ pub struct Action { } impl Action { - pub fn build_descriptors( - &self, - rules: Vec, - filter: &Filter, - ) -> protobuf::RepeatedField { - rules - .iter() - .filter(|rule: &&Rule| self.filter_rule_by_conditions(filter, &rule.conditions)) - // Mapping 1 Rule -> 1 Descriptor - // Filter out empty descriptors - .filter_map(|_| self.build_single_descriptor(filter, &self.data)) - .collect() - } - - fn filter_rule_by_conditions(&self, filter: &Filter, conditions: &[PatternExpression]) -> bool { - if conditions.is_empty() { - // no conditions is equivalent to matching all the requests. - return true; + pub fn build_descriptors(&self) -> RepeatedField { + let mut entries = RepeatedField::new(); + if let Some(desc) = self.build_single_descriptor() { + entries.push(desc); } - - conditions - .iter() - .all(|pattern_expression| self.pattern_expression_applies(filter, pattern_expression)) + entries } - fn pattern_expression_applies(&self, filter: &Filter, p_e: &PatternExpression) -> bool { - let attribute_path = p_e.path(); - debug!( - "#{} get_property: selector: {} path: {:?}", - filter.context_id, p_e.selector, attribute_path - ); - let attribute_value = match filter.get_property(attribute_path) { - None => { - debug!( - "#{} pattern_expression_applies: selector not found: {}, defaulting to ``", - filter.context_id, p_e.selector - ); - b"".to_vec() - } - Some(attribute_bytes) => attribute_bytes, - }; - match p_e.eval(attribute_value) { - Err(e) => { - debug!( - "#{} pattern_expression_applies failed: {}", - filter.context_id, e - ); - false - } - Ok(result) => result, - } - } - - fn build_single_descriptor( - &self, - filter: &Filter, - data_list: &[DataItem], - ) -> Option { - let mut entries = ::protobuf::RepeatedField::default(); + fn build_single_descriptor(&self) -> Option { + let mut entries = RepeatedField::default(); // iterate over data items to allow any data item to skip the entire descriptor - for data in data_list.iter() { + for data in self.data.iter() { match &data.item { DataType::Static(static_item) => { let mut descriptor_entry = RateLimitDescriptor_Entry::new(); @@ -620,14 +572,15 @@ impl Action { let attribute_path = selector_item.path(); debug!( - "#{} get_property: selector: {} path: {:?}", - filter.context_id, selector_item.selector, attribute_path + "get_property: selector: {} path: {:?}", + selector_item.selector, attribute_path ); - let value = match filter.get_property(attribute_path.tokens()) { + let value = match hostcalls::get_property(attribute_path.tokens()).unwrap() { + //TODO(didierofrivia): Replace hostcalls by DI None => { debug!( - "#{} build_single_descriptor: selector not found: {}", - filter.context_id, attribute_path + "build_single_descriptor: selector not found: {}", + attribute_path ); match &selector_item.default { None => return None, // skipping the entire descriptor @@ -639,8 +592,8 @@ impl Action { Some(attribute_bytes) => match Attribute::parse(attribute_bytes) { Ok(attr_str) => attr_str, Err(e) => { - debug!("#{} build_single_descriptor: failed to parse selector value: {}, error: {}", - filter.context_id, attribute_path, e); + debug!("build_single_descriptor: failed to parse selector value: {}, error: {}", + attribute_path, e); return None; } }, @@ -657,7 +610,6 @@ impl Action { } } } - let mut res = RateLimitDescriptor::new(); res.set_entries(entries); Some(res) @@ -697,9 +649,8 @@ mod test { "selector": "request.host", "operator": "eq", "value": "cars.toystore.com" - }] - }], - "actions": [ + }], + "actions": [ { "extension": "limitador", "scope": "rlp-ns-A/rlp-name-A", @@ -715,8 +666,8 @@ mod test { "selector": "auth.metadata.username" } }] - } - ] + }] + }] }] }"#; @@ -737,7 +688,7 @@ mod test { let conditions = &rules[0].conditions; assert_eq!(conditions.len(), 3); - let actions = &filter_config.policies[0].actions; + let actions = &rules[0].actions; assert_eq!(actions.len(), 1); let data_items = &actions[0].data; @@ -800,21 +751,23 @@ mod test { { "name": "rlp-ns-A/rlp-name-A", "hostnames": ["*.toystore.com", "example.com"], - "rules": [], - "actions": [ + "rules": [ { - "extension": "limitador", - "scope": "rlp-ns-A/rlp-name-A", - "data": [ + "conditions": [], + "actions": [ { - "selector": { - "selector": "my.selector.path", - "key": "mykey", - "default": "my_selector_default_value" - } + "extension": "limitador", + "scope": "rlp-ns-A/rlp-name-A", + "data": [ + { + "selector": { + "selector": "my.selector.path", + "key": "mykey", + "default": "my_selector_default_value" + } + }] }] - } - ] + }] }] }"#; let res = serde_json::from_str::(config); @@ -827,9 +780,9 @@ mod test { assert_eq!(filter_config.policies.len(), 1); let rules = &filter_config.policies[0].rules; - assert_eq!(rules.len(), 0); + assert_eq!(rules.len(), 1); - let actions = &filter_config.policies[0].actions; + let actions = &rules[0].actions; assert_eq!(actions.len(), 1); let data_items = &actions[0].data; @@ -888,15 +841,14 @@ mod test { "selector": "request.host", "operator": "matches", "value": "*.com" + }], + "actions": [ + { + "extension": "limitador", + "scope": "rlp-ns-A/rlp-name-A", + "data": [ { "selector": { "selector": "my.selector.path" } }] }] - }], - "actions": [ - { - "extension": "limitador", - "scope": "rlp-ns-A/rlp-name-A", - "data": [ { "selector": { "selector": "my.selector.path" } }] - } - ] + }] }] }"#; let res = serde_json::from_str::(config); @@ -944,27 +896,27 @@ mod test { { "name": "rlp-ns-A/rlp-name-A", "hostnames": ["*.toystore.com", "example.com"], - "rules": [{ - "conditions": [] - }], - "actions": [ + "rules": [ { - "extension": "limitador", - "scope": "rlp-ns-A/rlp-name-A", - "data": [ - { - "static": { - "key": "rlp-ns-A/rlp-name-A", - "value": "1" - } - }, + "conditions": [], + "actions": [ { - "selector": { - "selector": "auth.metadata.username" - } + "extension": "limitador", + "scope": "rlp-ns-A/rlp-name-A", + "data": [ + { + "static": { + "key": "rlp-ns-A/rlp-name-A", + "value": "1" + } + }, + { + "selector": { + "selector": "auth.metadata.username" + } + }] }] - } - ] + }] }] }"#; let res = serde_json::from_str::(config); @@ -998,8 +950,9 @@ mod test { { "name": "rlp-ns-A/rlp-name-A", "hostnames": ["*.toystore.com", "example.com"], - "rules": [], - "actions": [ + "rules": [ + { + "actions": [ { "extension": "limitador", "scope": "rlp-ns-A/rlp-name-A", @@ -1013,8 +966,8 @@ mod test { "selector": "auth.metadata.username" } }] - } - ] + }] + }] }] }"#; let res = serde_json::from_str::(bad_config); @@ -1034,8 +987,9 @@ mod test { "name": "rlp-ns-A/rlp-name-A", "service": "limitador-cluster", "hostnames": ["*.toystore.com", "example.com"], - "rules": [], - "actions": [ + "rules": [ + { + "actions": [ { "extension": "limitador", "scope": "rlp-ns-A/rlp-name-A", @@ -1046,8 +1000,8 @@ mod test { "value": "1" } }] - } - ] + }] + }] }] }"#; let res = serde_json::from_str::(bad_config); @@ -1073,15 +1027,14 @@ mod test { "selector": "request.path", "operator": "unknown", "value": "/admin/toy" + }], + "actions": [ + { + "extension": "limitador", + "scope": "rlp-ns-A/rlp-name-A", + "data": [ { "selector": { "selector": "my.selector.path" } }] }] - }], - "actions": [ - { - "extension": "limitador", - "scope": "rlp-ns-A/rlp-name-A", - "data": [ { "selector": { "selector": "my.selector.path" } }] - } - ] + }] }] }"#; let res = serde_json::from_str::(bad_config); diff --git a/src/filter/http_context.rs b/src/filter/http_context.rs index 1d61b432..e28e5f6d 100644 --- a/src/filter/http_context.rs +++ b/src/filter/http_context.rs @@ -31,7 +31,12 @@ impl Filter { } fn process_policy(&self, policy: &Policy) -> Action { - self.operation_dispatcher.build_operations(policy, self); + if let Some(rule) = policy.find_rule_that_applies() { + self.operation_dispatcher.build_operations(rule); + } else { + debug!("#{} process_policy: no rule applied", self.context_id); + return Action::Continue; + } if let Some(operation) = self.operation_dispatcher.next() { match operation.get_result() { @@ -172,10 +177,7 @@ impl HttpContext for Filter { Action::Continue } Some(policy) => { - debug!( - "#{} ratelimitpolicy selected {}", - self.context_id, policy.name - ); + debug!("#{} policy selected {}", self.context_id, policy.name); self.process_policy(policy) } } diff --git a/src/operation_dispatcher.rs b/src/operation_dispatcher.rs index 37f911d6..b89785ae 100644 --- a/src/operation_dispatcher.rs +++ b/src/operation_dispatcher.rs @@ -1,6 +1,5 @@ use crate::configuration::{Extension, ExtensionType, FailureMode}; -use crate::filter::http_context::Filter; -use crate::policy::Policy; +use crate::policy::Rule; use crate::service::grpc_message::GrpcMessageRequest; use crate::service::{GetMapValuesBytesFn, GrpcCallFn, GrpcServiceHandler}; use log::debug; @@ -120,20 +119,17 @@ impl OperationDispatcher { self.waiting_operations.borrow_mut().get(&token_id).cloned() } - pub fn build_operations(&self, policy: &Policy, filter: &Filter) { + pub fn build_operations(&self, rule: &Rule) { let mut operations: Vec = vec![]; - for action in policy.actions.iter() { + for action in rule.actions.iter() { // TODO(didierofrivia): Error handling if let Some(service) = self.service_handlers.get(&action.extension) { let descriptors = match service.get_extension_type() { ExtensionType::Auth => None, ExtensionType::RateLimit => { - let desc = action.build_descriptors(policy.rules.clone(), filter); + let desc = action.build_descriptors(); if desc.is_empty() { - debug!( - "#{} process_rate_limit_policy: empty descriptors", - filter.context_id - ); + debug!("process_policy: empty descriptors"); continue; } Some(desc) diff --git a/src/policy.rs b/src/policy.rs index 0437ddd6..c85eae8c 100644 --- a/src/policy.rs +++ b/src/policy.rs @@ -1,9 +1,12 @@ use crate::configuration::{Action, PatternExpression}; +use log::debug; +use proxy_wasm::hostcalls; use serde::Deserialize; #[derive(Deserialize, Debug, Clone)] pub struct Rule { pub conditions: Vec, + pub actions: Vec, } #[derive(Deserialize, Debug, Clone)] @@ -12,22 +15,55 @@ pub struct Policy { pub name: String, pub hostnames: Vec, pub rules: Vec, - pub actions: Vec, } impl Policy { #[cfg(test)] - pub fn new( - name: String, - hostnames: Vec, - rules: Vec, - actions: Vec, - ) -> Self { + pub fn new(name: String, hostnames: Vec, rules: Vec) -> Self { Policy { name, hostnames, rules, - actions, } } + + pub fn find_rule_that_applies(&self) -> Option<&Rule> { + self.rules + .iter() + .find(|rule: &&Rule| self.filter_rule_by_conditions(&rule.conditions)) + } + + fn filter_rule_by_conditions(&self, conditions: &[PatternExpression]) -> bool { + if conditions.is_empty() { + // no conditions is equivalent to matching all the requests. + return true; + } + + conditions + .iter() + .any(|condition| self.pattern_expression_applies(condition)) + } + + fn pattern_expression_applies(&self, p_e: &PatternExpression) -> bool { + let attribute_path = p_e.path(); + debug!( + "get_property: selector: {} path: {:?}", + p_e.selector, attribute_path + ); + let attribute_value = match hostcalls::get_property(attribute_path).unwrap() { + //TODO(didierofrivia): Replace hostcalls by DI + None => { + debug!( + "pattern_expression_applies: selector not found: {}, defaulting to ``", + p_e.selector + ); + b"".to_vec() + } + Some(attribute_bytes) => attribute_bytes, + }; + p_e.eval(attribute_value).unwrap_or_else(|e| { + debug!("pattern_expression_applies failed: {}", e); + false + }) + } } diff --git a/src/policy_index.rs b/src/policy_index.rs index 30adf4c7..0c0759a9 100644 --- a/src/policy_index.rs +++ b/src/policy_index.rs @@ -41,7 +41,7 @@ mod tests { use crate::policy_index::PolicyIndex; fn build_ratelimit_policy(name: &str) -> Policy { - Policy::new(name.to_owned(), Vec::new(), Vec::new(), Vec::new()) + Policy::new(name.to_owned(), Vec::new(), Vec::new()) } #[test] diff --git a/tests/rate_limited.rs b/tests/rate_limited.rs index 4b6e4b82..dda0702b 100644 --- a/tests/rate_limited.rs +++ b/tests/rate_limited.rs @@ -119,9 +119,8 @@ fn it_limits() { "operator": "eq", "value": "POST" } - ] - }], - "actions": [ + ], + "actions": [ { "extension": "limitador", "scope": "RLS-domain", @@ -133,8 +132,8 @@ fn it_limits() { } } ] - } - ] + }] + }] }] }"#; @@ -176,21 +175,18 @@ fn it_limits() { .returning(Some("cars.toystore.com".as_bytes())) .expect_get_property(Some(vec!["request", "method"])) .returning(Some("POST".as_bytes())) + .expect_log(Some(LogLevel::Debug), Some("#2 policy selected some-name")) .expect_log( Some(LogLevel::Debug), - Some("#2 ratelimitpolicy selected some-name"), + Some("get_property: selector: request.url_path path: [\"request\", \"url_path\"]"), ) .expect_log( Some(LogLevel::Debug), - Some("#2 get_property: selector: request.url_path path: [\"request\", \"url_path\"]"), + Some("get_property: selector: request.host path: [\"request\", \"host\"]"), ) .expect_log( Some(LogLevel::Debug), - Some("#2 get_property: selector: request.host path: [\"request\", \"host\"]"), - ) - .expect_log( - Some(LogLevel::Debug), - Some("#2 get_property: selector: request.method path: [\"request\", \"method\"]"), + Some("get_property: selector: request.method path: [\"request\", \"method\"]"), ) .expect_grpc_call( Some("limitador-cluster"), @@ -276,9 +272,8 @@ fn it_passes_additional_headers() { "operator": "eq", "value": "POST" } - ] - }], - "actions": [ + ], + "actions": [ { "extension": "limitador", "scope": "RLS-domain", @@ -290,8 +285,8 @@ fn it_passes_additional_headers() { } } ] - } - ] + }] + }] }] }"#; @@ -333,21 +328,18 @@ fn it_passes_additional_headers() { .returning(Some("cars.toystore.com".as_bytes())) .expect_get_property(Some(vec!["request", "method"])) .returning(Some("POST".as_bytes())) + .expect_log(Some(LogLevel::Debug), Some("#2 policy selected some-name")) .expect_log( Some(LogLevel::Debug), - Some("#2 ratelimitpolicy selected some-name"), + Some("get_property: selector: request.url_path path: [\"request\", \"url_path\"]"), ) .expect_log( Some(LogLevel::Debug), - Some("#2 get_property: selector: request.url_path path: [\"request\", \"url_path\"]"), + Some("get_property: selector: request.host path: [\"request\", \"host\"]"), ) .expect_log( Some(LogLevel::Debug), - Some("#2 get_property: selector: request.host path: [\"request\", \"host\"]"), - ) - .expect_log( - Some(LogLevel::Debug), - Some("#2 get_property: selector: request.method path: [\"request\", \"method\"]"), + Some("get_property: selector: request.method path: [\"request\", \"method\"]"), ) .expect_grpc_call( Some("limitador-cluster"), @@ -430,11 +422,9 @@ fn it_rate_limits_with_empty_conditions() { "name": "some-name", "hostnames": ["*.com"], "rules": [ - { - "conditions": [] - } - ], - "actions": [ + { + "conditions": [], + "actions": [ { "extension": "limitador", "scope": "RLS-domain", @@ -446,8 +436,8 @@ fn it_rate_limits_with_empty_conditions() { } } ] - } - ] + }] + }] }] }"#; @@ -483,10 +473,7 @@ fn it_rate_limits_with_empty_conditions() { .returning(None) .expect_get_header_map_value(Some(MapType::HttpRequestHeaders), Some("baggage")) .returning(None) - .expect_log( - Some(LogLevel::Debug), - Some("#2 ratelimitpolicy selected some-name"), - ) + .expect_log(Some(LogLevel::Debug), Some("#2 policy selected some-name")) .expect_grpc_call( Some("limitador-cluster"), Some("envoy.service.ratelimit.v3.RateLimitService"), @@ -554,11 +541,9 @@ fn it_does_not_rate_limits_when_selector_does_not_exist_and_misses_default_value "name": "some-name", "hostnames": ["*.com"], "rules": [ - { - "conditions": [] - } - ], - "actions": [ + { + "conditions": [], + "actions": [ { "extension": "limitador", "scope": "RLS-domain", @@ -569,8 +554,8 @@ fn it_does_not_rate_limits_when_selector_does_not_exist_and_misses_default_value } } ] - } - ] + }] + }] }] }"#; @@ -604,19 +589,19 @@ fn it_does_not_rate_limits_when_selector_does_not_exist_and_misses_default_value .returning(None) .expect_log( Some(LogLevel::Debug), - Some("#2 ratelimitpolicy selected some-name"), + Some("#2 policy selected some-name"), ) .expect_log( Some(LogLevel::Debug), - Some("#2 get_property: selector: unknown.path path: Path { tokens: [\"unknown\", \"path\"] }"), + Some("get_property: selector: unknown.path path: Path { tokens: [\"unknown\", \"path\"] }"), ) .expect_log( Some(LogLevel::Debug), - Some("#2 build_single_descriptor: selector not found: unknown.path"), + Some("build_single_descriptor: selector not found: unknown.path"), ) .expect_log( Some(LogLevel::Debug), - Some("#2 process_rate_limit_policy: empty descriptors"), + Some("process_policy: empty descriptors"), ) .execute_and_expect(ReturnType::Action(Action::Continue)) .unwrap(); diff --git a/utils/deploy/envoy-notls.yaml b/utils/deploy/envoy-notls.yaml index 31848620..e73be330 100644 --- a/utils/deploy/envoy-notls.yaml +++ b/utils/deploy/envoy-notls.yaml @@ -161,15 +161,15 @@ data: "operator": "eq", "value": "/get" } + ], + "actions": [ + { + "extension": "authorino", + "scope": "effective-route-1", + "data": [] + } ] } - ], - "actions": [ - { - "extension": "authorino", - "scope": "effective-route-1", - "data": [] - } ] }, { @@ -179,18 +179,18 @@ data: ], "rules": [ { - "conditions": [] - } - ], - "actions": [ - { - "extension": "limitador", - "scope": "rlp-ns-A/rlp-name-A", - "data": [ + "conditions": [], + "actions": [ { - "selector": { - "selector": "unknown.path" - } + "extension": "limitador", + "scope": "rlp-ns-A/rlp-name-A", + "data": [ + { + "selector": { + "selector": "unknown.path" + } + } + ] } ] } @@ -209,19 +209,19 @@ data: "operator": "startswith", "value": "/unknown-path" } - ] - } - ], - "actions": [ - { - "extension": "limitador", - "scope": "rlp-ns-B/rlp-name-B", - "data": [ + ], + "actions": [ { - "static": { - "key": "rlp-ns-B/rlp-name-B/limit-not-to-be-activated", - "value": "1" - } + "extension": "limitador", + "scope": "rlp-ns-B/rlp-name-B", + "data": [ + { + "static": { + "key": "rlp-ns-B/rlp-name-B/limit-not-to-be-activated", + "value": "1" + } + } + ] } ] } @@ -250,35 +250,35 @@ data: "operator": "eq", "value": "GET" } - ] - } - ], - "actions": [ - { - "extension": "limitador", - "scope": "rlp-ns-C/rlp-name-C", - "data": [ - { - "static": { - "key": "limit_to_be_activated", - "value": "1" - } - }, - { - "selector": { - "selector": "source.address" - } - }, - { - "selector": { - "selector": "request.headers.My-Custom-Header-01" - } - }, + ], + "actions": [ { - "selector": { - "selector": "metadata.filter_metadata.envoy\\.filters\\.http\\.header_to_metadata.user_id", - "key": "user_id" - } + "extension": "limitador", + "scope": "rlp-ns-C/rlp-name-C", + "data": [ + { + "static": { + "key": "limit_to_be_activated", + "value": "1" + } + }, + { + "selector": { + "selector": "source.address" + } + }, + { + "selector": { + "selector": "request.headers.My-Custom-Header-01" + } + }, + { + "selector": { + "selector": "metadata.filter_metadata.envoy\\.filters\\.http\\.header_to_metadata.user_id", + "key": "user_id" + } + } + ] } ] } @@ -297,24 +297,24 @@ data: "operator": "eq", "value": "/get" } - ] - } - ], - "actions": [ - { - "extension": "authorino", - "scope": "effective-route-1", - "data": [] - }, - { - "extension": "limitador", - "scope": "multi-ns-A/multi-name-A", - "data": [ + ], + "actions": [ + { + "extension": "authorino", + "scope": "effective-route-1", + "data": [] + }, { - "selector": { - "selector": "filter_state.wasm\\.kuadrant\\.identity\\.userid", - "key": "user_id" - } + "extension": "limitador", + "scope": "multi-ns-A/multi-name-A", + "data": [ + { + "selector": { + "selector": "filter_state.wasm\\.kuadrant\\.identity\\.userid", + "key": "user_id" + } + } + ] } ] } diff --git a/utils/deploy/envoy-tls.yaml b/utils/deploy/envoy-tls.yaml index d420595f..86264f2e 100644 --- a/utils/deploy/envoy-tls.yaml +++ b/utils/deploy/envoy-tls.yaml @@ -170,15 +170,15 @@ data: "operator": "eq", "value": "/get" } + ], + "actions": [ + { + "extension": "authorino", + "scope": "effective-route-1", + "data": [] + } ] } - ], - "actions": [ - { - "extension": "authorino", - "scope": "effective-route-1", - "data": [] - } ] }, { @@ -188,18 +188,18 @@ data: ], "rules": [ { - "conditions": [] - } - ], - "actions": [ - { - "extension": "limitador", - "scope": "rlp-ns-A/rlp-name-A", - "data": [ + "conditions": [], + "actions": [ { - "selector": { - "selector": "unknown.path" - } + "extension": "limitador", + "scope": "rlp-ns-A/rlp-name-A", + "data": [ + { + "selector": { + "selector": "unknown.path" + } + } + ] } ] } @@ -218,19 +218,19 @@ data: "operator": "startswith", "value": "/unknown-path" } - ] - } - ], - "actions": [ - { - "extension": "limitador", - "scope": "rlp-ns-B/rlp-name-B", - "data": [ + ], + "actions": [ { - "static": { - "key": "rlp-ns-B/rlp-name-B/limit-not-to-be-activated", - "value": "1" - } + "extension": "limitador", + "scope": "rlp-ns-B/rlp-name-B", + "data": [ + { + "static": { + "key": "rlp-ns-B/rlp-name-B/limit-not-to-be-activated", + "value": "1" + } + } + ] } ] } @@ -259,35 +259,35 @@ data: "operator": "eq", "value": "GET" } - ] - } - ], - "actions": [ - { - "extension": "limitador", - "scope": "rlp-ns-C/rlp-name-C", - "data": [ - { - "static": { - "key": "limit_to_be_activated", - "value": "1" - } - }, - { - "selector": { - "selector": "source.address" - } - }, - { - "selector": { - "selector": "request.headers.My-Custom-Header-01" - } - }, + ], + "actions": [ { - "selector": { - "selector": "metadata.filter_metadata.envoy\\.filters\\.http\\.header_to_metadata.user_id", - "key": "user_id" - } + "extension": "limitador", + "scope": "rlp-ns-C/rlp-name-C", + "data": [ + { + "static": { + "key": "limit_to_be_activated", + "value": "1" + } + }, + { + "selector": { + "selector": "source.address" + } + }, + { + "selector": { + "selector": "request.headers.My-Custom-Header-01" + } + }, + { + "selector": { + "selector": "metadata.filter_metadata.envoy\\.filters\\.http\\.header_to_metadata.user_id", + "key": "user_id" + } + } + ] } ] } @@ -306,24 +306,24 @@ data: "operator": "eq", "value": "/get" } - ] - } - ], - "actions": [ - { - "extension": "authorino", - "scope": "effective-route-1", - "data": [] - }, - { - "extension": "limitador", - "scope": "multi-ns-A/multi-name-A", - "data": [ + ], + "actions": [ + { + "extension": "authorino", + "scope": "effective-route-1", + "data": [] + }, { - "selector": { - "selector": "filter_state.wasm\\.kuadrant\\.identity\\.userid", - "key": "user_id" - } + "extension": "limitador", + "scope": "multi-ns-A/multi-name-A", + "data": [ + { + "selector": { + "selector": "filter_state.wasm\\.kuadrant\\.identity\\.userid", + "key": "user_id" + } + } + ] } ] }