diff --git a/go.mod b/go.mod index 13b3239..6f41aab 100644 --- a/go.mod +++ b/go.mod @@ -2,10 +2,10 @@ module github.com/apigee/apigee-remote-service-envoy/v2 go 1.16 -// replace github.com/apigee/apigee-remote-service-golib/v2 => ../apigee-remote-service-golib +//replace github.com/apigee/apigee-remote-service-golib/v2 => ../apigee-remote-service-golib require ( - github.com/apigee/apigee-remote-service-golib/v2 v2.0.7-0.20230308165829-ba684bc16fda + github.com/apigee/apigee-remote-service-golib/v2 v2.0.7-0.20230308201312-6db69e217dea github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad github.com/gogo/googleapis v1.4.1 github.com/golang/protobuf v1.5.2 diff --git a/go.sum b/go.sum index 4309977..4d71cca 100644 --- a/go.sum +++ b/go.sum @@ -42,8 +42,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/apigee/apigee-remote-service-golib/v2 v2.0.7-0.20230308165829-ba684bc16fda h1:T1VfDgp3mSIXqOiLo14VdwhnwmVjV+/wGESBzr5KOGg= -github.com/apigee/apigee-remote-service-golib/v2 v2.0.7-0.20230308165829-ba684bc16fda/go.mod h1:km/iROUzLa13srZgVP0R31sAcsdgYnCJlvZdCW7ud98= +github.com/apigee/apigee-remote-service-golib/v2 v2.0.7-0.20230308201312-6db69e217dea h1:iwqx15jtWqCTKDjq1hKh3CRjCyl9pI7+ujQijjqXRw0= +github.com/apigee/apigee-remote-service-golib/v2 v2.0.7-0.20230308201312-6db69e217dea/go.mod h1:km/iROUzLa13srZgVP0R31sAcsdgYnCJlvZdCW7ud98= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= diff --git a/server/authorization_test.go b/server/authorization_test.go index 378ae2d..78b50fc 100644 --- a/server/authorization_test.go +++ b/server/authorization_test.go @@ -362,14 +362,15 @@ func TestImmediateAnalytics(t *testing.T) { testAuthMan := &testAuthMan{} ac := &auth.Context{ - ClientID: "client id", - AccessToken: "token", - Application: "app", - APIProducts: []string{"product1"}, - Expires: time.Now(), - DeveloperEmail: "email", - Scopes: []string{"scope"}, - APIKey: "apikey", + ClientID: "client id", + AccessToken: "token", + Application: "app", + APIProducts: []string{"product1"}, + Expires: time.Now(), + DeveloperEmail: "email", + Scopes: []string{"scope"}, + APIKey: "apikey", + CustomAttributes: "{\"tier\":\"standard\"}", } testAuthMan.sendAuth(ac, auth.ErrBadAuth) diff --git a/server/header_context.go b/server/header_context.go index 158f993..d35a3f8 100644 --- a/server/header_context.go +++ b/server/header_context.go @@ -39,7 +39,9 @@ func makeMetadataHeaders(api string, ac *auth.Context, authorized bool) []*core. header(headerOrganization, ac.Organization()), header(headerScope, strings.Join(ac.Scopes, " ")), } - + if ac.CustomAttributes != "" { + headers = append(headers, header(headerCustomAttributes, ac.CustomAttributes)) + } if authorized { headers = append(headers, header(headerAuthorized, "true")) } @@ -77,12 +79,13 @@ func (h *Handler) decodeMetadataHeaders(headers map[string]string) (string, *aut } return api, &auth.Context{ - Context: rootContext, - AccessToken: headers[headerAccessToken], - APIProducts: strings.Split(headers[headerAPIProducts], ","), - Application: headers[headerApplication], - ClientID: headers[headerClientID], - DeveloperEmail: headers[headerDeveloperEmail], - Scopes: strings.Split(headers[headerScope], " "), + Context: rootContext, + AccessToken: headers[headerAccessToken], + APIProducts: strings.Split(headers[headerAPIProducts], ","), + Application: headers[headerApplication], + ClientID: headers[headerClientID], + DeveloperEmail: headers[headerDeveloperEmail], + Scopes: strings.Split(headers[headerScope], " "), + CustomAttributes: headers[headerCustomAttributes], } } diff --git a/server/header_context_test.go b/server/header_context_test.go index e6b1b83..cec0476 100644 --- a/server/header_context_test.go +++ b/server/header_context_test.go @@ -34,13 +34,14 @@ func TestMetadataHeaders(t *testing.T) { "env", } authContext := &auth.Context{ - Context: h, - ClientID: "clientid", - AccessToken: "accesstoken", - Application: "application", - APIProducts: []string{"prod1", "prod2"}, - DeveloperEmail: "dev@google.com", - Scopes: []string{"scope1", "scope2"}, + Context: h, + ClientID: "clientid", + AccessToken: "accesstoken", + Application: "application", + APIProducts: []string{"prod1", "prod2"}, + DeveloperEmail: "dev@google.com", + Scopes: []string{"scope1", "scope2"}, + CustomAttributes: "{\"tier\":\"standard\"}", } api := "api" opts = makeMetadataHeaders(api, authContext, true) @@ -61,6 +62,7 @@ func TestMetadataHeaders(t *testing.T) { equal(headerApplication, authContext.Application) equal(headerClientID, authContext.ClientID) equal(headerDeveloperEmail, authContext.DeveloperEmail) + equal(headerCustomAttributes, authContext.CustomAttributes) equal(headerEnvironment, authContext.Environment()) equal(headerOrganization, authContext.Organization()) equal(headerScope, strings.Join(authContext.Scopes, " ")) @@ -75,6 +77,35 @@ func TestMetadataHeaders(t *testing.T) { } } +func TestCustomAttributeMetadata(t *testing.T) { + h := &multitenantContext{ + &Handler{ + orgName: "org", + envName: "*", + isMultitenant: true, + }, + "env", + } + ac := &auth.Context{ + Context: h, + ClientID: "clientid", + AccessToken: "accesstoken", + Application: "application", + APIProducts: []string{"prod1", "prod2"}, + DeveloperEmail: "dev@google.com", + Scopes: []string{"scope1", "scope2"}, + } + + // Call the function with authorized set to true + headers := makeMetadataHeaders("api", ac, true) + + // Verify that the CustomAttributes header is not included in the headers + for _, h := range headers { + if h.Header.Key == headerCustomAttributes { + t.Errorf("Expected CustomAttributes header to not be included, but found it with value %s", h.Header.Value) + } + } +} func TestMetadataHeadersExceptions(t *testing.T) { opts := makeMetadataHeaders("api", nil, true) if opts != nil { diff --git a/server/metadata_context.go b/server/metadata_context.go index b2bd1ff..af5cf8d 100644 --- a/server/metadata_context.go +++ b/server/metadata_context.go @@ -26,16 +26,17 @@ import ( const ( extAuthzFilterNamespace = "envoy.filters.http.ext_authz" - headerAuthorized = "x-apigee-authorized" - headerAccessToken = "x-apigee-accesstoken" - headerAPI = "x-apigee-api" - headerAPIProducts = "x-apigee-apiproducts" - headerApplication = "x-apigee-application" - headerClientID = "x-apigee-clientid" - headerDeveloperEmail = "x-apigee-developeremail" - headerEnvironment = "x-apigee-environment" - headerOrganization = "x-apigee-organization" - headerScope = "x-apigee-scope" + headerAuthorized = "x-apigee-authorized" + headerAccessToken = "x-apigee-accesstoken" + headerAPI = "x-apigee-api" + headerAPIProducts = "x-apigee-apiproducts" + headerApplication = "x-apigee-application" + headerClientID = "x-apigee-clientid" + headerDeveloperEmail = "x-apigee-developeremail" + headerEnvironment = "x-apigee-environment" + headerOrganization = "x-apigee-organization" + headerScope = "x-apigee-scope" + headerCustomAttributes = "x-apigee-customattributes" ) // encodeExtAuthzMetadata encodes given api and auth context into @@ -56,6 +57,11 @@ func encodeExtAuthzMetadata(api string, ac *auth.Context, authorized bool) *stru headerOrganization: stringValueFrom(ac.Organization()), headerScope: stringValueFrom(strings.Join(ac.Scopes, " ")), } + + if ac.CustomAttributes != "" { + fields[headerCustomAttributes] = stringValueFrom(ac.CustomAttributes) + } + if authorized { fields[headerAuthorized] = stringValueFrom("true") } @@ -119,12 +125,13 @@ func (h *Handler) decodeExtAuthzMetadata(fields map[string]*structpb.Value) (str } return api, &auth.Context{ - Context: rootContext, - AccessToken: fields[headerAccessToken].GetStringValue(), - APIProducts: strings.Split(fields[headerAPIProducts].GetStringValue(), ","), - Application: fields[headerApplication].GetStringValue(), - ClientID: fields[headerClientID].GetStringValue(), - DeveloperEmail: fields[headerDeveloperEmail].GetStringValue(), - Scopes: strings.Split(fields[headerScope].GetStringValue(), " "), + Context: rootContext, + AccessToken: fields[headerAccessToken].GetStringValue(), + APIProducts: strings.Split(fields[headerAPIProducts].GetStringValue(), ","), + Application: fields[headerApplication].GetStringValue(), + ClientID: fields[headerClientID].GetStringValue(), + DeveloperEmail: fields[headerDeveloperEmail].GetStringValue(), + Scopes: strings.Split(fields[headerScope].GetStringValue(), " "), + CustomAttributes: fields[headerCustomAttributes].GetStringValue(), } } diff --git a/server/metadata_context_test.go b/server/metadata_context_test.go index 46a150b..315e65b 100644 --- a/server/metadata_context_test.go +++ b/server/metadata_context_test.go @@ -33,13 +33,14 @@ func TestEncodeMetadata(t *testing.T) { "env", } authContext := &auth.Context{ - Context: h, - ClientID: "clientid", - AccessToken: "accesstoken", - Application: "application", - APIProducts: []string{"prod1", "prod2"}, - DeveloperEmail: "dev@google.com", - Scopes: []string{"scope1", "scope2"}, + Context: h, + ClientID: "clientid", + AccessToken: "accesstoken", + Application: "application", + APIProducts: []string{"prod1", "prod2"}, + DeveloperEmail: "dev@google.com", + Scopes: []string{"scope1", "scope2"}, + CustomAttributes: "{\"tier\":\"standard\"}", } api := "api" metadata := encodeExtAuthzMetadata(api, authContext, true) @@ -63,6 +64,7 @@ func TestEncodeMetadata(t *testing.T) { equal(headerEnvironment, authContext.Environment()) equal(headerOrganization, authContext.Organization()) equal(headerScope, strings.Join(authContext.Scopes, " ")) + equal(headerCustomAttributes, authContext.CustomAttributes) api2, ac2 := h.decodeExtAuthzMetadata(metadata.GetFields()) if api != api2 { @@ -86,13 +88,14 @@ func TestEncodeMetadataAuthorizedField(t *testing.T) { envName: "env", } authContext := &auth.Context{ - Context: h, - ClientID: "clientid", - AccessToken: "accesstoken", - Application: "application", - APIProducts: []string{"prod1", "prod2"}, - DeveloperEmail: "dev@google.com", - Scopes: []string{"scope1", "scope2"}, + Context: h, + ClientID: "clientid", + AccessToken: "accesstoken", + Application: "application", + APIProducts: []string{"prod1", "prod2"}, + DeveloperEmail: "dev@google.com", + Scopes: []string{"scope1", "scope2"}, + CustomAttributes: "", } metadata := encodeExtAuthzMetadata("api", authContext, true)