mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Merge pull request #53929 from wackxu/valuse
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. Validate usage strings when creating bootstrap tokens via kubeadm **What this PR does / why we need it**: fix TODO: Validate usages here so we don't allow something unsupported **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes # **Special notes for your reviewer**: **Release note**: ```release-note NONE ```
This commit is contained in:
commit
5653b69bee
@ -218,6 +218,11 @@ func RunCreateToken(out io.Writer, client clientset.Interface, token string, tok
|
||||
}
|
||||
}
|
||||
|
||||
// validate usages
|
||||
if err := bootstrapapi.ValidateUsages(usages); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err := tokenphase.CreateNewToken(client, token, tokenDuration, usages, extraGroups, description)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -53,7 +53,11 @@ func UpdateOrCreateToken(client clientset.Interface, token string, failIfExists
|
||||
return fmt.Errorf("a token with id %q already exists", tokenID)
|
||||
}
|
||||
// Secret with this ID already exists, update it:
|
||||
secret.Data = encodeTokenSecretData(tokenID, tokenSecret, tokenDuration, usages, extraGroups, description)
|
||||
tokenSecretData, err := encodeTokenSecretData(tokenID, tokenSecret, tokenDuration, usages, extraGroups, description)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
secret.Data = tokenSecretData
|
||||
if _, err := client.CoreV1().Secrets(metav1.NamespaceSystem).Update(secret); err == nil {
|
||||
return nil
|
||||
}
|
||||
@ -63,12 +67,17 @@ func UpdateOrCreateToken(client clientset.Interface, token string, failIfExists
|
||||
|
||||
// Secret does not already exist:
|
||||
if apierrors.IsNotFound(err) {
|
||||
tokenSecretData, err := encodeTokenSecretData(tokenID, tokenSecret, tokenDuration, usages, extraGroups, description)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
secret = &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: secretName,
|
||||
},
|
||||
Type: v1.SecretType(bootstrapapi.SecretTypeBootstrapToken),
|
||||
Data: encodeTokenSecretData(tokenID, tokenSecret, tokenDuration, usages, extraGroups, description),
|
||||
Data: tokenSecretData,
|
||||
}
|
||||
if _, err := client.CoreV1().Secrets(metav1.NamespaceSystem).Create(secret); err == nil {
|
||||
return nil
|
||||
@ -86,7 +95,7 @@ func UpdateOrCreateToken(client clientset.Interface, token string, failIfExists
|
||||
}
|
||||
|
||||
// encodeTokenSecretData takes the token discovery object and an optional duration and returns the .Data for the Secret
|
||||
func encodeTokenSecretData(tokenID, tokenSecret string, duration time.Duration, usages []string, extraGroups []string, description string) map[string][]byte {
|
||||
func encodeTokenSecretData(tokenID, tokenSecret string, duration time.Duration, usages []string, extraGroups []string, description string) (map[string][]byte, error) {
|
||||
data := map[string][]byte{
|
||||
bootstrapapi.BootstrapTokenIDKey: []byte(tokenID),
|
||||
bootstrapapi.BootstrapTokenSecretKey: []byte(tokenSecret),
|
||||
@ -104,9 +113,13 @@ func encodeTokenSecretData(tokenID, tokenSecret string, duration time.Duration,
|
||||
if len(description) > 0 {
|
||||
data[bootstrapapi.BootstrapTokenDescriptionKey] = []byte(description)
|
||||
}
|
||||
|
||||
// validate usages
|
||||
if err := bootstrapapi.ValidateUsages(usages); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, usage := range usages {
|
||||
// TODO: Validate the usage string here before
|
||||
data[bootstrapapi.BootstrapTokenUsagePrefix+usage] = []byte("true")
|
||||
}
|
||||
return data
|
||||
return data, nil
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ func TestEncodeTokenSecretData(t *testing.T) {
|
||||
{token: &kubeadmapi.TokenDiscovery{ID: "foo", Secret: "bar"}, t: time.Second}, // should use default
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := encodeTokenSecretData(rt.token.ID, rt.token.Secret, rt.t, []string{}, []string{}, "")
|
||||
actual, _ := encodeTokenSecretData(rt.token.ID, rt.token.Secret, rt.t, []string{}, []string{}, "")
|
||||
if !bytes.Equal(actual["token-id"], []byte(rt.token.ID)) {
|
||||
t.Errorf(
|
||||
"failed EncodeTokenSecretData:\n\texpected: %s\n\t actual: %s",
|
||||
|
@ -14,7 +14,10 @@ go_library(
|
||||
"types.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/bootstrap/api",
|
||||
deps = ["//vendor/k8s.io/api/core/v1:go_default_library"],
|
||||
deps = [
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
|
@ -18,7 +18,9 @@ package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var bootstrapGroupRegexp = regexp.MustCompile(`\A` + BootstrapGroupPattern + `\z`)
|
||||
@ -32,3 +34,19 @@ func ValidateBootstrapGroupName(name string) error {
|
||||
}
|
||||
return fmt.Errorf("bootstrap group %q is invalid (must match %s)", name, BootstrapGroupPattern)
|
||||
}
|
||||
|
||||
// ValidateUsages validates that the passed in string are valid usage strings for bootstrap tokens.
|
||||
func ValidateUsages(usages []string) error {
|
||||
usageAuthentication := strings.TrimPrefix(BootstrapTokenUsageAuthentication, BootstrapTokenUsagePrefix)
|
||||
usageSigning := strings.TrimPrefix(BootstrapTokenUsageSigningKey, BootstrapTokenUsagePrefix)
|
||||
invalidUsages := sets.NewString()
|
||||
for _, usage := range usages {
|
||||
if usage != usageAuthentication && usage != usageSigning {
|
||||
invalidUsages.Insert(usage)
|
||||
}
|
||||
}
|
||||
if len(invalidUsages) > 0 {
|
||||
return fmt.Errorf("invalide bootstrap token usage string: %s, valid usage option: %s, %s", strings.Join(invalidUsages.List(), ","), usageAuthentication, usageSigning)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -50,3 +50,27 @@ func TestValidateBootstrapGroupName(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateUsages(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input []string
|
||||
valid bool
|
||||
}{
|
||||
{"valid of signing", []string{"signing"}, true},
|
||||
{"valid of authentication", []string{"authentication"}, true},
|
||||
{"all valid", []string{"authentication", "signing"}, true},
|
||||
{"single invalid", []string{"authentication", "foo"}, false},
|
||||
{"all invalid", []string{"foo", "bar"}, false},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
err := ValidateUsages(test.input)
|
||||
if err != nil && test.valid {
|
||||
t.Errorf("test %q: ValidateUsages(%v) returned unexpected error: %v", test.name, test.input, err)
|
||||
}
|
||||
if err == nil && !test.valid {
|
||||
t.Errorf("test %q: ValidateUsages(%v) was supposed to return an error but didn't", test.name, test.input)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user