diff --git a/api/v1beta1/temporalcluster_types.go b/api/v1beta1/temporalcluster_types.go index 831bf3ad..3072ae48 100644 --- a/api/v1beta1/temporalcluster_types.go +++ b/api/v1beta1/temporalcluster_types.go @@ -878,6 +878,44 @@ type FilestoreArchiver struct { DirPermissions string `json:"dirPermissions"` } +// AuthorizationSpec defines the specifications for authorization in the temporal cluster. It contains fields +// that configure how JWT tokens are validated, how permissions are managed, and how claims are mapped. +type AuthorizationSpec struct { + // JWTKeyProvider specifies the signing key provider used for validating JWT tokens. + // +optional + JWTKeyProvider AuthorizationSpecJWTKeyProvider `json:"jwtKeyProvider"` + + // PermissionsClaimName is the name of the claim within the JWT token that contains the user's permissions. + // +optional + PermissionsClaimName string `json:"permissionsClaimName"` + + // Authorizer defines the authorization mechanism to be used. It can be left as an empty string to + // use a no-operation authorizer (noopAuthorizer), or set to "default" to use the temporal's default + // authorizer (defaultAuthorizer). + // +optional + Authorizer string `json:"authorizer"` + + // ClaimMapper specifies the claim mapping mechanism used for handling JWT claims. Similar to the Authorizer, + // it can be left as an empty string to use a no-operation claim mapper (noopClaimMapper), or set to "default" + // to use the default JWT claim mapper (defaultJWTClaimMapper). + // +optional + ClaimMapper string `json:"claimMapper"` +} + +// AuthorizationSpecJWTKeyProvider defines the configuration for a JWT key provider within the AuthorizationSpec. +// It specifies where to source the JWT keys from and how often they should be refreshed. +type AuthorizationSpecJWTKeyProvider struct { + // KeySourceURIs is a list of URIs where the JWT signing keys can be obtained. These URIs are used by the + // authorization system to fetch the public keys necessary for validating JWT tokens. + // +optional + KeySourceURIs []string `json:"keySourceURIs"` + + // RefreshInterval defines the time interval at which temporal should refresh the JWT signing keys from + // the specified URIs. + // +optional + RefreshInterval *metav1.Duration `json:"refreshInterval"` +} + // S3Archiver is the S3 archival provider configuration. type S3Archiver struct { // Region is the aws s3 region. @@ -970,6 +1008,9 @@ type TemporalClusterSpec struct { // Archival allows Workflow Execution Event Histories and Visibility data backups for the temporal cluster. // +optional Archival *ClusterArchivalSpec `json:"archival,omitempty"` + // Authorization allows authorization configuration for the temporal cluster. + // +optional + Authorization *AuthorizationSpec `json:"authorization,omitempty"` } // ServiceStatus reports a service status. diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index 1209a562..692cc3a6 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -78,6 +78,47 @@ func (in *ArchivalSpec) DeepCopy() *ArchivalSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthorizationSpec) DeepCopyInto(out *AuthorizationSpec) { + *out = *in + in.JWTKeyProvider.DeepCopyInto(&out.JWTKeyProvider) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizationSpec. +func (in *AuthorizationSpec) DeepCopy() *AuthorizationSpec { + if in == nil { + return nil + } + out := new(AuthorizationSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthorizationSpecJWTKeyProvider) DeepCopyInto(out *AuthorizationSpecJWTKeyProvider) { + *out = *in + if in.KeySourceURIs != nil { + in, out := &in.KeySourceURIs, &out.KeySourceURIs + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.RefreshInterval != nil { + in, out := &in.RefreshInterval, &out.RefreshInterval + *out = new(metav1.Duration) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizationSpecJWTKeyProvider. +func (in *AuthorizationSpecJWTKeyProvider) DeepCopy() *AuthorizationSpecJWTKeyProvider { + if in == nil { + return nil + } + out := new(AuthorizationSpecJWTKeyProvider) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CassandraConsistencySpec) DeepCopyInto(out *CassandraConsistencySpec) { *out = *in @@ -1252,6 +1293,11 @@ func (in *TemporalClusterSpec) DeepCopyInto(out *TemporalClusterSpec) { *out = new(ClusterArchivalSpec) (*in).DeepCopyInto(*out) } + if in.Authorization != nil { + in, out := &in.Authorization, &out.Authorization + *out = new(AuthorizationSpec) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TemporalClusterSpec. diff --git a/config/crd/bases/temporal.io_temporalclusters.yaml b/config/crd/bases/temporal.io_temporalclusters.yaml index b6026272..7963d368 100644 --- a/config/crd/bases/temporal.io_temporalclusters.yaml +++ b/config/crd/bases/temporal.io_temporalclusters.yaml @@ -288,6 +288,31 @@ spec: - paused type: object type: object + authorization: + description: Authorization + properties: + authorizer: + description: Authorizer defines the authorization mechanism to be used. It can be left as an empty string to use a no-operation authorizer (noopAuthorizer), or set to "default" to use the temporal's default authorizer (defaultAuthorizer). + type: string + claimMapper: + description: ClaimMapper specifies the claim mapping mechanism used for handling JWT claims. Similar to the Authorizer, it can be left as an empty string to use a no-operation claim mapper (noopClaimMapper), or set to "default" to use the default JWT claim mapper (defaultJWTClaimMapper). + type: string + jwtKeyProvider: + description: JWTKeyProvider specifies the signing key provider used for validating JWT tokens. + properties: + keySourceURIs: + description: KeySourceURIs is a list of URIs where the JWT signing keys can be obtained. These URIs are used by the authorization system to fetch the public keys necessary for validating JWT tokens. + items: + type: string + type: array + refreshInterval: + description: RefreshInterval defines the time interval at which temporal should refresh the JWT signing keys from the specified URIs. + type: string + type: object + permissionsClaimName: + description: PermissionsClaimName is the name of the claim within the JWT token that contains the user's permissions. + type: string + type: object dynamicConfig: description: DynamicConfig allows advanced configuration for the temporal cluster. properties: diff --git a/docs/api/v1beta1.md b/docs/api/v1beta1.md index 6d881c13..14d58ee8 100644 --- a/docs/api/v1beta1.md +++ b/docs/api/v1beta1.md @@ -268,6 +268,19 @@ ClusterArchivalSpec

Archival allows Workflow Execution Event Histories and Visibility data backups for the temporal cluster.

+ + +authorization
+ + +AuthorizationSpec + + + + +

Authorization

+ + @@ -608,6 +621,132 @@ string +

AuthorizationSpec +

+

+(Appears on: +TemporalClusterSpec) +

+

AuthorizationSpec defines the specifications for authorization in the temporal cluster. It contains fields +that configure how JWT tokens are validated, how permissions are managed, and how claims are mapped.

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+jwtKeyProvider
+ + +AuthorizationSpecJWTKeyProvider + + +
+(Optional) +

JWTKeyProvider specifies the signing key provider used for validating JWT tokens.

+
+permissionsClaimName
+ +string + +
+(Optional) +

PermissionsClaimName is the name of the claim within the JWT token that contains the user’s permissions.

+
+authorizer
+ +string + +
+(Optional) +

Authorizer defines the authorization mechanism to be used. It can be left as an empty string to +use a no-operation authorizer (noopAuthorizer), or set to “default” to use the temporal’s default +authorizer (defaultAuthorizer).

+
+claimMapper
+ +string + +
+(Optional) +

ClaimMapper specifies the claim mapping mechanism used for handling JWT claims. Similar to the Authorizer, +it can be left as an empty string to use a no-operation claim mapper (noopClaimMapper), or set to “default” +to use the default JWT claim mapper (defaultJWTClaimMapper).

+
+
+
+

AuthorizationSpecJWTKeyProvider +

+

+(Appears on: +AuthorizationSpec) +

+

AuthorizationSpecJWTKeyProvider defines the configuration for a JWT key provider within the AuthorizationSpec. +It specifies where to source the JWT keys from and how often they should be refreshed.

+
+
+ + + + + + + + + + + + + + + + + +
FieldDescription
+keySourceURIs
+ +[]string + +
+(Optional) +

KeySourceURIs is a list of URIs where the JWT signing keys can be obtained. These URIs are used by the +authorization system to fetch the public keys necessary for validating JWT tokens.

+
+refreshInterval
+ + +Kubernetes meta/v1.Duration + + +
+(Optional) +

RefreshInterval defines the time interval at which temporal should refresh the JWT signing keys from +the specified URIs.

+
+
+

CassandraConsistencySpec

@@ -3665,6 +3804,19 @@ ClusterArchivalSpec

Archival allows Workflow Execution Event Histories and Visibility data backups for the temporal cluster.

+ + +authorization
+ + +AuthorizationSpec + + + + +

Authorization

+ + diff --git a/internal/resource/config/configmap_builder.go b/internal/resource/config/configmap_builder.go index 9010536c..58023f27 100644 --- a/internal/resource/config/configmap_builder.go +++ b/internal/resource/config/configmap_builder.go @@ -29,6 +29,7 @@ import ( "github.com/alexandrevilain/temporal-operator/internal/resource/meta" "github.com/alexandrevilain/temporal-operator/internal/resource/mtls/certmanager" archivalutil "github.com/alexandrevilain/temporal-operator/pkg/temporal/archival" + "github.com/alexandrevilain/temporal-operator/pkg/temporal/authorization" "github.com/alexandrevilain/temporal-operator/pkg/temporal/log" "github.com/alexandrevilain/temporal-operator/pkg/temporal/persistence" "github.com/alexandrevilain/temporal-operator/pkg/version" @@ -213,6 +214,7 @@ func (b *ConfigmapBuilder) Update(object client.Object) error { MaxJoinDuration: 30 * time.Second, BroadcastAddress: "{{ default .Env.POD_IP \"0.0.0.0\" }}", }, + Authorization: authorization.ToTemporalAuthorization(b.instance.Spec.Authorization), }, Persistence: *persistenceConfig, Log: log.NewSQLConfigFromDatastoreSpec(b.instance.Spec.Log), diff --git a/pkg/temporal/authorization/authorization.go b/pkg/temporal/authorization/authorization.go new file mode 100644 index 00000000..60405b29 --- /dev/null +++ b/pkg/temporal/authorization/authorization.go @@ -0,0 +1,40 @@ +// Licensed to Alexandre VILAIN under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Alexandre VILAIN licenses this file to you 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 authorization + +import ( + "github.com/alexandrevilain/temporal-operator/api/v1beta1" + "go.temporal.io/server/common/config" +) + +// ToTemporalAuthorization transforms v1beta1.AuthorizationSpec to temporal's authorization config. +func ToTemporalAuthorization(authorization *v1beta1.AuthorizationSpec) config.Authorization { + if authorization == nil { + return config.Authorization{} + } + + return config.Authorization{ + JWTKeyProvider: config.JWTKeyProvider{ + KeySourceURIs: authorization.JWTKeyProvider.KeySourceURIs, + RefreshInterval: authorization.JWTKeyProvider.RefreshInterval.Duration, + }, + PermissionsClaimName: authorization.PermissionsClaimName, + Authorizer: authorization.Authorizer, + ClaimMapper: authorization.ClaimMapper, + } +}