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.

719 lines
21 KiB

  1. package s3acl
  2. import (
  3. "encoding/json"
  4. "encoding/xml"
  5. "fmt"
  6. "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil"
  7. "github.com/aws/aws-sdk-go/service/s3"
  8. "github.com/seaweedfs/seaweedfs/weed/filer"
  9. "github.com/seaweedfs/seaweedfs/weed/glog"
  10. "github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
  11. "github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
  12. "github.com/seaweedfs/seaweedfs/weed/s3api/s3account"
  13. "github.com/seaweedfs/seaweedfs/weed/s3api/s3err"
  14. "github.com/seaweedfs/seaweedfs/weed/util"
  15. "net/http"
  16. "strings"
  17. )
  18. var customAclHeaders = []string{s3_constants.AmzAclFullControl, s3_constants.AmzAclRead, s3_constants.AmzAclReadAcp, s3_constants.AmzAclWrite, s3_constants.AmzAclWriteAcp}
  19. // GetAccountId get AccountId from request headers, AccountAnonymousId will be return if not presen
  20. func GetAccountId(r *http.Request) string {
  21. id := r.Header.Get(s3_constants.AmzAccountId)
  22. if len(id) == 0 {
  23. return s3account.AccountAnonymous.Id
  24. } else {
  25. return id
  26. }
  27. }
  28. // ValidateAccount validate weather request account id is allowed to access
  29. func ValidateAccount(requestAccountId string, allowedAccounts ...string) bool {
  30. for _, allowedAccount := range allowedAccounts {
  31. if requestAccountId == allowedAccount {
  32. return true
  33. }
  34. }
  35. return false
  36. }
  37. // ExtractBucketAcl extracts the acl from the request body, or from the header if request body is empty
  38. func ExtractBucketAcl(r *http.Request, accountManager *s3account.AccountManager, objectOwnership, bucketOwnerId, requestAccountId string, createBucket bool) (grants []*s3.Grant, errCode s3err.ErrorCode) {
  39. cannedAclPresent := false
  40. if r.Header.Get(s3_constants.AmzCannedAcl) != "" {
  41. cannedAclPresent = true
  42. }
  43. customAclPresent := false
  44. for _, customAclHeader := range customAclHeaders {
  45. if r.Header.Get(customAclHeader) != "" {
  46. customAclPresent = true
  47. break
  48. }
  49. }
  50. // AccessControlList body is not support when create object/bucket
  51. if !createBucket && r.Body != nil && r.Body != http.NoBody {
  52. defer util.CloseRequest(r)
  53. if cannedAclPresent || customAclPresent {
  54. return nil, s3err.ErrUnexpectedContent
  55. }
  56. var acp s3.AccessControlPolicy
  57. err := xmlutil.UnmarshalXML(&acp, xml.NewDecoder(r.Body), "")
  58. if err != nil || acp.Owner == nil || acp.Owner.ID == nil {
  59. return nil, s3err.ErrInvalidRequest
  60. }
  61. //owner should present && owner is immutable
  62. if *acp.Owner.ID == "" || *acp.Owner.ID != bucketOwnerId {
  63. glog.V(3).Infof("set acl denied! owner account is not consistent, request account id: %s, expect account id: %s", *acp.Owner.ID, bucketOwnerId)
  64. return nil, s3err.ErrAccessDenied
  65. }
  66. grants = acp.Grants
  67. } else {
  68. if cannedAclPresent && customAclPresent {
  69. return nil, s3err.ErrInvalidRequest
  70. }
  71. if cannedAclPresent {
  72. grants, errCode = ExtractBucketCannedAcl(r, requestAccountId)
  73. } else if customAclPresent {
  74. grants, errCode = ExtractCustomAcl(r)
  75. }
  76. if errCode != s3err.ErrNone {
  77. return nil, errCode
  78. }
  79. }
  80. errCode = ValidateObjectOwnershipAndGrants(objectOwnership, bucketOwnerId, grants)
  81. if errCode != s3err.ErrNone {
  82. return nil, errCode
  83. }
  84. grants, errCode = ValidateAndTransferGrants(accountManager, grants)
  85. if errCode != s3err.ErrNone {
  86. return nil, errCode
  87. }
  88. return grants, s3err.ErrNone
  89. }
  90. // ExtractObjectAcl extracts the acl from the request body, or from the header if request body is empty
  91. func ExtractObjectAcl(r *http.Request, accountManager *s3account.AccountManager, objectOwnership, bucketOwnerId, requestAccountId string, createObject bool) (ownerId string, grants []*s3.Grant, errCode s3err.ErrorCode) {
  92. cannedAclPresent := false
  93. if r.Header.Get(s3_constants.AmzCannedAcl) != "" {
  94. cannedAclPresent = true
  95. }
  96. customAclPresent := false
  97. for _, customAclHeader := range customAclHeaders {
  98. if r.Header.Get(customAclHeader) != "" {
  99. customAclPresent = true
  100. break
  101. }
  102. }
  103. // AccessControlList body is not support when create object/bucket
  104. if !createObject && r.Body != nil && r.Body != http.NoBody {
  105. defer util.CloseRequest(r)
  106. if cannedAclPresent || customAclPresent {
  107. return "", nil, s3err.ErrUnexpectedContent
  108. }
  109. var acp s3.AccessControlPolicy
  110. err := xmlutil.UnmarshalXML(&acp, xml.NewDecoder(r.Body), "")
  111. if err != nil || acp.Owner == nil || acp.Owner.ID == nil {
  112. return "", nil, s3err.ErrInvalidRequest
  113. }
  114. //owner should present && owner is immutable
  115. if *acp.Owner.ID == "" {
  116. glog.V(1).Infof("Access denied! The owner id is required when specifying grants using AccessControlList")
  117. return "", nil, s3err.ErrAccessDenied
  118. }
  119. ownerId = *acp.Owner.ID
  120. grants = acp.Grants
  121. } else {
  122. if cannedAclPresent && customAclPresent {
  123. return "", nil, s3err.ErrInvalidRequest
  124. }
  125. if cannedAclPresent {
  126. ownerId, grants, errCode = ExtractObjectCannedAcl(r, objectOwnership, bucketOwnerId, requestAccountId, createObject)
  127. } else {
  128. grants, errCode = ExtractCustomAcl(r)
  129. }
  130. if errCode != s3err.ErrNone {
  131. return "", nil, errCode
  132. }
  133. }
  134. errCode = ValidateObjectOwnershipAndGrants(objectOwnership, bucketOwnerId, grants)
  135. if errCode != s3err.ErrNone {
  136. return "", nil, errCode
  137. }
  138. grants, errCode = ValidateAndTransferGrants(accountManager, grants)
  139. return ownerId, grants, errCode
  140. }
  141. func ExtractCustomAcl(r *http.Request) ([]*s3.Grant, s3err.ErrorCode) {
  142. var errCode s3err.ErrorCode
  143. var grants []*s3.Grant
  144. for _, customAclHeader := range customAclHeaders {
  145. headerValue := r.Header.Get(customAclHeader)
  146. switch customAclHeader {
  147. case s3_constants.AmzAclRead:
  148. errCode = ParseCustomAclHeader(headerValue, s3_constants.PermissionRead, &grants)
  149. case s3_constants.AmzAclWrite:
  150. errCode = ParseCustomAclHeader(headerValue, s3_constants.PermissionWrite, &grants)
  151. case s3_constants.AmzAclReadAcp:
  152. errCode = ParseCustomAclHeader(headerValue, s3_constants.PermissionReadAcp, &grants)
  153. case s3_constants.AmzAclWriteAcp:
  154. errCode = ParseCustomAclHeader(headerValue, s3_constants.PermissionWriteAcp, &grants)
  155. case s3_constants.AmzAclFullControl:
  156. errCode = ParseCustomAclHeader(headerValue, s3_constants.PermissionFullControl, &grants)
  157. default:
  158. errCode = s3err.ErrInvalidAclArgument
  159. }
  160. if errCode != s3err.ErrNone {
  161. return nil, errCode
  162. }
  163. }
  164. return grants, s3err.ErrNone
  165. }
  166. func ParseCustomAclHeader(headerValue, permission string, grants *[]*s3.Grant) s3err.ErrorCode {
  167. if len(headerValue) > 0 {
  168. split := strings.Split(headerValue, ",")
  169. for _, grantStr := range split {
  170. kv := strings.Split(grantStr, "=")
  171. if len(kv) != 2 {
  172. return s3err.ErrInvalidRequest
  173. }
  174. switch strings.TrimSpace(kv[0]) {
  175. case "id":
  176. accountId := decodeGranteeValue(kv[1])
  177. *grants = append(*grants, &s3.Grant{
  178. Grantee: &s3.Grantee{
  179. Type: &s3_constants.GrantTypeCanonicalUser,
  180. ID: &accountId,
  181. },
  182. Permission: &permission,
  183. })
  184. case "emailAddress":
  185. emailAddress := decodeGranteeValue(kv[1])
  186. *grants = append(*grants, &s3.Grant{
  187. Grantee: &s3.Grantee{
  188. Type: &s3_constants.GrantTypeAmazonCustomerByEmail,
  189. EmailAddress: &emailAddress,
  190. },
  191. Permission: &permission,
  192. })
  193. case "uri":
  194. var groupName string
  195. groupName = decodeGranteeValue(kv[1])
  196. *grants = append(*grants, &s3.Grant{
  197. Grantee: &s3.Grantee{
  198. Type: &s3_constants.GrantTypeGroup,
  199. URI: &groupName,
  200. },
  201. Permission: &permission,
  202. })
  203. }
  204. }
  205. }
  206. return s3err.ErrNone
  207. }
  208. func decodeGranteeValue(value string) (result string) {
  209. if !strings.HasPrefix(value, "\"") {
  210. return value
  211. }
  212. _ = json.Unmarshal([]byte(value), &result)
  213. if result == "" {
  214. result = value
  215. }
  216. return result
  217. }
  218. // ExtractBucketCannedAcl parse bucket canned acl, includes: 'private'|'public-read'|'public-read-write'|'authenticated-read'
  219. func ExtractBucketCannedAcl(request *http.Request, requestAccountId string) (grants []*s3.Grant, err s3err.ErrorCode) {
  220. cannedAcl := request.Header.Get(s3_constants.AmzCannedAcl)
  221. if cannedAcl == "" {
  222. return grants, s3err.ErrNone
  223. }
  224. err = s3err.ErrNone
  225. objectWriterFullControl := &s3.Grant{
  226. Grantee: &s3.Grantee{
  227. ID: &requestAccountId,
  228. Type: &s3_constants.GrantTypeCanonicalUser,
  229. },
  230. Permission: &s3_constants.PermissionFullControl,
  231. }
  232. switch cannedAcl {
  233. case s3_constants.CannedAclPrivate:
  234. grants = append(grants, objectWriterFullControl)
  235. case s3_constants.CannedAclPublicRead:
  236. grants = append(grants, objectWriterFullControl)
  237. grants = append(grants, s3_constants.PublicRead...)
  238. case s3_constants.CannedAclPublicReadWrite:
  239. grants = append(grants, objectWriterFullControl)
  240. grants = append(grants, s3_constants.PublicReadWrite...)
  241. case s3_constants.CannedAclAuthenticatedRead:
  242. grants = append(grants, objectWriterFullControl)
  243. grants = append(grants, s3_constants.AuthenticatedRead...)
  244. default:
  245. err = s3err.ErrInvalidAclArgument
  246. }
  247. return
  248. }
  249. // ExtractObjectCannedAcl parse object canned acl, includes: 'private'|'public-read'|'public-read-write'|'authenticated-read'|'aws-exec-read'|'bucket-owner-read'|'bucket-owner-full-control'
  250. func ExtractObjectCannedAcl(request *http.Request, objectOwnership, bucketOwnerId, requestAccountId string, createObject bool) (ownerId string, grants []*s3.Grant, errCode s3err.ErrorCode) {
  251. if createObject {
  252. ownerId = requestAccountId
  253. }
  254. cannedAcl := request.Header.Get(s3_constants.AmzCannedAcl)
  255. if cannedAcl == "" {
  256. return ownerId, grants, s3err.ErrNone
  257. }
  258. errCode = s3err.ErrNone
  259. objectWriterFullControl := &s3.Grant{
  260. Grantee: &s3.Grantee{
  261. ID: &requestAccountId,
  262. Type: &s3_constants.GrantTypeCanonicalUser,
  263. },
  264. Permission: &s3_constants.PermissionFullControl,
  265. }
  266. switch cannedAcl {
  267. case s3_constants.CannedAclPrivate:
  268. grants = append(grants, objectWriterFullControl)
  269. case s3_constants.CannedAclPublicRead:
  270. grants = append(grants, objectWriterFullControl)
  271. grants = append(grants, s3_constants.PublicRead...)
  272. case s3_constants.CannedAclPublicReadWrite:
  273. grants = append(grants, objectWriterFullControl)
  274. grants = append(grants, s3_constants.PublicReadWrite...)
  275. case s3_constants.CannedAclAuthenticatedRead:
  276. grants = append(grants, objectWriterFullControl)
  277. grants = append(grants, s3_constants.AuthenticatedRead...)
  278. case s3_constants.CannedAclLogDeliveryWrite:
  279. grants = append(grants, objectWriterFullControl)
  280. grants = append(grants, s3_constants.LogDeliveryWrite...)
  281. case s3_constants.CannedAclBucketOwnerRead:
  282. grants = append(grants, objectWriterFullControl)
  283. if requestAccountId != bucketOwnerId {
  284. grants = append(grants,
  285. &s3.Grant{
  286. Grantee: &s3.Grantee{
  287. Type: &s3_constants.GrantTypeCanonicalUser,
  288. ID: &bucketOwnerId,
  289. },
  290. Permission: &s3_constants.PermissionRead,
  291. })
  292. }
  293. case s3_constants.CannedAclBucketOwnerFullControl:
  294. if bucketOwnerId != "" {
  295. // if set ownership to 'BucketOwnerPreferred' when upload object, the bucket owner will be the object owner
  296. if createObject && objectOwnership == s3_constants.OwnershipBucketOwnerPreferred {
  297. ownerId = bucketOwnerId
  298. grants = append(grants,
  299. &s3.Grant{
  300. Grantee: &s3.Grantee{
  301. Type: &s3_constants.GrantTypeCanonicalUser,
  302. ID: &bucketOwnerId,
  303. },
  304. Permission: &s3_constants.PermissionFullControl,
  305. })
  306. } else {
  307. grants = append(grants, objectWriterFullControl)
  308. if requestAccountId != bucketOwnerId {
  309. grants = append(grants,
  310. &s3.Grant{
  311. Grantee: &s3.Grantee{
  312. Type: &s3_constants.GrantTypeCanonicalUser,
  313. ID: &bucketOwnerId,
  314. },
  315. Permission: &s3_constants.PermissionFullControl,
  316. })
  317. }
  318. }
  319. }
  320. default:
  321. errCode = s3err.ErrInvalidAclArgument
  322. }
  323. return
  324. }
  325. // ValidateAndTransferGrants validate grant entity exists and transfer Email-Grant to Id-Grant
  326. func ValidateAndTransferGrants(accountManager *s3account.AccountManager, grants []*s3.Grant) ([]*s3.Grant, s3err.ErrorCode) {
  327. var result []*s3.Grant
  328. for _, grant := range grants {
  329. grantee := grant.Grantee
  330. if grantee == nil || grantee.Type == nil {
  331. glog.Warning("invalid grantee! grantee or granteeType is nil")
  332. return nil, s3err.ErrInvalidRequest
  333. }
  334. switch *grantee.Type {
  335. case s3_constants.GrantTypeGroup:
  336. if grantee.URI == nil {
  337. glog.Warning("invalid group grantee! group URI is nil")
  338. return nil, s3err.ErrInvalidRequest
  339. }
  340. ok := s3_constants.ValidateGroup(*grantee.URI)
  341. if !ok {
  342. glog.Warningf("invalid group grantee! group name[%s] is not valid", *grantee.URI)
  343. return nil, s3err.ErrInvalidRequest
  344. }
  345. result = append(result, grant)
  346. case s3_constants.GrantTypeCanonicalUser:
  347. if grantee.ID == nil {
  348. glog.Warning("invalid canonical grantee! account id is nil")
  349. return nil, s3err.ErrInvalidRequest
  350. }
  351. _, ok := accountManager.IdNameMapping[*grantee.ID]
  352. if !ok {
  353. glog.Warningf("invalid canonical grantee! account id[%s] is not exists", *grantee.ID)
  354. return nil, s3err.ErrInvalidRequest
  355. }
  356. result = append(result, grant)
  357. case s3_constants.GrantTypeAmazonCustomerByEmail:
  358. if grantee.EmailAddress == nil {
  359. glog.Warning("invalid email grantee! email address is nil")
  360. return nil, s3err.ErrInvalidRequest
  361. }
  362. accountId, ok := accountManager.EmailIdMapping[*grantee.EmailAddress]
  363. if !ok {
  364. glog.Warningf("invalid email grantee! email address[%s] is not exists", *grantee.EmailAddress)
  365. return nil, s3err.ErrInvalidRequest
  366. }
  367. result = append(result, &s3.Grant{
  368. Grantee: &s3.Grantee{
  369. Type: &s3_constants.GrantTypeCanonicalUser,
  370. ID: &accountId,
  371. },
  372. Permission: grant.Permission,
  373. })
  374. default:
  375. return nil, s3err.ErrInvalidRequest
  376. }
  377. }
  378. return result, s3err.ErrNone
  379. }
  380. // ValidateObjectOwnershipAndGrants validate if grants equals OwnerFullControl when 'ObjectOwnership' is 'BucketOwnerEnforced'
  381. func ValidateObjectOwnershipAndGrants(objectOwnership, bucketOwnerId string, grants []*s3.Grant) s3err.ErrorCode {
  382. if len(grants) == 0 {
  383. return s3err.ErrNone
  384. }
  385. if objectOwnership == "" {
  386. objectOwnership = s3_constants.DefaultObjectOwnership
  387. }
  388. if objectOwnership != s3_constants.OwnershipBucketOwnerEnforced {
  389. return s3err.ErrNone
  390. }
  391. if len(grants) > 1 {
  392. return s3err.AccessControlListNotSupported
  393. }
  394. bucketOwnerFullControlGrant := &s3.Grant{
  395. Permission: &s3_constants.PermissionFullControl,
  396. Grantee: &s3.Grantee{
  397. Type: &s3_constants.GrantTypeCanonicalUser,
  398. ID: &bucketOwnerId,
  399. },
  400. }
  401. if GrantEquals(bucketOwnerFullControlGrant, grants[0]) {
  402. return s3err.ErrNone
  403. }
  404. return s3err.AccessControlListNotSupported
  405. }
  406. // DetermineRequiredGrants generates the grant set (Grants) according to accountId and reqPermission.
  407. func DetermineRequiredGrants(accountId, permission string) (grants []*s3.Grant) {
  408. // group grantee (AllUsers)
  409. grants = append(grants, &s3.Grant{
  410. Grantee: &s3.Grantee{
  411. Type: &s3_constants.GrantTypeGroup,
  412. URI: &s3_constants.GranteeGroupAllUsers,
  413. },
  414. Permission: &permission,
  415. })
  416. grants = append(grants, &s3.Grant{
  417. Grantee: &s3.Grantee{
  418. Type: &s3_constants.GrantTypeGroup,
  419. URI: &s3_constants.GranteeGroupAllUsers,
  420. },
  421. Permission: &s3_constants.PermissionFullControl,
  422. })
  423. // canonical grantee (accountId)
  424. grants = append(grants, &s3.Grant{
  425. Grantee: &s3.Grantee{
  426. Type: &s3_constants.GrantTypeCanonicalUser,
  427. ID: &accountId,
  428. },
  429. Permission: &permission,
  430. })
  431. grants = append(grants, &s3.Grant{
  432. Grantee: &s3.Grantee{
  433. Type: &s3_constants.GrantTypeCanonicalUser,
  434. ID: &accountId,
  435. },
  436. Permission: &s3_constants.PermissionFullControl,
  437. })
  438. // group grantee (AuthenticateUsers)
  439. if accountId != s3account.AccountAnonymous.Id {
  440. grants = append(grants, &s3.Grant{
  441. Grantee: &s3.Grantee{
  442. Type: &s3_constants.GrantTypeGroup,
  443. URI: &s3_constants.GranteeGroupAuthenticatedUsers,
  444. },
  445. Permission: &permission,
  446. })
  447. grants = append(grants, &s3.Grant{
  448. Grantee: &s3.Grantee{
  449. Type: &s3_constants.GrantTypeGroup,
  450. URI: &s3_constants.GranteeGroupAuthenticatedUsers,
  451. },
  452. Permission: &s3_constants.PermissionFullControl,
  453. })
  454. }
  455. return
  456. }
  457. func SetAcpOwnerHeader(r *http.Request, acpOwnerId string) {
  458. r.Header.Set(s3_constants.ExtAmzOwnerKey, acpOwnerId)
  459. }
  460. func GetAcpOwner(entryExtended map[string][]byte, defaultOwner string) string {
  461. ownerIdBytes, ok := entryExtended[s3_constants.ExtAmzOwnerKey]
  462. if ok && len(ownerIdBytes) > 0 {
  463. return string(ownerIdBytes)
  464. }
  465. return defaultOwner
  466. }
  467. func SetAcpGrantsHeader(r *http.Request, grants []*s3.Grant) {
  468. if len(grants) > 0 {
  469. a, err := MarshalGrantsToJson(grants)
  470. if err == nil {
  471. r.Header.Set(s3_constants.ExtAmzAclKey, string(a))
  472. } else {
  473. glog.Warning("Marshal acp grants err", err)
  474. }
  475. }
  476. }
  477. // GetAcpGrants return grants parsed from entry
  478. func GetAcpGrants(ownerId *string, entryExtended map[string][]byte) []*s3.Grant {
  479. acpBytes, ok := entryExtended[s3_constants.ExtAmzAclKey]
  480. if ok && len(acpBytes) > 0 {
  481. var grants []*s3.Grant
  482. err := json.Unmarshal(acpBytes, &grants)
  483. if err == nil {
  484. return grants
  485. }
  486. glog.Warning("grants Unmarshal error", err)
  487. }
  488. if ownerId == nil {
  489. return nil
  490. }
  491. return []*s3.Grant{
  492. {
  493. Grantee: &s3.Grantee{
  494. Type: &s3_constants.GrantTypeCanonicalUser,
  495. ID: ownerId,
  496. },
  497. Permission: &s3_constants.PermissionFullControl,
  498. },
  499. }
  500. }
  501. // AssembleEntryWithAcp fill entry with owner and grants
  502. func AssembleEntryWithAcp(filerEntry *filer_pb.Entry, ownerId string, grants []*s3.Grant) s3err.ErrorCode {
  503. if filerEntry.Extended == nil {
  504. filerEntry.Extended = make(map[string][]byte)
  505. }
  506. if len(ownerId) > 0 {
  507. filerEntry.Extended[s3_constants.ExtAmzOwnerKey] = []byte(ownerId)
  508. } else {
  509. delete(filerEntry.Extended, s3_constants.ExtAmzOwnerKey)
  510. }
  511. if grants != nil {
  512. grantsBytes, err := MarshalGrantsToJson(grants)
  513. if err != nil {
  514. glog.Warning("assemble acp to entry:", err)
  515. return s3err.ErrInvalidRequest
  516. }
  517. filerEntry.Extended[s3_constants.ExtAmzAclKey] = grantsBytes
  518. } else {
  519. delete(filerEntry.Extended, s3_constants.ExtAmzAclKey)
  520. }
  521. return s3err.ErrNone
  522. }
  523. // GrantEquals Compare whether two Grants are equal in meaning, not completely
  524. // equal (compare Grantee.Type and the corresponding Value for equality, other
  525. // fields of Grantee are ignored)
  526. func GrantEquals(a, b *s3.Grant) bool {
  527. // grant
  528. if a == b {
  529. return true
  530. }
  531. if a == nil || b == nil {
  532. return false
  533. }
  534. // grant.Permission
  535. if a.Permission != b.Permission {
  536. if a.Permission == nil || b.Permission == nil {
  537. return false
  538. }
  539. if *a.Permission != *b.Permission {
  540. return false
  541. }
  542. }
  543. // grant.Grantee
  544. ag := a.Grantee
  545. bg := b.Grantee
  546. if ag != bg {
  547. if ag == nil || bg == nil {
  548. return false
  549. }
  550. // grantee.Type
  551. if ag.Type != bg.Type {
  552. if ag.Type == nil || bg.Type == nil {
  553. return false
  554. }
  555. if *ag.Type != *bg.Type {
  556. return false
  557. }
  558. }
  559. // value corresponding to granteeType
  560. if ag.Type != nil {
  561. switch *ag.Type {
  562. case s3_constants.GrantTypeGroup:
  563. if ag.URI != bg.URI {
  564. if ag.URI == nil || bg.URI == nil {
  565. return false
  566. }
  567. if *ag.URI != *bg.URI {
  568. return false
  569. }
  570. }
  571. case s3_constants.GrantTypeCanonicalUser:
  572. if ag.ID != bg.ID {
  573. if ag.ID == nil || bg.ID == nil {
  574. return false
  575. }
  576. if *ag.ID != *bg.ID {
  577. return false
  578. }
  579. }
  580. case s3_constants.GrantTypeAmazonCustomerByEmail:
  581. if ag.EmailAddress != bg.EmailAddress {
  582. if ag.EmailAddress == nil || bg.EmailAddress == nil {
  583. return false
  584. }
  585. if *ag.EmailAddress != *bg.EmailAddress {
  586. return false
  587. }
  588. }
  589. }
  590. }
  591. }
  592. return true
  593. }
  594. func MarshalGrantsToJson(grants []*s3.Grant) ([]byte, error) {
  595. if len(grants) == 0 {
  596. return []byte{}, nil
  597. }
  598. var GrantsToMap []map[string]any
  599. for _, grant := range grants {
  600. grantee := grant.Grantee
  601. switch *grantee.Type {
  602. case s3_constants.GrantTypeGroup:
  603. GrantsToMap = append(GrantsToMap, map[string]any{
  604. "Permission": grant.Permission,
  605. "Grantee": map[string]any{
  606. "Type": grantee.Type,
  607. "URI": grantee.URI,
  608. },
  609. })
  610. case s3_constants.GrantTypeCanonicalUser:
  611. GrantsToMap = append(GrantsToMap, map[string]any{
  612. "Permission": grant.Permission,
  613. "Grantee": map[string]any{
  614. "Type": grantee.Type,
  615. "ID": grantee.ID,
  616. },
  617. })
  618. case s3_constants.GrantTypeAmazonCustomerByEmail:
  619. GrantsToMap = append(GrantsToMap, map[string]any{
  620. "Permission": grant.Permission,
  621. "Grantee": map[string]any{
  622. "Type": grantee.Type,
  623. "EmailAddress": grantee.EmailAddress,
  624. },
  625. })
  626. default:
  627. return nil, fmt.Errorf("grantee type[%s] is not valid", *grantee.Type)
  628. }
  629. }
  630. return json.Marshal(GrantsToMap)
  631. }
  632. func GrantWithFullControl(accountId string) *s3.Grant {
  633. return &s3.Grant{
  634. Permission: &s3_constants.PermissionFullControl,
  635. Grantee: &s3.Grantee{
  636. Type: &s3_constants.GrantTypeCanonicalUser,
  637. ID: &accountId,
  638. },
  639. }
  640. }
  641. func CheckObjectAccessForReadObject(r *http.Request, w http.ResponseWriter, entry *filer.Entry, bucketOwnerId string) (statusCode int, ok bool) {
  642. if entry.IsDirectory() {
  643. return http.StatusOK, true
  644. }
  645. requestAccountId := GetAccountId(r)
  646. if len(requestAccountId) == 0 {
  647. glog.Warning("#checkObjectAccessForReadObject header[accountId] not exists!")
  648. return http.StatusForbidden, false
  649. }
  650. //owner access
  651. objectOwner := GetAcpOwner(entry.Extended, bucketOwnerId)
  652. if ValidateAccount(requestAccountId, objectOwner) {
  653. return http.StatusOK, true
  654. }
  655. //find in Grants
  656. acpGrants := GetAcpGrants(nil, entry.Extended)
  657. if acpGrants != nil {
  658. reqGrants := DetermineRequiredGrants(requestAccountId, s3_constants.PermissionRead)
  659. for _, requiredGrant := range reqGrants {
  660. for _, grant := range acpGrants {
  661. if GrantEquals(requiredGrant, grant) {
  662. return http.StatusOK, true
  663. }
  664. }
  665. }
  666. }
  667. glog.V(3).Infof("acl denied! request account id: %s", requestAccountId)
  668. return http.StatusForbidden, false
  669. }