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

🐛 Fix rke2 registration token being created twice - backport to release-0.2 #240

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 62 additions & 8 deletions bootstrap/internal/controllers/rke2config_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,14 +334,28 @@ func (r *RKE2ConfigReconciler) handleClusterNotInitialized(ctx context.Context,

conditions.MarkTrue(scope.Config, bootstrapv1.CertificatesAvailableCondition)

token, err := r.generateAndStoreToken(ctx, scope)
// RKE2 server token must only be generated once, so all nodes join the cluster with the same registration token.
var token string

tokenName := bsutil.TokenName(scope.Cluster.Name)
token, err := r.generateAndStoreToken(ctx, scope, tokenName)

if err != nil {
scope.Logger.Error(err, "unable to generate and store an RKE2 server token")
if !apierrors.IsAlreadyExists(err) {
scope.Logger.Error(err, "unable to generate and store an RKE2 server token")

return ctrl.Result{}, err
}
return ctrl.Result{}, err
}

scope.Logger.Info("RKE2 server token generated and stored in Secret!")
token, err = r.getRegistrationTokenFromSecretValue(ctx, tokenName, scope.Cluster.Namespace)
if err != nil {
scope.Logger.Error(err, "unable to retrieve an RKE2 server token from existing secret")

return ctrl.Result{}, err
}
} else {
scope.Logger.Info("RKE2 server token generated and stored in Secret!")
}

configStruct, configFiles, err := rke2.GenerateInitControlPlaneConfig(
rke2.ServerConfigOpts{
Expand Down Expand Up @@ -730,8 +744,24 @@ func (r *RKE2ConfigReconciler) joinWorker(ctx context.Context, scope *Scope) (re
return ctrl.Result{}, nil
}

// getRegistrationTokenFromSecretValue retrieves the registration token from an existing secret's value.
func (r *RKE2ConfigReconciler) getRegistrationTokenFromSecretValue(ctx context.Context, name, namespace string) (string, error) {
tokenSecret := &corev1.Secret{}
secretKey := types.NamespacedName{
Name: name,
Namespace: namespace,
}

err := r.Client.Get(ctx, secretKey, tokenSecret)
if err != nil {
return "", errors.Wrapf(err, "could not retrieve secret %s/%s", namespace, name)
}

return string(tokenSecret.Data["value"]), nil
}

// generateAndStoreToken generates a random token with 16 characters then stores it in a Secret in the API.
func (r *RKE2ConfigReconciler) generateAndStoreToken(ctx context.Context, scope *Scope) (string, error) {
func (r *RKE2ConfigReconciler) generateAndStoreToken(ctx context.Context, scope *Scope, name string) (string, error) {
token, err := bsutil.Random(defaultTokenLength)
if err != nil {
return "", err
Expand All @@ -741,7 +771,7 @@ func (r *RKE2ConfigReconciler) generateAndStoreToken(ctx context.Context, scope

secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: bsutil.TokenName(scope.Cluster.Name),
Name: name,
Namespace: scope.Config.Namespace,
Labels: map[string]string{
clusterv1.ClusterNameLabel: scope.Cluster.Name,
Expand All @@ -762,7 +792,7 @@ func (r *RKE2ConfigReconciler) generateAndStoreToken(ctx context.Context, scope
Type: clusterv1.ClusterSecretType,
}

if err := r.createOrUpdateSecretFromObject(ctx, *secret, scope.Logger, "token", *scope.Config); err != nil {
if err := r.createSecretFromObject(ctx, *secret, scope.Logger, "token", *scope.Config); err != nil {
return "", err
}

Expand Down Expand Up @@ -806,6 +836,30 @@ func (r *RKE2ConfigReconciler) storeBootstrapData(ctx context.Context, scope *Sc
return nil
}

// createSecretFromObject tries to create the given secret in the API, if that secret exists it will return an error.
func (r *RKE2ConfigReconciler) createSecretFromObject(
ctx context.Context,
secret corev1.Secret,
logger logr.Logger,
secretType string,
config bootstrapv1.RKE2Config,
) (reterr error) {
if err := r.Client.Create(ctx, &secret); err != nil {
if !apierrors.IsAlreadyExists(err) {
return errors.Wrapf(err, "failed to create %s secret for %s: %s/%s", secretType, config.Kind, config.Name, config.Namespace)
}

logger.Info("Secret already exists, won't update it",
"secret-type", secretType,
"secret-ref", secret.Namespace+"/"+secret.Name,
"RKE2Config", config.Name)

return err
}

return
}

// createOrUpdateSecret tries to create the given secret in the API, if that secret exists it will update it.
func (r *RKE2ConfigReconciler) createOrUpdateSecretFromObject(
ctx context.Context,
Expand Down