1
16
17 package bootstrap
18
19 import (
20 "testing"
21 "time"
22
23 "k8s.io/api/core/v1"
24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25 bootstrapapi "k8s.io/cluster-bootstrap/token/api"
26 "k8s.io/klog/v2/ktesting"
27 )
28
29 const (
30 givenTokenID = "abc123"
31 givenTokenID2 = "def456"
32 givenTokenSecret = "tokenSecret"
33 )
34
35 func timeString(delta time.Duration) string {
36 return time.Now().Add(delta).Format(time.RFC3339)
37 }
38
39 func TestValidateSecretForSigning(t *testing.T) {
40 cases := []struct {
41 description string
42 tokenID string
43 tokenSecret string
44 okToSign string
45 expiration string
46 valid bool
47 }{
48 {
49 "Signing token with no exp",
50 givenTokenID, givenTokenSecret, "true", "", true,
51 },
52 {
53 "Signing token with valid exp",
54 givenTokenID, givenTokenSecret, "true", timeString(time.Hour), true,
55 },
56 {
57 "Expired signing token",
58 givenTokenID, givenTokenSecret, "true", timeString(-time.Hour), false,
59 },
60 {
61 "Signing token with bad exp",
62 givenTokenID, givenTokenSecret, "true", "garbage", false,
63 },
64 {
65 "Signing token without signing bit",
66 givenTokenID, givenTokenSecret, "", "garbage", false,
67 },
68 {
69 "Signing token with bad signing bit",
70 givenTokenID, givenTokenSecret, "", "", false,
71 },
72 {
73 "Signing token with no ID",
74 "", givenTokenSecret, "true", "", false,
75 },
76 {
77 "Signing token with no secret",
78 givenTokenID, "", "true", "", false,
79 },
80 }
81
82 for _, tc := range cases {
83 t.Run(tc.description, func(t *testing.T) {
84 _, ctx := ktesting.NewTestContext(t)
85 secret := &v1.Secret{
86 ObjectMeta: metav1.ObjectMeta{
87 Namespace: metav1.NamespaceSystem,
88 Name: bootstrapapi.BootstrapTokenSecretPrefix + givenTokenID,
89 ResourceVersion: "1",
90 },
91 Type: bootstrapapi.SecretTypeBootstrapToken,
92 Data: map[string][]byte{
93 bootstrapapi.BootstrapTokenIDKey: []byte(tc.tokenID),
94 bootstrapapi.BootstrapTokenSecretKey: []byte(tc.tokenSecret),
95 bootstrapapi.BootstrapTokenUsageSigningKey: []byte(tc.okToSign),
96 bootstrapapi.BootstrapTokenExpirationKey: []byte(tc.expiration),
97 },
98 }
99
100 tokenID, tokenSecret, ok := validateSecretForSigning(ctx, secret)
101 if ok != tc.valid {
102 t.Errorf("Unexpected validation failure. Expected %v, got %v", tc.valid, ok)
103 }
104 if ok {
105 if tokenID != tc.tokenID {
106 t.Errorf("Unexpected Token ID. Expected %q, got %q", givenTokenID, tokenID)
107 }
108 if tokenSecret != tc.tokenSecret {
109 t.Errorf("Unexpected Token Secret. Expected %q, got %q", givenTokenSecret, tokenSecret)
110 }
111 }
112 })
113 }
114
115 }
116
117 func TestValidateSecret(t *testing.T) {
118 _, ctx := ktesting.NewTestContext(t)
119 secret := &v1.Secret{
120 ObjectMeta: metav1.ObjectMeta{
121 Namespace: metav1.NamespaceSystem,
122 Name: bootstrapapi.BootstrapTokenSecretPrefix + givenTokenID,
123 ResourceVersion: "1",
124 },
125 Type: bootstrapapi.SecretTypeBootstrapToken,
126 Data: map[string][]byte{
127 bootstrapapi.BootstrapTokenIDKey: []byte(givenTokenID),
128 bootstrapapi.BootstrapTokenSecretKey: []byte(givenTokenSecret),
129 bootstrapapi.BootstrapTokenUsageSigningKey: []byte("true"),
130 },
131 }
132
133 tokenID, tokenSecret, ok := validateSecretForSigning(ctx, secret)
134 if !ok {
135 t.Errorf("Unexpected validation failure.")
136 }
137 if tokenID != givenTokenID {
138 t.Errorf("Unexpected Token ID. Expected %q, got %q", givenTokenID, tokenID)
139 }
140 if tokenSecret != givenTokenSecret {
141 t.Errorf("Unexpected Token Secret. Expected %q, got %q", givenTokenSecret, tokenSecret)
142 }
143 }
144
145 func TestBadSecretName(t *testing.T) {
146 _, ctx := ktesting.NewTestContext(t)
147 secret := &v1.Secret{
148 ObjectMeta: metav1.ObjectMeta{
149 Namespace: metav1.NamespaceSystem,
150 Name: givenTokenID,
151 ResourceVersion: "1",
152 },
153 Type: bootstrapapi.SecretTypeBootstrapToken,
154 Data: map[string][]byte{
155 bootstrapapi.BootstrapTokenIDKey: []byte(givenTokenID),
156 bootstrapapi.BootstrapTokenSecretKey: []byte(givenTokenSecret),
157 bootstrapapi.BootstrapTokenUsageSigningKey: []byte("true"),
158 },
159 }
160
161 _, _, ok := validateSecretForSigning(ctx, secret)
162 if ok {
163 t.Errorf("Token validation should fail with bad name")
164 }
165 }
166
167 func TestMismatchSecretName(t *testing.T) {
168 _, ctx := ktesting.NewTestContext(t)
169 secret := &v1.Secret{
170 ObjectMeta: metav1.ObjectMeta{
171 Namespace: metav1.NamespaceSystem,
172 Name: bootstrapapi.BootstrapTokenSecretPrefix + givenTokenID2,
173 ResourceVersion: "1",
174 },
175 Type: bootstrapapi.SecretTypeBootstrapToken,
176 Data: map[string][]byte{
177 bootstrapapi.BootstrapTokenIDKey: []byte(givenTokenID),
178 bootstrapapi.BootstrapTokenSecretKey: []byte(givenTokenSecret),
179 bootstrapapi.BootstrapTokenUsageSigningKey: []byte("true"),
180 },
181 }
182
183 _, _, ok := validateSecretForSigning(ctx, secret)
184 if ok {
185 t.Errorf("Token validation should fail with mismatched name")
186 }
187 }
188
View as plain text