// Copyright 2023 The CubeFS Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or // implied. See the License for the specific language governing // permissions and limitations under the License. package objectnode import ( "encoding/xml" "net/http" "strings" "testing" "github.com/stretchr/testify/require" ) func TestHasAclInRequest(t *testing.T) { aclExample := ` user http://acs.amazonaws.com/groups/global/AllUsers WRITE ` // both have body acl and canned acl req, _ := http.NewRequest("PUT", "http://bucket.s3.com?acl", strings.NewReader(aclExample)) req.ContentLength = int64(len(aclExample)) require.Equal(t, true, HasAclInRequest(req)) req, _ = http.NewRequest("PUT", "http://bucket.s3.com?acl", nil) req.Header.Set("x-amz-acl", "private") require.Equal(t, true, HasAclInRequest(req)) req, _ = http.NewRequest("PUT", "http://bucket.s3.com?acl", nil) req.Header.Set("x-amz-grant-read", "id=user") require.Equal(t, true, HasAclInRequest(req)) req, _ = http.NewRequest("PUT", "http://bucket.s3.com?acl", nil) require.Equal(t, false, HasAclInRequest(req)) } func TestParseAcl_CannedAcl(t *testing.T) { // private req, _ := http.NewRequest("PUT", "http://bucket.s3.com?acl", nil) req.Header.Add("x-amz-acl", "private") acp, err := ParseACL(req, "user", false, false) require.NoError(t, err) require.Equal(t, "user", acp.Owner.Id) require.Equal(t, "user", acp.Acl.Grants[0].Grantee.Id) require.Equal(t, "CanonicalUser", acp.Acl.Grants[0].Grantee.Type) require.Equal(t, "FULL_CONTROL", acp.Acl.Grants[0].Permission) // public-read req, _ = http.NewRequest("PUT", "http://bucket.s3.com?acl", nil) req.Header.Add("x-amz-acl", "public-read") acp, err = ParseACL(req, "user", false, false) require.NoError(t, err) require.Equal(t, "user", acp.Owner.Id) require.Equal(t, "user", acp.Acl.Grants[0].Grantee.Id) require.Equal(t, "CanonicalUser", acp.Acl.Grants[0].Grantee.Type) require.Equal(t, "FULL_CONTROL", acp.Acl.Grants[0].Permission) require.Equal(t, "", acp.Acl.Grants[1].Grantee.Id) require.Equal(t, "http://acs.amazonaws.com/groups/global/AllUsers", acp.Acl.Grants[1].Grantee.URI) require.Equal(t, "Group", acp.Acl.Grants[1].Grantee.Type) require.Equal(t, "READ", acp.Acl.Grants[1].Permission) // public-read-write req, _ = http.NewRequest("PUT", "http://bucket.s3.com?acl", nil) req.Header.Add("x-amz-acl", "public-read-write") acp, err = ParseACL(req, "user", false, false) require.NoError(t, err) require.Equal(t, "user", acp.Owner.Id) require.Equal(t, "user", acp.Acl.Grants[0].Grantee.Id) require.Equal(t, "CanonicalUser", acp.Acl.Grants[0].Grantee.Type) require.Equal(t, "FULL_CONTROL", acp.Acl.Grants[0].Permission) require.Equal(t, "", acp.Acl.Grants[1].Grantee.Id) require.Equal(t, "http://acs.amazonaws.com/groups/global/AllUsers", acp.Acl.Grants[1].Grantee.URI) require.Equal(t, "Group", acp.Acl.Grants[1].Grantee.Type) require.Equal(t, "READ", acp.Acl.Grants[1].Permission) require.Equal(t, "", acp.Acl.Grants[2].Grantee.Id) require.Equal(t, "http://acs.amazonaws.com/groups/global/AllUsers", acp.Acl.Grants[2].Grantee.URI) require.Equal(t, "Group", acp.Acl.Grants[2].Grantee.Type) require.Equal(t, "WRITE", acp.Acl.Grants[2].Permission) // authenticated-read req, _ = http.NewRequest("PUT", "http://bucket.s3.com?acl", nil) req.Header.Add("x-amz-acl", "authenticated-read") acp, err = ParseACL(req, "user", false, false) require.NoError(t, err) require.Equal(t, "user", acp.Owner.Id) require.Equal(t, "user", acp.Acl.Grants[0].Grantee.Id) require.Equal(t, "CanonicalUser", acp.Acl.Grants[0].Grantee.Type) require.Equal(t, "FULL_CONTROL", acp.Acl.Grants[0].Permission) require.Equal(t, "", acp.Acl.Grants[1].Grantee.Id) require.Equal(t, "http://acs.amazonaws.com/groups/global/AuthenticatedUsers", acp.Acl.Grants[1].Grantee.URI) require.Equal(t, "Group", acp.Acl.Grants[1].Grantee.Type) require.Equal(t, "READ", acp.Acl.Grants[1].Permission) } func TestParseAcl_GrantAclHeader(t *testing.T) { req, _ := http.NewRequest("PUT", "http://bucket.s3.com?acl", nil) req.Header.Add("x-amz-grant-read", "uri=http://acs.amazonaws.com/groups/global/AllUsers, id=user1") req.Header.Add("x-amz-grant-write", "id = user2, id=user3") req.Header.Add("x-amz-grant-read-acp", "id=user4") req.Header.Add("x-amz-grant-write-acp", "id=user5") req.Header.Add("x-amz-grant-full-control", "id=user") acp, err := ParseACL(req, "user", false, false) require.NoError(t, err) _, err = xml.Marshal(acp) require.NoError(t, err) expectAclXml := ` user http://acs.amazonaws.com/groups/global/AllUsers READ user1 READ user2 WRITE user3 WRITE user4 READ_ACP user5 WRITE_ACP user FULL_CONTROL ` var expectAcp AccessControlPolicy err = xml.Unmarshal([]byte(expectAclXml), &expectAcp) require.NoError(t, err) require.Equal(t, &expectAcp, acp) req, _ = http.NewRequest("PUT", "http://bucket.s3.com?acl", nil) req.Header.Add("x-amz-grant-read", "") _, err = ParseACL(req, "user", false, false) require.EqualError(t, err, ErrMissingGrants.Error()) req, _ = http.NewRequest("PUT", "http://bucket.s3.com?acl", nil) req.Header.Add("x-amz-grant-read", "uri=http://acs.amazonaws.com/wrong/uri") _, err = ParseACL(req, "user", false, false) require.EqualError(t, err, ErrInvalidGroupUri.Error()) req, _ = http.NewRequest("PUT", "http://bucket.s3.com?acl", nil) req.Header.Add("x-amz-grant-read", "id=user1 id=user2") _, err = ParseACL(req, "user", false, false) require.EqualError(t, err, InvalidArgument.Error()) req, _ = http.NewRequest("PUT", "http://bucket.s3.com?acl", nil) req.Header.Add("x-amz-grant-read", "id=") _, err = ParseACL(req, "user", false, false) require.EqualError(t, err, InvalidArgument.Error()) req, _ = http.NewRequest("PUT", "http://bucket.s3.com?acl", nil) req.Header.Add("x-amz-grant-read", "=user") _, err = ParseACL(req, "user", false, false) require.EqualError(t, err, InvalidArgument.Error()) } func TestParseAcl_XmlBodyAcl(t *testing.T) { aclExample := ` user http://acs.amazonaws.com/groups/global/AllUsers WRITE user1 READ ` req, _ := http.NewRequest("PUT", "http://bucket.s3.com?acl", strings.NewReader(aclExample)) req.ContentLength = int64(len(aclExample)) acp, err := ParseACL(req, "user", true, false) require.NoError(t, err) require.Equal(t, "user", acp.Owner.Id) require.Equal(t, "WRITE", acp.Acl.Grants[0].Permission) require.Equal(t, "Group", acp.Acl.Grants[0].Grantee.Type) require.Equal(t, "http://acs.amazonaws.com/groups/global/AllUsers", acp.Acl.Grants[0].Grantee.URI) require.Equal(t, "READ", acp.Acl.Grants[1].Permission) require.Equal(t, "CanonicalUser", acp.Acl.Grants[1].Grantee.Type) require.Equal(t, "user1", acp.Acl.Grants[1].Grantee.Id) aclExample = ` user http://acs.amazonaws.com/groups/global/AllUsers WRITE ` // wrong xml format req, _ = http.NewRequest("PUT", "http://bucket.s3.com?acl", strings.NewReader(aclExample)) req.ContentLength = int64(len(aclExample)) _, err = ParseACL(req, "user", true, false) require.EqualError(t, err, ErrMalformedACL.Error()) aclExample = ` user WRITE ` // both have no URI and ID req, _ = http.NewRequest("PUT", "http://bucket.s3.com?acl", strings.NewReader(aclExample)) req.ContentLength = int64(len(aclExample)) _, err = ParseACL(req, "user", true, false) require.EqualError(t, err, ErrMalformedACL.Error()) aclExample = ` user user1 http://acs.amazonaws.com/groups/global/AllUsers READ_ACP ` // both have ID and URI req, _ = http.NewRequest("PUT", "http://bucket.s3.com?acl", strings.NewReader(aclExample)) req.ContentLength = int64(len(aclExample)) _, err = ParseACL(req, "user", true, false) require.EqualError(t, err, ErrMalformedACL.Error()) aclExample = ` user http://acs.amazonaws.com/groups/global/WrongRUI READ_ACP ` // Group but gave an invalid URI req, _ = http.NewRequest("PUT", "http://bucket.s3.com?acl", strings.NewReader(aclExample)) req.ContentLength = int64(len(aclExample)) _, err = ParseACL(req, "user", true, false) require.EqualError(t, err, ErrInvalidGroupUri.Error()) aclExample = ` user http://acs.amazonaws.com/groups/global/AllUsers READ_ACP ` // CanonicalUser but given the URI req, _ = http.NewRequest("PUT", "http://bucket.s3.com?acl", strings.NewReader(aclExample)) req.ContentLength = int64(len(aclExample)) _, err = ParseACL(req, "user", true, false) require.EqualError(t, err, ErrMalformedACL.Error()) aclExample = ` user http://acs.amazonaws.com/groups/global/AllUsers READ_ACP ` // invalid type req, _ = http.NewRequest("PUT", "http://bucket.s3.com?acl", strings.NewReader(aclExample)) req.ContentLength = int64(len(aclExample)) _, err = ParseACL(req, "user", true, false) require.EqualError(t, err, ErrMalformedACL.Error()) aclExample = ` UserIsNotOwner http://acs.amazonaws.com/groups/global/AllUsers WRITE ` // user is not owner req, _ = http.NewRequest("PUT", "http://bucket.s3.com?acl", strings.NewReader(aclExample)) req.ContentLength = int64(len(aclExample)) _, err = ParseACL(req, "user", true, false) require.EqualError(t, err, AccessDenied.Error()) } func TestCreateDefaultACL(t *testing.T) { req, _ := http.NewRequest("PUT", "http://bucket.s3.com?acl", nil) acp, err := ParseACL(req, "user", false, true) require.NoError(t, err) require.Equal(t, "user", acp.Owner.Id) require.Equal(t, "user", acp.Acl.Grants[0].Grantee.Id) require.Equal(t, "CanonicalUser", acp.Acl.Grants[0].Grantee.Type) require.Equal(t, "FULL_CONTROL", acp.Acl.Grants[0].Permission) } func TestConflictAcl(t *testing.T) { aclExample := ` user http://acs.amazonaws.com/groups/global/AllUsers WRITE ` // both have body acl and canned acl req, _ := http.NewRequest("PUT", "http://bucket.s3.com?acl", strings.NewReader(aclExample)) req.ContentLength = int64(len(aclExample)) req.Header.Set("x-amz-acl", "private") _, err := ParseACL(req, "user", true, false) require.EqualError(t, err, ErrUnexpectedContent.Error()) // both have body acl and grant acl req, _ = http.NewRequest("PUT", "http://bucket.s3.com?acl", strings.NewReader(aclExample)) req.ContentLength = int64(len(aclExample)) req.Header.Set("x-amz-grant-read", "id=user1") _, err = ParseACL(req, "user", true, false) require.EqualError(t, err, ErrUnexpectedContent.Error()) // both have canned acl and grant acl req, _ = http.NewRequest("PUT", "http://bucket.s3.com?acl", nil) req.Header.Set("x-amz-grant-read", "id=user1") req.Header.Set("x-amz-acl", "public-read") _, err = ParseACL(req, "user", false, false) require.EqualError(t, err, ErrConflictAclHeader.Error()) }