...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package internal
16
17 import (
18 "context"
19 "crypto/rsa"
20 "crypto/x509"
21 "encoding/json"
22 "encoding/pem"
23 "errors"
24 "fmt"
25 "io"
26 "net/http"
27 "os"
28 "sync"
29 "time"
30
31 "cloud.google.com/go/compute/metadata"
32 )
33
34 const (
35
36 TokenTypeBearer = "Bearer"
37
38
39
40 QuotaProjectEnvVar = "GOOGLE_CLOUD_QUOTA_PROJECT"
41 projectEnvVar = "GOOGLE_CLOUD_PROJECT"
42 maxBodySize = 1 << 20
43
44
45
46 DefaultUniverseDomain = "googleapis.com"
47 )
48
49
50 func CloneDefaultClient() *http.Client {
51 return &http.Client{
52 Transport: http.DefaultTransport.(*http.Transport).Clone(),
53 Timeout: 30 * time.Second,
54 }
55 }
56
57
58
59
60
61
62 func ParseKey(key []byte) (*rsa.PrivateKey, error) {
63 block, _ := pem.Decode(key)
64 if block != nil {
65 key = block.Bytes
66 }
67 parsedKey, err := x509.ParsePKCS8PrivateKey(key)
68 if err != nil {
69 parsedKey, err = x509.ParsePKCS1PrivateKey(key)
70 if err != nil {
71 return nil, fmt.Errorf("private key should be a PEM or plain PKCS1 or PKCS8: %w", err)
72 }
73 }
74 parsed, ok := parsedKey.(*rsa.PrivateKey)
75 if !ok {
76 return nil, errors.New("private key is invalid")
77 }
78 return parsed, nil
79 }
80
81
82
83 func GetQuotaProject(b []byte, override string) string {
84 if override != "" {
85 return override
86 }
87 if env := os.Getenv(QuotaProjectEnvVar); env != "" {
88 return env
89 }
90 if b == nil {
91 return ""
92 }
93 var v struct {
94 QuotaProject string `json:"quota_project_id"`
95 }
96 if err := json.Unmarshal(b, &v); err != nil {
97 return ""
98 }
99 return v.QuotaProject
100 }
101
102
103
104 func GetProjectID(b []byte, override string) string {
105 if override != "" {
106 return override
107 }
108 if env := os.Getenv(projectEnvVar); env != "" {
109 return env
110 }
111 if b == nil {
112 return ""
113 }
114 var v struct {
115 ProjectID string `json:"project_id"`
116 Project string `json:"project"`
117 }
118 if err := json.Unmarshal(b, &v); err != nil {
119 return ""
120 }
121 if v.ProjectID != "" {
122 return v.ProjectID
123 }
124 return v.Project
125 }
126
127
128
129 func ReadAll(r io.Reader) ([]byte, error) {
130 return io.ReadAll(io.LimitReader(r, maxBodySize))
131 }
132
133
134
135 func StaticCredentialsProperty(s string) StaticProperty {
136 return StaticProperty(s)
137 }
138
139
140 type StaticProperty string
141
142
143 func (p StaticProperty) GetProperty(context.Context) (string, error) {
144 return string(p), nil
145 }
146
147
148
149 type ComputeUniverseDomainProvider struct {
150 universeDomainOnce sync.Once
151 universeDomain string
152 universeDomainErr error
153 }
154
155
156
157 func (c *ComputeUniverseDomainProvider) GetProperty(ctx context.Context) (string, error) {
158 c.universeDomainOnce.Do(func() {
159 c.universeDomain, c.universeDomainErr = getMetadataUniverseDomain(ctx)
160 })
161 if c.universeDomainErr != nil {
162 return "", c.universeDomainErr
163 }
164 return c.universeDomain, nil
165 }
166
167
168 var httpGetMetadataUniverseDomain = func(ctx context.Context) (string, error) {
169 client := metadata.NewClient(&http.Client{Timeout: time.Second})
170
171 return client.Get("universe/universe_domain")
172 }
173
174 func getMetadataUniverseDomain(ctx context.Context) (string, error) {
175 universeDomain, err := httpGetMetadataUniverseDomain(ctx)
176 if err == nil {
177 return universeDomain, nil
178 }
179 if _, ok := err.(metadata.NotDefinedError); ok {
180
181 return DefaultUniverseDomain, nil
182 }
183 return "", err
184 }
185
View as plain text