1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package storage
16
17 import (
18 "context"
19 "errors"
20 "fmt"
21 "time"
22
23 "cloud.google.com/go/storage/internal/apiv2/storagepb"
24 "google.golang.org/api/iterator"
25 raw "google.golang.org/api/storage/v1"
26 )
27
28
29 type HMACState string
30
31 const (
32
33
34 Active HMACState = "ACTIVE"
35
36
37
38 Inactive HMACState = "INACTIVE"
39
40
41
42
43
44 Deleted HMACState = "DELETED"
45 )
46
47
48
49
50
51 type HMACKey struct {
52
53 Secret string
54
55
56 AccessID string
57
58
59 Etag string
60
61
62 ID string
63
64
65
66 ProjectID string
67
68
69
70 ServiceAccountEmail string
71
72
73 CreatedTime time.Time
74
75
76 UpdatedTime time.Time
77
78
79
80 State HMACState
81 }
82
83
84 type HMACKeyHandle struct {
85 projectID string
86 accessID string
87 retry *retryConfig
88 tc storageClient
89 }
90
91
92 func (c *Client) HMACKeyHandle(projectID, accessID string) *HMACKeyHandle {
93 return &HMACKeyHandle{
94 projectID: projectID,
95 accessID: accessID,
96 retry: c.retry,
97 tc: c.tc,
98 }
99 }
100
101
102
103
104
105
106 func (hkh *HMACKeyHandle) Get(ctx context.Context, opts ...HMACKeyOption) (*HMACKey, error) {
107 desc := new(hmacKeyDesc)
108 for _, opt := range opts {
109 opt.withHMACKeyDesc(desc)
110 }
111
112 o := makeStorageOpts(true, hkh.retry, desc.userProjectID)
113 hk, err := hkh.tc.GetHMACKey(ctx, hkh.projectID, hkh.accessID, o...)
114
115 return hk, err
116 }
117
118
119
120
121 func (hkh *HMACKeyHandle) Delete(ctx context.Context, opts ...HMACKeyOption) error {
122 desc := new(hmacKeyDesc)
123 for _, opt := range opts {
124 opt.withHMACKeyDesc(desc)
125 }
126
127 o := makeStorageOpts(true, hkh.retry, desc.userProjectID)
128 return hkh.tc.DeleteHMACKey(ctx, hkh.projectID, hkh.accessID, o...)
129 }
130
131 func toHMACKeyFromRaw(hk *raw.HmacKey, updatedTimeCanBeNil bool) (*HMACKey, error) {
132 hkmd := hk.Metadata
133 if hkmd == nil {
134 return nil, errors.New("field Metadata cannot be nil")
135 }
136 createdTime, err := time.Parse(time.RFC3339, hkmd.TimeCreated)
137 if err != nil {
138 return nil, fmt.Errorf("field CreatedTime: %w", err)
139 }
140 updatedTime, err := time.Parse(time.RFC3339, hkmd.Updated)
141 if err != nil && !updatedTimeCanBeNil {
142 return nil, fmt.Errorf("field UpdatedTime: %w", err)
143 }
144
145 hmKey := &HMACKey{
146 AccessID: hkmd.AccessId,
147 Secret: hk.Secret,
148 Etag: hkmd.Etag,
149 ID: hkmd.Id,
150 State: HMACState(hkmd.State),
151 ProjectID: hkmd.ProjectId,
152 CreatedTime: createdTime,
153 UpdatedTime: updatedTime,
154
155 ServiceAccountEmail: hkmd.ServiceAccountEmail,
156 }
157
158 return hmKey, nil
159 }
160
161 func toHMACKeyFromProto(pbmd *storagepb.HmacKeyMetadata) *HMACKey {
162 if pbmd == nil {
163 return nil
164 }
165
166 return &HMACKey{
167 AccessID: pbmd.GetAccessId(),
168 ID: pbmd.GetId(),
169 State: HMACState(pbmd.GetState()),
170 ProjectID: pbmd.GetProject(),
171 CreatedTime: convertProtoTime(pbmd.GetCreateTime()),
172 UpdatedTime: convertProtoTime(pbmd.GetUpdateTime()),
173 ServiceAccountEmail: pbmd.GetServiceAccountEmail(),
174 }
175 }
176
177
178 func (c *Client) CreateHMACKey(ctx context.Context, projectID, serviceAccountEmail string, opts ...HMACKeyOption) (*HMACKey, error) {
179 if projectID == "" {
180 return nil, errors.New("storage: expecting a non-blank projectID")
181 }
182 if serviceAccountEmail == "" {
183 return nil, errors.New("storage: expecting a non-blank service account email")
184 }
185
186 desc := new(hmacKeyDesc)
187 for _, opt := range opts {
188 opt.withHMACKeyDesc(desc)
189 }
190
191 o := makeStorageOpts(false, c.retry, desc.userProjectID)
192 hk, err := c.tc.CreateHMACKey(ctx, projectID, serviceAccountEmail, o...)
193 return hk, err
194 }
195
196
197 type HMACKeyAttrsToUpdate struct {
198
199 State HMACState
200
201
202 Etag string
203 }
204
205
206 func (h *HMACKeyHandle) Update(ctx context.Context, au HMACKeyAttrsToUpdate, opts ...HMACKeyOption) (*HMACKey, error) {
207 if au.State != Active && au.State != Inactive {
208 return nil, fmt.Errorf("storage: invalid state %q for update, must be either %q or %q", au.State, Active, Inactive)
209 }
210
211 desc := new(hmacKeyDesc)
212 for _, opt := range opts {
213 opt.withHMACKeyDesc(desc)
214 }
215
216 isIdempotent := len(au.Etag) > 0
217 o := makeStorageOpts(isIdempotent, h.retry, desc.userProjectID)
218 hk, err := h.tc.UpdateHMACKey(ctx, h.projectID, desc.forServiceAccountEmail, h.accessID, &au, o...)
219 return hk, err
220 }
221
222
223
224
225 type HMACKeysIterator struct {
226 ctx context.Context
227 raw *raw.ProjectsHmacKeysService
228 projectID string
229 hmacKeys []*HMACKey
230 pageInfo *iterator.PageInfo
231 nextFunc func() error
232 index int
233 desc hmacKeyDesc
234 retry *retryConfig
235 }
236
237
238
239
240 func (c *Client) ListHMACKeys(ctx context.Context, projectID string, opts ...HMACKeyOption) *HMACKeysIterator {
241 desc := new(hmacKeyDesc)
242 for _, opt := range opts {
243 opt.withHMACKeyDesc(desc)
244 }
245
246 o := makeStorageOpts(true, c.retry, desc.userProjectID)
247 return c.tc.ListHMACKeys(ctx, projectID, desc.forServiceAccountEmail, desc.showDeletedKeys, o...)
248 }
249
250
251
252
253
254
255 func (it *HMACKeysIterator) Next() (*HMACKey, error) {
256 if err := it.nextFunc(); err != nil {
257 return nil, err
258 }
259
260 key := it.hmacKeys[it.index]
261 it.index++
262
263 return key, nil
264 }
265
266
267
268
269 func (it *HMACKeysIterator) PageInfo() *iterator.PageInfo { return it.pageInfo }
270
271 func (it *HMACKeysIterator) fetch(pageSize int, pageToken string) (token string, err error) {
272
273
274 call := it.raw.List(it.projectID)
275 setClientHeader(call.Header())
276 if pageToken != "" {
277 call = call.PageToken(pageToken)
278 }
279 if it.desc.showDeletedKeys {
280 call = call.ShowDeletedKeys(true)
281 }
282 if it.desc.userProjectID != "" {
283 call = call.UserProject(it.desc.userProjectID)
284 }
285 if it.desc.forServiceAccountEmail != "" {
286 call = call.ServiceAccountEmail(it.desc.forServiceAccountEmail)
287 }
288 if pageSize > 0 {
289 call = call.MaxResults(int64(pageSize))
290 }
291
292 var resp *raw.HmacKeysMetadata
293 err = run(it.ctx, func(ctx context.Context) error {
294 resp, err = call.Context(ctx).Do()
295 return err
296 }, it.retry, true)
297 if err != nil {
298 return "", err
299 }
300
301 for _, metadata := range resp.Items {
302 hk := &raw.HmacKey{
303 Metadata: metadata,
304 }
305 hkey, err := toHMACKeyFromRaw(hk, true)
306 if err != nil {
307 return "", err
308 }
309 it.hmacKeys = append(it.hmacKeys, hkey)
310 }
311 return resp.NextPageToken, nil
312 }
313
314 type hmacKeyDesc struct {
315 forServiceAccountEmail string
316 showDeletedKeys bool
317 userProjectID string
318 }
319
320
321 type HMACKeyOption interface {
322 withHMACKeyDesc(*hmacKeyDesc)
323 }
324
325 type hmacKeyDescFunc func(*hmacKeyDesc)
326
327 func (hkdf hmacKeyDescFunc) withHMACKeyDesc(hkd *hmacKeyDesc) {
328 hkdf(hkd)
329 }
330
331
332
333
334
335
336 func ForHMACKeyServiceAccountEmail(serviceAccountEmail string) HMACKeyOption {
337 return hmacKeyDescFunc(func(hkd *hmacKeyDesc) {
338 hkd.forServiceAccountEmail = serviceAccountEmail
339 })
340 }
341
342
343 func ShowDeletedHMACKeys() HMACKeyOption {
344 return hmacKeyDescFunc(func(hkd *hmacKeyDesc) {
345 hkd.showDeletedKeys = true
346 })
347 }
348
349
350
351
352
353 func UserProjectForHMACKeys(userProjectID string) HMACKeyOption {
354 return hmacKeyDescFunc(func(hkd *hmacKeyDesc) {
355 hkd.userProjectID = userProjectID
356 })
357 }
358
View as plain text