Skip to content

File tree

7 files changed

+78
-60
lines changed

7 files changed

+78
-60
lines changed
 

‎api/v1alpha1/connection_types.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import (
55
)
66

77
type ConnectionOptions struct {
8-
AccessToken *AccessTokenAuth `json:"accessToken,omitempty"`
9-
StaticCredentials *StaticCredentialsAuth `json:"staticCredentials,omitempty"`
10-
Oauth2TokenExhange *Oauth2TokenExchange `json:"oauth2TokenExchange,omitempty"`
8+
AccessToken *AccessTokenAuth `json:"accessToken,omitempty"`
9+
StaticCredentials *StaticCredentialsAuth `json:"staticCredentials,omitempty"`
10+
Oauth2TokenExchange *Oauth2TokenExchange `json:"oauth2TokenExchange,omitempty"`
1111
}
1212

1313
type AccessTokenAuth struct {
@@ -22,13 +22,13 @@ type StaticCredentialsAuth struct {
2222
type Oauth2TokenExchange struct {
2323
Endpoint string `json:"endpoint"`
2424
PrivateKey *CredentialSource `json:"privateKey"`
25-
JWTHeader *JWTHeader `json:",inline"`
26-
JWTClaims *JWTClaims `json:",inline"`
25+
JWTHeader `json:",inline"`
26+
JWTClaims `json:",inline"`
2727
}
2828

2929
type JWTHeader struct {
30-
KeyID string `json:"keyID,omitempty"`
31-
SignAlg string `json:"signAlg,omitempty"`
30+
KeyID *string `json:"keyID"`
31+
SignAlg string `json:"signAlg,omitempty"`
3232
}
3333
type JWTClaims struct {
3434
Issuer string `json:"issuer,omitempty"`

‎api/v1alpha1/const.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@ const (
3333
BinariesDir = "/opt/ydb/bin"
3434
DaemonBinaryName = "ydbd"
3535

36-
DefaultRootUsername = "root"
37-
DefaultRootPassword = ""
36+
DefaultRootUsername = "root"
37+
DefaultRootPassword = ""
38+
DefaultSignAlgorithm = "RS256"
3839

3940
LabelDeploymentKey = "deployment"
4041
LabelDeploymentValueKubernetes = "kubernetes"

‎api/v1alpha1/storage_webhook.go

+40
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"math/rand"
77

8+
"github.com/golang-jwt/jwt/v4"
89
"github.com/google/go-cmp/cmp"
910
"github.com/google/go-cmp/cmp/cmpopts"
1011
corev1 "k8s.io/api/core/v1"
@@ -107,6 +108,14 @@ func (r *StorageDefaulter) Default(ctx context.Context, obj runtime.Object) erro
107108
return nil
108109
}
109110

111+
if storage.Spec.OperatorConnection != nil {
112+
if storage.Spec.OperatorConnection.Oauth2TokenExchange != nil {
113+
if storage.Spec.OperatorConnection.Oauth2TokenExchange.SignAlg == "" {
114+
storage.Spec.OperatorConnection.Oauth2TokenExchange.SignAlg = DefaultSignAlgorithm
115+
}
116+
}
117+
}
118+
110119
if storage.Spec.Image == nil {
111120
storage.Spec.Image = &PodImage{}
112121
}
@@ -171,6 +180,17 @@ func (r *StorageDefaulter) Default(ctx context.Context, obj runtime.Object) erro
171180

172181
var _ webhook.Validator = &Storage{}
173182

183+
func isSignAlgorithmSupported(alg string) bool {
184+
supportedAlgs := jwt.GetAlgorithms()
185+
186+
for _, supportedAlg := range supportedAlgs {
187+
if alg == supportedAlg {
188+
return true
189+
}
190+
}
191+
return false
192+
}
193+
174194
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
175195
func (r *Storage) ValidateCreate() error {
176196
storagelog.Info("validate create", "name", r.Name)
@@ -207,6 +227,16 @@ func (r *Storage) ValidateCreate() error {
207227
return fmt.Errorf("field 'spec.operatorConnection' does not satisfy with config option `enforce_user_token_requirement: %t`", authEnabled)
208228
}
209229

230+
if r.Spec.OperatorConnection != nil && r.Spec.OperatorConnection.Oauth2TokenExchange != nil {
231+
auth := r.Spec.OperatorConnection.Oauth2TokenExchange
232+
if auth.KeyID == nil {
233+
return fmt.Errorf("field keyID is required for OAuth2TokenExchange type")
234+
}
235+
if !isSignAlgorithmSupported(auth.SignAlg) {
236+
return fmt.Errorf("signAlg %s does not supported for OAuth2TokenExchange type", auth.SignAlg)
237+
}
238+
}
239+
210240
if r.Spec.NodeSets != nil {
211241
var nodesInSetsCount int32
212242
for _, nodeSetInline := range r.Spec.NodeSets {
@@ -294,6 +324,16 @@ func (r *Storage) ValidateUpdate(old runtime.Object) error {
294324
return fmt.Errorf("field 'spec.operatorConnection' does not align with config option `enforce_user_token_requirement: %t`", authEnabled)
295325
}
296326

327+
if r.Spec.OperatorConnection != nil && r.Spec.OperatorConnection.Oauth2TokenExchange != nil {
328+
auth := r.Spec.OperatorConnection.Oauth2TokenExchange
329+
if auth.KeyID == nil {
330+
return fmt.Errorf("field keyID is required for OAuth2TokenExchange type")
331+
}
332+
if !isSignAlgorithmSupported(auth.SignAlg) {
333+
return fmt.Errorf("signAlg %s does not supported for OAuth2TokenExchange type", auth.SignAlg)
334+
}
335+
}
336+
297337
if !r.Spec.OperatorSync {
298338
oldStorage := old.(*Storage)
299339

‎api/v1alpha1/zz_generated.deepcopy.go

+9-12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎deploy/ydb-operator/Chart.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ type: application
1515
# This is the chart version. This version number should be incremented each time you make changes
1616
# to the chart and its templates, including the app version.
1717
# Versions are expected to follow Semantic Versioning (https://semver.org/)
18-
version: 0.5.20
18+
version: 0.5.21
1919

2020
# This is the version number of the application being deployed. This version number should be
2121
# incremented each time you make changes to the application. Versions are not expected to
2222
# follow Semantic Versioning. They should reflect the version the application is using.
2323
# It is recommended to use it with quotes.
24-
appVersion: "0.5.20"
24+
appVersion: "0.5.21"

‎deploy/ydb-operator/crds/storage.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -4900,6 +4900,7 @@ spec:
49004900
type: string
49014901
required:
49024902
- endpoint
4903+
- keyID
49034904
- privateKey
49044905
type: object
49054906
staticCredentials:

‎internal/resources/resource.go

+16-37
Original file line numberDiff line numberDiff line change
@@ -407,49 +407,39 @@ func getYDBOauth2Credentials(
407407
ctx,
408408
storage.Namespace,
409409
restConfig,
410-
auth.Oauth2TokenExhange.PrivateKey.SecretKeyRef,
410+
auth.Oauth2TokenExchange.PrivateKey.SecretKeyRef,
411411
)
412412
if err != nil {
413413
return nil, fmt.Errorf(
414414
"failed to get RSA private key for Oauth2TokenExchange from secret: %s, key: %s, error: %w",
415-
auth.Oauth2TokenExhange.PrivateKey.SecretKeyRef.Name,
416-
auth.Oauth2TokenExhange.PrivateKey.SecretKeyRef.Key,
415+
auth.Oauth2TokenExchange.PrivateKey.SecretKeyRef.Name,
416+
auth.Oauth2TokenExchange.PrivateKey.SecretKeyRef.Key,
417417
err)
418418
}
419+
420+
keyID := *auth.Oauth2TokenExchange.KeyID
421+
signMethod := jwt.GetSigningMethod(auth.Oauth2TokenExchange.SignAlg)
419422
privateKeyPEM, err := jwt.ParseRSAPrivateKeyFromPEM([]byte(privateKey))
420423
if err != nil {
421424
return nil, fmt.Errorf(
422425
"failed to parse RSA private key for Oauth2TokenExchange from secret: %s, key: %s, error: %w",
423-
auth.Oauth2TokenExhange.PrivateKey.SecretKeyRef.Name,
424-
auth.Oauth2TokenExhange.PrivateKey.SecretKeyRef.Key,
426+
auth.Oauth2TokenExchange.PrivateKey.SecretKeyRef.Name,
427+
auth.Oauth2TokenExchange.PrivateKey.SecretKeyRef.Key,
425428
err,
426429
)
427430
}
428431

429-
var signMethod jwt.SigningMethod
430-
if auth.Oauth2TokenExhange.JWTHeader.SignAlg != "" {
431-
if !isSignAlgorithmSupported(auth.Oauth2TokenExhange.JWTHeader.SignAlg) {
432-
return nil, fmt.Errorf(
433-
"sign algorithm %s does not supported",
434-
auth.Oauth2TokenExhange.JWTHeader.SignAlg,
435-
)
436-
}
437-
signMethod = jwt.GetSigningMethod(auth.Oauth2TokenExhange.JWTHeader.SignAlg)
438-
} else {
439-
signMethod = jwt.SigningMethodRS256
440-
}
441-
442432
return ydbCredentials.NewOauth2TokenExchangeCredentials(
443-
ydbCredentials.WithTokenEndpoint(auth.Oauth2TokenExhange.Endpoint),
444-
ydbCredentials.WithAudience(auth.Oauth2TokenExhange.JWTClaims.Audience),
433+
ydbCredentials.WithTokenEndpoint(auth.Oauth2TokenExchange.Endpoint),
434+
ydbCredentials.WithAudience(auth.Oauth2TokenExchange.Audience),
445435
ydbCredentials.WithJWTSubjectToken(
436+
ydbCredentials.WithKeyID(keyID),
446437
ydbCredentials.WithSigningMethod(signMethod),
447438
ydbCredentials.WithPrivateKey(privateKeyPEM),
448-
ydbCredentials.WithKeyID(auth.Oauth2TokenExhange.JWTHeader.KeyID),
449-
ydbCredentials.WithAudience(auth.Oauth2TokenExhange.JWTClaims.Audience),
450-
ydbCredentials.WithIssuer(auth.Oauth2TokenExhange.JWTClaims.Issuer),
451-
ydbCredentials.WithSubject(auth.Oauth2TokenExhange.JWTClaims.Subject),
452-
ydbCredentials.WithID(auth.Oauth2TokenExhange.JWTClaims.ID),
439+
ydbCredentials.WithIssuer(auth.Oauth2TokenExchange.Issuer),
440+
ydbCredentials.WithSubject(auth.Oauth2TokenExchange.Subject),
441+
ydbCredentials.WithID(auth.Oauth2TokenExchange.ID),
442+
ydbCredentials.WithAudience(auth.Oauth2TokenExchange.Audience),
453443
))
454444
}
455445

@@ -485,7 +475,7 @@ func GetYDBCredentials(
485475
return getYDBStaticCredentials(ctx, storage, restConfig)
486476
}
487477

488-
if auth.Oauth2TokenExhange != nil {
478+
if auth.Oauth2TokenExchange != nil {
489479
return getYDBOauth2Credentials(ctx, storage, restConfig)
490480
}
491481

@@ -602,14 +592,3 @@ func PodIsReady(e corev1.Pod) bool {
602592
}
603593
return false
604594
}
605-
606-
func isSignAlgorithmSupported(alg string) bool {
607-
supportedAlgs := jwt.GetAlgorithms()
608-
609-
for _, supportedAlg := range supportedAlgs {
610-
if alg == supportedAlg {
611-
return true
612-
}
613-
}
614-
return false
615-
}

0 commit comments

Comments
 (0)
Please sign in to comment.