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.

723 lines
21 KiB

  1. package s3api
  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. "github.com/seaweedfs/seaweedfs/weed/util"
  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.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.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. default:
  324. errCode = s3err.ErrInvalidAclArgument
  325. }
  326. return
  327. }
  328. // ValidateAndTransferGrants validate grant & transfer Email-Grant to Id-Grant
  329. func ValidateAndTransferGrants(accountManager AccountManager, grants []*s3.Grant) ([]*s3.Grant, s3err.ErrorCode) {
  330. var result []*s3.Grant
  331. for _, grant := range grants {
  332. grantee := grant.Grantee
  333. if grantee == nil || grantee.Type == nil {
  334. glog.Warning("invalid grantee! grantee or granteeType is nil")
  335. return nil, s3err.ErrInvalidRequest
  336. }
  337. switch *grantee.Type {
  338. case s3_constants.GrantTypeGroup:
  339. if grantee.URI == nil {
  340. glog.Warning("invalid group grantee! group URI is nil")
  341. return nil, s3err.ErrInvalidRequest
  342. }
  343. ok := s3_constants.ValidateGroup(*grantee.URI)
  344. if !ok {
  345. glog.Warningf("invalid group grantee! group name[%s] is not valid", *grantee.URI)
  346. return nil, s3err.ErrInvalidRequest
  347. }
  348. result = append(result, grant)
  349. case s3_constants.GrantTypeCanonicalUser:
  350. if grantee.ID == nil {
  351. glog.Warning("invalid canonical grantee! account id is nil")
  352. return nil, s3err.ErrInvalidRequest
  353. }
  354. name := accountManager.GetAccountNameById(*grantee.ID)
  355. if len(name) == 0 {
  356. glog.Warningf("invalid canonical grantee! account id[%s] is not exists", *grantee.ID)
  357. return nil, s3err.ErrInvalidRequest
  358. }
  359. result = append(result, grant)
  360. case s3_constants.GrantTypeAmazonCustomerByEmail:
  361. if grantee.EmailAddress == nil {
  362. glog.Warning("invalid email grantee! email address is nil")
  363. return nil, s3err.ErrInvalidRequest
  364. }
  365. accountId := accountManager.GetAccountIdByEmail(*grantee.EmailAddress)
  366. if len(accountId) == 0 {
  367. glog.Warningf("invalid email grantee! email address[%s] is not exists", *grantee.EmailAddress)
  368. return nil, s3err.ErrInvalidRequest
  369. }
  370. result = append(result, &s3.Grant{
  371. Grantee: &s3.Grantee{
  372. Type: &s3_constants.GrantTypeCanonicalUser,
  373. ID: &accountId,
  374. },
  375. Permission: grant.Permission,
  376. })
  377. default:
  378. return nil, s3err.ErrInvalidRequest
  379. }
  380. }
  381. return result, s3err.ErrNone
  382. }
  383. // ValidateObjectOwnershipAndGrants validate if grants equals OwnerFullControl when 'ObjectOwnership' is 'BucketOwnerEnforced'
  384. func ValidateObjectOwnershipAndGrants(objectOwnership, bucketOwnerId string, grants []*s3.Grant) s3err.ErrorCode {
  385. if len(grants) == 0 {
  386. return s3err.ErrNone
  387. }
  388. if objectOwnership == "" {
  389. objectOwnership = s3_constants.DefaultObjectOwnership
  390. }
  391. if objectOwnership != s3_constants.OwnershipBucketOwnerEnforced {
  392. return s3err.ErrNone
  393. }
  394. if len(grants) > 1 {
  395. return s3err.AccessControlListNotSupported
  396. }
  397. bucketOwnerFullControlGrant := &s3.Grant{
  398. Permission: &s3_constants.PermissionFullControl,
  399. Grantee: &s3.Grantee{
  400. Type: &s3_constants.GrantTypeCanonicalUser,
  401. ID: &bucketOwnerId,
  402. },
  403. }
  404. if GrantEquals(bucketOwnerFullControlGrant, grants[0]) {
  405. return s3err.ErrNone
  406. }
  407. return s3err.AccessControlListNotSupported
  408. }
  409. // DetermineRequiredGrants generates the grant set (Grants) according to accountId and reqPermission.
  410. func DetermineRequiredGrants(accountId, permission string) (grants []*s3.Grant) {
  411. // group grantee (AllUsers)
  412. grants = append(grants, &s3.Grant{
  413. Grantee: &s3.Grantee{
  414. Type: &s3_constants.GrantTypeGroup,
  415. URI: &s3_constants.GranteeGroupAllUsers,
  416. },
  417. Permission: &permission,
  418. })
  419. grants = append(grants, &s3.Grant{
  420. Grantee: &s3.Grantee{
  421. Type: &s3_constants.GrantTypeGroup,
  422. URI: &s3_constants.GranteeGroupAllUsers,
  423. },
  424. Permission: &s3_constants.PermissionFullControl,
  425. })
  426. // canonical grantee (accountId)
  427. grants = append(grants, &s3.Grant{
  428. Grantee: &s3.Grantee{
  429. Type: &s3_constants.GrantTypeCanonicalUser,
  430. ID: &accountId,
  431. },
  432. Permission: &permission,
  433. })
  434. grants = append(grants, &s3.Grant{
  435. Grantee: &s3.Grantee{
  436. Type: &s3_constants.GrantTypeCanonicalUser,
  437. ID: &accountId,
  438. },
  439. Permission: &s3_constants.PermissionFullControl,
  440. })
  441. // group grantee (AuthenticateUsers)
  442. if accountId != s3_constants.AccountAnonymousId {
  443. grants = append(grants, &s3.Grant{
  444. Grantee: &s3.Grantee{
  445. Type: &s3_constants.GrantTypeGroup,
  446. URI: &s3_constants.GranteeGroupAuthenticatedUsers,
  447. },
  448. Permission: &permission,
  449. })
  450. grants = append(grants, &s3.Grant{
  451. Grantee: &s3.Grantee{
  452. Type: &s3_constants.GrantTypeGroup,
  453. URI: &s3_constants.GranteeGroupAuthenticatedUsers,
  454. },
  455. Permission: &s3_constants.PermissionFullControl,
  456. })
  457. }
  458. return
  459. }
  460. func SetAcpOwnerHeader(r *http.Request, acpOwnerId string) {
  461. r.Header.Set(s3_constants.ExtAmzOwnerKey, acpOwnerId)
  462. }
  463. func GetAcpOwner(entryExtended map[string][]byte, defaultOwner string) string {
  464. ownerIdBytes, ok := entryExtended[s3_constants.ExtAmzOwnerKey]
  465. if ok && len(ownerIdBytes) > 0 {
  466. return string(ownerIdBytes)
  467. }
  468. return defaultOwner
  469. }
  470. func SetAcpGrantsHeader(r *http.Request, grants []*s3.Grant) {
  471. if len(grants) > 0 {
  472. a, err := MarshalGrantsToJson(grants)
  473. if err == nil {
  474. r.Header.Set(s3_constants.ExtAmzAclKey, string(a))
  475. } else {
  476. glog.Warning("Marshal acp grants err", err)
  477. }
  478. }
  479. }
  480. // GetAcpGrants return grants parsed from entry
  481. func GetAcpGrants(ownerId *string, entryExtended map[string][]byte) []*s3.Grant {
  482. acpBytes, ok := entryExtended[s3_constants.ExtAmzAclKey]
  483. if ok && len(acpBytes) > 0 {
  484. var grants []*s3.Grant
  485. err := json.Unmarshal(acpBytes, &grants)
  486. if err == nil {
  487. return grants
  488. }
  489. glog.Warning("grants Unmarshal error", err)
  490. }
  491. if ownerId == nil {
  492. return nil
  493. }
  494. return []*s3.Grant{
  495. {
  496. Grantee: &s3.Grantee{
  497. Type: &s3_constants.GrantTypeCanonicalUser,
  498. ID: ownerId,
  499. },
  500. Permission: &s3_constants.PermissionFullControl,
  501. },
  502. }
  503. }
  504. // AssembleEntryWithAcp fill entry with owner and grants
  505. func AssembleEntryWithAcp(filerEntry *filer_pb.Entry, ownerId string, grants []*s3.Grant) s3err.ErrorCode {
  506. if filerEntry.Extended == nil {
  507. filerEntry.Extended = make(map[string][]byte)
  508. }
  509. if len(ownerId) > 0 {
  510. filerEntry.Extended[s3_constants.ExtAmzOwnerKey] = []byte(ownerId)
  511. } else {
  512. delete(filerEntry.Extended, s3_constants.ExtAmzOwnerKey)
  513. }
  514. if grants != nil {
  515. grantsBytes, err := MarshalGrantsToJson(grants)
  516. if err != nil {
  517. glog.Warning("assemble acp to entry:", err)
  518. return s3err.ErrInvalidRequest
  519. }
  520. filerEntry.Extended[s3_constants.ExtAmzAclKey] = grantsBytes
  521. } else {
  522. delete(filerEntry.Extended, s3_constants.ExtAmzAclKey)
  523. }
  524. return s3err.ErrNone
  525. }
  526. // GrantEquals Compare whether two Grants are equal in meaning, not completely
  527. // equal (compare Grantee.Type and the corresponding Value for equality, other
  528. // fields of Grantee are ignored)
  529. func GrantEquals(a, b *s3.Grant) bool {
  530. // grant
  531. if a == b {
  532. return true
  533. }
  534. if a == nil || b == nil {
  535. return false
  536. }
  537. // grant.Permission
  538. if a.Permission != b.Permission {
  539. if a.Permission == nil || b.Permission == nil {
  540. return false
  541. }
  542. if *a.Permission != *b.Permission {
  543. return false
  544. }
  545. }
  546. // grant.Grantee
  547. ag := a.Grantee
  548. bg := b.Grantee
  549. if ag != bg {
  550. if ag == nil || bg == nil {
  551. return false
  552. }
  553. // grantee.Type
  554. if ag.Type != bg.Type {
  555. if ag.Type == nil || bg.Type == nil {
  556. return false
  557. }
  558. if *ag.Type != *bg.Type {
  559. return false
  560. }
  561. }
  562. // value corresponding to granteeType
  563. if ag.Type != nil {
  564. switch *ag.Type {
  565. case s3_constants.GrantTypeGroup:
  566. if ag.URI != bg.URI {
  567. if ag.URI == nil || bg.URI == nil {
  568. return false
  569. }
  570. if *ag.URI != *bg.URI {
  571. return false
  572. }
  573. }
  574. case s3_constants.GrantTypeCanonicalUser:
  575. if ag.ID != bg.ID {
  576. if ag.ID == nil || bg.ID == nil {
  577. return false
  578. }
  579. if *ag.ID != *bg.ID {
  580. return false
  581. }
  582. }
  583. case s3_constants.GrantTypeAmazonCustomerByEmail:
  584. if ag.EmailAddress != bg.EmailAddress {
  585. if ag.EmailAddress == nil || bg.EmailAddress == nil {
  586. return false
  587. }
  588. if *ag.EmailAddress != *bg.EmailAddress {
  589. return false
  590. }
  591. }
  592. }
  593. }
  594. }
  595. return true
  596. }
  597. func MarshalGrantsToJson(grants []*s3.Grant) ([]byte, error) {
  598. if len(grants) == 0 {
  599. return []byte{}, nil
  600. }
  601. var GrantsToMap []map[string]any
  602. for _, grant := range grants {
  603. grantee := grant.Grantee
  604. switch *grantee.Type {
  605. case s3_constants.GrantTypeGroup:
  606. GrantsToMap = append(GrantsToMap, map[string]any{
  607. "Permission": grant.Permission,
  608. "Grantee": map[string]any{
  609. "Type": grantee.Type,
  610. "URI": grantee.URI,
  611. },
  612. })
  613. case s3_constants.GrantTypeCanonicalUser:
  614. GrantsToMap = append(GrantsToMap, map[string]any{
  615. "Permission": grant.Permission,
  616. "Grantee": map[string]any{
  617. "Type": grantee.Type,
  618. "ID": grantee.ID,
  619. },
  620. })
  621. case s3_constants.GrantTypeAmazonCustomerByEmail:
  622. GrantsToMap = append(GrantsToMap, map[string]any{
  623. "Permission": grant.Permission,
  624. "Grantee": map[string]any{
  625. "Type": grantee.Type,
  626. "EmailAddress": grantee.EmailAddress,
  627. },
  628. })
  629. default:
  630. return nil, fmt.Errorf("grantee type[%s] is not valid", *grantee.Type)
  631. }
  632. }
  633. return json.Marshal(GrantsToMap)
  634. }
  635. func GrantWithFullControl(accountId string) *s3.Grant {
  636. return &s3.Grant{
  637. Permission: &s3_constants.PermissionFullControl,
  638. Grantee: &s3.Grantee{
  639. Type: &s3_constants.GrantTypeCanonicalUser,
  640. ID: &accountId,
  641. },
  642. }
  643. }
  644. func CheckObjectAccessForReadObject(r *http.Request, w http.ResponseWriter, entry *filer.Entry, bucketOwnerId string) (statusCode int, ok bool) {
  645. if entry.IsDirectory() {
  646. return http.StatusOK, true
  647. }
  648. requestAccountId := GetAccountId(r)
  649. if len(requestAccountId) == 0 {
  650. glog.Warning("#checkObjectAccessForReadObject header[accountId] not exists!")
  651. return http.StatusForbidden, false
  652. }
  653. //owner access
  654. objectOwner := GetAcpOwner(entry.Extended, bucketOwnerId)
  655. if ValidateAccount(requestAccountId, objectOwner) {
  656. return http.StatusOK, true
  657. }
  658. //find in Grants
  659. acpGrants := GetAcpGrants(nil, entry.Extended)
  660. if acpGrants != nil {
  661. reqGrants := DetermineRequiredGrants(requestAccountId, s3_constants.PermissionRead)
  662. for _, requiredGrant := range reqGrants {
  663. for _, grant := range acpGrants {
  664. if GrantEquals(requiredGrant, grant) {
  665. return http.StatusOK, true
  666. }
  667. }
  668. }
  669. }
  670. glog.V(3).Infof("acl denied! request account id: %s", requestAccountId)
  671. return http.StatusForbidden, false
  672. }