From 36215d033d2c46d60505db4acf631ea3be964dac Mon Sep 17 00:00:00 2001 From: Dmitry Kartsev Date: Mon, 8 Dec 2025 11:54:18 +0200 Subject: [PATCH] envoy-jwt-auth-helper: Added support for environment variable configuration overwrite for envoy-jwt-auth-helper envoy-jwt-auth-helper: Upgraded envoy-jwt-auth-helper go.mod to Go 1.25.5 envoy-jwt-auth-helper: Fixed few deprecations envoy-jwt-auth-helper: Upgraded build-stage base image to golang:1.25.5-bookworm envoy-jwt-auth-helper: Added docs Signed-off-by: Dmitry Kartsev --- k8s/envoy-jwt-auth-helper/Dockerfile | 2 +- k8s/envoy-jwt-auth-helper/README.md | 10 +++++++ k8s/envoy-jwt-auth-helper/go.mod | 5 ++-- k8s/envoy-jwt-auth-helper/go.sum | 6 +++++ .../pkg/auth/ext_auth_server.go | 5 +--- .../pkg/config/config.go | 27 ++++++++++++++----- 6 files changed, 42 insertions(+), 13 deletions(-) diff --git a/k8s/envoy-jwt-auth-helper/Dockerfile b/k8s/envoy-jwt-auth-helper/Dockerfile index 8cd85c6..3cb831d 100644 --- a/k8s/envoy-jwt-auth-helper/Dockerfile +++ b/k8s/envoy-jwt-auth-helper/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:bookworm AS build-stage +FROM golang:1.25.5-bookworm AS build-stage WORKDIR /app COPY . . diff --git a/k8s/envoy-jwt-auth-helper/README.md b/k8s/envoy-jwt-auth-helper/README.md index 73714ff..a74d483 100644 --- a/k8s/envoy-jwt-auth-helper/README.md +++ b/k8s/envoy-jwt-auth-helper/README.md @@ -39,6 +39,16 @@ port = 9010 jwt_mode = "jwt_svid_validator" audience = "spiffe://example.org/myservice" ``` +Configuration values can be overridden using environment variables with +the `SPIRE_ENVOY_JWT_HELPER_` prefix followed by the configuration parameter name in uppercase. +``` +export SPIRE_ENVOY_JWT_HELPER_SOCKET_PATH="unix:///run/secrets/workload-spiffe-uds" +export SPIRE_ENVOY_JWT_HELPER_HOST="0.0.0.0" +export SPIRE_ENVOY_JWT_HELPER_PORT=8080 +export SPIRE_ENVOY_JWT_HELPER_JWT_MODE="jwt_svid_validator" +export SPIRE_ENVOY_JWT_HELPER_AUDIENCE="spiffe://example.org/myservice" +``` + ## As Envoy External Authorization filter diff --git a/k8s/envoy-jwt-auth-helper/go.mod b/k8s/envoy-jwt-auth-helper/go.mod index 990a61d..e78a4e0 100644 --- a/k8s/envoy-jwt-auth-helper/go.mod +++ b/k8s/envoy-jwt-auth-helper/go.mod @@ -1,12 +1,12 @@ module github.com/spiffe/envoy-jwt-auth-helper -go 1.20 +go 1.25.5 require ( github.com/envoyproxy/go-control-plane v0.11.0 github.com/gogo/googleapis v1.4.1 - github.com/golang/protobuf v1.5.3 github.com/hashicorp/hcl v1.0.0 + github.com/kelseyhightower/envconfig v1.4.0 github.com/spiffe/go-spiffe/v2 v2.1.3 google.golang.org/genproto v0.0.0-20230327215041-6ac7f18bb9d5 google.golang.org/grpc v1.54.0 @@ -18,6 +18,7 @@ require ( github.com/envoyproxy/protoc-gen-validate v0.10.1 // indirect github.com/go-jose/go-jose/v3 v3.0.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/zeebo/errs v1.3.0 // indirect golang.org/x/crypto v0.7.0 // indirect golang.org/x/mod v0.9.0 // indirect diff --git a/k8s/envoy-jwt-auth-helper/go.sum b/k8s/envoy-jwt-auth-helper/go.sum index 5cf4eab..cca300e 100644 --- a/k8s/envoy-jwt-auth-helper/go.sum +++ b/k8s/envoy-jwt-auth-helper/go.sum @@ -32,8 +32,11 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= +github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -44,6 +47,7 @@ github.com/spiffe/go-spiffe/v2 v2.1.3/go.mod h1:eVDqm9xFvyqao6C+eQensb9ZPkyNEeaU github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zeebo/errs v1.3.0 h1:hmiaKqgYZzcVgRL1Vkc1Mn2914BbzB0IBxs+ebeutGs= @@ -79,6 +83,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -121,5 +126,6 @@ google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/k8s/envoy-jwt-auth-helper/pkg/auth/ext_auth_server.go b/k8s/envoy-jwt-auth-helper/pkg/auth/ext_auth_server.go index 7e7baa4..bf45332 100644 --- a/k8s/envoy-jwt-auth-helper/pkg/auth/ext_auth_server.go +++ b/k8s/envoy-jwt-auth-helper/pkg/auth/ext_auth_server.go @@ -10,7 +10,6 @@ import ( auth "github.com/envoyproxy/go-control-plane/envoy/service/auth/v3" envoy_type "github.com/envoyproxy/go-control-plane/envoy/type/v3" "github.com/gogo/googleapis/google/rpc" - "github.com/golang/protobuf/ptypes/wrappers" "github.com/spiffe/go-spiffe/v2/svid/jwtsvid" "github.com/spiffe/go-spiffe/v2/workloadapi" rpcstatus "google.golang.org/genproto/googleapis/rpc/status" @@ -126,9 +125,7 @@ func (a *AuthServer) injectJWTSVID(ctx context.Context) (*auth.CheckResponse, er response := &auth.CheckResponse{} headers := []*core.HeaderValueOption{ { - Append: &wrappers.BoolValue{ - Value: false, //Default is true - }, + AppendAction: core.HeaderValueOption_OVERWRITE_IF_EXISTS_OR_ADD, Header: &core.HeaderValue{ Key: "authorization", Value: fmt.Sprintf("Bearer %s", jwtSVID.Marshal()), diff --git a/k8s/envoy-jwt-auth-helper/pkg/config/config.go b/k8s/envoy-jwt-auth-helper/pkg/config/config.go index 13aade2..a1c73d6 100644 --- a/k8s/envoy-jwt-auth-helper/pkg/config/config.go +++ b/k8s/envoy-jwt-auth-helper/pkg/config/config.go @@ -3,22 +3,26 @@ package config import ( "fmt" "io/ioutil" + "log" "os" "path/filepath" "github.com/hashicorp/hcl" + "github.com/kelseyhightower/envconfig" ) +const EnvVarPrefix = "SPIRE_ENVOY_JWT_HELPER" + // Config available configurations type Config struct { - SocketPath string `hcl:"socket_path"` - Host string `hcl:"host"` - Port int `hcl:"port"` - JWTMode string `hcl:"jwt_mode"` - Audience string `hcl:"audience"` + SocketPath string `hcl:"socket_path" envconfig:"SOCKET_PATH"` + Host string `hcl:"host" envconfig:"HOST"` + Port int `hcl:"port" envconfig:"PORT"` + JWTMode string `hcl:"jwt_mode" envconfig:"JWT_MODE"` + Audience string `hcl:"audience" envconfig:"AUDIENCE"` } -//ParseConfigFile parse config file +// ParseConfigFile parse config file func ParseConfigFile(filePath string) (*Config, error) { data, err := ioutil.ReadFile(filePath) if err != nil { @@ -39,5 +43,16 @@ func ParseConfigFile(filePath string) (*Config, error) { return nil, fmt.Errorf("unable to decode configuration: %v", err) } + err = envconfig.Process(EnvVarPrefix, c) + if err != nil { + return nil, fmt.Errorf("environment variable configuration overwrite failed: %v", err) + } + c.Print() + return c, nil } + +func (c *Config) Print() { + msg := "loaded config:\nSocketPath: %s \nHost: %s\nPort: %d\nJWTMode: %s\nAudience: %s\n" + log.Printf(msg, c.SocketPath, c.Host, c.Port, c.JWTMode, c.Audience) +}