...
1
16
17
18 package main
19
20 import (
21 "encoding/json"
22 "errors"
23 "fmt"
24 "io"
25 "net/http"
26
27 credentialproviderv1 "k8s.io/kubelet/pkg/apis/credentialprovider/v1"
28 )
29
30 const (
31 maxReadLength = 10 * 1 << 20
32 )
33
34 var containerRegistryUrls = []string{"container.cloud.google.com", "gcr.io", "*.gcr.io", "*.pkg.dev"}
35
36
37 type HTTPError struct {
38 StatusCode int
39 URL string
40 }
41
42 var _ error = &HTTPError{}
43
44
45 func (h *HTTPError) Error() string {
46 return fmt.Sprintf("http status code: %d while fetching url %s",
47 h.StatusCode, h.URL)
48 }
49
50
51
52 type TokenBlob struct {
53 AccessToken string `json:"access_token"`
54 }
55
56 type provider struct {
57 client *http.Client
58 tokenEndpoint string
59 }
60
61 func (p *provider) Provide(image string) (map[string]credentialproviderv1.AuthConfig, error) {
62 cfg := map[string]credentialproviderv1.AuthConfig{}
63
64 tokenJSONBlob, err := readURL(p.tokenEndpoint, p.client)
65 if err != nil {
66 return cfg, err
67 }
68
69 var parsedBlob TokenBlob
70 if err := json.Unmarshal(tokenJSONBlob, &parsedBlob); err != nil {
71 return cfg, err
72 }
73
74 authConfig := credentialproviderv1.AuthConfig{
75 Username: "_token",
76 Password: parsedBlob.AccessToken,
77 }
78
79
80 for _, k := range containerRegistryUrls {
81 cfg[k] = authConfig
82 }
83 return cfg, nil
84 }
85
86 func readURL(url string, client *http.Client) (body []byte, err error) {
87 req, err := http.NewRequest("GET", url, nil)
88 if err != nil {
89 return nil, err
90 }
91
92 req.Header = http.Header{
93 "Metadata-Flavor": []string{"Google"},
94 }
95
96 resp, err := client.Do(req)
97 if err != nil {
98 return nil, err
99 }
100 defer resp.Body.Close()
101
102 if resp.StatusCode != http.StatusOK {
103 return nil, &HTTPError{
104 StatusCode: resp.StatusCode,
105 URL: url,
106 }
107 }
108
109 limitedReader := &io.LimitedReader{R: resp.Body, N: maxReadLength}
110 contents, err := io.ReadAll(limitedReader)
111 if err != nil {
112 return nil, err
113 }
114
115 if limitedReader.N <= 0 {
116 return nil, errors.New("the read limit is reached")
117 }
118
119 return contents, nil
120 }
121
View as plain text