From c28d96ed7024588a61c2b6aa9755e1187680fa16 Mon Sep 17 00:00:00 2001 From: Tom Wieczorek Date: Mon, 5 Feb 2024 13:04:24 +0100 Subject: [PATCH] Extract BootstrapToken secret generation in its own function This allows the secret to be created without creating it in the cluster. Signed-off-by: Tom Wieczorek --- pkg/token/manager.go | 78 +++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 33 deletions(-) diff --git a/pkg/token/manager.go b/pkg/token/manager.go index 5fe01dc7c788..dcea57727bd5 100644 --- a/pkg/token/manager.go +++ b/pkg/token/manager.go @@ -22,9 +22,10 @@ import ( "time" "github.com/sirupsen/logrus" - v1 "k8s.io/api/core/v1" + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/fields" "k8s.io/client-go/kubernetes" "github.com/k0sproject/k0s/internal/pkg/random" @@ -65,48 +66,59 @@ type Manager struct { client kubernetes.Interface } -// Create creates a new bootstrap token -func (m *Manager) Create(ctx context.Context, valid time.Duration, role string) (string, error) { +func RandomBootstrapSecret(role string, valid time.Duration) (*corev1.Secret, string, error) { tokenID := random.String(6) tokenSecret := random.String(16) - token := fmt.Sprintf("%s.%s", tokenID, tokenSecret) + s := corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("bootstrap-token-%s", tokenID), + Namespace: "kube-system", + }, + Type: corev1.SecretTypeBootstrapToken, + StringData: map[string]string{ + "token-id": tokenID, + "token-secret": tokenSecret, + + // This "usage-" is shared for all roles of the token which allows + // them to execute calls to the k0s API. This is done because we + // need to call the k0s API from windows workers during the join + // step. + "usage-bootstrap-api-auth": "true", + }, + } - data := make(map[string]string) - data["token-id"] = tokenID - data["token-secret"] = tokenSecret if valid != 0 { - data["expiration"] = time.Now().Add(valid).UTC().Format(time.RFC3339) - logrus.Debugf("Set expiry to %s", data["expiration"]) + exp := time.Now().Add(valid).UTC().Format(time.RFC3339) + s.StringData["expiration"] = exp + logrus.Debug("Set expiry to ", exp) } - // This "usage-" is shared for both roles of the token - // which allows both roles execute calls to the k0s api. - // this is done because we need to call k0s api from - // windows workers during the join step - data["usage-bootstrap-api-auth"] = "true" - - if role == "worker" { - data["description"] = "Worker bootstrap token generated by k0s" - data["usage-bootstrap-authentication"] = "true" - data["usage-bootstrap-api-worker-calls"] = "true" - } else { - data["description"] = "Controller bootstrap token generated by k0s" - data["usage-bootstrap-authentication"] = "false" - data["usage-bootstrap-signing"] = "false" - data["usage-controller-join"] = "true" + switch role { + case "worker": + s.StringData["description"] = "Worker bootstrap token generated by k0s" + s.StringData["usage-bootstrap-authentication"] = "true" + s.StringData["usage-bootstrap-api-worker-calls"] = "true" + case "controller": + s.StringData["description"] = "Controller bootstrap token generated by k0s" + s.StringData["usage-bootstrap-authentication"] = "false" + s.StringData["usage-bootstrap-signing"] = "false" + s.StringData["usage-controller-join"] = "true" + default: + return nil, "", fmt.Errorf("unsupported role %q", role) } - secret := &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("bootstrap-token-%s", tokenID), - Namespace: "kube-system", - }, - Type: v1.SecretTypeBootstrapToken, - StringData: data, + return &s, fmt.Sprintf("%s.%s", tokenID, tokenSecret), nil +} + +// Create creates a new bootstrap token +func (m *Manager) Create(ctx context.Context, valid time.Duration, role string) (string, error) { + secret, token, err := RandomBootstrapSecret(role, valid) + if err != nil { + return "", err } - _, err := m.client.CoreV1().Secrets("kube-system").Create(ctx, secret, metav1.CreateOptions{}) + _, err = m.client.CoreV1().Secrets("kube-system").Create(ctx, secret, metav1.CreateOptions{}) if err != nil { return "", err } @@ -117,7 +129,7 @@ func (m *Manager) Create(ctx context.Context, valid time.Duration, role string) // List returns all the join tokens for given role. If role == "" then it returns all join tokens func (m *Manager) List(ctx context.Context, role string) ([]Token, error) { tokenList, err := m.client.CoreV1().Secrets("kube-system").List(ctx, metav1.ListOptions{ - FieldSelector: "type=bootstrap.kubernetes.io/token", + FieldSelector: fields.OneTermEqualSelector("type", string(corev1.SecretTypeBootstrapToken)).String(), }) if err != nil { return nil, err