diff --git a/adapter/internal/oasparser/model/http_route.go b/adapter/internal/oasparser/model/http_route.go index 6c996c39b8..df0ee7d0d9 100644 --- a/adapter/internal/oasparser/model/http_route.go +++ b/adapter/internal/oasparser/model/http_route.go @@ -35,8 +35,8 @@ import ( // ResourceParams contains httproute related parameters type ResourceParams struct { - AuthSchemes map[string]dpv1alpha1.Authentication - ResourceAuthSchemes map[string]dpv1alpha1.Authentication + AuthSchemes map[string]dpv1alpha2.Authentication + ResourceAuthSchemes map[string]dpv1alpha2.Authentication APIPolicies map[string]dpv1alpha2.APIPolicy ResourceAPIPolicies map[string]dpv1alpha2.APIPolicy InterceptorServiceMapping map[string]dpv1alpha1.InterceptorService @@ -58,7 +58,7 @@ func (swagger *AdapterInternalAPI) SetInfoHTTPRouteCR(httpRoute *gwapiv1b1.HTTPR disableScopes := true config := config.ReadConfigs() - var authScheme *dpv1alpha1.Authentication + var authScheme *dpv1alpha2.Authentication if outputAuthScheme != nil { authScheme = *outputAuthScheme } @@ -545,9 +545,9 @@ func concatAPIPolicies(schemeUp *dpv1alpha2.APIPolicy, schemeDown *dpv1alpha2.AP return &apiPolicy } -func concatAuthSchemes(schemeUp *dpv1alpha1.Authentication, schemeDown *dpv1alpha1.Authentication) *dpv1alpha1.Authentication { - finalAuth := dpv1alpha1.Authentication{ - Spec: dpv1alpha1.AuthenticationSpec{}, +func concatAuthSchemes(schemeUp *dpv1alpha2.Authentication, schemeDown *dpv1alpha2.Authentication) *dpv1alpha2.Authentication { + finalAuth := dpv1alpha2.Authentication{ + Spec: dpv1alpha2.AuthenticationSpec{}, } if schemeUp != nil && schemeDown != nil { finalAuth.Spec.Override = utils.SelectPolicy(&schemeUp.Spec.Override, &schemeUp.Spec.Default, &schemeDown.Spec.Override, &schemeDown.Spec.Default) @@ -562,7 +562,7 @@ func concatAuthSchemes(schemeUp *dpv1alpha1.Authentication, schemeDown *dpv1alph // getSecurity returns security schemes and it's definitions with flag to indicate if security is disabled // make sure authscheme only has external service override values. (i.e. empty default values) // tip: use concatScheme method -func getSecurity(authScheme *dpv1alpha1.Authentication) *Authentication { +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 diff --git a/adapter/internal/operator/PROJECT b/adapter/internal/operator/PROJECT index 8960d64abc..efd003c288 100644 --- a/adapter/internal/operator/PROJECT +++ b/adapter/internal/operator/PROJECT @@ -133,6 +133,15 @@ resources: kind: API path: github.com/wso2/apk/adapter/internal/operator/apis/dp/v1alpha2 version: v1alpha2 +- api: + crdVersion: v1 + namespaced: true + controller: true + domain: wso2.com + group: dp + kind: Authentication + path: github.com/wso2/apk/adapter/internal/operator/apis/dp/v1alpha2 + version: v1alpha2 - api: crdVersion: v1 namespaced: true diff --git a/adapter/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml b/adapter/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml index 1dbc523a5b..f1e5242cf4 100644 --- a/adapter/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml +++ b/adapter/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml @@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.9.2 - creationTimestamp: null + controller-gen.kubebuilder.io/version: v0.12.0 name: authentications.dp.wso2.com spec: group: dp.wso2.com @@ -16,6 +15,214 @@ spec: scope: Namespaced versions: - name: v1alpha1 + schema: + openAPIV3Schema: + description: Authentication is the Schema for the authentications API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: AuthenticationSpec defines the desired state of Authentication + properties: + default: + description: AuthSpec specification of the authentication service + properties: + authTypes: + description: AuthTypes is to specify the authentication scheme + types and details + properties: + 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 + oauth2: + description: Oauth2 is to specify the Oauth2 authentication + scheme details + properties: + disabled: + default: false + description: Disabled is to disable OAuth2 authentication + type: boolean + header: + default: authorization + 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 + type: string + sendTokenToUpstream: + description: SendTokenToUpstream is to specify whether + the Test Console Key should be sent to the upstream + type: boolean + type: object + type: object + disabled: + description: Disabled is to disable all authentications + type: boolean + type: object + override: + description: AuthSpec specification of the authentication service + properties: + authTypes: + description: AuthTypes is to specify the authentication scheme + types and details + properties: + 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 + oauth2: + description: Oauth2 is to specify the Oauth2 authentication + scheme details + properties: + disabled: + default: false + description: Disabled is to disable OAuth2 authentication + type: boolean + header: + default: authorization + 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 + type: string + sendTokenToUpstream: + description: SendTokenToUpstream is to specify whether + the Test Console Key should be sent to the upstream + type: boolean + type: object + type: object + disabled: + description: Disabled is to disable all authentications + type: boolean + 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. + properties: + group: + description: Group is the group of the target resource. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the target resource. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the target resource. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: Namespace is the namespace of the referent. When + unspecified, the local namespace is inferred. Even when policy + targets a resource in a different namespace, it MUST only apply + to traffic originating from the same namespace as the policy. + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - name + type: object + type: object + status: + description: AuthenticationStatus defines the observed state of Authentication + type: object + type: object + served: true + storage: false + subresources: + status: {} + - name: v1alpha2 schema: openAPIV3Schema: description: Authentication is the Schema for the authentications API @@ -103,6 +310,7 @@ spec: description: Disabled is to disable mTLS authentication type: boolean required: + default: optional description: Required indicates whether mutualSSL is mandatory or optional enum: @@ -129,8 +337,6 @@ spec: - name type: object type: array - required: - - required type: object oauth2: description: Oauth2 is to specify the Oauth2 authentication @@ -238,6 +444,7 @@ spec: description: Disabled is to disable mTLS authentication type: boolean required: + default: optional description: Required indicates whether mutualSSL is mandatory or optional enum: @@ -264,8 +471,6 @@ spec: - name type: object type: array - required: - - required type: object oauth2: description: Oauth2 is to specify the Oauth2 authentication diff --git a/adapter/internal/operator/config/webhook/manifests.yaml b/adapter/internal/operator/config/webhook/manifests.yaml index 474f6dc2f4..411ed6ee86 100644 --- a/adapter/internal/operator/config/webhook/manifests.yaml +++ b/adapter/internal/operator/config/webhook/manifests.yaml @@ -2,7 +2,6 @@ apiVersion: admissionregistration.k8s.io/v1 kind: MutatingWebhookConfiguration metadata: - creationTimestamp: null name: mutating-webhook-configuration webhooks: - admissionReviewVersions: @@ -11,14 +10,14 @@ webhooks: service: name: webhook-service namespace: system - path: /mutate-dp-wso2-com-v1alpha1-api + path: /mutate-dp-wso2-com-v1alpha2-api failurePolicy: Fail name: mapi.kb.io rules: - apiGroups: - dp.wso2.com apiVersions: - - v1alpha1 + - v1alpha2 operations: - CREATE - UPDATE @@ -35,6 +34,46 @@ webhooks: failurePolicy: Fail name: mapipolicy.kb.io rules: + - apiGroups: + - dp.wso2.com + apiVersions: + - v1alpha2 + operations: + - CREATE + - UPDATE + resources: + - apipolicies + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /mutate-dp-wso2-com-v1alpha2-authentication + failurePolicy: Fail + name: mauthentication.kb.io + rules: + - apiGroups: + - dp.wso2.com + apiVersions: + - v1alpha2 + operations: + - CREATE + - UPDATE + resources: + - authentications + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /mutate-dp-wso2-com-v1alpha1-apipolicy + failurePolicy: Fail + name: mapipolicy.kb.io + rules: - apiGroups: - dp.wso2.com apiVersions: @@ -149,7 +188,6 @@ webhooks: apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: - creationTimestamp: null name: validating-webhook-configuration webhooks: - admissionReviewVersions: @@ -158,14 +196,14 @@ webhooks: service: name: webhook-service namespace: system - path: /validate-dp-wso2-com-v1alpha1-api + path: /validate-dp-wso2-com-v1alpha2-api failurePolicy: Fail name: vapi.kb.io rules: - apiGroups: - dp.wso2.com apiVersions: - - v1alpha1 + - v1alpha2 operations: - CREATE - UPDATE @@ -182,6 +220,46 @@ webhooks: failurePolicy: Fail name: vapipolicy.kb.io rules: + - apiGroups: + - dp.wso2.com + apiVersions: + - v1alpha2 + operations: + - CREATE + - UPDATE + resources: + - apipolicies + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-dp-wso2-com-v1alpha2-authentication + failurePolicy: Fail + name: vauthentication.kb.io + rules: + - apiGroups: + - dp.wso2.com + apiVersions: + - v1alpha2 + operations: + - CREATE + - UPDATE + resources: + - authentications + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-dp-wso2-com-v1alpha1-apipolicy + failurePolicy: Fail + name: vapipolicy.kb.io + rules: - apiGroups: - dp.wso2.com apiVersions: diff --git a/adapter/internal/operator/controllers/dp/api_controller.go b/adapter/internal/operator/controllers/dp/api_controller.go index c49297a7b0..b9992ae070 100644 --- a/adapter/internal/operator/controllers/dp/api_controller.go +++ b/adapter/internal/operator/controllers/dp/api_controller.go @@ -143,7 +143,7 @@ func NewAPIController(mgr manager.Manager, operatorDataStore *synchronizer.Opera return err } - if err := c.Watch(source.Kind(mgr.GetCache(), &dpv1alpha1.Authentication{}), handler.EnqueueRequestsFromMapFunc(apiReconciler.getAPIsForAuthentication), + if err := c.Watch(source.Kind(mgr.GetCache(), &dpv1alpha2.Authentication{}), handler.EnqueueRequestsFromMapFunc(apiReconciler.getAPIsForAuthentication), predicates...); err != nil { loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2616, logging.BLOCKER, "Error watching Authentication resources: %v", err)) return err @@ -547,10 +547,10 @@ func (apiReconciler *APIReconciler) concatHTTPRoutes(ctx context.Context, httpRo } func (apiReconciler *APIReconciler) getAuthenticationsForAPI(ctx context.Context, - api dpv1alpha2.API) (map[string]dpv1alpha1.Authentication, error) { + api dpv1alpha2.API) (map[string]dpv1alpha2.Authentication, error) { nameSpacedName := utils.NamespacedName(&api).String() - authentications := make(map[string]dpv1alpha1.Authentication) - authenticationList := &dpv1alpha1.AuthenticationList{} + authentications := make(map[string]dpv1alpha2.Authentication) + authenticationList := &dpv1alpha2.AuthenticationList{} if err := apiReconciler.client.List(ctx, authenticationList, &k8client.ListOptions{ FieldSelector: fields.OneTermEqualSelector(apiAuthenticationIndex, nameSpacedName), }); err != nil { @@ -609,10 +609,10 @@ func (apiReconciler *APIReconciler) getScopesForHTTPRoute(ctx context.Context, } func (apiReconciler *APIReconciler) getAuthenticationsForResources(ctx context.Context, - api dpv1alpha2.API) (map[string]dpv1alpha1.Authentication, error) { + api dpv1alpha2.API) (map[string]dpv1alpha2.Authentication, error) { nameSpacedName := utils.NamespacedName(&api).String() - authentications := make(map[string]dpv1alpha1.Authentication) - authenticationList := &dpv1alpha1.AuthenticationList{} + authentications := make(map[string]dpv1alpha2.Authentication) + authenticationList := &dpv1alpha2.AuthenticationList{} if err := apiReconciler.client.List(ctx, authenticationList, &k8client.ListOptions{ FieldSelector: fields.OneTermEqualSelector(apiAuthenticationResourceIndex, nameSpacedName), }); err != nil { @@ -768,8 +768,8 @@ func (apiReconciler *APIReconciler) getAPIPolicyChildrenRefs(ctx context.Context } func (apiReconciler *APIReconciler) resolveAuthentications(ctx context.Context, - authentications map[string]dpv1alpha1.Authentication) (*dpv1alpha1.MutualSSL, error) { - resolvedMutualSSL := dpv1alpha1.MutualSSL{} + authentications map[string]dpv1alpha2.Authentication) (*dpv1alpha2.MutualSSL, error) { + resolvedMutualSSL := dpv1alpha2.MutualSSL{} for _, authentication := range authentications { err := utils.GetResolvedMutualSSL(ctx, apiReconciler.client, authentication, &resolvedMutualSSL) if err != nil { @@ -901,7 +901,7 @@ func (apiReconciler *APIReconciler) getAPIsForSecret(ctx context.Context, obj k8 // from Authentication objects. If the changes are done for an API stored in the Operator Data store, // a new reconcile event will be created and added to the reconcile event queue. func (apiReconciler *APIReconciler) getAPIsForAuthentication(ctx context.Context, obj k8client.Object) []reconcile.Request { - authentication, ok := obj.(*dpv1alpha1.Authentication) + authentication, ok := obj.(*dpv1alpha2.Authentication) if !ok { loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2622, logging.TRIVIAL, "Unexpected object type, bypassing reconciliation: %v", authentication)) return []reconcile.Request{} @@ -909,13 +909,6 @@ func (apiReconciler *APIReconciler) getAPIsForAuthentication(ctx context.Context requests := []reconcile.Request{} - // todo(amali) move this validation to validation hook - if !(authentication.Spec.TargetRef.Kind == constants.KindAPI || authentication.Spec.TargetRef.Kind == constants.KindResource) { - loggers.LoggerAPKOperator.Errorf("Unsupported target ref kind : %s was given for authentication: %s", - authentication.Spec.TargetRef.Kind, authentication.Name) - return requests - } - namespace, err := utils.ValidateAndRetrieveNamespace((*gwapiv1b1.Namespace)(authentication.Spec.TargetRef.Namespace), authentication.Namespace) if err != nil { @@ -1306,9 +1299,9 @@ func addIndexes(ctx context.Context, mgr manager.Manager) error { } // authentication to API indexer - if err := mgr.GetFieldIndexer().IndexField(ctx, &dpv1alpha1.Authentication{}, apiAuthenticationIndex, + if err := mgr.GetFieldIndexer().IndexField(ctx, &dpv1alpha2.Authentication{}, apiAuthenticationIndex, func(rawObj k8client.Object) []string { - authentication := rawObj.(*dpv1alpha1.Authentication) + authentication := rawObj.(*dpv1alpha2.Authentication) var apis []string if authentication.Spec.TargetRef.Kind == constants.KindAPI { @@ -1332,9 +1325,9 @@ func addIndexes(ctx context.Context, mgr manager.Manager) error { } // Secret to Authentication indexer - if err := mgr.GetFieldIndexer().IndexField(ctx, &dpv1alpha1.Authentication{}, secretAuthentication, + if err := mgr.GetFieldIndexer().IndexField(ctx, &dpv1alpha2.Authentication{}, secretAuthentication, func(rawObj k8client.Object) []string { - authentication := rawObj.(*dpv1alpha1.Authentication) + authentication := rawObj.(*dpv1alpha2.Authentication) var secrets []string if authentication.Spec.Default != nil && authentication.Spec.Default.AuthTypes != nil && authentication.Spec.Default.AuthTypes.MutualSSL != nil && authentication.Spec.Default.AuthTypes.MutualSSL.SecretRefs != nil && len(authentication.Spec.Default.AuthTypes.MutualSSL.SecretRefs) > 0 { for _, secret := range authentication.Spec.Default.AuthTypes.MutualSSL.SecretRefs { @@ -1366,9 +1359,9 @@ func addIndexes(ctx context.Context, mgr manager.Manager) error { } // ConfigMap to Authentication indexer - if err := mgr.GetFieldIndexer().IndexField(ctx, &dpv1alpha1.Authentication{}, configMapAuthentication, + if err := mgr.GetFieldIndexer().IndexField(ctx, &dpv1alpha2.Authentication{}, configMapAuthentication, func(rawObj k8client.Object) []string { - authentication := rawObj.(*dpv1alpha1.Authentication) + authentication := rawObj.(*dpv1alpha2.Authentication) var configMaps []string if authentication.Spec.Default != nil && authentication.Spec.Default.AuthTypes != nil && authentication.Spec.Default.AuthTypes.MutualSSL != nil && authentication.Spec.Default.AuthTypes.MutualSSL.ConfigMapRefs != nil && len(authentication.Spec.Default.AuthTypes.MutualSSL.ConfigMapRefs) > 0 { for _, configMap := range authentication.Spec.Default.AuthTypes.MutualSSL.ConfigMapRefs { @@ -1403,9 +1396,9 @@ func addIndexes(ctx context.Context, mgr manager.Manager) error { // https://gateway-api.sigs.k8s.io/geps/gep-713/?h=multiple+targetrefs#apply-policies-to-sections-of-a-resource-future-extension // we will use a temporary kindName called Resource for policy attachments // TODO(amali) Fix after the official support is available - if err := mgr.GetFieldIndexer().IndexField(ctx, &dpv1alpha1.Authentication{}, apiAuthenticationResourceIndex, + if err := mgr.GetFieldIndexer().IndexField(ctx, &dpv1alpha2.Authentication{}, apiAuthenticationResourceIndex, func(rawObj k8client.Object) []string { - authentication := rawObj.(*dpv1alpha1.Authentication) + authentication := rawObj.(*dpv1alpha2.Authentication) var apis []string if authentication.Spec.TargetRef.Kind == constants.KindResource { @@ -1555,20 +1548,6 @@ func addIndexes(ctx context.Context, mgr manager.Manager) error { Name: string(apiPolicy.Spec.Override.BackendJWTPolicy.Name), }.String()) } - // if apiPolicy.Spec.Default != nil && apiPolicy.Spec.Default.BackendJWTPolicy != nil { - // backendJWTs = append(backendJWTs, - // types.NamespacedName{ - // Namespace: apiPolicy.Namespace, - // Name: string(apiPolicy.Spec.Default.BackendJWTPolicy.Name), - // }.String()) - // } - // if apiPolicy.Spec.Override != nil && apiPolicy.Spec.Override.BackendJWTPolicy != nil { - // backendJWTs = append(backendJWTs, - // types.NamespacedName{ - // Namespace: apiPolicy.Namespace, - // Name: string(apiPolicy.Spec.Override.BackendJWTPolicy.Name), - // }.String()) - // } return backendJWTs }); err != nil { return err diff --git a/adapter/internal/operator/synchronizer/api_state.go b/adapter/internal/operator/synchronizer/api_state.go index 452ac34959..83edd78296 100644 --- a/adapter/internal/operator/synchronizer/api_state.go +++ b/adapter/internal/operator/synchronizer/api_state.go @@ -30,9 +30,9 @@ type APIState struct { APIDefinition *v1alpha2.API ProdHTTPRoute *HTTPRouteState SandHTTPRoute *HTTPRouteState - Authentications map[string]v1alpha1.Authentication + Authentications map[string]v1alpha2.Authentication RateLimitPolicies map[string]v1alpha1.RateLimitPolicy - ResourceAuthentications map[string]v1alpha1.Authentication + ResourceAuthentications map[string]v1alpha2.Authentication ResourceRateLimitPolicies map[string]v1alpha1.RateLimitPolicy ResourceAPIPolicies map[string]v1alpha2.APIPolicy APIPolicies map[string]v1alpha2.APIPolicy @@ -41,7 +41,7 @@ type APIState struct { APIDefinitionFile []byte OldOrganizationID string SubscriptionValidation bool - MutualSSL *v1alpha1.MutualSSL + MutualSSL *v1alpha2.MutualSSL } // HTTPRouteState holds the state of the deployed httpRoutes. This state is compared with diff --git a/adapter/internal/operator/synchronizer/zz_generated.deepcopy.go b/adapter/internal/operator/synchronizer/zz_generated.deepcopy.go index e70e23770f..230ec77128 100644 --- a/adapter/internal/operator/synchronizer/zz_generated.deepcopy.go +++ b/adapter/internal/operator/synchronizer/zz_generated.deepcopy.go @@ -48,7 +48,7 @@ func (in *APIState) DeepCopyInto(out *APIState) { } if in.Authentications != nil { in, out := &in.Authentications, &out.Authentications - *out = make(map[string]v1alpha1.Authentication, len(*in)) + *out = make(map[string]v1alpha2.Authentication, len(*in)) for key, val := range *in { (*out)[key] = *val.DeepCopy() } @@ -62,7 +62,7 @@ func (in *APIState) DeepCopyInto(out *APIState) { } if in.ResourceAuthentications != nil { in, out := &in.ResourceAuthentications, &out.ResourceAuthentications - *out = make(map[string]v1alpha1.Authentication, len(*in)) + *out = make(map[string]v1alpha2.Authentication, len(*in)) for key, val := range *in { (*out)[key] = *val.DeepCopy() } @@ -109,7 +109,7 @@ func (in *APIState) DeepCopyInto(out *APIState) { } if in.MutualSSL != nil { in, out := &in.MutualSSL, &out.MutualSSL - *out = new(v1alpha1.MutualSSL) + *out = new(v1alpha2.MutualSSL) (*in).DeepCopyInto(*out) } } diff --git a/adapter/internal/operator/utils/utils.go b/adapter/internal/operator/utils/utils.go index 2333156f68..95a28e8b22 100644 --- a/adapter/internal/operator/utils/utils.go +++ b/adapter/internal/operator/utils/utils.go @@ -458,13 +458,13 @@ func getResolvedBackendSecurity(ctx context.Context, client k8client.Client, } // GetResolvedMutualSSL resolves mTLS related security configurations. -func GetResolvedMutualSSL(ctx context.Context, client k8client.Client, authentication dpv1alpha1.Authentication, resolvedMutualSSL *dpv1alpha1.MutualSSL) error { - var mutualSSL *dpv1alpha1.MutualSSLConfig - if authentication.Spec.Default != nil && authentication.Spec.Default.AuthTypes != nil && authentication.Spec.Default.AuthTypes.MutualSSL != nil { - mutualSSL = authentication.Spec.Default.AuthTypes.MutualSSL - } else if authentication.Spec.Override != nil && authentication.Spec.Override.AuthTypes != nil && authentication.Spec.Override.AuthTypes.MutualSSL != nil { - mutualSSL = authentication.Spec.Override.AuthTypes.MutualSSL +func GetResolvedMutualSSL(ctx context.Context, client k8client.Client, authentication dpv1alpha2.Authentication, resolvedMutualSSL *dpv1alpha2.MutualSSL) error { + var mutualSSL *dpv1alpha2.MutualSSLConfig + authSpec := SelectPolicy(&authentication.Spec.Override, &authentication.Spec.Default, nil, nil) + if authSpec.AuthTypes != nil { + mutualSSL = authSpec.AuthTypes.MutualSSL } + if mutualSSL != nil { resolvedCertificates, err := ResolveAllmTLSCertificates(ctx, mutualSSL, client, authentication.Namespace) resolvedMutualSSL.Disabled = mutualSSL.Disabled @@ -480,7 +480,7 @@ func GetResolvedMutualSSL(ctx context.Context, client k8client.Client, authentic } // ResolveAllmTLSCertificates resolves all mTLS certificates -func ResolveAllmTLSCertificates(ctx context.Context, mutualSSL *dpv1alpha1.MutualSSLConfig, client k8client.Client, namespace string) ([]string, error) { +func ResolveAllmTLSCertificates(ctx context.Context, mutualSSL *dpv1alpha2.MutualSSLConfig, client k8client.Client, namespace string) ([]string, error) { var resolvedCertificates []string var err error var certificate string @@ -492,13 +492,13 @@ func ResolveAllmTLSCertificates(ctx context.Context, mutualSSL *dpv1alpha1.Mutua } if mutualSSL.ConfigMapRefs != nil { for _, cert := range mutualSSL.ConfigMapRefs { - certificate, err = ResolveCertificate(ctx, client, namespace, nil, cert, nil) + certificate, err = ResolveCertificate(ctx, client, namespace, nil, ConvertRefConfigsV2ToV1(cert), nil) resolvedCertificates = append(resolvedCertificates, certificate) } } if mutualSSL.SecretRefs != nil { for _, cert := range mutualSSL.SecretRefs { - certificate, err = ResolveCertificate(ctx, client, namespace, nil, nil, cert) + certificate, err = ResolveCertificate(ctx, client, namespace, nil, nil, ConvertRefConfigsV2ToV1(cert)) resolvedCertificates = append(resolvedCertificates, certificate) } } 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 new file mode 100644 index 0000000000..f1e5242cf4 --- /dev/null +++ b/common-controller/internal/operator/config/crd/bases/dp.wso2.com_authentications.yaml @@ -0,0 +1,558 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.0 + name: authentications.dp.wso2.com +spec: + group: dp.wso2.com + names: + kind: Authentication + listKind: AuthenticationList + plural: authentications + singular: authentication + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: Authentication is the Schema for the authentications API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: AuthenticationSpec defines the desired state of Authentication + properties: + default: + description: AuthSpec specification of the authentication service + properties: + authTypes: + description: AuthTypes is to specify the authentication scheme + types and details + properties: + 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 + oauth2: + description: Oauth2 is to specify the Oauth2 authentication + scheme details + properties: + disabled: + default: false + description: Disabled is to disable OAuth2 authentication + type: boolean + header: + default: authorization + 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 + type: string + sendTokenToUpstream: + description: SendTokenToUpstream is to specify whether + the Test Console Key should be sent to the upstream + type: boolean + type: object + type: object + disabled: + description: Disabled is to disable all authentications + type: boolean + type: object + override: + description: AuthSpec specification of the authentication service + properties: + authTypes: + description: AuthTypes is to specify the authentication scheme + types and details + properties: + 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 + oauth2: + description: Oauth2 is to specify the Oauth2 authentication + scheme details + properties: + disabled: + default: false + description: Disabled is to disable OAuth2 authentication + type: boolean + header: + default: authorization + 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 + type: string + sendTokenToUpstream: + description: SendTokenToUpstream is to specify whether + the Test Console Key should be sent to the upstream + type: boolean + type: object + type: object + disabled: + description: Disabled is to disable all authentications + type: boolean + 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. + properties: + group: + description: Group is the group of the target resource. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the target resource. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the target resource. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: Namespace is the namespace of the referent. When + unspecified, the local namespace is inferred. Even when policy + targets a resource in a different namespace, it MUST only apply + to traffic originating from the same namespace as the policy. + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - name + type: object + type: object + status: + description: AuthenticationStatus defines the observed state of Authentication + type: object + type: object + served: true + storage: false + subresources: + status: {} + - name: v1alpha2 + schema: + openAPIV3Schema: + description: Authentication is the Schema for the authentications API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: AuthenticationSpec defines the desired state of Authentication + properties: + default: + description: AuthSpec specification of the authentication service + properties: + authTypes: + description: AuthTypes is to specify the authentication scheme + types and details + properties: + 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 + mtls: + description: MutualSSL is to specify the features and certificates + for mutual SSL + properties: + certificatesInline: + description: CertificatesInline is the Inline Certificate + entry + items: + type: string + type: array + configMapRefs: + description: ConfigMapRefs denotes the reference to the + ConfigMap that contains the Certificate + items: + description: RefConfig holds a config for a secret or + a configmap + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + type: array + disabled: + default: false + description: Disabled is to disable mTLS authentication + type: boolean + required: + default: optional + description: Required indicates whether mutualSSL is mandatory + or optional + enum: + - mandatory + - optional + type: string + secretRefs: + description: SecretRefs denotes the reference to the Secret + that contains the Certificate + items: + description: RefConfig holds a config for a secret or + a configmap + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + type: array + type: object + oauth2: + description: Oauth2 is to specify the Oauth2 authentication + scheme details + properties: + disabled: + default: false + description: Disabled is to disable OAuth2 authentication + type: boolean + header: + default: authorization + 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 + type: string + sendTokenToUpstream: + description: SendTokenToUpstream is to specify whether + the Test Console Key should be sent to the upstream + type: boolean + type: object + type: object + disabled: + description: Disabled is to disable all authentications + type: boolean + type: object + override: + description: AuthSpec specification of the authentication service + properties: + authTypes: + description: AuthTypes is to specify the authentication scheme + types and details + properties: + 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 + mtls: + description: MutualSSL is to specify the features and certificates + for mutual SSL + properties: + certificatesInline: + description: CertificatesInline is the Inline Certificate + entry + items: + type: string + type: array + configMapRefs: + description: ConfigMapRefs denotes the reference to the + ConfigMap that contains the Certificate + items: + description: RefConfig holds a config for a secret or + a configmap + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + type: array + disabled: + default: false + description: Disabled is to disable mTLS authentication + type: boolean + required: + default: optional + description: Required indicates whether mutualSSL is mandatory + or optional + enum: + - mandatory + - optional + type: string + secretRefs: + description: SecretRefs denotes the reference to the Secret + that contains the Certificate + items: + description: RefConfig holds a config for a secret or + a configmap + properties: + key: + description: Key of the secret or configmap + minLength: 1 + type: string + name: + description: Name of the secret or configmap + minLength: 1 + type: string + required: + - key + - name + type: object + type: array + type: object + oauth2: + description: Oauth2 is to specify the Oauth2 authentication + scheme details + properties: + disabled: + default: false + description: Disabled is to disable OAuth2 authentication + type: boolean + header: + default: authorization + 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 + type: string + sendTokenToUpstream: + description: SendTokenToUpstream is to specify whether + the Test Console Key should be sent to the upstream + type: boolean + type: object + type: object + disabled: + description: Disabled is to disable all authentications + type: boolean + 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. + properties: + group: + description: Group is the group of the target resource. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the target resource. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the target resource. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: Namespace is the namespace of the referent. When + unspecified, the local namespace is inferred. Even when policy + targets a resource in a different namespace, it MUST only apply + to traffic originating from the same namespace as the policy. + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - name + type: object + type: object + status: + description: AuthenticationStatus defines the observed state of Authentication + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/common-controller/internal/operator/config/crd/kustomization.yaml b/common-controller/internal/operator/config/crd/kustomization.yaml index 16ac3fc02d..460c451aee 100644 --- a/common-controller/internal/operator/config/crd/kustomization.yaml +++ b/common-controller/internal/operator/config/crd/kustomization.yaml @@ -7,6 +7,7 @@ resources: - bases/cp.wso2.com_applications.yaml - bases/cp.wso2.com_subscriptions.yaml - bases/cp.wso2.com_applicationmappings.yaml +- bases/dp.wso2.com_authentications.yaml #+kubebuilder:scaffold:crdkustomizeresource patches: diff --git a/common-controller/internal/operator/config/crd/patches/cainjection_in_dp_authentications.yaml b/common-controller/internal/operator/config/crd/patches/cainjection_in_dp_authentications.yaml new file mode 100644 index 0000000000..680a50baf9 --- /dev/null +++ b/common-controller/internal/operator/config/crd/patches/cainjection_in_dp_authentications.yaml @@ -0,0 +1,7 @@ +# The following patch adds a directive for certmanager to inject CA into the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) + name: authentications.dp.wso2.com diff --git a/common-controller/internal/operator/config/crd/patches/webhook_in_dp_authentications.yaml b/common-controller/internal/operator/config/crd/patches/webhook_in_dp_authentications.yaml new file mode 100644 index 0000000000..a0c8163283 --- /dev/null +++ b/common-controller/internal/operator/config/crd/patches/webhook_in_dp_authentications.yaml @@ -0,0 +1,16 @@ +# The following patch enables a conversion webhook for the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: authentications.dp.wso2.com +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + namespace: system + name: webhook-service + path: /convert + conversionReviewVersions: + - v1 diff --git a/common-controller/internal/operator/config/rbac/dp_authentication_editor_role.yaml b/common-controller/internal/operator/config/rbac/dp_authentication_editor_role.yaml new file mode 100644 index 0000000000..4d3e0f752a --- /dev/null +++ b/common-controller/internal/operator/config/rbac/dp_authentication_editor_role.yaml @@ -0,0 +1,31 @@ +# permissions for end users to edit authentications. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: authentication-editor-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: operator + app.kubernetes.io/part-of: operator + app.kubernetes.io/managed-by: kustomize + name: authentication-editor-role +rules: +- apiGroups: + - dp.wso2.com + resources: + - authentications + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - dp.wso2.com + resources: + - authentications/status + verbs: + - get diff --git a/common-controller/internal/operator/config/rbac/dp_authentication_viewer_role.yaml b/common-controller/internal/operator/config/rbac/dp_authentication_viewer_role.yaml new file mode 100644 index 0000000000..ab69c164cb --- /dev/null +++ b/common-controller/internal/operator/config/rbac/dp_authentication_viewer_role.yaml @@ -0,0 +1,27 @@ +# permissions for end users to view authentications. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: authentication-viewer-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: operator + app.kubernetes.io/part-of: operator + app.kubernetes.io/managed-by: kustomize + name: authentication-viewer-role +rules: +- apiGroups: + - dp.wso2.com + resources: + - authentications + verbs: + - get + - list + - watch +- apiGroups: + - dp.wso2.com + resources: + - authentications/status + verbs: + - get diff --git a/common-controller/internal/operator/config/samples/dp_v1alpha2_authentication.yaml b/common-controller/internal/operator/config/samples/dp_v1alpha2_authentication.yaml new file mode 100644 index 0000000000..7c1486aeb0 --- /dev/null +++ b/common-controller/internal/operator/config/samples/dp_v1alpha2_authentication.yaml @@ -0,0 +1,12 @@ +apiVersion: dp.wso2.com/v1alpha2 +kind: Authentication +metadata: + labels: + app.kubernetes.io/name: authentication + app.kubernetes.io/instance: authentication-sample + app.kubernetes.io/part-of: operator + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: operator + name: authentication-sample +spec: + # TODO(user): Add fields here diff --git a/common-controller/internal/operator/config/webhook/manifests.yaml b/common-controller/internal/operator/config/webhook/manifests.yaml index 7d86cb2248..411ed6ee86 100644 --- a/common-controller/internal/operator/config/webhook/manifests.yaml +++ b/common-controller/internal/operator/config/webhook/manifests.yaml @@ -44,6 +44,26 @@ webhooks: resources: - apipolicies sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /mutate-dp-wso2-com-v1alpha2-authentication + failurePolicy: Fail + name: mauthentication.kb.io + rules: + - apiGroups: + - dp.wso2.com + apiVersions: + - v1alpha2 + operations: + - CREATE + - UPDATE + resources: + - authentications + sideEffects: None - admissionReviewVersions: - v1 clientConfig: @@ -210,6 +230,26 @@ webhooks: resources: - apipolicies sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-dp-wso2-com-v1alpha2-authentication + failurePolicy: Fail + name: vauthentication.kb.io + rules: + - apiGroups: + - dp.wso2.com + apiVersions: + - v1alpha2 + operations: + - CREATE + - UPDATE + resources: + - authentications + sideEffects: None - admissionReviewVersions: - v1 clientConfig: diff --git a/common-controller/internal/operator/operator.go b/common-controller/internal/operator/operator.go index d3414c534e..73a2520743 100644 --- a/common-controller/internal/operator/operator.go +++ b/common-controller/internal/operator/operator.go @@ -121,7 +121,7 @@ func InitOperator() { "Unable to create webhook for APIPolicy, error: %v", err)) } - if err = (&dpv1alpha1.Authentication{}).SetupWebhookWithManager(mgr); err != nil { + if err = (&dpv1alpha2.Authentication{}).SetupWebhookWithManager(mgr); err != nil { loggers.LoggerAPKOperator.ErrorC(logging.PrintError(logging.Error2638, logging.MAJOR, "Unable to create webhook for Authentication, error: %v", err)) } diff --git a/common-go-libs/PROJECT b/common-go-libs/PROJECT index cb1f5622f9..51763f3fd2 100644 --- a/common-go-libs/PROJECT +++ b/common-go-libs/PROJECT @@ -32,6 +32,7 @@ resources: path: github.com/wso2/apk/common-go-libs/apis/dp/v1alpha1 version: v1alpha1 webhooks: + conversion: true defaulting: true validation: true webhookVersion: v1 @@ -145,4 +146,17 @@ resources: kind: TokenIssuer path: github.com/wso2/apk/common-go-libs/apis/dp/v1alpha2 version: v1alpha2 +- api: + crdVersion: v1 + namespaced: true + domain: wso2.com + group: dp + kind: Authentication + path: github.com/wso2/apk/common-go-libs/apis/dp/v1alpha2 + version: v1alpha2 + webhooks: + conversion: true + defaulting: true + validation: true + webhookVersion: v1 version: "3" diff --git a/common-go-libs/apis/dp/v1alpha1/authentication_conversion.go b/common-go-libs/apis/dp/v1alpha1/authentication_conversion.go new file mode 100644 index 0000000000..dd98f8ecc1 --- /dev/null +++ b/common-go-libs/apis/dp/v1alpha1/authentication_conversion.go @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package v1alpha1 + +import ( + "github.com/wso2/apk/common-go-libs/apis/dp/v1alpha2" + "sigs.k8s.io/controller-runtime/pkg/conversion" +) + +// ConvertTo converts this Authentication CR to the Hub version (v1alpha2). +// src is v1alpha1.Authentication and dst is v1alpha2.Authentication. +func (src *Authentication) ConvertTo(dstRaw conversion.Hub) error { + + dst := dstRaw.(*v1alpha2.Authentication) + dst.ObjectMeta = src.ObjectMeta + + // Spec + dst.Spec.TargetRef = src.Spec.TargetRef + + dst.Spec.Default.Disabled = src.Spec.Default.Disabled + dst.Spec.Override.Disabled = src.Spec.Override.Disabled + + // Convert Oauth2Auth to v1alpha2.Oauth2Auth + dst.Spec.Default.AuthTypes.Oauth2 = v1alpha2.Oauth2Auth(src.Spec.Default.AuthTypes.Oauth2) + dst.Spec.Override.AuthTypes.Oauth2 = v1alpha2.Oauth2Auth(src.Spec.Override.AuthTypes.Oauth2) + + for _, apiKeyAuth := range src.Spec.Default.AuthTypes.APIKey { + convertedAPIKeyAuth := v1alpha2.APIKeyAuth(apiKeyAuth) + dst.Spec.Default.AuthTypes.APIKey = append(dst.Spec.Default.AuthTypes.APIKey, convertedAPIKeyAuth) + } + + for _, apiKeyAuth := range src.Spec.Override.AuthTypes.APIKey { + convertedAPIKeyAuth := v1alpha2.APIKeyAuth(apiKeyAuth) + dst.Spec.Override.AuthTypes.APIKey = append(dst.Spec.Override.AuthTypes.APIKey, convertedAPIKeyAuth) + } + + // Status + dst.Status = v1alpha2.AuthenticationStatus(src.Status) + + return nil +} + +// ConvertFrom converts from the Hub version (v1alpha2) to this version. +// src is v1alpha1.Authentication and dst is v1alpha2.Authentication. +func (src *Authentication) ConvertFrom(srcRaw conversion.Hub) error { + + dst := srcRaw.(*v1alpha2.Authentication) + src.ObjectMeta = dst.ObjectMeta + + // Spec + src.Spec.TargetRef = dst.Spec.TargetRef + + src.Spec.Default.Disabled = dst.Spec.Default.Disabled + src.Spec.Override.Disabled = dst.Spec.Override.Disabled + src.Spec.Default.AuthTypes.Oauth2 = Oauth2Auth(dst.Spec.Default.AuthTypes.Oauth2) + src.Spec.Override.AuthTypes.Oauth2 = Oauth2Auth(dst.Spec.Override.AuthTypes.Oauth2) + + for _, apiKeyAuth := range dst.Spec.Default.AuthTypes.APIKey { + convertedAPIKeyAuth := APIKeyAuth(apiKeyAuth) + src.Spec.Default.AuthTypes.APIKey = append(src.Spec.Default.AuthTypes.APIKey, convertedAPIKeyAuth) + } + + for _, apiKeyAuth := range dst.Spec.Override.AuthTypes.APIKey { + convertedAPIKeyAuth := APIKeyAuth(apiKeyAuth) + src.Spec.Override.AuthTypes.APIKey = append(src.Spec.Override.AuthTypes.APIKey, convertedAPIKeyAuth) + } + + // Status + src.Status = AuthenticationStatus(dst.Status) + return nil +} diff --git a/common-go-libs/apis/dp/v1alpha1/authentication_types.go b/common-go-libs/apis/dp/v1alpha1/authentication_types.go index 6bdf75db5d..55da2c21b7 100644 --- a/common-go-libs/apis/dp/v1alpha1/authentication_types.go +++ b/common-go-libs/apis/dp/v1alpha1/authentication_types.go @@ -57,36 +57,6 @@ type APIAuth struct { // // +optional TestConsoleKey TestConsoleKeyAuth `json:"testConsoleKey,omitempty"` - - // MutualSSL is to specify the features and certificates for mutual SSL - // - // +optional - MutualSSL *MutualSSLConfig `json:"mtls,omitempty"` -} - -// MutualSSLConfig scheme type and details -type MutualSSLConfig struct { - - // Disabled is to disable mTLS authentication - // - // +kubebuilder:default:=false - // +optional - Disabled bool `json:"disabled,omitempty"` - - // Required indicates whether mutualSSL is mandatory or optional - // +kubebuilder:validation:Enum=mandatory;optional - // +kubebuilder:default=optional - // +optional - Required string `json:"required"` - - // CertificatesInline is the Inline Certificate entry - CertificatesInline []*string `json:"certificatesInline,omitempty"` - - // SecretRefs denotes the reference to the Secret that contains the Certificate - SecretRefs []*RefConfig `json:"secretRefs,omitempty"` - - // ConfigMapRefs denotes the reference to the ConfigMap that contains the Certificate - ConfigMapRefs []*RefConfig `json:"configMapRefs,omitempty"` } // TestConsoleKeyAuth Test Console Key Authentication scheme details diff --git a/common-go-libs/apis/dp/v1alpha1/authentication_webhook.go b/common-go-libs/apis/dp/v1alpha1/authentication_webhook.go index fb3f69747f..0eefa868f8 100644 --- a/common-go-libs/apis/dp/v1alpha1/authentication_webhook.go +++ b/common-go-libs/apis/dp/v1alpha1/authentication_webhook.go @@ -18,8 +18,6 @@ package v1alpha1 import ( - "strings" - constants "github.com/wso2/apk/common-go-libs/constants" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" @@ -67,9 +65,6 @@ func (r *Authentication) ValidateUpdate(old runtime.Object) (admission.Warnings, // ValidateAuthentication validates the Authentication func (r *Authentication) ValidateAuthentication() error { var allErrs field.ErrorList - isOAuthDisabled := false - isMTLSMandatory := false - isMTLSDisabled := false if r.Spec.TargetRef.Name == "" { allErrs = append(allErrs, field.Required(field.NewPath("spec").Child("targetRef").Child("name"), "Name is required")) @@ -78,39 +73,6 @@ func (r *Authentication) ValidateAuthentication() error { allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("targetRef").Child("kind"), r.Spec.TargetRef.Kind, "Invalid Kind is provided")) } - var mutualSSL *MutualSSLConfig - - if r.Spec.Default != nil && r.Spec.Default.AuthTypes != nil && r.Spec.Default.AuthTypes.MutualSSL != nil { - isOAuthDisabled = r.Spec.Default.AuthTypes.Oauth2.Disabled - mutualSSL = r.Spec.Default.AuthTypes.MutualSSL - - isMTLSMandatory = strings.ToLower(mutualSSL.Required) == "mandatory" - isMTLSDisabled = mutualSSL.Disabled - if isOAuthDisabled && (!isMTLSMandatory || isMTLSDisabled) { - allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("default").Child("authTypes").Child("mtls"), r.Spec.Default.AuthTypes, - "invalid authentication configuration - one of mTLS or OAuth2 must be enabled and mandatory")) - } - if 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 { - isOAuthDisabled = r.Spec.Override.AuthTypes.Oauth2.Disabled - mutualSSL = r.Spec.Override.AuthTypes.MutualSSL - - isMTLSMandatory = strings.ToLower(mutualSSL.Required) == "mandatory" - isMTLSDisabled = mutualSSL.Disabled - if isOAuthDisabled && (!isMTLSMandatory || isMTLSDisabled) { - allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("override").Child("authTypes").Child("mtls"), r.Spec.Override.AuthTypes, - "invalid authentication configuration - one of mTLS or OAuth2 must be enabled and mandatory")) - } - - if 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, - "invalid mTLS configuration - certificates not provided")) - } - } if len(allErrs) > 0 { return apierrors.NewInvalid( diff --git a/common-go-libs/apis/dp/v1alpha1/zz_generated.deepcopy.go b/common-go-libs/apis/dp/v1alpha1/zz_generated.deepcopy.go index a82496ccfd..60b8ac15b6 100644 --- a/common-go-libs/apis/dp/v1alpha1/zz_generated.deepcopy.go +++ b/common-go-libs/apis/dp/v1alpha1/zz_generated.deepcopy.go @@ -64,11 +64,6 @@ func (in *APIAuth) DeepCopyInto(out *APIAuth) { copy(*out, *in) } out.TestConsoleKey = in.TestConsoleKey - if in.MutualSSL != nil { - in, out := &in.MutualSSL, &out.MutualSSL - *out = new(MutualSSLConfig) - (*in).DeepCopyInto(*out) - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIAuth. @@ -1045,74 +1040,6 @@ func (in JWTIssuerMapping) DeepCopy() JWTIssuerMapping { return *out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *MutualSSL) DeepCopyInto(out *MutualSSL) { - *out = *in - if in.ClientCertificates != nil { - in, out := &in.ClientCertificates, &out.ClientCertificates - *out = make([]string, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MutualSSL. -func (in *MutualSSL) DeepCopy() *MutualSSL { - if in == nil { - return nil - } - out := new(MutualSSL) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *MutualSSLConfig) DeepCopyInto(out *MutualSSLConfig) { - *out = *in - if in.CertificatesInline != nil { - in, out := &in.CertificatesInline, &out.CertificatesInline - *out = make([]*string, len(*in)) - for i := range *in { - if (*in)[i] != nil { - in, out := &(*in)[i], &(*out)[i] - *out = new(string) - **out = **in - } - } - } - if in.SecretRefs != nil { - in, out := &in.SecretRefs, &out.SecretRefs - *out = make([]*RefConfig, len(*in)) - for i := range *in { - if (*in)[i] != nil { - in, out := &(*in)[i], &(*out)[i] - *out = new(RefConfig) - **out = **in - } - } - } - if in.ConfigMapRefs != nil { - in, out := &in.ConfigMapRefs, &out.ConfigMapRefs - *out = make([]*RefConfig, len(*in)) - for i := range *in { - if (*in)[i] != nil { - in, out := &(*in)[i], &(*out)[i] - *out = new(RefConfig) - **out = **in - } - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MutualSSLConfig. -func (in *MutualSSLConfig) DeepCopy() *MutualSSLConfig { - if in == nil { - return nil - } - out := new(MutualSSLConfig) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Oauth2Auth) DeepCopyInto(out *Oauth2Auth) { *out = *in diff --git a/common-go-libs/apis/dp/v1alpha2/authentication_conversion.go b/common-go-libs/apis/dp/v1alpha2/authentication_conversion.go new file mode 100644 index 0000000000..a225d48953 --- /dev/null +++ b/common-go-libs/apis/dp/v1alpha2/authentication_conversion.go @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package v1alpha2 + +// Hub marks this type as a conversion hub. +func (*Authentication) Hub() {} diff --git a/common-go-libs/apis/dp/v1alpha2/authentication_types.go b/common-go-libs/apis/dp/v1alpha2/authentication_types.go new file mode 100644 index 0000000000..68abe7b97d --- /dev/null +++ b/common-go-libs/apis/dp/v1alpha2/authentication_types.go @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package v1alpha2 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + gwapiv1b1 "sigs.k8s.io/gateway-api/apis/v1alpha2" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +// AuthenticationSpec defines the desired state of Authentication +type AuthenticationSpec struct { + Default *AuthSpec `json:"default,omitempty"` + Override *AuthSpec `json:"override,omitempty"` + TargetRef gwapiv1b1.PolicyTargetReference `json:"targetRef,omitempty"` +} + +// AuthSpec specification of the authentication service +type AuthSpec struct { + // Disabled is to disable all authentications + Disabled *bool `json:"disabled,omitempty"` + + // AuthTypes is to specify the authentication scheme types and details + AuthTypes *APIAuth `json:"authTypes,omitempty"` +} + +// APIAuth Authentication scheme type and details +type APIAuth struct { + // Oauth2 is to specify the Oauth2 authentication scheme details + // + // +optional + Oauth2 Oauth2Auth `json:"oauth2,omitempty"` + + // APIKey is to specify the APIKey authentication scheme details + // + // +optional + // +nullable + APIKey []APIKeyAuth `json:"apiKey,omitempty"` + + // TestConsoleKey is to specify the Test Console Key authentication scheme details + // + // +optional + TestConsoleKey TestConsoleKeyAuth `json:"testConsoleKey,omitempty"` + + // MutualSSL is to specify the features and certificates for mutual SSL + // + // +optional + MutualSSL *MutualSSLConfig `json:"mtls,omitempty"` +} + +// MutualSSLConfig scheme type and details +type MutualSSLConfig struct { + + // Disabled is to disable mTLS authentication + // + // +kubebuilder:default=false + // +optional + Disabled bool `json:"disabled,omitempty"` + + // Required indicates whether mutualSSL is mandatory or optional + // +kubebuilder:validation:Enum=mandatory;optional + // +kubebuilder:default=optional + // +optional + Required string `json:"required"` + + // CertificatesInline is the Inline Certificate entry + CertificatesInline []*string `json:"certificatesInline,omitempty"` + + // SecretRefs denotes the reference to the Secret that contains the Certificate + SecretRefs []*RefConfig `json:"secretRefs,omitempty"` + + // ConfigMapRefs denotes the reference to the ConfigMap that contains the Certificate + ConfigMapRefs []*RefConfig `json:"configMapRefs,omitempty"` +} + +// TestConsoleKeyAuth Test Console Key Authentication scheme details +type TestConsoleKeyAuth struct { + // Header is the header name used to pass the Test Console Key + // + // +kubebuilder:default:=internal-key + // +optional + // +kubebuilder:validation:MinLength=1 + Header string `json:"header,omitempty"` + + // SendTokenToUpstream is to specify whether the Test Console Key should be sent to the upstream + // + // +optional + SendTokenToUpstream bool `json:"sendTokenToUpstream,omitempty"` +} + +// Oauth2Auth OAuth2 Authentication scheme details +type Oauth2Auth struct { + + // Disabled is to disable OAuth2 authentication + // + // +kubebuilder:default=false + // +optional + Disabled bool `json:"disabled"` + + // Header is the header name used to pass the OAuth2 token + // + // +kubebuilder:default=authorization + // +optional + Header string `json:"header,omitempty"` + + // SendTokenToUpstream is to specify whether the OAuth2 token should be sent to the upstream + // + // +optional + SendTokenToUpstream bool `json:"sendTokenToUpstream,omitempty"` +} + +// APIKeyAuth APIKey Authentication scheme details +type APIKeyAuth struct { + // In is to specify how the APIKey is passed to the request + // + // +kubebuilder:validation:Enum=Header;Query + // +kubebuilder:validation:MinLength=1 + In string `json:"in,omitempty"` + + // Name is the name of the header or query parameter to be used + // +kubebuilder:validation:MinLength=1 + Name string `json:"name,omitempty"` + + // SendTokenToUpstream is to specify whether the APIKey should be sent to the upstream + // + // +optional + SendTokenToUpstream bool `json:"sendTokenToUpstream,omitempty"` +} + +// AuthenticationStatus defines the observed state of Authentication +type AuthenticationStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file +} + +// +genclient +//+kubebuilder:object:root=true +//+kubebuilder:subresource:status +//+kubebuilder:storageversion + +// Authentication is the Schema for the authentications API +type Authentication struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec AuthenticationSpec `json:"spec,omitempty"` + Status AuthenticationStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// AuthenticationList contains a list of Authentication +type AuthenticationList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Authentication `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Authentication{}, &AuthenticationList{}) +} diff --git a/common-go-libs/apis/dp/v1alpha2/authentication_webhook.go b/common-go-libs/apis/dp/v1alpha2/authentication_webhook.go new file mode 100644 index 0000000000..56fe74e0eb --- /dev/null +++ b/common-go-libs/apis/dp/v1alpha2/authentication_webhook.go @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +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" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/validation/field" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" +) + +func (r *Authentication) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +// TODO(user): EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! + +//+kubebuilder:webhook:path=/mutate-dp-wso2-com-v1alpha2-authentication,mutating=true,failurePolicy=fail,sideEffects=None,groups=dp.wso2.com,resources=authentications,verbs=create;update,versions=v1alpha2,name=mauthentication.kb.io,admissionReviewVersions=v1 + +var _ webhook.Defaulter = &Authentication{} + +// Default implements webhook.Defaulter so a webhook will be registered for the type +func (r *Authentication) Default() { + // TODO(user): fill in your defaulting logic. +} + +// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. +//+kubebuilder:webhook:path=/validate-dp-wso2-com-v1alpha2-authentication,mutating=false,failurePolicy=fail,sideEffects=None,groups=dp.wso2.com,resources=authentications,verbs=create;update,versions=v1alpha2,name=vauthentication.kb.io,admissionReviewVersions=v1 + +var _ webhook.Validator = &Authentication{} + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (r *Authentication) ValidateCreate() (admission.Warnings, error) { + // TODO(user): fill in your validation logic upon object creation. + return nil, r.ValidateAuthentication() +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (r *Authentication) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { + return nil, r.ValidateAuthentication() +} + +// ValidateAuthentication validates the Authentication +func (r *Authentication) ValidateAuthentication() error { + var allErrs field.ErrorList + isOAuthDisabled := false + isMTLSMandatory := false + isMTLSDisabled := false + + 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 + + if r.Spec.Default != nil && r.Spec.Default.AuthTypes != nil && r.Spec.Default.AuthTypes.MutualSSL != nil { + isOAuthDisabled = r.Spec.Default.AuthTypes.Oauth2.Disabled + mutualSSL = r.Spec.Default.AuthTypes.MutualSSL + + isMTLSMandatory = strings.ToLower(mutualSSL.Required) == "mandatory" + isMTLSDisabled = mutualSSL.Disabled + if isOAuthDisabled && (!isMTLSMandatory || isMTLSDisabled) { + allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("default").Child("authTypes").Child("mtls"), r.Spec.Default.AuthTypes, + "invalid authentication configuration - one of mTLS or OAuth2 must be enabled and mandatory")) + } + if 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 { + isOAuthDisabled = r.Spec.Override.AuthTypes.Oauth2.Disabled + mutualSSL = r.Spec.Override.AuthTypes.MutualSSL + + isMTLSMandatory = strings.ToLower(mutualSSL.Required) == "mandatory" + isMTLSDisabled = mutualSSL.Disabled + if isOAuthDisabled && (!isMTLSMandatory || isMTLSDisabled) { + allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("override").Child("authTypes").Child("mtls"), r.Spec.Override.AuthTypes, + "invalid authentication configuration - one of mTLS or OAuth2 must be enabled and mandatory")) + } + + if 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, + "invalid mTLS configuration - certificates not provided")) + } + } + + if len(allErrs) > 0 { + return apierrors.NewInvalid( + schema.GroupKind{Group: "dp.wso2.com", Kind: "Authentication"}, + r.Name, allErrs) + } + return nil +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (r *Authentication) ValidateDelete() (admission.Warnings, error) { + // TODO(user): fill in your validation logic upon object deletion. + return nil, nil +} diff --git a/common-go-libs/apis/dp/v1alpha1/mutualSSL.go b/common-go-libs/apis/dp/v1alpha2/mutualSSL.go similarity index 90% rename from common-go-libs/apis/dp/v1alpha1/mutualSSL.go rename to common-go-libs/apis/dp/v1alpha2/mutualSSL.go index 96485a159d..54e21c54c2 100644 --- a/common-go-libs/apis/dp/v1alpha1/mutualSSL.go +++ b/common-go-libs/apis/dp/v1alpha2/mutualSSL.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,7 @@ * */ -package v1alpha1 +package v1alpha2 // MutualSSL defines the mutual SSL configurations for an API type MutualSSL struct { diff --git a/common-go-libs/apis/dp/v1alpha2/webhook_suite_test.go b/common-go-libs/apis/dp/v1alpha2/webhook_suite_test.go index a43cff45ae..d9905b38bd 100644 --- a/common-go-libs/apis/dp/v1alpha2/webhook_suite_test.go +++ b/common-go-libs/apis/dp/v1alpha2/webhook_suite_test.go @@ -103,6 +103,9 @@ var _ = BeforeSuite(func() { err = (&APIPolicy{}).SetupWebhookWithManager(mgr) Expect(err).NotTo(HaveOccurred()) + err = (&Authentication{}).SetupWebhookWithManager(mgr) + Expect(err).NotTo(HaveOccurred()) + //+kubebuilder:scaffold:webhook go func() { 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 afe0b0ab33..53522405dd 100644 --- a/common-go-libs/apis/dp/v1alpha2/zz_generated.deepcopy.go +++ b/common-go-libs/apis/dp/v1alpha2/zz_generated.deepcopy.go @@ -54,6 +54,48 @@ func (in *API) DeepCopyObject() runtime.Object { return nil } +// 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 + if in.APIKey != nil { + in, out := &in.APIKey, &out.APIKey + *out = make([]APIKeyAuth, len(*in)) + copy(*out, *in) + } + out.TestConsoleKey = in.TestConsoleKey + if in.MutualSSL != nil { + in, out := &in.MutualSSL, &out.MutualSSL + *out = new(MutualSSLConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIAuth. +func (in *APIAuth) DeepCopy() *APIAuth { + if in == nil { + return nil + } + out := new(APIAuth) + 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 +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIKeyAuth. +func (in *APIKeyAuth) DeepCopy() *APIKeyAuth { + if in == nil { + return nil + } + out := new(APIKeyAuth) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *APIList) DeepCopyInto(out *APIList) { *out = *in @@ -236,6 +278,131 @@ func (in *APIStatus) DeepCopy() *APIStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthSpec) DeepCopyInto(out *AuthSpec) { + *out = *in + if in.Disabled != nil { + in, out := &in.Disabled, &out.Disabled + *out = new(bool) + **out = **in + } + if in.AuthTypes != nil { + in, out := &in.AuthTypes, &out.AuthTypes + *out = new(APIAuth) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthSpec. +func (in *AuthSpec) DeepCopy() *AuthSpec { + if in == nil { + return nil + } + out := new(AuthSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Authentication) DeepCopyInto(out *Authentication) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Authentication. +func (in *Authentication) DeepCopy() *Authentication { + if in == nil { + return nil + } + out := new(Authentication) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Authentication) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthenticationList) DeepCopyInto(out *AuthenticationList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Authentication, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthenticationList. +func (in *AuthenticationList) DeepCopy() *AuthenticationList { + if in == nil { + return nil + } + out := new(AuthenticationList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *AuthenticationList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthenticationSpec) DeepCopyInto(out *AuthenticationSpec) { + *out = *in + if in.Default != nil { + in, out := &in.Default, &out.Default + *out = new(AuthSpec) + (*in).DeepCopyInto(*out) + } + if in.Override != nil { + in, out := &in.Override, &out.Override + *out = new(AuthSpec) + (*in).DeepCopyInto(*out) + } + in.TargetRef.DeepCopyInto(&out.TargetRef) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthenticationSpec. +func (in *AuthenticationSpec) DeepCopy() *AuthenticationSpec { + if in == nil { + return nil + } + out := new(AuthenticationSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthenticationStatus) DeepCopyInto(out *AuthenticationStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthenticationStatus. +func (in *AuthenticationStatus) DeepCopy() *AuthenticationStatus { + if in == nil { + return nil + } + out := new(AuthenticationStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackendJWTToken) DeepCopyInto(out *BackendJWTToken) { *out = *in @@ -415,6 +582,89 @@ func (in *JWKS) DeepCopy() *JWKS { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MutualSSL) DeepCopyInto(out *MutualSSL) { + *out = *in + if in.ClientCertificates != nil { + in, out := &in.ClientCertificates, &out.ClientCertificates + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MutualSSL. +func (in *MutualSSL) DeepCopy() *MutualSSL { + if in == nil { + return nil + } + out := new(MutualSSL) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MutualSSLConfig) DeepCopyInto(out *MutualSSLConfig) { + *out = *in + if in.CertificatesInline != nil { + in, out := &in.CertificatesInline, &out.CertificatesInline + *out = make([]*string, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(string) + **out = **in + } + } + } + if in.SecretRefs != nil { + in, out := &in.SecretRefs, &out.SecretRefs + *out = make([]*RefConfig, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(RefConfig) + **out = **in + } + } + } + if in.ConfigMapRefs != nil { + in, out := &in.ConfigMapRefs, &out.ConfigMapRefs + *out = make([]*RefConfig, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(RefConfig) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MutualSSLConfig. +func (in *MutualSSLConfig) DeepCopy() *MutualSSLConfig { + if in == nil { + return nil + } + out := new(MutualSSLConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +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 { + if in == nil { + return nil + } + out := new(Oauth2Auth) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PolicySpec) DeepCopyInto(out *PolicySpec) { *out = *in @@ -505,6 +755,21 @@ func (in *SignatureValidation) DeepCopy() *SignatureValidation { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestConsoleKeyAuth) DeepCopyInto(out *TestConsoleKeyAuth) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestConsoleKeyAuth. +func (in *TestConsoleKeyAuth) DeepCopy() *TestConsoleKeyAuth { + if in == nil { + return nil + } + out := new(TestConsoleKeyAuth) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TokenIssuer) DeepCopyInto(out *TokenIssuer) { *out = *in 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 fcb15768ba..f1e5242cf4 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 @@ -15,6 +15,214 @@ spec: scope: Namespaced versions: - name: v1alpha1 + schema: + openAPIV3Schema: + description: Authentication is the Schema for the authentications API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: AuthenticationSpec defines the desired state of Authentication + properties: + default: + description: AuthSpec specification of the authentication service + properties: + authTypes: + description: AuthTypes is to specify the authentication scheme + types and details + properties: + 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 + oauth2: + description: Oauth2 is to specify the Oauth2 authentication + scheme details + properties: + disabled: + default: false + description: Disabled is to disable OAuth2 authentication + type: boolean + header: + default: authorization + 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 + type: string + sendTokenToUpstream: + description: SendTokenToUpstream is to specify whether + the Test Console Key should be sent to the upstream + type: boolean + type: object + type: object + disabled: + description: Disabled is to disable all authentications + type: boolean + type: object + override: + description: AuthSpec specification of the authentication service + properties: + authTypes: + description: AuthTypes is to specify the authentication scheme + types and details + properties: + 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 + oauth2: + description: Oauth2 is to specify the Oauth2 authentication + scheme details + properties: + disabled: + default: false + description: Disabled is to disable OAuth2 authentication + type: boolean + header: + default: authorization + 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 + type: string + sendTokenToUpstream: + description: SendTokenToUpstream is to specify whether + the Test Console Key should be sent to the upstream + type: boolean + type: object + type: object + disabled: + description: Disabled is to disable all authentications + type: boolean + 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. + properties: + group: + description: Group is the group of the target resource. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the target resource. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the target resource. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: Namespace is the namespace of the referent. When + unspecified, the local namespace is inferred. Even when policy + targets a resource in a different namespace, it MUST only apply + to traffic originating from the same namespace as the policy. + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - name + type: object + type: object + status: + description: AuthenticationStatus defines the observed state of Authentication + type: object + type: object + served: true + storage: false + subresources: + status: {} + - name: v1alpha2 schema: openAPIV3Schema: description: Authentication is the Schema for the authentications API @@ -102,6 +310,7 @@ spec: description: Disabled is to disable mTLS authentication type: boolean required: + default: optional description: Required indicates whether mutualSSL is mandatory or optional enum: @@ -128,8 +337,6 @@ spec: - name type: object type: array - required: - - required type: object oauth2: description: Oauth2 is to specify the Oauth2 authentication @@ -237,6 +444,7 @@ spec: description: Disabled is to disable mTLS authentication type: boolean required: + default: optional description: Required indicates whether mutualSSL is mandatory or optional enum: @@ -263,8 +471,6 @@ spec: - name type: object type: array - required: - - required type: object oauth2: description: Oauth2 is to specify the Oauth2 authentication diff --git a/common-go-libs/config/webhook/manifests.yaml b/common-go-libs/config/webhook/manifests.yaml index 7d86cb2248..411ed6ee86 100644 --- a/common-go-libs/config/webhook/manifests.yaml +++ b/common-go-libs/config/webhook/manifests.yaml @@ -44,6 +44,26 @@ webhooks: resources: - apipolicies sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /mutate-dp-wso2-com-v1alpha2-authentication + failurePolicy: Fail + name: mauthentication.kb.io + rules: + - apiGroups: + - dp.wso2.com + apiVersions: + - v1alpha2 + operations: + - CREATE + - UPDATE + resources: + - authentications + sideEffects: None - admissionReviewVersions: - v1 clientConfig: @@ -210,6 +230,26 @@ webhooks: resources: - apipolicies sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-dp-wso2-com-v1alpha2-authentication + failurePolicy: Fail + name: vauthentication.kb.io + rules: + - apiGroups: + - dp.wso2.com + apiVersions: + - v1alpha2 + operations: + - CREATE + - UPDATE + resources: + - authentications + sideEffects: None - admissionReviewVersions: - v1 clientConfig: diff --git a/helm-charts/crds/dp.wso2.com_authentications.yaml b/helm-charts/crds/dp.wso2.com_authentications.yaml index 1dbc523a5b..f1e5242cf4 100644 --- a/helm-charts/crds/dp.wso2.com_authentications.yaml +++ b/helm-charts/crds/dp.wso2.com_authentications.yaml @@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.9.2 - creationTimestamp: null + controller-gen.kubebuilder.io/version: v0.12.0 name: authentications.dp.wso2.com spec: group: dp.wso2.com @@ -16,6 +15,214 @@ spec: scope: Namespaced versions: - name: v1alpha1 + schema: + openAPIV3Schema: + description: Authentication is the Schema for the authentications API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: AuthenticationSpec defines the desired state of Authentication + properties: + default: + description: AuthSpec specification of the authentication service + properties: + authTypes: + description: AuthTypes is to specify the authentication scheme + types and details + properties: + 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 + oauth2: + description: Oauth2 is to specify the Oauth2 authentication + scheme details + properties: + disabled: + default: false + description: Disabled is to disable OAuth2 authentication + type: boolean + header: + default: authorization + 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 + type: string + sendTokenToUpstream: + description: SendTokenToUpstream is to specify whether + the Test Console Key should be sent to the upstream + type: boolean + type: object + type: object + disabled: + description: Disabled is to disable all authentications + type: boolean + type: object + override: + description: AuthSpec specification of the authentication service + properties: + authTypes: + description: AuthTypes is to specify the authentication scheme + types and details + properties: + 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 + oauth2: + description: Oauth2 is to specify the Oauth2 authentication + scheme details + properties: + disabled: + default: false + description: Disabled is to disable OAuth2 authentication + type: boolean + header: + default: authorization + 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 + type: string + sendTokenToUpstream: + description: SendTokenToUpstream is to specify whether + the Test Console Key should be sent to the upstream + type: boolean + type: object + type: object + disabled: + description: Disabled is to disable all authentications + type: boolean + 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. + properties: + group: + description: Group is the group of the target resource. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the target resource. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the target resource. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: Namespace is the namespace of the referent. When + unspecified, the local namespace is inferred. Even when policy + targets a resource in a different namespace, it MUST only apply + to traffic originating from the same namespace as the policy. + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - name + type: object + type: object + status: + description: AuthenticationStatus defines the observed state of Authentication + type: object + type: object + served: true + storage: false + subresources: + status: {} + - name: v1alpha2 schema: openAPIV3Schema: description: Authentication is the Schema for the authentications API @@ -103,6 +310,7 @@ spec: description: Disabled is to disable mTLS authentication type: boolean required: + default: optional description: Required indicates whether mutualSSL is mandatory or optional enum: @@ -129,8 +337,6 @@ spec: - name type: object type: array - required: - - required type: object oauth2: description: Oauth2 is to specify the Oauth2 authentication @@ -238,6 +444,7 @@ spec: description: Disabled is to disable mTLS authentication type: boolean required: + default: optional description: Required indicates whether mutualSSL is mandatory or optional enum: @@ -264,8 +471,6 @@ spec: - name type: object type: array - required: - - required type: object oauth2: description: Oauth2 is to specify the Oauth2 authentication diff --git a/helm-charts/templates/data-plane/gateway-components/common-controller/webhook/adapter-mutating-webhook-config.yaml b/helm-charts/templates/data-plane/gateway-components/common-controller/webhook/adapter-mutating-webhook-config.yaml index 229ef819d2..6b30071c94 100644 --- a/helm-charts/templates/data-plane/gateway-components/common-controller/webhook/adapter-mutating-webhook-config.yaml +++ b/helm-charts/templates/data-plane/gateway-components/common-controller/webhook/adapter-mutating-webhook-config.yaml @@ -64,19 +64,19 @@ webhooks: - apipolicies sideEffects: None - admissionReviewVersions: - - v1 + - v1 clientConfig: service: name: {{ template "apk-helm.resource.prefix" . }}-common-controller-service namespace: {{ .Release.Namespace }} - path: /mutate-dp-wso2-com-v1alpha1-authentication + path: /mutate-dp-wso2-com-v1alpha2-authentication failurePolicy: Fail name: mauthentication.kb.io rules: - apiGroups: - dp.wso2.com apiVersions: - - v1alpha1 + - v1alpha2 operations: - CREATE - UPDATE diff --git a/helm-charts/templates/data-plane/gateway-components/common-controller/webhook/adapter-validation-webhook-config.yaml b/helm-charts/templates/data-plane/gateway-components/common-controller/webhook/adapter-validation-webhook-config.yaml index 0a2ca5d9c1..5edc76ec99 100644 --- a/helm-charts/templates/data-plane/gateway-components/common-controller/webhook/adapter-validation-webhook-config.yaml +++ b/helm-charts/templates/data-plane/gateway-components/common-controller/webhook/adapter-validation-webhook-config.yaml @@ -89,14 +89,14 @@ webhooks: service: name: {{ template "apk-helm.resource.prefix" . }}-common-controller-service namespace: {{ .Release.Namespace }} - path: /validate-dp-wso2-com-v1alpha1-authentication + path: /validate-dp-wso2-com-v1alpha2-authentication failurePolicy: Fail name: vauthentication.kb.io rules: - apiGroups: - dp.wso2.com apiVersions: - - v1alpha1 + - v1alpha2 operations: - CREATE - UPDATE diff --git a/runtime/config-deployer-service/ballerina/K8sClient.bal b/runtime/config-deployer-service/ballerina/K8sClient.bal index e11aaefed1..7dd1ff34ff 100644 --- a/runtime/config-deployer-service/ballerina/K8sClient.bal +++ b/runtime/config-deployer-service/ballerina/K8sClient.bal @@ -61,21 +61,22 @@ isolated function deleteAPICR(string name, string namespace) returns http:Respon } isolated function deleteAuthenticationCR(string name, string namespace) returns http:Response|http:ClientError { - string endpoint = "/apis/dp.wso2.com/v1alpha1/namespaces/" + namespace + "/authentications/" + name; + string endpoint = "/apis/dp.wso2.com/v1alpha2/namespaces/" + namespace + "/authentications/" + name; return k8sApiServerEp->delete(endpoint, targetType = http:Response); } + isolated function getAuthenticationCR(string name, string namespace) returns model:Authentication|http:ClientError { - string endpoint = "/apis/dp.wso2.com/v1alpha1/namespaces/" + namespace + "/authentications/" + name; + string endpoint = "/apis/dp.wso2.com/v1alpha2/namespaces/" + namespace + "/authentications/" + name; return k8sApiServerEp->get(endpoint, targetType = model:Authentication); } isolated function deployAuthenticationCR(model:Authentication authentication, string namespace) returns http:Response|http:ClientError { - string endpoint = "/apis/dp.wso2.com/v1alpha1/namespaces/" + namespace + "/authentications"; + string endpoint = "/apis/dp.wso2.com/v1alpha2/namespaces/" + namespace + "/authentications"; return k8sApiServerEp->post(endpoint, authentication, targetType = http:Response); } isolated function updateAuthenticationCR(model:Authentication authentication, string namespace) returns http:Response|http:ClientError { - string endpoint = "/apis/dp.wso2.com/v1alpha1/namespaces/" + namespace + "/authentications/" + authentication.metadata.name; + string endpoint = "/apis/dp.wso2.com/v1alpha2/namespaces/" + namespace + "/authentications/" + authentication.metadata.name; return k8sApiServerEp->put(endpoint, authentication, targetType = http:Response); } @@ -93,6 +94,7 @@ isolated function getConfigMap(string name, string namespace) returns model:Conf string endpoint = "/api/v1/namespaces/" + namespace + "/configmaps/" + name; return k8sApiServerEp->get(endpoint, targetType = model:ConfigMap); } + isolated function deleteConfigMap(string name, string namespace) returns http:Response|http:ClientError { string endpoint = "/api/v1/namespaces/" + namespace + "/configmaps/" + name; return k8sApiServerEp->delete(endpoint, targetType = http:Response); @@ -169,6 +171,7 @@ isolated function getBackendCR(string name, string namespace) returns model:Back string endpoint = "/apis/dp.wso2.com/v1alpha1/namespaces/" + namespace + "/backends/" + name; return k8sApiServerEp->get(endpoint, targetType = model:Backend); } + isolated function deployBackendCR(model:Backend backend, string namespace) returns http:Response|http:ClientError { string endpoint = "/apis/dp.wso2.com/v1alpha1/namespaces/" + namespace + "/backends"; return k8sApiServerEp->post(endpoint, backend, targetType = http:Response); @@ -231,6 +234,7 @@ isolated function getRateLimitPolicyCR(string name, string namespace) returns mo string endpoint = "/apis/dp.wso2.com/v1alpha1/namespaces/" + namespace + "/ratelimitpolicies/" + name; return k8sApiServerEp->get(endpoint, targetType = model:RateLimitPolicy); } + isolated function deleteRateLimitPolicyCR(string name, string namespace) returns http:Response|http:ClientError { string endpoint = "/apis/dp.wso2.com/v1alpha1/namespaces/" + namespace + "/ratelimitpolicies/" + name; return k8sApiServerEp->delete(endpoint, targetType = http:Response); @@ -280,6 +284,7 @@ isolated function getInterceptorServiceCR(string name, string namespace) returns string endpoint = "/apis/dp.wso2.com/v1alpha1/namespaces/" + namespace + "/interceptorservices/" + name; return k8sApiServerEp->get(endpoint, targetType = model:InterceptorService); } + isolated function deleteInterceptorServiceCR(string name, string namespace) returns http:Response|http:ClientError { string endpoint = "/apis/dp.wso2.com/v1alpha1/namespaces/" + namespace + "/interceptorservices/" + name; return k8sApiServerEp->delete(endpoint, targetType = http:Response); @@ -299,10 +304,12 @@ isolated function updateBackendJWTCr(model:BackendJWT backendJWT, string namespa string endpoint = "/apis/dp.wso2.com/v1alpha1/namespaces/" + namespace + "/backendjwts/" + backendJWT.metadata.name; return k8sApiServerEp->put(endpoint, backendJWT, targetType = http:Response); } + isolated function getBackendJWTCr(string name, string namespace) returns model:BackendJWT|http:ClientError { string endpoint = "/apis/dp.wso2.com/v1alpha1/namespaces/" + namespace + "/backendjwts/" + name; return k8sApiServerEp->get(endpoint, targetType = model:BackendJWT); } + isolated function deleteBackendJWTCr(string name, string namespace) returns http:Response|http:ClientError { string endpoint = "/apis/dp.wso2.com/v1alpha1/namespaces/" + namespace + "/backendjwts/" + name; return k8sApiServerEp->delete(endpoint, targetType = http:Response); diff --git a/runtime/config-deployer-service/ballerina/modules/model/Authentication.bal b/runtime/config-deployer-service/ballerina/modules/model/Authentication.bal index 7fc022be4c..4220e5e8d6 100644 --- a/runtime/config-deployer-service/ballerina/modules/model/Authentication.bal +++ b/runtime/config-deployer-service/ballerina/modules/model/Authentication.bal @@ -16,7 +16,7 @@ // under the License. // public type Authentication record { - string apiVersion = "dp.wso2.com/v1alpha1"; + string apiVersion = "dp.wso2.com/v1alpha2"; string kind = "Authentication"; Metadata metadata; AuthenticationSpec spec; @@ -66,7 +66,7 @@ public type APIKey record { }; public type AuthenticationList record { - string apiVersion = "dp.wso2.com/v1alpha1"; + string apiVersion = "dp.wso2.com/v1alpha2"; string kind = "AuthenticationList"; Authentication[] items; ListMeta metadata;