acl.go 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  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. "context"
  17. "net/http"
  18. "reflect"
  19. "cloud.google.com/go/internal/trace"
  20. "cloud.google.com/go/storage/internal/apiv2/storagepb"
  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
  44. // Google Cloud Storage object or bucket.
  45. type ACLRule struct {
  46. Entity ACLEntity
  47. EntityID string
  48. Role ACLRole
  49. Domain string
  50. Email string
  51. ProjectTeam *ProjectTeam
  52. }
  53. // ProjectTeam is the project team associated with the entity, if any.
  54. type ProjectTeam struct {
  55. ProjectNumber string
  56. Team string
  57. }
  58. // ACLHandle provides operations on an access control list for a Google Cloud Storage bucket or object.
  59. // ACLHandle on an object operates on the latest generation of that object by default.
  60. // Selecting a specific generation of an object is not currently supported by the client.
  61. type ACLHandle struct {
  62. c *Client
  63. bucket string
  64. object string
  65. isDefault bool
  66. userProject string // for requester-pays buckets
  67. retry *retryConfig
  68. }
  69. // Delete permanently deletes the ACL entry for the given entity.
  70. func (a *ACLHandle) Delete(ctx context.Context, entity ACLEntity) (err error) {
  71. ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.ACL.Delete")
  72. defer func() { trace.EndSpan(ctx, err) }()
  73. if a.object != "" {
  74. return a.objectDelete(ctx, entity)
  75. }
  76. if a.isDefault {
  77. return a.bucketDefaultDelete(ctx, entity)
  78. }
  79. return a.bucketDelete(ctx, entity)
  80. }
  81. // Set sets the role for the given entity.
  82. func (a *ACLHandle) Set(ctx context.Context, entity ACLEntity, role ACLRole) (err error) {
  83. ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.ACL.Set")
  84. defer func() { trace.EndSpan(ctx, err) }()
  85. if a.object != "" {
  86. return a.objectSet(ctx, entity, role, false)
  87. }
  88. if a.isDefault {
  89. return a.objectSet(ctx, entity, role, true)
  90. }
  91. return a.bucketSet(ctx, entity, role)
  92. }
  93. // List retrieves ACL entries.
  94. func (a *ACLHandle) List(ctx context.Context) (rules []ACLRule, err error) {
  95. ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.ACL.List")
  96. defer func() { trace.EndSpan(ctx, err) }()
  97. if a.object != "" {
  98. return a.objectList(ctx)
  99. }
  100. if a.isDefault {
  101. return a.bucketDefaultList(ctx)
  102. }
  103. return a.bucketList(ctx)
  104. }
  105. func (a *ACLHandle) bucketDefaultList(ctx context.Context) ([]ACLRule, error) {
  106. opts := makeStorageOpts(true, a.retry, a.userProject)
  107. return a.c.tc.ListDefaultObjectACLs(ctx, a.bucket, opts...)
  108. }
  109. func (a *ACLHandle) bucketDefaultDelete(ctx context.Context, entity ACLEntity) error {
  110. opts := makeStorageOpts(false, a.retry, a.userProject)
  111. return a.c.tc.DeleteDefaultObjectACL(ctx, a.bucket, entity, opts...)
  112. }
  113. func (a *ACLHandle) bucketList(ctx context.Context) ([]ACLRule, error) {
  114. opts := makeStorageOpts(true, a.retry, a.userProject)
  115. return a.c.tc.ListBucketACLs(ctx, a.bucket, opts...)
  116. }
  117. func (a *ACLHandle) bucketSet(ctx context.Context, entity ACLEntity, role ACLRole) error {
  118. opts := makeStorageOpts(false, a.retry, a.userProject)
  119. return a.c.tc.UpdateBucketACL(ctx, a.bucket, entity, role, opts...)
  120. }
  121. func (a *ACLHandle) bucketDelete(ctx context.Context, entity ACLEntity) error {
  122. opts := makeStorageOpts(false, a.retry, a.userProject)
  123. return a.c.tc.DeleteBucketACL(ctx, a.bucket, entity, opts...)
  124. }
  125. func (a *ACLHandle) objectList(ctx context.Context) ([]ACLRule, error) {
  126. opts := makeStorageOpts(true, a.retry, a.userProject)
  127. return a.c.tc.ListObjectACLs(ctx, a.bucket, a.object, opts...)
  128. }
  129. func (a *ACLHandle) objectSet(ctx context.Context, entity ACLEntity, role ACLRole, isBucketDefault bool) error {
  130. opts := makeStorageOpts(false, a.retry, a.userProject)
  131. if isBucketDefault {
  132. return a.c.tc.UpdateDefaultObjectACL(ctx, a.bucket, entity, role, opts...)
  133. }
  134. return a.c.tc.UpdateObjectACL(ctx, a.bucket, a.object, entity, role, opts...)
  135. }
  136. func (a *ACLHandle) objectDelete(ctx context.Context, entity ACLEntity) error {
  137. opts := makeStorageOpts(false, a.retry, a.userProject)
  138. return a.c.tc.DeleteObjectACL(ctx, a.bucket, a.object, entity, opts...)
  139. }
  140. func (a *ACLHandle) configureCall(ctx context.Context, call interface{ Header() http.Header }) {
  141. vc := reflect.ValueOf(call)
  142. vc.MethodByName("Context").Call([]reflect.Value{reflect.ValueOf(ctx)})
  143. if a.userProject != "" {
  144. vc.MethodByName("UserProject").Call([]reflect.Value{reflect.ValueOf(a.userProject)})
  145. }
  146. setClientHeader(call.Header())
  147. }
  148. func toObjectACLRules(items []*raw.ObjectAccessControl) []ACLRule {
  149. var rs []ACLRule
  150. for _, item := range items {
  151. rs = append(rs, toObjectACLRule(item))
  152. }
  153. return rs
  154. }
  155. func toObjectACLRulesFromProto(items []*storagepb.ObjectAccessControl) []ACLRule {
  156. var rs []ACLRule
  157. for _, item := range items {
  158. rs = append(rs, toObjectACLRuleFromProto(item))
  159. }
  160. return rs
  161. }
  162. func toBucketACLRules(items []*raw.BucketAccessControl) []ACLRule {
  163. var rs []ACLRule
  164. for _, item := range items {
  165. rs = append(rs, toBucketACLRule(item))
  166. }
  167. return rs
  168. }
  169. func toBucketACLRulesFromProto(items []*storagepb.BucketAccessControl) []ACLRule {
  170. var rs []ACLRule
  171. for _, item := range items {
  172. rs = append(rs, toBucketACLRuleFromProto(item))
  173. }
  174. return rs
  175. }
  176. func toObjectACLRule(a *raw.ObjectAccessControl) ACLRule {
  177. return ACLRule{
  178. Entity: ACLEntity(a.Entity),
  179. EntityID: a.EntityId,
  180. Role: ACLRole(a.Role),
  181. Domain: a.Domain,
  182. Email: a.Email,
  183. ProjectTeam: toObjectProjectTeam(a.ProjectTeam),
  184. }
  185. }
  186. func toObjectACLRuleFromProto(a *storagepb.ObjectAccessControl) ACLRule {
  187. return ACLRule{
  188. Entity: ACLEntity(a.GetEntity()),
  189. EntityID: a.GetEntityId(),
  190. Role: ACLRole(a.GetRole()),
  191. Domain: a.GetDomain(),
  192. Email: a.GetEmail(),
  193. ProjectTeam: toProjectTeamFromProto(a.GetProjectTeam()),
  194. }
  195. }
  196. func toBucketACLRule(a *raw.BucketAccessControl) ACLRule {
  197. return ACLRule{
  198. Entity: ACLEntity(a.Entity),
  199. EntityID: a.EntityId,
  200. Role: ACLRole(a.Role),
  201. Domain: a.Domain,
  202. Email: a.Email,
  203. ProjectTeam: toBucketProjectTeam(a.ProjectTeam),
  204. }
  205. }
  206. func toBucketACLRuleFromProto(a *storagepb.BucketAccessControl) ACLRule {
  207. return ACLRule{
  208. Entity: ACLEntity(a.GetEntity()),
  209. EntityID: a.GetEntityId(),
  210. Role: ACLRole(a.GetRole()),
  211. Domain: a.GetDomain(),
  212. Email: a.GetEmail(),
  213. ProjectTeam: toProjectTeamFromProto(a.GetProjectTeam()),
  214. }
  215. }
  216. func toRawObjectACL(rules []ACLRule) []*raw.ObjectAccessControl {
  217. if len(rules) == 0 {
  218. return nil
  219. }
  220. r := make([]*raw.ObjectAccessControl, 0, len(rules))
  221. for _, rule := range rules {
  222. r = append(r, rule.toRawObjectAccessControl("")) // bucket name unnecessary
  223. }
  224. return r
  225. }
  226. func toProtoObjectACL(rules []ACLRule) []*storagepb.ObjectAccessControl {
  227. if len(rules) == 0 {
  228. return nil
  229. }
  230. r := make([]*storagepb.ObjectAccessControl, 0, len(rules))
  231. for _, rule := range rules {
  232. r = append(r, rule.toProtoObjectAccessControl("")) // bucket name unnecessary
  233. }
  234. return r
  235. }
  236. func toRawBucketACL(rules []ACLRule) []*raw.BucketAccessControl {
  237. if len(rules) == 0 {
  238. return nil
  239. }
  240. r := make([]*raw.BucketAccessControl, 0, len(rules))
  241. for _, rule := range rules {
  242. r = append(r, rule.toRawBucketAccessControl("")) // bucket name unnecessary
  243. }
  244. return r
  245. }
  246. func toProtoBucketACL(rules []ACLRule) []*storagepb.BucketAccessControl {
  247. if len(rules) == 0 {
  248. return nil
  249. }
  250. r := make([]*storagepb.BucketAccessControl, 0, len(rules))
  251. for _, rule := range rules {
  252. r = append(r, rule.toProtoBucketAccessControl())
  253. }
  254. return r
  255. }
  256. func (r ACLRule) toRawBucketAccessControl(bucket string) *raw.BucketAccessControl {
  257. return &raw.BucketAccessControl{
  258. Bucket: bucket,
  259. Entity: string(r.Entity),
  260. Role: string(r.Role),
  261. // The other fields are not settable.
  262. }
  263. }
  264. func (r ACLRule) toRawObjectAccessControl(bucket string) *raw.ObjectAccessControl {
  265. return &raw.ObjectAccessControl{
  266. Bucket: bucket,
  267. Entity: string(r.Entity),
  268. Role: string(r.Role),
  269. // The other fields are not settable.
  270. }
  271. }
  272. func (r ACLRule) toProtoObjectAccessControl(bucket string) *storagepb.ObjectAccessControl {
  273. return &storagepb.ObjectAccessControl{
  274. Entity: string(r.Entity),
  275. Role: string(r.Role),
  276. // The other fields are not settable.
  277. }
  278. }
  279. func (r ACLRule) toProtoBucketAccessControl() *storagepb.BucketAccessControl {
  280. return &storagepb.BucketAccessControl{
  281. Entity: string(r.Entity),
  282. Role: string(r.Role),
  283. // The other fields are not settable.
  284. }
  285. }
  286. func toBucketProjectTeam(p *raw.BucketAccessControlProjectTeam) *ProjectTeam {
  287. if p == nil {
  288. return nil
  289. }
  290. return &ProjectTeam{
  291. ProjectNumber: p.ProjectNumber,
  292. Team: p.Team,
  293. }
  294. }
  295. func toProjectTeamFromProto(p *storagepb.ProjectTeam) *ProjectTeam {
  296. if p == nil {
  297. return nil
  298. }
  299. return &ProjectTeam{
  300. ProjectNumber: p.GetProjectNumber(),
  301. Team: p.GetTeam(),
  302. }
  303. }
  304. func toObjectProjectTeam(p *raw.ObjectAccessControlProjectTeam) *ProjectTeam {
  305. if p == nil {
  306. return nil
  307. }
  308. return &ProjectTeam{
  309. ProjectNumber: p.ProjectNumber,
  310. Team: p.Team,
  311. }
  312. }