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.

1477 lines
47 KiB

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