1
16
17
20 package bootstrap
21
22 import (
23 "context"
24 "crypto/subtle"
25 "fmt"
26 "time"
27
28 "k8s.io/klog/v2"
29
30 corev1 "k8s.io/api/core/v1"
31 "k8s.io/apimachinery/pkg/api/errors"
32 "k8s.io/apiserver/pkg/authentication/authenticator"
33 "k8s.io/apiserver/pkg/authentication/user"
34 corev1listers "k8s.io/client-go/listers/core/v1"
35 bootstrapapi "k8s.io/cluster-bootstrap/token/api"
36 bootstrapsecretutil "k8s.io/cluster-bootstrap/util/secrets"
37 bootstraptokenutil "k8s.io/cluster-bootstrap/util/tokens"
38 )
39
40
41
42
43
44
45
46
47 func NewTokenAuthenticator(lister corev1listers.SecretNamespaceLister) *TokenAuthenticator {
48 return &TokenAuthenticator{lister}
49 }
50
51
52 type TokenAuthenticator struct {
53 lister corev1listers.SecretNamespaceLister
54 }
55
56
57
58
59
60 func tokenErrorf(s *corev1.Secret, format string, i ...interface{}) {
61 format = fmt.Sprintf("Bootstrap secret %s/%s matching bearer token ", s.Namespace, s.Name) + format
62 klog.V(3).Infof(format, i...)
63 }
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90 func (t *TokenAuthenticator) AuthenticateToken(ctx context.Context, token string) (*authenticator.Response, bool, error) {
91 tokenID, tokenSecret, err := bootstraptokenutil.ParseToken(token)
92 if err != nil {
93
94 return nil, false, nil
95 }
96
97 secretName := bootstrapapi.BootstrapTokenSecretPrefix + tokenID
98 secret, err := t.lister.Get(secretName)
99 if err != nil {
100 if errors.IsNotFound(err) {
101 klog.V(3).Infof("No secret of name %s to match bootstrap bearer token", secretName)
102 return nil, false, nil
103 }
104 return nil, false, err
105 }
106
107 if secret.DeletionTimestamp != nil {
108 tokenErrorf(secret, "is deleted and awaiting removal")
109 return nil, false, nil
110 }
111
112 if string(secret.Type) != string(bootstrapapi.SecretTypeBootstrapToken) || secret.Data == nil {
113 tokenErrorf(secret, "has invalid type, expected %s.", bootstrapapi.SecretTypeBootstrapToken)
114 return nil, false, nil
115 }
116
117 ts := bootstrapsecretutil.GetData(secret, bootstrapapi.BootstrapTokenSecretKey)
118 if subtle.ConstantTimeCompare([]byte(ts), []byte(tokenSecret)) != 1 {
119 tokenErrorf(secret, "has invalid value for key %s.", bootstrapapi.BootstrapTokenSecretKey)
120 return nil, false, nil
121 }
122
123 id := bootstrapsecretutil.GetData(secret, bootstrapapi.BootstrapTokenIDKey)
124 if id != tokenID {
125 tokenErrorf(secret, "has invalid value for key %s.", bootstrapapi.BootstrapTokenIDKey)
126 return nil, false, nil
127 }
128
129 if bootstrapsecretutil.HasExpired(secret, time.Now()) {
130
131 return nil, false, nil
132 }
133
134 if bootstrapsecretutil.GetData(secret, bootstrapapi.BootstrapTokenUsageAuthentication) != "true" {
135 tokenErrorf(secret, "not marked %s=true.", bootstrapapi.BootstrapTokenUsageAuthentication)
136 return nil, false, nil
137 }
138
139 groups, err := bootstrapsecretutil.GetGroups(secret)
140 if err != nil {
141 tokenErrorf(secret, "has invalid value for key %s: %v.", bootstrapapi.BootstrapTokenExtraGroupsKey, err)
142 return nil, false, nil
143 }
144
145 return &authenticator.Response{
146 User: &user.DefaultInfo{
147 Name: bootstrapapi.BootstrapUserPrefix + string(id),
148 Groups: groups,
149 },
150 }, true, nil
151 }
152
View as plain text