summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-07-03 18:21:42 -0600
committermo khan <mo@mokhan.ca>2025-07-03 18:21:42 -0600
commit2e926541711ffa6eedb17000d0e08b28414929e8 (patch)
treee37ecca4e9d61a29c567045803bbf6427ce1aa73
parent22349f2dd5141bbb1247a4f374d39a9a091f0243 (diff)
parent3e8acb357822807a0eccb28ec84c881724e045ce (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--.gitignore1
-rw-r--r--.gitlab-ci.yml2
-rw-r--r--.runway/runway.yml2
-rw-r--r--Dockerfile36
-rw-r--r--Makefile28
-rw-r--r--Procfile2
-rw-r--r--README.md4
-rw-r--r--bin/.keep0
-rwxr-xr-xbin/envoy3
-rw-r--r--etc/envoy/envoy.yaml163
-rw-r--r--mise.toml1
11 files changed, 217 insertions, 25 deletions
diff --git a/.gitignore b/.gitignore
index 4ea11ebf..2d67c87d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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:
diff --git a/Dockerfile b/Dockerfile
index 07f6f58a..ecb28272 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -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"]
diff --git a/Makefile b/Makefile
index ca1a93db..6eb1ec31 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/README.md b/README.md
index 260f044d..f873358f 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/mise.toml b/mise.toml
index 276d2e72..21f7cb80 100644
--- a/mise.toml
+++ b/mise.toml
@@ -1,4 +1,5 @@
[tools]
+go = "latest"
grpcurl = "latest"
make = "latest"
rust = "latest"