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.

725 lines
21 KiB

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