refactor bootstrap token utils

This commit is contained in:
Di Xu
2019-04-29 20:52:48 +08:00
parent 00e13dbc12
commit af9ae4c11a
11 changed files with 352 additions and 296 deletions

View File

@@ -23,20 +23,18 @@ import (
"context"
"crypto/subtle"
"fmt"
"regexp"
"strings"
"time"
"k8s.io/klog"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apiserver/pkg/authentication/authenticator"
"k8s.io/apiserver/pkg/authentication/user"
corev1listers "k8s.io/client-go/listers/core/v1"
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
bootstraputil "k8s.io/cluster-bootstrap/token/util"
bootstrapsecretutil "k8s.io/cluster-bootstrap/util/secrets"
bootstraptokenutil "k8s.io/cluster-bootstrap/util/tokens"
)
// TODO: A few methods in this package is copied from other sources. Either
@@ -92,7 +90,7 @@ func tokenErrorf(s *corev1.Secret, format string, i ...interface{}) {
// ( token-id ).( token-secret )
//
func (t *TokenAuthenticator) AuthenticateToken(ctx context.Context, token string) (*authenticator.Response, bool, error) {
tokenID, tokenSecret, err := parseToken(token)
tokenID, tokenSecret, err := bootstraptokenutil.ParseToken(token)
if err != nil {
// Token isn't of the correct form, ignore it.
return nil, false, nil
@@ -118,29 +116,29 @@ func (t *TokenAuthenticator) AuthenticateToken(ctx context.Context, token string
return nil, false, nil
}
ts := getSecretString(secret, bootstrapapi.BootstrapTokenSecretKey)
ts := bootstrapsecretutil.GetData(secret, bootstrapapi.BootstrapTokenSecretKey)
if subtle.ConstantTimeCompare([]byte(ts), []byte(tokenSecret)) != 1 {
tokenErrorf(secret, "has invalid value for key %s, expected %s.", bootstrapapi.BootstrapTokenSecretKey, tokenSecret)
return nil, false, nil
}
id := getSecretString(secret, bootstrapapi.BootstrapTokenIDKey)
id := bootstrapsecretutil.GetData(secret, bootstrapapi.BootstrapTokenIDKey)
if id != tokenID {
tokenErrorf(secret, "has invalid value for key %s, expected %s.", bootstrapapi.BootstrapTokenIDKey, tokenID)
return nil, false, nil
}
if isSecretExpired(secret) {
if bootstrapsecretutil.HasExpired(secret, time.Now()) {
// logging done in isSecretExpired method.
return nil, false, nil
}
if getSecretString(secret, bootstrapapi.BootstrapTokenUsageAuthentication) != "true" {
if bootstrapsecretutil.GetData(secret, bootstrapapi.BootstrapTokenUsageAuthentication) != "true" {
tokenErrorf(secret, "not marked %s=true.", bootstrapapi.BootstrapTokenUsageAuthentication)
return nil, false, nil
}
groups, err := getGroups(secret)
groups, err := bootstrapsecretutil.GetGroups(secret)
if err != nil {
tokenErrorf(secret, "has invalid value for key %s: %v.", bootstrapapi.BootstrapTokenExtraGroupsKey, err)
return nil, false, nil
@@ -153,76 +151,3 @@ func (t *TokenAuthenticator) AuthenticateToken(ctx context.Context, token string
},
}, true, nil
}
// Copied from k8s.io/cluster-bootstrap/token/api
func getSecretString(secret *corev1.Secret, key string) string {
data, ok := secret.Data[key]
if !ok {
return ""
}
return string(data)
}
// Copied from k8s.io/cluster-bootstrap/token/api
func isSecretExpired(secret *corev1.Secret) bool {
expiration := getSecretString(secret, bootstrapapi.BootstrapTokenExpirationKey)
if len(expiration) > 0 {
expTime, err2 := time.Parse(time.RFC3339, expiration)
if err2 != nil {
klog.V(3).Infof("Unparseable expiration time (%s) in %s/%s Secret: %v. Treating as expired.",
expiration, secret.Namespace, secret.Name, err2)
return true
}
if time.Now().After(expTime) {
klog.V(3).Infof("Expired bootstrap token in %s/%s Secret: %v",
secret.Namespace, secret.Name, expiration)
return true
}
}
return false
}
// Copied from kubernetes/cmd/kubeadm/app/util/token
var (
// tokenRegexpString defines id.secret regular expression pattern
tokenRegexpString = "^([a-z0-9]{6})\\.([a-z0-9]{16})$"
// tokenRegexp is a compiled regular expression of TokenRegexpString
tokenRegexp = regexp.MustCompile(tokenRegexpString)
)
// parseToken tries and parse a valid token from a string.
// A token ID and token secret are returned in case of success, an error otherwise.
func parseToken(s string) (string, string, error) {
split := tokenRegexp.FindStringSubmatch(s)
if len(split) != 3 {
return "", "", fmt.Errorf("token [%q] was not of form [%q]", s, tokenRegexpString)
}
return split[1], split[2], nil
}
// getGroups loads and validates the bootstrapapi.BootstrapTokenExtraGroupsKey
// key from the bootstrap token secret, returning a list of group names or an
// error if any of the group names are invalid.
func getGroups(secret *corev1.Secret) ([]string, error) {
// always include the default group
groups := sets.NewString(bootstrapapi.BootstrapDefaultGroup)
// grab any extra groups and if there are none, return just the default
extraGroupsString := getSecretString(secret, bootstrapapi.BootstrapTokenExtraGroupsKey)
if extraGroupsString == "" {
return groups.List(), nil
}
// validate the names of the extra groups
for _, group := range strings.Split(extraGroupsString, ",") {
if err := bootstraputil.ValidateBootstrapGroupName(group); err != nil {
return nil, err
}
groups.Insert(group)
}
// return the result as a deduplicated, sorted list
return groups.List(), nil
}