1// Copyright 2017 Google LLC 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package storage 16 17import ( 18 "context" 19 20 "cloud.google.com/go/iam" 21 "cloud.google.com/go/internal/trace" 22 raw "google.golang.org/api/storage/v1" 23 iampb "google.golang.org/genproto/googleapis/iam/v1" 24) 25 26// IAM provides access to IAM access control for the bucket. 27func (b *BucketHandle) IAM() *iam.Handle { 28 return iam.InternalNewHandleClient(&iamClient{ 29 raw: b.c.raw, 30 userProject: b.userProject, 31 }, b.name) 32} 33 34// iamClient implements the iam.client interface. 35type iamClient struct { 36 raw *raw.Service 37 userProject string 38} 39 40func (c *iamClient) Get(ctx context.Context, resource string) (p *iampb.Policy, err error) { 41 ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.IAM.Get") 42 defer func() { trace.EndSpan(ctx, err) }() 43 44 call := c.raw.Buckets.GetIamPolicy(resource) 45 setClientHeader(call.Header()) 46 if c.userProject != "" { 47 call.UserProject(c.userProject) 48 } 49 var rp *raw.Policy 50 err = runWithRetry(ctx, func() error { 51 rp, err = call.Context(ctx).Do() 52 return err 53 }) 54 if err != nil { 55 return nil, err 56 } 57 return iamFromStoragePolicy(rp), nil 58} 59 60func (c *iamClient) Set(ctx context.Context, resource string, p *iampb.Policy) (err error) { 61 ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.IAM.Set") 62 defer func() { trace.EndSpan(ctx, err) }() 63 64 rp := iamToStoragePolicy(p) 65 call := c.raw.Buckets.SetIamPolicy(resource, rp) 66 setClientHeader(call.Header()) 67 if c.userProject != "" { 68 call.UserProject(c.userProject) 69 } 70 return runWithRetry(ctx, func() error { 71 _, err := call.Context(ctx).Do() 72 return err 73 }) 74} 75 76func (c *iamClient) Test(ctx context.Context, resource string, perms []string) (permissions []string, err error) { 77 ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.IAM.Test") 78 defer func() { trace.EndSpan(ctx, err) }() 79 80 call := c.raw.Buckets.TestIamPermissions(resource, perms) 81 setClientHeader(call.Header()) 82 if c.userProject != "" { 83 call.UserProject(c.userProject) 84 } 85 var res *raw.TestIamPermissionsResponse 86 err = runWithRetry(ctx, func() error { 87 res, err = call.Context(ctx).Do() 88 return err 89 }) 90 if err != nil { 91 return nil, err 92 } 93 return res.Permissions, nil 94} 95 96func iamToStoragePolicy(ip *iampb.Policy) *raw.Policy { 97 return &raw.Policy{ 98 Bindings: iamToStorageBindings(ip.Bindings), 99 Etag: string(ip.Etag), 100 } 101} 102 103func iamToStorageBindings(ibs []*iampb.Binding) []*raw.PolicyBindings { 104 var rbs []*raw.PolicyBindings 105 for _, ib := range ibs { 106 rbs = append(rbs, &raw.PolicyBindings{ 107 Role: ib.Role, 108 Members: ib.Members, 109 }) 110 } 111 return rbs 112} 113 114func iamFromStoragePolicy(rp *raw.Policy) *iampb.Policy { 115 return &iampb.Policy{ 116 Bindings: iamFromStorageBindings(rp.Bindings), 117 Etag: []byte(rp.Etag), 118 } 119} 120 121func iamFromStorageBindings(rbs []*raw.PolicyBindings) []*iampb.Binding { 122 var ibs []*iampb.Binding 123 for _, rb := range rbs { 124 ibs = append(ibs, &iampb.Binding{ 125 Role: rb.Role, 126 Members: rb.Members, 127 }) 128 } 129 return ibs 130} 131