From 736e7cc0a1f77b8abd73c5b0e9841e92d4088ecf Mon Sep 17 00:00:00 2001 From: Eguzki Astiz Lezaun Date: Thu, 9 Nov 2023 20:51:41 +0100 Subject: [PATCH 1/4] gRPC server reflection Signed-off-by: Eguzki Astiz Lezaun --- Cargo.lock | 14 ++++ limitador-server/Cargo.toml | 1 + limitador-server/build.rs | 22 ++++-- limitador-server/sandbox/.gitignore | 1 + limitador-server/sandbox/Makefile | 21 ++++++ limitador-server/sandbox/README.md | 73 +++++++++++++++++++ .../docker-compose-limitador-disk.yaml | 1 + .../docker-compose-limitador-infinispan.yaml | 1 + .../docker-compose-limitador-memory.yaml | 1 + ...docker-compose-limitador-redis-cached.yaml | 1 + .../docker-compose-limitador-redis.yaml | 1 + limitador-server/src/envoy_rls/server.rs | 10 +++ 12 files changed, 139 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 90ab1c58..25ea980b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1577,6 +1577,7 @@ dependencies = [ "tokio", "tonic", "tonic-build", + "tonic-reflection", "url", ] @@ -3027,6 +3028,19 @@ dependencies = [ "syn 2.0.32", ] +[[package]] +name = "tonic-reflection" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fa37c513df1339d197f4ba21d28c918b9ef1ac1768265f11ecb6b7f1cba1b76" +dependencies = [ + "prost", + "prost-types", + "tokio", + "tokio-stream", + "tonic", +] + [[package]] name = "tower" version = "0.4.13" diff --git a/limitador-server/Cargo.toml b/limitador-server/Cargo.toml index 011a2cd7..404718f4 100644 --- a/limitador-server/Cargo.toml +++ b/limitador-server/Cargo.toml @@ -22,6 +22,7 @@ limitador = { path = "../limitador", features = ['lenient_conditions'] } tokio = { version = "1", features = ["full"] } thiserror = "1" tonic = "0.10" +tonic-reflection = "0.10.2" prost = "0.12" prost-types = "0.12" serde_yaml = "0.9" diff --git a/limitador-server/build.rs b/limitador-server/build.rs index 0a816902..780efae2 100644 --- a/limitador-server/build.rs +++ b/limitador-server/build.rs @@ -1,4 +1,6 @@ +use std::env; use std::error::Error; +use std::path::PathBuf; use std::process::Command; fn main() -> Result<(), Box> { @@ -9,14 +11,18 @@ fn main() -> Result<(), Box> { } fn generate_protobuf() -> Result<(), Box> { - tonic_build::configure().build_server(true).compile( - &["envoy/service/ratelimit/v3/rls.proto"], - &[ - "vendor/protobufs/data-plane-api", - "vendor/protobufs/protoc-gen-validate", - "vendor/protobufs/xds", - ], - )?; + let original_out_dir = PathBuf::from(env::var("OUT_DIR")?); + tonic_build::configure() + .build_server(true) + .file_descriptor_set_path(original_out_dir.join("rls.bin")) + .compile( + &["envoy/service/ratelimit/v3/rls.proto"], + &[ + "vendor/protobufs/data-plane-api", + "vendor/protobufs/protoc-gen-validate", + "vendor/protobufs/xds", + ], + )?; Ok(()) } diff --git a/limitador-server/sandbox/.gitignore b/limitador-server/sandbox/.gitignore index fc648bed..90006a67 100644 --- a/limitador-server/sandbox/.gitignore +++ b/limitador-server/sandbox/.gitignore @@ -1,3 +1,4 @@ +/bin/ *.crt *.key *.pem diff --git a/limitador-server/sandbox/Makefile b/limitador-server/sandbox/Makefile index 1fd82052..e72a15ad 100644 --- a/limitador-server/sandbox/Makefile +++ b/limitador-server/sandbox/Makefile @@ -74,8 +74,29 @@ clean-containers: ## clean containers - $(DOCKER) compose -f docker-compose-envoy.yaml -f docker-compose-limitador-redis.yaml down --volumes --remove-orphans - $(DOCKER)_compose -f docker-compose-envoy.yaml -f docker-compose-limitador-redis-cached.yaml down --volumes --remove-orphans - $(DOCKER) compose -f docker-compose-envoy.yaml -f docker-compose-limitador-infinispan.yaml down --volumes --remove-orphans + - $(DOCKER) compose -f docker-compose-envoy.yaml -f docker-compose-limitador-disk.yaml down --volumes --remove-orphans - $(MAKE) cleancerts clean: ## clean all - $(MAKE) clean-containers - $(MAKE) redis-clean-certs + +GRPCURL=$(PROJECT_PATH)/bin/grpcurl +$(GRPCURL): + $(call go-install-tool,$(GRPCURL),github.com/fullstorydev/grpcurl/cmd/grpcurl@v1.8.9) + +.PHONY: grpcurl +grpcurl: $(GRPCURL) ## Download grpcurl locally if necessary. + +# go-install-tool will 'go install' any package $2 and install it to $1. +define go-install-tool +@[ -f $(1) ] || { \ +set -e ;\ +TMP_DIR=$$(mktemp -d) ;\ +cd $$TMP_DIR ;\ +go mod init tmp ;\ +echo "Downloading $(2)" ;\ +GOBIN=$(PROJECT_PATH)/bin go install $(2) ;\ +rm -rf $$TMP_DIR ;\ +} +endef diff --git a/limitador-server/sandbox/README.md b/limitador-server/sandbox/README.md index 2d4113a4..36c98ae8 100644 --- a/limitador-server/sandbox/README.md +++ b/limitador-server/sandbox/README.md @@ -27,10 +27,83 @@ Check out `make help` for all the targets. ### Limitador's admin HTTP endpoint +Limits + ```bash curl -i http://127.0.0.1:18080/limits/test_namespace ``` +Counters + +```bash +curl -i http://127.0.0.1:18080/counters/test_namespace +``` + +Metrics + +```bash +curl -i http://127.0.0.1:18080/metrics +``` + +### Limitador's GRPC RateLimitService endpoint + +Get `grpcurl`. You need [Go SDK](https://golang.org/doc/install) installed. + +Golang version >= 1.18 (from [fullstorydev/grpcurl](https://github.com/fullstorydev/grpcurl/blob/v1.8.9/go.mod#L3)) + +```bash +make grpcurl +``` + +Inspect `RateLimitService` GRPC service + +```bash +bin/grpcurl -plaintext 127.0.0.1:18081 describe envoy.service.ratelimit.v3.RateLimitService +``` + +Make a custom request + +```bash +bin/grpcurl -plaintext -d @ 127.0.0.1:18081 envoy.service.ratelimit.v3.RateLimitService.ShouldRateLimit <, @@ -202,8 +206,14 @@ pub async fn run_envoy_rls_server( let rate_limiter = MyRateLimiter::new(limiter, rate_limit_headers); let svc = RateLimitServiceServer::new(rate_limiter); + let reflection_service = tonic_reflection::server::Builder::configure() + .register_encoded_file_descriptor_set(rls_proto::RLS_DESCRIPTOR_SET) + .build() + .unwrap(); + Server::builder() .add_service(svc) + .add_service(reflection_service) .serve(address.parse().unwrap()) .await } From 80be4142b78a09cf748ee0a3c3798e2729c60a58 Mon Sep 17 00:00:00 2001 From: Eguzki Astiz Lezaun Date: Fri, 10 Nov 2023 00:16:17 +0100 Subject: [PATCH 2/4] deploy-disk: add to doc and cleaning target --- limitador-server/sandbox/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/limitador-server/sandbox/README.md b/limitador-server/sandbox/README.md index 36c98ae8..3172a0f1 100644 --- a/limitador-server/sandbox/README.md +++ b/limitador-server/sandbox/README.md @@ -24,6 +24,7 @@ Check out `make help` for all the targets. | Redis Secured | `make deploy-redis-tls` | Uses Redis with TLS and password protected to store counters | | Redis Cached | `make deploy-redis-cached` | Uses Redis to store counters, with an in-memory cache | | Infinispan | `make deploy-infinispan` | Uses Infinispan to store counters | +| Disk | `make deploy-disk` | Uses disk to store counters | ### Limitador's admin HTTP endpoint From f31a56b317923ab526b6a75fcee9dae631c49230 Mon Sep 17 00:00:00 2001 From: Eguzki Astiz Lezaun Date: Tue, 19 Dec 2023 17:17:47 +0100 Subject: [PATCH 3/4] gRPC server reflection enabled with --grpc-reflection-service command line param --- .../sandbox/docker-compose-limitador-disk.yaml | 1 + .../docker-compose-limitador-infinispan.yaml | 1 + .../sandbox/docker-compose-limitador-memory.yaml | 1 + .../docker-compose-limitador-redis-cached.yaml | 1 + .../docker-compose-limitador-redis-tls.yaml | 1 + .../sandbox/docker-compose-limitador-redis.yaml | 1 + limitador-server/src/config.rs | 4 ++++ limitador-server/src/envoy_rls/server.rs | 16 +++++++++++----- limitador-server/src/main.rs | 10 ++++++++++ 9 files changed, 31 insertions(+), 5 deletions(-) diff --git a/limitador-server/sandbox/docker-compose-limitador-disk.yaml b/limitador-server/sandbox/docker-compose-limitador-disk.yaml index 7ebeebcd..b62397a1 100644 --- a/limitador-server/sandbox/docker-compose-limitador-disk.yaml +++ b/limitador-server/sandbox/docker-compose-limitador-disk.yaml @@ -16,6 +16,7 @@ services: - --http-port - "8080" - -vvv + - --grpc-reflection-service - /opt/kuadrant/limits/limits.yaml - disk - "/tmp/data" diff --git a/limitador-server/sandbox/docker-compose-limitador-infinispan.yaml b/limitador-server/sandbox/docker-compose-limitador-infinispan.yaml index 5e0e0d20..100c693d 100644 --- a/limitador-server/sandbox/docker-compose-limitador-infinispan.yaml +++ b/limitador-server/sandbox/docker-compose-limitador-infinispan.yaml @@ -17,6 +17,7 @@ services: - --http-port - "8080" - -vvvv + - --grpc-reflection-service - /opt/kuadrant/limits/limits.yaml - infinispan - --cache-name diff --git a/limitador-server/sandbox/docker-compose-limitador-memory.yaml b/limitador-server/sandbox/docker-compose-limitador-memory.yaml index fe2ed907..eec05ecf 100644 --- a/limitador-server/sandbox/docker-compose-limitador-memory.yaml +++ b/limitador-server/sandbox/docker-compose-limitador-memory.yaml @@ -16,6 +16,7 @@ services: - --http-port - "8080" - -vvv + - --grpc-reflection-service - /opt/kuadrant/limits/limits.yaml - memory expose: diff --git a/limitador-server/sandbox/docker-compose-limitador-redis-cached.yaml b/limitador-server/sandbox/docker-compose-limitador-redis-cached.yaml index 47b88e94..6db3a4de 100644 --- a/limitador-server/sandbox/docker-compose-limitador-redis-cached.yaml +++ b/limitador-server/sandbox/docker-compose-limitador-redis-cached.yaml @@ -17,6 +17,7 @@ services: - --http-port - "8080" - -vvv + - --grpc-reflection-service - /opt/kuadrant/limits/limits.yaml - redis_cached - --ttl diff --git a/limitador-server/sandbox/docker-compose-limitador-redis-tls.yaml b/limitador-server/sandbox/docker-compose-limitador-redis-tls.yaml index 172cfbb3..1046b25b 100644 --- a/limitador-server/sandbox/docker-compose-limitador-redis-tls.yaml +++ b/limitador-server/sandbox/docker-compose-limitador-redis-tls.yaml @@ -17,6 +17,7 @@ services: - --http-port - "8080" - -vvv + - --grpc-reflection-service - /opt/kuadrant/limits/limits.yaml - redis - rediss://:foobared@redis:6379/#insecure diff --git a/limitador-server/sandbox/docker-compose-limitador-redis.yaml b/limitador-server/sandbox/docker-compose-limitador-redis.yaml index 1329bc42..611e0f1b 100644 --- a/limitador-server/sandbox/docker-compose-limitador-redis.yaml +++ b/limitador-server/sandbox/docker-compose-limitador-redis.yaml @@ -17,6 +17,7 @@ services: - --http-port - "8080" - -vvv + - --grpc-reflection-service - /opt/kuadrant/limits/limits.yaml - redis - redis://redis:6379 diff --git a/limitador-server/src/config.rs b/limitador-server/src/config.rs index 3cbb7712..73ee74ed 100644 --- a/limitador-server/src/config.rs +++ b/limitador-server/src/config.rs @@ -33,6 +33,7 @@ pub struct Configuration { pub limit_name_in_labels: bool, pub log_level: Option, pub rate_limit_headers: RateLimitHeaders, + pub grpc_reflection_service: bool, } pub mod env { @@ -83,6 +84,7 @@ impl Configuration { http_port: u16, limit_name_in_labels: bool, rate_limit_headers: RateLimitHeaders, + grpc_reflection_service: bool, ) -> Self { Self { limits_file, @@ -94,6 +96,7 @@ impl Configuration { limit_name_in_labels, log_level: None, rate_limit_headers, + grpc_reflection_service, } } @@ -121,6 +124,7 @@ impl Default for Configuration { limit_name_in_labels: false, log_level: None, rate_limit_headers: RateLimitHeaders::None, + grpc_reflection_service: false, } } } diff --git a/limitador-server/src/envoy_rls/server.rs b/limitador-server/src/envoy_rls/server.rs index 39f54cd6..de6f8925 100644 --- a/limitador-server/src/envoy_rls/server.rs +++ b/limitador-server/src/envoy_rls/server.rs @@ -202,18 +202,24 @@ pub async fn run_envoy_rls_server( address: String, limiter: Arc, rate_limit_headers: RateLimitHeaders, + grpc_reflection_service: bool, ) -> Result<(), transport::Error> { let rate_limiter = MyRateLimiter::new(limiter, rate_limit_headers); let svc = RateLimitServiceServer::new(rate_limiter); - let reflection_service = tonic_reflection::server::Builder::configure() - .register_encoded_file_descriptor_set(rls_proto::RLS_DESCRIPTOR_SET) - .build() - .unwrap(); + let reflection_service = match grpc_reflection_service { + false => None, + true => Some( + tonic_reflection::server::Builder::configure() + .register_encoded_file_descriptor_set(rls_proto::RLS_DESCRIPTOR_SET) + .build() + .unwrap(), + ), + }; Server::builder() .add_service(svc) - .add_service(reflection_service) + .add_optional_service(reflection_service) .serve(address.parse().unwrap()) .await } diff --git a/limitador-server/src/main.rs b/limitador-server/src/main.rs index d1ecdf65..e5546578 100644 --- a/limitador-server/src/main.rs +++ b/limitador-server/src/main.rs @@ -302,6 +302,7 @@ async fn main() -> Result<(), Box> { let envoy_rls_address = config.rlp_address(); let http_api_address = config.http_address(); let rate_limit_headers = config.rate_limit_headers.clone(); + let grpc_reflection_service = config.grpc_reflection_service; let rate_limiter: Arc = match Limiter::new(config).await { Ok(limiter) => Arc::new(limiter), @@ -390,6 +391,7 @@ async fn main() -> Result<(), Box> { envoy_rls_address.to_string(), rate_limiter.clone(), rate_limit_headers, + grpc_reflection_service, )); info!("HTTP server starting on {}", http_api_address); @@ -515,6 +517,13 @@ fn create_config() -> (Configuration, &'static str) { ])) .help("Enables rate limit response headers"), ) + .arg( + Arg::new("grpc_reflection_service") + .long("grpc-reflection-service") + .action(ArgAction::SetTrue) + .display_order(9) + .help("enable gRPC server reflection service"), + ) .subcommand( Command::new("memory") .display_order(1) @@ -745,6 +754,7 @@ fn create_config() -> (Configuration, &'static str) { matches.get_flag("limit_name_in_labels") || env_option_is_enabled("LIMIT_NAME_IN_PROMETHEUS_LABELS"), rate_limit_headers, + matches.get_flag("grpc_reflection_service"), ); config.log_level = match matches.get_count("v") { From d55df6d22ded2d267216d83704811eca68fbf897 Mon Sep 17 00:00:00 2001 From: Eguzki Astiz Lezaun Date: Tue, 19 Dec 2023 17:26:10 +0100 Subject: [PATCH 4/4] gRPC server reflection: doc --- README.md | 1 + doc/server/configuration.md | 2 ++ limitador-server/src/main.rs | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 68413592..c82dec2b 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ port, that implements the Envoy Rate Limit protocol (v3). - [**Getting started**](#getting-started) - [**How it works**](/doc/how-it-works.md) +- [**Configuration**](/doc/server/configuration.md) - [**Development**](#development) - [**Testing Environment**](limitador-server/sandbox/README.md) - [**Kubernetes**](limitador-server/kubernetes/) diff --git a/doc/server/configuration.md b/doc/server/configuration.md index f76baf87..2cfb8d4f 100644 --- a/doc/server/configuration.md +++ b/doc/server/configuration.md @@ -35,6 +35,8 @@ Options: Validates the LIMITS_FILE and exits -H, --rate-limit-headers Enables rate limit response headers [default: NONE] [possible values: NONE, DRAFT_VERSION_03] + --grpc-reflection-service + Enables gRPC server reflection service -h, --help Print help -V, --version diff --git a/limitador-server/src/main.rs b/limitador-server/src/main.rs index e5546578..079e45fc 100644 --- a/limitador-server/src/main.rs +++ b/limitador-server/src/main.rs @@ -522,7 +522,7 @@ fn create_config() -> (Configuration, &'static str) { .long("grpc-reflection-service") .action(ArgAction::SetTrue) .display_order(9) - .help("enable gRPC server reflection service"), + .help("Enables gRPC server reflection service"), ) .subcommand( Command::new("memory")