Skip to content
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
############# builder #############
FROM golang:1.23.3 AS builder
FROM golang:1.24.1 AS builder

WORKDIR /go/src/github.com/gardener/machine-controller-manager
COPY . .
Expand Down
3 changes: 1 addition & 2 deletions pkg/controller/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -465,8 +465,7 @@ func (c *controller) machineCreate(machine *v1alpha1.Machine, driver driver.Driv
c.updateMachineStatus(machine, lastOperation, currentStatus)

var actualProviderID, nodeName string

err := c.addBootstrapTokenToUserData(machine.Name, driver)
err := c.addBootstrapTokenToUserData(machine.Spec.NodeTemplateSpec.Labels, machine.Name, driver)
if err != nil {
klog.Errorf("Error while creating bootstrap token for machine %s: %s", machine.Name, err.Error())
lastOperation := v1alpha1.LastOperation{
Expand Down
121 changes: 91 additions & 30 deletions pkg/controller/machine_bootstrap_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ package controller
import (
"crypto/rand"
"encoding/hex"
"fmt"
"math/big"
"sort"
"strings"
"time"

Expand All @@ -36,12 +38,27 @@ import (
)

const placeholder = "<<BOOTSTRAP_TOKEN>>"
const maxRetriesGetBootstrapToken = 5
const retryIntervalBootstrapToken = 3 * time.Second

func (c *controller) addBootstrapTokenToUserData(machineName string, driver driver.Driver) error {
func (c *controller) addBootstrapTokenToUserData(machineLabels map[string]string, machineName string, driver driver.Driver) error {
userData := driver.GetUserData()
klog.V(4).Infof("Creating bootstrap token!")
bootstrapTokenSecret, err := c.getBootstrapTokenOrCreateIfNotExist(machineName)
var bootstrapTokenSecret *v1.Secret
var err error
for attempt := 1; attempt <= maxRetriesGetBootstrapToken; attempt++ {
bootstrapTokenSecret, err = c.getBootstrapTokenOrCreateIfNotExist(machineLabels, machineName)
if err == nil {
break
}

klog.Warningf("attempt %d/%d: failed to get or create bootstrap token: %v", attempt, maxRetriesGetBootstrapToken, err)
if attempt < maxRetriesGetBootstrapToken {
time.Sleep(retryIntervalBootstrapToken)
}
}
if err != nil {
klog.Errorf("all %d attempts failed to get or create bootstrap token: %v", maxRetriesGetBootstrapToken, err)
return err
}

Expand All @@ -56,41 +73,85 @@ func (c *controller) addBootstrapTokenToUserData(machineName string, driver driv
return nil
}

func (c *controller) getBootstrapTokenOrCreateIfNotExist(machineName string) (secret *v1.Secret, err error) {
tokenID, secretName := getTokenIDAndSecretName(machineName)
func (c *controller) getBootstrapTokenOrCreateIfNotExist(machineLabels map[string]string, machineName string) (secret *v1.Secret, err error) {
if machineLabels == nil {
klog.Warningf("failed to get labels from machine: '%s'\nCreating bootstrap token by MCM!", machineName)
mcmToken, err := c.createBootstrapToken(machineName)
if err != nil {
return nil, err
}
return mcmToken, nil
}

secret, err = c.targetCoreClient.CoreV1().Secrets(metav1.NamespaceSystem).Get(secretName, metav1.GetOptions{})
value, ok := machineLabels["node.deckhouse.io/group"]
if !ok || value == "" {
klog.Warningf("failed to get nodegroup name from spec node.deckhouse.io/group of machine: '%s'\nCreating bootstrap token by MCM!", machineName)
mcmToken, err := c.createBootstrapToken(machineName)
if err != nil {
return nil, err
}
return mcmToken, nil
}
labelSelector := fmt.Sprintf("node-manager.deckhouse.io/node-group=%s", value)
secretListNodeManager, err := c.targetCoreClient.CoreV1().Secrets(metav1.NamespaceSystem).List(metav1.ListOptions{
LabelSelector: labelSelector,
})
if err != nil {
if apierrors.IsNotFound(err) {
bootstrapTokenSecretKey, err := generateRandomStringFromCharset(16, "0123456789abcdefghijklmnopqrstuvwxyz")
if err != nil {
return nil, err
}
data := map[string][]byte{
bootstraptokenapi.BootstrapTokenDescriptionKey: []byte("A bootstrap token generated by MachineControllManager."),
bootstraptokenapi.BootstrapTokenIDKey: []byte(tokenID),
bootstraptokenapi.BootstrapTokenSecretKey: []byte(bootstrapTokenSecretKey),
bootstraptokenapi.BootstrapTokenExpirationKey: []byte(metav1.Now().Add(c.safetyOptions.MachineCreationTimeout.Duration).Format(time.RFC3339)),
bootstraptokenapi.BootstrapTokenUsageAuthentication: []byte("true"),
bootstraptokenapi.BootstrapTokenUsageSigningKey: []byte("true"),
bootstraptokenapi.BootstrapTokenExtraGroupsKey: []byte(c.bootstrapTokenAuthExtraGroups),
}

secret = &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: secretName,
Namespace: metav1.NamespaceSystem,
},
Type: bootstraptokenapi.SecretTypeBootstrapToken,
Data: data,
klog.Warningf("failed to list secrets in namespace kube-system created by node-manager: '%v'\nCreating bootstrap token by MCM!", err)
mcmToken, err := c.createBootstrapToken(machineName)
if err != nil {
return nil, err
}
return mcmToken, nil
}
if len(secretListNodeManager.Items) != 0 {
var filteredSecrets []*v1.Secret
for i := range secretListNodeManager.Items {
if strings.HasPrefix(secretListNodeManager.Items[i].Name, bootstraptokenapi.BootstrapTokenSecretPrefix) {
filteredSecrets = append(filteredSecrets, &secretListNodeManager.Items[i])
}

return c.targetCoreClient.CoreV1().Secrets(metav1.NamespaceSystem).Create(secret)
}
sort.Slice(filteredSecrets, func(i, j int) bool {
timeI := filteredSecrets[i].CreationTimestamp.Time
timeJ := filteredSecrets[j].CreationTimestamp.Time
return timeI.After(timeJ)
})
return filteredSecrets[0], nil
}
klog.Warningf("failed to get bootstrap token created by node-manager\nCreating bootstrap token from MCM!")
mcmToken, err := c.createBootstrapToken(machineName)
if err != nil {
return nil, err
}
return mcmToken, nil
}

func (c *controller) createBootstrapToken(machineName string) (secret *v1.Secret, err error) {
tokenID, secretName := getTokenIDAndSecretName(machineName)
bootstrapTokenSecretKey, err := generateRandomStringFromCharset(16, "0123456789abcdefghijklmnopqrstuvwxyz")
if err != nil {
return nil, err
}
data := map[string][]byte{
bootstraptokenapi.BootstrapTokenDescriptionKey: []byte("A bootstrap token generated by MachineControllManager."),
bootstraptokenapi.BootstrapTokenIDKey: []byte(tokenID),
bootstraptokenapi.BootstrapTokenSecretKey: []byte(bootstrapTokenSecretKey),
bootstraptokenapi.BootstrapTokenExpirationKey: []byte(metav1.Now().Add(c.safetyOptions.MachineCreationTimeout.Duration).Format(time.RFC3339)),
bootstraptokenapi.BootstrapTokenUsageAuthentication: []byte("true"),
bootstraptokenapi.BootstrapTokenUsageSigningKey: []byte("true"),
bootstraptokenapi.BootstrapTokenExtraGroupsKey: []byte(c.bootstrapTokenAuthExtraGroups),
}

secret = &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: secretName,
Namespace: metav1.NamespaceSystem,
},
Type: bootstraptokenapi.SecretTypeBootstrapToken,
Data: data,
}

return secret, nil
return c.targetCoreClient.CoreV1().Secrets(metav1.NamespaceSystem).Create(secret)
}

func (c *controller) deleteBootstrapToken(machineName string) error {
Expand Down
Loading