]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/cloud.google.com/go/iam/iam.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / cloud.google.com / go / iam / iam.go
1 // Copyright 2016 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
15 // Package iam supports the resource-specific operations of Google Cloud
16 // IAM (Identity and Access Management) for the Google Cloud Libraries.
17 // See https://cloud.google.com/iam for more about IAM.
18 //
19 // Users of the Google Cloud Libraries will typically not use this package
20 // directly. Instead they will begin with some resource that supports IAM, like
21 // a pubsub topic, and call its IAM method to get a Handle for that resource.
22 package iam
23
24 import (
25 "context"
26 "fmt"
27 "time"
28
29 gax "github.com/googleapis/gax-go/v2"
30 pb "google.golang.org/genproto/googleapis/iam/v1"
31 "google.golang.org/grpc"
32 "google.golang.org/grpc/codes"
33 "google.golang.org/grpc/metadata"
34 )
35
36 // client abstracts the IAMPolicy API to allow multiple implementations.
37 type client interface {
38 Get(ctx context.Context, resource string) (*pb.Policy, error)
39 Set(ctx context.Context, resource string, p *pb.Policy) error
40 Test(ctx context.Context, resource string, perms []string) ([]string, error)
41 }
42
43 // grpcClient implements client for the standard gRPC-based IAMPolicy service.
44 type grpcClient struct {
45 c pb.IAMPolicyClient
46 }
47
48 var withRetry = gax.WithRetry(func() gax.Retryer {
49 return gax.OnCodes([]codes.Code{
50 codes.DeadlineExceeded,
51 codes.Unavailable,
52 }, gax.Backoff{
53 Initial: 100 * time.Millisecond,
54 Max: 60 * time.Second,
55 Multiplier: 1.3,
56 })
57 })
58
59 func (g *grpcClient) Get(ctx context.Context, resource string) (*pb.Policy, error) {
60 var proto *pb.Policy
61 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "resource", resource))
62 ctx = insertMetadata(ctx, md)
63
64 err := gax.Invoke(ctx, func(ctx context.Context, _ gax.CallSettings) error {
65 var err error
66 proto, err = g.c.GetIamPolicy(ctx, &pb.GetIamPolicyRequest{Resource: resource})
67 return err
68 }, withRetry)
69 if err != nil {
70 return nil, err
71 }
72 return proto, nil
73 }
74
75 func (g *grpcClient) Set(ctx context.Context, resource string, p *pb.Policy) error {
76 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "resource", resource))
77 ctx = insertMetadata(ctx, md)
78
79 return gax.Invoke(ctx, func(ctx context.Context, _ gax.CallSettings) error {
80 _, err := g.c.SetIamPolicy(ctx, &pb.SetIamPolicyRequest{
81 Resource: resource,
82 Policy: p,
83 })
84 return err
85 }, withRetry)
86 }
87
88 func (g *grpcClient) Test(ctx context.Context, resource string, perms []string) ([]string, error) {
89 var res *pb.TestIamPermissionsResponse
90 md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "resource", resource))
91 ctx = insertMetadata(ctx, md)
92
93 err := gax.Invoke(ctx, func(ctx context.Context, _ gax.CallSettings) error {
94 var err error
95 res, err = g.c.TestIamPermissions(ctx, &pb.TestIamPermissionsRequest{
96 Resource: resource,
97 Permissions: perms,
98 })
99 return err
100 }, withRetry)
101 if err != nil {
102 return nil, err
103 }
104 return res.Permissions, nil
105 }
106
107 // A Handle provides IAM operations for a resource.
108 type Handle struct {
109 c client
110 resource string
111 }
112
113 // InternalNewHandle is for use by the Google Cloud Libraries only.
114 //
115 // InternalNewHandle returns a Handle for resource.
116 // The conn parameter refers to a server that must support the IAMPolicy service.
117 func InternalNewHandle(conn *grpc.ClientConn, resource string) *Handle {
118 return InternalNewHandleGRPCClient(pb.NewIAMPolicyClient(conn), resource)
119 }
120
121 // InternalNewHandleGRPCClient is for use by the Google Cloud Libraries only.
122 //
123 // InternalNewHandleClient returns a Handle for resource using the given
124 // grpc service that implements IAM as a mixin
125 func InternalNewHandleGRPCClient(c pb.IAMPolicyClient, resource string) *Handle {
126 return InternalNewHandleClient(&grpcClient{c: c}, resource)
127 }
128
129 // InternalNewHandleClient is for use by the Google Cloud Libraries only.
130 //
131 // InternalNewHandleClient returns a Handle for resource using the given
132 // client implementation.
133 func InternalNewHandleClient(c client, resource string) *Handle {
134 return &Handle{
135 c: c,
136 resource: resource,
137 }
138 }
139
140 // Policy retrieves the IAM policy for the resource.
141 func (h *Handle) Policy(ctx context.Context) (*Policy, error) {
142 proto, err := h.c.Get(ctx, h.resource)
143 if err != nil {
144 return nil, err
145 }
146 return &Policy{InternalProto: proto}, nil
147 }
148
149 // SetPolicy replaces the resource's current policy with the supplied Policy.
150 //
151 // If policy was created from a prior call to Get, then the modification will
152 // only succeed if the policy has not changed since the Get.
153 func (h *Handle) SetPolicy(ctx context.Context, policy *Policy) error {
154 return h.c.Set(ctx, h.resource, policy.InternalProto)
155 }
156
157 // TestPermissions returns the subset of permissions that the caller has on the resource.
158 func (h *Handle) TestPermissions(ctx context.Context, permissions []string) ([]string, error) {
159 return h.c.Test(ctx, h.resource, permissions)
160 }
161
162 // A RoleName is a name representing a collection of permissions.
163 type RoleName string
164
165 // Common role names.
166 const (
167 Owner RoleName = "roles/owner"
168 Editor RoleName = "roles/editor"
169 Viewer RoleName = "roles/viewer"
170 )
171
172 const (
173 // AllUsers is a special member that denotes all users, even unauthenticated ones.
174 AllUsers = "allUsers"
175
176 // AllAuthenticatedUsers is a special member that denotes all authenticated users.
177 AllAuthenticatedUsers = "allAuthenticatedUsers"
178 )
179
180 // A Policy is a list of Bindings representing roles
181 // granted to members.
182 //
183 // The zero Policy is a valid policy with no bindings.
184 type Policy struct {
185 // TODO(jba): when type aliases are available, put Policy into an internal package
186 // and provide an exported alias here.
187
188 // This field is exported for use by the Google Cloud Libraries only.
189 // It may become unexported in a future release.
190 InternalProto *pb.Policy
191 }
192
193 // Members returns the list of members with the supplied role.
194 // The return value should not be modified. Use Add and Remove
195 // to modify the members of a role.
196 func (p *Policy) Members(r RoleName) []string {
197 b := p.binding(r)
198 if b == nil {
199 return nil
200 }
201 return b.Members
202 }
203
204 // HasRole reports whether member has role r.
205 func (p *Policy) HasRole(member string, r RoleName) bool {
206 return memberIndex(member, p.binding(r)) >= 0
207 }
208
209 // Add adds member member to role r if it is not already present.
210 // A new binding is created if there is no binding for the role.
211 func (p *Policy) Add(member string, r RoleName) {
212 b := p.binding(r)
213 if b == nil {
214 if p.InternalProto == nil {
215 p.InternalProto = &pb.Policy{}
216 }
217 p.InternalProto.Bindings = append(p.InternalProto.Bindings, &pb.Binding{
218 Role: string(r),
219 Members: []string{member},
220 })
221 return
222 }
223 if memberIndex(member, b) < 0 {
224 b.Members = append(b.Members, member)
225 return
226 }
227 }
228
229 // Remove removes member from role r if it is present.
230 func (p *Policy) Remove(member string, r RoleName) {
231 bi := p.bindingIndex(r)
232 if bi < 0 {
233 return
234 }
235 bindings := p.InternalProto.Bindings
236 b := bindings[bi]
237 mi := memberIndex(member, b)
238 if mi < 0 {
239 return
240 }
241 // Order doesn't matter for bindings or members, so to remove, move the last item
242 // into the removed spot and shrink the slice.
243 if len(b.Members) == 1 {
244 // Remove binding.
245 last := len(bindings) - 1
246 bindings[bi] = bindings[last]
247 bindings[last] = nil
248 p.InternalProto.Bindings = bindings[:last]
249 return
250 }
251 // Remove member.
252 // TODO(jba): worry about multiple copies of m?
253 last := len(b.Members) - 1
254 b.Members[mi] = b.Members[last]
255 b.Members[last] = ""
256 b.Members = b.Members[:last]
257 }
258
259 // Roles returns the names of all the roles that appear in the Policy.
260 func (p *Policy) Roles() []RoleName {
261 if p.InternalProto == nil {
262 return nil
263 }
264 var rns []RoleName
265 for _, b := range p.InternalProto.Bindings {
266 rns = append(rns, RoleName(b.Role))
267 }
268 return rns
269 }
270
271 // binding returns the Binding for the suppied role, or nil if there isn't one.
272 func (p *Policy) binding(r RoleName) *pb.Binding {
273 i := p.bindingIndex(r)
274 if i < 0 {
275 return nil
276 }
277 return p.InternalProto.Bindings[i]
278 }
279
280 func (p *Policy) bindingIndex(r RoleName) int {
281 if p.InternalProto == nil {
282 return -1
283 }
284 for i, b := range p.InternalProto.Bindings {
285 if b.Role == string(r) {
286 return i
287 }
288 }
289 return -1
290 }
291
292 // memberIndex returns the index of m in b's Members, or -1 if not found.
293 func memberIndex(m string, b *pb.Binding) int {
294 if b == nil {
295 return -1
296 }
297 for i, mm := range b.Members {
298 if mm == m {
299 return i
300 }
301 }
302 return -1
303 }
304
305 // insertMetadata inserts metadata into the given context
306 func insertMetadata(ctx context.Context, mds ...metadata.MD) context.Context {
307 out, _ := metadata.FromOutgoingContext(ctx)
308 out = out.Copy()
309 for _, md := range mds {
310 for k, v := range md {
311 out[k] = append(out[k], v...)
312 }
313 }
314 return metadata.NewOutgoingContext(ctx, out)
315 }