diff options
| author | mo khan <mo@mokhan.ca> | 2025-07-03 18:21:42 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-07-03 18:21:42 -0600 |
| commit | 2e926541711ffa6eedb17000d0e08b28414929e8 (patch) | |
| tree | e37ecca4e9d61a29c567045803bbf6427ce1aa73 | |
| parent | 22349f2dd5141bbb1247a4f374d39a9a091f0243 (diff) | |
| parent | 3e8acb357822807a0eccb28ec84c881724e045ce (diff) | |
Merge branch 'envoy' into 'main'
Add Envoy Proxy Integration to authzd
See merge request gitlab-org/software-supply-chain-security/authorization/authzd!3
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | .gitlab-ci.yml | 2 | ||||
| -rw-r--r-- | .runway/runway.yml | 2 | ||||
| -rw-r--r-- | Dockerfile | 36 | ||||
| -rw-r--r-- | Makefile | 28 | ||||
| -rw-r--r-- | Procfile | 2 | ||||
| -rw-r--r-- | README.md | 4 | ||||
| -rw-r--r-- | bin/.keep | 0 | ||||
| -rwxr-xr-x | bin/envoy | 3 | ||||
| -rw-r--r-- | etc/envoy/envoy.yaml | 163 | ||||
| -rw-r--r-- | mise.toml | 1 |
11 files changed, 217 insertions, 25 deletions
@@ -1,3 +1,4 @@ +bin target # Explicitly include vendor directory diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 375ce308..6ae0a526 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -43,6 +43,6 @@ lint: stage: test needs: [] before_script: - - make setup + - rustup component add clippy rustfmt script: - make lint diff --git a/.runway/runway.yml b/.runway/runway.yml index a82a3911..2824fe1d 100644 --- a/.runway/runway.yml +++ b/.runway/runway.yml @@ -7,7 +7,7 @@ metadata: owner_email_handle: mkhan product_category: authorization spec: - container_port: 50051 + container_port: 20000 deployment: strategy: "expedited" regions: @@ -1,14 +1,36 @@ # syntax=docker/dockerfile:1 -FROM rust:alpine AS builder +# Build stage for authzd +FROM rust:alpine AS authzd-builder RUN apk add --no-cache musl-dev WORKDIR /app COPY . ./ RUN cargo build --release --target x86_64-unknown-linux-musl --offline RUN strip /app/target/x86_64-unknown-linux-musl/release/authzd -FROM gcr.io/distroless/static-debian12:nonroot -EXPOSE 50051 -WORKDIR /var/www -COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/authzd /bin/authzd -COPY --from=builder /app/etc/authzd /etc/authzd -ENTRYPOINT ["/bin/authzd"] +# Build stage for getting Envoy binary +FROM envoyproxy/envoy:v1.34-latest AS envoy-binary + +# Build stage for Procfile supervisor +FROM golang:1.24-alpine AS minit-builder +RUN go install github.com/xlgmokha/minit@latest + +# Build stage for getting dumb-init +FROM debian:bookworm-slim AS dumb-init-builder +RUN apt-get update && apt-get install -y wget && \ + wget -O /usr/bin/dumb-init https://github.com/Yelp/dumb-init/releases/download/v1.2.5/dumb-init_1.2.5_x86_64 && \ + chmod +x /usr/bin/dumb-init + +# Final stage +FROM gcr.io/distroless/base-debian12:nonroot +EXPOSE 20000 +WORKDIR / +COPY --from=authzd-builder /app/Procfile /Procfile +COPY --from=authzd-builder /app/etc/authzd /etc/authzd +COPY --from=authzd-builder /app/etc/envoy /etc/envoy +COPY --from=authzd-builder /app/target/x86_64-unknown-linux-musl/release/authzd /bin/authzd +COPY --from=envoy-binary /usr/local/bin/envoy /bin/envoy +COPY --from=minit-builder /go/bin/minit /bin/minit +COPY --from=dumb-init-builder /usr/bin/dumb-init /usr/bin/dumb-init + +ENTRYPOINT ["/usr/bin/dumb-init", "--"] +CMD ["/bin/minit"] @@ -1,15 +1,17 @@ -PROJECT_NAME := $(shell basename $(shell pwd)) +PROJECT_NAME := $(shell basename $(shell pwd))# {{{}}} GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD | sed 's/\//_/g') IMAGE_TAG := $(PROJECT_NAME):$(GIT_BRANCH) .PHONY: build check test run clean fmt lint doc vendor -.PHONY: build-image run-image health-check list-services test-grpc +.PHONY: build-image run-image health-check list-services test-image setup: - @rustup component add clippy rustfmt + mise install + mise exec go -- go install github.com/xlgmokha/minit@latest + mise exec rust -- rustup component add clippy rustfmt # Cargo targets -build: vendor +build: @cargo build --offline check: @@ -18,8 +20,9 @@ check: test: @cargo test -run: - @cargo run --offline +run: build + @cp target/debug/authzd bin/authzd + @minit clean: @cargo clean @@ -37,18 +40,15 @@ vendor: @cargo vendor # Docker targets -build-image: vendor +build-image: @docker build --tag $(IMAGE_TAG) . -build-image-clean: - @docker build --no-cache --tag $(IMAGE_TAG) . - run-image: build-image - @docker run --rm -p 50051:50051 --init -it $(IMAGE_TAG) + @docker run --rm -p 20000:20000 --init -it $(IMAGE_TAG) -# gRPC testing targets +# HTTP and gRPC testing targets health-check: - @grpcurl -plaintext localhost:50051 grpc.health.v1.Health/Check + @grpcurl -plaintext localhost:20000 grpc.health.v1.Health/Check list-services: - @grpcurl -plaintext localhost:50051 list + @grpcurl -plaintext localhost:20000 list diff --git a/Procfile b/Procfile new file mode 100644 index 00000000..7d0c1cc8 --- /dev/null +++ b/Procfile @@ -0,0 +1,2 @@ +authzd: ./bin/authzd +envoy: ./bin/envoy -c ./etc/envoy/envoy.yaml --base-id 1 --log-level warn --component-log-level admin:warn,connection:warn,grpc:trace,http:warn,http2:warn,router:warn,upstream:warn @@ -51,13 +51,13 @@ It integrates with an identity provider (IdP) and uses message queues to stay in 1. Install tools: ```sh - $ mise install + $ make setup ``` 1. Start servers: ```sh - $ cargo run + $ make run ``` ## Environments diff --git a/bin/.keep b/bin/.keep new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/bin/.keep diff --git a/bin/envoy b/bin/envoy new file mode 100755 index 00000000..ede6290c --- /dev/null +++ b/bin/envoy @@ -0,0 +1,3 @@ +#!/bin/sh + +exec envoy $@ diff --git a/etc/envoy/envoy.yaml b/etc/envoy/envoy.yaml new file mode 100644 index 00000000..1cf88353 --- /dev/null +++ b/etc/envoy/envoy.yaml @@ -0,0 +1,163 @@ +node: + id: authzd + cluster: authzd +admin: + address: + socket_address: + address: 0.0.0.0 + port_value: 9991 +application_log_config: + log_format: + json_format: + timestamp: "%Y-%m-%dT%T.%FZ" + thread_id: "%t" + level: "%l" + logger: "%n" + message: "%j" +overload_manager: + resource_monitors: + - name: "envoy.resource_monitors.global_downstream_max_connections" + typed_config: + "@type": type.googleapis.com/envoy.extensions.resource_monitors.downstream_connections.v3.DownstreamConnectionsConfig + max_active_downstream_connections: 10240 +static_resources: + clusters: + - name: authzd + connect_timeout: 5s + type: STATIC + lb_policy: ROUND_ROBIN + load_assignment: + cluster_name: authzd + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 50051 + typed_extension_protocol_options: + envoy.extensions.upstreams.http.v3.HttpProtocolOptions: + "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions + explicit_http_config: + http2_protocol_options: {} + health_checks: + - timeout: 3s + interval: 5s + unhealthy_threshold: 2 + healthy_threshold: 2 + grpc_health_check: {} + circuit_breakers: + thresholds: + - priority: DEFAULT + max_connections: 1024 + max_pending_requests: 1024 + max_requests: 1024 + max_retries: 3 + listeners: + - name: main_listener + address: + socket_address: + protocol: TCP + address: 0.0.0.0 + port_value: 20000 + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + access_log: + - name: envoy.access_loggers.stdout + filter: + not_health_check_filter: {} + typed_config: + "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog + log_format: + json_format: + timestamp: "%START_TIME(%FT%T.%3fZ)%" + method: "%REQ(:METHOD)%" + path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%" + protocol: "%PROTOCOL%" + response_code: "%RESPONSE_CODE%" + response_flags: "%RESPONSE_FLAGS%" + bytes_received: "%BYTES_RECEIVED%" + bytes_sent: "%BYTES_SENT%" + duration_ms: "%DURATION%" + upstream_service_time: "%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%" + x_forwarded_for: "%REQ(X-FORWARDED-FOR)%" + user_agent: "%REQ(USER-AGENT)%" + request_id: "%REQ(X-REQUEST-ID)%" + authority: "%REQ(:AUTHORITY)%" + upstream_host: "%UPSTREAM_HOST%" + codec_type: AUTO + request_timeout: 30s + stream_idle_timeout: 300s + http_filters: + # - name: envoy.filters.http.health_check + # typed_config: + # "@type": type.googleapis.com/envoy.extensions.filters.http.health_check.v3.HealthCheck + # pass_through_mode: false + # headers: + # - name: ":path" + # string_match: + # exact: "/health" + # - name: envoy.filters.http.ext_authz + # typed_config: + # "@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz + # transport_api_version: V3 + # grpc_service: + # envoy_grpc: + # cluster_name: authzd + # timeout: 5s + # failure_mode_allow: false + # include_peer_certificate: true + # clear_route_cache: true + # status_on_error: + # code: 503 + - name: envoy.filters.http.router + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + suppress_envoy_headers: true + route_config: + name: local_route + request_headers_to_remove: + - authorization + - cookie + response_headers_to_add: + - header: + key: "x-content-type-options" + value: "nosniff" + - header: + key: "x-frame-options" + value: "DENY" + - header: + key: "x-xss-protection" + value: "1; mode=block" + virtual_hosts: + - name: backend + domains: ["*"] + routes: + - match: + prefix: "/" + route: + cluster: authzd + timeout: 30s + retry_policy: + retry_on: "5xx,reset,connect-failure,retriable-status-codes" + num_retries: 3 + per_try_timeout: 10s + retriable_status_codes: [503] + request_headers_to_add: + - header: + key: "x-real-ip" + value: "%DOWNSTREAM_REMOTE_ADDRESS_WITHOUT_PORT%" + - header: + key: "x-forwarded-proto" + value: "%REQ(X-FORWARDED-PROTO)%" + stat_prefix: ingress_http + common_http_protocol_options: + idle_timeout: 300s + headers_with_underscores_action: REJECT_REQUEST + http2_protocol_options: + max_concurrent_streams: 100 + initial_stream_window_size: 65536 + server_header_transformation: PASS_THROUGH @@ -1,4 +1,5 @@ [tools] +go = "latest" grpcurl = "latest" make = "latest" rust = "latest" |
