77 "github.com/agentgateway/agentgateway/go/api"
88 "istio.io/istio/pkg/kube/krt"
99 "istio.io/istio/pkg/ptr"
10+
1011 corev1 "k8s.io/api/core/v1"
1112 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1213 "k8s.io/apimachinery/pkg/labels"
@@ -15,6 +16,7 @@ import (
1516 "github.com/kgateway-dev/kgateway/v2/api/v1alpha1/agentgateway"
1617 "github.com/kgateway-dev/kgateway/v2/pkg/agentgateway/plugins"
1718 "github.com/kgateway-dev/kgateway/v2/pkg/agentgateway/utils"
19+ "github.com/kgateway-dev/kgateway/v2/pkg/kgateway/wellknown"
1820 "github.com/kgateway-dev/kgateway/v2/pkg/logging"
1921 "github.com/kgateway-dev/kgateway/v2/pkg/utils/kubeutils"
2022)
@@ -224,11 +226,17 @@ func translateAIBackends(ctx plugins.PolicyCtx, be *agentgateway.AgentgatewayBac
224226
225227 aiBackend := & api.AIBackend {}
226228 if llm := ai .LLM ; llm != nil {
227- provider , err := translateLLMProvider (llm , utils .SingularLLMProviderSubBackendName )
229+ provider , auth , err := translateLLMProvider (ctx , llm , utils .SingularLLMProviderSubBackendName , be . Namespace )
228230 if err != nil {
229231 return nil , fmt .Errorf ("failed to translate LLM provider: %w" , err )
230232 }
231-
233+ if auth != nil {
234+ inlinePolicies = append (inlinePolicies , & api.BackendPolicySpec {
235+ Kind : & api.BackendPolicySpec_Auth {
236+ Auth : auth ,
237+ },
238+ })
239+ }
232240 aiBackend .ProviderGroups = []* api.AIBackend_ProviderGroup {{
233241 Providers : []* api.AIBackend_Provider {provider },
234242 }}
@@ -237,7 +245,7 @@ func translateAIBackends(ctx plugins.PolicyCtx, be *agentgateway.AgentgatewayBac
237245 providerGroup := & api.AIBackend_ProviderGroup {}
238246
239247 for _ , provider := range group .Providers {
240- tp , err := translateLLMProvider (& provider .LLMProvider , string (provider .Name ))
248+ tp , auth , err := translateLLMProvider (ctx , & provider .LLMProvider , string (provider .Name ), be . Namespace )
241249 if err != nil {
242250 return nil , fmt .Errorf ("failed to translate LLM provider: %w" , err )
243251 }
@@ -247,6 +255,13 @@ func translateAIBackends(ctx plugins.PolicyCtx, be *agentgateway.AgentgatewayBac
247255 logger .Warn ("failed to translate AI backend policies" , "err" , err )
248256 }
249257 tp .InlinePolicies = pol
258+ if auth != nil {
259+ tp .InlinePolicies = append (tp .InlinePolicies , & api.BackendPolicySpec {
260+ Kind : & api.BackendPolicySpec_Auth {
261+ Auth : auth ,
262+ },
263+ })
264+ }
250265
251266 providerGroup .Providers = append (providerGroup .Providers , tp )
252267 }
@@ -303,7 +318,7 @@ func translateAIBackendPolicies(
303318 })
304319}
305320
306- func translateLLMProvider (llm * agentgateway.LLMProvider , providerName string ) (* api.AIBackend_Provider , error ) {
321+ func translateLLMProvider (ctx plugins. PolicyCtx , llm * agentgateway.LLMProvider , providerName , namespace string ) (* api.AIBackend_Provider , * api. BackendAuthPolicy , error ) {
307322 provider := & api.AIBackend_Provider {
308323 Name : providerName ,
309324 }
@@ -318,6 +333,7 @@ func translateLLMProvider(llm *agentgateway.LLMProvider, providerName string) (*
318333 if llm .Path != "" {
319334 provider .PathOverride = & llm .Path
320335 }
336+ var auth * api.BackendAuthPolicy
321337
322338 // Extract auth token and model based on provider
323339 if llm .OpenAI != nil {
@@ -363,6 +379,12 @@ func translateLLMProvider(llm *agentgateway.LLMProvider, providerName string) (*
363379 guardrailVersion = & llm .Bedrock .Guardrail .GuardrailVersion
364380 }
365381
382+ var err error
383+ auth , err = buildBedrockAuthPolicy (ctx .Krt , region , llm .Bedrock .Auth , ctx .Collections .Secrets , namespace )
384+ if err != nil {
385+ return nil , nil , err
386+ }
387+
366388 provider .Provider = & api.AIBackend_Provider_Bedrock {
367389 Bedrock : & api.AIBackend_Bedrock {
368390 Model : llm .Bedrock .Model ,
@@ -372,10 +394,10 @@ func translateLLMProvider(llm *agentgateway.LLMProvider, providerName string) (*
372394 },
373395 }
374396 } else {
375- return nil , fmt .Errorf ("no supported LLM provider configured" )
397+ return nil , nil , fmt .Errorf ("no supported LLM provider configured" )
376398 }
377399
378- return provider , nil
400+ return provider , auth , nil
379401}
380402
381403func toMCPProtocol (appProtocol string ) api.MCPTarget_Protocol {
@@ -391,3 +413,70 @@ func toMCPProtocol(appProtocol string) api.MCPTarget_Protocol {
391413 return api .MCPTarget_UNDEFINED
392414 }
393415}
416+
417+ func buildBedrockAuthPolicy (krtctx krt.HandlerContext , region string , auth * agentgateway.AwsAuth , secrets krt.Collection [* corev1.Secret ], namespace string ) (* api.BackendAuthPolicy , error ) {
418+ var errs []error
419+ if auth == nil {
420+ logger .Warn ("using implicit AWS auth for AI backend" )
421+ return & api.BackendAuthPolicy {
422+ Kind : & api.BackendAuthPolicy_Aws {
423+ Aws : & api.Aws {
424+ Kind : & api.Aws_Implicit {
425+ Implicit : & api.AwsImplicit {},
426+ },
427+ },
428+ },
429+ }, nil
430+ }
431+
432+ if auth .SecretRef == nil {
433+ logger .Warn ("not using any auth for AWS - it's most likely not what you want" )
434+ return nil , nil
435+ }
436+
437+ // Get secret using the SecretIndex
438+ secret , err := kubeutils .GetSecret (secrets , krtctx , auth .SecretRef .Name , namespace )
439+ if err != nil {
440+ // Return nil auth policy if secret not found - this will be handled upstream
441+ // TODO(npolshak): Add backend status errors https://github.com/kgateway-dev/kgateway/issues/11966
442+ return nil , err
443+ }
444+
445+ var accessKeyId , secretAccessKey string
446+ var sessionToken * string
447+
448+ // Extract access key
449+ if value , exists := kubeutils .GetSecretValue (secret , wellknown .AccessKey ); ! exists {
450+ errs = append (errs , errors .New ("accessKey is missing or not a valid string" ))
451+ } else {
452+ accessKeyId = value
453+ }
454+
455+ // Extract secret key
456+ if value , exists := kubeutils .GetSecretValue (secret , wellknown .SecretKey ); ! exists {
457+ errs = append (errs , errors .New ("secretKey is missing or not a valid string" ))
458+ } else {
459+ secretAccessKey = value
460+ }
461+
462+ // Extract session token (optional)
463+ if value , exists := kubeutils .GetSecretValue (secret , wellknown .SessionToken ); exists {
464+ sessionToken = ptr .Of (value )
465+ }
466+
467+ return & api.BackendAuthPolicy {
468+ Kind : & api.BackendAuthPolicy_Aws {
469+ Aws : & api.Aws {
470+ Kind : & api.Aws_ExplicitConfig {
471+ ExplicitConfig : & api.AwsExplicitConfig {
472+ AccessKeyId : accessKeyId ,
473+ SecretAccessKey : secretAccessKey ,
474+ SessionToken : sessionToken ,
475+ Region : region ,
476+ },
477+ },
478+ },
479+ },
480+ }, errors .Join (errs ... )
481+
482+ }
0 commit comments