@@ -14,11 +14,17 @@ import (
1414 "strings"
1515
1616 "github.com/golang-jwt/jwt/v5"
17+ "k8s.io/apimachinery/pkg/util/sets"
1718
1819 "github.com/envoyproxy/ai-gateway/internal/filterapi"
1920)
2021
22+ // authorizeRequest authorizes the request based on the given MCPRouteAuthorization configuration.
2123func (m * MCPProxy ) authorizeRequest (authorization * filterapi.MCPRouteAuthorization , headers http.Header , backendName , toolName string , argments any ) bool {
24+ if authorization == nil {
25+ return true
26+ }
27+
2228 defaultAction := authorization .DefaultAction == filterapi .AuthorizationActionAllow
2329
2430 // If there are no rules, return the default action.
@@ -28,6 +34,8 @@ func (m *MCPProxy) authorizeRequest(authorization *filterapi.MCPRouteAuthorizati
2834
2935 // If the rules are defined, a valid bearer token is required.
3036 token , err := bearerToken (headers .Get ("Authorization" ))
37+ // This is just a sanity check. The actual JWT verification is performed by Envoy before reaching here, and the token
38+ // should always be present and valid.
3139 if err != nil {
3240 m .l .Info ("missing or invalid bearer token" , slog .String ("error" , err .Error ()))
3341 return false
@@ -40,10 +48,7 @@ func (m *MCPProxy) authorizeRequest(authorization *filterapi.MCPRouteAuthorizati
4048 return false
4149 }
4250
43- scopeSet := make (map [string ]struct {})
44- for _ , scope := range extractScopes (claims ) {
45- scopeSet [scope ] = struct {}{}
46- }
51+ scopeSet := sets .New [string ](extractScopes (claims )... )
4752
4853 for _ , rule := range authorization .Rules {
4954 var args map [string ]any
@@ -52,7 +57,7 @@ func (m *MCPProxy) authorizeRequest(authorization *filterapi.MCPRouteAuthorizati
5257 args = cast
5358 }
5459 }
55- if ! toolMatches (args , filterapi.ToolCall {BackendName : backendName , ToolName : toolName }, rule .Target .Tools ) {
60+ if ! m . toolMatches (filterapi.ToolCall {BackendName : backendName , ToolName : toolName }, rule .Target .Tools , args ) {
5661 continue
5762 }
5863 if scopesSatisfied (scopeSet , rule .Source .JWTSource .Scopes ) {
@@ -104,7 +109,7 @@ func extractScopes(claims jwt.MapClaims) []string {
104109 }
105110}
106111
107- func toolMatches ( args map [ string ] any , target filterapi.ToolCall , tools []filterapi.ToolCall ) bool {
112+ func ( m * MCPProxy ) toolMatches ( target filterapi.ToolCall , tools []filterapi.ToolCall , args map [ string ] any ) bool {
108113 if len (tools ) == 0 {
109114 return true
110115 }
@@ -128,6 +133,7 @@ func toolMatches(args map[string]any, target filterapi.ToolCall, tools []filtera
128133 }
129134 re , err := regexp .Compile (pattern )
130135 if err != nil {
136+ m .l .Error ("invalid argument regex pattern" , slog .String ("pattern" , pattern ), slog .String ("error" , err .Error ()))
131137 allMatch = false
132138 break
133139 }
@@ -137,6 +143,7 @@ func toolMatches(args map[string]any, target filterapi.ToolCall, tools []filtera
137143 } else {
138144 jsonVal , err := json .Marshal (rawVal )
139145 if err != nil {
146+ m .l .Error ("failed to marshal argument value to json" , slog .String ("key" , key ), slog .String ("error" , err .Error ()))
140147 allMatch = false
141148 break
142149 }
@@ -155,7 +162,7 @@ func toolMatches(args map[string]any, target filterapi.ToolCall, tools []filtera
155162 return false
156163}
157164
158- func scopesSatisfied (have map [string ]struct {} , required []string ) bool {
165+ func scopesSatisfied (have sets. Set [string ], required []string ) bool {
159166 if len (required ) == 0 {
160167 return true
161168 }
0 commit comments