k8s.io/kubernetes@v1.29.3/pkg/controller/bootstrap/util_test.go (about) 1 /* 2 Copyright 2016 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 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 }