diff --git a/adapter/api/proto/wso2/discovery/api/api.proto b/adapter/api/proto/wso2/discovery/api/api.proto index 53842ee71..4e394e4dc 100644 --- a/adapter/api/proto/wso2/discovery/api/api.proto +++ b/adapter/api/proto/wso2/discovery/api/api.proto @@ -51,7 +51,7 @@ message Api { // bool isMockedApi = 18; repeated Certificate clientCertificates = 14; string mutualSSL = 15; - bool applicationSecurity = 16; + map applicationSecurity = 16; bool transportSecurity = 17; /// string graphQLSchema = 22; repeated GraphqlComplexity graphqlComplexityInfo = 23; diff --git a/adapter/internal/controlplane/eventPublisher.go b/adapter/internal/controlplane/eventPublisher.go index 3f760656b..f01f39c50 100644 --- a/adapter/internal/controlplane/eventPublisher.go +++ b/adapter/internal/controlplane/eventPublisher.go @@ -96,6 +96,7 @@ type API struct { SandVhost string `json:"sandVhost"` SecurityScheme []string `json:"securityScheme"` AuthHeader string `json:"authHeader"` + APIKeyHeader string `json:"apiKeyHeader"` Operations []Operation `json:"operations"` APIHash string `json:"-"` } diff --git a/adapter/internal/oasparser/config_generator.go b/adapter/internal/oasparser/config_generator.go index df33b61ae..eb4721e7c 100644 --- a/adapter/internal/oasparser/config_generator.go +++ b/adapter/internal/oasparser/config_generator.go @@ -233,7 +233,7 @@ func GetEnforcerAPI(adapterInternalAPI *model.AdapterInternalAPI, vhost string) // IsMockedApi: isMockedAPI, ClientCertificates: clientCertificates, MutualSSL: adapterInternalAPI.GetMutualSSL(), - ApplicationSecurity: adapterInternalAPI.GetXWSO2ApplicationSecurity(), + ApplicationSecurity: adapterInternalAPI.GetApplicationSecurity(), TransportSecurity: !adapterInternalAPI.GetDisableMtls(), // GraphQLSchema: adapterInternalAPI.GraphQLSchema, // GraphqlComplexityInfo: adapterInternalAPI.GraphQLComplexities.Data.List, @@ -297,7 +297,9 @@ func castAPIAuthenticationsToEnforcerAPIAuthentications(authentication *model.Au SendTokenToUpstream: apiKey.SendTokenToUpstream, }) } - enforcerAuthentication.Apikey = apiKeys + if len(apiKeys) > 0 { + enforcerAuthentication.Apikey = apiKeys + } if authentication.Oauth2 != nil { enforcerAuthentication.Oauth2 = &api.Oauth2{ Header: strings.ToLower(authentication.Oauth2.Header), diff --git a/adapter/internal/oasparser/constants/constants.go b/adapter/internal/oasparser/constants/constants.go index 92ce52d45..38b0c23bc 100644 --- a/adapter/internal/oasparser/constants/constants.go +++ b/adapter/internal/oasparser/constants/constants.go @@ -146,3 +146,9 @@ const ( Production = "Production" Sandbox = "Sandbox" ) + +// Security scheme constants +const ( + OAuth2 string = "OAuth2" + APIKey string = "APIKey" +) diff --git a/adapter/internal/oasparser/model/adapter_internal_api.go b/adapter/internal/oasparser/model/adapter_internal_api.go index a18267d16..56f455820 100644 --- a/adapter/internal/oasparser/model/adapter_internal_api.go +++ b/adapter/internal/oasparser/model/adapter_internal_api.go @@ -66,7 +66,7 @@ type AdapterInternalAPI struct { IsDefaultVersion bool clientCertificates []Certificate mutualSSL string - xWso2ApplicationSecurity bool + applicationSecurity map[string]bool EnvType string backendJWTTokenInfo *BackendJWTTokenInfo apiDefinitionFile []byte @@ -420,14 +420,18 @@ func (adapterInternalAPI *AdapterInternalAPI) SetDisableMtls(disableMtls bool) { adapterInternalAPI.disableMtls = disableMtls } -// SetXWSO2ApplicationSecurity sets the optional or mandatory application security -func (adapterInternalAPI *AdapterInternalAPI) SetXWSO2ApplicationSecurity(applicationSecurity bool) { - adapterInternalAPI.xWso2ApplicationSecurity = applicationSecurity +// SetApplicationSecurity sets the optional or mandatory application security for each security type +// true means mandatory +func (adapterInternalAPI *AdapterInternalAPI) SetApplicationSecurity(key string, value bool) { + if adapterInternalAPI.applicationSecurity == nil { + adapterInternalAPI.applicationSecurity = make(map[string]bool) + } + adapterInternalAPI.applicationSecurity[key] = value } -// GetXWSO2ApplicationSecurity returns true if application security is mandatory, and false if optional -func (adapterInternalAPI *AdapterInternalAPI) GetXWSO2ApplicationSecurity() bool { - return adapterInternalAPI.xWso2ApplicationSecurity +// GetApplicationSecurity returns true if application security is mandatory, and false if optional +func (adapterInternalAPI *AdapterInternalAPI) GetApplicationSecurity() map[string]bool { + return adapterInternalAPI.applicationSecurity } // GetOrganizationID returns OrganizationID @@ -959,10 +963,18 @@ func (adapterInternalAPI *AdapterInternalAPI) SetInfoHTTPRouteCR(httpRoute *gwap } authSpec := utils.SelectPolicy(&authScheme.Spec.Override, &authScheme.Spec.Default, nil, nil) - if authSpec != nil && authSpec.AuthTypes != nil && authSpec.AuthTypes.Oauth2.Required != "" { - adapterInternalAPI.SetXWSO2ApplicationSecurity(authSpec.AuthTypes.Oauth2.Required == "mandatory") + if authSpec != nil && authSpec.AuthTypes != nil { + if authSpec.AuthTypes.OAuth2.Required != "" { + adapterInternalAPI.SetApplicationSecurity(constants.OAuth2, authSpec.AuthTypes.OAuth2.Required == "mandatory") + } else { + adapterInternalAPI.SetApplicationSecurity(constants.OAuth2, true) + } + + if authSpec.AuthTypes.APIKey != nil { + adapterInternalAPI.SetApplicationSecurity(constants.APIKey, authSpec.AuthTypes.APIKey.Required == "mandatory") + } } else { - adapterInternalAPI.SetXWSO2ApplicationSecurity(true) + adapterInternalAPI.SetApplicationSecurity(constants.OAuth2, true) } adapterInternalAPI.disableScopes = disableScopes diff --git a/adapter/internal/oasparser/model/http_route.go b/adapter/internal/oasparser/model/http_route.go index b6db96f7e..feccb11d4 100644 --- a/adapter/internal/oasparser/model/http_route.go +++ b/adapter/internal/oasparser/model/http_route.go @@ -235,12 +235,12 @@ func concatAuthSchemes(schemeUp *dpv1alpha2.Authentication, schemeDown *dpv1alph // tip: use concatScheme method func getSecurity(authScheme *dpv1alpha2.Authentication) *Authentication { authHeader := constants.AuthorizationHeader - if authScheme != nil && authScheme.Spec.Override != nil && authScheme.Spec.Override.AuthTypes != nil && len(authScheme.Spec.Override.AuthTypes.Oauth2.Header) > 0 { - authHeader = authScheme.Spec.Override.AuthTypes.Oauth2.Header + if authScheme != nil && authScheme.Spec.Override != nil && authScheme.Spec.Override.AuthTypes != nil && len(authScheme.Spec.Override.AuthTypes.OAuth2.Header) > 0 { + authHeader = authScheme.Spec.Override.AuthTypes.OAuth2.Header } sendTokenToUpstream := false if authScheme != nil && authScheme.Spec.Override != nil && authScheme.Spec.Override.AuthTypes != nil { - sendTokenToUpstream = authScheme.Spec.Override.AuthTypes.Oauth2.SendTokenToUpstream + sendTokenToUpstream = authScheme.Spec.Override.AuthTypes.OAuth2.SendTokenToUpstream } auth := &Authentication{Disabled: false, Oauth2: &Oauth2{Header: authHeader, SendTokenToUpstream: sendTokenToUpstream}, @@ -250,7 +250,7 @@ func getSecurity(authScheme *dpv1alpha2.Authentication) *Authentication { return &Authentication{Disabled: true} } authFound := false - if authScheme.Spec.Override.AuthTypes != nil && !authScheme.Spec.Override.AuthTypes.Oauth2.Disabled { + if authScheme.Spec.Override.AuthTypes != nil && !authScheme.Spec.Override.AuthTypes.OAuth2.Disabled { authFound = true } else { auth = &Authentication{Disabled: false} @@ -268,9 +268,9 @@ func getSecurity(authScheme *dpv1alpha2.Authentication) *Authentication { authFound = true } if authScheme.Spec.Override.AuthTypes != nil && authScheme.Spec.Override.AuthTypes.APIKey != nil { - authFound = authFound || len(authScheme.Spec.Override.AuthTypes.APIKey) > 0 + authFound = authFound || len(authScheme.Spec.Override.AuthTypes.APIKey.Keys) > 0 var apiKeys []APIKey - for _, apiKey := range authScheme.Spec.Override.AuthTypes.APIKey { + for _, apiKey := range authScheme.Spec.Override.AuthTypes.APIKey.Keys { apiKeys = append(apiKeys, APIKey{ Name: apiKey.Name, In: apiKey.In, diff --git a/adapter/internal/operator/controllers/dp/api_controller.go b/adapter/internal/operator/controllers/dp/api_controller.go index 41cd45e01..c614eaa0e 100644 --- a/adapter/internal/operator/controllers/dp/api_controller.go +++ b/adapter/internal/operator/controllers/dp/api_controller.go @@ -2457,7 +2457,7 @@ func (apiReconciler *APIReconciler) convertAPIStateToAPICp(ctx context.Context, corsPolicy := pickOneCorsForCP(&apiState) vhost := getProdVhost(&apiState) sandVhost := geSandVhost(&apiState) - securityScheme, authHeader := prepareSecuritySchemeForCP(&apiState) + securityScheme, authHeader, apiKeyHeader := prepareSecuritySchemeForCP(&apiState) operations := prepareOperations(&apiState) api := controlplane.API{ APIName: spec.APIName, @@ -2482,6 +2482,7 @@ func (apiReconciler *APIReconciler) convertAPIStateToAPICp(ctx context.Context, AuthHeader: authHeader, Operations: operations, APIHash: apiHash, + APIKeyHeader: apiKeyHeader, } apiCPEvent.API = api apiCPEvent.CRName = apiState.APIDefinition.ObjectMeta.Name @@ -2767,9 +2768,10 @@ func geSandVhost(apiState *synchronizer.APIState) string { return "sandbox.default.gw.wso2.com" } -func prepareSecuritySchemeForCP(apiState *synchronizer.APIState) ([]string, string) { +func prepareSecuritySchemeForCP(apiState *synchronizer.APIState) ([]string, string, string) { var pickedAuth *v1alpha2.Authentication authHeader := "Authorization" + apiKeyHeader := "ApiKey" for _, auth := range apiState.Authentications { pickedAuth = &auth break @@ -2786,13 +2788,13 @@ func prepareSecuritySchemeForCP(apiState *synchronizer.APIState) ([]string, stri authSchemes := []string{} isAuthMandatory := false isMTLSMandatory := false - if authSpec.AuthTypes.Oauth2.Required == "mandatory" { + if authSpec.AuthTypes.OAuth2.Required == "mandatory" { isAuthMandatory = true } - if !authSpec.AuthTypes.Oauth2.Disabled { + if !authSpec.AuthTypes.OAuth2.Disabled { authSchemes = append(authSchemes, "oauth2") - if authSpec.AuthTypes.Oauth2.Header != "" { - authHeader = authSpec.AuthTypes.Oauth2.Header + if authSpec.AuthTypes.OAuth2.Header != "" { + authHeader = authSpec.AuthTypes.OAuth2.Header } } if authSpec.AuthTypes.MutualSSL != nil && authSpec.AuthTypes.MutualSSL.Required == "mandatory" { @@ -2800,21 +2802,30 @@ func prepareSecuritySchemeForCP(apiState *synchronizer.APIState) ([]string, stri } if authSpec.AuthTypes.MutualSSL != nil && !authSpec.AuthTypes.MutualSSL.Disabled { authSchemes = append(authSchemes, "mutualssl") + if isMTLSMandatory { + authSchemes = append(authSchemes, "mutualssl_mandatory") + } else { + authSchemes = append(authSchemes, "mutualssl_optional") + } } - if len(authSpec.AuthTypes.APIKey) > 0 { + if len(authSpec.AuthTypes.APIKey.Keys) > 0 { authSchemes = append(authSchemes, "api_key") + for _, apiKey := range authSpec.AuthTypes.APIKey.Keys { + if apiKey.In == "Header" { + apiKeyHeader = apiKey.Name + } + } } if isAuthMandatory { authSchemes = append(authSchemes, "oauth_basic_auth_api_key_mandatory") + } else { + authSchemes = append(authSchemes, "oauth_basic_auth_api_key_optional") } - if isMTLSMandatory { - authSchemes = append(authSchemes, "mutualssl_mandatory") - } - return authSchemes, authHeader + return authSchemes, authHeader, apiKeyHeader } } } - return []string{"oauth2", "oauth_basic_auth_api_key_mandatory"}, authHeader + return []string{"oauth2", "oauth_basic_auth_api_key_mandatory"}, authHeader, apiKeyHeader } func prepareOperations(apiState *synchronizer.APIState) []controlplane.Operation { diff --git a/adapter/pkg/discovery/api/wso2/discovery/api/api.pb.go b/adapter/pkg/discovery/api/wso2/discovery/api/api.pb.go index 3d12ab090..8f785e8a2 100644 --- a/adapter/pkg/discovery/api/wso2/discovery/api/api.pb.go +++ b/adapter/pkg/discovery/api/wso2/discovery/api/api.pb.go @@ -56,10 +56,10 @@ type Api struct { Vhost string `protobuf:"bytes,12,opt,name=vhost,proto3" json:"vhost,omitempty"` OrganizationId string `protobuf:"bytes,13,opt,name=organizationId,proto3" json:"organizationId,omitempty"` // bool isMockedApi = 18; - ClientCertificates []*Certificate `protobuf:"bytes,14,rep,name=clientCertificates,proto3" json:"clientCertificates,omitempty"` - MutualSSL string `protobuf:"bytes,15,opt,name=mutualSSL,proto3" json:"mutualSSL,omitempty"` - ApplicationSecurity bool `protobuf:"varint,16,opt,name=applicationSecurity,proto3" json:"applicationSecurity,omitempty"` - TransportSecurity bool `protobuf:"varint,17,opt,name=transportSecurity,proto3" json:"transportSecurity,omitempty"` + ClientCertificates []*Certificate `protobuf:"bytes,14,rep,name=clientCertificates,proto3" json:"clientCertificates,omitempty"` + MutualSSL string `protobuf:"bytes,15,opt,name=mutualSSL,proto3" json:"mutualSSL,omitempty"` + ApplicationSecurity map[string]bool `protobuf:"bytes,16,rep,name=applicationSecurity,proto3" json:"applicationSecurity,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` + TransportSecurity bool `protobuf:"varint,17,opt,name=transportSecurity,proto3" json:"transportSecurity,omitempty"` /// string graphQLSchema = 22; GraphqlComplexityInfo []*GraphqlComplexity `protobuf:"bytes,23,rep,name=graphqlComplexityInfo,proto3" json:"graphqlComplexityInfo,omitempty"` SystemAPI bool `protobuf:"varint,24,opt,name=systemAPI,proto3" json:"systemAPI,omitempty"` @@ -209,11 +209,11 @@ func (x *Api) GetMutualSSL() string { return "" } -func (x *Api) GetApplicationSecurity() bool { +func (x *Api) GetApplicationSecurity() map[string]bool { if x != nil { return x.ApplicationSecurity } - return false + return nil } func (x *Api) GetTransportSecurity() bool { @@ -309,7 +309,7 @@ var file_wso2_discovery_api_api_proto_rawDesc = []byte{ 0x2f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x24, 0x77, 0x73, 0x6f, 0x32, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x69, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xad, 0x09, 0x0a, 0x03, 0x41, 0x70, 0x69, 0x12, 0x0e, 0x0a, 0x02, + 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa7, 0x0a, 0x0a, 0x03, 0x41, 0x70, 0x69, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, @@ -343,55 +343,63 @@ var file_wso2_discovery_api_api_proto_rawDesc = []byte{ 0x61, 0x74, 0x65, 0x52, 0x12, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x6d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x53, 0x53, 0x4c, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x75, 0x74, 0x75, - 0x61, 0x6c, 0x53, 0x53, 0x4c, 0x12, 0x30, 0x0a, 0x13, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x18, 0x10, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x13, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, - 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x12, 0x2c, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x6e, 0x73, - 0x70, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x18, 0x11, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x11, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x63, - 0x75, 0x72, 0x69, 0x74, 0x79, 0x12, 0x5b, 0x0a, 0x15, 0x67, 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, - 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x18, 0x17, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x77, 0x73, 0x6f, 0x32, 0x2e, 0x64, 0x69, 0x73, 0x63, - 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x71, - 0x6c, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x74, 0x79, 0x52, 0x15, 0x67, 0x72, 0x61, - 0x70, 0x68, 0x71, 0x6c, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x74, 0x79, 0x49, 0x6e, - 0x66, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x41, 0x50, 0x49, 0x18, - 0x18, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x41, 0x50, 0x49, - 0x12, 0x59, 0x0a, 0x13, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x4a, 0x57, 0x54, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, - 0x77, 0x73, 0x6f, 0x32, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x4a, 0x57, 0x54, 0x54, 0x6f, 0x6b, - 0x65, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x13, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x4a, - 0x57, 0x54, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2c, 0x0a, 0x11, 0x61, - 0x70, 0x69, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, 0x65, - 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x11, 0x61, 0x70, 0x69, 0x44, 0x65, 0x66, 0x69, 0x6e, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x65, 0x6e, 0x76, - 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, - 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x36, 0x0a, 0x16, 0x73, + 0x61, 0x6c, 0x53, 0x53, 0x4c, 0x12, 0x62, 0x0a, 0x13, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x18, 0x10, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x77, 0x73, 0x6f, 0x32, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x70, 0x69, 0x2e, 0x41, 0x70, 0x70, 0x6c, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x52, 0x13, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x12, 0x2c, 0x0a, 0x11, 0x74, 0x72, 0x61, + 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x18, 0x11, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x12, 0x5b, 0x0a, 0x15, 0x67, 0x72, 0x61, 0x70, 0x68, + 0x71, 0x6c, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x74, 0x79, 0x49, 0x6e, 0x66, 0x6f, + 0x18, 0x17, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x77, 0x73, 0x6f, 0x32, 0x2e, 0x64, 0x69, + 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x72, 0x61, 0x70, + 0x68, 0x71, 0x6c, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x74, 0x79, 0x52, 0x15, 0x67, + 0x72, 0x61, 0x70, 0x68, 0x71, 0x6c, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x74, 0x79, + 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x41, 0x50, + 0x49, 0x18, 0x18, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x41, + 0x50, 0x49, 0x12, 0x59, 0x0a, 0x13, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x4a, 0x57, 0x54, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x27, 0x2e, 0x77, 0x73, 0x6f, 0x32, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x4a, 0x57, 0x54, 0x54, + 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x13, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, + 0x64, 0x4a, 0x57, 0x54, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2c, 0x0a, + 0x11, 0x61, 0x70, 0x69, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, + 0x6c, 0x65, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x11, 0x61, 0x70, 0x69, 0x44, 0x65, 0x66, + 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x65, + 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x36, 0x0a, + 0x16, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x73, 0x75, 0x62, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, - 0x18, 0x1d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x77, 0x73, 0x6f, 0x32, 0x2e, 0x64, 0x69, - 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x45, 0x6e, 0x64, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x09, 0x65, 0x6e, 0x64, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x4c, 0x0a, 0x10, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x18, 0x1e, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x20, 0x2e, 0x77, 0x73, 0x6f, 0x32, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, - 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x49, 0x6e, - 0x66, 0x6f, 0x52, 0x10, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x65, 0x63, 0x75, - 0x72, 0x69, 0x74, 0x79, 0x12, 0x3e, 0x0a, 0x0a, 0x61, 0x69, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, - 0x65, 0x72, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x77, 0x73, 0x6f, 0x32, 0x2e, - 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x49, - 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x61, 0x69, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x64, 0x65, 0x72, 0x42, 0x70, 0x0a, 0x23, 0x6f, 0x72, 0x67, 0x2e, 0x77, 0x73, 0x6f, 0x32, - 0x2e, 0x61, 0x70, 0x6b, 0x2e, 0x65, 0x6e, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x72, 0x2e, 0x64, 0x69, - 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x42, 0x08, 0x41, 0x70, 0x69, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6e, 0x76, 0x6f, 0x79, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x67, - 0x6f, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2d, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, - 0x77, 0x73, 0x6f, 0x32, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2f, 0x61, - 0x70, 0x69, 0x3b, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x73, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x77, 0x73, 0x6f, 0x32, 0x2e, + 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x45, 0x6e, + 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x09, 0x65, + 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x4c, 0x0a, 0x10, 0x65, 0x6e, 0x64, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x18, 0x1e, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x77, 0x73, 0x6f, 0x32, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, + 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x10, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x65, + 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x12, 0x3e, 0x0a, 0x0a, 0x61, 0x69, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x77, 0x73, 0x6f, + 0x32, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x41, 0x49, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x61, 0x69, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x1a, 0x46, 0x0a, 0x18, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x70, + 0x0a, 0x23, 0x6f, 0x72, 0x67, 0x2e, 0x77, 0x73, 0x6f, 0x32, 0x2e, 0x61, 0x70, 0x6b, 0x2e, 0x65, + 0x6e, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x72, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, + 0x79, 0x2e, 0x61, 0x70, 0x69, 0x42, 0x08, 0x41, 0x70, 0x69, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, + 0x01, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6e, + 0x76, 0x6f, 0x79, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x67, 0x6f, 0x2d, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2d, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x77, 0x73, 0x6f, 0x32, 0x2f, 0x64, + 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x2f, 0x61, 0x70, 0x69, 0x3b, 0x61, 0x70, 0x69, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -406,30 +414,32 @@ func file_wso2_discovery_api_api_proto_rawDescGZIP() []byte { return file_wso2_discovery_api_api_proto_rawDescData } -var file_wso2_discovery_api_api_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_wso2_discovery_api_api_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_wso2_discovery_api_api_proto_goTypes = []interface{}{ (*Api)(nil), // 0: wso2.discovery.api.Api - (*Resource)(nil), // 1: wso2.discovery.api.Resource - (*Certificate)(nil), // 2: wso2.discovery.api.Certificate - (*GraphqlComplexity)(nil), // 3: wso2.discovery.api.GraphqlComplexity - (*BackendJWTTokenInfo)(nil), // 4: wso2.discovery.api.BackendJWTTokenInfo - (*EndpointCluster)(nil), // 5: wso2.discovery.api.EndpointCluster - (*SecurityInfo)(nil), // 6: wso2.discovery.api.SecurityInfo - (*AIProvider)(nil), // 7: wso2.discovery.api.AIProvider + nil, // 1: wso2.discovery.api.Api.ApplicationSecurityEntry + (*Resource)(nil), // 2: wso2.discovery.api.Resource + (*Certificate)(nil), // 3: wso2.discovery.api.Certificate + (*GraphqlComplexity)(nil), // 4: wso2.discovery.api.GraphqlComplexity + (*BackendJWTTokenInfo)(nil), // 5: wso2.discovery.api.BackendJWTTokenInfo + (*EndpointCluster)(nil), // 6: wso2.discovery.api.EndpointCluster + (*SecurityInfo)(nil), // 7: wso2.discovery.api.SecurityInfo + (*AIProvider)(nil), // 8: wso2.discovery.api.AIProvider } var file_wso2_discovery_api_api_proto_depIdxs = []int32{ - 1, // 0: wso2.discovery.api.Api.resources:type_name -> wso2.discovery.api.Resource - 2, // 1: wso2.discovery.api.Api.clientCertificates:type_name -> wso2.discovery.api.Certificate - 3, // 2: wso2.discovery.api.Api.graphqlComplexityInfo:type_name -> wso2.discovery.api.GraphqlComplexity - 4, // 3: wso2.discovery.api.Api.backendJWTTokenInfo:type_name -> wso2.discovery.api.BackendJWTTokenInfo - 5, // 4: wso2.discovery.api.Api.endpoints:type_name -> wso2.discovery.api.EndpointCluster - 6, // 5: wso2.discovery.api.Api.endpointSecurity:type_name -> wso2.discovery.api.SecurityInfo - 7, // 6: wso2.discovery.api.Api.aiprovider:type_name -> wso2.discovery.api.AIProvider - 7, // [7:7] is the sub-list for method output_type - 7, // [7:7] is the sub-list for method input_type - 7, // [7:7] is the sub-list for extension type_name - 7, // [7:7] is the sub-list for extension extendee - 0, // [0:7] is the sub-list for field type_name + 2, // 0: wso2.discovery.api.Api.resources:type_name -> wso2.discovery.api.Resource + 3, // 1: wso2.discovery.api.Api.clientCertificates:type_name -> wso2.discovery.api.Certificate + 1, // 2: wso2.discovery.api.Api.applicationSecurity:type_name -> wso2.discovery.api.Api.ApplicationSecurityEntry + 4, // 3: wso2.discovery.api.Api.graphqlComplexityInfo:type_name -> wso2.discovery.api.GraphqlComplexity + 5, // 4: wso2.discovery.api.Api.backendJWTTokenInfo:type_name -> wso2.discovery.api.BackendJWTTokenInfo + 6, // 5: wso2.discovery.api.Api.endpoints:type_name -> wso2.discovery.api.EndpointCluster + 7, // 6: wso2.discovery.api.Api.endpointSecurity:type_name -> wso2.discovery.api.SecurityInfo + 8, // 7: wso2.discovery.api.Api.aiprovider:type_name -> wso2.discovery.api.AIProvider + 8, // [8:8] is the sub-list for method output_type + 8, // [8:8] is the sub-list for method input_type + 8, // [8:8] is the sub-list for extension type_name + 8, // [8:8] is the sub-list for extension extendee + 0, // [0:8] is the sub-list for field type_name } func init() { file_wso2_discovery_api_api_proto_init() } @@ -464,7 +474,7 @@ func file_wso2_discovery_api_api_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_wso2_discovery_api_api_proto_rawDesc, NumEnums: 0, - NumMessages: 1, + NumMessages: 2, NumExtensions: 0, NumServices: 0, }, diff --git a/common-controller/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml b/common-controller/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml index f1e5242cf..4bd03db7c 100644 --- a/common-controller/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml +++ b/common-controller/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml @@ -178,10 +178,11 @@ spec: type: object targetRef: description: PolicyTargetReference identifies an API object to apply - policy to. This should be used as part of Policy resources that - can target Gateway API resources. For more information on how this - policy attachment model works, and a sample Policy resource, refer - to the policy attachment documentation for Gateway API. + a direct or inherited policy to. This should be used as part of + Policy resources that can target Gateway API resources. For more + information on how this policy attachment model works, and a sample + Policy resource, refer to the policy attachment documentation for + Gateway API. properties: group: description: Group is the group of the target resource. @@ -252,29 +253,63 @@ spec: apiKey: description: APIKey is to specify the APIKey authentication scheme details - items: - description: APIKeyAuth APIKey Authentication scheme details - properties: - in: - description: In is to specify how the APIKey is passed - to the request - enum: - - Header - - Query - minLength: 1 - type: string - name: - description: Name is the name of the header or query - parameter to be used - minLength: 1 - type: string - sendTokenToUpstream: - description: SendTokenToUpstream is to specify whether - the APIKey should be sent to the upstream - type: boolean - type: object nullable: true - type: array + properties: + keys: + description: APIKeys lists the values for the API Key + authentication + items: + description: APIKey APIKey details + properties: + in: + description: In is to specify how the APIKey is + passed to the request + enum: + - Header + - Query + minLength: 1 + type: string + name: + description: Name is the name of the header or query + parameter to be used + minLength: 1 + type: string + sendTokenToUpstream: + description: SendTokenToUpstream is to specify whether + the APIKey should be sent to the upstream + type: boolean + type: object + type: array + required: + default: optional + description: Required indicates if this authentication + is optional or mandatory + type: string + type: object + jwt: + description: JWT is to specify the JWT authentication scheme + details + properties: + audience: + description: Audience who can invoke a corresponding API + items: + type: string + type: array + disabled: + default: true + description: Disabled is to disable JWT authentication + type: boolean + header: + default: internal-key + description: Header is the header name used to pass the + JWT + minLength: 1 + type: string + sendTokenToUpstream: + description: SendTokenToUpstream is to specify whether + the JWT should be sent to the upstream + type: boolean + type: object mtls: description: MutualSSL is to specify the features and certificates for mutual SSL @@ -339,7 +374,7 @@ spec: type: array type: object oauth2: - description: Oauth2 is to specify the Oauth2 authentication + description: OAuth2 is to specify the OAuth2 authentication scheme details properties: disabled: @@ -351,24 +386,17 @@ spec: description: Header is the header name used to pass the OAuth2 token type: string - sendTokenToUpstream: - description: SendTokenToUpstream is to specify whether - the OAuth2 token should be sent to the upstream - type: boolean - type: object - testConsoleKey: - description: TestConsoleKey is to specify the Test Console - Key authentication scheme details - properties: - header: - default: internal-key - description: Header is the header name used to pass the - Test Console Key - minLength: 1 + required: + default: mandatory + description: Required indicates whether OAuth2 is mandatory + or optional + enum: + - mandatory + - optional type: string sendTokenToUpstream: description: SendTokenToUpstream is to specify whether - the Test Console Key should be sent to the upstream + the OAuth2 token should be sent to the upstream type: boolean type: object type: object @@ -386,29 +414,63 @@ spec: apiKey: description: APIKey is to specify the APIKey authentication scheme details - items: - description: APIKeyAuth APIKey Authentication scheme details - properties: - in: - description: In is to specify how the APIKey is passed - to the request - enum: - - Header - - Query - minLength: 1 - type: string - name: - description: Name is the name of the header or query - parameter to be used - minLength: 1 - type: string - sendTokenToUpstream: - description: SendTokenToUpstream is to specify whether - the APIKey should be sent to the upstream - type: boolean - type: object nullable: true - type: array + properties: + keys: + description: APIKeys lists the values for the API Key + authentication + items: + description: APIKey APIKey details + properties: + in: + description: In is to specify how the APIKey is + passed to the request + enum: + - Header + - Query + minLength: 1 + type: string + name: + description: Name is the name of the header or query + parameter to be used + minLength: 1 + type: string + sendTokenToUpstream: + description: SendTokenToUpstream is to specify whether + the APIKey should be sent to the upstream + type: boolean + type: object + type: array + required: + default: optional + description: Required indicates if this authentication + is optional or mandatory + type: string + type: object + jwt: + description: JWT is to specify the JWT authentication scheme + details + properties: + audience: + description: Audience who can invoke a corresponding API + items: + type: string + type: array + disabled: + default: true + description: Disabled is to disable JWT authentication + type: boolean + header: + default: internal-key + description: Header is the header name used to pass the + JWT + minLength: 1 + type: string + sendTokenToUpstream: + description: SendTokenToUpstream is to specify whether + the JWT should be sent to the upstream + type: boolean + type: object mtls: description: MutualSSL is to specify the features and certificates for mutual SSL @@ -473,7 +535,7 @@ spec: type: array type: object oauth2: - description: Oauth2 is to specify the Oauth2 authentication + description: OAuth2 is to specify the OAuth2 authentication scheme details properties: disabled: @@ -485,24 +547,17 @@ spec: description: Header is the header name used to pass the OAuth2 token type: string - sendTokenToUpstream: - description: SendTokenToUpstream is to specify whether - the OAuth2 token should be sent to the upstream - type: boolean - type: object - testConsoleKey: - description: TestConsoleKey is to specify the Test Console - Key authentication scheme details - properties: - header: - default: internal-key - description: Header is the header name used to pass the - Test Console Key - minLength: 1 + required: + default: mandatory + description: Required indicates whether OAuth2 is mandatory + or optional + enum: + - mandatory + - optional type: string sendTokenToUpstream: description: SendTokenToUpstream is to specify whether - the Test Console Key should be sent to the upstream + the OAuth2 token should be sent to the upstream type: boolean type: object type: object @@ -512,10 +567,11 @@ spec: type: object targetRef: description: PolicyTargetReference identifies an API object to apply - policy to. This should be used as part of Policy resources that - can target Gateway API resources. For more information on how this - policy attachment model works, and a sample Policy resource, refer - to the policy attachment documentation for Gateway API. + a direct or inherited policy to. This should be used as part of + Policy resources that can target Gateway API resources. For more + information on how this policy attachment model works, and a sample + Policy resource, refer to the policy attachment documentation for + Gateway API. properties: group: description: Group is the group of the target resource. diff --git a/common-go-libs/apis/dp/v1alpha1/authentication_conversion.go b/common-go-libs/apis/dp/v1alpha1/authentication_conversion.go index 6843cc7e7..05346c4b3 100644 --- a/common-go-libs/apis/dp/v1alpha1/authentication_conversion.go +++ b/common-go-libs/apis/dp/v1alpha1/authentication_conversion.go @@ -37,20 +37,30 @@ func (src *Authentication) ConvertTo(dstRaw conversion.Hub) error { defaultAuthenticationSpec.Disabled = defaultAuthv1Spec.Disabled if defaultAuthv1Spec.AuthTypes != nil { v1alpha2authTypes := v1alpha2.APIAuth{} - v1alpha2authTypes.Oauth2 = v1alpha2.Oauth2Auth{ + v1alpha2authTypes.OAuth2 = v1alpha2.OAuth2Auth{ Required: "mandatory", Disabled: defaultAuthv1Spec.AuthTypes.Oauth2.Disabled, Header: defaultAuthv1Spec.AuthTypes.Oauth2.Header, SendTokenToUpstream: defaultAuthv1Spec.AuthTypes.Oauth2.SendTokenToUpstream, } - // Convert Oauth2Auth Default to v1alpha2.APIKey : Required field added as optional for APIKey - for _, apiKeyAuth := range defaultAuthv1Spec.AuthTypes.APIKey { - convertedAPIKeyAuth := v1alpha2.APIKeyAuth{ - In: apiKeyAuth.In, - Name: apiKeyAuth.Name, - SendTokenToUpstream: apiKeyAuth.SendTokenToUpstream, + var apiKeys []v1alpha2.APIKey + // Convert APIKeyAuth Default to v1alpha2.APIKey : Required field added as optional for APIKey + if defaultAuthv1Spec.AuthTypes.APIKey != nil { + for _, apiKeyAuth := range defaultAuthv1Spec.AuthTypes.APIKey { + convertedAPIKeyAuth := v1alpha2.APIKey{ + In: apiKeyAuth.In, + Name: apiKeyAuth.Name, + SendTokenToUpstream: apiKeyAuth.SendTokenToUpstream, + } + apiKeys = append(apiKeys, convertedAPIKeyAuth) + } + } + + if len(apiKeys) > 0 { + v1alpha2authTypes.APIKey = &v1alpha2.APIKeyAuth{ + Required: "optional", + Keys: apiKeys, } - v1alpha2authTypes.APIKey = append(v1alpha2authTypes.APIKey, convertedAPIKeyAuth) } if defaultAuthv1Spec.AuthTypes.TestConsoleKey != (TestConsoleKeyAuth{}) { v1alpha2authTypes.JWT = v1alpha2.JWT{ @@ -69,20 +79,30 @@ func (src *Authentication) ConvertTo(dstRaw conversion.Hub) error { overrideAuthenticationSpec.Disabled = overrideAuthv1Spec.Disabled if overrideAuthv1Spec.AuthTypes != nil { v1alpha2authTypes := v1alpha2.APIAuth{} - v1alpha2authTypes.Oauth2 = v1alpha2.Oauth2Auth{ + v1alpha2authTypes.OAuth2 = v1alpha2.OAuth2Auth{ Required: "mandatory", Disabled: overrideAuthv1Spec.AuthTypes.Oauth2.Disabled, Header: overrideAuthv1Spec.AuthTypes.Oauth2.Header, SendTokenToUpstream: overrideAuthv1Spec.AuthTypes.Oauth2.SendTokenToUpstream, } - // Convert Oauth2Auth Default to v1alpha2.APIKey : Required field added as optional for APIKey - for _, apiKeyAuth := range overrideAuthv1Spec.AuthTypes.APIKey { - convertedAPIKeyAuth := v1alpha2.APIKeyAuth{ - In: apiKeyAuth.In, - Name: apiKeyAuth.Name, - SendTokenToUpstream: apiKeyAuth.SendTokenToUpstream, + var apiKeys []v1alpha2.APIKey + // Convert Oauth2Auth Override to v1alpha2.APIKey : Required field added as optional for APIKey + if overrideAuthv1Spec.AuthTypes.APIKey != nil { + for _, apiKeyAuth := range overrideAuthv1Spec.AuthTypes.APIKey { + convertedAPIKeyAuth := v1alpha2.APIKey{ + In: apiKeyAuth.In, + Name: apiKeyAuth.Name, + SendTokenToUpstream: apiKeyAuth.SendTokenToUpstream, + } + apiKeys = append(apiKeys, convertedAPIKeyAuth) + } + } + + if len(apiKeys) > 0 { + v1alpha2authTypes.APIKey = &v1alpha2.APIKeyAuth{ + Required: "optional", + Keys: apiKeys, } - v1alpha2authTypes.APIKey = append(v1alpha2authTypes.APIKey, convertedAPIKeyAuth) } if overrideAuthv1Spec.AuthTypes.TestConsoleKey != (TestConsoleKeyAuth{}) { v1alpha2authTypes.JWT = v1alpha2.JWT{ @@ -116,18 +136,20 @@ func (src *Authentication) ConvertFrom(srcRaw conversion.Hub) error { if defaultAuthv2Spec.AuthTypes != nil { v1alpha1authTypes := APIAuth{} v1alpha1authTypes.Oauth2 = Oauth2Auth{ - Disabled: defaultAuthv2Spec.AuthTypes.Oauth2.Disabled, - Header: defaultAuthv2Spec.AuthTypes.Oauth2.Header, - SendTokenToUpstream: defaultAuthv2Spec.AuthTypes.Oauth2.SendTokenToUpstream, + Disabled: defaultAuthv2Spec.AuthTypes.OAuth2.Disabled, + Header: defaultAuthv2Spec.AuthTypes.OAuth2.Header, + SendTokenToUpstream: defaultAuthv2Spec.AuthTypes.OAuth2.SendTokenToUpstream, } - // Convert Oauth2Auth Default to v1alpha2.APIKey : Required field added as optional for APIKey - for _, apiKeyAuth := range defaultAuthv2Spec.AuthTypes.APIKey { - convertedAPIKeyAuth := APIKeyAuth{ - In: apiKeyAuth.In, - Name: apiKeyAuth.Name, - SendTokenToUpstream: apiKeyAuth.SendTokenToUpstream, + // Convert APIKeyAuth Default to v1alpha2.APIKey : Required field added as optional for APIKey + if defaultAuthv2Spec.AuthTypes.APIKey != nil && defaultAuthv2Spec.AuthTypes.APIKey.Keys != nil { + for _, apiKeyAuth := range defaultAuthv2Spec.AuthTypes.APIKey.Keys { + convertedAPIKeyAuth := APIKeyAuth{ + In: apiKeyAuth.In, + Name: apiKeyAuth.Name, + SendTokenToUpstream: apiKeyAuth.SendTokenToUpstream, + } + v1alpha1authTypes.APIKey = append(v1alpha1authTypes.APIKey, convertedAPIKeyAuth) } - v1alpha1authTypes.APIKey = append(v1alpha1authTypes.APIKey, convertedAPIKeyAuth) } v1alpha1authTypes.TestConsoleKey = TestConsoleKeyAuth{ Header: defaultAuthv2Spec.AuthTypes.JWT.Header, @@ -145,18 +167,20 @@ func (src *Authentication) ConvertFrom(srcRaw conversion.Hub) error { if overrideAuthv2Spec.AuthTypes != nil { v1alpha1authTypes := APIAuth{} v1alpha1authTypes.Oauth2 = Oauth2Auth{ - Disabled: overrideAuthv2Spec.AuthTypes.Oauth2.Disabled, - Header: overrideAuthv2Spec.AuthTypes.Oauth2.Header, - SendTokenToUpstream: overrideAuthv2Spec.AuthTypes.Oauth2.SendTokenToUpstream, + Disabled: overrideAuthv2Spec.AuthTypes.OAuth2.Disabled, + Header: overrideAuthv2Spec.AuthTypes.OAuth2.Header, + SendTokenToUpstream: overrideAuthv2Spec.AuthTypes.OAuth2.SendTokenToUpstream, } // Convert Oauth2Auth Default to v1alpha2.APIKey : Required field added as optional for APIKey - for _, apiKeyAuth := range overrideAuthv2Spec.AuthTypes.APIKey { - convertedAPIKeyAuth := APIKeyAuth{ - In: apiKeyAuth.In, - Name: apiKeyAuth.Name, - SendTokenToUpstream: apiKeyAuth.SendTokenToUpstream, + if overrideAuthv2Spec.AuthTypes.APIKey != nil && overrideAuthv2Spec.AuthTypes.APIKey.Keys != nil { + for _, apiKeyAuth := range overrideAuthv2Spec.AuthTypes.APIKey.Keys { + convertedAPIKeyAuth := APIKeyAuth{ + In: apiKeyAuth.In, + Name: apiKeyAuth.Name, + SendTokenToUpstream: apiKeyAuth.SendTokenToUpstream, + } + v1alpha1authTypes.APIKey = append(v1alpha1authTypes.APIKey, convertedAPIKeyAuth) } - v1alpha1authTypes.APIKey = append(v1alpha1authTypes.APIKey, convertedAPIKeyAuth) } v1alpha1authTypes.TestConsoleKey = TestConsoleKeyAuth{ Header: overrideAuthv2Spec.AuthTypes.JWT.Header, diff --git a/common-go-libs/apis/dp/v1alpha2/authentication_types.go b/common-go-libs/apis/dp/v1alpha2/authentication_types.go index c0eb99d3e..25cb5cb9b 100644 --- a/common-go-libs/apis/dp/v1alpha2/authentication_types.go +++ b/common-go-libs/apis/dp/v1alpha2/authentication_types.go @@ -44,16 +44,16 @@ type AuthSpec struct { // APIAuth Authentication scheme type and details type APIAuth struct { - // Oauth2 is to specify the Oauth2 authentication scheme details + // OAuth2 is to specify the OAuth2 authentication scheme details // // +optional - Oauth2 Oauth2Auth `json:"oauth2,omitempty"` + OAuth2 OAuth2Auth `json:"oauth2,omitempty"` // APIKey is to specify the APIKey authentication scheme details // // +optional // +nullable - APIKey []APIKeyAuth `json:"apiKey,omitempty"` + APIKey *APIKeyAuth `json:"apiKey,omitempty"` // JWT is to specify the JWT authentication scheme details // @@ -118,8 +118,8 @@ type JWT struct { Audience []string `json:"audience,omitempty"` } -// Oauth2Auth OAuth2 Authentication scheme details -type Oauth2Auth struct { +// OAuth2Auth OAuth2 Authentication scheme details +type OAuth2Auth struct { // Required indicates whether OAuth2 is mandatory or optional // +kubebuilder:validation:Enum=mandatory;optional @@ -147,7 +147,18 @@ type Oauth2Auth struct { // APIKeyAuth APIKey Authentication scheme details type APIKeyAuth struct { + // Required indicates if this authentication is optional or mandatory + // + // +kubebuilder:default:=optional + Required string `json:"required,omitempty"` + + // APIKeys lists the values for the API Key authentication + // + Keys []APIKey `json:"keys,omitempty"` +} +// APIKey APIKey details +type APIKey struct { // In is to specify how the APIKey is passed to the request // // +kubebuilder:validation:Enum=Header;Query diff --git a/common-go-libs/apis/dp/v1alpha2/authentication_webhook.go b/common-go-libs/apis/dp/v1alpha2/authentication_webhook.go index 8ddfa2089..c51e44f8f 100644 --- a/common-go-libs/apis/dp/v1alpha2/authentication_webhook.go +++ b/common-go-libs/apis/dp/v1alpha2/authentication_webhook.go @@ -18,8 +18,6 @@ package v1alpha2 import ( - "strings" - constants "github.com/wso2/apk/common-go-libs/constants" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" @@ -71,76 +69,37 @@ func (r *Authentication) ValidateAuthentication() error { if r.Spec.TargetRef.Name == "" { allErrs = append(allErrs, field.Required(field.NewPath("spec").Child("targetRef").Child("name"), "Name is required")) } + if !(r.Spec.TargetRef.Kind == constants.KindAPI || r.Spec.TargetRef.Kind == constants.KindResource) { allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("targetRef").Child("kind"), r.Spec.TargetRef.Kind, "Invalid Kind is provided")) } - var mutualSSL *MutualSSLConfig - var oauth2Auth Oauth2Auth - - isOAuthDisabled := false - isOAuthOptional := false - - isMTLSDisabled := false - isMTLSMandatory := false - if r.Spec.Default != nil && r.Spec.Default.AuthTypes != nil && r.Spec.Default.AuthTypes.MutualSSL != nil { - oauth2Auth = r.Spec.Default.AuthTypes.Oauth2 - mutualSSL = r.Spec.Default.AuthTypes.MutualSSL - - isOAuthDisabled = oauth2Auth.Disabled - isOAuthOptional = oauth2Auth.Required == "optional" - - isMTLSMandatory = strings.ToLower(mutualSSL.Required) == "mandatory" - isMTLSDisabled = mutualSSL.Disabled - - if mutualSSL != nil && r.Spec.TargetRef.Kind != constants.KindAPI { - allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("default").Child("authTypes").Child("oauth2"), r.Spec.Default.AuthTypes.MutualSSL, - "invalid authentication - mTLS can currently only be added for APIs")) - } - - if (mutualSSL == nil || !isMTLSMandatory) && isOAuthDisabled { - allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("default").Child("authTypes").Child("mtls"), r.Spec.Default.AuthTypes, - "invalid authentication configuration - security not enforced for API")) - } - - if isMTLSDisabled && isOAuthOptional { - allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("default").Child("authTypes").Child("mtls"), r.Spec.Default.AuthTypes, - "invalid authentication configuration - security not enforced for API")) + if r.Spec.TargetRef.Kind != constants.KindAPI { + allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("default").Child("authTypes").Child("mtls"), r.Spec.Default.AuthTypes.MutualSSL, + "invalid authentication - mTLS can only be added for APIs")) } + mutualSSL := r.Spec.Default.AuthTypes.MutualSSL if mutualSSL != nil && len(mutualSSL.CertificatesInline) == 0 && len(mutualSSL.ConfigMapRefs) == 0 && len(mutualSSL.SecretRefs) == 0 { allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("default").Child("authTypes").Child("mtls"), r.Spec.Default.AuthTypes.MutualSSL, "invalid mTLS configuration - certificates not provided")) } - } else if r.Spec.Override != nil && r.Spec.Override.AuthTypes != nil && r.Spec.Override.AuthTypes.MutualSSL != nil { - oauth2Auth := r.Spec.Override.AuthTypes.Oauth2 - mutualSSL = r.Spec.Override.AuthTypes.MutualSSL - - isOAuthDisabled = r.Spec.Override.AuthTypes.Oauth2.Disabled - isOAuthOptional = oauth2Auth.Required == "optional" - - isMTLSMandatory = strings.ToLower(mutualSSL.Required) == "mandatory" - isMTLSDisabled = mutualSSL.Disabled - - if mutualSSL != nil && r.Spec.TargetRef.Kind != constants.KindAPI { - allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("override").Child("authTypes").Child("oauth2"), r.Spec.Override.AuthTypes.MutualSSL, - "invalid authentication - mTLS can currently only be added for APIs")) - } + } - if (mutualSSL == nil || !isMTLSMandatory) && isOAuthDisabled { - allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("override").Child("authTypes").Child("mtls"), r.Spec.Override.AuthTypes, - "invalid authentication configuration - security not enforced for API")) + if r.Spec.Override != nil && r.Spec.Override.AuthTypes != nil { + if r.Spec.Override.AuthTypes.MutualSSL != nil { + if r.Spec.TargetRef.Kind != constants.KindAPI { + allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("override").Child("authTypes").Child("mtls"), r.Spec.Override.AuthTypes.MutualSSL, + "invalid authentication - mTLS can currently only be added for APIs")) + } } - if isMTLSDisabled && isOAuthOptional { - allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("override").Child("authTypes").Child("mtls"), r.Spec.Override.AuthTypes, - "invalid authentication configuration - security not enforced for API")) - } + mutualSSL := r.Spec.Override.AuthTypes.MutualSSL if mutualSSL != nil && len(mutualSSL.CertificatesInline) == 0 && len(mutualSSL.ConfigMapRefs) == 0 && len(mutualSSL.SecretRefs) == 0 { - allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("override").Child("authTypes").Child("mtls"), r.Spec.Override.AuthTypes.MutualSSL, + allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("default").Child("authTypes").Child("mtls"), r.Spec.Default.AuthTypes.MutualSSL, "invalid mTLS configuration - certificates not provided")) } } diff --git a/common-go-libs/apis/dp/v1alpha2/zz_generated.deepcopy.go b/common-go-libs/apis/dp/v1alpha2/zz_generated.deepcopy.go index f3ef8ae5f..3fb997640 100644 --- a/common-go-libs/apis/dp/v1alpha2/zz_generated.deepcopy.go +++ b/common-go-libs/apis/dp/v1alpha2/zz_generated.deepcopy.go @@ -58,11 +58,11 @@ func (in *API) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *APIAuth) DeepCopyInto(out *APIAuth) { *out = *in - out.Oauth2 = in.Oauth2 + out.OAuth2 = in.OAuth2 if in.APIKey != nil { in, out := &in.APIKey, &out.APIKey - *out = make([]APIKeyAuth, len(*in)) - copy(*out, *in) + *out = new(APIKeyAuth) + (*in).DeepCopyInto(*out) } in.JWT.DeepCopyInto(&out.JWT) if in.MutualSSL != nil { @@ -82,9 +82,29 @@ func (in *APIAuth) DeepCopy() *APIAuth { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *APIKey) DeepCopyInto(out *APIKey) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIKey. +func (in *APIKey) DeepCopy() *APIKey { + if in == nil { + return nil + } + out := new(APIKey) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *APIKeyAuth) DeepCopyInto(out *APIKeyAuth) { *out = *in + if in.Keys != nil { + in, out := &in.Keys, &out.Keys + *out = make([]APIKey, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIKeyAuth. @@ -1046,16 +1066,16 @@ func (in *MutualSSLConfig) DeepCopy() *MutualSSLConfig { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Oauth2Auth) DeepCopyInto(out *Oauth2Auth) { +func (in *OAuth2Auth) DeepCopyInto(out *OAuth2Auth) { *out = *in } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Oauth2Auth. -func (in *Oauth2Auth) DeepCopy() *Oauth2Auth { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OAuth2Auth. +func (in *OAuth2Auth) DeepCopy() *OAuth2Auth { if in == nil { return nil } - out := new(Oauth2Auth) + out := new(OAuth2Auth) in.DeepCopyInto(out) return out } diff --git a/common-go-libs/config/crd/bases/dp.wso2.com_authentications.yaml b/common-go-libs/config/crd/bases/dp.wso2.com_authentications.yaml index ae400c208..4bd03db7c 100644 --- a/common-go-libs/config/crd/bases/dp.wso2.com_authentications.yaml +++ b/common-go-libs/config/crd/bases/dp.wso2.com_authentications.yaml @@ -253,29 +253,39 @@ spec: apiKey: description: APIKey is to specify the APIKey authentication scheme details - items: - description: APIKeyAuth APIKey Authentication scheme details - properties: - in: - description: In is to specify how the APIKey is passed - to the request - enum: - - Header - - Query - minLength: 1 - type: string - name: - description: Name is the name of the header or query - parameter to be used - minLength: 1 - type: string - sendTokenToUpstream: - description: SendTokenToUpstream is to specify whether - the APIKey should be sent to the upstream - type: boolean - type: object nullable: true - type: array + properties: + keys: + description: APIKeys lists the values for the API Key + authentication + items: + description: APIKey APIKey details + properties: + in: + description: In is to specify how the APIKey is + passed to the request + enum: + - Header + - Query + minLength: 1 + type: string + name: + description: Name is the name of the header or query + parameter to be used + minLength: 1 + type: string + sendTokenToUpstream: + description: SendTokenToUpstream is to specify whether + the APIKey should be sent to the upstream + type: boolean + type: object + type: array + required: + default: optional + description: Required indicates if this authentication + is optional or mandatory + type: string + type: object jwt: description: JWT is to specify the JWT authentication scheme details @@ -364,7 +374,7 @@ spec: type: array type: object oauth2: - description: Oauth2 is to specify the Oauth2 authentication + description: OAuth2 is to specify the OAuth2 authentication scheme details properties: disabled: @@ -404,29 +414,39 @@ spec: apiKey: description: APIKey is to specify the APIKey authentication scheme details - items: - description: APIKeyAuth APIKey Authentication scheme details - properties: - in: - description: In is to specify how the APIKey is passed - to the request - enum: - - Header - - Query - minLength: 1 - type: string - name: - description: Name is the name of the header or query - parameter to be used - minLength: 1 - type: string - sendTokenToUpstream: - description: SendTokenToUpstream is to specify whether - the APIKey should be sent to the upstream - type: boolean - type: object nullable: true - type: array + properties: + keys: + description: APIKeys lists the values for the API Key + authentication + items: + description: APIKey APIKey details + properties: + in: + description: In is to specify how the APIKey is + passed to the request + enum: + - Header + - Query + minLength: 1 + type: string + name: + description: Name is the name of the header or query + parameter to be used + minLength: 1 + type: string + sendTokenToUpstream: + description: SendTokenToUpstream is to specify whether + the APIKey should be sent to the upstream + type: boolean + type: object + type: array + required: + default: optional + description: Required indicates if this authentication + is optional or mandatory + type: string + type: object jwt: description: JWT is to specify the JWT authentication scheme details @@ -515,7 +535,7 @@ spec: type: array type: object oauth2: - description: Oauth2 is to specify the Oauth2 authentication + description: OAuth2 is to specify the OAuth2 authentication scheme details properties: disabled: diff --git a/gateway/enforcer/org.wso2.apk.enforcer.commons/src/main/java/org/wso2/apk/enforcer/commons/model/APIConfig.java b/gateway/enforcer/org.wso2.apk.enforcer.commons/src/main/java/org/wso2/apk/enforcer/commons/model/APIConfig.java index 06a058bb3..0c2fc2579 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer.commons/src/main/java/org/wso2/apk/enforcer/commons/model/APIConfig.java +++ b/gateway/enforcer/org.wso2.apk.enforcer.commons/src/main/java/org/wso2/apk/enforcer/commons/model/APIConfig.java @@ -48,7 +48,7 @@ public class APIConfig { private KeyStore trustStore; private String mutualSSL; private boolean transportSecurity; - private boolean applicationSecurity; + private Map applicationSecurity; private GraphQLSchemaDTO graphQLSchemaDTO; private JWTConfigurationDto jwtConfigurationDto; private boolean systemAPI; @@ -229,7 +229,7 @@ public boolean isTransportSecurity() { * * @return application security optionality */ - public boolean getApplicationSecurity() { + public Map getApplicationSecurity() { return applicationSecurity; } @@ -295,7 +295,7 @@ public static class Builder { private boolean isMockedApi; private KeyStore trustStore; private String mutualSSL; - private boolean applicationSecurity; + private Map applicationSecurity; private GraphQLSchemaDTO graphQLSchemaDTO; private boolean systemAPI; private byte[] apiDefinition; @@ -395,7 +395,7 @@ public Builder mutualSSL(String mutualSSL) { return this; } - public Builder applicationSecurity(boolean applicationSecurity) { + public Builder applicationSecurity(Map applicationSecurity) { this.applicationSecurity = applicationSecurity; return this; } diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/api/GraphQLAPI.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/api/GraphQLAPI.java index 2a3bb9fdc..7f8ac1278 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/api/GraphQLAPI.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/api/GraphQLAPI.java @@ -81,7 +81,7 @@ public String init(Api api) { String apiType = api.getApiType(); List resources = new ArrayList<>(); String mutualSSL = api.getMutualSSL(); - boolean applicationSecurity = api.getApplicationSecurity(); + Map applicationSecurity = api.getApplicationSecurityMap(); EndpointCluster endpoints = Utils.processEndpoints(api.getEndpoints()); EndpointSecurity[] endpointSecurity = APIProcessUtils.convertProtoEndpointSecurity( diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/api/RestAPI.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/api/RestAPI.java index bbbb2ad3e..79e882b7d 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/api/RestAPI.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/api/RestAPI.java @@ -72,7 +72,7 @@ public String init(Api api) { String apiType = api.getApiType(); List resources = new ArrayList<>(); String mutualSSL = api.getMutualSSL(); - boolean applicationSecurity = api.getApplicationSecurity(); + Map applicationSecurity = api.getApplicationSecurityMap(); for (Resource res : api.getResourcesList()) { for (Operation operation : res.getMethodsList()) { diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/constants/APIConstants.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/constants/APIConstants.java index 348f29150..1f658f343 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/constants/APIConstants.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/constants/APIConstants.java @@ -51,7 +51,7 @@ public class APIConstants { public static final String AUTHORIZATION_HEADER_BASIC = "Basic"; public static final String API_SECURITY_OAUTH2 = "OAuth2"; public static final String API_SECURITY_BASIC_AUTH = "basic_auth"; - public static final String SWAGGER_API_KEY_AUTH_TYPE_NAME = "apiKey"; + public static final String API_SECURITY_API_KEY = "\"API Key\""; public static final String SWAGGER_API_KEY_IN_HEADER = "Header"; public static final String SWAGGER_API_KEY_IN_QUERY = "Query"; public static final String API_SECURITY_MUTUAL_SSL_NAME = "mtls"; diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/Api.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/Api.java index a25a00654..508410367 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/Api.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/Api.java @@ -164,9 +164,17 @@ private Api( mutualSSL_ = s; break; } - case 128: { - - applicationSecurity_ = input.readBool(); + case 130: { + if (!((mutable_bitField0_ & 0x00000004) != 0)) { + applicationSecurity_ = com.google.protobuf.MapField.newMapField( + ApplicationSecurityDefaultEntryHolder.defaultEntry); + mutable_bitField0_ |= 0x00000004; + } + com.google.protobuf.MapEntry + applicationSecurity__ = input.readMessage( + ApplicationSecurityDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); + applicationSecurity_.getMutableMap().put( + applicationSecurity__.getKey(), applicationSecurity__.getValue()); break; } case 136: { @@ -175,9 +183,9 @@ private Api( break; } case 186: { - if (!((mutable_bitField0_ & 0x00000004) != 0)) { + if (!((mutable_bitField0_ & 0x00000008) != 0)) { graphqlComplexityInfo_ = new java.util.ArrayList(); - mutable_bitField0_ |= 0x00000004; + mutable_bitField0_ |= 0x00000008; } graphqlComplexityInfo_.add( input.readMessage(org.wso2.apk.enforcer.discovery.api.GraphqlComplexity.parser(), extensionRegistry)); @@ -231,9 +239,9 @@ private Api( break; } case 242: { - if (!((mutable_bitField0_ & 0x00000008) != 0)) { + if (!((mutable_bitField0_ & 0x00000010) != 0)) { endpointSecurity_ = new java.util.ArrayList(); - mutable_bitField0_ |= 0x00000008; + mutable_bitField0_ |= 0x00000010; } endpointSecurity_.add( input.readMessage(org.wso2.apk.enforcer.discovery.api.SecurityInfo.parser(), extensionRegistry)); @@ -273,10 +281,10 @@ private Api( if (((mutable_bitField0_ & 0x00000002) != 0)) { clientCertificates_ = java.util.Collections.unmodifiableList(clientCertificates_); } - if (((mutable_bitField0_ & 0x00000004) != 0)) { + if (((mutable_bitField0_ & 0x00000008) != 0)) { graphqlComplexityInfo_ = java.util.Collections.unmodifiableList(graphqlComplexityInfo_); } - if (((mutable_bitField0_ & 0x00000008) != 0)) { + if (((mutable_bitField0_ & 0x00000010) != 0)) { endpointSecurity_ = java.util.Collections.unmodifiableList(endpointSecurity_); } this.unknownFields = unknownFields.build(); @@ -288,6 +296,18 @@ private Api( return org.wso2.apk.enforcer.discovery.api.ApiProto.internal_static_wso2_discovery_api_Api_descriptor; } + @SuppressWarnings({"rawtypes"}) + @java.lang.Override + protected com.google.protobuf.MapField internalGetMapField( + int number) { + switch (number) { + case 16: + return internalGetApplicationSecurity(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { @@ -837,14 +857,84 @@ public java.lang.String getMutualSSL() { } public static final int APPLICATIONSECURITY_FIELD_NUMBER = 16; - private boolean applicationSecurity_; + private static final class ApplicationSecurityDefaultEntryHolder { + static final com.google.protobuf.MapEntry< + java.lang.String, java.lang.Boolean> defaultEntry = + com.google.protobuf.MapEntry + .newDefaultInstance( + org.wso2.apk.enforcer.discovery.api.ApiProto.internal_static_wso2_discovery_api_Api_ApplicationSecurityEntry_descriptor, + com.google.protobuf.WireFormat.FieldType.STRING, + "", + com.google.protobuf.WireFormat.FieldType.BOOL, + false); + } + private com.google.protobuf.MapField< + java.lang.String, java.lang.Boolean> applicationSecurity_; + private com.google.protobuf.MapField + internalGetApplicationSecurity() { + if (applicationSecurity_ == null) { + return com.google.protobuf.MapField.emptyMapField( + ApplicationSecurityDefaultEntryHolder.defaultEntry); + } + return applicationSecurity_; + } + + public int getApplicationSecurityCount() { + return internalGetApplicationSecurity().getMap().size(); + } /** - * bool applicationSecurity = 16; - * @return The applicationSecurity. + * map<string, bool> applicationSecurity = 16; */ + @java.lang.Override - public boolean getApplicationSecurity() { - return applicationSecurity_; + public boolean containsApplicationSecurity( + java.lang.String key) { + if (key == null) { throw new java.lang.NullPointerException(); } + return internalGetApplicationSecurity().getMap().containsKey(key); + } + /** + * Use {@link #getApplicationSecurityMap()} instead. + */ + @java.lang.Override + @java.lang.Deprecated + public java.util.Map getApplicationSecurity() { + return getApplicationSecurityMap(); + } + /** + * map<string, bool> applicationSecurity = 16; + */ + @java.lang.Override + + public java.util.Map getApplicationSecurityMap() { + return internalGetApplicationSecurity().getMap(); + } + /** + * map<string, bool> applicationSecurity = 16; + */ + @java.lang.Override + + public boolean getApplicationSecurityOrDefault( + java.lang.String key, + boolean defaultValue) { + if (key == null) { throw new java.lang.NullPointerException(); } + java.util.Map map = + internalGetApplicationSecurity().getMap(); + return map.containsKey(key) ? map.get(key) : defaultValue; + } + /** + * map<string, bool> applicationSecurity = 16; + */ + @java.lang.Override + + public boolean getApplicationSecurityOrThrow( + java.lang.String key) { + if (key == null) { throw new java.lang.NullPointerException(); } + java.util.Map map = + internalGetApplicationSecurity().getMap(); + if (!map.containsKey(key)) { + throw new java.lang.IllegalArgumentException(); + } + return map.get(key); } public static final int TRANSPORTSECURITY_FIELD_NUMBER = 17; @@ -1166,9 +1256,12 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) if (!getMutualSSLBytes().isEmpty()) { com.google.protobuf.GeneratedMessageV3.writeString(output, 15, mutualSSL_); } - if (applicationSecurity_ != false) { - output.writeBool(16, applicationSecurity_); - } + com.google.protobuf.GeneratedMessageV3 + .serializeStringMapTo( + output, + internalGetApplicationSecurity(), + ApplicationSecurityDefaultEntryHolder.defaultEntry, + 16); if (transportSecurity_ != false) { output.writeBool(17, transportSecurity_); } @@ -1257,9 +1350,15 @@ public int getSerializedSize() { if (!getMutualSSLBytes().isEmpty()) { size += com.google.protobuf.GeneratedMessageV3.computeStringSize(15, mutualSSL_); } - if (applicationSecurity_ != false) { + for (java.util.Map.Entry entry + : internalGetApplicationSecurity().getMap().entrySet()) { + com.google.protobuf.MapEntry + applicationSecurity__ = ApplicationSecurityDefaultEntryHolder.defaultEntry.newBuilderForType() + .setKey(entry.getKey()) + .setValue(entry.getValue()) + .build(); size += com.google.protobuf.CodedOutputStream - .computeBoolSize(16, applicationSecurity_); + .computeMessageSize(16, applicationSecurity__); } if (transportSecurity_ != false) { size += com.google.protobuf.CodedOutputStream @@ -1345,8 +1444,8 @@ public boolean equals(final java.lang.Object obj) { .equals(other.getClientCertificatesList())) return false; if (!getMutualSSL() .equals(other.getMutualSSL())) return false; - if (getApplicationSecurity() - != other.getApplicationSecurity()) return false; + if (!internalGetApplicationSecurity().equals( + other.internalGetApplicationSecurity())) return false; if (getTransportSecurity() != other.getTransportSecurity()) return false; if (!getGraphqlComplexityInfoList() @@ -1423,9 +1522,10 @@ public int hashCode() { } hash = (37 * hash) + MUTUALSSL_FIELD_NUMBER; hash = (53 * hash) + getMutualSSL().hashCode(); - hash = (37 * hash) + APPLICATIONSECURITY_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( - getApplicationSecurity()); + if (!internalGetApplicationSecurity().getMap().isEmpty()) { + hash = (37 * hash) + APPLICATIONSECURITY_FIELD_NUMBER; + hash = (53 * hash) + internalGetApplicationSecurity().hashCode(); + } hash = (37 * hash) + TRANSPORTSECURITY_FIELD_NUMBER; hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( getTransportSecurity()); @@ -1570,6 +1670,28 @@ public static final class Builder extends return org.wso2.apk.enforcer.discovery.api.ApiProto.internal_static_wso2_discovery_api_Api_descriptor; } + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapField internalGetMapField( + int number) { + switch (number) { + case 16: + return internalGetApplicationSecurity(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapField internalGetMutableMapField( + int number) { + switch (number) { + case 16: + return internalGetMutableApplicationSecurity(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { @@ -1638,13 +1760,12 @@ public Builder clear() { } mutualSSL_ = ""; - applicationSecurity_ = false; - + internalGetMutableApplicationSecurity().clear(); transportSecurity_ = false; if (graphqlComplexityInfoBuilder_ == null) { graphqlComplexityInfo_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000004); + bitField0_ = (bitField0_ & ~0x00000008); } else { graphqlComplexityInfoBuilder_.clear(); } @@ -1670,7 +1791,7 @@ public Builder clear() { } if (endpointSecurityBuilder_ == null) { endpointSecurity_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000008); + bitField0_ = (bitField0_ & ~0x00000010); } else { endpointSecurityBuilder_.clear(); } @@ -1738,12 +1859,13 @@ public org.wso2.apk.enforcer.discovery.api.Api buildPartial() { result.clientCertificates_ = clientCertificatesBuilder_.build(); } result.mutualSSL_ = mutualSSL_; - result.applicationSecurity_ = applicationSecurity_; + result.applicationSecurity_ = internalGetApplicationSecurity(); + result.applicationSecurity_.makeImmutable(); result.transportSecurity_ = transportSecurity_; if (graphqlComplexityInfoBuilder_ == null) { - if (((bitField0_ & 0x00000004) != 0)) { + if (((bitField0_ & 0x00000008) != 0)) { graphqlComplexityInfo_ = java.util.Collections.unmodifiableList(graphqlComplexityInfo_); - bitField0_ = (bitField0_ & ~0x00000004); + bitField0_ = (bitField0_ & ~0x00000008); } result.graphqlComplexityInfo_ = graphqlComplexityInfo_; } else { @@ -1764,9 +1886,9 @@ public org.wso2.apk.enforcer.discovery.api.Api buildPartial() { result.endpoints_ = endpointsBuilder_.build(); } if (endpointSecurityBuilder_ == null) { - if (((bitField0_ & 0x00000008) != 0)) { + if (((bitField0_ & 0x00000010) != 0)) { endpointSecurity_ = java.util.Collections.unmodifiableList(endpointSecurity_); - bitField0_ = (bitField0_ & ~0x00000008); + bitField0_ = (bitField0_ & ~0x00000010); } result.endpointSecurity_ = endpointSecurity_; } else { @@ -1927,9 +2049,8 @@ public Builder mergeFrom(org.wso2.apk.enforcer.discovery.api.Api other) { mutualSSL_ = other.mutualSSL_; onChanged(); } - if (other.getApplicationSecurity() != false) { - setApplicationSecurity(other.getApplicationSecurity()); - } + internalGetMutableApplicationSecurity().mergeFrom( + other.internalGetApplicationSecurity()); if (other.getTransportSecurity() != false) { setTransportSecurity(other.getTransportSecurity()); } @@ -1937,7 +2058,7 @@ public Builder mergeFrom(org.wso2.apk.enforcer.discovery.api.Api other) { if (!other.graphqlComplexityInfo_.isEmpty()) { if (graphqlComplexityInfo_.isEmpty()) { graphqlComplexityInfo_ = other.graphqlComplexityInfo_; - bitField0_ = (bitField0_ & ~0x00000004); + bitField0_ = (bitField0_ & ~0x00000008); } else { ensureGraphqlComplexityInfoIsMutable(); graphqlComplexityInfo_.addAll(other.graphqlComplexityInfo_); @@ -1950,7 +2071,7 @@ public Builder mergeFrom(org.wso2.apk.enforcer.discovery.api.Api other) { graphqlComplexityInfoBuilder_.dispose(); graphqlComplexityInfoBuilder_ = null; graphqlComplexityInfo_ = other.graphqlComplexityInfo_; - bitField0_ = (bitField0_ & ~0x00000004); + bitField0_ = (bitField0_ & ~0x00000008); graphqlComplexityInfoBuilder_ = com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? getGraphqlComplexityInfoFieldBuilder() : null; @@ -1982,7 +2103,7 @@ public Builder mergeFrom(org.wso2.apk.enforcer.discovery.api.Api other) { if (!other.endpointSecurity_.isEmpty()) { if (endpointSecurity_.isEmpty()) { endpointSecurity_ = other.endpointSecurity_; - bitField0_ = (bitField0_ & ~0x00000008); + bitField0_ = (bitField0_ & ~0x00000010); } else { ensureEndpointSecurityIsMutable(); endpointSecurity_.addAll(other.endpointSecurity_); @@ -1995,7 +2116,7 @@ public Builder mergeFrom(org.wso2.apk.enforcer.discovery.api.Api other) { endpointSecurityBuilder_.dispose(); endpointSecurityBuilder_ = null; endpointSecurity_ = other.endpointSecurity_; - bitField0_ = (bitField0_ & ~0x00000008); + bitField0_ = (bitField0_ & ~0x00000010); endpointSecurityBuilder_ = com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? getEndpointSecurityFieldBuilder() : null; @@ -3487,34 +3608,131 @@ public Builder setMutualSSLBytes( return this; } - private boolean applicationSecurity_ ; + private com.google.protobuf.MapField< + java.lang.String, java.lang.Boolean> applicationSecurity_; + private com.google.protobuf.MapField + internalGetApplicationSecurity() { + if (applicationSecurity_ == null) { + return com.google.protobuf.MapField.emptyMapField( + ApplicationSecurityDefaultEntryHolder.defaultEntry); + } + return applicationSecurity_; + } + private com.google.protobuf.MapField + internalGetMutableApplicationSecurity() { + onChanged();; + if (applicationSecurity_ == null) { + applicationSecurity_ = com.google.protobuf.MapField.newMapField( + ApplicationSecurityDefaultEntryHolder.defaultEntry); + } + if (!applicationSecurity_.isMutable()) { + applicationSecurity_ = applicationSecurity_.copy(); + } + return applicationSecurity_; + } + + public int getApplicationSecurityCount() { + return internalGetApplicationSecurity().getMap().size(); + } /** - * bool applicationSecurity = 16; - * @return The applicationSecurity. + * map<string, bool> applicationSecurity = 16; */ + @java.lang.Override - public boolean getApplicationSecurity() { - return applicationSecurity_; + public boolean containsApplicationSecurity( + java.lang.String key) { + if (key == null) { throw new java.lang.NullPointerException(); } + return internalGetApplicationSecurity().getMap().containsKey(key); } /** - * bool applicationSecurity = 16; - * @param value The applicationSecurity to set. - * @return This builder for chaining. + * Use {@link #getApplicationSecurityMap()} instead. */ - public Builder setApplicationSecurity(boolean value) { - - applicationSecurity_ = value; - onChanged(); - return this; + @java.lang.Override + @java.lang.Deprecated + public java.util.Map getApplicationSecurity() { + return getApplicationSecurityMap(); } /** - * bool applicationSecurity = 16; - * @return This builder for chaining. + * map<string, bool> applicationSecurity = 16; */ + @java.lang.Override + + public java.util.Map getApplicationSecurityMap() { + return internalGetApplicationSecurity().getMap(); + } + /** + * map<string, bool> applicationSecurity = 16; + */ + @java.lang.Override + + public boolean getApplicationSecurityOrDefault( + java.lang.String key, + boolean defaultValue) { + if (key == null) { throw new java.lang.NullPointerException(); } + java.util.Map map = + internalGetApplicationSecurity().getMap(); + return map.containsKey(key) ? map.get(key) : defaultValue; + } + /** + * map<string, bool> applicationSecurity = 16; + */ + @java.lang.Override + + public boolean getApplicationSecurityOrThrow( + java.lang.String key) { + if (key == null) { throw new java.lang.NullPointerException(); } + java.util.Map map = + internalGetApplicationSecurity().getMap(); + if (!map.containsKey(key)) { + throw new java.lang.IllegalArgumentException(); + } + return map.get(key); + } + public Builder clearApplicationSecurity() { + internalGetMutableApplicationSecurity().getMutableMap() + .clear(); + return this; + } + /** + * map<string, bool> applicationSecurity = 16; + */ + + public Builder removeApplicationSecurity( + java.lang.String key) { + if (key == null) { throw new java.lang.NullPointerException(); } + internalGetMutableApplicationSecurity().getMutableMap() + .remove(key); + return this; + } + /** + * Use alternate mutation accessors instead. + */ + @java.lang.Deprecated + public java.util.Map + getMutableApplicationSecurity() { + return internalGetMutableApplicationSecurity().getMutableMap(); + } + /** + * map<string, bool> applicationSecurity = 16; + */ + public Builder putApplicationSecurity( + java.lang.String key, + boolean value) { + if (key == null) { throw new java.lang.NullPointerException(); } - applicationSecurity_ = false; - onChanged(); + internalGetMutableApplicationSecurity().getMutableMap() + .put(key, value); + return this; + } + /** + * map<string, bool> applicationSecurity = 16; + */ + + public Builder putAllApplicationSecurity( + java.util.Map values) { + internalGetMutableApplicationSecurity().getMutableMap() + .putAll(values); return this; } @@ -3552,9 +3770,9 @@ public Builder clearTransportSecurity() { private java.util.List graphqlComplexityInfo_ = java.util.Collections.emptyList(); private void ensureGraphqlComplexityInfoIsMutable() { - if (!((bitField0_ & 0x00000004) != 0)) { + if (!((bitField0_ & 0x00000008) != 0)) { graphqlComplexityInfo_ = new java.util.ArrayList(graphqlComplexityInfo_); - bitField0_ |= 0x00000004; + bitField0_ |= 0x00000008; } } @@ -3748,7 +3966,7 @@ public Builder addAllGraphqlComplexityInfo( public Builder clearGraphqlComplexityInfo() { if (graphqlComplexityInfoBuilder_ == null) { graphqlComplexityInfo_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000004); + bitField0_ = (bitField0_ & ~0x00000008); onChanged(); } else { graphqlComplexityInfoBuilder_.clear(); @@ -3853,7 +4071,7 @@ public org.wso2.apk.enforcer.discovery.api.GraphqlComplexity.Builder addGraphqlC graphqlComplexityInfoBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< org.wso2.apk.enforcer.discovery.api.GraphqlComplexity, org.wso2.apk.enforcer.discovery.api.GraphqlComplexity.Builder, org.wso2.apk.enforcer.discovery.api.GraphqlComplexityOrBuilder>( graphqlComplexityInfo_, - ((bitField0_ & 0x00000004) != 0), + ((bitField0_ & 0x00000008) != 0), getParentForChildren(), isClean()); graphqlComplexityInfo_ = null; @@ -4274,9 +4492,9 @@ public org.wso2.apk.enforcer.discovery.api.EndpointClusterOrBuilder getEndpoints private java.util.List endpointSecurity_ = java.util.Collections.emptyList(); private void ensureEndpointSecurityIsMutable() { - if (!((bitField0_ & 0x00000008) != 0)) { + if (!((bitField0_ & 0x00000010) != 0)) { endpointSecurity_ = new java.util.ArrayList(endpointSecurity_); - bitField0_ |= 0x00000008; + bitField0_ |= 0x00000010; } } @@ -4426,7 +4644,7 @@ public Builder addAllEndpointSecurity( public Builder clearEndpointSecurity() { if (endpointSecurityBuilder_ == null) { endpointSecurity_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000008); + bitField0_ = (bitField0_ & ~0x00000010); onChanged(); } else { endpointSecurityBuilder_.clear(); @@ -4503,7 +4721,7 @@ public org.wso2.apk.enforcer.discovery.api.SecurityInfo.Builder addEndpointSecur endpointSecurityBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< org.wso2.apk.enforcer.discovery.api.SecurityInfo, org.wso2.apk.enforcer.discovery.api.SecurityInfo.Builder, org.wso2.apk.enforcer.discovery.api.SecurityInfoOrBuilder>( endpointSecurity_, - ((bitField0_ & 0x00000008) != 0), + ((bitField0_ & 0x00000010) != 0), getParentForChildren(), isClean()); endpointSecurity_ = null; diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/ApiOrBuilder.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/ApiOrBuilder.java index 2e13b4b2c..437851660 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/ApiOrBuilder.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/ApiOrBuilder.java @@ -220,10 +220,38 @@ org.wso2.apk.enforcer.discovery.api.CertificateOrBuilder getClientCertificatesOr getMutualSSLBytes(); /** - * bool applicationSecurity = 16; - * @return The applicationSecurity. + * map<string, bool> applicationSecurity = 16; */ - boolean getApplicationSecurity(); + int getApplicationSecurityCount(); + /** + * map<string, bool> applicationSecurity = 16; + */ + boolean containsApplicationSecurity( + java.lang.String key); + /** + * Use {@link #getApplicationSecurityMap()} instead. + */ + @java.lang.Deprecated + java.util.Map + getApplicationSecurity(); + /** + * map<string, bool> applicationSecurity = 16; + */ + java.util.Map + getApplicationSecurityMap(); + /** + * map<string, bool> applicationSecurity = 16; + */ + + boolean getApplicationSecurityOrDefault( + java.lang.String key, + boolean defaultValue); + /** + * map<string, bool> applicationSecurity = 16; + */ + + boolean getApplicationSecurityOrThrow( + java.lang.String key); /** * bool transportSecurity = 17; diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/ApiProto.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/ApiProto.java index 36bd21b3b..8f168c4d2 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/ApiProto.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/discovery/api/ApiProto.java @@ -19,6 +19,11 @@ public static void registerAllExtensions( static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internal_static_wso2_discovery_api_Api_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_wso2_discovery_api_Api_ApplicationSecurityEntry_descriptor; + static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_wso2_discovery_api_Api_ApplicationSecurityEntry_fieldAccessorTable; public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { @@ -36,7 +41,7 @@ public static void registerAllExtensions( "luster.proto\032&wso2/discovery/api/securit" + "y_info.proto\032 wso2/discovery/api/graphql" + ".proto\032$wso2/discovery/api/ai_provider.p" + - "roto\"\274\006\n\003Api\022\n\n\002id\030\001 \001(\t\022\r\n\005title\030\002 \001(\t\022" + + "roto\"\252\007\n\003Api\022\n\n\002id\030\001 \001(\t\022\r\n\005title\030\002 \001(\t\022" + "\017\n\007version\030\003 \001(\t\022\017\n\007apiType\030\004 \001(\t\022\036\n\026dis" + "ableAuthentications\030\005 \001(\010\022\025\n\rdisableScop" + "es\030\006 \001(\010\022\017\n\007envType\030\007 \001(\t\022/\n\tresources\030\010" + @@ -45,21 +50,24 @@ public static void registerAllExtensions( "leState\030\013 \001(\t\022\r\n\005vhost\030\014 \001(\t\022\026\n\016organiza" + "tionId\030\r \001(\t\022;\n\022clientCertificates\030\016 \003(\013" + "2\037.wso2.discovery.api.Certificate\022\021\n\tmut" + - "ualSSL\030\017 \001(\t\022\033\n\023applicationSecurity\030\020 \001(" + - "\010\022\031\n\021transportSecurity\030\021 \001(\010\022D\n\025graphqlC" + - "omplexityInfo\030\027 \003(\0132%.wso2.discovery.api" + - ".GraphqlComplexity\022\021\n\tsystemAPI\030\030 \001(\010\022D\n" + - "\023backendJWTTokenInfo\030\031 \001(\0132\'.wso2.discov" + - "ery.api.BackendJWTTokenInfo\022\031\n\021apiDefini" + - "tionFile\030\032 \001(\014\022\023\n\013environment\030\033 \001(\t\022\036\n\026s" + - "ubscriptionValidation\030\034 \001(\010\0226\n\tendpoints" + - "\030\035 \001(\0132#.wso2.discovery.api.EndpointClus" + - "ter\022:\n\020endpointSecurity\030\036 \003(\0132 .wso2.dis" + - "covery.api.SecurityInfo\0222\n\naiprovider\030\037 " + - "\001(\0132\036.wso2.discovery.api.AIProviderBp\n#o" + - "rg.wso2.apk.enforcer.discovery.apiB\010ApiP" + - "rotoP\001Z=github.com/envoyproxy/go-control" + - "-plane/wso2/discovery/api;apib\006proto3" + "ualSSL\030\017 \001(\t\022M\n\023applicationSecurity\030\020 \003(" + + "\01320.wso2.discovery.api.Api.ApplicationSe" + + "curityEntry\022\031\n\021transportSecurity\030\021 \001(\010\022D" + + "\n\025graphqlComplexityInfo\030\027 \003(\0132%.wso2.dis" + + "covery.api.GraphqlComplexity\022\021\n\tsystemAP" + + "I\030\030 \001(\010\022D\n\023backendJWTTokenInfo\030\031 \001(\0132\'.w" + + "so2.discovery.api.BackendJWTTokenInfo\022\031\n" + + "\021apiDefinitionFile\030\032 \001(\014\022\023\n\013environment\030" + + "\033 \001(\t\022\036\n\026subscriptionValidation\030\034 \001(\010\0226\n" + + "\tendpoints\030\035 \001(\0132#.wso2.discovery.api.En" + + "dpointCluster\022:\n\020endpointSecurity\030\036 \003(\0132" + + " .wso2.discovery.api.SecurityInfo\0222\n\naip" + + "rovider\030\037 \001(\0132\036.wso2.discovery.api.AIPro" + + "vider\032:\n\030ApplicationSecurityEntry\022\013\n\003key" + + "\030\001 \001(\t\022\r\n\005value\030\002 \001(\010:\0028\001Bp\n#org.wso2.ap" + + "k.enforcer.discovery.apiB\010ApiProtoP\001Z=gi" + + "thub.com/envoyproxy/go-control-plane/wso" + + "2/discovery/api;apib\006proto3" }; descriptor = com.google.protobuf.Descriptors.FileDescriptor .internalBuildGeneratedFileFrom(descriptorData, @@ -78,6 +86,12 @@ public static void registerAllExtensions( com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( internal_static_wso2_discovery_api_Api_descriptor, new java.lang.String[] { "Id", "Title", "Version", "ApiType", "DisableAuthentications", "DisableScopes", "EnvType", "Resources", "BasePath", "Tier", "ApiLifeCycleState", "Vhost", "OrganizationId", "ClientCertificates", "MutualSSL", "ApplicationSecurity", "TransportSecurity", "GraphqlComplexityInfo", "SystemAPI", "BackendJWTTokenInfo", "ApiDefinitionFile", "Environment", "SubscriptionValidation", "Endpoints", "EndpointSecurity", "Aiprovider", }); + internal_static_wso2_discovery_api_Api_ApplicationSecurityEntry_descriptor = + internal_static_wso2_discovery_api_Api_descriptor.getNestedTypes().get(0); + internal_static_wso2_discovery_api_Api_ApplicationSecurityEntry_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_wso2_discovery_api_Api_ApplicationSecurityEntry_descriptor, + new java.lang.String[] { "Key", "Value", }); org.wso2.apk.enforcer.discovery.api.ResourceProto.getDescriptor(); org.wso2.apk.enforcer.discovery.api.CertificateProto.getDescriptor(); org.wso2.apk.enforcer.discovery.api.BackendJWTTokenInfoProto.getDescriptor(); diff --git a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/AuthFilter.java b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/AuthFilter.java index 3982396f8..e3e2fed11 100644 --- a/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/AuthFilter.java +++ b/gateway/enforcer/org.wso2.apk.enforcer/src/main/java/org/wso2/apk/enforcer/security/AuthFilter.java @@ -18,6 +18,7 @@ package org.wso2.apk.enforcer.security; import java.util.stream.Collectors; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.wso2.apk.enforcer.commons.Filter; @@ -57,7 +58,8 @@ public class AuthFilter implements Filter { private List authenticators = new ArrayList<>(); private static final Logger log = LogManager.getLogger(AuthFilter.class); private boolean isMutualSSLMandatory; - private boolean isOAuthBasicAuthMandatory; + private boolean isOAuth2Mandatory; + private boolean isAPIKeyMandatory; @Override public void init(APIConfig apiConfig, Map configProperties) { @@ -67,10 +69,16 @@ public void init(APIConfig apiConfig, Map configProperties) { private void initializeAuthenticators(APIConfig apiConfig) { // TODO: Check security schema and add relevant authenticators. boolean isMutualSSLProtected = false; + boolean isAPIKeyProtected = false; isMutualSSLMandatory = false; // Set security conditions - isOAuthBasicAuthMandatory = apiConfig.getApplicationSecurity(); + Map securityMaps = apiConfig.getApplicationSecurity(); + isOAuth2Mandatory = securityMaps.getOrDefault("OAuth2", true); + isAPIKeyProtected = securityMaps.containsKey("APIKey"); + if (isAPIKeyProtected) { + isAPIKeyMandatory = securityMaps.getOrDefault("APIKey", false); + } if (!Objects.isNull(apiConfig.getMutualSSL())) { if (apiConfig.isTransportSecurity()) { @@ -85,7 +93,6 @@ private void initializeAuthenticators(APIConfig apiConfig) { } } - // TODO: Set authenticator for isBasicAuthProtected if (isMutualSSLProtected) { Authenticator mtlsAuthenticator = new MTLSAuthenticator(); authenticators.add(mtlsAuthenticator); @@ -98,8 +105,11 @@ private void initializeAuthenticators(APIConfig apiConfig) { Authenticator oauthAuthenticator = new Oauth2Authenticator(jwtConfigurationDto, isGatewayTokenCacheEnabled); authenticators.add(oauthAuthenticator); - APIKeyAuthenticator apiKeyAuthenticator = new APIKeyAuthenticator(jwtConfigurationDto); - authenticators.add(apiKeyAuthenticator); + + if (isAPIKeyProtected){ + APIKeyAuthenticator apiKeyAuthenticator = new APIKeyAuthenticator(jwtConfigurationDto); + authenticators.add(apiKeyAuthenticator); + } Authenticator jwtAuthenticator = new JWTAuthenticator(jwtConfigurationDto, isGatewayTokenCacheEnabled); authenticators.add(jwtAuthenticator); @@ -153,10 +163,11 @@ public boolean handleRequest(RequestContext requestContext) { break; } // Check if the failed authentication is a mandatory application level security - if (isOAuthBasicAuthMandatory && !authenticator.getName() - .contains(APIConstants.API_SECURITY_MUTUAL_SSL_NAME)) { + if (!authenticator.getName() + .contains(APIConstants.API_SECURITY_MUTUAL_SSL_NAME) && (isAPIKeyMandatory || isOAuth2Mandatory)) { authenticated = false; } + } } if (authenticated) { @@ -190,19 +201,19 @@ private AuthenticationResponse authenticate(Authenticator authenticator, Request boolean isApplicationSecurityDisabled = requestContext.getMatchedResourcePaths().get(0) .getAuthenticationConfig().isDisabled(); // proceed to the next authenticator only if application security is enabled and - // if OAuth2 is mandatory + // is mandatory return new AuthenticationResponse(true, isMutualSSLMandatory, - !isApplicationSecurityDisabled && isOAuthBasicAuthMandatory); + !isApplicationSecurityDisabled && (isOAuth2Mandatory || isAPIKeyMandatory)); } else { if (isMutualSSLMandatory) { log.debug("Mandatory mTLS authentication was failed for the request: {} , API: {}:{}, " + - "APIUUID: {} ", + "APIUUID: {} ", requestContext.getMatchedResourcePaths().get(0).getPath(), requestContext.getMatchedAPI().getName(), requestContext.getMatchedAPI().getVersion(), requestContext.getMatchedAPI().getUuid()); } else { log.debug("Optional mTLS authentication was failed for the request: {} , API: {}:{}, " + - "APIUUID: {} ", + "APIUUID: {} ", requestContext.getMatchedResourcePaths().get(0).getPath(), requestContext.getMatchedAPI().getName(), requestContext.getMatchedAPI().getVersion(), requestContext.getMatchedAPI().getUuid()); @@ -212,7 +223,7 @@ private AuthenticationResponse authenticate(Authenticator authenticator, Request } // for all authenticators other than mTLS } else if (authenticate.isAuthenticated()) { - return new AuthenticationResponse(true, isOAuthBasicAuthMandatory, false); + return new AuthenticationResponse(true, isOAuth2Mandatory && isAPIKeyMandatory, false); } } catch (APISecurityException e) { // TODO: (VirajSalaka) provide the error code properly based on exception (401, @@ -224,7 +235,7 @@ private AuthenticationResponse authenticate(Authenticator authenticator, Request continueToNextAuth = false; } return new AuthenticationResponse(false, - isOAuthBasicAuthMandatory || isMutualSSLMandatory, continueToNextAuth); + isOAuth2Mandatory || isMutualSSLMandatory, continueToNextAuth); } private String getAuthenticatorsChallengeString() { diff --git a/helm-charts/templates/crds/dp.wso2.com_authentications.yaml b/helm-charts/templates/crds/dp.wso2.com_authentications.yaml index 3fe87f259..024fac232 100644 --- a/helm-charts/templates/crds/dp.wso2.com_authentications.yaml +++ b/helm-charts/templates/crds/dp.wso2.com_authentications.yaml @@ -265,29 +265,39 @@ spec: apiKey: description: APIKey is to specify the APIKey authentication scheme details - items: - description: APIKeyAuth APIKey Authentication scheme details - properties: - in: - description: In is to specify how the APIKey is passed - to the request - enum: - - Header - - Query - minLength: 1 - type: string - name: - description: Name is the name of the header or query - parameter to be used - minLength: 1 - type: string - sendTokenToUpstream: - description: SendTokenToUpstream is to specify whether - the APIKey should be sent to the upstream - type: boolean - type: object nullable: true - type: array + properties: + keys: + description: APIKeys lists the values for the API Key + authentication + items: + description: APIKey APIKey details + properties: + in: + description: In is to specify how the APIKey is + passed to the request + enum: + - Header + - Query + minLength: 1 + type: string + name: + description: Name is the name of the header or query + parameter to be used + minLength: 1 + type: string + sendTokenToUpstream: + description: SendTokenToUpstream is to specify whether + the APIKey should be sent to the upstream + type: boolean + type: object + type: array + required: + default: optional + description: Required indicates if this authentication + is optional or mandatory + type: string + type: object jwt: description: JWT is to specify the JWT authentication scheme details @@ -376,7 +386,7 @@ spec: type: array type: object oauth2: - description: Oauth2 is to specify the Oauth2 authentication + description: OAuth2 is to specify the OAuth2 authentication scheme details properties: disabled: @@ -416,29 +426,39 @@ spec: apiKey: description: APIKey is to specify the APIKey authentication scheme details - items: - description: APIKeyAuth APIKey Authentication scheme details - properties: - in: - description: In is to specify how the APIKey is passed - to the request - enum: - - Header - - Query - minLength: 1 - type: string - name: - description: Name is the name of the header or query - parameter to be used - minLength: 1 - type: string - sendTokenToUpstream: - description: SendTokenToUpstream is to specify whether - the APIKey should be sent to the upstream - type: boolean - type: object nullable: true - type: array + properties: + keys: + description: APIKeys lists the values for the API Key + authentication + items: + description: APIKey APIKey details + properties: + in: + description: In is to specify how the APIKey is + passed to the request + enum: + - Header + - Query + minLength: 1 + type: string + name: + description: Name is the name of the header or query + parameter to be used + minLength: 1 + type: string + sendTokenToUpstream: + description: SendTokenToUpstream is to specify whether + the APIKey should be sent to the upstream + type: boolean + type: object + type: array + required: + default: optional + description: Required indicates if this authentication + is optional or mandatory + type: string + type: object jwt: description: JWT is to specify the JWT authentication scheme details @@ -527,7 +547,7 @@ spec: type: array type: object oauth2: - description: Oauth2 is to specify the Oauth2 authentication + description: OAuth2 is to specify the OAuth2 authentication scheme details properties: disabled: @@ -559,10 +579,11 @@ spec: type: object targetRef: description: PolicyTargetReference identifies an API object to apply - policy to. This should be used as part of Policy resources that - can target Gateway API resources. For more information on how this - policy attachment model works, and a sample Policy resource, refer - to the policy attachment documentation for Gateway API. + a direct or inherited policy to. This should be used as part of + Policy resources that can target Gateway API resources. For more + information on how this policy attachment model works, and a sample + Policy resource, refer to the policy attachment documentation for + Gateway API. properties: group: description: Group is the group of the target resource. diff --git a/runtime/config-deployer-service/ballerina/APIClient.bal b/runtime/config-deployer-service/ballerina/APIClient.bal index 8dbfba067..1469775e0 100644 --- a/runtime/config-deployer-service/ballerina/APIClient.bal +++ b/runtime/config-deployer-service/ballerina/APIClient.bal @@ -348,41 +348,45 @@ public class APIClient { map createdEndpointMap, commons:Organization organization) returns error? { map authenticationMap = {}; model:AuthenticationExtensionType authTypes = {}; - boolean isOAuthDisabled = false; - boolean isOAuthOptional = false; - boolean isMTLSMandatory = false; - boolean isMTLSDisabled = false; foreach AuthenticationRequest authentication in authentications { if authentication.authType == "OAuth2" { OAuth2Authentication oauth2Authentication = check authentication.cloneWithType(OAuth2Authentication); - isOAuthDisabled = !oauth2Authentication.enabled; - isOAuthOptional = oauth2Authentication.required == "optional"; authTypes.oauth2 = {header: oauth2Authentication.headerName, sendTokenToUpstream: oauth2Authentication.sendTokenToUpstream, disabled: !oauth2Authentication.enabled, required: oauth2Authentication.required}; } else if authentication.authType == "JWT" { JWTAuthentication jwtAuthentication = check authentication.cloneWithType(JWTAuthentication); authTypes.jwt = {header: jwtAuthentication.headerName, sendTokenToUpstream: jwtAuthentication.sendTokenToUpstream, disabled: !jwtAuthentication.enabled, audience: jwtAuthentication.audience}; - } else if authentication.authType == "APIKey" && authentication is APIKeyAuthentication { - APIKeyAuthentication apiKeyAuthentication = check authentication.cloneWithType(APIKeyAuthentication); - model:APIKey[] apiKeys = []; - - if apiKeyAuthentication.headerEnable { - apiKeys.push({'in: "Header", name: apiKeyAuthentication.headerName, sendTokenToUpstream: apiKeyAuthentication.sendTokenToUpstream}); + } else if authentication.authType == "APIKey" { + APIKeyAuthentication apiKeyAuthentication; + if authentication is OAuth2Authentication { + apiKeyAuthentication = { + enabled: authentication.enabled, + required: authentication.required, + sendTokenToUpstream: authentication.sendTokenToUpstream, + headerName: authentication.headerName, + headerEnable: authentication.headerEnable + }; + } else { + apiKeyAuthentication = check authentication.cloneWithType(APIKeyAuthentication); } - if apiKeyAuthentication.queryParamEnable { - apiKeys.push({'in: "Query", name: apiKeyAuthentication.queryParamName, sendTokenToUpstream: apiKeyAuthentication.sendTokenToUpstream}); + model:APIKey[] apiKeys = []; + if apiKeyAuthentication.enabled { + if apiKeyAuthentication.headerEnable { + apiKeys.push({'in: "Header", name: apiKeyAuthentication.headerName, sendTokenToUpstream: apiKeyAuthentication.sendTokenToUpstream}); + } + if apiKeyAuthentication.queryParamEnable { + apiKeys.push({'in: "Query", name: apiKeyAuthentication.queryParamName, sendTokenToUpstream: apiKeyAuthentication.sendTokenToUpstream}); + } + authTypes.apiKey = { + required: apiKeyAuthentication.required, + keys: apiKeys + }; } - authTypes.apiKey = apiKeys; } else if authentication.authType == "mTLS" { MTLSAuthentication mtlsAuthentication = check authentication.cloneWithType(MTLSAuthentication); - isMTLSMandatory = mtlsAuthentication.required == "mandatory"; - isMTLSDisabled = !mtlsAuthentication.enabled; - if ((isOAuthDisabled && (!isMTLSMandatory || isMTLSDisabled)) || (isOAuthOptional && isMTLSDisabled)) { - log:printError("Invalid authtypes provided: one of mTLS or OAuth2 has to be enabled and mandatory"); - return e909019(); - } authTypes.mtls = {disabled: !mtlsAuthentication.enabled, configMapRefs: mtlsAuthentication.certificates, required: mtlsAuthentication.required}; } } + log:printDebug("Auth Types:" + authTypes.toString()); string[] keys = createdEndpointMap.keys(); log:printDebug("createdEndpointMap.keys:" + createdEndpointMap.keys().toString()); diff --git a/runtime/config-deployer-service/ballerina/modules/model/Authentication.bal b/runtime/config-deployer-service/ballerina/modules/model/Authentication.bal index ad876f71b..912bd3706 100644 --- a/runtime/config-deployer-service/ballerina/modules/model/Authentication.bal +++ b/runtime/config-deployer-service/ballerina/modules/model/Authentication.bal @@ -36,9 +36,9 @@ public type AuthenticationData record { public type AuthenticationExtensionType record { OAuth2Authentication oauth2?; - APIKey[] apiKey = []; MutualSSL mtls?; JWTAuthentication jwt?; + APIKeyAuthentication apiKey?; }; public type MutualSSL record { @@ -63,6 +63,11 @@ public type JWTAuthentication record { string[] audience = []; }; +public type APIKeyAuthentication record { + string required; + APIKey[] keys = []; +}; + public type InternalKey record { string header?; string sendTokenToUpstream?; diff --git a/runtime/config-deployer-service/ballerina/tests/APIClientTest.bal b/runtime/config-deployer-service/ballerina/tests/APIClientTest.bal index 8f7f4997b..3bc80e414 100644 --- a/runtime/config-deployer-service/ballerina/tests/APIClientTest.bal +++ b/runtime/config-deployer-service/ballerina/tests/APIClientTest.bal @@ -1,8 +1,10 @@ -import ballerina/test; import config_deployer_service.model; import config_deployer_service.org.wso2.apk.config.model as runtimeModels; -import wso2/apk_common_lib; + import ballerina/io; +import ballerina/test; + +import wso2/apk_common_lib; import wso2/apk_common_lib as commons; commons:Organization organization = { @@ -505,18 +507,21 @@ public function testAPIKeyOnlyEnable() returns error? { model:AuthenticationData expectedAuthenticationData = { disabled: false, authTypes: { - apiKey: [ - { - 'in: "Header", - name: "apiKey", - sendTokenToUpstream: false - }, - { - 'in: "Query", - name: "apiKey", - sendTokenToUpstream: false - } - ] + apiKey: { + required: "optional", + keys: [ + { + 'in: "Header", + name: "apiKey", + sendTokenToUpstream: false + }, + { + 'in: "Query", + name: "apiKey", + sendTokenToUpstream: false + } + ] + } } }; @@ -545,18 +550,22 @@ public function testAPIKeyAndJWTEnable() returns error? { model:AuthenticationData expectedAuthenticationData = { disabled: false, authTypes: { - apiKey: [ - { - 'in: "Header", - name: "apiKey", - sendTokenToUpstream: false - }, - { - 'in: "Query", - name: "apiKey", - sendTokenToUpstream: false - } - ], + apiKey: { + required: "optional", + keys: + [ + { + 'in: "Header", + name: "apiKey", + sendTokenToUpstream: false + }, + { + 'in: "Query", + name: "apiKey", + sendTokenToUpstream: false + } + ] + }, oauth2: { required: "mandatory", disabled: false, diff --git a/runtime/config-deployer-service/ballerina/types.bal b/runtime/config-deployer-service/ballerina/types.bal index 225df34ad..dee63aa89 100644 --- a/runtime/config-deployer-service/ballerina/types.bal +++ b/runtime/config-deployer-service/ballerina/types.bal @@ -514,6 +514,7 @@ public type RetryPolicy record { # Configuration for API Key Auth Type # +# + required - If APIKey is optional or mandatory # + sendTokenToUpstream - Enables sending the API Key to upstream. # + headerName - Name of APIKey header. # + queryParamName - Name of APIKey query parameter. @@ -521,6 +522,7 @@ public type RetryPolicy record { # + queryParamEnable - Enable sending API Key as a query param. public type APIKeyAuthentication record {| *Authentication; + string required = "optional"; boolean sendTokenToUpstream = false; string headerName = "apiKey"; string queryParamName = "apiKey"; diff --git a/test/cucumber-tests/src/test/resources/tests/api/MTLSwithOAuth2Mandatory.feature b/test/cucumber-tests/src/test/resources/tests/api/MTLSwithOAuth2Mandatory.feature index 1f6cc149a..6cd8fb4fe 100644 --- a/test/cucumber-tests/src/test/resources/tests/api/MTLSwithOAuth2Mandatory.feature +++ b/test/cucumber-tests/src/test/resources/tests/api/MTLSwithOAuth2Mandatory.feature @@ -118,7 +118,6 @@ Feature: Test mTLS between client and gateway with client certificate sent in he When I undeploy the API whose ID is "mtls-optional-oauth2-enabled" Then the response status code should be 202 - # Disabled scenarios # mTLS optional OAuth2 disabled Scenario: Test optional mTLS and disabled OAuth2 with a valid client certificate in header Given The system is ready @@ -126,16 +125,64 @@ Feature: Test mTLS between client and gateway with client certificate sent in he When I use the APK Conf file "artifacts/apk-confs/mtls/mtls_optional_oauth2_disabled.apk-conf" And the definition file "artifacts/definitions/employees_api.json" And make the API deployment request - Then the response status code should be 406 + Then the response status code should be 200 + Then I set headers + | Authorization | bearer invalidToken | + And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body "" + And I eventually receive 401 response code, not accepting + | 200 | + Then I set headers + | Authorization | bearer ${accessToken} | + And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body "" + And I eventually receive 401 response code, not accepting + | 200 | + Then I set headers + | X-WSO2-CLIENT-CERTIFICATE | ${clientCertificate} | + And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body "" + And I eventually receive 200 response code, not accepting + | 401 | + + Scenario: Undeploy API + Given The system is ready + And I have a valid subscription + When I undeploy the API whose ID is "mtls-optional-oauth2-disabled" + Then the response status code should be 202 # mTLS disabled OAuth2 optional Scenario: Test an API with mTLS disabled and OAuth2 optional Given The system is ready - And I have a valid subscription + And I have a valid token with a client certificate "config-map-1.txt" When I use the APK Conf file "artifacts/apk-confs/mtls/mtls_disabled_oauth2_optional.apk-conf" And the definition file "artifacts/definitions/employees_api.json" And make the API deployment request - Then the response status code should be 406 + Then the response status code should be 200 + Then I set headers + | Authorization | bearer ${accessToken} | + | X-WSO2-CLIENT-CERTIFICATE | ${clientCertificate} | + And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body "" + And I eventually receive 200 response code, not accepting + | 401 | + Then I set headers + | Authorization | bearer ${accessToken} | + And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body "" + And I eventually receive 200 response code, not accepting + | 401 | + Then I set headers + | X-WSO2-CLIENT-CERTIFICATE | ${clientCertificate} | + And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body "" + And I eventually receive 200 response code, not accepting + | 401 | + Then I set headers + | Authorization | bearer invalidToken | + And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body "" + And I eventually receive 401 response code, not accepting + | 200 | + + Scenario: Undeploy API + Given The system is ready + And I have a valid subscription + When I undeploy the API whose ID is "mtls-disabled-oauth2-optional" + Then the response status code should be 202 # mTLS disabled OAuth2 disabled Scenario: Test an API with mTLS disabled and OAuth2 disabled @@ -144,7 +191,21 @@ Feature: Test mTLS between client and gateway with client certificate sent in he When I use the APK Conf file "artifacts/apk-confs/mtls/mtls_disabled_oauth2_disabled.apk-conf" And the definition file "artifacts/definitions/employees_api.json" And make the API deployment request - Then the response status code should be 406 + Then the response status code should be 200 + Then I set headers + | Authorization | bearer invalidToken | + And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body "" + And I eventually receive 200 response code, not accepting + | 401 | + And I send "GET" request to "https://default.gw.wso2.com:9095/mtls/3.14/employee/" with body "" + And I eventually receive 200 response code, not accepting + | 401 | + + Scenario: Undeploy API + Given The system is ready + And I have a valid subscription + When I undeploy the API whose ID is "mtls-disabled-oauth2-disabled" + Then the response status code should be 202 # mTLS mandatory OAuth2 disabled Scenario: Test mandatory mTLS and disabled OAuth2 with a valid client certificate in header