You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

246 lines
6.6 KiB

  1. // Copyright 2014 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. package storage
  15. import (
  16. "net/http"
  17. "reflect"
  18. "cloud.google.com/go/internal/trace"
  19. "golang.org/x/net/context"
  20. "google.golang.org/api/googleapi"
  21. raw "google.golang.org/api/storage/v1"
  22. )
  23. // ACLRole is the level of access to grant.
  24. type ACLRole string
  25. const (
  26. RoleOwner ACLRole = "OWNER"
  27. RoleReader ACLRole = "READER"
  28. RoleWriter ACLRole = "WRITER"
  29. )
  30. // ACLEntity refers to a user or group.
  31. // They are sometimes referred to as grantees.
  32. //
  33. // It could be in the form of:
  34. // "user-<userId>", "user-<email>", "group-<groupId>", "group-<email>",
  35. // "domain-<domain>" and "project-team-<projectId>".
  36. //
  37. // Or one of the predefined constants: AllUsers, AllAuthenticatedUsers.
  38. type ACLEntity string
  39. const (
  40. AllUsers ACLEntity = "allUsers"
  41. AllAuthenticatedUsers ACLEntity = "allAuthenticatedUsers"
  42. )
  43. // ACLRule represents a grant for a role to an entity (user, group or team) for a Google Cloud Storage object or bucket.
  44. type ACLRule struct {
  45. Entity ACLEntity
  46. Role ACLRole
  47. }
  48. // ACLHandle provides operations on an access control list for a Google Cloud Storage bucket or object.
  49. type ACLHandle struct {
  50. c *Client
  51. bucket string
  52. object string
  53. isDefault bool
  54. userProject string // for requester-pays buckets
  55. }
  56. // Delete permanently deletes the ACL entry for the given entity.
  57. func (a *ACLHandle) Delete(ctx context.Context, entity ACLEntity) (err error) {
  58. ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.ACL.Delete")
  59. defer func() { trace.EndSpan(ctx, err) }()
  60. if a.object != "" {
  61. return a.objectDelete(ctx, entity)
  62. }
  63. if a.isDefault {
  64. return a.bucketDefaultDelete(ctx, entity)
  65. }
  66. return a.bucketDelete(ctx, entity)
  67. }
  68. // Set sets the permission level for the given entity.
  69. func (a *ACLHandle) Set(ctx context.Context, entity ACLEntity, role ACLRole) (err error) {
  70. ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.ACL.Set")
  71. defer func() { trace.EndSpan(ctx, err) }()
  72. if a.object != "" {
  73. return a.objectSet(ctx, entity, role, false)
  74. }
  75. if a.isDefault {
  76. return a.objectSet(ctx, entity, role, true)
  77. }
  78. return a.bucketSet(ctx, entity, role)
  79. }
  80. // List retrieves ACL entries.
  81. func (a *ACLHandle) List(ctx context.Context) (rules []ACLRule, err error) {
  82. ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.ACL.List")
  83. defer func() { trace.EndSpan(ctx, err) }()
  84. if a.object != "" {
  85. return a.objectList(ctx)
  86. }
  87. if a.isDefault {
  88. return a.bucketDefaultList(ctx)
  89. }
  90. return a.bucketList(ctx)
  91. }
  92. func (a *ACLHandle) bucketDefaultList(ctx context.Context) ([]ACLRule, error) {
  93. var acls *raw.ObjectAccessControls
  94. var err error
  95. err = runWithRetry(ctx, func() error {
  96. req := a.c.raw.DefaultObjectAccessControls.List(a.bucket)
  97. a.configureCall(req, ctx)
  98. acls, err = req.Do()
  99. return err
  100. })
  101. if err != nil {
  102. return nil, err
  103. }
  104. return toACLRules(acls.Items), nil
  105. }
  106. func (a *ACLHandle) bucketDefaultDelete(ctx context.Context, entity ACLEntity) error {
  107. return runWithRetry(ctx, func() error {
  108. req := a.c.raw.DefaultObjectAccessControls.Delete(a.bucket, string(entity))
  109. a.configureCall(req, ctx)
  110. return req.Do()
  111. })
  112. }
  113. func (a *ACLHandle) bucketList(ctx context.Context) ([]ACLRule, error) {
  114. var acls *raw.BucketAccessControls
  115. var err error
  116. err = runWithRetry(ctx, func() error {
  117. req := a.c.raw.BucketAccessControls.List(a.bucket)
  118. a.configureCall(req, ctx)
  119. acls, err = req.Do()
  120. return err
  121. })
  122. if err != nil {
  123. return nil, err
  124. }
  125. r := make([]ACLRule, len(acls.Items))
  126. for i, v := range acls.Items {
  127. r[i].Entity = ACLEntity(v.Entity)
  128. r[i].Role = ACLRole(v.Role)
  129. }
  130. return r, nil
  131. }
  132. func (a *ACLHandle) bucketSet(ctx context.Context, entity ACLEntity, role ACLRole) error {
  133. acl := &raw.BucketAccessControl{
  134. Bucket: a.bucket,
  135. Entity: string(entity),
  136. Role: string(role),
  137. }
  138. err := runWithRetry(ctx, func() error {
  139. req := a.c.raw.BucketAccessControls.Update(a.bucket, string(entity), acl)
  140. a.configureCall(req, ctx)
  141. _, err := req.Do()
  142. return err
  143. })
  144. if err != nil {
  145. return err
  146. }
  147. return nil
  148. }
  149. func (a *ACLHandle) bucketDelete(ctx context.Context, entity ACLEntity) error {
  150. err := runWithRetry(ctx, func() error {
  151. req := a.c.raw.BucketAccessControls.Delete(a.bucket, string(entity))
  152. a.configureCall(req, ctx)
  153. return req.Do()
  154. })
  155. if err != nil {
  156. return err
  157. }
  158. return nil
  159. }
  160. func (a *ACLHandle) objectList(ctx context.Context) ([]ACLRule, error) {
  161. var acls *raw.ObjectAccessControls
  162. var err error
  163. err = runWithRetry(ctx, func() error {
  164. req := a.c.raw.ObjectAccessControls.List(a.bucket, a.object)
  165. a.configureCall(req, ctx)
  166. acls, err = req.Do()
  167. return err
  168. })
  169. if err != nil {
  170. return nil, err
  171. }
  172. return toACLRules(acls.Items), nil
  173. }
  174. func (a *ACLHandle) objectSet(ctx context.Context, entity ACLEntity, role ACLRole, isBucketDefault bool) error {
  175. type setRequest interface {
  176. Do(opts ...googleapi.CallOption) (*raw.ObjectAccessControl, error)
  177. Header() http.Header
  178. }
  179. acl := &raw.ObjectAccessControl{
  180. Bucket: a.bucket,
  181. Entity: string(entity),
  182. Role: string(role),
  183. }
  184. var req setRequest
  185. if isBucketDefault {
  186. req = a.c.raw.DefaultObjectAccessControls.Update(a.bucket, string(entity), acl)
  187. } else {
  188. req = a.c.raw.ObjectAccessControls.Update(a.bucket, a.object, string(entity), acl)
  189. }
  190. a.configureCall(req, ctx)
  191. return runWithRetry(ctx, func() error {
  192. _, err := req.Do()
  193. return err
  194. })
  195. }
  196. func (a *ACLHandle) objectDelete(ctx context.Context, entity ACLEntity) error {
  197. return runWithRetry(ctx, func() error {
  198. req := a.c.raw.ObjectAccessControls.Delete(a.bucket, a.object, string(entity))
  199. a.configureCall(req, ctx)
  200. return req.Do()
  201. })
  202. }
  203. func (a *ACLHandle) configureCall(call interface {
  204. Header() http.Header
  205. }, ctx context.Context) {
  206. vc := reflect.ValueOf(call)
  207. vc.MethodByName("Context").Call([]reflect.Value{reflect.ValueOf(ctx)})
  208. if a.userProject != "" {
  209. vc.MethodByName("UserProject").Call([]reflect.Value{reflect.ValueOf(a.userProject)})
  210. }
  211. setClientHeader(call.Header())
  212. }
  213. func toACLRules(items []*raw.ObjectAccessControl) []ACLRule {
  214. r := make([]ACLRule, 0, len(items))
  215. for _, item := range items {
  216. r = append(r, ACLRule{Entity: ACLEntity(item.Entity), Role: ACLRole(item.Role)})
  217. }
  218. return r
  219. }