1
16
17 package bootstrap
18
19 import (
20 "context"
21 "crypto/rand"
22 "encoding/hex"
23 "errors"
24 "time"
25
26 v1 "k8s.io/api/core/v1"
27 apierrors "k8s.io/apimachinery/pkg/api/errors"
28 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29 "k8s.io/apimachinery/pkg/util/wait"
30 clientset "k8s.io/client-go/kubernetes"
31 bootstrapapi "k8s.io/cluster-bootstrap/token/api"
32 "k8s.io/kubernetes/test/e2e/framework"
33 )
34
35 func newTokenSecret(tokenID, tokenSecret string) *v1.Secret {
36 return &v1.Secret{
37 ObjectMeta: metav1.ObjectMeta{
38 Namespace: metav1.NamespaceSystem,
39 Name: bootstrapapi.BootstrapTokenSecretPrefix + tokenID,
40 },
41 Type: bootstrapapi.SecretTypeBootstrapToken,
42 Data: map[string][]byte{
43 bootstrapapi.BootstrapTokenIDKey: []byte(tokenID),
44 bootstrapapi.BootstrapTokenSecretKey: []byte(tokenSecret),
45 bootstrapapi.BootstrapTokenUsageSigningKey: []byte("true"),
46 },
47 }
48 }
49
50
51 func GenerateTokenID() (string, error) {
52 tokenID, err := randBytes(TokenIDBytes)
53 if err != nil {
54 return "", err
55 }
56 return tokenID, nil
57 }
58
59
60 func GenerateTokenSecret() (string, error) {
61 tokenSecret, err := randBytes(TokenSecretBytes)
62 if err != nil {
63 return "", err
64 }
65 return tokenSecret, err
66 }
67
68 func randBytes(length int) (string, error) {
69 b := make([]byte, length)
70 _, err := rand.Read(b)
71 if err != nil {
72 return "", err
73 }
74 return hex.EncodeToString(b), nil
75 }
76
77 func addSecretExpiration(s *v1.Secret, expiration string) {
78 s.Data[bootstrapapi.BootstrapTokenExpirationKey] = []byte(expiration)
79 }
80
81
82
83 func TimeStringFromNow(delta time.Duration) string {
84 return time.Now().Add(delta).UTC().Format(time.RFC3339)
85 }
86
87
88 func WaitforSignedClusterInfoByBootStrapToken(c clientset.Interface, tokenID string) error {
89
90 return wait.Poll(framework.Poll, 2*time.Minute, func() (bool, error) {
91 cfgMap, err := c.CoreV1().ConfigMaps(metav1.NamespacePublic).Get(context.TODO(), bootstrapapi.ConfigMapClusterInfo, metav1.GetOptions{})
92 if err != nil {
93 framework.Failf("Failed to get cluster-info configMap: %v", err)
94 return false, err
95 }
96 _, ok := cfgMap.Data[bootstrapapi.JWSSignatureKeyPrefix+tokenID]
97 if !ok {
98 return false, nil
99 }
100 return true, nil
101 })
102 }
103
104
105 func WaitForSignedClusterInfoGetUpdatedByBootstrapToken(c clientset.Interface, tokenID string, signedToken string) error {
106
107 return wait.Poll(framework.Poll, 2*time.Minute, func() (bool, error) {
108 cfgMap, err := c.CoreV1().ConfigMaps(metav1.NamespacePublic).Get(context.TODO(), bootstrapapi.ConfigMapClusterInfo, metav1.GetOptions{})
109 if err != nil {
110 framework.Failf("Failed to get cluster-info configMap: %v", err)
111 return false, err
112 }
113 updated, ok := cfgMap.Data[bootstrapapi.JWSSignatureKeyPrefix+tokenID]
114 if !ok || updated == signedToken {
115 return false, nil
116 }
117 return true, nil
118 })
119 }
120
121
122 func WaitForSignedClusterInfoByBootstrapTokenToDisappear(c clientset.Interface, tokenID string) error {
123
124 return wait.Poll(framework.Poll, 2*time.Minute, func() (bool, error) {
125 cfgMap, err := c.CoreV1().ConfigMaps(metav1.NamespacePublic).Get(context.TODO(), bootstrapapi.ConfigMapClusterInfo, metav1.GetOptions{})
126 if err != nil {
127 framework.Failf("Failed to get cluster-info configMap: %v", err)
128 return false, err
129 }
130 _, ok := cfgMap.Data[bootstrapapi.JWSSignatureKeyPrefix+tokenID]
131 if ok {
132 return false, nil
133 }
134 return true, nil
135 })
136 }
137
138
139 func WaitForBootstrapTokenSecretToDisappear(c clientset.Interface, tokenID string) error {
140
141 return wait.Poll(framework.Poll, 1*time.Minute, func() (bool, error) {
142 _, err := c.CoreV1().Secrets(metav1.NamespaceSystem).Get(context.TODO(), bootstrapapi.BootstrapTokenSecretPrefix+tokenID, metav1.GetOptions{})
143 if apierrors.IsNotFound(err) {
144 return true, nil
145 }
146 return false, nil
147 })
148 }
149
150
151 func WaitForBootstrapTokenSecretNotDisappear(c clientset.Interface, tokenID string, t time.Duration) error {
152 err := wait.Poll(framework.Poll, t, func() (bool, error) {
153 secret, err := c.CoreV1().Secrets(metav1.NamespaceSystem).Get(context.TODO(), bootstrapapi.BootstrapTokenSecretPrefix+tokenID, metav1.GetOptions{})
154 if apierrors.IsNotFound(err) {
155 return true, errors.New("secret not exists")
156 }
157 if secret != nil {
158 return false, nil
159 }
160 return true, err
161 })
162 if wait.Interrupted(err) {
163 return nil
164 }
165 return err
166 }
167
View as plain text