Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: support to update and delete system accounts #8756

Merged
merged 14 commits into from
Jan 21, 2025
30 changes: 23 additions & 7 deletions apis/apps/v1/componentdefinition_types.go
Original file line number Diff line number Diff line change
@@ -1212,26 +1212,42 @@ type SystemAccount struct {
// +optional
InitAccount bool `json:"initAccount,omitempty"`

// Defines the statement used to create the account with the necessary privileges.
// Defines the statements used to create, delete, and update the account.
//
// This field is immutable once set.
//
// +optional
Statement string `json:"statement,omitempty"`
Statement *SystemAccountStatement `json:"statement,omitempty"`

// Specifies the policy for generating the account's password.
//
// This field is immutable once set.
//
// +optional
PasswordGenerationPolicy PasswordConfig `json:"passwordGenerationPolicy"`
}

type SystemAccountStatement struct {
// The statement to create a new account with the necessary privileges.
//
// This field is immutable once set.
//
// +optional
Create string `json:"create,omitempty"`

// The statement to delete a account.
//
// This field is immutable once set.
//
// +optional
Delete string `json:"delete,omitempty"`

// Refers to the secret from which data will be copied to create the new account.
// The statement to update an existing account.
//
// This field is immutable once set.
//
// +optional
SecretRef *ProvisionSecretRef `json:"secretRef,omitempty"`
Update string `json:"update,omitempty"`
}

type TLS struct {
@@ -1735,9 +1751,9 @@ type ComponentLifecycleActions struct {
//
// The container executing this action has access to following variables:
//
// - KB_ACCOUNT_NAME: The name of the system account to be created.
// - KB_ACCOUNT_PASSWORD: The password for the system account. // TODO: how to pass the password securely?
// - KB_ACCOUNT_STATEMENT: The statement used to create the system account.
// - KB_ACCOUNT_NAME: The name of the system account to be manipulated.
// - KB_ACCOUNT_PASSWORD: The password for the system account.
// - KB_ACCOUNT_STATEMENT: The statement used to manipulate the system account.
//
// Note: This field is immutable once it has been set.
//
12 changes: 12 additions & 0 deletions apis/apps/v1/types.go
Original file line number Diff line number Diff line change
@@ -347,6 +347,12 @@ type ComponentSystemAccount struct {
// +kubebuilder:validation:Required
Name string `json:"name"`

// Specifies whether the system account is disabled.
//
// +kubebuilder:default=false
// +optional
Disabled *bool `json:"disabled,omitempty"`

// Specifies the policy for generating the account's password.
//
// This field is immutable once set.
@@ -429,6 +435,12 @@ type ProvisionSecretRef struct {
//
// +kubebuilder:validation:Required
Namespace string `json:"namespace"`

// The key in the secret data that contains the password.
//
// +kubebuilder:default="password"
// +optional
Password string `json:"password,omitempty"`
}

// ClusterComponentConfig represents a config with its source bound.
28 changes: 24 additions & 4 deletions apis/apps/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions config/crd/bases/apps.kubeblocks.io_clusters.yaml
Original file line number Diff line number Diff line change
@@ -5311,6 +5311,10 @@ spec:
ComponentDefinition.
items:
properties:
disabled:
default: false
description: Specifies whether the system account is disabled.
type: boolean
name:
description: The name of the system account.
type: string
@@ -5369,6 +5373,11 @@ spec:
namespace:
description: The namespace where the secret is located.
type: string
password:
default: password
description: The key in the secret data that contains
the password.
type: string
required:
- name
- namespace
@@ -14047,6 +14056,11 @@ spec:
ComponentDefinition.
items:
properties:
disabled:
default: false
description: Specifies whether the system account
is disabled.
type: boolean
name:
description: The name of the system account.
type: string
@@ -14106,6 +14120,11 @@ spec:
description: The namespace where the secret is
located.
type: string
password:
default: password
description: The key in the secret data that contains
the password.
type: string
required:
- name
- namespace
41 changes: 23 additions & 18 deletions config/crd/bases/apps.kubeblocks.io_componentdefinitions.yaml
Original file line number Diff line number Diff line change
@@ -4501,9 +4501,9 @@ spec:
The container executing this action has access to following variables:


- KB_ACCOUNT_NAME: The name of the system account to be created.
- KB_ACCOUNT_PASSWORD: The password for the system account. // TODO: how to pass the password securely?
- KB_ACCOUNT_STATEMENT: The statement used to create the system account.
- KB_ACCOUNT_NAME: The name of the system account to be manipulated.
- KB_ACCOUNT_PASSWORD: The password for the system account.
- KB_ACCOUNT_STATEMENT: The statement used to manipulate the system account.


Note: This field is immutable once it has been set.
@@ -16727,30 +16727,35 @@ spec:
Cannot be updated.
type: string
type: object
secretRef:
statement:
description: |-
Refers to the secret from which data will be copied to create the new account.
Defines the statements used to create, delete, and update the account.


This field is immutable once set.
properties:
name:
description: The unique identifier of the secret.
create:
description: |-
The statement to create a new account with the necessary privileges.


This field is immutable once set.
type: string
namespace:
description: The namespace where the secret is located.
delete:
description: |-
The statement to delete a account.


This field is immutable once set.
type: string
required:
- name
- namespace
type: object
statement:
description: |-
Defines the statement used to create the account with the necessary privileges.
update:
description: |-
The statement to update an existing account.


This field is immutable once set.
type: string
This field is immutable once set.
type: string
type: object
required:
- name
type: object
9 changes: 9 additions & 0 deletions config/crd/bases/apps.kubeblocks.io_components.yaml
Original file line number Diff line number Diff line change
@@ -5505,6 +5505,10 @@ spec:
description: Overrides system accounts defined in referenced ComponentDefinition.
items:
properties:
disabled:
default: false
description: Specifies whether the system account is disabled.
type: boolean
name:
description: The name of the system account.
type: string
@@ -5563,6 +5567,11 @@ spec:
namespace:
description: The namespace where the secret is located.
type: string
password:
default: password
description: The key in the secret data that contains the
password.
type: string
required:
- name
- namespace
Original file line number Diff line number Diff line change
@@ -196,6 +196,7 @@ func copyAndMergeComponent(oldCompObj, newCompObj *appsv1.Component) *appsv1.Com
compObjCopy.Spec.VolumeClaimTemplates = compProto.Spec.VolumeClaimTemplates
compObjCopy.Spec.Volumes = compProto.Spec.Volumes
compObjCopy.Spec.Services = compProto.Spec.Services
compObjCopy.Spec.SystemAccounts = compProto.Spec.SystemAccounts
compObjCopy.Spec.Replicas = compProto.Spec.Replicas
compObjCopy.Spec.Configs = compProto.Spec.Configs
compObjCopy.Spec.ServiceAccountName = compProto.Spec.ServiceAccountName
Original file line number Diff line number Diff line change
@@ -118,17 +118,7 @@ func (t *clusterShardingAccountTransformer) newSystemAccountSecret(transCtx *clu
if err != nil {
return nil, err
}

var password []byte
switch {
case account.SecretRef != nil:
var err error
if password, err = t.getPasswordFromSecret(transCtx, account); err != nil {
return nil, err
}
default:
password = t.buildPassword(transCtx, account, sharding.Name)
}
password := t.buildPassword(transCtx, account, sharding.Name)
return t.newAccountSecretWithPassword(transCtx, sharding, accountName, password)
}

@@ -152,7 +142,6 @@ func (t *clusterShardingAccountTransformer) definedSystemAccount(transCtx *clust
if compAccount.PasswordConfig != nil {
account.PasswordGenerationPolicy = *compAccount.PasswordConfig
}
account.SecretRef = compAccount.SecretRef
}
return *account
}
@@ -165,21 +154,6 @@ func (t *clusterShardingAccountTransformer) definedSystemAccount(transCtx *clust
return appsv1.SystemAccount{}, fmt.Errorf("system account %s not found in component definition %s", accountName, compDef.Name)
}

func (t *clusterShardingAccountTransformer) getPasswordFromSecret(ctx graph.TransformContext, account appsv1.SystemAccount) ([]byte, error) {
secretKey := types.NamespacedName{
Namespace: account.SecretRef.Namespace,
Name: account.SecretRef.Name,
}
secret := &corev1.Secret{}
if err := ctx.GetClient().Get(ctx.GetContext(), secretKey, secret); err != nil {
return nil, err
}
if len(secret.Data) == 0 || len(secret.Data[constant.AccountPasswdForSecret]) == 0 {
return nil, fmt.Errorf("referenced account secret has no required credential field")
}
return secret.Data[constant.AccountPasswdForSecret], nil
}

func (t *clusterShardingAccountTransformer) buildPassword(transCtx *clusterTransformContext, account appsv1.SystemAccount, shardingName string) []byte {
password := []byte(factory.GetRestoreSystemAccountPassword(transCtx.Cluster.Annotations, shardingName, account.Name))
if len(password) == 0 {
@@ -227,20 +201,21 @@ func (t *clusterShardingAccountTransformer) rewriteSystemAccount(transCtx *clust
var (
cluster = transCtx.Cluster
)
account := appsv1.ComponentSystemAccount{
newAccount := appsv1.ComponentSystemAccount{
Name: accountName,
SecretRef: &appsv1.ProvisionSecretRef{
Name: shardingAccountSecretName(cluster.Name, sharding.Name, accountName),
Namespace: cluster.Namespace,
},
}
for i := range sharding.Template.SystemAccounts {
if sharding.Template.SystemAccounts[i].Name == accountName {
sharding.Template.SystemAccounts[i] = account
for i, account := range sharding.Template.SystemAccounts {
if account.Name == accountName {
newAccount.Disabled = account.Disabled
sharding.Template.SystemAccounts[i] = newAccount
return
}
}
sharding.Template.SystemAccounts = []appsv1.ComponentSystemAccount{account}
sharding.Template.SystemAccounts = []appsv1.ComponentSystemAccount{newAccount}
}

func shardingAccountSecretName(cluster, sharding, account string) string {
Loading
Loading