From 31770840c37fa158b020e7621409d6ab49b22c8f Mon Sep 17 00:00:00 2001 From: Yuval Kohavi Date: Wed, 10 Dec 2025 16:53:09 -0500 Subject: [PATCH 01/12] bring back bed rock auth Signed-off-by: Yuval Kohavi --- .../agentgateway_backend_types.go | 15 +++ .../agentgateway/zz_generated.deepcopy.go | 25 +++++ ...agentgateway.dev_agentgatewaybackends.yaml | 48 +++++++++ ...(responses_and_anthropic_token_count).yaml | 3 + .../Bedrock_backend_with_new_secret_ref.yaml | 18 ++++ ...kend_with_custom_region_and_guardrail.yaml | 4 + .../agentgatewaysyncer/backend/translate.go | 100 ++++++++++++++++-- .../backend/translate_test.go | 30 ++++++ 8 files changed, 237 insertions(+), 6 deletions(-) create mode 100644 pkg/kgateway/agentgatewaysyncer/backend/testdata/Bedrock_backend_with_new_secret_ref.yaml diff --git a/api/v1alpha1/agentgateway/agentgateway_backend_types.go b/api/v1alpha1/agentgateway/agentgateway_backend_types.go index d41c311a42e..15a4373d60a 100644 --- a/api/v1alpha1/agentgateway/agentgateway_backend_types.go +++ b/api/v1alpha1/agentgateway/agentgateway_backend_types.go @@ -1,6 +1,7 @@ package agentgateway import ( + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" gwv1 "sigs.k8s.io/gateway-api/apis/v1" ) @@ -288,6 +289,20 @@ type BedrockConfig struct { // If not specified, the AWS Guardrail policy will not be used. // +optional Guardrail *AWSGuardrailConfig `json:"guardrail,omitempty"` + + // Auth specifies an explicit AWS authentication method for the backend. + // When omitted, we will try to use the default AWS SDK authentication methods. + // + // +optional + Auth *AwsAuth `json:"auth,omitempty"` +} + +// AwsAuth specifies the authentication method to use for the backend. +type AwsAuth struct { + // SecretRef references a Kubernetes Secret containing the AWS credentials. + // The Secret must have keys "accessKey", "secretKey", and optionally "sessionToken". + // +required + SecretRef *corev1.LocalObjectReference `json:"secretRef,omitempty"` } type AWSGuardrailConfig struct { diff --git a/api/v1alpha1/agentgateway/zz_generated.deepcopy.go b/api/v1alpha1/agentgateway/zz_generated.deepcopy.go index b4f50c334ea..849971b94b0 100644 --- a/api/v1alpha1/agentgateway/zz_generated.deepcopy.go +++ b/api/v1alpha1/agentgateway/zz_generated.deepcopy.go @@ -630,6 +630,26 @@ func (in *AttributeAdd) DeepCopy() *AttributeAdd { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AwsAuth) DeepCopyInto(out *AwsAuth) { + *out = *in + if in.SecretRef != nil { + in, out := &in.SecretRef, &out.SecretRef + *out = new(corev1.LocalObjectReference) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AwsAuth. +func (in *AwsAuth) DeepCopy() *AwsAuth { + if in == nil { + return nil + } + out := new(AwsAuth) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AzureOpenAIConfig) DeepCopyInto(out *AzureOpenAIConfig) { *out = *in @@ -1023,6 +1043,11 @@ func (in *BedrockConfig) DeepCopyInto(out *BedrockConfig) { *out = new(AWSGuardrailConfig) (*in).DeepCopyInto(*out) } + if in.Auth != nil { + in, out := &in.Auth, &out.Auth + *out = new(AwsAuth) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BedrockConfig. diff --git a/install/helm/kgateway-crds/templates/agentgateway.dev_agentgatewaybackends.yaml b/install/helm/kgateway-crds/templates/agentgateway.dev_agentgatewaybackends.yaml index f83338e8743..a77d93c7529 100644 --- a/install/helm/kgateway-crds/templates/agentgateway.dev_agentgatewaybackends.yaml +++ b/install/helm/kgateway-crds/templates/agentgateway.dev_agentgatewaybackends.yaml @@ -137,6 +137,30 @@ spec: bedrock: description: Bedrock provider properties: + auth: + description: |- + Auth specifies an explicit AWS authentication method for the backend. + When omitted, we will try to use the default AWS SDK authentication methods. + properties: + secretRef: + description: |- + SecretRef references a Kubernetes Secret containing the AWS credentials. + The Secret must have keys "accessKey", "secretKey", and optionally "sessionToken". + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + required: + - secretRef + type: object guardrail: description: |- Guardrail configures the Guardrail policy to use for the backend. See @@ -1545,6 +1569,30 @@ spec: bedrock: description: Bedrock provider properties: + auth: + description: |- + Auth specifies an explicit AWS authentication method for the backend. + When omitted, we will try to use the default AWS SDK authentication methods. + properties: + secretRef: + description: |- + SecretRef references a Kubernetes Secret containing the AWS credentials. + The Secret must have keys "accessKey", "secretKey", and optionally "sessionToken". + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + required: + - secretRef + type: object guardrail: description: |- Guardrail configures the Guardrail policy to use for the backend. See diff --git a/pkg/kgateway/agentgatewaysyncer/backend/testdata/Bedrock_backend_with_new_route_types_(responses_and_anthropic_token_count).yaml b/pkg/kgateway/agentgatewaysyncer/backend/testdata/Bedrock_backend_with_new_route_types_(responses_and_anthropic_token_count).yaml index 57cd9212c4f..cc9464823cd 100644 --- a/pkg/kgateway/agentgatewaysyncer/backend/testdata/Bedrock_backend_with_new_route_types_(responses_and_anthropic_token_count).yaml +++ b/pkg/kgateway/agentgatewaysyncer/backend/testdata/Bedrock_backend_with_new_route_types_(responses_and_anthropic_token_count).yaml @@ -12,6 +12,9 @@ inlinePolicies: /v1/messages/count_tokens: ANTHROPIC_TOKEN_COUNT /v1/models: MODELS /v1/responses: RESPONSES +- auth: + aws: + implicit: {} key: test-ns/bedrock-with-new-routes name: name: bedrock-with-new-routes diff --git a/pkg/kgateway/agentgatewaysyncer/backend/testdata/Bedrock_backend_with_new_secret_ref.yaml b/pkg/kgateway/agentgatewaysyncer/backend/testdata/Bedrock_backend_with_new_secret_ref.yaml new file mode 100644 index 00000000000..978e2ed665a --- /dev/null +++ b/pkg/kgateway/agentgatewaysyncer/backend/testdata/Bedrock_backend_with_new_secret_ref.yaml @@ -0,0 +1,18 @@ +ai: + providerGroups: + - providers: + - bedrock: + region: us-east-1 + name: backend +inlinePolicies: +- auth: + aws: + explicitConfig: + accessKeyId: secret-accessKey + region: us-east-1 + secretAccessKey: secret-secretKey + sessionToken: secret-sessionToken +key: test-ns/bedrock-with-secret-ref +name: + name: bedrock-with-secret-ref + namespace: test-ns diff --git a/pkg/kgateway/agentgatewaysyncer/backend/testdata/Valid_Bedrock_backend_with_custom_region_and_guardrail.yaml b/pkg/kgateway/agentgatewaysyncer/backend/testdata/Valid_Bedrock_backend_with_custom_region_and_guardrail.yaml index 1739102401c..9d1c371aaf9 100644 --- a/pkg/kgateway/agentgatewaysyncer/backend/testdata/Valid_Bedrock_backend_with_custom_region_and_guardrail.yaml +++ b/pkg/kgateway/agentgatewaysyncer/backend/testdata/Valid_Bedrock_backend_with_custom_region_and_guardrail.yaml @@ -7,6 +7,10 @@ ai: model: anthropic.claude-3-haiku-20240307-v1:0 region: eu-west-1 name: backend +inlinePolicies: +- auth: + aws: + implicit: {} key: test-ns/bedrock-backend-custom name: name: bedrock-backend-custom diff --git a/pkg/kgateway/agentgatewaysyncer/backend/translate.go b/pkg/kgateway/agentgatewaysyncer/backend/translate.go index b22ea4768e0..0155631e92f 100644 --- a/pkg/kgateway/agentgatewaysyncer/backend/translate.go +++ b/pkg/kgateway/agentgatewaysyncer/backend/translate.go @@ -15,6 +15,7 @@ import ( "github.com/kgateway-dev/kgateway/v2/api/v1alpha1/agentgateway" "github.com/kgateway-dev/kgateway/v2/pkg/agentgateway/plugins" "github.com/kgateway-dev/kgateway/v2/pkg/agentgateway/utils" + "github.com/kgateway-dev/kgateway/v2/pkg/kgateway/wellknown" "github.com/kgateway-dev/kgateway/v2/pkg/logging" "github.com/kgateway-dev/kgateway/v2/pkg/utils/kubeutils" ) @@ -224,11 +225,17 @@ func translateAIBackends(ctx plugins.PolicyCtx, be *agentgateway.AgentgatewayBac aiBackend := &api.AIBackend{} if llm := ai.LLM; llm != nil { - provider, err := translateLLMProvider(llm, utils.SingularLLMProviderSubBackendName) + provider, auth, err := translateLLMProvider(ctx, llm, utils.SingularLLMProviderSubBackendName, be.Namespace) if err != nil { return nil, fmt.Errorf("failed to translate LLM provider: %w", err) } - + if auth != nil { + inlinePolicies = append(inlinePolicies, &api.BackendPolicySpec{ + Kind: &api.BackendPolicySpec_Auth{ + Auth: auth, + }, + }) + } aiBackend.ProviderGroups = []*api.AIBackend_ProviderGroup{{ Providers: []*api.AIBackend_Provider{provider}, }} @@ -237,7 +244,7 @@ func translateAIBackends(ctx plugins.PolicyCtx, be *agentgateway.AgentgatewayBac providerGroup := &api.AIBackend_ProviderGroup{} for _, provider := range group.Providers { - tp, err := translateLLMProvider(&provider.LLMProvider, string(provider.Name)) + tp, auth, err := translateLLMProvider(ctx, &provider.LLMProvider, string(provider.Name), be.Namespace) if err != nil { return nil, fmt.Errorf("failed to translate LLM provider: %w", err) } @@ -247,6 +254,13 @@ func translateAIBackends(ctx plugins.PolicyCtx, be *agentgateway.AgentgatewayBac logger.Warn("failed to translate AI backend policies", "err", err) } tp.InlinePolicies = pol + if auth != nil { + tp.InlinePolicies = append(tp.InlinePolicies, &api.BackendPolicySpec{ + Kind: &api.BackendPolicySpec_Auth{ + Auth: auth, + }, + }) + } providerGroup.Providers = append(providerGroup.Providers, tp) } @@ -303,7 +317,7 @@ func translateAIBackendPolicies( }) } -func translateLLMProvider(llm *agentgateway.LLMProvider, providerName string) (*api.AIBackend_Provider, error) { +func translateLLMProvider(ctx plugins.PolicyCtx, llm *agentgateway.LLMProvider, providerName, namespace string) (*api.AIBackend_Provider, *api.BackendAuthPolicy, error) { provider := &api.AIBackend_Provider{ Name: providerName, } @@ -318,6 +332,7 @@ func translateLLMProvider(llm *agentgateway.LLMProvider, providerName string) (* if llm.Path != "" { provider.PathOverride = &llm.Path } + var auth *api.BackendAuthPolicy // Extract auth token and model based on provider if llm.OpenAI != nil { @@ -363,6 +378,12 @@ func translateLLMProvider(llm *agentgateway.LLMProvider, providerName string) (* guardrailVersion = &llm.Bedrock.Guardrail.GuardrailVersion } + var err error + auth, err = buildBedrockAuthPolicy(ctx.Krt, region, llm.Bedrock.Auth, ctx.Collections.Secrets, namespace) + if err != nil { + return nil, nil, err + } + provider.Provider = &api.AIBackend_Provider_Bedrock{ Bedrock: &api.AIBackend_Bedrock{ Model: llm.Bedrock.Model, @@ -372,10 +393,10 @@ func translateLLMProvider(llm *agentgateway.LLMProvider, providerName string) (* }, } } else { - return nil, fmt.Errorf("no supported LLM provider configured") + return nil, nil, fmt.Errorf("no supported LLM provider configured") } - return provider, nil + return provider, auth, nil } func toMCPProtocol(appProtocol string) api.MCPTarget_Protocol { @@ -391,3 +412,70 @@ func toMCPProtocol(appProtocol string) api.MCPTarget_Protocol { return api.MCPTarget_UNDEFINED } } + +func buildBedrockAuthPolicy(krtctx krt.HandlerContext, region string, auth *agentgateway.AwsAuth, secrets krt.Collection[*corev1.Secret], namespace string) (*api.BackendAuthPolicy, error) { + var errs []error + if auth == nil { + logger.Warn("using implicit AWS auth for AI backend") + return &api.BackendAuthPolicy{ + Kind: &api.BackendAuthPolicy_Aws{ + Aws: &api.Aws{ + Kind: &api.Aws_Implicit{ + Implicit: &api.AwsImplicit{}, + }, + }, + }, + }, nil + } + + if auth.SecretRef == nil { + logger.Warn("not using any auth for AWS - it's most likely not what you want") + return nil, nil + } + + // Get secret using the SecretIndex + secret, err := kubeutils.GetSecret(secrets, krtctx, auth.SecretRef.Name, namespace) + if err != nil { + // Return nil auth policy if secret not found - this will be handled upstream + // TODO(npolshak): Add backend status errors https://github.com/kgateway-dev/kgateway/issues/11966 + return nil, err + } + + var accessKeyId, secretAccessKey string + var sessionToken *string + + // Extract access key + if value, exists := kubeutils.GetSecretValue(secret, wellknown.AccessKey); !exists { + errs = append(errs, errors.New("accessKey is missing or not a valid string")) + } else { + accessKeyId = value + } + + // Extract secret key + if value, exists := kubeutils.GetSecretValue(secret, wellknown.SecretKey); !exists { + errs = append(errs, errors.New("secretKey is missing or not a valid string")) + } else { + secretAccessKey = value + } + + // Extract session token (optional) + if value, exists := kubeutils.GetSecretValue(secret, wellknown.SessionToken); exists { + sessionToken = ptr.Of(value) + } + + return &api.BackendAuthPolicy{ + Kind: &api.BackendAuthPolicy_Aws{ + Aws: &api.Aws{ + Kind: &api.Aws_ExplicitConfig{ + ExplicitConfig: &api.AwsExplicitConfig{ + AccessKeyId: accessKeyId, + SecretAccessKey: secretAccessKey, + SessionToken: sessionToken, + Region: region, + }, + }, + }, + }, + }, errors.Join(errs...) + +} diff --git a/pkg/kgateway/agentgatewaysyncer/backend/translate_test.go b/pkg/kgateway/agentgatewaysyncer/backend/translate_test.go index 1de7cc25ac8..5d57cc250f1 100644 --- a/pkg/kgateway/agentgatewaysyncer/backend/translate_test.go +++ b/pkg/kgateway/agentgatewaysyncer/backend/translate_test.go @@ -491,6 +491,36 @@ func TestBuildAIBackend(t *testing.T) { }, }, }, + { + name: "Bedrock backend with new secret ref", + backend: &agentgateway.AgentgatewayBackend{ + ObjectMeta: metav1.ObjectMeta{ + Name: "bedrock-with-secret-ref", + Namespace: "test-ns", + }, + Spec: agentgateway.AgentgatewayBackendSpec{ + AI: &agentgateway.AIBackend{ + LLM: &agentgateway.LLMProvider{ + Bedrock: &agentgateway.BedrockConfig{ + Region: "us-east-1", + Auth: &agentgateway.AwsAuth{ + SecretRef: &corev1.LocalObjectReference{ + Name: "bedrock-secret", + }, + }, + }, + }, + }, + }, + }, + inputs: []any{ + createMockSecret("test-ns", "bedrock-secret", map[string]string{ + "accessKey": "secret-accessKey", + "secretKey": "secret-secretKey", + "sessionToken": "secret-sessionToken", + }), + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { From 804d8c2f8480df3740623eb6d3a10c58ad698d45 Mon Sep 17 00:00:00 2001 From: Yuval Kohavi Date: Wed, 10 Dec 2025 17:29:56 -0500 Subject: [PATCH 02/12] more yaml tests Signed-off-by: Yuval Kohavi --- .../testdata/outputs/backend/bedrock-backend.yaml | 4 ++++ .../testdata/outputs/backend/multipool-priority-levels.yaml | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/pkg/kgateway/agentgatewaysyncer/testdata/outputs/backend/bedrock-backend.yaml b/pkg/kgateway/agentgatewaysyncer/testdata/outputs/backend/bedrock-backend.yaml index c29eee02f6b..78f90aa01ba 100644 --- a/pkg/kgateway/agentgatewaysyncer/testdata/outputs/backend/bedrock-backend.yaml +++ b/pkg/kgateway/agentgatewaysyncer/testdata/outputs/backend/bedrock-backend.yaml @@ -8,6 +8,10 @@ Backends: model: anthropic.claude-3-5-haiku-20241022-v1:0 region: us-west-2 name: backend + inlinePolicies: + - auth: + aws: + implicit: {} key: default/bedrock name: name: bedrock diff --git a/pkg/kgateway/agentgatewaysyncer/testdata/outputs/backend/multipool-priority-levels.yaml b/pkg/kgateway/agentgatewaysyncer/testdata/outputs/backend/multipool-priority-levels.yaml index 67820d9d3d3..93975064c88 100644 --- a/pkg/kgateway/agentgatewaysyncer/testdata/outputs/backend/multipool-priority-levels.yaml +++ b/pkg/kgateway/agentgatewaysyncer/testdata/outputs/backend/multipool-priority-levels.yaml @@ -42,6 +42,10 @@ Backends: - bedrock: model: anthropic.claude-3-haiku-20240307-v1:0 region: us-east-1 + inlinePolicies: + - auth: + aws: + implicit: {} name: bedrock key: default/multipool-priority name: From 8e61c84bacad54f8e36b67cf73d5b20741ef96f0 Mon Sep 17 00:00:00 2001 From: Yuval Kohavi Date: Wed, 10 Dec 2025 17:40:31 -0500 Subject: [PATCH 03/12] PR comments Signed-off-by: Yuval Kohavi --- api/v1alpha1/agentgateway/agentgateway_backend_types.go | 2 +- api/v1alpha1/agentgateway/zz_generated.deepcopy.go | 8 ++------ pkg/kgateway/agentgatewaysyncer/backend/translate.go | 3 +-- pkg/kgateway/agentgatewaysyncer/backend/translate_test.go | 2 +- 4 files changed, 5 insertions(+), 10 deletions(-) diff --git a/api/v1alpha1/agentgateway/agentgateway_backend_types.go b/api/v1alpha1/agentgateway/agentgateway_backend_types.go index 15a4373d60a..9ba3f280806 100644 --- a/api/v1alpha1/agentgateway/agentgateway_backend_types.go +++ b/api/v1alpha1/agentgateway/agentgateway_backend_types.go @@ -302,7 +302,7 @@ type AwsAuth struct { // SecretRef references a Kubernetes Secret containing the AWS credentials. // The Secret must have keys "accessKey", "secretKey", and optionally "sessionToken". // +required - SecretRef *corev1.LocalObjectReference `json:"secretRef,omitempty"` + SecretRef corev1.LocalObjectReference `json:"secretRef"` } type AWSGuardrailConfig struct { diff --git a/api/v1alpha1/agentgateway/zz_generated.deepcopy.go b/api/v1alpha1/agentgateway/zz_generated.deepcopy.go index 849971b94b0..f24e6ea3872 100644 --- a/api/v1alpha1/agentgateway/zz_generated.deepcopy.go +++ b/api/v1alpha1/agentgateway/zz_generated.deepcopy.go @@ -633,11 +633,7 @@ func (in *AttributeAdd) DeepCopy() *AttributeAdd { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AwsAuth) DeepCopyInto(out *AwsAuth) { *out = *in - if in.SecretRef != nil { - in, out := &in.SecretRef, &out.SecretRef - *out = new(corev1.LocalObjectReference) - **out = **in - } + out.SecretRef = in.SecretRef } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AwsAuth. @@ -1046,7 +1042,7 @@ func (in *BedrockConfig) DeepCopyInto(out *BedrockConfig) { if in.Auth != nil { in, out := &in.Auth, &out.Auth *out = new(AwsAuth) - (*in).DeepCopyInto(*out) + **out = **in } } diff --git a/pkg/kgateway/agentgatewaysyncer/backend/translate.go b/pkg/kgateway/agentgatewaysyncer/backend/translate.go index 0155631e92f..5db3684df45 100644 --- a/pkg/kgateway/agentgatewaysyncer/backend/translate.go +++ b/pkg/kgateway/agentgatewaysyncer/backend/translate.go @@ -428,7 +428,7 @@ func buildBedrockAuthPolicy(krtctx krt.HandlerContext, region string, auth *agen }, nil } - if auth.SecretRef == nil { + if auth.SecretRef.Name == "" { logger.Warn("not using any auth for AWS - it's most likely not what you want") return nil, nil } @@ -477,5 +477,4 @@ func buildBedrockAuthPolicy(krtctx krt.HandlerContext, region string, auth *agen }, }, }, errors.Join(errs...) - } diff --git a/pkg/kgateway/agentgatewaysyncer/backend/translate_test.go b/pkg/kgateway/agentgatewaysyncer/backend/translate_test.go index 5d57cc250f1..cb5b7531d9a 100644 --- a/pkg/kgateway/agentgatewaysyncer/backend/translate_test.go +++ b/pkg/kgateway/agentgatewaysyncer/backend/translate_test.go @@ -504,7 +504,7 @@ func TestBuildAIBackend(t *testing.T) { Bedrock: &agentgateway.BedrockConfig{ Region: "us-east-1", Auth: &agentgateway.AwsAuth{ - SecretRef: &corev1.LocalObjectReference{ + SecretRef: corev1.LocalObjectReference{ Name: "bedrock-secret", }, }, From 7af67c20a1f9dc6a9c2052c3ae503f3c1d8faf5f Mon Sep 17 00:00:00 2001 From: Yuval Kohavi Date: Wed, 10 Dec 2025 19:01:35 -0500 Subject: [PATCH 04/12] move auth to the provider Signed-off-by: Yuval Kohavi --- ...(responses_and_anthropic_token_count).yaml | 7 ++-- .../Bedrock_backend_with_new_secret_ref.yaml | 16 ++++----- ...kend_with_custom_region_and_guardrail.yaml | 8 ++--- .../agentgatewaysyncer/backend/translate.go | 35 +++++++------------ .../outputs/backend/bedrock-backend.yaml | 8 ++--- .../backend/multipool-priority-levels.yaml | 4 --- 6 files changed, 32 insertions(+), 46 deletions(-) diff --git a/pkg/kgateway/agentgatewaysyncer/backend/testdata/Bedrock_backend_with_new_route_types_(responses_and_anthropic_token_count).yaml b/pkg/kgateway/agentgatewaysyncer/backend/testdata/Bedrock_backend_with_new_route_types_(responses_and_anthropic_token_count).yaml index cc9464823cd..450c8d2a340 100644 --- a/pkg/kgateway/agentgatewaysyncer/backend/testdata/Bedrock_backend_with_new_route_types_(responses_and_anthropic_token_count).yaml +++ b/pkg/kgateway/agentgatewaysyncer/backend/testdata/Bedrock_backend_with_new_route_types_(responses_and_anthropic_token_count).yaml @@ -3,6 +3,10 @@ ai: - providers: - bedrock: region: us-east-1 + inlinePolicies: + - auth: + aws: + implicit: {} name: backend inlinePolicies: - ai: @@ -12,9 +16,6 @@ inlinePolicies: /v1/messages/count_tokens: ANTHROPIC_TOKEN_COUNT /v1/models: MODELS /v1/responses: RESPONSES -- auth: - aws: - implicit: {} key: test-ns/bedrock-with-new-routes name: name: bedrock-with-new-routes diff --git a/pkg/kgateway/agentgatewaysyncer/backend/testdata/Bedrock_backend_with_new_secret_ref.yaml b/pkg/kgateway/agentgatewaysyncer/backend/testdata/Bedrock_backend_with_new_secret_ref.yaml index 978e2ed665a..2efcef0b5bf 100644 --- a/pkg/kgateway/agentgatewaysyncer/backend/testdata/Bedrock_backend_with_new_secret_ref.yaml +++ b/pkg/kgateway/agentgatewaysyncer/backend/testdata/Bedrock_backend_with_new_secret_ref.yaml @@ -3,15 +3,15 @@ ai: - providers: - bedrock: region: us-east-1 + inlinePolicies: + - auth: + aws: + explicitConfig: + accessKeyId: secret-accessKey + region: us-east-1 + secretAccessKey: secret-secretKey + sessionToken: secret-sessionToken name: backend -inlinePolicies: -- auth: - aws: - explicitConfig: - accessKeyId: secret-accessKey - region: us-east-1 - secretAccessKey: secret-secretKey - sessionToken: secret-sessionToken key: test-ns/bedrock-with-secret-ref name: name: bedrock-with-secret-ref diff --git a/pkg/kgateway/agentgatewaysyncer/backend/testdata/Valid_Bedrock_backend_with_custom_region_and_guardrail.yaml b/pkg/kgateway/agentgatewaysyncer/backend/testdata/Valid_Bedrock_backend_with_custom_region_and_guardrail.yaml index 9d1c371aaf9..de1f27f572c 100644 --- a/pkg/kgateway/agentgatewaysyncer/backend/testdata/Valid_Bedrock_backend_with_custom_region_and_guardrail.yaml +++ b/pkg/kgateway/agentgatewaysyncer/backend/testdata/Valid_Bedrock_backend_with_custom_region_and_guardrail.yaml @@ -6,11 +6,11 @@ ai: guardrailVersion: "1.0" model: anthropic.claude-3-haiku-20240307-v1:0 region: eu-west-1 + inlinePolicies: + - auth: + aws: + implicit: {} name: backend -inlinePolicies: -- auth: - aws: - implicit: {} key: test-ns/bedrock-backend-custom name: name: bedrock-backend-custom diff --git a/pkg/kgateway/agentgatewaysyncer/backend/translate.go b/pkg/kgateway/agentgatewaysyncer/backend/translate.go index 5db3684df45..a55e0b306a1 100644 --- a/pkg/kgateway/agentgatewaysyncer/backend/translate.go +++ b/pkg/kgateway/agentgatewaysyncer/backend/translate.go @@ -225,17 +225,10 @@ func translateAIBackends(ctx plugins.PolicyCtx, be *agentgateway.AgentgatewayBac aiBackend := &api.AIBackend{} if llm := ai.LLM; llm != nil { - provider, auth, err := translateLLMProvider(ctx, llm, utils.SingularLLMProviderSubBackendName, be.Namespace) + provider, err := translateLLMProvider(ctx, llm, utils.SingularLLMProviderSubBackendName, be.Namespace) if err != nil { return nil, fmt.Errorf("failed to translate LLM provider: %w", err) } - if auth != nil { - inlinePolicies = append(inlinePolicies, &api.BackendPolicySpec{ - Kind: &api.BackendPolicySpec_Auth{ - Auth: auth, - }, - }) - } aiBackend.ProviderGroups = []*api.AIBackend_ProviderGroup{{ Providers: []*api.AIBackend_Provider{provider}, }} @@ -244,7 +237,7 @@ func translateAIBackends(ctx plugins.PolicyCtx, be *agentgateway.AgentgatewayBac providerGroup := &api.AIBackend_ProviderGroup{} for _, provider := range group.Providers { - tp, auth, err := translateLLMProvider(ctx, &provider.LLMProvider, string(provider.Name), be.Namespace) + tp, err := translateLLMProvider(ctx, &provider.LLMProvider, string(provider.Name), be.Namespace) if err != nil { return nil, fmt.Errorf("failed to translate LLM provider: %w", err) } @@ -254,13 +247,6 @@ func translateAIBackends(ctx plugins.PolicyCtx, be *agentgateway.AgentgatewayBac logger.Warn("failed to translate AI backend policies", "err", err) } tp.InlinePolicies = pol - if auth != nil { - tp.InlinePolicies = append(tp.InlinePolicies, &api.BackendPolicySpec{ - Kind: &api.BackendPolicySpec_Auth{ - Auth: auth, - }, - }) - } providerGroup.Providers = append(providerGroup.Providers, tp) } @@ -317,7 +303,7 @@ func translateAIBackendPolicies( }) } -func translateLLMProvider(ctx plugins.PolicyCtx, llm *agentgateway.LLMProvider, providerName, namespace string) (*api.AIBackend_Provider, *api.BackendAuthPolicy, error) { +func translateLLMProvider(ctx plugins.PolicyCtx, llm *agentgateway.LLMProvider, providerName, namespace string) (*api.AIBackend_Provider, error) { provider := &api.AIBackend_Provider{ Name: providerName, } @@ -332,7 +318,6 @@ func translateLLMProvider(ctx plugins.PolicyCtx, llm *agentgateway.LLMProvider, if llm.Path != "" { provider.PathOverride = &llm.Path } - var auth *api.BackendAuthPolicy // Extract auth token and model based on provider if llm.OpenAI != nil { @@ -378,10 +363,9 @@ func translateLLMProvider(ctx plugins.PolicyCtx, llm *agentgateway.LLMProvider, guardrailVersion = &llm.Bedrock.Guardrail.GuardrailVersion } - var err error - auth, err = buildBedrockAuthPolicy(ctx.Krt, region, llm.Bedrock.Auth, ctx.Collections.Secrets, namespace) + auth, err := buildBedrockAuthPolicy(ctx.Krt, region, llm.Bedrock.Auth, ctx.Collections.Secrets, namespace) if err != nil { - return nil, nil, err + return nil, err } provider.Provider = &api.AIBackend_Provider_Bedrock{ @@ -392,11 +376,16 @@ func translateLLMProvider(ctx plugins.PolicyCtx, llm *agentgateway.LLMProvider, GuardrailVersion: guardrailVersion, }, } + provider.InlinePolicies = append(provider.InlinePolicies, &api.BackendPolicySpec{ + Kind: &api.BackendPolicySpec_Auth{ + Auth: auth, + }, + }) } else { - return nil, nil, fmt.Errorf("no supported LLM provider configured") + return nil, fmt.Errorf("no supported LLM provider configured") } - return provider, auth, nil + return provider, nil } func toMCPProtocol(appProtocol string) api.MCPTarget_Protocol { diff --git a/pkg/kgateway/agentgatewaysyncer/testdata/outputs/backend/bedrock-backend.yaml b/pkg/kgateway/agentgatewaysyncer/testdata/outputs/backend/bedrock-backend.yaml index 78f90aa01ba..7fccfa80b69 100644 --- a/pkg/kgateway/agentgatewaysyncer/testdata/outputs/backend/bedrock-backend.yaml +++ b/pkg/kgateway/agentgatewaysyncer/testdata/outputs/backend/bedrock-backend.yaml @@ -7,11 +7,11 @@ Backends: guardrailVersion: guardrail-policy-version model: anthropic.claude-3-5-haiku-20241022-v1:0 region: us-west-2 + inlinePolicies: + - auth: + aws: + implicit: {} name: backend - inlinePolicies: - - auth: - aws: - implicit: {} key: default/bedrock name: name: bedrock diff --git a/pkg/kgateway/agentgatewaysyncer/testdata/outputs/backend/multipool-priority-levels.yaml b/pkg/kgateway/agentgatewaysyncer/testdata/outputs/backend/multipool-priority-levels.yaml index 93975064c88..67820d9d3d3 100644 --- a/pkg/kgateway/agentgatewaysyncer/testdata/outputs/backend/multipool-priority-levels.yaml +++ b/pkg/kgateway/agentgatewaysyncer/testdata/outputs/backend/multipool-priority-levels.yaml @@ -42,10 +42,6 @@ Backends: - bedrock: model: anthropic.claude-3-haiku-20240307-v1:0 region: us-east-1 - inlinePolicies: - - auth: - aws: - implicit: {} name: bedrock key: default/multipool-priority name: From bcab27cb640d85ad163ef8557108245552d77647 Mon Sep 17 00:00:00 2001 From: Yuval Kohavi Date: Thu, 11 Dec 2025 08:02:26 -0500 Subject: [PATCH 05/12] move aws to policy. there's no region in the policy, so this depends on https://github.com/agentgateway/agentgateway/pull/718 Signed-off-by: Yuval Kohavi --- .../agentgateway_backend_types.go | 15 -- .../agentgateway/agentgateway_policy_types.go | 18 +- .../agentgateway/zz_generated.deepcopy.go | 10 +- ...agentgateway.dev_agentgatewaybackends.yaml | 194 ++++++++++++------ ...agentgateway.dev_agentgatewaypolicies.yaml | 60 +++++- pkg/agentgateway/plugins/backend_policies.go | 70 +++++++ .../testdata/backendpolicy/awsauth.yaml | 65 ++++++ ...(responses_and_anthropic_token_count).yaml | 4 - .../Bedrock_backend_with_new_secret_ref.yaml | 18 -- ...kend_with_custom_region_and_guardrail.yaml | 4 - .../agentgatewaysyncer/backend/translate.go | 77 ------- .../backend/translate_test.go | 30 --- .../outputs/backend/bedrock-backend.yaml | 4 - 13 files changed, 343 insertions(+), 226 deletions(-) create mode 100644 pkg/agentgateway/plugins/testdata/backendpolicy/awsauth.yaml delete mode 100644 pkg/kgateway/agentgatewaysyncer/backend/testdata/Bedrock_backend_with_new_secret_ref.yaml diff --git a/api/v1alpha1/agentgateway/agentgateway_backend_types.go b/api/v1alpha1/agentgateway/agentgateway_backend_types.go index 9ba3f280806..d41c311a42e 100644 --- a/api/v1alpha1/agentgateway/agentgateway_backend_types.go +++ b/api/v1alpha1/agentgateway/agentgateway_backend_types.go @@ -1,7 +1,6 @@ package agentgateway import ( - corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" gwv1 "sigs.k8s.io/gateway-api/apis/v1" ) @@ -289,20 +288,6 @@ type BedrockConfig struct { // If not specified, the AWS Guardrail policy will not be used. // +optional Guardrail *AWSGuardrailConfig `json:"guardrail,omitempty"` - - // Auth specifies an explicit AWS authentication method for the backend. - // When omitted, we will try to use the default AWS SDK authentication methods. - // - // +optional - Auth *AwsAuth `json:"auth,omitempty"` -} - -// AwsAuth specifies the authentication method to use for the backend. -type AwsAuth struct { - // SecretRef references a Kubernetes Secret containing the AWS credentials. - // The Secret must have keys "accessKey", "secretKey", and optionally "sessionToken". - // +required - SecretRef corev1.LocalObjectReference `json:"secretRef"` } type AWSGuardrailConfig struct { diff --git a/api/v1alpha1/agentgateway/agentgateway_policy_types.go b/api/v1alpha1/agentgateway/agentgateway_policy_types.go index 478bc16cb12..99bbe9a2ba2 100644 --- a/api/v1alpha1/agentgateway/agentgateway_policy_types.go +++ b/api/v1alpha1/agentgateway/agentgateway_policy_types.go @@ -707,7 +707,7 @@ const ( HostnameRewriteModeNone HostnameRewriteMode = "None" ) -// +kubebuilder:validation:ExactlyOneOf=key;secretRef;passthrough +// +kubebuilder:validation:ExactlyOneOf=key;secretRef;passthrough;aws type BackendAuth struct { // key provides an inline key to use as the value of the Authorization header. // This option is the least secure; usage of a Secret is preferred. @@ -726,7 +726,21 @@ type BackendAuth struct { // request, the original token would be unchanged, so this would have no effect. // +optional Passthrough *BackendAuthPassthrough `json:"passthrough,omitempty"` - // TODO: aws, azure, gcp + // TODO: azure, gcp + + // Auth specifies an explicit AWS authentication method for the backend. + // When omitted, we will try to use the default AWS SDK authentication methods. + // + // +optional + AWS *AwsAuth `json:"aws,omitempty"` +} + +// AwsAuth specifies the authentication method to use for the backend. +type AwsAuth struct { + // SecretRef references a Kubernetes Secret containing the AWS credentials. + // The Secret must have keys "accessKey", "secretKey", and optionally "sessionToken". + // +required + SecretRef corev1.LocalObjectReference `json:"secretRef"` } type BackendAuthPassthrough struct { diff --git a/api/v1alpha1/agentgateway/zz_generated.deepcopy.go b/api/v1alpha1/agentgateway/zz_generated.deepcopy.go index f24e6ea3872..45c59be8ea0 100644 --- a/api/v1alpha1/agentgateway/zz_generated.deepcopy.go +++ b/api/v1alpha1/agentgateway/zz_generated.deepcopy.go @@ -747,6 +747,11 @@ func (in *BackendAuth) DeepCopyInto(out *BackendAuth) { *out = new(BackendAuthPassthrough) **out = **in } + if in.AWS != nil { + in, out := &in.AWS, &out.AWS + *out = new(AwsAuth) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendAuth. @@ -1039,11 +1044,6 @@ func (in *BedrockConfig) DeepCopyInto(out *BedrockConfig) { *out = new(AWSGuardrailConfig) (*in).DeepCopyInto(*out) } - if in.Auth != nil { - in, out := &in.Auth, &out.Auth - *out = new(AwsAuth) - **out = **in - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BedrockConfig. diff --git a/install/helm/kgateway-crds/templates/agentgateway.dev_agentgatewaybackends.yaml b/install/helm/kgateway-crds/templates/agentgateway.dev_agentgatewaybackends.yaml index a77d93c7529..c28f5dcc81f 100644 --- a/install/helm/kgateway-crds/templates/agentgateway.dev_agentgatewaybackends.yaml +++ b/install/helm/kgateway-crds/templates/agentgateway.dev_agentgatewaybackends.yaml @@ -137,30 +137,6 @@ spec: bedrock: description: Bedrock provider properties: - auth: - description: |- - Auth specifies an explicit AWS authentication method for the backend. - When omitted, we will try to use the default AWS SDK authentication methods. - properties: - secretRef: - description: |- - SecretRef references a Kubernetes Secret containing the AWS credentials. - The Secret must have keys "accessKey", "secretKey", and optionally "sessionToken". - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - required: - - secretRef - type: object guardrail: description: |- Guardrail configures the Guardrail policy to use for the backend. See @@ -501,6 +477,30 @@ spec: authentication to the backend properties: + aws: + description: |- + Auth specifies an explicit AWS authentication method for the backend. + When omitted, we will try to use the default AWS SDK authentication methods. + properties: + secretRef: + description: |- + SecretRef references a Kubernetes Secret containing the AWS credentials. + The Secret must have keys "accessKey", "secretKey", and optionally "sessionToken". + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + required: + - secretRef + type: object key: description: |- key provides an inline key to use as the value of the Authorization header. @@ -534,9 +534,9 @@ spec: x-kubernetes-validations: - message: exactly one of the fields in [key secretRef - passthrough] must be - set - rule: '[has(self.key),has(self.secretRef),has(self.passthrough)].filter(x,x==true).size() + passthrough aws] must + be set + rule: '[has(self.key),has(self.secretRef),has(self.passthrough),has(self.aws)].filter(x,x==true).size() == 1' http: description: http defines @@ -1237,6 +1237,30 @@ spec: description: auth defines settings for managing authentication to the backend properties: + aws: + description: |- + Auth specifies an explicit AWS authentication method for the backend. + When omitted, we will try to use the default AWS SDK authentication methods. + properties: + secretRef: + description: |- + SecretRef references a Kubernetes Secret containing the AWS credentials. + The Secret must have keys "accessKey", "secretKey", and optionally "sessionToken". + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + required: + - secretRef + type: object key: description: |- key provides an inline key to use as the value of the Authorization header. @@ -1269,8 +1293,8 @@ spec: type: object x-kubernetes-validations: - message: exactly one of the fields in [key secretRef - passthrough] must be set - rule: '[has(self.key),has(self.secretRef),has(self.passthrough)].filter(x,x==true).size() + passthrough aws] must be set + rule: '[has(self.key),has(self.secretRef),has(self.passthrough),has(self.aws)].filter(x,x==true).size() == 1' http: description: http defines settings for managing @@ -1569,30 +1593,6 @@ spec: bedrock: description: Bedrock provider properties: - auth: - description: |- - Auth specifies an explicit AWS authentication method for the backend. - When omitted, we will try to use the default AWS SDK authentication methods. - properties: - secretRef: - description: |- - SecretRef references a Kubernetes Secret containing the AWS credentials. - The Secret must have keys "accessKey", "secretKey", and optionally "sessionToken". - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - required: - - secretRef - type: object guardrail: description: |- Guardrail configures the Guardrail policy to use for the backend. See @@ -1877,6 +1877,30 @@ spec: description: auth defines settings for managing authentication to the backend properties: + aws: + description: |- + Auth specifies an explicit AWS authentication method for the backend. + When omitted, we will try to use the default AWS SDK authentication methods. + properties: + secretRef: + description: |- + SecretRef references a Kubernetes Secret containing the AWS credentials. + The Secret must have keys "accessKey", "secretKey", and optionally "sessionToken". + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + required: + - secretRef + type: object key: description: |- key provides an inline key to use as the value of the Authorization header. @@ -1909,8 +1933,8 @@ spec: type: object x-kubernetes-validations: - message: exactly one of the fields in [key secretRef - passthrough] must be set - rule: '[has(self.key),has(self.secretRef),has(self.passthrough)].filter(x,x==true).size() + passthrough aws] must be set + rule: '[has(self.key),has(self.secretRef),has(self.passthrough),has(self.aws)].filter(x,x==true).size() == 1' http: description: http defines settings for managing @@ -2576,6 +2600,30 @@ spec: description: auth defines settings for managing authentication to the backend properties: + aws: + description: |- + Auth specifies an explicit AWS authentication method for the backend. + When omitted, we will try to use the default AWS SDK authentication methods. + properties: + secretRef: + description: |- + SecretRef references a Kubernetes Secret containing the AWS credentials. + The Secret must have keys "accessKey", "secretKey", and optionally "sessionToken". + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + required: + - secretRef + type: object key: description: |- key provides an inline key to use as the value of the Authorization header. @@ -2608,9 +2656,9 @@ spec: type: object x-kubernetes-validations: - message: exactly one of the fields in - [key secretRef passthrough] must be - set - rule: '[has(self.key),has(self.secretRef),has(self.passthrough)].filter(x,x==true).size() + [key secretRef passthrough aws] must + be set + rule: '[has(self.key),has(self.secretRef),has(self.passthrough),has(self.aws)].filter(x,x==true).size() == 1' http: description: http defines settings for managing @@ -3269,6 +3317,30 @@ spec: description: auth defines settings for managing authentication to the backend properties: + aws: + description: |- + Auth specifies an explicit AWS authentication method for the backend. + When omitted, we will try to use the default AWS SDK authentication methods. + properties: + secretRef: + description: |- + SecretRef references a Kubernetes Secret containing the AWS credentials. + The Secret must have keys "accessKey", "secretKey", and optionally "sessionToken". + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + required: + - secretRef + type: object key: description: |- key provides an inline key to use as the value of the Authorization header. @@ -3300,9 +3372,9 @@ spec: x-kubernetes-map-type: atomic type: object x-kubernetes-validations: - - message: exactly one of the fields in [key secretRef passthrough] - must be set - rule: '[has(self.key),has(self.secretRef),has(self.passthrough)].filter(x,x==true).size() + - message: exactly one of the fields in [key secretRef passthrough + aws] must be set + rule: '[has(self.key),has(self.secretRef),has(self.passthrough),has(self.aws)].filter(x,x==true).size() == 1' http: description: http defines settings for managing HTTP requests diff --git a/install/helm/kgateway-crds/templates/agentgateway.dev_agentgatewaypolicies.yaml b/install/helm/kgateway-crds/templates/agentgateway.dev_agentgatewaypolicies.yaml index 986372210b1..ed25f8935d8 100644 --- a/install/helm/kgateway-crds/templates/agentgateway.dev_agentgatewaypolicies.yaml +++ b/install/helm/kgateway-crds/templates/agentgateway.dev_agentgatewaypolicies.yaml @@ -315,6 +315,30 @@ spec: description: auth defines settings for managing authentication to the backend properties: + aws: + description: |- + Auth specifies an explicit AWS authentication method for the backend. + When omitted, we will try to use the default AWS SDK authentication methods. + properties: + secretRef: + description: |- + SecretRef references a Kubernetes Secret containing the AWS credentials. + The Secret must have keys "accessKey", "secretKey", and optionally "sessionToken". + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + required: + - secretRef + type: object key: description: |- key provides an inline key to use as the value of the Authorization header. @@ -347,9 +371,9 @@ spec: type: object x-kubernetes-validations: - message: exactly one of the fields in - [key secretRef passthrough] must be - set - rule: '[has(self.key),has(self.secretRef),has(self.passthrough)].filter(x,x==true).size() + [key secretRef passthrough aws] must + be set + rule: '[has(self.key),has(self.secretRef),has(self.passthrough),has(self.aws)].filter(x,x==true).size() == 1' http: description: http defines settings for managing @@ -1008,6 +1032,30 @@ spec: description: auth defines settings for managing authentication to the backend properties: + aws: + description: |- + Auth specifies an explicit AWS authentication method for the backend. + When omitted, we will try to use the default AWS SDK authentication methods. + properties: + secretRef: + description: |- + SecretRef references a Kubernetes Secret containing the AWS credentials. + The Secret must have keys "accessKey", "secretKey", and optionally "sessionToken". + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + required: + - secretRef + type: object key: description: |- key provides an inline key to use as the value of the Authorization header. @@ -1039,9 +1087,9 @@ spec: x-kubernetes-map-type: atomic type: object x-kubernetes-validations: - - message: exactly one of the fields in [key secretRef passthrough] - must be set - rule: '[has(self.key),has(self.secretRef),has(self.passthrough)].filter(x,x==true).size() + - message: exactly one of the fields in [key secretRef passthrough + aws] must be set + rule: '[has(self.key),has(self.secretRef),has(self.passthrough),has(self.aws)].filter(x,x==true).size() == 1' http: description: http defines settings for managing HTTP requests diff --git a/pkg/agentgateway/plugins/backend_policies.go b/pkg/agentgateway/plugins/backend_policies.go index bfe55be102c..1da56902404 100644 --- a/pkg/agentgateway/plugins/backend_policies.go +++ b/pkg/agentgateway/plugins/backend_policies.go @@ -482,6 +482,10 @@ func translateBackendAuth(ctx PolicyCtx, policy *agentgateway.AgentgatewayPolicy errs = append(errs, fmt.Errorf("secret %s/%s missing Authorization value", policy.Namespace, auth.SecretRef.Name)) } } + } else if auth.AWS != nil { + awsAuth, err := buildAwsAuthPolicy(ctx.Krt, auth.AWS, ctx.Collections.Secrets, policy.Namespace) + translatedAuth = awsAuth + errs = append(errs, err) } else { errs = append(errs, fmt.Errorf("backend auth requires either inline key or secretRef")) } @@ -529,3 +533,69 @@ func translateRouteType(rt agentgateway.RouteType) api.BackendPolicySpec_Ai_Rout return api.BackendPolicySpec_Ai_COMPLETIONS } } + +func buildAwsAuthPolicy(krtctx krt.HandlerContext, auth *agentgateway.AwsAuth, secrets krt.Collection[*corev1.Secret], namespace string) (*api.BackendAuthPolicy, error) { + var errs []error + if auth == nil { + logger.Warn("using implicit AWS auth for AI backend") + return &api.BackendAuthPolicy{ + Kind: &api.BackendAuthPolicy_Aws{ + Aws: &api.Aws{ + Kind: &api.Aws_Implicit{ + Implicit: &api.AwsImplicit{}, + }, + }, + }, + }, nil + } + + if auth.SecretRef.Name == "" { + logger.Warn("not using any auth for AWS - it's most likely not what you want") + return nil, nil + } + + // Get secret using the SecretIndex + secret, err := kubeutils.GetSecret(secrets, krtctx, auth.SecretRef.Name, namespace) + if err != nil { + // Return nil auth policy if secret not found - this will be handled upstream + // TODO(npolshak): Add backend status errors https://github.com/kgateway-dev/kgateway/issues/11966 + return nil, err + } + + var accessKeyId, secretAccessKey string + var sessionToken *string + + // Extract access key + if value, exists := kubeutils.GetSecretValue(secret, wellknown.AccessKey); !exists { + errs = append(errs, errors.New("accessKey is missing or not a valid string")) + } else { + accessKeyId = value + } + + // Extract secret key + if value, exists := kubeutils.GetSecretValue(secret, wellknown.SecretKey); !exists { + errs = append(errs, errors.New("secretKey is missing or not a valid string")) + } else { + secretAccessKey = value + } + + // Extract session token (optional) + if value, exists := kubeutils.GetSecretValue(secret, wellknown.SessionToken); exists { + sessionToken = ptr.Of(value) + } + + return &api.BackendAuthPolicy{ + Kind: &api.BackendAuthPolicy_Aws{ + Aws: &api.Aws{ + Kind: &api.Aws_ExplicitConfig{ + ExplicitConfig: &api.AwsExplicitConfig{ + AccessKeyId: accessKeyId, + SecretAccessKey: secretAccessKey, + SessionToken: sessionToken, + Region: "", + }, + }, + }, + }, + }, errors.Join(errs...) +} diff --git a/pkg/agentgateway/plugins/testdata/backendpolicy/awsauth.yaml b/pkg/agentgateway/plugins/testdata/backendpolicy/awsauth.yaml new file mode 100644 index 00000000000..e7e8e43b5e3 --- /dev/null +++ b/pkg/agentgateway/plugins/testdata/backendpolicy/awsauth.yaml @@ -0,0 +1,65 @@ +apiVersion: agentgateway.dev/v1alpha1 +kind: AgentgatewayPolicy +metadata: + name: agw + namespace: default +spec: + targetRefs: + - kind: HTTPRoute + name: test + group: gateway.networking.k8s.io + backend: + auth: + aws: + secretRef: + name: aws-auth-secret +--- +apiVersion: v1 +kind: Secret +metadata: + name: aws-auth-secret + namespace: default +type: Opaque +data: + accessKey: c2VjcmV0LWFjY2Vzc0tleQ== + secretKey: c2VjcmV0LXNlY3JldEtleQ== + sessionToken: c2VjcmV0LXNlc3Npb25Ub2tlbg== +--- +# Output +output: +- Policy: + backend: + auth: + aws: + explicitConfig: + accessKeyId: secret-accessKey + secretAccessKey: secret-secretKey + sessionToken: secret-sessionToken + key: backend/default/agw:backend-auth:default/test + name: + kind: AgentgatewayPolicy + name: agw + namespace: default + target: + route: + name: test + namespace: default +status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: test + namespace: default + conditions: + - lastTransitionTime: fake + message: Policy accepted + reason: Valid + status: "True" + type: Accepted + - lastTransitionTime: fake + message: Attached to all targets + reason: Attached + status: "True" + type: Attached + controllerName: kgateway.dev/agentgateway diff --git a/pkg/kgateway/agentgatewaysyncer/backend/testdata/Bedrock_backend_with_new_route_types_(responses_and_anthropic_token_count).yaml b/pkg/kgateway/agentgatewaysyncer/backend/testdata/Bedrock_backend_with_new_route_types_(responses_and_anthropic_token_count).yaml index 450c8d2a340..57cd9212c4f 100644 --- a/pkg/kgateway/agentgatewaysyncer/backend/testdata/Bedrock_backend_with_new_route_types_(responses_and_anthropic_token_count).yaml +++ b/pkg/kgateway/agentgatewaysyncer/backend/testdata/Bedrock_backend_with_new_route_types_(responses_and_anthropic_token_count).yaml @@ -3,10 +3,6 @@ ai: - providers: - bedrock: region: us-east-1 - inlinePolicies: - - auth: - aws: - implicit: {} name: backend inlinePolicies: - ai: diff --git a/pkg/kgateway/agentgatewaysyncer/backend/testdata/Bedrock_backend_with_new_secret_ref.yaml b/pkg/kgateway/agentgatewaysyncer/backend/testdata/Bedrock_backend_with_new_secret_ref.yaml deleted file mode 100644 index 2efcef0b5bf..00000000000 --- a/pkg/kgateway/agentgatewaysyncer/backend/testdata/Bedrock_backend_with_new_secret_ref.yaml +++ /dev/null @@ -1,18 +0,0 @@ -ai: - providerGroups: - - providers: - - bedrock: - region: us-east-1 - inlinePolicies: - - auth: - aws: - explicitConfig: - accessKeyId: secret-accessKey - region: us-east-1 - secretAccessKey: secret-secretKey - sessionToken: secret-sessionToken - name: backend -key: test-ns/bedrock-with-secret-ref -name: - name: bedrock-with-secret-ref - namespace: test-ns diff --git a/pkg/kgateway/agentgatewaysyncer/backend/testdata/Valid_Bedrock_backend_with_custom_region_and_guardrail.yaml b/pkg/kgateway/agentgatewaysyncer/backend/testdata/Valid_Bedrock_backend_with_custom_region_and_guardrail.yaml index de1f27f572c..1739102401c 100644 --- a/pkg/kgateway/agentgatewaysyncer/backend/testdata/Valid_Bedrock_backend_with_custom_region_and_guardrail.yaml +++ b/pkg/kgateway/agentgatewaysyncer/backend/testdata/Valid_Bedrock_backend_with_custom_region_and_guardrail.yaml @@ -6,10 +6,6 @@ ai: guardrailVersion: "1.0" model: anthropic.claude-3-haiku-20240307-v1:0 region: eu-west-1 - inlinePolicies: - - auth: - aws: - implicit: {} name: backend key: test-ns/bedrock-backend-custom name: diff --git a/pkg/kgateway/agentgatewaysyncer/backend/translate.go b/pkg/kgateway/agentgatewaysyncer/backend/translate.go index a55e0b306a1..21dd62467d3 100644 --- a/pkg/kgateway/agentgatewaysyncer/backend/translate.go +++ b/pkg/kgateway/agentgatewaysyncer/backend/translate.go @@ -15,7 +15,6 @@ import ( "github.com/kgateway-dev/kgateway/v2/api/v1alpha1/agentgateway" "github.com/kgateway-dev/kgateway/v2/pkg/agentgateway/plugins" "github.com/kgateway-dev/kgateway/v2/pkg/agentgateway/utils" - "github.com/kgateway-dev/kgateway/v2/pkg/kgateway/wellknown" "github.com/kgateway-dev/kgateway/v2/pkg/logging" "github.com/kgateway-dev/kgateway/v2/pkg/utils/kubeutils" ) @@ -363,11 +362,6 @@ func translateLLMProvider(ctx plugins.PolicyCtx, llm *agentgateway.LLMProvider, guardrailVersion = &llm.Bedrock.Guardrail.GuardrailVersion } - auth, err := buildBedrockAuthPolicy(ctx.Krt, region, llm.Bedrock.Auth, ctx.Collections.Secrets, namespace) - if err != nil { - return nil, err - } - provider.Provider = &api.AIBackend_Provider_Bedrock{ Bedrock: &api.AIBackend_Bedrock{ Model: llm.Bedrock.Model, @@ -376,11 +370,6 @@ func translateLLMProvider(ctx plugins.PolicyCtx, llm *agentgateway.LLMProvider, GuardrailVersion: guardrailVersion, }, } - provider.InlinePolicies = append(provider.InlinePolicies, &api.BackendPolicySpec{ - Kind: &api.BackendPolicySpec_Auth{ - Auth: auth, - }, - }) } else { return nil, fmt.Errorf("no supported LLM provider configured") } @@ -401,69 +390,3 @@ func toMCPProtocol(appProtocol string) api.MCPTarget_Protocol { return api.MCPTarget_UNDEFINED } } - -func buildBedrockAuthPolicy(krtctx krt.HandlerContext, region string, auth *agentgateway.AwsAuth, secrets krt.Collection[*corev1.Secret], namespace string) (*api.BackendAuthPolicy, error) { - var errs []error - if auth == nil { - logger.Warn("using implicit AWS auth for AI backend") - return &api.BackendAuthPolicy{ - Kind: &api.BackendAuthPolicy_Aws{ - Aws: &api.Aws{ - Kind: &api.Aws_Implicit{ - Implicit: &api.AwsImplicit{}, - }, - }, - }, - }, nil - } - - if auth.SecretRef.Name == "" { - logger.Warn("not using any auth for AWS - it's most likely not what you want") - return nil, nil - } - - // Get secret using the SecretIndex - secret, err := kubeutils.GetSecret(secrets, krtctx, auth.SecretRef.Name, namespace) - if err != nil { - // Return nil auth policy if secret not found - this will be handled upstream - // TODO(npolshak): Add backend status errors https://github.com/kgateway-dev/kgateway/issues/11966 - return nil, err - } - - var accessKeyId, secretAccessKey string - var sessionToken *string - - // Extract access key - if value, exists := kubeutils.GetSecretValue(secret, wellknown.AccessKey); !exists { - errs = append(errs, errors.New("accessKey is missing or not a valid string")) - } else { - accessKeyId = value - } - - // Extract secret key - if value, exists := kubeutils.GetSecretValue(secret, wellknown.SecretKey); !exists { - errs = append(errs, errors.New("secretKey is missing or not a valid string")) - } else { - secretAccessKey = value - } - - // Extract session token (optional) - if value, exists := kubeutils.GetSecretValue(secret, wellknown.SessionToken); exists { - sessionToken = ptr.Of(value) - } - - return &api.BackendAuthPolicy{ - Kind: &api.BackendAuthPolicy_Aws{ - Aws: &api.Aws{ - Kind: &api.Aws_ExplicitConfig{ - ExplicitConfig: &api.AwsExplicitConfig{ - AccessKeyId: accessKeyId, - SecretAccessKey: secretAccessKey, - SessionToken: sessionToken, - Region: region, - }, - }, - }, - }, - }, errors.Join(errs...) -} diff --git a/pkg/kgateway/agentgatewaysyncer/backend/translate_test.go b/pkg/kgateway/agentgatewaysyncer/backend/translate_test.go index cb5b7531d9a..1de7cc25ac8 100644 --- a/pkg/kgateway/agentgatewaysyncer/backend/translate_test.go +++ b/pkg/kgateway/agentgatewaysyncer/backend/translate_test.go @@ -491,36 +491,6 @@ func TestBuildAIBackend(t *testing.T) { }, }, }, - { - name: "Bedrock backend with new secret ref", - backend: &agentgateway.AgentgatewayBackend{ - ObjectMeta: metav1.ObjectMeta{ - Name: "bedrock-with-secret-ref", - Namespace: "test-ns", - }, - Spec: agentgateway.AgentgatewayBackendSpec{ - AI: &agentgateway.AIBackend{ - LLM: &agentgateway.LLMProvider{ - Bedrock: &agentgateway.BedrockConfig{ - Region: "us-east-1", - Auth: &agentgateway.AwsAuth{ - SecretRef: corev1.LocalObjectReference{ - Name: "bedrock-secret", - }, - }, - }, - }, - }, - }, - }, - inputs: []any{ - createMockSecret("test-ns", "bedrock-secret", map[string]string{ - "accessKey": "secret-accessKey", - "secretKey": "secret-secretKey", - "sessionToken": "secret-sessionToken", - }), - }, - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/pkg/kgateway/agentgatewaysyncer/testdata/outputs/backend/bedrock-backend.yaml b/pkg/kgateway/agentgatewaysyncer/testdata/outputs/backend/bedrock-backend.yaml index 7fccfa80b69..c29eee02f6b 100644 --- a/pkg/kgateway/agentgatewaysyncer/testdata/outputs/backend/bedrock-backend.yaml +++ b/pkg/kgateway/agentgatewaysyncer/testdata/outputs/backend/bedrock-backend.yaml @@ -7,10 +7,6 @@ Backends: guardrailVersion: guardrail-policy-version model: anthropic.claude-3-5-haiku-20241022-v1:0 region: us-west-2 - inlinePolicies: - - auth: - aws: - implicit: {} name: backend key: default/bedrock name: From 91bc916dd8715bd452dbde00d81ad663d3f38e0d Mon Sep 17 00:00:00 2001 From: Yuval Kohavi Date: Thu, 11 Dec 2025 09:44:05 -0500 Subject: [PATCH 06/12] cleanup Signed-off-by: Yuval Kohavi --- pkg/kgateway/agentgatewaysyncer/backend/translate.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/kgateway/agentgatewaysyncer/backend/translate.go b/pkg/kgateway/agentgatewaysyncer/backend/translate.go index 21dd62467d3..b22ea4768e0 100644 --- a/pkg/kgateway/agentgatewaysyncer/backend/translate.go +++ b/pkg/kgateway/agentgatewaysyncer/backend/translate.go @@ -224,10 +224,11 @@ func translateAIBackends(ctx plugins.PolicyCtx, be *agentgateway.AgentgatewayBac aiBackend := &api.AIBackend{} if llm := ai.LLM; llm != nil { - provider, err := translateLLMProvider(ctx, llm, utils.SingularLLMProviderSubBackendName, be.Namespace) + provider, err := translateLLMProvider(llm, utils.SingularLLMProviderSubBackendName) if err != nil { return nil, fmt.Errorf("failed to translate LLM provider: %w", err) } + aiBackend.ProviderGroups = []*api.AIBackend_ProviderGroup{{ Providers: []*api.AIBackend_Provider{provider}, }} @@ -236,7 +237,7 @@ func translateAIBackends(ctx plugins.PolicyCtx, be *agentgateway.AgentgatewayBac providerGroup := &api.AIBackend_ProviderGroup{} for _, provider := range group.Providers { - tp, err := translateLLMProvider(ctx, &provider.LLMProvider, string(provider.Name), be.Namespace) + tp, err := translateLLMProvider(&provider.LLMProvider, string(provider.Name)) if err != nil { return nil, fmt.Errorf("failed to translate LLM provider: %w", err) } @@ -302,7 +303,7 @@ func translateAIBackendPolicies( }) } -func translateLLMProvider(ctx plugins.PolicyCtx, llm *agentgateway.LLMProvider, providerName, namespace string) (*api.AIBackend_Provider, error) { +func translateLLMProvider(llm *agentgateway.LLMProvider, providerName string) (*api.AIBackend_Provider, error) { provider := &api.AIBackend_Provider{ Name: providerName, } From ba9cf5741be15d1a7fb19e1b4a80e4ae916d5316 Mon Sep 17 00:00:00 2001 From: Yuval Kohavi Date: Thu, 11 Dec 2025 13:21:33 -0500 Subject: [PATCH 07/12] bump agentgw Signed-off-by: Yuval Kohavi --- go.mod | 2 +- go.sum | 2 ++ pkg/deployer/wellknown.go | 2 +- .../agentgateway-controller-but-custom-gatewayclass-out.yaml | 2 +- test/deployer/testdata/agentgateway-custom-configmap-out.yaml | 2 +- test/deployer/testdata/agentgateway-env-out.yaml | 2 +- test/deployer/testdata/agentgateway-image-repo-only-out.yaml | 2 +- test/deployer/testdata/agentgateway-infrastructure-out.yaml | 2 +- test/deployer/testdata/agentgateway-logging-format-out.yaml | 2 +- .../testdata/agentgateway-omitdefaultsecuritycontext-out.yaml | 2 +- ...entgateway-omitdefaultsecuritycontext-ref-gwp-on-gw-out.yaml | 2 +- test/deployer/testdata/agentgateway-out.yaml | 2 +- .../testdata/agentgateway-rawconfig-typed-conflict-out.yaml | 2 +- test/deployer/testdata/agentgateway-shutdown-out.yaml | 2 +- test/deployer/testdata/agentgateway-tls-out.yaml | 2 +- 15 files changed, 16 insertions(+), 14 deletions(-) diff --git a/go.mod b/go.mod index cdf91b7dc4e..989eb3adb04 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.25.3 require ( // Also update AgentgatewayDefaultTag in pkg/deployer/wellknown.go and test/deployer/testdata/* - github.com/agentgateway/agentgateway v0.10.6-0.20251203184148-f45f1a94cdfa + github.com/agentgateway/agentgateway v0.10.6-0.20251211180119-76b0afc55496 github.com/avast/retry-go/v4 v4.3.3 github.com/cncf/xds/go v0.0.0-20251110193048-8bfbf64dc13e github.com/envoyproxy/go-control-plane v0.14.0 diff --git a/go.sum b/go.sum index ef9b5f56ee6..eddec00a9c5 100644 --- a/go.sum +++ b/go.sum @@ -198,6 +198,8 @@ github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpH github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= github.com/agentgateway/agentgateway v0.10.6-0.20251203184148-f45f1a94cdfa h1:PWDaZIBsPpGIo/3PdYRRIrU5kCKC86nkkEZLqTDi5rI= github.com/agentgateway/agentgateway v0.10.6-0.20251203184148-f45f1a94cdfa/go.mod h1:/Lzpteag/nnE4bwW/3Dh5GaxuICmCQs40VhQpkTatlk= +github.com/agentgateway/agentgateway v0.10.6-0.20251211180119-76b0afc55496 h1:A7qJ8Ac6vMHDSqcFDpk/IBfZPjxbH44/78dtsodxiEk= +github.com/agentgateway/agentgateway v0.10.6-0.20251211180119-76b0afc55496/go.mod h1:/Lzpteag/nnE4bwW/3Dh5GaxuICmCQs40VhQpkTatlk= github.com/agnivade/levenshtein v1.2.1 h1:EHBY3UOn1gwdy/VbFwgo4cxecRznFk7fKWN1KOX7eoM= github.com/agnivade/levenshtein v1.2.1/go.mod h1:QVVI16kDrtSuwcpd0p1+xMC6Z/VfhtCyDIjcwga4/DU= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= diff --git a/pkg/deployer/wellknown.go b/pkg/deployer/wellknown.go index 058ef443cfd..326242cc260 100644 --- a/pkg/deployer/wellknown.go +++ b/pkg/deployer/wellknown.go @@ -17,7 +17,7 @@ const ( AgentgatewayRegistry = "ghcr.io/agentgateway" // AgentgatewayDefaultTag is the default agentgateway image tag // Note: should be in sync with version in go.mod and test/deployer/testdata/* - AgentgatewayDefaultTag = "0.11.0-alpha.f45f1a94cdfa53d96e14301d59ac62200214cb9c" + AgentgatewayDefaultTag = "0.11.0-alpha.76b0afc55496e7027395a93a3ba1ceca4b832647" // SdsImage is the image of the sds container. SdsImage = "sds" // SdsContainerName is the name of the container in the proxy deployment for the SDS integration. diff --git a/test/deployer/testdata/agentgateway-controller-but-custom-gatewayclass-out.yaml b/test/deployer/testdata/agentgateway-controller-but-custom-gatewayclass-out.yaml index 7de4b95b63f..933fe4c4b52 100644 --- a/test/deployer/testdata/agentgateway-controller-but-custom-gatewayclass-out.yaml +++ b/test/deployer/testdata/agentgateway-controller-but-custom-gatewayclass-out.yaml @@ -121,7 +121,7 @@ spec: fieldPath: metadata.namespace - name: GATEWAY value: gw - image: ghcr.io/agentgateway/agentgateway:0.11.0-alpha.f45f1a94cdfa53d96e14301d59ac62200214cb9c + image: ghcr.io/agentgateway/agentgateway:0.11.0-alpha.76b0afc55496e7027395a93a3ba1ceca4b832647 name: agent-gateway ports: - containerPort: 15020 diff --git a/test/deployer/testdata/agentgateway-custom-configmap-out.yaml b/test/deployer/testdata/agentgateway-custom-configmap-out.yaml index 266ea9fb600..4fdc58b001c 100644 --- a/test/deployer/testdata/agentgateway-custom-configmap-out.yaml +++ b/test/deployer/testdata/agentgateway-custom-configmap-out.yaml @@ -121,7 +121,7 @@ spec: value: agent-gateway - name: RUST_LOG value: debug - image: ghcr.io/agentgateway/agentgateway:0.11.0-alpha.f45f1a94cdfa53d96e14301d59ac62200214cb9c + image: ghcr.io/agentgateway/agentgateway:0.11.0-alpha.76b0afc55496e7027395a93a3ba1ceca4b832647 name: agent-gateway ports: - containerPort: 15020 diff --git a/test/deployer/testdata/agentgateway-env-out.yaml b/test/deployer/testdata/agentgateway-env-out.yaml index b3a908d3183..9f29afd0afc 100644 --- a/test/deployer/testdata/agentgateway-env-out.yaml +++ b/test/deployer/testdata/agentgateway-env-out.yaml @@ -125,7 +125,7 @@ spec: value: $(GATEWAY) - name: TEST_OF_AVOIDING_VARIABLE_EXPANSION value: $$(GATEWAY) - image: ghcr.io/agentgateway/agentgateway:0.11.0-alpha.f45f1a94cdfa53d96e14301d59ac62200214cb9c + image: ghcr.io/agentgateway/agentgateway:0.11.0-alpha.76b0afc55496e7027395a93a3ba1ceca4b832647 name: agent-gateway ports: - containerPort: 15020 diff --git a/test/deployer/testdata/agentgateway-image-repo-only-out.yaml b/test/deployer/testdata/agentgateway-image-repo-only-out.yaml index 0c350837a4e..6db00de7664 100644 --- a/test/deployer/testdata/agentgateway-image-repo-only-out.yaml +++ b/test/deployer/testdata/agentgateway-image-repo-only-out.yaml @@ -121,7 +121,7 @@ spec: fieldPath: metadata.namespace - name: GATEWAY value: gw - image: ghcr.io/agentgateway/custom-repo:0.11.0-alpha.f45f1a94cdfa53d96e14301d59ac62200214cb9c + image: ghcr.io/agentgateway/custom-repo:0.11.0-alpha.76b0afc55496e7027395a93a3ba1ceca4b832647 name: agent-gateway ports: - containerPort: 15020 diff --git a/test/deployer/testdata/agentgateway-infrastructure-out.yaml b/test/deployer/testdata/agentgateway-infrastructure-out.yaml index f9b2131f1d1..e8dca762505 100644 --- a/test/deployer/testdata/agentgateway-infrastructure-out.yaml +++ b/test/deployer/testdata/agentgateway-infrastructure-out.yaml @@ -153,7 +153,7 @@ spec: fieldPath: metadata.namespace - name: GATEWAY value: gw - image: ghcr.io/agentgateway/agentgateway:0.11.0-alpha.f45f1a94cdfa53d96e14301d59ac62200214cb9c + image: ghcr.io/agentgateway/agentgateway:0.11.0-alpha.76b0afc55496e7027395a93a3ba1ceca4b832647 name: agent-gateway ports: - containerPort: 15020 diff --git a/test/deployer/testdata/agentgateway-logging-format-out.yaml b/test/deployer/testdata/agentgateway-logging-format-out.yaml index ac57bb683f0..1429596e77a 100644 --- a/test/deployer/testdata/agentgateway-logging-format-out.yaml +++ b/test/deployer/testdata/agentgateway-logging-format-out.yaml @@ -123,7 +123,7 @@ spec: fieldPath: metadata.namespace - name: GATEWAY value: gw - image: ghcr.io/agentgateway/agentgateway:0.11.0-alpha.f45f1a94cdfa53d96e14301d59ac62200214cb9c + image: ghcr.io/agentgateway/agentgateway:0.11.0-alpha.76b0afc55496e7027395a93a3ba1ceca4b832647 name: agent-gateway ports: - containerPort: 15020 diff --git a/test/deployer/testdata/agentgateway-omitdefaultsecuritycontext-out.yaml b/test/deployer/testdata/agentgateway-omitdefaultsecuritycontext-out.yaml index f64fce31b4a..e6908775f9f 100644 --- a/test/deployer/testdata/agentgateway-omitdefaultsecuritycontext-out.yaml +++ b/test/deployer/testdata/agentgateway-omitdefaultsecuritycontext-out.yaml @@ -121,7 +121,7 @@ spec: fieldPath: metadata.namespace - name: GATEWAY value: gw - image: ghcr.io/agentgateway/agentgateway:0.11.0-alpha.f45f1a94cdfa53d96e14301d59ac62200214cb9c + image: ghcr.io/agentgateway/agentgateway:0.11.0-alpha.76b0afc55496e7027395a93a3ba1ceca4b832647 name: agent-gateway ports: - containerPort: 15020 diff --git a/test/deployer/testdata/agentgateway-omitdefaultsecuritycontext-ref-gwp-on-gw-out.yaml b/test/deployer/testdata/agentgateway-omitdefaultsecuritycontext-ref-gwp-on-gw-out.yaml index f64fce31b4a..e6908775f9f 100644 --- a/test/deployer/testdata/agentgateway-omitdefaultsecuritycontext-ref-gwp-on-gw-out.yaml +++ b/test/deployer/testdata/agentgateway-omitdefaultsecuritycontext-ref-gwp-on-gw-out.yaml @@ -121,7 +121,7 @@ spec: fieldPath: metadata.namespace - name: GATEWAY value: gw - image: ghcr.io/agentgateway/agentgateway:0.11.0-alpha.f45f1a94cdfa53d96e14301d59ac62200214cb9c + image: ghcr.io/agentgateway/agentgateway:0.11.0-alpha.76b0afc55496e7027395a93a3ba1ceca4b832647 name: agent-gateway ports: - containerPort: 15020 diff --git a/test/deployer/testdata/agentgateway-out.yaml b/test/deployer/testdata/agentgateway-out.yaml index c44ffd50592..c604b6597cf 100644 --- a/test/deployer/testdata/agentgateway-out.yaml +++ b/test/deployer/testdata/agentgateway-out.yaml @@ -121,7 +121,7 @@ spec: fieldPath: metadata.namespace - name: GATEWAY value: gw - image: ghcr.io/agentgateway/agentgateway:0.11.0-alpha.f45f1a94cdfa53d96e14301d59ac62200214cb9c + image: ghcr.io/agentgateway/agentgateway:0.11.0-alpha.76b0afc55496e7027395a93a3ba1ceca4b832647 name: agent-gateway ports: - containerPort: 15020 diff --git a/test/deployer/testdata/agentgateway-rawconfig-typed-conflict-out.yaml b/test/deployer/testdata/agentgateway-rawconfig-typed-conflict-out.yaml index 1195503449b..e9da5a21511 100644 --- a/test/deployer/testdata/agentgateway-rawconfig-typed-conflict-out.yaml +++ b/test/deployer/testdata/agentgateway-rawconfig-typed-conflict-out.yaml @@ -125,7 +125,7 @@ spec: fieldPath: metadata.namespace - name: GATEWAY value: gw - image: ghcr.io/agentgateway/agentgateway:0.11.0-alpha.f45f1a94cdfa53d96e14301d59ac62200214cb9c + image: ghcr.io/agentgateway/agentgateway:0.11.0-alpha.76b0afc55496e7027395a93a3ba1ceca4b832647 name: agent-gateway ports: - containerPort: 15020 diff --git a/test/deployer/testdata/agentgateway-shutdown-out.yaml b/test/deployer/testdata/agentgateway-shutdown-out.yaml index b985b946784..85d166838f2 100644 --- a/test/deployer/testdata/agentgateway-shutdown-out.yaml +++ b/test/deployer/testdata/agentgateway-shutdown-out.yaml @@ -121,7 +121,7 @@ spec: fieldPath: metadata.namespace - name: GATEWAY value: gw - image: ghcr.io/agentgateway/agentgateway:0.11.0-alpha.f45f1a94cdfa53d96e14301d59ac62200214cb9c + image: ghcr.io/agentgateway/agentgateway:0.11.0-alpha.76b0afc55496e7027395a93a3ba1ceca4b832647 name: agent-gateway ports: - containerPort: 15020 diff --git a/test/deployer/testdata/agentgateway-tls-out.yaml b/test/deployer/testdata/agentgateway-tls-out.yaml index d1f6a6bb7fc..916915d8982 100644 --- a/test/deployer/testdata/agentgateway-tls-out.yaml +++ b/test/deployer/testdata/agentgateway-tls-out.yaml @@ -152,7 +152,7 @@ spec: fieldPath: metadata.namespace - name: GATEWAY value: gw - image: ghcr.io/agentgateway/agentgateway:0.11.0-alpha.f45f1a94cdfa53d96e14301d59ac62200214cb9c + image: ghcr.io/agentgateway/agentgateway:0.11.0-alpha.76b0afc55496e7027395a93a3ba1ceca4b832647 name: agent-gateway ports: - containerPort: 15020 From d44b375da2a8447d7d6ff5b8bbd464cc82149777 Mon Sep 17 00:00:00 2001 From: Yuval Kohavi Date: Thu, 11 Dec 2025 13:53:10 -0500 Subject: [PATCH 08/12] fix build Signed-off-by: Yuval Kohavi --- pkg/agentgateway/plugins/traffic_plugin.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pkg/agentgateway/plugins/traffic_plugin.go b/pkg/agentgateway/plugins/traffic_plugin.go index 56926677baf..2c7e513615d 100644 --- a/pkg/agentgateway/plugins/traffic_plugin.go +++ b/pkg/agentgateway/plugins/traffic_plugin.go @@ -826,8 +826,12 @@ func processExtAuthPolicy( return nil, fmt.Errorf("failed to build extAuth: %v", err) } spec := &api.TrafficPolicySpec_ExternalAuth{ - Target: be, - Context: extAuth.ContextExtensions, + Target: be, + Protocol: &api.TrafficPolicySpec_ExternalAuth_Grpc{ + Grpc: &api.TrafficPolicySpec_ExternalAuth_GRPCProtocol{ + Context: extAuth.ContextExtensions, + }, + }, } if b := extAuth.ForwardBody; b != nil { spec.IncludeRequestBody = &api.TrafficPolicySpec_ExternalAuth_BodyOptions{ From 3b733f170fd7e731d386f0ad12bdba50fc6820d7 Mon Sep 17 00:00:00 2001 From: Yuval Kohavi Date: Thu, 11 Dec 2025 13:59:18 -0500 Subject: [PATCH 09/12] make verify Signed-off-by: Yuval Kohavi --- go.sum | 2 -- hack/utils/oss_compliance/osa_provided.md | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/go.sum b/go.sum index eddec00a9c5..0d808aef012 100644 --- a/go.sum +++ b/go.sum @@ -196,8 +196,6 @@ github.com/PuerkitoBio/goquery v1.10.1 h1:Y8JGYUkXWTGRB6Ars3+j3kN0xg1YqqlwvdTV8W github.com/PuerkitoBio/goquery v1.10.1/go.mod h1:IYiHrOMps66ag56LEH7QYDDupKXyo5A8qrjIx3ZtujY= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= -github.com/agentgateway/agentgateway v0.10.6-0.20251203184148-f45f1a94cdfa h1:PWDaZIBsPpGIo/3PdYRRIrU5kCKC86nkkEZLqTDi5rI= -github.com/agentgateway/agentgateway v0.10.6-0.20251203184148-f45f1a94cdfa/go.mod h1:/Lzpteag/nnE4bwW/3Dh5GaxuICmCQs40VhQpkTatlk= github.com/agentgateway/agentgateway v0.10.6-0.20251211180119-76b0afc55496 h1:A7qJ8Ac6vMHDSqcFDpk/IBfZPjxbH44/78dtsodxiEk= github.com/agentgateway/agentgateway v0.10.6-0.20251211180119-76b0afc55496/go.mod h1:/Lzpteag/nnE4bwW/3Dh5GaxuICmCQs40VhQpkTatlk= github.com/agnivade/levenshtein v1.2.1 h1:EHBY3UOn1gwdy/VbFwgo4cxecRznFk7fKWN1KOX7eoM= diff --git a/hack/utils/oss_compliance/osa_provided.md b/hack/utils/oss_compliance/osa_provided.md index b5f3f241c4d..77fe36a15e9 100644 --- a/hack/utils/oss_compliance/osa_provided.md +++ b/hack/utils/oss_compliance/osa_provided.md @@ -3,7 +3,7 @@ Name|Version|License [cel.dev/expr](https://cel.dev/expr)|v0.24.0|Apache License 2.0 [semver/v3](https://github.com/Masterminds/semver)|v3.4.0|MIT License [PuerkitoBio/goquery](https://github.com/PuerkitoBio/goquery)|v1.10.1|BSD 3-clause "New" or "Revised" License -[agentgateway/agentgateway](https://github.com/agentgateway/agentgateway)|v0.10.6-0.20251203184148-f45f1a94cdfa|Apache License 2.0 +[agentgateway/agentgateway](https://github.com/agentgateway/agentgateway)|v0.10.6-0.20251211180119-76b0afc55496|Apache License 2.0 [anthropics/anthropic-sdk-go](https://github.com/anthropics/anthropic-sdk-go)|v1.13.0|MIT License [retry-go/v4](https://github.com/avast/retry-go)|v4.3.3|MIT License [xds/go](https://github.com/cncf/xds)|v0.0.0-20251110193048-8bfbf64dc13e|Apache License 2.0 From ec09ef77ccd5a8feb1f43d03df5b4f664d202d40 Mon Sep 17 00:00:00 2001 From: Yuval Kohavi Date: Thu, 11 Dec 2025 14:32:14 -0500 Subject: [PATCH 10/12] fix yaml Signed-off-by: Yuval Kohavi --- .../testdata/outputs/trafficpolicy/extauth-route.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/kgateway/agentgatewaysyncer/testdata/outputs/trafficpolicy/extauth-route.yaml b/pkg/kgateway/agentgatewaysyncer/testdata/outputs/trafficpolicy/extauth-route.yaml index 52c6cec2f31..6df72ad9195 100644 --- a/pkg/kgateway/agentgatewaysyncer/testdata/outputs/trafficpolicy/extauth-route.yaml +++ b/pkg/kgateway/agentgatewaysyncer/testdata/outputs/trafficpolicy/extauth-route.yaml @@ -36,6 +36,7 @@ Policies: namespace: default traffic: extAuthz: + grpc: {} target: port: 4444 service: From ee8861954269944cd91db6743de7ab43e6c11e0c Mon Sep 17 00:00:00 2001 From: Yuval Kohavi Date: Thu, 11 Dec 2025 14:52:43 -0500 Subject: [PATCH 11/12] fix yaml after merge Signed-off-by: Yuval Kohavi --- pkg/agentgateway/plugins/testdata/backendpolicy/awsauth.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/agentgateway/plugins/testdata/backendpolicy/awsauth.yaml b/pkg/agentgateway/plugins/testdata/backendpolicy/awsauth.yaml index e7e8e43b5e3..8256ea41466 100644 --- a/pkg/agentgateway/plugins/testdata/backendpolicy/awsauth.yaml +++ b/pkg/agentgateway/plugins/testdata/backendpolicy/awsauth.yaml @@ -62,4 +62,4 @@ status: reason: Attached status: "True" type: Attached - controllerName: kgateway.dev/agentgateway + controllerName: agentgateway.dev/agentgateway From 90f4e716ec6a8bdc5efec9f85c9a3661b60bbb6a Mon Sep 17 00:00:00 2001 From: Yuval Kohavi Date: Thu, 11 Dec 2025 15:12:20 -0500 Subject: [PATCH 12/12] more yamls Signed-off-by: Yuval Kohavi --- .../testdata/outputs/trafficpolicy/extauth-gateway.yaml | 1 + .../testdata/outputs/trafficpolicy/extauth-listener.yaml | 1 + 2 files changed, 2 insertions(+) diff --git a/pkg/kgateway/agentgatewaysyncer/testdata/outputs/trafficpolicy/extauth-gateway.yaml b/pkg/kgateway/agentgatewaysyncer/testdata/outputs/trafficpolicy/extauth-gateway.yaml index f0138b7a9cf..0de92d767c4 100644 --- a/pkg/kgateway/agentgatewaysyncer/testdata/outputs/trafficpolicy/extauth-gateway.yaml +++ b/pkg/kgateway/agentgatewaysyncer/testdata/outputs/trafficpolicy/extauth-gateway.yaml @@ -36,6 +36,7 @@ Policies: namespace: default traffic: extAuthz: + grpc: {} target: port: 4444 service: diff --git a/pkg/kgateway/agentgatewaysyncer/testdata/outputs/trafficpolicy/extauth-listener.yaml b/pkg/kgateway/agentgatewaysyncer/testdata/outputs/trafficpolicy/extauth-listener.yaml index 5929d70e64c..811b27a6316 100644 --- a/pkg/kgateway/agentgatewaysyncer/testdata/outputs/trafficpolicy/extauth-listener.yaml +++ b/pkg/kgateway/agentgatewaysyncer/testdata/outputs/trafficpolicy/extauth-listener.yaml @@ -46,6 +46,7 @@ Policies: namespace: default traffic: extAuthz: + grpc: {} includeRequestBody: allowPartialMessage: true maxRequestBytes: 1024