Skip to content

Commit

Permalink
Merge pull request #2402 from sgayangi/2399-sgayangi-api-key
Browse files Browse the repository at this point in the history
Complete API Key support implementation
  • Loading branch information
CrowleyRajapakse authored Sep 18, 2024
2 parents 5960ba4 + cbfd4ec commit b911021
Show file tree
Hide file tree
Showing 28 changed files with 1,051 additions and 546 deletions.
2 changes: 1 addition & 1 deletion adapter/api/proto/wso2/discovery/api/api.proto
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ message Api {
// bool isMockedApi = 18;
repeated Certificate clientCertificates = 14;
string mutualSSL = 15;
bool applicationSecurity = 16;
map<string, bool> applicationSecurity = 16;
bool transportSecurity = 17;
/// string graphQLSchema = 22;
repeated GraphqlComplexity graphqlComplexityInfo = 23;
Expand Down
1 change: 1 addition & 0 deletions adapter/internal/controlplane/eventPublisher.go
Original file line number Diff line number Diff line change
Expand Up @@ -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:"-"`
}
Expand Down
6 changes: 4 additions & 2 deletions adapter/internal/oasparser/config_generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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),
Expand Down
6 changes: 6 additions & 0 deletions adapter/internal/oasparser/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,9 @@ const (
Production = "Production"
Sandbox = "Sandbox"
)

// Security scheme constants
const (
OAuth2 string = "OAuth2"
APIKey string = "APIKey"
)
32 changes: 22 additions & 10 deletions adapter/internal/oasparser/model/adapter_internal_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
12 changes: 6 additions & 6 deletions adapter/internal/oasparser/model/http_route.go
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand All @@ -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}
Expand All @@ -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,
Expand Down
35 changes: 23 additions & 12 deletions adapter/internal/operator/controllers/dp/api_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -2786,35 +2788,44 @@ 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" {
isMTLSMandatory = true
}
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 {
Expand Down
Loading

0 comments on commit b911021

Please sign in to comment.