From 8b3a79152b0588cd87f22a323c819e74e4e84cf5 Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Fri, 26 Apr 2024 15:26:41 -0600 Subject: [PATCH] core/kubernetes: fix impersonate group header (#5090) * core/kubernetes: fix impersonate group header * formatting --- authorize/evaluator/headers_evaluator_test.go | 24 +++++++++++++++++++ authorize/evaluator/opa/policy/headers.rego | 12 ++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/authorize/evaluator/headers_evaluator_test.go b/authorize/evaluator/headers_evaluator_test.go index ff71bdc2f..5f8156c4a 100644 --- a/authorize/evaluator/headers_evaluator_test.go +++ b/authorize/evaluator/headers_evaluator_test.go @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/timestamppb" @@ -22,6 +23,7 @@ import ( "github.com/pomerium/pomerium/config" "github.com/pomerium/pomerium/pkg/cryptutil" "github.com/pomerium/pomerium/pkg/grpc/session" + "github.com/pomerium/pomerium/pkg/grpc/user" "github.com/pomerium/pomerium/pkg/storage" ) @@ -58,6 +60,8 @@ func TestNewHeadersRequestFromPolicy_nil(t *testing.T) { } func TestHeadersEvaluator(t *testing.T) { + t.Parallel() + type A = []interface{} type M = map[string]interface{} @@ -231,6 +235,26 @@ func TestHeadersEvaluator(t *testing.T) { assert.Equal(t, "", output.Headers.Get("fingerprint")) }) + + t.Run("kubernetes", func(t *testing.T) { + t.Parallel() + + output, err := eval(t, + []protoreflect.ProtoMessage{ + &session.Session{Id: "s1", UserId: "u1"}, + &user.User{Id: "u1", Email: "u1@example.com"}, + }, + &HeadersRequest{ + Issuer: "from.example.com", + ToAudience: "to.example.com", + KubernetesServiceAccountToken: "TOKEN", + Session: RequestSession{ID: "s1"}, + }) + require.NoError(t, err) + assert.Equal(t, "Bearer TOKEN", output.Headers.Get("Authorization")) + assert.Equal(t, "u1@example.com", output.Headers.Get("Impersonate-User")) + assert.Empty(t, output.Headers["Impersonate-Group"]) + }) } func decodeJWSPayload(t *testing.T, jws string) []byte { diff --git a/authorize/evaluator/opa/policy/headers.rego b/authorize/evaluator/opa/policy/headers.rego index 20d55d0d9..379f575f8 100644 --- a/authorize/evaluator/opa/policy/headers.rego +++ b/authorize/evaluator/opa/policy/headers.rego @@ -174,11 +174,12 @@ signed_jwt := io.jwt.encode_sign(jwt_headers, jwt_payload, data.signing_key) kubernetes_headers := h if { input.kubernetes_service_account_token != "" - h := [ + + h := remove_empty_header_values([ ["Authorization", concat(" ", ["Bearer", input.kubernetes_service_account_token])], ["Impersonate-User", jwt_payload_email], ["Impersonate-Group", get_header_string_value(jwt_payload_groups)], - ] + ]) } else := [] google_cloud_serverless_authentication_service_account := s if { @@ -267,3 +268,10 @@ get_header_string_value(obj) := s if { } else := s if { s := concat(",", [obj]) } + +remove_empty_header_values(arr) := [[k, v] | + some idx + k := arr[idx][0] + v := arr[idx][1] + v != "" +]