Skip to content

Commit a5ad053

Browse files
committed
K8SPXC-1733 Ability to customize secrets generation
Customize secrets generation: * keep current secret generation behavior as default * Ability to customize the special symbols to include in secret generation * Ability to customize min/max secret length Linked to #2222
1 parent ac6d909 commit a5ad053

File tree

10 files changed

+310
-36
lines changed

10 files changed

+310
-36
lines changed

config/crd/bases/pxc.percona.com_perconaxtradbclusters.yaml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4414,6 +4414,29 @@ spec:
44144414
runtimeClassName:
44154415
type: string
44164416
type: object
4417+
passwordGenerationOptions:
4418+
properties:
4419+
maxLength:
4420+
default: 20
4421+
maximum: 128
4422+
minimum: 8
4423+
type: integer
4424+
minLength:
4425+
default: 16
4426+
maximum: 128
4427+
minimum: 8
4428+
type: integer
4429+
symbols:
4430+
default: '!#$%&()*+,-.<=>?@[]^_{}~'
4431+
maxLength: 32
4432+
type: string
4433+
required:
4434+
- maxLength
4435+
- minLength
4436+
- symbols
4437+
type: object
4438+
x-kubernetes-validations:
4439+
- rule: self.maxLength > self.minLength
44174440
pause:
44184441
type: boolean
44194442
platform:

deploy/bundle.yaml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5454,6 +5454,29 @@ spec:
54545454
runtimeClassName:
54555455
type: string
54565456
type: object
5457+
passwordGenerationOptions:
5458+
properties:
5459+
maxLength:
5460+
default: 20
5461+
maximum: 128
5462+
minimum: 8
5463+
type: integer
5464+
minLength:
5465+
default: 16
5466+
maximum: 128
5467+
minimum: 8
5468+
type: integer
5469+
symbols:
5470+
default: '!#$%&()*+,-.<=>?@[]^_{}~'
5471+
maxLength: 32
5472+
type: string
5473+
required:
5474+
- maxLength
5475+
- minLength
5476+
- symbols
5477+
type: object
5478+
x-kubernetes-validations:
5479+
- rule: self.maxLength > self.minLength
54575480
pause:
54585481
type: boolean
54595482
platform:

deploy/crd.yaml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5454,6 +5454,29 @@ spec:
54545454
runtimeClassName:
54555455
type: string
54565456
type: object
5457+
passwordGenerationOptions:
5458+
properties:
5459+
maxLength:
5460+
default: 20
5461+
maximum: 128
5462+
minimum: 8
5463+
type: integer
5464+
minLength:
5465+
default: 16
5466+
maximum: 128
5467+
minimum: 8
5468+
type: integer
5469+
symbols:
5470+
default: '!#$%&()*+,-.<=>?@[]^_{}~'
5471+
maxLength: 32
5472+
type: string
5473+
required:
5474+
- maxLength
5475+
- minLength
5476+
- symbols
5477+
type: object
5478+
x-kubernetes-validations:
5479+
- rule: self.maxLength > self.minLength
54575480
pause:
54585481
type: boolean
54595482
platform:

deploy/cw-bundle.yaml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5454,6 +5454,29 @@ spec:
54545454
runtimeClassName:
54555455
type: string
54565456
type: object
5457+
passwordGenerationOptions:
5458+
properties:
5459+
maxLength:
5460+
default: 20
5461+
maximum: 128
5462+
minimum: 8
5463+
type: integer
5464+
minLength:
5465+
default: 16
5466+
maximum: 128
5467+
minimum: 8
5468+
type: integer
5469+
symbols:
5470+
default: '!#$%&()*+,-.<=>?@[]^_{}~'
5471+
maxLength: 32
5472+
type: string
5473+
required:
5474+
- maxLength
5475+
- minLength
5476+
- symbols
5477+
type: object
5478+
x-kubernetes-validations:
5479+
- rule: self.maxLength > self.minLength
54575480
pause:
54585481
type: boolean
54595482
platform:

pkg/apis/pxc/v1/pxc_types.go

Lines changed: 51 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,26 +29,27 @@ import (
2929

3030
// PerconaXtraDBClusterSpec defines the desired state of PerconaXtraDBCluster
3131
type PerconaXtraDBClusterSpec struct {
32-
Platform version.Platform `json:"platform,omitempty"`
33-
CRVersion string `json:"crVersion,omitempty"`
34-
Pause bool `json:"pause,omitempty"`
35-
SecretsName string `json:"secretsName,omitempty"`
36-
VaultSecretName string `json:"vaultSecretName,omitempty"`
37-
SSLSecretName string `json:"sslSecretName,omitempty"`
38-
SSLInternalSecretName string `json:"sslInternalSecretName,omitempty"`
39-
LogCollectorSecretName string `json:"logCollectorSecretName,omitempty"`
40-
TLS *TLSSpec `json:"tls,omitempty"`
41-
PXC *PXCSpec `json:"pxc,omitempty"`
42-
ProxySQL *ProxySQLSpec `json:"proxysql,omitempty"`
43-
HAProxy *HAProxySpec `json:"haproxy,omitempty"`
44-
PMM *PMMSpec `json:"pmm,omitempty"`
45-
LogCollector *LogCollectorSpec `json:"logcollector,omitempty"`
46-
Backup *PXCScheduledBackup `json:"backup,omitempty"`
47-
UpdateStrategy appsv1.StatefulSetUpdateStrategyType `json:"updateStrategy,omitempty"`
48-
UpgradeOptions UpgradeOptions `json:"upgradeOptions,omitempty"`
49-
AllowUnsafeConfig bool `json:"allowUnsafeConfigurations,omitempty"`
50-
Unsafe UnsafeFlags `json:"unsafeFlags,omitempty"`
51-
VolumeExpansionEnabled bool `json:"enableVolumeExpansion,omitempty"`
32+
Platform version.Platform `json:"platform,omitempty"`
33+
CRVersion string `json:"crVersion,omitempty"`
34+
Pause bool `json:"pause,omitempty"`
35+
SecretsName string `json:"secretsName,omitempty"`
36+
PasswordGenerationOptions *PasswordGenerationOptions `json:"passwordGenerationOptions,omitempty"`
37+
VaultSecretName string `json:"vaultSecretName,omitempty"`
38+
SSLSecretName string `json:"sslSecretName,omitempty"`
39+
SSLInternalSecretName string `json:"sslInternalSecretName,omitempty"`
40+
LogCollectorSecretName string `json:"logCollectorSecretName,omitempty"`
41+
TLS *TLSSpec `json:"tls,omitempty"`
42+
PXC *PXCSpec `json:"pxc,omitempty"`
43+
ProxySQL *ProxySQLSpec `json:"proxysql,omitempty"`
44+
HAProxy *HAProxySpec `json:"haproxy,omitempty"`
45+
PMM *PMMSpec `json:"pmm,omitempty"`
46+
LogCollector *LogCollectorSpec `json:"logcollector,omitempty"`
47+
Backup *PXCScheduledBackup `json:"backup,omitempty"`
48+
UpdateStrategy appsv1.StatefulSetUpdateStrategyType `json:"updateStrategy,omitempty"`
49+
UpgradeOptions UpgradeOptions `json:"upgradeOptions,omitempty"`
50+
AllowUnsafeConfig bool `json:"allowUnsafeConfigurations,omitempty"`
51+
Unsafe UnsafeFlags `json:"unsafeFlags,omitempty"`
52+
VolumeExpansionEnabled bool `json:"enableVolumeExpansion,omitempty"`
5253

5354
// Deprecated, should be removed in the future. Use InitContainer.Image instead
5455
InitImage string `json:"initImage,omitempty"`
@@ -61,6 +62,35 @@ type PerconaXtraDBClusterSpec struct {
6162
Users []User `json:"users,omitempty"`
6263
}
6364

65+
// +kubebuilder:validation:XValidation:rule="self.maxLength > self.minLength"
66+
type PasswordGenerationOptions struct {
67+
// When set to true (the default), special symbols such as *!$%^ will be included in password generation
68+
// +kubebuilder:validation:Required
69+
// +kubebuilder:validation:MaxLength=32
70+
// +kubebuilder:default="!#$%&()*+,-.<=>?@[]^_{}~"
71+
Symbols string `json:"symbols"`
72+
// +kubebuilder:validation:Required
73+
// +kubebuilder:validation:Maximum=128
74+
// +kubebuilder:validation:Minimum=8
75+
// +kubebuilder:default=20
76+
MaxLength int `json:"maxLength"`
77+
// +kubebuilder:validation:Required
78+
// +kubebuilder:validation:Maximum=128
79+
// +kubebuilder:validation:Minimum=8
80+
// +kubebuilder:default=16
81+
MinLength int `json:"minLength"`
82+
}
83+
84+
func (cr *PerconaXtraDBCluster) setPasswordGenerationOptionsDefaults() {
85+
if cr.Spec.PasswordGenerationOptions == nil {
86+
cr.Spec.PasswordGenerationOptions = &PasswordGenerationOptions{
87+
Symbols: "!#$%&()*+,-.<=>?@[]^_{}~",
88+
MaxLength: 20,
89+
MinLength: 16,
90+
}
91+
}
92+
}
93+
6494
type SecretKeySelector struct {
6595
Name string `json:"name"`
6696
Key string `json:"key,omitempty"`
@@ -1190,6 +1220,7 @@ func (cr *PerconaXtraDBCluster) CheckNSetDefaults(serverVersion *version.ServerV
11901220

11911221
cr.setProbesDefaults()
11921222
cr.setPodSecurityContext()
1223+
cr.setPasswordGenerationOptionsDefaults()
11931224

11941225
if cr.Spec.EnableCRValidationWebhook == nil {
11951226
falseVal := false

pkg/apis/pxc/v1/zz_generated.deepcopy.go

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/controller/pxc/secrets.go

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileUsersSecret(ctx context.Context
3939
if err := validatePasswords(secretObj); err != nil {
4040
return nil, errors.Wrap(err, "validate passwords")
4141
}
42-
isChanged, err := setUserSecretDefaults(secretObj)
42+
isChanged, err := setUserSecretDefaults(secretObj, cr.Spec.PasswordGenerationOptions)
4343
if err != nil {
4444
return nil, errors.Wrap(err, "set user secret defaults")
4545
}
@@ -64,7 +64,7 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileUsersSecret(ctx context.Context
6464
Type: corev1.SecretTypeOpaque,
6565
}
6666

67-
if _, err = setUserSecretDefaults(secretObj); err != nil {
67+
if _, err = setUserSecretDefaults(secretObj, cr.Spec.PasswordGenerationOptions); err != nil {
6868
return nil, errors.Wrap(err, "set user secret defaults")
6969
}
7070

@@ -77,14 +77,14 @@ func (r *ReconcilePerconaXtraDBCluster) reconcileUsersSecret(ctx context.Context
7777
return secretObj, nil
7878
}
7979

80-
func setUserSecretDefaults(secret *corev1.Secret) (isChanged bool, err error) {
80+
func setUserSecretDefaults(secret *corev1.Secret, secretsOptions *api.PasswordGenerationOptions) (isChanged bool, err error) {
8181
if secret.Data == nil {
8282
secret.Data = make(map[string][]byte)
8383
}
8484
users := []string{users.Root, users.Xtrabackup, users.Monitor, users.ProxyAdmin, users.Operator, users.Replication}
8585
for _, user := range users {
8686
if pass, ok := secret.Data[user]; !ok || len(pass) == 0 {
87-
secret.Data[user], err = generatePass()
87+
secret.Data[user], err = generatePass(secretsOptions)
8888
if err != nil {
8989
return false, errors.Wrapf(err, "create %s users password", user)
9090
}
@@ -96,20 +96,18 @@ func setUserSecretDefaults(secret *corev1.Secret) (isChanged bool, err error) {
9696
}
9797

9898
const (
99-
passwordMaxLen = 20
100-
passwordMinLen = 16
101-
passSymbols = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
99+
passBaseSymbols = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
102100
"abcdefghijklmnopqrstuvwxyz" +
103-
"0123456789" +
104-
"!#$%&()*+,-.<=>?@[]^_{}~"
101+
"0123456789"
105102
)
106103

107-
// generatePass generates a random password
108-
func generatePass() ([]byte, error) {
104+
// generatePass generates a random password with or without special symbols
105+
func generatePass(secretsOptions *api.PasswordGenerationOptions) ([]byte, error) {
109106
mrand.Seed(time.Now().UnixNano())
110-
ln := mrand.Intn(passwordMaxLen-passwordMinLen) + passwordMinLen
107+
ln := mrand.Intn(secretsOptions.MaxLength-secretsOptions.MinLength) + secretsOptions.MinLength
111108
b := make([]byte, ln)
112109
for i := 0; i < ln; i++ {
110+
passSymbols := passBaseSymbols + secretsOptions.Symbols
113111
randInt, err := rand.Int(rand.Reader, big.NewInt(int64(len(passSymbols))))
114112
if err != nil {
115113
return nil, errors.Wrap(err, "get rand int")

0 commit comments

Comments
 (0)