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.

1466 lines
47 KiB

  1. package s3acl
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "github.com/aws/aws-sdk-go/service/s3"
  6. "github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
  7. "github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
  8. "github.com/seaweedfs/seaweedfs/weed/s3api/s3account"
  9. "github.com/seaweedfs/seaweedfs/weed/s3api/s3err"
  10. "io"
  11. "net/http"
  12. "testing"
  13. )
  14. var (
  15. accountManager = &s3account.AccountManager{
  16. IdNameMapping: map[string]string{
  17. s3account.AccountAdmin.Id: s3account.AccountAdmin.Name,
  18. s3account.AccountAnonymous.Id: s3account.AccountAnonymous.Name,
  19. "accountA": "accountA",
  20. "accountB": "accountB",
  21. },
  22. EmailIdMapping: map[string]string{
  23. s3account.AccountAdmin.EmailAddress: s3account.AccountAdmin.Id,
  24. s3account.AccountAnonymous.EmailAddress: s3account.AccountAnonymous.Id,
  25. "accountA@example.com": "accountA",
  26. "accountBexample.com": "accountB",
  27. },
  28. }
  29. )
  30. func TestGetAccountId(t *testing.T) {
  31. req := &http.Request{
  32. Header: make(map[string][]string),
  33. }
  34. //case1
  35. //accountId: "admin"
  36. req.Header.Set(s3_constants.AmzAccountId, s3account.AccountAdmin.Id)
  37. if GetAccountId(req) != s3account.AccountAdmin.Id {
  38. t.Fatal("expect accountId: admin")
  39. }
  40. //case2
  41. //accountId: "anoymous"
  42. req.Header.Set(s3_constants.AmzAccountId, s3account.AccountAnonymous.Id)
  43. if GetAccountId(req) != s3account.AccountAnonymous.Id {
  44. t.Fatal("expect accountId: anonymous")
  45. }
  46. //case3
  47. //accountId is nil => "anonymous"
  48. req.Header.Del(s3_constants.AmzAccountId)
  49. if GetAccountId(req) != s3account.AccountAnonymous.Id {
  50. t.Fatal("expect accountId: anonymous")
  51. }
  52. }
  53. func grantsEquals(a, b []*s3.Grant) bool {
  54. if len(a) != len(b) {
  55. return false
  56. }
  57. for i, grant := range a {
  58. if !GrantEquals(grant, b[i]) {
  59. return false
  60. }
  61. }
  62. return true
  63. }
  64. func TestDetermineReqGrants(t *testing.T) {
  65. {
  66. //case1: request account is anonymous
  67. accountId := s3account.AccountAnonymous.Id
  68. reqPermission := s3_constants.PermissionRead
  69. resultGrants := DetermineRequiredGrants(accountId, reqPermission)
  70. expectGrants := []*s3.Grant{
  71. {
  72. Grantee: &s3.Grantee{
  73. Type: &s3_constants.GrantTypeGroup,
  74. URI: &s3_constants.GranteeGroupAllUsers,
  75. },
  76. Permission: &reqPermission,
  77. },
  78. {
  79. Grantee: &s3.Grantee{
  80. Type: &s3_constants.GrantTypeGroup,
  81. URI: &s3_constants.GranteeGroupAllUsers,
  82. },
  83. Permission: &s3_constants.PermissionFullControl,
  84. },
  85. {
  86. Grantee: &s3.Grantee{
  87. Type: &s3_constants.GrantTypeCanonicalUser,
  88. ID: &accountId,
  89. },
  90. Permission: &reqPermission,
  91. },
  92. {
  93. Grantee: &s3.Grantee{
  94. Type: &s3_constants.GrantTypeCanonicalUser,
  95. ID: &accountId,
  96. },
  97. Permission: &s3_constants.PermissionFullControl,
  98. },
  99. }
  100. if !grantsEquals(resultGrants, expectGrants) {
  101. t.Fatalf("grants not expect")
  102. }
  103. }
  104. {
  105. //case2: request account is not anonymous (Iam authed)
  106. accountId := "accountX"
  107. reqPermission := s3_constants.PermissionRead
  108. resultGrants := DetermineRequiredGrants(accountId, reqPermission)
  109. expectGrants := []*s3.Grant{
  110. {
  111. Grantee: &s3.Grantee{
  112. Type: &s3_constants.GrantTypeGroup,
  113. URI: &s3_constants.GranteeGroupAllUsers,
  114. },
  115. Permission: &reqPermission,
  116. },
  117. {
  118. Grantee: &s3.Grantee{
  119. Type: &s3_constants.GrantTypeGroup,
  120. URI: &s3_constants.GranteeGroupAllUsers,
  121. },
  122. Permission: &s3_constants.PermissionFullControl,
  123. },
  124. {
  125. Grantee: &s3.Grantee{
  126. Type: &s3_constants.GrantTypeCanonicalUser,
  127. ID: &accountId,
  128. },
  129. Permission: &reqPermission,
  130. },
  131. {
  132. Grantee: &s3.Grantee{
  133. Type: &s3_constants.GrantTypeCanonicalUser,
  134. ID: &accountId,
  135. },
  136. Permission: &s3_constants.PermissionFullControl,
  137. },
  138. {
  139. Grantee: &s3.Grantee{
  140. Type: &s3_constants.GrantTypeGroup,
  141. URI: &s3_constants.GranteeGroupAuthenticatedUsers,
  142. },
  143. Permission: &reqPermission,
  144. },
  145. {
  146. Grantee: &s3.Grantee{
  147. Type: &s3_constants.GrantTypeGroup,
  148. URI: &s3_constants.GranteeGroupAuthenticatedUsers,
  149. },
  150. Permission: &s3_constants.PermissionFullControl,
  151. },
  152. }
  153. if !grantsEquals(resultGrants, expectGrants) {
  154. t.Fatalf("grants not expect")
  155. }
  156. }
  157. }
  158. func TestAssembleEntryWithAcp(t *testing.T) {
  159. defaultOwner := "admin"
  160. //case1
  161. //assemble with non-empty grants
  162. expectOwner := "accountS"
  163. expectGrants := []*s3.Grant{
  164. {
  165. Permission: &s3_constants.PermissionRead,
  166. Grantee: &s3.Grantee{
  167. Type: &s3_constants.GrantTypeGroup,
  168. ID: &s3account.AccountAdmin.Id,
  169. URI: &s3_constants.GranteeGroupAllUsers,
  170. },
  171. },
  172. }
  173. entry := &filer_pb.Entry{}
  174. AssembleEntryWithAcp(entry, expectOwner, expectGrants)
  175. resultOwner := GetAcpOwner(entry.Extended, defaultOwner)
  176. if resultOwner != expectOwner {
  177. t.Fatalf("owner not expect")
  178. }
  179. resultGrants := GetAcpGrants(nil, entry.Extended)
  180. if !grantsEquals(resultGrants, expectGrants) {
  181. t.Fatal("grants not expect")
  182. }
  183. //case2
  184. //assemble with empty grants (override)
  185. AssembleEntryWithAcp(entry, "", nil)
  186. resultOwner = GetAcpOwner(entry.Extended, defaultOwner)
  187. if resultOwner != defaultOwner {
  188. t.Fatalf("owner not expect")
  189. }
  190. resultGrants = GetAcpGrants(nil, entry.Extended)
  191. if len(resultGrants) != 0 {
  192. t.Fatal("grants not expect")
  193. }
  194. }
  195. func TestGrantEquals(t *testing.T) {
  196. testCases := map[bool]bool{
  197. GrantEquals(nil, nil): true,
  198. GrantEquals(&s3.Grant{}, nil): false,
  199. GrantEquals(&s3.Grant{}, &s3.Grant{}): true,
  200. GrantEquals(&s3.Grant{
  201. Permission: &s3_constants.PermissionRead,
  202. }, &s3.Grant{}): false,
  203. GrantEquals(&s3.Grant{
  204. Permission: &s3_constants.PermissionRead,
  205. }, &s3.Grant{
  206. Permission: &s3_constants.PermissionRead,
  207. }): true,
  208. GrantEquals(&s3.Grant{
  209. Permission: &s3_constants.PermissionRead,
  210. Grantee: &s3.Grantee{},
  211. }, &s3.Grant{
  212. Permission: &s3_constants.PermissionRead,
  213. Grantee: &s3.Grantee{},
  214. }): true,
  215. GrantEquals(&s3.Grant{
  216. Permission: &s3_constants.PermissionRead,
  217. Grantee: &s3.Grantee{
  218. Type: &s3_constants.GrantTypeGroup,
  219. },
  220. }, &s3.Grant{
  221. Permission: &s3_constants.PermissionRead,
  222. Grantee: &s3.Grantee{},
  223. }): false,
  224. //type not present, compare other fields of grant is meaningless
  225. GrantEquals(&s3.Grant{
  226. Permission: &s3_constants.PermissionRead,
  227. Grantee: &s3.Grantee{
  228. ID: &s3account.AccountAdmin.Id,
  229. EmailAddress: &s3account.AccountAdmin.EmailAddress,
  230. },
  231. }, &s3.Grant{
  232. Permission: &s3_constants.PermissionRead,
  233. Grantee: &s3.Grantee{
  234. ID: &s3account.AccountAdmin.Id,
  235. },
  236. }): true,
  237. GrantEquals(&s3.Grant{
  238. Permission: &s3_constants.PermissionRead,
  239. Grantee: &s3.Grantee{
  240. Type: &s3_constants.GrantTypeGroup,
  241. },
  242. }, &s3.Grant{
  243. Permission: &s3_constants.PermissionRead,
  244. Grantee: &s3.Grantee{
  245. Type: &s3_constants.GrantTypeGroup,
  246. },
  247. }): true,
  248. GrantEquals(&s3.Grant{
  249. Permission: &s3_constants.PermissionRead,
  250. Grantee: &s3.Grantee{
  251. Type: &s3_constants.GrantTypeGroup,
  252. URI: &s3_constants.GranteeGroupAllUsers,
  253. },
  254. }, &s3.Grant{
  255. Permission: &s3_constants.PermissionRead,
  256. Grantee: &s3.Grantee{
  257. Type: &s3_constants.GrantTypeGroup,
  258. URI: &s3_constants.GranteeGroupAllUsers,
  259. },
  260. }): true,
  261. GrantEquals(&s3.Grant{
  262. Permission: &s3_constants.PermissionWrite,
  263. Grantee: &s3.Grantee{
  264. Type: &s3_constants.GrantTypeGroup,
  265. URI: &s3_constants.GranteeGroupAllUsers,
  266. },
  267. }, &s3.Grant{
  268. Permission: &s3_constants.PermissionRead,
  269. Grantee: &s3.Grantee{
  270. Type: &s3_constants.GrantTypeGroup,
  271. URI: &s3_constants.GranteeGroupAllUsers,
  272. },
  273. }): false,
  274. GrantEquals(&s3.Grant{
  275. Permission: &s3_constants.PermissionRead,
  276. Grantee: &s3.Grantee{
  277. Type: &s3_constants.GrantTypeGroup,
  278. ID: &s3account.AccountAdmin.Id,
  279. },
  280. }, &s3.Grant{
  281. Permission: &s3_constants.PermissionRead,
  282. Grantee: &s3.Grantee{
  283. Type: &s3_constants.GrantTypeGroup,
  284. ID: &s3account.AccountAdmin.Id,
  285. },
  286. }): true,
  287. GrantEquals(&s3.Grant{
  288. Permission: &s3_constants.PermissionRead,
  289. Grantee: &s3.Grantee{
  290. Type: &s3_constants.GrantTypeGroup,
  291. ID: &s3account.AccountAdmin.Id,
  292. URI: &s3_constants.GranteeGroupAllUsers,
  293. },
  294. }, &s3.Grant{
  295. Permission: &s3_constants.PermissionRead,
  296. Grantee: &s3.Grantee{
  297. Type: &s3_constants.GrantTypeGroup,
  298. ID: &s3account.AccountAdmin.Id,
  299. },
  300. }): false,
  301. GrantEquals(&s3.Grant{
  302. Permission: &s3_constants.PermissionRead,
  303. Grantee: &s3.Grantee{
  304. Type: &s3_constants.GrantTypeGroup,
  305. ID: &s3account.AccountAdmin.Id,
  306. URI: &s3_constants.GranteeGroupAllUsers,
  307. },
  308. }, &s3.Grant{
  309. Permission: &s3_constants.PermissionRead,
  310. Grantee: &s3.Grantee{
  311. Type: &s3_constants.GrantTypeGroup,
  312. URI: &s3_constants.GranteeGroupAllUsers,
  313. },
  314. }): true,
  315. }
  316. for tc, expect := range testCases {
  317. if tc != expect {
  318. t.Fatal("TestGrantEquals not expect!")
  319. }
  320. }
  321. }
  322. func TestSetAcpOwnerHeader(t *testing.T) {
  323. ownerId := "accountZ"
  324. req := &http.Request{
  325. Header: make(map[string][]string),
  326. }
  327. SetAcpOwnerHeader(req, ownerId)
  328. if req.Header.Get(s3_constants.ExtAmzOwnerKey) != ownerId {
  329. t.Fatalf("owner unexpect")
  330. }
  331. }
  332. func TestSetAcpGrantsHeader(t *testing.T) {
  333. req := &http.Request{
  334. Header: make(map[string][]string),
  335. }
  336. grants := []*s3.Grant{
  337. {
  338. Permission: &s3_constants.PermissionRead,
  339. Grantee: &s3.Grantee{
  340. Type: &s3_constants.GrantTypeGroup,
  341. ID: &s3account.AccountAdmin.Id,
  342. URI: &s3_constants.GranteeGroupAllUsers,
  343. },
  344. },
  345. }
  346. SetAcpGrantsHeader(req, grants)
  347. grantsJson, _ := json.Marshal(grants)
  348. if req.Header.Get(s3_constants.ExtAmzAclKey) != string(grantsJson) {
  349. t.Fatalf("owner unexpect")
  350. }
  351. }
  352. func TestGrantWithFullControl(t *testing.T) {
  353. accountId := "Accountaskdfj"
  354. expect := &s3.Grant{
  355. Permission: &s3_constants.PermissionFullControl,
  356. Grantee: &s3.Grantee{
  357. Type: &s3_constants.GrantTypeCanonicalUser,
  358. ID: &accountId,
  359. },
  360. }
  361. result := GrantWithFullControl(accountId)
  362. if !GrantEquals(result, expect) {
  363. t.Fatal("GrantWithFullControl not expect")
  364. }
  365. }
  366. func TestExtractObjectAcl(t *testing.T) {
  367. type Case struct {
  368. id string
  369. resultErrCode, expectErrCode s3err.ErrorCode
  370. resultGrants, expectGrants []*s3.Grant
  371. resultOwnerId, expectOwnerId string
  372. }
  373. testCases := make([]*Case, 0)
  374. accountAdminId := "admin"
  375. //Request body to specify AccessControlList
  376. {
  377. //ownership: ObjectWriter
  378. //s3:PutObjectAcl('createObject' is set to false), config acl through request body
  379. req := &http.Request{
  380. Header: make(map[string][]string),
  381. }
  382. req.Body = io.NopCloser(bytes.NewReader([]byte(`
  383. <AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  384. <Owner>
  385. <ID>admin</ID>
  386. <DisplayName>admin</DisplayName>
  387. </Owner>
  388. <AccessControlList>
  389. <Grant>
  390. <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser">
  391. <ID>admin</ID>
  392. </Grantee>
  393. <Permission>FULL_CONTROL</Permission>
  394. </Grant>
  395. <Grant>
  396. <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Group">
  397. <URI>http://acs.amazonaws.com/groups/global/AllUsers</URI>
  398. </Grantee>
  399. <Permission>FULL_CONTROL</Permission>
  400. </Grant>
  401. </AccessControlList>
  402. </AccessControlPolicy>
  403. `)))
  404. requestAccountId := "accountA"
  405. ownerId, grants, errCode := ExtractObjectAcl(req, accountManager, s3_constants.OwnershipObjectWriter, accountAdminId, requestAccountId, false)
  406. testCases = append(testCases, &Case{
  407. "TestExtractObjectAcl: ownership-ObjectWriter, createObject-false, acl-requestBody",
  408. errCode, s3err.ErrNone,
  409. grants, []*s3.Grant{
  410. {
  411. Grantee: &s3.Grantee{
  412. Type: &s3_constants.GrantTypeCanonicalUser,
  413. ID: &accountAdminId,
  414. },
  415. Permission: &s3_constants.PermissionFullControl,
  416. },
  417. {
  418. Grantee: &s3.Grantee{
  419. Type: &s3_constants.GrantTypeGroup,
  420. URI: &s3_constants.GranteeGroupAllUsers,
  421. },
  422. Permission: &s3_constants.PermissionFullControl,
  423. },
  424. },
  425. ownerId, accountAdminId,
  426. })
  427. }
  428. {
  429. //ownership: BucketOwnerEnforced (extra acl is not allowed)
  430. //s3:PutObjectAcl('createObject' is set to false), config acl through request body
  431. req := &http.Request{
  432. Header: make(map[string][]string),
  433. }
  434. req.Body = io.NopCloser(bytes.NewReader([]byte(`
  435. <AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  436. <Owner>
  437. <ID>admin</ID>
  438. <DisplayName>admin</DisplayName>
  439. </Owner>
  440. <AccessControlList>
  441. <Grant>
  442. <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser">
  443. <ID>admin</ID>
  444. </Grantee>
  445. <Permission>FULL_CONTROL</Permission>
  446. </Grant>
  447. <Grant>
  448. <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Group">
  449. <URI>http://acs.amazonaws.com/groups/global/AllUsers</URI>
  450. </Grantee>
  451. <Permission>FULL_CONTROL</Permission>
  452. </Grant>
  453. </AccessControlList>
  454. </AccessControlPolicy>
  455. `)))
  456. requestAccountId := "accountA"
  457. _, _, errCode := ExtractObjectAcl(req, accountManager, s3_constants.OwnershipBucketOwnerEnforced, accountAdminId, requestAccountId, false)
  458. testCases = append(testCases, &Case{
  459. id: "TestExtractObjectAcl: ownership-BucketOwnerEnforced, createObject-false, acl-requestBody",
  460. resultErrCode: errCode, expectErrCode: s3err.AccessControlListNotSupported,
  461. })
  462. }
  463. {
  464. //ownership: ObjectWriter
  465. //s3:PutObject('createObject' is set to false), request body will be ignored when parse acl
  466. req := &http.Request{
  467. Header: make(map[string][]string),
  468. }
  469. req.Body = io.NopCloser(bytes.NewReader([]byte(`
  470. <AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  471. <Owner>
  472. <ID>admin</ID>
  473. <DisplayName>admin</DisplayName>
  474. </Owner>
  475. <AccessControlList>
  476. <Grant>
  477. <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser">
  478. <ID>admin</ID>
  479. </Grantee>
  480. <Permission>FULL_CONTROL</Permission>
  481. </Grant>
  482. <Grant>
  483. <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Group">
  484. <URI>http://acs.amazonaws.com/groups/global/AllUsers</URI>
  485. </Grantee>
  486. <Permission>FULL_CONTROL</Permission>
  487. </Grant>
  488. </AccessControlList>
  489. </AccessControlPolicy>
  490. `)))
  491. requestAccountId := "accountA"
  492. ownerId, grants, errCode := ExtractObjectAcl(req, accountManager, s3_constants.OwnershipObjectWriter, accountAdminId, requestAccountId, true)
  493. testCases = append(testCases, &Case{
  494. "TestExtractObjectAcl: ownership-ObjectWriter, createObject-true, acl-requestBody",
  495. errCode, s3err.ErrNone,
  496. grants, []*s3.Grant{},
  497. ownerId, "",
  498. })
  499. }
  500. {
  501. //ownership: BucketOwnerEnforced (extra acl is not allowed)
  502. //s3:PutObject('createObject' is set to true), request body will be ignored when parse acl
  503. req := &http.Request{
  504. Header: make(map[string][]string),
  505. }
  506. req.Body = io.NopCloser(bytes.NewReader([]byte(`
  507. <AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  508. <Owner>
  509. <ID>admin</ID>
  510. <DisplayName>admin</DisplayName>
  511. </Owner>
  512. <AccessControlList>
  513. <Grant>
  514. <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser">
  515. <ID>admin</ID>
  516. </Grantee>
  517. <Permission>FULL_CONTROL</Permission>
  518. </Grant>
  519. <Grant>
  520. <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Group">
  521. <URI>http://acs.amazonaws.com/groups/global/AllUsers</URI>
  522. </Grantee>
  523. <Permission>FULL_CONTROL</Permission>
  524. </Grant>
  525. </AccessControlList>
  526. </AccessControlPolicy>
  527. `)))
  528. requestAccountId := "accountA"
  529. ownerId, grants, errCode := ExtractObjectAcl(req, accountManager, s3_constants.OwnershipBucketOwnerEnforced, accountAdminId, requestAccountId, true)
  530. testCases = append(testCases, &Case{
  531. "TestExtractObjectAcl: ownership-BucketOwnerEnforced, createObject-true, acl-requestBody",
  532. errCode, s3err.ErrNone,
  533. grants, []*s3.Grant{},
  534. ownerId, "",
  535. })
  536. }
  537. //CannedAcl Header to specify ACL
  538. //cannedAcl, putObjectACL
  539. {
  540. //ownership: ObjectWriter
  541. //s3:PutObjectACL('createObject' is set to false), parse cannedACL header
  542. req := &http.Request{
  543. Header: make(map[string][]string),
  544. }
  545. req.Header.Set(s3_constants.AmzCannedAcl, s3_constants.CannedAclBucketOwnerFullControl)
  546. bucketOwnerId := "admin"
  547. requestAccountId := "accountA"
  548. ownerId, grants, errCode := ExtractObjectAcl(req, accountManager, s3_constants.OwnershipObjectWriter, bucketOwnerId, requestAccountId, false)
  549. testCases = append(testCases, &Case{
  550. "TestExtractObjectAcl: ownership-ObjectWriter, createObject-false, acl-CannedAcl",
  551. errCode, s3err.ErrNone,
  552. grants, []*s3.Grant{
  553. {
  554. Grantee: &s3.Grantee{
  555. Type: &s3_constants.GrantTypeCanonicalUser,
  556. ID: &requestAccountId,
  557. },
  558. Permission: &s3_constants.PermissionFullControl,
  559. },
  560. {
  561. Grantee: &s3.Grantee{
  562. Type: &s3_constants.GrantTypeCanonicalUser,
  563. ID: &bucketOwnerId,
  564. },
  565. Permission: &s3_constants.PermissionFullControl,
  566. },
  567. },
  568. ownerId, "",
  569. })
  570. }
  571. {
  572. //ownership: BucketOwnerPreferred
  573. //s3:PutObjectACL('createObject' is set to false), parse cannedACL header
  574. req := &http.Request{
  575. Header: make(map[string][]string),
  576. }
  577. req.Header.Set(s3_constants.AmzCannedAcl, s3_constants.CannedAclBucketOwnerFullControl)
  578. bucketOwnerId := "admin"
  579. requestAccountId := "accountA"
  580. ownerId, grants, errCode := ExtractObjectAcl(req, accountManager, s3_constants.OwnershipBucketOwnerPreferred, bucketOwnerId, requestAccountId, false)
  581. testCases = append(testCases, &Case{
  582. "TestExtractObjectAcl: ownership-BucketOwnerPreferred, createObject-false, acl-CannedAcl",
  583. errCode, s3err.ErrNone,
  584. grants, []*s3.Grant{
  585. {
  586. Grantee: &s3.Grantee{
  587. Type: &s3_constants.GrantTypeCanonicalUser,
  588. ID: &requestAccountId,
  589. },
  590. Permission: &s3_constants.PermissionFullControl,
  591. },
  592. {
  593. Grantee: &s3.Grantee{
  594. Type: &s3_constants.GrantTypeCanonicalUser,
  595. ID: &bucketOwnerId,
  596. },
  597. Permission: &s3_constants.PermissionFullControl,
  598. },
  599. },
  600. ownerId, "",
  601. })
  602. }
  603. {
  604. //ownership: BucketOwnerEnforced
  605. //s3:PutObjectACL('createObject' is set to false), parse cannedACL header
  606. req := &http.Request{
  607. Header: make(map[string][]string),
  608. }
  609. req.Header.Set(s3_constants.AmzCannedAcl, s3_constants.CannedAclBucketOwnerFullControl)
  610. bucketOwnerId := "admin"
  611. requestAccountId := "accountA"
  612. _, _, errCode := ExtractObjectAcl(req, accountManager, s3_constants.OwnershipBucketOwnerEnforced, bucketOwnerId, requestAccountId, false)
  613. testCases = append(testCases, &Case{
  614. id: "TestExtractObjectAcl: ownership-BucketOwnerEnforced, createObject-false, acl-CannedAcl",
  615. resultErrCode: errCode, expectErrCode: s3err.AccessControlListNotSupported,
  616. })
  617. }
  618. //cannedACL, putObject
  619. {
  620. //ownership: ObjectWriter
  621. //s3:PutObject('createObject' is set to true), parse cannedACL header
  622. req := &http.Request{
  623. Header: make(map[string][]string),
  624. }
  625. req.Header.Set(s3_constants.AmzCannedAcl, s3_constants.CannedAclBucketOwnerFullControl)
  626. bucketOwnerId := "admin"
  627. requestAccountId := "accountA"
  628. ownerId, grants, errCode := ExtractObjectAcl(req, accountManager, s3_constants.OwnershipObjectWriter, bucketOwnerId, requestAccountId, true)
  629. testCases = append(testCases, &Case{
  630. "TestExtractObjectAcl: ownership-ObjectWriter, createObject-true, acl-CannedAcl",
  631. errCode, s3err.ErrNone,
  632. grants, []*s3.Grant{
  633. {
  634. Grantee: &s3.Grantee{
  635. Type: &s3_constants.GrantTypeCanonicalUser,
  636. ID: &requestAccountId,
  637. },
  638. Permission: &s3_constants.PermissionFullControl,
  639. },
  640. {
  641. Grantee: &s3.Grantee{
  642. Type: &s3_constants.GrantTypeCanonicalUser,
  643. ID: &bucketOwnerId,
  644. },
  645. Permission: &s3_constants.PermissionFullControl,
  646. },
  647. },
  648. ownerId, "",
  649. })
  650. }
  651. {
  652. //ownership: BucketOwnerPreferred
  653. //s3:PutObject('createObject' is set to true), parse cannedACL header
  654. req := &http.Request{
  655. Header: make(map[string][]string),
  656. }
  657. req.Header.Set(s3_constants.AmzCannedAcl, s3_constants.CannedAclBucketOwnerFullControl)
  658. bucketOwnerId := "admin"
  659. requestAccountId := "accountA"
  660. ownerId, grants, errCode := ExtractObjectAcl(req, accountManager, s3_constants.OwnershipBucketOwnerPreferred, bucketOwnerId, requestAccountId, true)
  661. testCases = append(testCases, &Case{
  662. "TestExtractObjectAcl: ownership-BucketOwnerPreferred, createObject-true, acl-CannedAcl",
  663. errCode, s3err.ErrNone,
  664. grants, []*s3.Grant{
  665. {
  666. Grantee: &s3.Grantee{
  667. Type: &s3_constants.GrantTypeCanonicalUser,
  668. ID: &bucketOwnerId,
  669. },
  670. Permission: &s3_constants.PermissionFullControl,
  671. },
  672. },
  673. ownerId, "",
  674. })
  675. }
  676. {
  677. //ownership: BucketOwnerEnforced
  678. //s3:PutObject('createObject' is set to true), parse cannedACL header
  679. req := &http.Request{
  680. Header: make(map[string][]string),
  681. }
  682. req.Header.Set(s3_constants.AmzCannedAcl, s3_constants.CannedAclBucketOwnerFullControl)
  683. bucketOwnerId := "admin"
  684. requestAccountId := "accountA"
  685. _, _, errCode := ExtractObjectAcl(req, accountManager, s3_constants.OwnershipBucketOwnerEnforced, bucketOwnerId, requestAccountId, true)
  686. testCases = append(testCases, &Case{
  687. id: "TestExtractObjectAcl: ownership-BucketOwnerEnforced, createObject-true, acl-CannedAcl",
  688. resultErrCode: errCode, expectErrCode: s3err.AccessControlListNotSupported,
  689. })
  690. }
  691. //cannedAcl, putObjectACL
  692. {
  693. //ownership: ObjectWriter
  694. //s3:PutObjectACL('createObject' is set to false), parse customAcl header
  695. req := &http.Request{
  696. Header: make(map[string][]string),
  697. }
  698. req.Header.Set(s3_constants.AmzAclFullControl, "id=accountA,id=\"admin\"")
  699. bucketOwnerId := "admin"
  700. requestAccountId := "accountA"
  701. ownerId, grants, errCode := ExtractObjectAcl(req, accountManager, s3_constants.OwnershipObjectWriter, bucketOwnerId, requestAccountId, false)
  702. testCases = append(testCases, &Case{
  703. "TestExtractObjectAcl: ownership-ObjectWriter, createObject-false, acl-customAcl",
  704. errCode, s3err.ErrNone,
  705. grants, []*s3.Grant{
  706. {
  707. Grantee: &s3.Grantee{
  708. Type: &s3_constants.GrantTypeCanonicalUser,
  709. ID: &requestAccountId,
  710. },
  711. Permission: &s3_constants.PermissionFullControl,
  712. },
  713. {
  714. Grantee: &s3.Grantee{
  715. Type: &s3_constants.GrantTypeCanonicalUser,
  716. ID: &bucketOwnerId,
  717. },
  718. Permission: &s3_constants.PermissionFullControl,
  719. },
  720. },
  721. ownerId, "",
  722. })
  723. }
  724. {
  725. //ownership: BucketOwnerPreferred
  726. //s3:PutObjectACL('createObject' is set to false), parse customAcl header
  727. req := &http.Request{
  728. Header: make(map[string][]string),
  729. }
  730. req.Header.Set(s3_constants.AmzAclFullControl, "id=accountA,id=\"admin\"")
  731. bucketOwnerId := "admin"
  732. requestAccountId := "accountA"
  733. ownerId, grants, errCode := ExtractObjectAcl(req, accountManager, s3_constants.OwnershipBucketOwnerPreferred, bucketOwnerId, requestAccountId, false)
  734. testCases = append(testCases, &Case{
  735. "TestExtractObjectAcl: ownership-BucketOwnerPreferred, createObject-false, acl-customAcl",
  736. errCode, s3err.ErrNone,
  737. grants, []*s3.Grant{
  738. {
  739. Grantee: &s3.Grantee{
  740. Type: &s3_constants.GrantTypeCanonicalUser,
  741. ID: &requestAccountId,
  742. },
  743. Permission: &s3_constants.PermissionFullControl,
  744. },
  745. {
  746. Grantee: &s3.Grantee{
  747. Type: &s3_constants.GrantTypeCanonicalUser,
  748. ID: &bucketOwnerId,
  749. },
  750. Permission: &s3_constants.PermissionFullControl,
  751. },
  752. },
  753. ownerId, "",
  754. })
  755. }
  756. {
  757. //ownership: BucketOwnerEnforced
  758. //s3:PutObjectACL('createObject' is set to false), parse customAcl header
  759. req := &http.Request{
  760. Header: make(map[string][]string),
  761. }
  762. req.Header.Set(s3_constants.AmzAclFullControl, "id=accountA,id=\"admin\"")
  763. bucketOwnerId := "admin"
  764. requestAccountId := "accountA"
  765. _, _, errCode := ExtractObjectAcl(req, accountManager, s3_constants.OwnershipBucketOwnerEnforced, bucketOwnerId, requestAccountId, false)
  766. testCases = append(testCases, &Case{
  767. id: "TestExtractObjectAcl: ownership-BucketOwnerEnforced, createObject-false, acl-customAcl",
  768. resultErrCode: errCode, expectErrCode: s3err.AccessControlListNotSupported,
  769. })
  770. }
  771. //customAcl, putObject
  772. {
  773. //ownership: ObjectWriter
  774. //s3:PutObject('createObject' is set to true), parse customAcl header
  775. req := &http.Request{
  776. Header: make(map[string][]string),
  777. }
  778. req.Header.Set(s3_constants.AmzAclFullControl, "id=accountA,id=\"admin\"")
  779. bucketOwnerId := "admin"
  780. requestAccountId := "accountA"
  781. ownerId, grants, errCode := ExtractObjectAcl(req, accountManager, s3_constants.OwnershipObjectWriter, bucketOwnerId, requestAccountId, true)
  782. testCases = append(testCases, &Case{
  783. "TestExtractObjectAcl: ownership-ObjectWriter, createObject-true, acl-customAcl",
  784. errCode, s3err.ErrNone,
  785. grants, []*s3.Grant{
  786. {
  787. Grantee: &s3.Grantee{
  788. Type: &s3_constants.GrantTypeCanonicalUser,
  789. ID: &requestAccountId,
  790. },
  791. Permission: &s3_constants.PermissionFullControl,
  792. },
  793. {
  794. Grantee: &s3.Grantee{
  795. Type: &s3_constants.GrantTypeCanonicalUser,
  796. ID: &bucketOwnerId,
  797. },
  798. Permission: &s3_constants.PermissionFullControl,
  799. },
  800. },
  801. ownerId, "",
  802. })
  803. }
  804. {
  805. //ownership: BucketOwnerPreferred
  806. //s3:PutObject('createObject' is set to true), parse customAcl header
  807. req := &http.Request{
  808. Header: make(map[string][]string),
  809. }
  810. req.Header.Set(s3_constants.AmzAclFullControl, "id=\"admin\"")
  811. bucketOwnerId := "admin"
  812. requestAccountId := "accountA"
  813. ownerId, grants, errCode := ExtractObjectAcl(req, accountManager, s3_constants.OwnershipBucketOwnerPreferred, bucketOwnerId, requestAccountId, true)
  814. testCases = append(testCases, &Case{
  815. "TestExtractObjectAcl: ownership-BucketOwnerPreferred, createObject-true, acl-customAcl",
  816. errCode, s3err.ErrNone,
  817. grants, []*s3.Grant{
  818. {
  819. Grantee: &s3.Grantee{
  820. Type: &s3_constants.GrantTypeCanonicalUser,
  821. ID: &bucketOwnerId,
  822. },
  823. Permission: &s3_constants.PermissionFullControl,
  824. },
  825. },
  826. ownerId, "",
  827. })
  828. }
  829. {
  830. //ownership: BucketOwnerEnforced
  831. //s3:PutObject('createObject' is set to true), parse customAcl header
  832. req := &http.Request{
  833. Header: make(map[string][]string),
  834. }
  835. req.Header.Set(s3_constants.AmzAclFullControl, "id=accountA,id=\"admin\"")
  836. bucketOwnerId := "admin"
  837. requestAccountId := "accountA"
  838. _, _, errCode := ExtractObjectAcl(req, accountManager, s3_constants.OwnershipBucketOwnerEnforced, bucketOwnerId, requestAccountId, true)
  839. testCases = append(testCases, &Case{
  840. id: "TestExtractObjectAcl: ownership-BucketOwnerEnforced, createObject-true, acl-customAcl",
  841. resultErrCode: errCode, expectErrCode: s3err.AccessControlListNotSupported,
  842. })
  843. }
  844. {
  845. //parse acp from request header: both canned acl and custom acl not allowed
  846. req := &http.Request{
  847. Header: make(map[string][]string),
  848. }
  849. req.Header.Set(s3_constants.AmzAclFullControl, "id=admin, id=\"accountA\"")
  850. req.Header.Set(s3_constants.AmzCannedAcl, "private")
  851. bucketOwnerId := "admin"
  852. requestAccountId := "accountA"
  853. _, _, errCode := ExtractObjectAcl(req, accountManager, s3_constants.OwnershipObjectWriter, bucketOwnerId, requestAccountId, false)
  854. testCases = append(testCases, &Case{
  855. id: "Only one of cannedAcl, customAcl is allowed",
  856. resultErrCode: errCode, expectErrCode: s3err.ErrInvalidRequest,
  857. })
  858. }
  859. {
  860. //Acl can only be specified in one of requestBody, cannedAcl, customAcl, simultaneous use is not allowed
  861. req := &http.Request{
  862. Header: make(map[string][]string),
  863. }
  864. req.Header.Set(s3_constants.AmzAclFullControl, "id=admin, id=\"accountA\"")
  865. req.Header.Set(s3_constants.AmzCannedAcl, "private")
  866. req.Body = io.NopCloser(bytes.NewReader([]byte(`
  867. <AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  868. <Owner>
  869. <ID>admin</ID>
  870. <DisplayName>admin</DisplayName>
  871. </Owner>
  872. <AccessControlList>
  873. <Grant>
  874. <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser">
  875. <ID>admin</ID>
  876. </Grantee>
  877. <Permission>FULL_CONTROL</Permission>
  878. </Grant>
  879. <Grant>
  880. <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Group">
  881. <URI>http://acs.amazonaws.com/groups/global/AllUsers</URI>
  882. </Grantee>
  883. <Permission>FULL_CONTROL</Permission>
  884. </Grant>
  885. </AccessControlList>
  886. </AccessControlPolicy>
  887. `)))
  888. requestAccountId := "accountA"
  889. _, _, errCode := ExtractObjectAcl(req, accountManager, s3_constants.OwnershipObjectWriter, accountAdminId, requestAccountId, false)
  890. testCases = append(testCases, &Case{
  891. id: "Only one of requestBody, cannedAcl, customAcl is allowed",
  892. resultErrCode: errCode, expectErrCode: s3err.ErrUnexpectedContent,
  893. })
  894. }
  895. for _, tc := range testCases {
  896. if tc.resultErrCode != tc.expectErrCode {
  897. t.Fatalf("case[%s]: errorCode[%v] not expect[%v]", tc.id, s3err.GetAPIError(tc.resultErrCode).Code, s3err.GetAPIError(tc.expectErrCode).Code)
  898. }
  899. if !grantsEquals(tc.resultGrants, tc.expectGrants) {
  900. t.Fatalf("case[%s]: grants not expect", tc.id)
  901. }
  902. }
  903. }
  904. func TestBucketObjectAcl(t *testing.T) {
  905. type Case struct {
  906. id string
  907. resultErrCode, expectErrCode s3err.ErrorCode
  908. resultGrants, expectGrants []*s3.Grant
  909. }
  910. testCases := make([]*Case, 0)
  911. accountAdminId := "admin"
  912. //Request body to specify AccessControlList
  913. {
  914. //ownership: ObjectWriter
  915. //s3:PutBucketAcl('createObject' is set to false), config acl through request body
  916. req := &http.Request{
  917. Header: make(map[string][]string),
  918. }
  919. req.Body = io.NopCloser(bytes.NewReader([]byte(`
  920. <AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  921. <Owner>
  922. <ID>admin</ID>
  923. <DisplayName>admin</DisplayName>
  924. </Owner>
  925. <AccessControlList>
  926. <Grant>
  927. <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser">
  928. <ID>admin</ID>
  929. </Grantee>
  930. <Permission>FULL_CONTROL</Permission>
  931. </Grant>
  932. <Grant>
  933. <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Group">
  934. <URI>http://acs.amazonaws.com/groups/global/AllUsers</URI>
  935. </Grantee>
  936. <Permission>FULL_CONTROL</Permission>
  937. </Grant>
  938. </AccessControlList>
  939. </AccessControlPolicy>
  940. `)))
  941. bucketOwnerId := "admin"
  942. requestAccountId := "accountA"
  943. grants, errCode := ExtractBucketAcl(req, accountManager, s3_constants.OwnershipObjectWriter, bucketOwnerId, requestAccountId, false)
  944. testCases = append(testCases, &Case{
  945. "TestExtractBucketAcl: ownership-ObjectWriter, createObject-false, acl-requestBody",
  946. errCode, s3err.ErrNone,
  947. grants, []*s3.Grant{
  948. {
  949. Grantee: &s3.Grantee{
  950. Type: &s3_constants.GrantTypeCanonicalUser,
  951. ID: &accountAdminId,
  952. },
  953. Permission: &s3_constants.PermissionFullControl,
  954. },
  955. {
  956. Grantee: &s3.Grantee{
  957. Type: &s3_constants.GrantTypeGroup,
  958. URI: &s3_constants.GranteeGroupAllUsers,
  959. },
  960. Permission: &s3_constants.PermissionFullControl,
  961. },
  962. },
  963. })
  964. }
  965. {
  966. //ownership: BucketOwnerEnforced (extra acl is not allowed)
  967. //s3:PutBucketAcl('createObject' is set to false), config acl through request body
  968. req := &http.Request{
  969. Header: make(map[string][]string),
  970. }
  971. req.Body = io.NopCloser(bytes.NewReader([]byte(`
  972. <AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  973. <Owner>
  974. <ID>admin</ID>
  975. <DisplayName>admin</DisplayName>
  976. </Owner>
  977. <AccessControlList>
  978. <Grant>
  979. <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser">
  980. <ID>admin</ID>
  981. </Grantee>
  982. <Permission>FULL_CONTROL</Permission>
  983. </Grant>
  984. <Grant>
  985. <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Group">
  986. <URI>http://acs.amazonaws.com/groups/global/AllUsers</URI>
  987. </Grantee>
  988. <Permission>FULL_CONTROL</Permission>
  989. </Grant>
  990. </AccessControlList>
  991. </AccessControlPolicy>
  992. `)))
  993. requestAccountId := "accountA"
  994. _, errCode := ExtractBucketAcl(req, accountManager, s3_constants.OwnershipBucketOwnerEnforced, accountAdminId, requestAccountId, false)
  995. testCases = append(testCases, &Case{
  996. id: "TestExtractBucketAcl: ownership-BucketOwnerEnforced, createObject-false, acl-requestBody",
  997. resultErrCode: errCode, expectErrCode: s3err.AccessControlListNotSupported,
  998. })
  999. }
  1000. {
  1001. //ownership: ObjectWriter
  1002. //s3:PutObject('createObject' is set to false), request body will be ignored when parse acl
  1003. req := &http.Request{
  1004. Header: make(map[string][]string),
  1005. }
  1006. req.Body = io.NopCloser(bytes.NewReader([]byte(`
  1007. <AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  1008. <Owner>
  1009. <ID>admin</ID>
  1010. <DisplayName>admin</DisplayName>
  1011. </Owner>
  1012. <AccessControlList>
  1013. <Grant>
  1014. <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser">
  1015. <ID>admin</ID>
  1016. </Grantee>
  1017. <Permission>FULL_CONTROL</Permission>
  1018. </Grant>
  1019. <Grant>
  1020. <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Group">
  1021. <URI>http://acs.amazonaws.com/groups/global/AllUsers</URI>
  1022. </Grantee>
  1023. <Permission>FULL_CONTROL</Permission>
  1024. </Grant>
  1025. </AccessControlList>
  1026. </AccessControlPolicy>
  1027. `)))
  1028. requestAccountId := "accountA"
  1029. grants, errCode := ExtractBucketAcl(req, accountManager, s3_constants.OwnershipObjectWriter, accountAdminId, requestAccountId, true)
  1030. testCases = append(testCases, &Case{
  1031. "TestExtractBucketAcl: ownership-ObjectWriter, createObject-true, acl-requestBody",
  1032. errCode, s3err.ErrNone,
  1033. grants, []*s3.Grant{},
  1034. })
  1035. }
  1036. {
  1037. //ownership: BucketOwnerEnforced (extra acl is not allowed)
  1038. //s3:PutObject('createObject' is set to true), request body will be ignored when parse acl
  1039. req := &http.Request{
  1040. Header: make(map[string][]string),
  1041. }
  1042. req.Body = io.NopCloser(bytes.NewReader([]byte(`
  1043. <AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  1044. <Owner>
  1045. <ID>admin</ID>
  1046. <DisplayName>admin</DisplayName>
  1047. </Owner>
  1048. <AccessControlList>
  1049. <Grant>
  1050. <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser">
  1051. <ID>admin</ID>
  1052. </Grantee>
  1053. <Permission>FULL_CONTROL</Permission>
  1054. </Grant>
  1055. <Grant>
  1056. <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Group">
  1057. <URI>http://acs.amazonaws.com/groups/global/AllUsers</URI>
  1058. </Grantee>
  1059. <Permission>FULL_CONTROL</Permission>
  1060. </Grant>
  1061. </AccessControlList>
  1062. </AccessControlPolicy>
  1063. `)))
  1064. requestAccountId := "accountA"
  1065. grants, errCode := ExtractBucketAcl(req, accountManager, s3_constants.OwnershipBucketOwnerEnforced, accountAdminId, requestAccountId, true)
  1066. testCases = append(testCases, &Case{
  1067. "TestExtractBucketAcl: ownership-BucketOwnerEnforced, createObject-true, acl-requestBody",
  1068. errCode, s3err.ErrNone,
  1069. grants, []*s3.Grant{},
  1070. })
  1071. }
  1072. //CannedAcl Header to specify ACL
  1073. //cannedAcl, PutBucketAcl
  1074. {
  1075. //ownership: ObjectWriter
  1076. //s3:PutBucketAcl('createObject' is set to false), parse cannedACL header
  1077. req := &http.Request{
  1078. Header: make(map[string][]string),
  1079. }
  1080. req.Header.Set(s3_constants.AmzCannedAcl, s3_constants.CannedAclBucketOwnerFullControl)
  1081. bucketOwnerId := "admin"
  1082. requestAccountId := "accountA"
  1083. _, errCode := ExtractBucketAcl(req, accountManager, s3_constants.OwnershipObjectWriter, bucketOwnerId, requestAccountId, false)
  1084. testCases = append(testCases, &Case{
  1085. id: "TestExtractBucketAcl: ownership-ObjectWriter, createObject-false, acl-CannedAcl",
  1086. resultErrCode: errCode, expectErrCode: s3err.ErrInvalidAclArgument,
  1087. })
  1088. }
  1089. {
  1090. //ownership: BucketOwnerPreferred
  1091. //s3:PutBucketAcl('createObject' is set to false), parse cannedACL header
  1092. req := &http.Request{
  1093. Header: make(map[string][]string),
  1094. }
  1095. req.Header.Set(s3_constants.AmzCannedAcl, s3_constants.CannedAclBucketOwnerFullControl)
  1096. bucketOwnerId := "admin"
  1097. requestAccountId := "accountA"
  1098. _, errCode := ExtractBucketAcl(req, accountManager, s3_constants.OwnershipBucketOwnerPreferred, bucketOwnerId, requestAccountId, false)
  1099. testCases = append(testCases, &Case{
  1100. id: "TestExtractBucketAcl: ownership-BucketOwnerPreferred, createObject-false, acl-CannedAcl",
  1101. resultErrCode: errCode, expectErrCode: s3err.ErrInvalidAclArgument,
  1102. })
  1103. }
  1104. {
  1105. //ownership: BucketOwnerEnforced
  1106. //s3:PutBucketAcl('createObject' is set to false), parse cannedACL header
  1107. req := &http.Request{
  1108. Header: make(map[string][]string),
  1109. }
  1110. req.Header.Set(s3_constants.AmzCannedAcl, s3_constants.CannedAclBucketOwnerFullControl)
  1111. bucketOwnerId := "admin"
  1112. requestAccountId := "accountA"
  1113. _, errCode := ExtractBucketAcl(req, accountManager, s3_constants.OwnershipBucketOwnerEnforced, bucketOwnerId, requestAccountId, false)
  1114. testCases = append(testCases, &Case{
  1115. id: "TestExtractBucketAcl: ownership-BucketOwnerEnforced, createObject-false, acl-CannedAcl",
  1116. resultErrCode: errCode, expectErrCode: s3err.ErrInvalidAclArgument,
  1117. })
  1118. }
  1119. //cannedACL, createBucket
  1120. {
  1121. //ownership: ObjectWriter
  1122. //s3:PutObject('createObject' is set to true), parse cannedACL header
  1123. req := &http.Request{
  1124. Header: make(map[string][]string),
  1125. }
  1126. req.Header.Set(s3_constants.AmzCannedAcl, s3_constants.CannedAclBucketOwnerFullControl)
  1127. bucketOwnerId := "admin"
  1128. requestAccountId := "accountA"
  1129. _, errCode := ExtractBucketAcl(req, accountManager, s3_constants.OwnershipObjectWriter, bucketOwnerId, requestAccountId, true)
  1130. testCases = append(testCases, &Case{
  1131. id: "TestExtractBucketAcl: ownership-BucketOwnerEnforced, createObject-true, acl-CannedAcl",
  1132. resultErrCode: errCode, expectErrCode: s3err.ErrInvalidAclArgument,
  1133. })
  1134. }
  1135. {
  1136. //ownership: BucketOwnerPreferred
  1137. //s3:PutObject('createObject' is set to true), parse cannedACL header
  1138. req := &http.Request{
  1139. Header: make(map[string][]string),
  1140. }
  1141. req.Header.Set(s3_constants.AmzCannedAcl, s3_constants.CannedAclBucketOwnerFullControl)
  1142. bucketOwnerId := "admin"
  1143. requestAccountId := "accountA"
  1144. _, errCode := ExtractBucketAcl(req, accountManager, s3_constants.OwnershipBucketOwnerPreferred, bucketOwnerId, requestAccountId, true)
  1145. testCases = append(testCases, &Case{
  1146. id: "TestExtractBucketAcl: ownership-BucketOwnerPreferred, createObject-true, acl-CannedAcl",
  1147. resultErrCode: errCode, expectErrCode: s3err.ErrInvalidAclArgument,
  1148. })
  1149. }
  1150. {
  1151. //ownership: BucketOwnerEnforced
  1152. //s3:PutObject('createObject' is set to true), parse cannedACL header
  1153. req := &http.Request{
  1154. Header: make(map[string][]string),
  1155. }
  1156. req.Header.Set(s3_constants.AmzCannedAcl, s3_constants.CannedAclBucketOwnerFullControl)
  1157. bucketOwnerId := "admin"
  1158. requestAccountId := "accountA"
  1159. _, errCode := ExtractBucketAcl(req, accountManager, s3_constants.OwnershipBucketOwnerEnforced, bucketOwnerId, requestAccountId, true)
  1160. testCases = append(testCases, &Case{
  1161. id: "TestExtractBucketAcl: ownership-BucketOwnerEnforced, createObject-true, acl-CannedAcl",
  1162. resultErrCode: errCode, expectErrCode: s3err.ErrInvalidAclArgument,
  1163. })
  1164. }
  1165. //customAcl, PutBucketAcl
  1166. {
  1167. //ownership: ObjectWriter
  1168. //s3:PutBucketAcl('createObject' is set to false), parse customAcl header
  1169. req := &http.Request{
  1170. Header: make(map[string][]string),
  1171. }
  1172. req.Header.Set(s3_constants.AmzAclFullControl, "id=accountA,id=\"admin\"")
  1173. bucketOwnerId := "admin"
  1174. requestAccountId := "accountA"
  1175. grants, errCode := ExtractBucketAcl(req, accountManager, s3_constants.OwnershipObjectWriter, bucketOwnerId, requestAccountId, false)
  1176. testCases = append(testCases, &Case{
  1177. "TestExtractBucketAcl: ownership-ObjectWriter, createObject-false, acl-customAcl",
  1178. errCode, s3err.ErrNone,
  1179. grants, []*s3.Grant{
  1180. {
  1181. Grantee: &s3.Grantee{
  1182. Type: &s3_constants.GrantTypeCanonicalUser,
  1183. ID: &requestAccountId,
  1184. },
  1185. Permission: &s3_constants.PermissionFullControl,
  1186. },
  1187. {
  1188. Grantee: &s3.Grantee{
  1189. Type: &s3_constants.GrantTypeCanonicalUser,
  1190. ID: &bucketOwnerId,
  1191. },
  1192. Permission: &s3_constants.PermissionFullControl,
  1193. },
  1194. },
  1195. })
  1196. }
  1197. {
  1198. //ownership: BucketOwnerPreferred
  1199. //s3:PutBucketAcl('createObject' is set to false), parse customAcl header
  1200. req := &http.Request{
  1201. Header: make(map[string][]string),
  1202. }
  1203. req.Header.Set(s3_constants.AmzAclFullControl, "id=accountA,id=\"admin\"")
  1204. bucketOwnerId := "admin"
  1205. requestAccountId := "accountA"
  1206. grants, errCode := ExtractBucketAcl(req, accountManager, s3_constants.OwnershipBucketOwnerPreferred, bucketOwnerId, requestAccountId, false)
  1207. testCases = append(testCases, &Case{
  1208. "TestExtractBucketAcl: ownership-BucketOwnerPreferred, createObject-false, acl-customAcl",
  1209. errCode, s3err.ErrNone,
  1210. grants, []*s3.Grant{
  1211. {
  1212. Grantee: &s3.Grantee{
  1213. Type: &s3_constants.GrantTypeCanonicalUser,
  1214. ID: &requestAccountId,
  1215. },
  1216. Permission: &s3_constants.PermissionFullControl,
  1217. },
  1218. {
  1219. Grantee: &s3.Grantee{
  1220. Type: &s3_constants.GrantTypeCanonicalUser,
  1221. ID: &bucketOwnerId,
  1222. },
  1223. Permission: &s3_constants.PermissionFullControl,
  1224. },
  1225. },
  1226. })
  1227. }
  1228. {
  1229. //ownership: BucketOwnerEnforced
  1230. //s3:PutBucketAcl('createObject' is set to false), parse customAcl header
  1231. req := &http.Request{
  1232. Header: make(map[string][]string),
  1233. }
  1234. req.Header.Set(s3_constants.AmzAclFullControl, "id=accountA,id=\"admin\"")
  1235. bucketOwnerId := "admin"
  1236. requestAccountId := "accountA"
  1237. _, errCode := ExtractBucketAcl(req, accountManager, s3_constants.OwnershipBucketOwnerEnforced, bucketOwnerId, requestAccountId, false)
  1238. testCases = append(testCases, &Case{
  1239. id: "TestExtractBucketAcl: ownership-BucketOwnerEnforced, createObject-false, acl-customAcl",
  1240. resultErrCode: errCode, expectErrCode: s3err.AccessControlListNotSupported,
  1241. })
  1242. }
  1243. //customAcl, putObject
  1244. {
  1245. //ownership: ObjectWriter
  1246. //s3:PutObject('createObject' is set to true), parse customAcl header
  1247. req := &http.Request{
  1248. Header: make(map[string][]string),
  1249. }
  1250. req.Header.Set(s3_constants.AmzAclFullControl, "id=accountA,id=\"admin\"")
  1251. bucketOwnerId := "admin"
  1252. requestAccountId := "accountA"
  1253. grants, errCode := ExtractBucketAcl(req, accountManager, s3_constants.OwnershipObjectWriter, bucketOwnerId, requestAccountId, true)
  1254. testCases = append(testCases, &Case{
  1255. "TestExtractBucketAcl: ownership-ObjectWriter, createObject-true, acl-customAcl",
  1256. errCode, s3err.ErrNone,
  1257. grants, []*s3.Grant{
  1258. {
  1259. Grantee: &s3.Grantee{
  1260. Type: &s3_constants.GrantTypeCanonicalUser,
  1261. ID: &requestAccountId,
  1262. },
  1263. Permission: &s3_constants.PermissionFullControl,
  1264. },
  1265. {
  1266. Grantee: &s3.Grantee{
  1267. Type: &s3_constants.GrantTypeCanonicalUser,
  1268. ID: &bucketOwnerId,
  1269. },
  1270. Permission: &s3_constants.PermissionFullControl,
  1271. },
  1272. },
  1273. })
  1274. }
  1275. {
  1276. //ownership: BucketOwnerPreferred
  1277. //s3:PutObject('createObject' is set to true), parse customAcl header
  1278. req := &http.Request{
  1279. Header: make(map[string][]string),
  1280. }
  1281. req.Header.Set(s3_constants.AmzAclFullControl, "id=\"admin\"")
  1282. bucketOwnerId := "admin"
  1283. requestAccountId := "accountA"
  1284. grants, errCode := ExtractBucketAcl(req, accountManager, s3_constants.OwnershipBucketOwnerPreferred, bucketOwnerId, requestAccountId, true)
  1285. testCases = append(testCases, &Case{
  1286. "TestExtractBucketAcl: ownership-BucketOwnerPreferred, createObject-true, acl-customAcl",
  1287. errCode, s3err.ErrNone,
  1288. grants, []*s3.Grant{
  1289. {
  1290. Grantee: &s3.Grantee{
  1291. Type: &s3_constants.GrantTypeCanonicalUser,
  1292. ID: &bucketOwnerId,
  1293. },
  1294. Permission: &s3_constants.PermissionFullControl,
  1295. },
  1296. },
  1297. })
  1298. }
  1299. {
  1300. //ownership: BucketOwnerEnforced
  1301. //s3:PutObject('createObject' is set to true), parse customAcl header
  1302. req := &http.Request{
  1303. Header: make(map[string][]string),
  1304. }
  1305. req.Header.Set(s3_constants.AmzAclFullControl, "id=accountA,id=\"admin\"")
  1306. bucketOwnerId := "admin"
  1307. requestAccountId := "accountA"
  1308. _, errCode := ExtractBucketAcl(req, accountManager, s3_constants.OwnershipBucketOwnerEnforced, bucketOwnerId, requestAccountId, true)
  1309. testCases = append(testCases, &Case{
  1310. id: "TestExtractBucketAcl: ownership-BucketOwnerEnforced, createObject-true, acl-customAcl",
  1311. resultErrCode: errCode, expectErrCode: s3err.AccessControlListNotSupported,
  1312. })
  1313. }
  1314. {
  1315. //parse acp from request header: both canned acl and custom acl not allowed
  1316. req := &http.Request{
  1317. Header: make(map[string][]string),
  1318. }
  1319. req.Header.Set(s3_constants.AmzAclFullControl, "id=admin, id=\"accountA\"")
  1320. req.Header.Set(s3_constants.AmzCannedAcl, "private")
  1321. bucketOwnerId := "admin"
  1322. requestAccountId := "accountA"
  1323. _, errCode := ExtractBucketAcl(req, accountManager, s3_constants.OwnershipObjectWriter, bucketOwnerId, requestAccountId, false)
  1324. testCases = append(testCases, &Case{
  1325. id: "Only one of cannedAcl, customAcl is allowed",
  1326. resultErrCode: errCode, expectErrCode: s3err.ErrInvalidRequest,
  1327. })
  1328. }
  1329. {
  1330. //Acl can only be specified in one of requestBody, cannedAcl, customAcl, simultaneous use is not allowed
  1331. req := &http.Request{
  1332. Header: make(map[string][]string),
  1333. }
  1334. req.Header.Set(s3_constants.AmzAclFullControl, "id=admin, id=\"accountA\"")
  1335. req.Header.Set(s3_constants.AmzCannedAcl, "private")
  1336. req.Body = io.NopCloser(bytes.NewReader([]byte(`
  1337. <AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  1338. <Owner>
  1339. <ID>admin</ID>
  1340. <DisplayName>admin</DisplayName>
  1341. </Owner>
  1342. <AccessControlList>
  1343. <Grant>
  1344. <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser">
  1345. <ID>admin</ID>
  1346. </Grantee>
  1347. <Permission>FULL_CONTROL</Permission>
  1348. </Grant>
  1349. <Grant>
  1350. <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Group">
  1351. <URI>http://acs.amazonaws.com/groups/global/AllUsers</URI>
  1352. </Grantee>
  1353. <Permission>FULL_CONTROL</Permission>
  1354. </Grant>
  1355. </AccessControlList>
  1356. </AccessControlPolicy>
  1357. `)))
  1358. requestAccountId := "accountA"
  1359. _, errCode := ExtractBucketAcl(req, accountManager, s3_constants.OwnershipObjectWriter, accountAdminId, requestAccountId, false)
  1360. testCases = append(testCases, &Case{
  1361. id: "Only one of requestBody, cannedAcl, customAcl is allowed",
  1362. resultErrCode: errCode, expectErrCode: s3err.ErrUnexpectedContent,
  1363. })
  1364. }
  1365. for _, tc := range testCases {
  1366. if tc.resultErrCode != tc.expectErrCode {
  1367. t.Fatalf("case[%s]: errorCode[%v] not expect[%v]", tc.id, s3err.GetAPIError(tc.resultErrCode).Code, s3err.GetAPIError(tc.expectErrCode).Code)
  1368. }
  1369. if !grantsEquals(tc.resultGrants, tc.expectGrants) {
  1370. t.Fatalf("case[%s]: grants not expect", tc.id)
  1371. }
  1372. }
  1373. }
  1374. func TestMarshalGrantsToJson(t *testing.T) {
  1375. //ok
  1376. bucketOwnerId := "admin"
  1377. requestAccountId := "accountA"
  1378. grants := []*s3.Grant{
  1379. {
  1380. Grantee: &s3.Grantee{
  1381. Type: &s3_constants.GrantTypeCanonicalUser,
  1382. ID: &requestAccountId,
  1383. },
  1384. Permission: &s3_constants.PermissionFullControl,
  1385. },
  1386. {
  1387. Grantee: &s3.Grantee{
  1388. Type: &s3_constants.GrantTypeCanonicalUser,
  1389. ID: &bucketOwnerId,
  1390. },
  1391. Permission: &s3_constants.PermissionFullControl,
  1392. },
  1393. }
  1394. result, err := MarshalGrantsToJson(grants)
  1395. if err != nil {
  1396. t.Error(err)
  1397. }
  1398. var grants2 []*s3.Grant
  1399. err = json.Unmarshal(result, &grants2)
  1400. if err != nil {
  1401. t.Error(err)
  1402. }
  1403. print(string(result))
  1404. if !grantsEquals(grants, grants2) {
  1405. t.Fatal("grants not equal", grants, grants2)
  1406. }
  1407. //ok
  1408. result, err = MarshalGrantsToJson(nil)
  1409. if result != nil && err != nil {
  1410. t.Fatal("error: result, err = MarshalGrantsToJson(nil)")
  1411. }
  1412. }