2021-07-21 11:59:46 +00:00
package handler
import (
2022-11-09 14:25:02 +00:00
"bytes"
2021-07-21 11:59:46 +00:00
"crypto/ecdsa"
2021-08-30 07:55:42 +00:00
"crypto/rand"
"crypto/sha256"
2021-07-21 11:59:46 +00:00
"encoding/hex"
2022-11-09 14:25:02 +00:00
"encoding/json"
2024-03-05 06:56:12 +00:00
"encoding/xml"
2022-07-12 10:39:25 +00:00
"fmt"
2021-08-30 07:55:42 +00:00
"io"
2021-07-21 11:59:46 +00:00
"net/http"
2023-06-30 09:03:55 +00:00
"net/http/httptest"
2021-07-21 11:59:46 +00:00
"testing"
2023-03-07 14:38:08 +00:00
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
2023-06-30 09:03:55 +00:00
s3errors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
2024-03-01 14:11:07 +00:00
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer"
2023-07-05 14:05:45 +00:00
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
2023-03-07 14:38:08 +00:00
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
2023-12-08 07:44:13 +00:00
engineiam "git.frostfs.info/TrueCloudLab/policy-engine/iam"
2024-02-12 14:29:36 +00:00
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine"
2021-07-21 11:59:46 +00:00
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/stretchr/testify/require"
)
func TestTableToAst ( t * testing . T ) {
2021-08-30 07:55:42 +00:00
b := make ( [ ] byte , 32 )
_ , err := io . ReadFull ( rand . Reader , b )
require . NoError ( t , err )
2022-04-25 09:57:58 +00:00
var id oid . ID
2022-02-08 16:54:04 +00:00
id . SetSHA256 ( sha256 . Sum256 ( b ) )
2021-08-30 07:55:42 +00:00
2021-07-21 11:59:46 +00:00
key , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
key2 , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
table := new ( eacl . Table )
record := eacl . NewRecord ( )
record . SetAction ( eacl . ActionAllow )
record . SetOperation ( eacl . OperationGet )
eacl . AddFormedTarget ( record , eacl . RoleOthers )
table . AddRecord ( record )
record2 := eacl . NewRecord ( )
record2 . SetAction ( eacl . ActionDeny )
record2 . SetOperation ( eacl . OperationPut )
2022-07-07 09:00:09 +00:00
// Unknown role is used, because it is ignored when keys are set
2022-07-06 12:39:15 +00:00
eacl . AddFormedTarget ( record2 , eacl . RoleUnknown , * ( * ecdsa . PublicKey ) ( key . PublicKey ( ) ) , * ( ( * ecdsa . PublicKey ) ( key2 . PublicKey ( ) ) ) )
2022-09-07 06:59:24 +00:00
record2 . AddObjectAttributeFilter ( eacl . MatchStringEqual , object . AttributeFilePath , "objectName" )
2022-02-08 16:54:04 +00:00
record2 . AddObjectIDFilter ( eacl . MatchStringEqual , id )
2021-07-21 11:59:46 +00:00
table . AddRecord ( record2 )
expectedAst := & ast {
Resources : [ ] * astResource {
{
2021-08-30 07:55:42 +00:00
resourceInfo : resourceInfo { Bucket : "bucketName" } ,
2021-07-21 11:59:46 +00:00
Operations : [ ] * astOperation { {
2022-07-06 13:28:28 +00:00
Op : eacl . OperationGet ,
Action : eacl . ActionAllow ,
2021-07-21 11:59:46 +00:00
} } } ,
{
2021-08-30 07:55:42 +00:00
resourceInfo : resourceInfo {
Bucket : "bucketName" ,
Object : "objectName" ,
2022-05-25 17:25:43 +00:00
Version : id . EncodeToString ( ) ,
2021-08-30 07:55:42 +00:00
} ,
2021-07-21 11:59:46 +00:00
Operations : [ ] * astOperation { {
Users : [ ] string {
hex . EncodeToString ( key . PublicKey ( ) . Bytes ( ) ) ,
hex . EncodeToString ( key2 . PublicKey ( ) . Bytes ( ) ) ,
} ,
2022-07-06 13:28:28 +00:00
Op : eacl . OperationPut ,
Action : eacl . ActionDeny ,
2021-07-21 11:59:46 +00:00
} } } ,
} ,
}
2021-08-30 07:55:42 +00:00
actualAst := tableToAst ( table , expectedAst . Resources [ 0 ] . Bucket )
2021-07-21 11:59:46 +00:00
2021-08-30 07:55:42 +00:00
if actualAst . Resources [ 0 ] . Name ( ) == expectedAst . Resources [ 0 ] . Name ( ) {
2021-07-21 11:59:46 +00:00
require . Equal ( t , expectedAst , actualAst )
} else {
require . Equal ( t , len ( expectedAst . Resources ) , len ( actualAst . Resources ) )
require . Equal ( t , expectedAst . Resources [ 0 ] , actualAst . Resources [ 1 ] )
require . Equal ( t , expectedAst . Resources [ 1 ] , actualAst . Resources [ 0 ] )
}
}
func TestPolicyToAst ( t * testing . T ) {
key , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
policy := & bucketPolicy {
Statement : [ ] statement {
{
Effect : "Allow" ,
Principal : principal { AWS : allUsersWildcard } ,
Action : [ ] string { "s3:PutObject" } ,
Resource : [ ] string { "arn:aws:s3:::bucketName" } ,
} ,
{
Effect : "Deny" ,
Principal : principal {
CanonicalUser : hex . EncodeToString ( key . PublicKey ( ) . Bytes ( ) ) ,
} ,
Action : [ ] string { "s3:GetObject" } ,
Resource : [ ] string { "arn:aws:s3:::bucketName/object" } ,
} } ,
}
2021-08-30 07:55:42 +00:00
policy . Bucket = "bucketName"
2021-07-21 11:59:46 +00:00
expectedAst := & ast {
Resources : [ ] * astResource {
{
2021-08-30 07:55:42 +00:00
resourceInfo : resourceInfo {
Bucket : "bucketName" ,
} ,
2021-07-21 11:59:46 +00:00
Operations : [ ] * astOperation { {
2022-07-06 13:28:28 +00:00
Op : eacl . OperationPut ,
Action : eacl . ActionAllow ,
2021-07-21 11:59:46 +00:00
} } ,
} ,
{
2021-08-30 07:55:42 +00:00
resourceInfo : resourceInfo {
Bucket : "bucketName" ,
Object : "object" ,
} ,
2022-07-06 12:39:15 +00:00
Operations : getReadOps ( key , false , eacl . ActionDeny ) ,
2021-07-21 11:59:46 +00:00
} ,
} ,
}
actualAst , err := policyToAst ( policy )
require . NoError ( t , err )
2021-08-30 07:55:42 +00:00
if actualAst . Resources [ 0 ] . Name ( ) == expectedAst . Resources [ 0 ] . Name ( ) {
2021-07-21 11:59:46 +00:00
require . Equal ( t , expectedAst , actualAst )
} else {
require . Equal ( t , len ( expectedAst . Resources ) , len ( actualAst . Resources ) )
require . Equal ( t , expectedAst . Resources [ 0 ] , actualAst . Resources [ 1 ] )
require . Equal ( t , expectedAst . Resources [ 1 ] , actualAst . Resources [ 0 ] )
}
}
2022-07-06 12:39:15 +00:00
func getReadOps ( key * keys . PrivateKey , groupGrantee bool , action eacl . Action ) [ ] * astOperation {
2022-07-06 13:28:28 +00:00
var (
result [ ] * astOperation
users [ ] string
)
if ! groupGrantee {
users = append ( users , hex . EncodeToString ( key . PublicKey ( ) . Bytes ( ) ) )
}
2021-07-21 11:59:46 +00:00
for _ , op := range readOps {
result = append ( result , & astOperation {
2022-07-06 13:28:28 +00:00
Users : users ,
Op : op ,
Action : action ,
2021-07-21 11:59:46 +00:00
} )
}
return result
}
func TestMergeAstUnModified ( t * testing . T ) {
key , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
child := & ast {
Resources : [ ] * astResource {
{
2021-08-30 07:55:42 +00:00
resourceInfo : resourceInfo {
Bucket : "bucket" ,
Object : "objectName" ,
} ,
2021-07-21 11:59:46 +00:00
Operations : [ ] * astOperation { {
2022-07-06 13:28:28 +00:00
Users : [ ] string { hex . EncodeToString ( key . PublicKey ( ) . Bytes ( ) ) } ,
Op : eacl . OperationPut ,
Action : eacl . ActionDeny ,
2021-07-21 11:59:46 +00:00
} } ,
} ,
} ,
}
parent := & ast {
Resources : [ ] * astResource {
{
2021-08-30 07:55:42 +00:00
resourceInfo : resourceInfo {
Bucket : "bucket" ,
} ,
2021-07-21 11:59:46 +00:00
Operations : [ ] * astOperation { {
2022-07-06 13:28:28 +00:00
Op : eacl . OperationGet ,
Action : eacl . ActionAllow ,
2021-07-21 11:59:46 +00:00
} } ,
} ,
child . Resources [ 0 ] ,
} ,
}
result , updated := mergeAst ( parent , child )
require . False ( t , updated )
require . Equal ( t , parent , result )
}
func TestMergeAstModified ( t * testing . T ) {
child := & ast {
Resources : [ ] * astResource {
{
2021-08-30 07:55:42 +00:00
resourceInfo : resourceInfo {
Bucket : "bucket" ,
Object : "objectName" ,
} ,
2021-07-21 11:59:46 +00:00
Operations : [ ] * astOperation { {
2022-07-06 13:28:28 +00:00
Op : eacl . OperationPut ,
Action : eacl . ActionDeny ,
2021-07-21 11:59:46 +00:00
} , {
2022-07-06 13:28:28 +00:00
Users : [ ] string { "user2" } ,
Op : eacl . OperationGet ,
Action : eacl . ActionDeny ,
2021-07-21 11:59:46 +00:00
} } ,
} ,
} ,
}
parent := & ast {
Resources : [ ] * astResource {
{
2021-08-30 07:55:42 +00:00
resourceInfo : resourceInfo {
Bucket : "bucket" ,
Object : "objectName" ,
} ,
2021-07-21 11:59:46 +00:00
Operations : [ ] * astOperation { {
2022-07-06 13:28:28 +00:00
Users : [ ] string { "user1" } ,
Op : eacl . OperationGet ,
Action : eacl . ActionDeny ,
2021-07-21 11:59:46 +00:00
} } ,
} ,
} ,
}
expected := & ast {
Resources : [ ] * astResource {
{
2021-08-30 07:55:42 +00:00
resourceInfo : resourceInfo {
Bucket : "bucket" ,
Object : "objectName" ,
} ,
2021-07-21 11:59:46 +00:00
Operations : [ ] * astOperation {
child . Resources [ 0 ] . Operations [ 0 ] ,
{
2022-07-06 13:28:28 +00:00
Users : [ ] string { "user1" , "user2" } ,
Op : eacl . OperationGet ,
Action : eacl . ActionDeny ,
2021-07-21 11:59:46 +00:00
} ,
} ,
} ,
} ,
}
actual , updated := mergeAst ( parent , child )
require . True ( t , updated )
require . Equal ( t , expected , actual )
}
2022-07-17 03:33:47 +00:00
func TestMergeAppended ( t * testing . T ) {
key , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
users := [ ] string { hex . EncodeToString ( key . PublicKey ( ) . Bytes ( ) ) }
parent := & ast {
Resources : [ ] * astResource {
{
resourceInfo : resourceInfo {
Bucket : "bucket" ,
} ,
Operations : [ ] * astOperation {
{
Users : users ,
Op : eacl . OperationGet ,
Action : eacl . ActionAllow ,
} ,
{
Users : users ,
Op : eacl . OperationPut ,
Action : eacl . ActionAllow ,
} ,
{
Users : users ,
Op : eacl . OperationDelete ,
Action : eacl . ActionAllow ,
} ,
{
Op : eacl . OperationGet ,
Action : eacl . ActionDeny ,
} ,
{
Op : eacl . OperationPut ,
Action : eacl . ActionDeny ,
} ,
{
Op : eacl . OperationDelete ,
Action : eacl . ActionDeny ,
} ,
} ,
} ,
} ,
}
child := & ast {
Resources : [ ] * astResource {
{
resourceInfo : resourceInfo {
Bucket : "bucket" ,
Object : "objectName" ,
} ,
Operations : [ ] * astOperation {
{
Users : users ,
Op : eacl . OperationGet ,
Action : eacl . ActionAllow ,
} ,
{
Users : users ,
Op : eacl . OperationPut ,
Action : eacl . ActionAllow ,
} ,
{
Users : users ,
Op : eacl . OperationDelete ,
Action : eacl . ActionAllow ,
} ,
{
Op : eacl . OperationGet ,
Action : eacl . ActionAllow ,
} ,
{
Op : eacl . OperationPut ,
Action : eacl . ActionAllow ,
} ,
{
Op : eacl . OperationDelete ,
Action : eacl . ActionAllow ,
} ,
} ,
} ,
} ,
}
expected := & ast {
Resources : [ ] * astResource {
{
resourceInfo : resourceInfo {
Bucket : "bucket" ,
} ,
Operations : [ ] * astOperation {
{
Users : users ,
Op : eacl . OperationGet ,
Action : eacl . ActionAllow ,
} ,
{
Users : users ,
Op : eacl . OperationPut ,
Action : eacl . ActionAllow ,
} ,
{
Users : users ,
Op : eacl . OperationDelete ,
Action : eacl . ActionAllow ,
} ,
{
Op : eacl . OperationGet ,
Action : eacl . ActionDeny ,
} ,
{
Op : eacl . OperationPut ,
Action : eacl . ActionDeny ,
} ,
{
Op : eacl . OperationDelete ,
Action : eacl . ActionDeny ,
} ,
} ,
} ,
{
resourceInfo : resourceInfo {
Bucket : "bucket" ,
Object : "objectName" ,
} ,
Operations : [ ] * astOperation {
{
Users : users ,
Op : eacl . OperationGet ,
Action : eacl . ActionAllow ,
} ,
{
Users : users ,
Op : eacl . OperationPut ,
Action : eacl . ActionAllow ,
} ,
{
Users : users ,
Op : eacl . OperationDelete ,
Action : eacl . ActionAllow ,
} ,
{
Op : eacl . OperationGet ,
Action : eacl . ActionAllow ,
} ,
{
Op : eacl . OperationPut ,
Action : eacl . ActionAllow ,
} ,
{
Op : eacl . OperationDelete ,
Action : eacl . ActionAllow ,
} ,
} ,
} ,
} ,
}
actual , updated := mergeAst ( parent , child )
require . True ( t , updated )
require . Equal ( t , expected , actual )
}
func TestOrder ( t * testing . T ) {
key , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
users := [ ] string { hex . EncodeToString ( key . PublicKey ( ) . Bytes ( ) ) }
targetUser := eacl . NewTarget ( )
targetUser . SetBinaryKeys ( [ ] [ ] byte { key . PublicKey ( ) . Bytes ( ) } )
targetOther := eacl . NewTarget ( )
targetOther . SetRole ( eacl . RoleOthers )
bucketName := "bucket"
objectName := "objectName"
expectedAst := & ast {
Resources : [ ] * astResource {
{
resourceInfo : resourceInfo {
Bucket : bucketName ,
} ,
Operations : [ ] * astOperation {
{
Users : users ,
Op : eacl . OperationGet ,
Action : eacl . ActionAllow ,
} ,
{
Op : eacl . OperationGet ,
Action : eacl . ActionDeny ,
} ,
} ,
} ,
{
resourceInfo : resourceInfo {
Bucket : bucketName ,
Object : objectName ,
} ,
Operations : [ ] * astOperation {
{
Users : users ,
2022-07-15 14:35:11 +00:00
Op : eacl . OperationPut ,
2022-07-17 03:33:47 +00:00
Action : eacl . ActionAllow ,
} ,
{
2022-07-15 14:35:11 +00:00
Op : eacl . OperationPut ,
2022-07-17 03:33:47 +00:00
Action : eacl . ActionDeny ,
} ,
} ,
} ,
} ,
}
2022-07-15 14:35:11 +00:00
bucketServiceRec := & ServiceRecord { Resource : expectedAst . Resources [ 0 ] . Name ( ) , GroupRecordsLength : 2 }
bucketUsersGetRec := eacl . NewRecord ( )
bucketUsersGetRec . SetOperation ( eacl . OperationGet )
bucketUsersGetRec . SetAction ( eacl . ActionAllow )
bucketUsersGetRec . SetTargets ( * targetUser )
bucketOtherGetRec := eacl . NewRecord ( )
bucketOtherGetRec . SetOperation ( eacl . OperationGet )
bucketOtherGetRec . SetAction ( eacl . ActionDeny )
bucketOtherGetRec . SetTargets ( * targetOther )
objectServiceRec := & ServiceRecord { Resource : expectedAst . Resources [ 1 ] . Name ( ) , GroupRecordsLength : 2 }
objectUsersPutRec := eacl . NewRecord ( )
objectUsersPutRec . SetOperation ( eacl . OperationPut )
objectUsersPutRec . SetAction ( eacl . ActionAllow )
2022-09-07 06:59:24 +00:00
objectUsersPutRec . AddObjectAttributeFilter ( eacl . MatchStringEqual , object . AttributeFilePath , objectName )
2022-07-15 14:35:11 +00:00
objectUsersPutRec . SetTargets ( * targetUser )
objectOtherPutRec := eacl . NewRecord ( )
objectOtherPutRec . SetOperation ( eacl . OperationPut )
objectOtherPutRec . SetAction ( eacl . ActionDeny )
2022-09-07 06:59:24 +00:00
objectOtherPutRec . AddObjectAttributeFilter ( eacl . MatchStringEqual , object . AttributeFilePath , objectName )
2022-07-15 14:35:11 +00:00
objectOtherPutRec . SetTargets ( * targetOther )
2022-07-17 03:33:47 +00:00
expectedEacl := eacl . NewTable ( )
2022-07-15 14:35:11 +00:00
expectedEacl . AddRecord ( objectServiceRec . ToEACLRecord ( ) )
expectedEacl . AddRecord ( objectOtherPutRec )
expectedEacl . AddRecord ( objectUsersPutRec )
expectedEacl . AddRecord ( bucketServiceRec . ToEACLRecord ( ) )
expectedEacl . AddRecord ( bucketOtherGetRec )
expectedEacl . AddRecord ( bucketUsersGetRec )
2022-07-17 03:33:47 +00:00
t . Run ( "astToTable order and vice versa" , func ( t * testing . T ) {
actualEacl , err := astToTable ( expectedAst )
require . NoError ( t , err )
require . Equal ( t , expectedEacl , actualEacl )
actualAst := tableToAst ( actualEacl , bucketName )
require . Equal ( t , expectedAst , actualAst )
} )
t . Run ( "tableToAst order and vice versa" , func ( t * testing . T ) {
actualAst := tableToAst ( expectedEacl , bucketName )
require . Equal ( t , expectedAst , actualAst )
actualEacl , err := astToTable ( actualAst )
require . NoError ( t , err )
require . Equal ( t , expectedEacl , actualEacl )
} )
t . Run ( "append a resource" , func ( t * testing . T ) {
childName := "child"
child := & ast { Resources : [ ] * astResource { {
resourceInfo : resourceInfo {
Bucket : bucketName ,
Object : childName ,
} ,
Operations : [ ] * astOperation { { Op : eacl . OperationDelete , Action : eacl . ActionDeny } } } } ,
}
childRecord := eacl . NewRecord ( )
childRecord . SetOperation ( eacl . OperationDelete )
childRecord . SetAction ( eacl . ActionDeny )
childRecord . SetTargets ( * targetOther )
2022-09-07 06:59:24 +00:00
childRecord . AddObjectAttributeFilter ( eacl . MatchStringEqual , object . AttributeFilePath , childName )
2022-07-17 03:33:47 +00:00
mergedAst , updated := mergeAst ( expectedAst , child )
require . True ( t , updated )
mergedEacl , err := astToTable ( mergedAst )
require . NoError ( t , err )
2022-07-15 14:35:11 +00:00
require . Equal ( t , * childRecord , mergedEacl . Records ( ) [ 1 ] )
2022-07-17 03:33:47 +00:00
} )
}
2021-07-21 11:59:46 +00:00
func TestMergeAstModifiedConflict ( t * testing . T ) {
child := & ast {
Resources : [ ] * astResource {
{
2021-08-30 07:55:42 +00:00
resourceInfo : resourceInfo {
Bucket : "bucket" ,
Object : "objectName" ,
} ,
2021-07-21 11:59:46 +00:00
Operations : [ ] * astOperation { {
2022-07-06 13:28:28 +00:00
Users : [ ] string { "user1" } ,
Op : eacl . OperationPut ,
Action : eacl . ActionDeny ,
2021-07-21 11:59:46 +00:00
} , {
2022-07-06 13:28:28 +00:00
Users : [ ] string { "user3" } ,
Op : eacl . OperationGet ,
Action : eacl . ActionAllow ,
2021-07-21 11:59:46 +00:00
} } ,
} ,
} ,
}
parent := & ast {
Resources : [ ] * astResource {
{
2021-08-30 07:55:42 +00:00
resourceInfo : resourceInfo {
Bucket : "bucket" ,
Object : "objectName" ,
} ,
2021-07-21 11:59:46 +00:00
Operations : [ ] * astOperation { {
2022-07-06 13:28:28 +00:00
Users : [ ] string { "user1" } ,
Op : eacl . OperationPut ,
Action : eacl . ActionAllow ,
2021-07-21 11:59:46 +00:00
} , {
2022-07-06 13:28:28 +00:00
Users : [ ] string { "user2" } ,
Op : eacl . OperationPut ,
Action : eacl . ActionDeny ,
2021-07-21 11:59:46 +00:00
} , {
2022-07-06 13:28:28 +00:00
Users : [ ] string { "user3" } ,
Op : eacl . OperationGet ,
Action : eacl . ActionDeny ,
2021-07-21 11:59:46 +00:00
} } ,
} ,
} ,
}
expected := & ast {
Resources : [ ] * astResource {
{
2021-08-30 07:55:42 +00:00
resourceInfo : resourceInfo {
Bucket : "bucket" ,
Object : "objectName" ,
} ,
2021-07-21 11:59:46 +00:00
Operations : [ ] * astOperation {
{
2022-07-06 13:28:28 +00:00
Users : [ ] string { "user2" , "user1" } ,
Op : eacl . OperationPut ,
Action : eacl . ActionDeny ,
2021-07-21 11:59:46 +00:00
} , {
2022-07-06 13:28:28 +00:00
Users : [ ] string { "user3" } ,
Op : eacl . OperationGet ,
Action : eacl . ActionAllow ,
2021-07-21 11:59:46 +00:00
} ,
} ,
} ,
} ,
}
actual , updated := mergeAst ( parent , child )
require . True ( t , updated )
require . Equal ( t , expected , actual )
}
func TestAstToTable ( t * testing . T ) {
key , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
ast := & ast {
Resources : [ ] * astResource {
{
2021-08-30 07:55:42 +00:00
resourceInfo : resourceInfo {
Bucket : "bucketName" ,
} ,
2021-07-21 11:59:46 +00:00
Operations : [ ] * astOperation { {
2022-07-06 13:28:28 +00:00
Users : [ ] string { hex . EncodeToString ( key . PublicKey ( ) . Bytes ( ) ) } ,
Op : eacl . OperationPut ,
Action : eacl . ActionAllow ,
2021-07-21 11:59:46 +00:00
} } ,
} ,
{
2021-08-30 07:55:42 +00:00
resourceInfo : resourceInfo {
Bucket : "bucketName" ,
Object : "objectName" ,
} ,
2021-07-21 11:59:46 +00:00
Operations : [ ] * astOperation { {
2022-07-06 13:28:28 +00:00
Op : eacl . OperationGet ,
Action : eacl . ActionDeny ,
2021-07-21 11:59:46 +00:00
} } ,
} ,
} ,
}
expectedTable := eacl . NewTable ( )
2022-07-15 14:35:11 +00:00
serviceRec1 := & ServiceRecord { Resource : ast . Resources [ 0 ] . Name ( ) , GroupRecordsLength : 1 }
record1 := eacl . NewRecord ( )
record1 . SetAction ( eacl . ActionAllow )
record1 . SetOperation ( eacl . OperationPut )
// Unknown role is used, because it is ignored when keys are set
eacl . AddFormedTarget ( record1 , eacl . RoleUnknown , * ( * ecdsa . PublicKey ) ( key . PublicKey ( ) ) )
2022-07-17 03:33:47 +00:00
2022-07-15 14:35:11 +00:00
serviceRec2 := & ServiceRecord { Resource : ast . Resources [ 1 ] . Name ( ) , GroupRecordsLength : 1 }
2021-07-21 11:59:46 +00:00
record2 := eacl . NewRecord ( )
2022-07-15 14:35:11 +00:00
record2 . SetAction ( eacl . ActionDeny )
record2 . SetOperation ( eacl . OperationGet )
eacl . AddFormedTarget ( record2 , eacl . RoleOthers )
2022-09-07 06:59:24 +00:00
record2 . AddObjectAttributeFilter ( eacl . MatchStringEqual , object . AttributeFilePath , "objectName" )
2022-07-15 14:35:11 +00:00
expectedTable . AddRecord ( serviceRec2 . ToEACLRecord ( ) )
2021-07-21 11:59:46 +00:00
expectedTable . AddRecord ( record2 )
2022-07-15 14:35:11 +00:00
expectedTable . AddRecord ( serviceRec1 . ToEACLRecord ( ) )
expectedTable . AddRecord ( record1 )
2021-07-21 11:59:46 +00:00
2021-08-30 07:55:42 +00:00
actualTable , err := astToTable ( ast )
2021-07-21 11:59:46 +00:00
require . NoError ( t , err )
require . Equal ( t , expectedTable , actualTable )
}
func TestRemoveUsers ( t * testing . T ) {
resource := & astResource {
2021-08-30 07:55:42 +00:00
resourceInfo : resourceInfo {
Bucket : "bucket" ,
} ,
2021-07-21 11:59:46 +00:00
Operations : [ ] * astOperation { {
2022-07-06 13:28:28 +00:00
Users : [ ] string { "user1" , "user3" , "user4" } ,
Op : eacl . OperationPut ,
Action : eacl . ActionAllow ,
} ,
{
Users : [ ] string { "user5" } ,
Op : eacl . OperationGet ,
Action : eacl . ActionDeny ,
} ,
} ,
2021-07-21 11:59:46 +00:00
}
2022-07-06 13:28:28 +00:00
op1 := & astOperation {
Op : eacl . OperationPut ,
Action : eacl . ActionAllow ,
}
op2 := & astOperation {
Op : eacl . OperationGet ,
Action : eacl . ActionDeny ,
2021-07-21 11:59:46 +00:00
}
2022-07-06 13:28:28 +00:00
removeUsers ( resource , op1 , [ ] string { "user1" , "user2" , "user4" } ) // modify astOperation
removeUsers ( resource , op2 , [ ] string { "user5" } ) // remove astOperation
2021-07-21 11:59:46 +00:00
require . Equal ( t , len ( resource . Operations ) , 1 )
2022-07-06 13:01:47 +00:00
require . Equal ( t , [ ] string { "user3" } , resource . Operations [ 0 ] . Users )
2021-07-21 11:59:46 +00:00
}
func TestBucketAclToPolicy ( t * testing . T ) {
key , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
key2 , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
id := hex . EncodeToString ( key . PublicKey ( ) . Bytes ( ) )
id2 := hex . EncodeToString ( key2 . PublicKey ( ) . Bytes ( ) )
acl := & AccessControlPolicy {
Owner : Owner {
ID : id ,
DisplayName : "user1" ,
} ,
AccessControlList : [ ] * Grant { {
Grantee : & Grantee {
URI : allUsersGroup ,
Type : acpGroup ,
} ,
Permission : aclRead ,
} , {
Grantee : & Grantee {
ID : id2 ,
Type : acpCanonicalUser ,
} ,
Permission : aclWrite ,
} } ,
2021-08-30 07:55:42 +00:00
}
resInfo := & resourceInfo {
Bucket : "bucketName" ,
2021-07-21 11:59:46 +00:00
}
expectedPolicy := & bucketPolicy {
2022-07-12 10:39:25 +00:00
Bucket : resInfo . Bucket ,
2021-07-21 11:59:46 +00:00
Statement : [ ] statement {
{
Effect : "Allow" ,
Principal : principal {
CanonicalUser : id ,
} ,
Action : [ ] string { "s3:ListBucket" , "s3:ListBucketVersions" , "s3:ListBucketMultipartUploads" , "s3:PutObject" , "s3:DeleteObject" } ,
2021-08-30 07:55:42 +00:00
Resource : [ ] string { arnAwsPrefix + resInfo . Name ( ) } ,
2022-07-12 10:39:25 +00:00
} ,
{
2021-07-21 11:59:46 +00:00
Effect : "Allow" ,
Principal : principal { AWS : allUsersWildcard } ,
Action : [ ] string { "s3:ListBucket" , "s3:ListBucketVersions" , "s3:ListBucketMultipartUploads" } ,
2021-08-30 07:55:42 +00:00
Resource : [ ] string { arnAwsPrefix + resInfo . Name ( ) } ,
2022-07-12 10:39:25 +00:00
} ,
{
2021-07-21 11:59:46 +00:00
Effect : "Allow" ,
Principal : principal {
CanonicalUser : id2 ,
} ,
Action : [ ] string { "s3:PutObject" , "s3:DeleteObject" } ,
2021-08-30 07:55:42 +00:00
Resource : [ ] string { arnAwsPrefix + resInfo . Name ( ) } ,
2021-07-21 11:59:46 +00:00
} ,
} ,
}
2021-08-30 07:55:42 +00:00
actualPolicy , err := aclToPolicy ( acl , resInfo )
2021-07-21 11:59:46 +00:00
require . NoError ( t , err )
require . Equal ( t , expectedPolicy , actualPolicy )
}
func TestObjectAclToPolicy ( t * testing . T ) {
key , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
key2 , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
id := hex . EncodeToString ( key . PublicKey ( ) . Bytes ( ) )
id2 := hex . EncodeToString ( key2 . PublicKey ( ) . Bytes ( ) )
acl := & AccessControlPolicy {
Owner : Owner {
ID : id ,
DisplayName : "user1" ,
} ,
AccessControlList : [ ] * Grant { {
Grantee : & Grantee {
ID : id ,
Type : acpCanonicalUser ,
} ,
Permission : aclFullControl ,
} , {
Grantee : & Grantee {
ID : id2 ,
Type : acpCanonicalUser ,
} ,
Permission : aclFullControl ,
} , {
Grantee : & Grantee {
URI : allUsersGroup ,
Type : acpGroup ,
} ,
Permission : aclRead ,
} } ,
2021-08-30 07:55:42 +00:00
}
resInfo := & resourceInfo {
Bucket : "bucketName" ,
Object : "object" ,
2021-07-21 11:59:46 +00:00
}
expectedPolicy := & bucketPolicy {
2022-07-12 10:39:25 +00:00
Bucket : resInfo . Bucket ,
2021-07-21 11:59:46 +00:00
Statement : [ ] statement {
{
Effect : "Allow" ,
Principal : principal {
CanonicalUser : id ,
} ,
Action : [ ] string { "s3:GetObject" , "s3:GetObjectVersion" } ,
2021-08-30 07:55:42 +00:00
Resource : [ ] string { arnAwsPrefix + resInfo . Name ( ) } ,
2021-07-21 11:59:46 +00:00
} ,
{
Effect : "Allow" ,
Principal : principal {
CanonicalUser : id2 ,
} ,
Action : [ ] string { "s3:GetObject" , "s3:GetObjectVersion" } ,
2021-08-30 07:55:42 +00:00
Resource : [ ] string { arnAwsPrefix + resInfo . Name ( ) } ,
2022-07-12 10:39:25 +00:00
} ,
{
2021-07-21 11:59:46 +00:00
Effect : "Allow" ,
Principal : principal { AWS : allUsersWildcard } ,
Action : [ ] string { "s3:GetObject" , "s3:GetObjectVersion" } ,
2021-08-30 07:55:42 +00:00
Resource : [ ] string { arnAwsPrefix + resInfo . Name ( ) } ,
2021-07-21 11:59:46 +00:00
} ,
} ,
}
2021-08-30 07:55:42 +00:00
actualPolicy , err := aclToPolicy ( acl , resInfo )
2021-07-21 11:59:46 +00:00
require . NoError ( t , err )
require . Equal ( t , expectedPolicy , actualPolicy )
}
2022-07-12 10:39:25 +00:00
func TestObjectWithVersionAclToTable ( t * testing . T ) {
key , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
id := hex . EncodeToString ( key . PublicKey ( ) . Bytes ( ) )
acl := & AccessControlPolicy {
Owner : Owner {
ID : id ,
DisplayName : "user1" ,
} ,
AccessControlList : [ ] * Grant { {
Grantee : & Grantee {
ID : id ,
Type : acpCanonicalUser ,
} ,
Permission : aclFullControl ,
} } ,
}
resInfoObject := & resourceInfo {
Bucket : "bucketName" ,
Object : "object" ,
}
2022-07-21 09:55:33 +00:00
expectedTable := allowedTableForPrivateObject ( t , key , resInfoObject )
2022-07-12 10:39:25 +00:00
actualTable := tableFromACL ( t , acl , resInfoObject )
checkTables ( t , expectedTable , actualTable )
resInfoObjectVersion := & resourceInfo {
Bucket : "bucketName" ,
Object : "objectVersion" ,
Version : "Gfrct4Afhio8pCGCCKVNTf1kyexQjMBeaUfvDtQCkAvg" ,
}
2022-07-21 09:55:33 +00:00
expectedTable = allowedTableForPrivateObject ( t , key , resInfoObjectVersion )
2022-07-12 10:39:25 +00:00
actualTable = tableFromACL ( t , acl , resInfoObjectVersion )
checkTables ( t , expectedTable , actualTable )
}
2022-07-21 09:55:33 +00:00
func allowedTableForPrivateObject ( t * testing . T , key * keys . PrivateKey , resInfo * resourceInfo ) * eacl . Table {
2022-07-12 10:39:25 +00:00
var isVersion bool
var objID oid . ID
if resInfo . Version != "" {
isVersion = true
err := objID . DecodeString ( resInfo . Version )
require . NoError ( t , err )
}
expectedTable := eacl . NewTable ( )
2022-07-21 09:55:33 +00:00
serviceRec := & ServiceRecord { Resource : resInfo . Name ( ) , GroupRecordsLength : len ( readOps ) * 2 }
2022-07-15 14:35:11 +00:00
expectedTable . AddRecord ( serviceRec . ToEACLRecord ( ) )
for i := len ( readOps ) - 1 ; i >= 0 ; i -- {
op := readOps [ i ]
2022-07-12 10:39:25 +00:00
record := getAllowRecord ( op , key . PublicKey ( ) )
if isVersion {
record . AddObjectIDFilter ( eacl . MatchStringEqual , objID )
} else {
2022-09-07 06:59:24 +00:00
record . AddObjectAttributeFilter ( eacl . MatchStringEqual , object . AttributeFilePath , resInfo . Object )
2022-07-12 10:39:25 +00:00
}
expectedTable . AddRecord ( record )
}
2022-07-21 09:55:33 +00:00
for i := len ( readOps ) - 1 ; i >= 0 ; i -- {
op := readOps [ i ]
record := getOthersRecord ( op , eacl . ActionDeny )
if isVersion {
record . AddObjectIDFilter ( eacl . MatchStringEqual , objID )
} else {
2022-09-07 06:59:24 +00:00
record . AddObjectAttributeFilter ( eacl . MatchStringEqual , object . AttributeFilePath , resInfo . Object )
2022-07-21 09:55:33 +00:00
}
expectedTable . AddRecord ( record )
}
2022-07-12 10:39:25 +00:00
return expectedTable
}
func tableFromACL ( t * testing . T , acl * AccessControlPolicy , resInfo * resourceInfo ) * eacl . Table {
actualPolicy , err := aclToPolicy ( acl , resInfo )
require . NoError ( t , err )
actualAst , err := policyToAst ( actualPolicy )
require . NoError ( t , err )
actualTable , err := astToTable ( actualAst )
require . NoError ( t , err )
return actualTable
}
func checkTables ( t * testing . T , expectedTable , actualTable * eacl . Table ) {
require . Equal ( t , len ( expectedTable . Records ( ) ) , len ( actualTable . Records ( ) ) , "different number of records" )
for i , record := range expectedTable . Records ( ) {
actRecord := actualTable . Records ( ) [ i ]
require . Equal ( t , len ( record . Targets ( ) ) , len ( actRecord . Targets ( ) ) , "different number of targets" )
for j , target := range record . Targets ( ) {
actTarget := actRecord . Targets ( ) [ j ]
expected := fmt . Sprintf ( "%s %v" , target . Role ( ) . String ( ) , target . BinaryKeys ( ) )
actual := fmt . Sprintf ( "%s %v" , actTarget . Role ( ) . String ( ) , actTarget . BinaryKeys ( ) )
require . Equalf ( t , target , actTarget , "want: '%s'\ngot: '%s'" , expected , actual )
}
require . Equal ( t , len ( record . Filters ( ) ) , len ( actRecord . Filters ( ) ) , "different number of filters" )
for j , filter := range record . Filters ( ) {
actFilter := actRecord . Filters ( ) [ j ]
expected := fmt . Sprintf ( "%s:%s %s %s" , filter . From ( ) . String ( ) , filter . Key ( ) , filter . Matcher ( ) . String ( ) , filter . Value ( ) )
actual := fmt . Sprintf ( "%s:%s %s %s" , actFilter . From ( ) . String ( ) , actFilter . Key ( ) , actFilter . Matcher ( ) . String ( ) , actFilter . Value ( ) )
require . Equalf ( t , filter , actFilter , "want: '%s'\ngot: '%s'" , expected , actual )
}
require . Equal ( t , record . Action ( ) . String ( ) , actRecord . Action ( ) . String ( ) )
require . Equal ( t , record . Operation ( ) . String ( ) , actRecord . Operation ( ) . String ( ) )
}
}
2021-07-21 11:59:46 +00:00
func TestParseCannedACLHeaders ( t * testing . T ) {
key , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
id := hex . EncodeToString ( key . PublicKey ( ) . Bytes ( ) )
address := key . PublicKey ( ) . Address ( )
req := & http . Request {
Header : map [ string ] [ ] string {
api . AmzACL : { basicACLReadOnly } ,
} ,
}
expectedACL := & AccessControlPolicy {
Owner : Owner {
ID : id ,
DisplayName : address ,
} ,
AccessControlList : [ ] * Grant { {
Grantee : & Grantee {
ID : id ,
DisplayName : address ,
Type : acpCanonicalUser ,
} ,
Permission : aclFullControl ,
} , {
Grantee : & Grantee {
URI : allUsersGroup ,
Type : acpGroup ,
} ,
Permission : aclRead ,
} } ,
}
2021-10-19 15:08:07 +00:00
actualACL , err := parseACLHeaders ( req . Header , key . PublicKey ( ) )
2021-07-21 11:59:46 +00:00
require . NoError ( t , err )
require . Equal ( t , expectedACL , actualACL )
}
func TestParseACLHeaders ( t * testing . T ) {
key , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
id := hex . EncodeToString ( key . PublicKey ( ) . Bytes ( ) )
address := key . PublicKey ( ) . Address ( )
req := & http . Request {
Header : map [ string ] [ ] string {
api . AmzGrantFullControl : { "id=\"user1\"" } ,
api . AmzGrantRead : { "uri=\"" + allUsersGroup + "\", id=\"user2\"" } ,
api . AmzGrantWrite : { "id=\"user2\", id=\"user3\"" } ,
} ,
}
expectedACL := & AccessControlPolicy {
Owner : Owner {
ID : id ,
DisplayName : address ,
} ,
AccessControlList : [ ] * Grant { {
Grantee : & Grantee {
ID : id ,
DisplayName : address ,
Type : acpCanonicalUser ,
} ,
Permission : aclFullControl ,
} , {
Grantee : & Grantee {
ID : "user1" ,
Type : acpCanonicalUser ,
} ,
Permission : aclFullControl ,
} , {
Grantee : & Grantee {
URI : allUsersGroup ,
Type : acpGroup ,
} ,
Permission : aclRead ,
} , {
Grantee : & Grantee {
ID : "user2" ,
Type : acpCanonicalUser ,
} ,
Permission : aclRead ,
} , {
Grantee : & Grantee {
ID : "user2" ,
Type : acpCanonicalUser ,
} ,
Permission : aclWrite ,
} , {
Grantee : & Grantee {
ID : "user3" ,
Type : acpCanonicalUser ,
} ,
Permission : aclWrite ,
} } ,
}
2021-10-19 15:08:07 +00:00
actualACL , err := parseACLHeaders ( req . Header , key . PublicKey ( ) )
2021-07-21 11:59:46 +00:00
require . NoError ( t , err )
require . Equal ( t , expectedACL , actualACL )
}
func TestAddGranteeError ( t * testing . T ) {
headers := map [ string ] [ ] string {
api . AmzGrantFullControl : { "i=\"user1\"" } ,
api . AmzGrantRead : { "uri, id=\"user2\"" } ,
api . AmzGrantWrite : { "emailAddress=\"user2\"" } ,
"unknown header" : { "something" } ,
}
expectedList := [ ] * Grant { {
Permission : "predefined" ,
} }
actualList , err := addGrantees ( expectedList , headers , "unknown header1" )
require . NoError ( t , err )
require . Equal ( t , expectedList , actualList )
actualList , err = addGrantees ( expectedList , headers , "unknown header" )
require . Error ( t , err )
require . Nil ( t , actualList )
actualList , err = addGrantees ( expectedList , headers , api . AmzGrantFullControl )
require . Error ( t , err )
require . Nil ( t , actualList )
actualList , err = addGrantees ( expectedList , headers , api . AmzGrantRead )
require . Error ( t , err )
require . Nil ( t , actualList )
actualList , err = addGrantees ( expectedList , headers , api . AmzGrantWrite )
require . Error ( t , err )
require . Nil ( t , actualList )
}
func TestBucketAclToTable ( t * testing . T ) {
key , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
key2 , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
id := hex . EncodeToString ( key . PublicKey ( ) . Bytes ( ) )
id2 := hex . EncodeToString ( key2 . PublicKey ( ) . Bytes ( ) )
acl := & AccessControlPolicy {
Owner : Owner {
ID : id ,
DisplayName : "user1" ,
} ,
AccessControlList : [ ] * Grant { {
Grantee : & Grantee {
URI : allUsersGroup ,
Type : acpGroup ,
} ,
Permission : aclRead ,
} , {
Grantee : & Grantee {
ID : id2 ,
Type : acpCanonicalUser ,
} ,
Permission : aclWrite ,
} } ,
}
expectedTable := new ( eacl . Table )
for _ , op := range readOps {
expectedTable . AddRecord ( getOthersRecord ( op , eacl . ActionAllow ) )
}
for _ , op := range writeOps {
expectedTable . AddRecord ( getAllowRecord ( op , key2 . PublicKey ( ) ) )
}
for _ , op := range fullOps {
expectedTable . AddRecord ( getAllowRecord ( op , key . PublicKey ( ) ) )
}
for _ , op := range fullOps {
expectedTable . AddRecord ( getOthersRecord ( op , eacl . ActionDeny ) )
}
2021-08-30 07:55:42 +00:00
resInfo := & resourceInfo {
Bucket : "bucketName" ,
}
2021-07-21 11:59:46 +00:00
2021-08-30 07:55:42 +00:00
actualTable , err := bucketACLToTable ( acl , resInfo )
2021-07-21 11:59:46 +00:00
require . NoError ( t , err )
require . Equal ( t , expectedTable . Records ( ) , actualTable . Records ( ) )
}
2021-08-30 07:55:42 +00:00
func TestObjectAclToAst ( t * testing . T ) {
b := make ( [ ] byte , 32 )
_ , err := io . ReadFull ( rand . Reader , b )
require . NoError ( t , err )
2022-04-25 09:57:58 +00:00
var objID oid . ID
2022-02-08 16:54:04 +00:00
objID . SetSHA256 ( sha256 . Sum256 ( b ) )
2021-08-30 07:55:42 +00:00
key , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
key2 , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
id := hex . EncodeToString ( key . PublicKey ( ) . Bytes ( ) )
id2 := hex . EncodeToString ( key2 . PublicKey ( ) . Bytes ( ) )
acl := & AccessControlPolicy {
Owner : Owner {
ID : id ,
DisplayName : "user1" ,
} ,
AccessControlList : [ ] * Grant { {
Grantee : & Grantee {
ID : id ,
Type : acpCanonicalUser ,
} ,
Permission : aclFullControl ,
} , {
Grantee : & Grantee {
ID : id2 ,
Type : acpCanonicalUser ,
} ,
Permission : aclRead ,
} ,
} ,
}
resInfo := & resourceInfo {
Bucket : "bucketName" ,
Object : "object" ,
2022-05-25 17:25:43 +00:00
Version : objID . EncodeToString ( ) ,
2021-08-30 07:55:42 +00:00
}
var operations [ ] * astOperation
for _ , op := range readOps {
astOp := & astOperation { Users : [ ] string {
hex . EncodeToString ( key . PublicKey ( ) . Bytes ( ) ) ,
hex . EncodeToString ( key2 . PublicKey ( ) . Bytes ( ) ) ,
} ,
2022-07-06 13:28:28 +00:00
Op : op ,
Action : eacl . ActionAllow ,
2021-08-30 07:55:42 +00:00
}
operations = append ( operations , astOp )
}
expectedAst := & ast {
Resources : [ ] * astResource {
{
resourceInfo : * resInfo ,
Operations : operations ,
} ,
} ,
}
actualAst , err := aclToAst ( acl , resInfo )
require . NoError ( t , err )
require . Equal ( t , expectedAst , actualAst )
}
func TestBucketAclToAst ( t * testing . T ) {
b := make ( [ ] byte , 32 )
_ , err := io . ReadFull ( rand . Reader , b )
require . NoError ( t , err )
2022-04-25 09:57:58 +00:00
var objID oid . ID
2022-02-08 16:54:04 +00:00
objID . SetSHA256 ( sha256 . Sum256 ( b ) )
2021-08-30 07:55:42 +00:00
key , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
key2 , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
id := hex . EncodeToString ( key . PublicKey ( ) . Bytes ( ) )
id2 := hex . EncodeToString ( key2 . PublicKey ( ) . Bytes ( ) )
acl := & AccessControlPolicy {
Owner : Owner {
ID : id ,
DisplayName : "user1" ,
} ,
AccessControlList : [ ] * Grant {
{
Grantee : & Grantee {
ID : id2 ,
Type : acpCanonicalUser ,
} ,
Permission : aclWrite ,
} , {
Grantee : & Grantee {
URI : allUsersGroup ,
Type : acpGroup ,
} ,
Permission : aclRead ,
} ,
} ,
}
var operations [ ] * astOperation
for _ , op := range readOps {
astOp := & astOperation { Users : [ ] string {
hex . EncodeToString ( key . PublicKey ( ) . Bytes ( ) ) ,
} ,
2022-07-06 13:28:28 +00:00
Op : op ,
Action : eacl . ActionAllow ,
2021-08-30 07:55:42 +00:00
}
operations = append ( operations , astOp )
}
for _ , op := range writeOps {
astOp := & astOperation { Users : [ ] string {
hex . EncodeToString ( key . PublicKey ( ) . Bytes ( ) ) ,
hex . EncodeToString ( key2 . PublicKey ( ) . Bytes ( ) ) ,
} ,
2022-07-06 13:28:28 +00:00
Op : op ,
Action : eacl . ActionAllow ,
2021-08-30 07:55:42 +00:00
}
operations = append ( operations , astOp )
}
for _ , op := range readOps {
astOp := & astOperation {
2022-07-06 13:28:28 +00:00
Op : op ,
Action : eacl . ActionAllow ,
2021-08-30 07:55:42 +00:00
}
operations = append ( operations , astOp )
}
resInfo := & resourceInfo { Bucket : "bucketName" }
expectedAst := & ast {
Resources : [ ] * astResource {
{
resourceInfo : * resInfo ,
Operations : operations ,
} ,
} ,
}
actualAst , err := aclToAst ( acl , resInfo )
require . NoError ( t , err )
require . Equal ( t , expectedAst , actualAst )
}
2022-09-06 07:43:04 +00:00
func TestPutBucketACL ( t * testing . T ) {
tc := prepareHandlerContext ( t )
2024-02-14 14:04:35 +00:00
tc . config . aclEnabled = true
2022-09-06 07:43:04 +00:00
bktName := "bucket-for-acl"
2024-02-14 14:04:35 +00:00
info := createBucket ( tc , bktName )
2022-09-06 07:43:04 +00:00
header := map [ string ] string { api . AmzACL : "public-read" }
2024-02-14 14:04:35 +00:00
putBucketACL ( tc , bktName , info . Box , header )
2022-09-06 07:43:04 +00:00
header = map [ string ] string { api . AmzACL : "private" }
2024-02-14 14:04:35 +00:00
putBucketACL ( tc , bktName , info . Box , header )
checkLastRecords ( t , tc , info . BktInfo , eacl . ActionDeny )
2022-09-06 07:43:04 +00:00
}
2024-02-12 14:29:36 +00:00
func TestPutBucketAPE ( t * testing . T ) {
hc := prepareHandlerContext ( t )
bktName := "bucket-for-acl-ape"
info := createBucket ( hc , bktName )
2024-03-01 14:11:07 +00:00
_ , err := hc . tp . ContainerEACL ( hc . Context ( ) , layer . PrmContainerEACL { ContainerID : info . BktInfo . CID } )
2024-02-12 14:29:36 +00:00
require . ErrorContains ( t , err , "not found" )
2024-02-13 08:50:11 +00:00
chains , err := hc . h . ape . ( * apeMock ) . ListChains ( engine . NamespaceTarget ( "" ) )
2024-02-12 14:29:36 +00:00
require . NoError ( t , err )
require . Len ( t , chains , 2 )
}
2024-03-19 13:56:32 +00:00
func TestPutObjectACLErrorAPE ( t * testing . T ) {
2024-02-12 14:29:36 +00:00
hc := prepareHandlerContext ( t )
bktName , objName := "bucket-for-acl-ape" , "object"
info := createBucket ( hc , bktName )
2024-03-19 13:56:32 +00:00
putObjectWithHeadersAssertS3Error ( hc , bktName , objName , map [ string ] string { api . AmzACL : basicACLPublic } , s3errors . ErrAccessControlListNotSupported )
putObjectWithHeaders ( hc , bktName , objName , map [ string ] string { api . AmzACL : basicACLPrivate } ) // only `private` canned acl is allowed, that is actually ignored
putObjectWithHeaders ( hc , bktName , objName , nil )
2024-02-12 14:29:36 +00:00
2024-03-19 13:56:32 +00:00
aclBody := & AccessControlPolicy { }
2024-02-12 14:29:36 +00:00
putObjectACLAssertS3Error ( hc , bktName , objName , info . Box , nil , aclBody , s3errors . ErrAccessControlListNotSupported )
2024-03-19 13:56:32 +00:00
aclRes := getObjectACL ( hc , bktName , objName )
checkPrivateACL ( t , aclRes , info . Key . PublicKey ( ) )
}
func TestCreateObjectACLErrorAPE ( t * testing . T ) {
hc := prepareHandlerContext ( t )
bktName , objName , objNameCopy := "bucket-for-acl-ape" , "object" , "copy"
createBucket ( hc , bktName )
putObject ( hc , bktName , objName )
copyObject ( hc , bktName , objName , objNameCopy , CopyMeta { Headers : map [ string ] string { api . AmzACL : basicACLPublic } } , http . StatusBadRequest )
copyObject ( hc , bktName , objName , objNameCopy , CopyMeta { Headers : map [ string ] string { api . AmzACL : basicACLPrivate } } , http . StatusOK )
createMultipartUploadAssertS3Error ( hc , bktName , objName , map [ string ] string { api . AmzACL : basicACLPublic } , s3errors . ErrAccessControlListNotSupported )
createMultipartUpload ( hc , bktName , objName , map [ string ] string { api . AmzACL : basicACLPrivate } )
}
func TestPutObjectACLBackwardCompatibility ( t * testing . T ) {
hc := prepareHandlerContext ( t )
hc . config . aclEnabled = true
bktName , objName := "bucket-for-acl-ape" , "object"
info := createBucket ( hc , bktName )
putObjectWithHeadersBase ( hc , bktName , objName , map [ string ] string { api . AmzACL : basicACLPrivate } , info . Box , nil )
putObjectWithHeadersBase ( hc , bktName , objName , map [ string ] string { api . AmzACL : basicACLPublic } , info . Box , nil )
aclRes := getObjectACL ( hc , bktName , objName )
require . Len ( t , aclRes . AccessControlList , 2 )
require . Equal ( t , hex . EncodeToString ( info . Key . PublicKey ( ) . Bytes ( ) ) , aclRes . AccessControlList [ 0 ] . Grantee . ID )
require . Equal ( t , aclFullControl , aclRes . AccessControlList [ 0 ] . Permission )
require . Equal ( t , allUsersGroup , aclRes . AccessControlList [ 1 ] . Grantee . URI )
require . Equal ( t , aclFullControl , aclRes . AccessControlList [ 1 ] . Permission )
aclBody := & AccessControlPolicy { }
putObjectACLBase ( hc , bktName , objName , info . Box , nil , aclBody )
2024-02-12 14:29:36 +00:00
}
2024-03-19 13:56:32 +00:00
func TestBucketACLAPE ( t * testing . T ) {
2024-02-12 14:29:36 +00:00
hc := prepareHandlerContext ( t )
bktName := "bucket-for-acl-ape"
info := createBucket ( hc , bktName )
2024-03-19 13:56:32 +00:00
aclBody := & AccessControlPolicy { }
putBucketACLAssertS3Error ( hc , bktName , info . Box , nil , aclBody , s3errors . ErrAccessControlListNotSupported )
2024-02-12 14:29:36 +00:00
aclRes := getBucketACL ( hc , bktName )
2024-03-19 13:56:32 +00:00
checkPrivateACL ( t , aclRes , info . Key . PublicKey ( ) )
2024-02-12 14:29:36 +00:00
putBucketACL ( hc , bktName , info . Box , map [ string ] string { api . AmzACL : basicACLPrivate } )
aclRes = getBucketACL ( hc , bktName )
2024-03-19 13:56:32 +00:00
checkPrivateACL ( t , aclRes , info . Key . PublicKey ( ) )
2024-02-12 14:29:36 +00:00
putBucketACL ( hc , bktName , info . Box , map [ string ] string { api . AmzACL : basicACLReadOnly } )
aclRes = getBucketACL ( hc , bktName )
2024-03-19 13:56:32 +00:00
checkPublicReadACL ( t , aclRes , info . Key . PublicKey ( ) )
2024-02-12 14:29:36 +00:00
putBucketACL ( hc , bktName , info . Box , map [ string ] string { api . AmzACL : basicACLPublic } )
aclRes = getBucketACL ( hc , bktName )
2024-03-19 13:56:32 +00:00
checkPublicReadWriteACL ( t , aclRes , info . Key . PublicKey ( ) )
2024-02-12 14:29:36 +00:00
}
2024-03-19 13:56:32 +00:00
func checkPrivateACL ( t * testing . T , aclRes * AccessControlPolicy , ownerKey * keys . PublicKey ) {
checkACLOwner ( t , aclRes , ownerKey , 1 )
2024-02-12 14:29:36 +00:00
}
2024-03-19 13:56:32 +00:00
func checkPublicReadACL ( t * testing . T , aclRes * AccessControlPolicy , ownerKey * keys . PublicKey ) {
checkACLOwner ( t , aclRes , ownerKey , 2 )
2024-02-12 14:29:36 +00:00
require . Equal ( t , allUsersGroup , aclRes . AccessControlList [ 1 ] . Grantee . URI )
require . Equal ( t , aclRead , aclRes . AccessControlList [ 1 ] . Permission )
}
2024-03-19 13:56:32 +00:00
func checkPublicReadWriteACL ( t * testing . T , aclRes * AccessControlPolicy , ownerKey * keys . PublicKey ) {
checkACLOwner ( t , aclRes , ownerKey , 3 )
2024-02-12 14:29:36 +00:00
require . Equal ( t , allUsersGroup , aclRes . AccessControlList [ 1 ] . Grantee . URI )
require . Equal ( t , aclWrite , aclRes . AccessControlList [ 1 ] . Permission )
require . Equal ( t , allUsersGroup , aclRes . AccessControlList [ 2 ] . Grantee . URI )
require . Equal ( t , aclRead , aclRes . AccessControlList [ 2 ] . Permission )
}
2024-03-19 13:56:32 +00:00
func checkACLOwner ( t * testing . T , aclRes * AccessControlPolicy , ownerKey * keys . PublicKey , ln int ) {
2024-02-12 14:29:36 +00:00
ownerIDStr := hex . EncodeToString ( ownerKey . Bytes ( ) )
ownerNameStr := ownerKey . Address ( )
require . Equal ( t , ownerIDStr , aclRes . Owner . ID )
require . Equal ( t , ownerNameStr , aclRes . Owner . DisplayName )
require . Len ( t , aclRes . AccessControlList , ln )
require . Equal ( t , ownerIDStr , aclRes . AccessControlList [ 0 ] . Grantee . ID )
require . Equal ( t , ownerNameStr , aclRes . AccessControlList [ 0 ] . Grantee . DisplayName )
require . Equal ( t , aclFullControl , aclRes . AccessControlList [ 0 ] . Permission )
}
2022-11-09 14:25:02 +00:00
func TestBucketPolicy ( t * testing . T ) {
hc := prepareHandlerContext ( t )
bktName := "bucket-for-policy"
2023-12-08 07:44:13 +00:00
createTestBucket ( hc , bktName )
2022-11-09 14:25:02 +00:00
2023-12-08 07:44:13 +00:00
getBucketPolicy ( hc , bktName , s3errors . ErrNoSuchBucketPolicy )
2022-11-09 14:25:02 +00:00
2023-12-08 07:44:13 +00:00
newPolicy := engineiam . Policy {
Statement : [ ] engineiam . Statement { {
Principal : map [ engineiam . PrincipalType ] [ ] string { engineiam . Wildcard : { } } ,
Effect : engineiam . DenyEffect ,
Action : engineiam . Action { "s3:PutObject" } ,
Resource : engineiam . Resource { "arn:aws:s3:::test/*" } ,
2022-11-09 14:25:02 +00:00
} } ,
}
2023-12-08 07:44:13 +00:00
putBucketPolicy ( hc , bktName , newPolicy , s3errors . ErrMalformedPolicy )
2022-11-09 14:25:02 +00:00
2023-12-08 07:44:13 +00:00
newPolicy . Statement [ 0 ] . Resource [ 0 ] = arnAwsPrefix + bktName + "/*"
putBucketPolicy ( hc , bktName , newPolicy )
2022-11-09 14:25:02 +00:00
2023-12-08 07:44:13 +00:00
bktPolicy := getBucketPolicy ( hc , bktName )
require . Equal ( t , newPolicy , bktPolicy )
2022-11-09 14:25:02 +00:00
}
2024-03-05 06:56:12 +00:00
func TestBucketPolicyStatus ( t * testing . T ) {
hc := prepareHandlerContext ( t )
bktName := "bucket-for-policy"
createTestBucket ( hc , bktName )
getBucketPolicy ( hc , bktName , s3errors . ErrNoSuchBucketPolicy )
newPolicy := engineiam . Policy {
Statement : [ ] engineiam . Statement { {
NotPrincipal : engineiam . Principal { engineiam . Wildcard : { } } ,
Effect : engineiam . AllowEffect ,
Action : engineiam . Action { "s3:PutObject" } ,
Resource : engineiam . Resource { arnAwsPrefix + bktName + "/*" } ,
} } ,
}
putBucketPolicy ( hc , bktName , newPolicy , s3errors . ErrMalformedPolicyNotPrincipal )
newPolicy . Statement [ 0 ] . NotPrincipal = nil
newPolicy . Statement [ 0 ] . Principal = map [ engineiam . PrincipalType ] [ ] string { engineiam . Wildcard : { } }
putBucketPolicy ( hc , bktName , newPolicy )
bktPolicyStatus := getBucketPolicyStatus ( hc , bktName )
require . True ( t , PolicyStatusIsPublicTrue == bktPolicyStatus . IsPublic )
key , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
hc . Handler ( ) . frostfsid . ( * frostfsidMock ) . data [ "devenv" ] = key . PublicKey ( )
newPolicy . Statement [ 0 ] . Principal = map [ engineiam . PrincipalType ] [ ] string { engineiam . AWSPrincipalType : { "arn:aws:iam:::user/devenv" } }
putBucketPolicy ( hc , bktName , newPolicy )
bktPolicyStatus = getBucketPolicyStatus ( hc , bktName )
require . True ( t , PolicyStatusIsPublicFalse == bktPolicyStatus . IsPublic )
}
2023-02-17 12:52:52 +00:00
func TestBucketPolicyUnmarshal ( t * testing . T ) {
for _ , tc := range [ ] struct {
name string
policy string
} {
{
name : "action/resource array" ,
policy : `
{
"Version" : "2012-10-17" ,
"Statement" : [ {
"Principal" : {
"AWS" : "arn:aws:iam::111122223333:role/JohnDoe"
} ,
"Effect" : "Allow" ,
"Action" : [
2023-03-24 12:49:23 +00:00
"s3:GetObject" ,
2023-02-17 12:52:52 +00:00
"s3:GetObjectVersion"
] ,
"Resource" : [
"arn:aws:s3:::DOC-EXAMPLE-BUCKET/*" ,
"arn:aws:s3:::DOC-EXAMPLE-BUCKET2/*"
]
} ]
}
` ,
} ,
{
name : "action/resource string" ,
policy : `
{
"Version" : "2012-10-17" ,
"Statement" : [ {
"Principal" : {
"AWS" : "arn:aws:iam::111122223333:role/JohnDoe"
} ,
"Effect" : "Deny" ,
"Action" : "s3:GetObject" ,
"Resource" : "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"
} ]
}
` ,
} ,
} {
t . Run ( tc . name , func ( t * testing . T ) {
bktPolicy := & bucketPolicy { }
err := json . Unmarshal ( [ ] byte ( tc . policy ) , bktPolicy )
require . NoError ( t , err )
} )
}
}
func TestPutBucketPolicy ( t * testing . T ) {
bktPolicy := `
{
"Version" : "2012-10-17" ,
"Statement" : [ {
2023-12-08 07:44:13 +00:00
"Principal" : "*" ,
2023-02-17 12:52:52 +00:00
"Effect" : "Deny" ,
"Action" : "s3:GetObject" ,
"Resource" : "arn:aws:s3:::bucket-for-policy/*"
} ]
}
`
hc := prepareHandlerContext ( t )
bktName := "bucket-for-policy"
2023-12-08 07:44:13 +00:00
createTestBucket ( hc , bktName )
2023-02-17 12:52:52 +00:00
w , r := prepareTestPayloadRequest ( hc , bktName , "" , bytes . NewReader ( [ ] byte ( bktPolicy ) ) )
hc . Handler ( ) . PutBucketPolicyHandler ( w , r )
assertStatus ( hc . t , w , http . StatusOK )
}
2023-12-08 07:44:13 +00:00
func getBucketPolicy ( hc * handlerContext , bktName string , errCode ... s3errors . ErrorCode ) engineiam . Policy {
2022-11-09 14:25:02 +00:00
w , r := prepareTestRequest ( hc , bktName , "" , nil )
hc . Handler ( ) . GetBucketPolicyHandler ( w , r )
2023-12-08 07:44:13 +00:00
var policy engineiam . Policy
if len ( errCode ) == 0 {
assertStatus ( hc . t , w , http . StatusOK )
err := json . NewDecoder ( w . Result ( ) . Body ) . Decode ( & policy )
require . NoError ( hc . t , err )
} else {
assertS3Error ( hc . t , w , s3errors . GetAPIError ( errCode [ 0 ] ) )
}
2022-11-09 14:25:02 +00:00
return policy
}
2024-03-05 06:56:12 +00:00
func getBucketPolicyStatus ( hc * handlerContext , bktName string , errCode ... s3errors . ErrorCode ) PolicyStatus {
w , r := prepareTestRequest ( hc , bktName , "" , nil )
hc . Handler ( ) . GetBucketPolicyStatusHandler ( w , r )
var policyStatus PolicyStatus
if len ( errCode ) == 0 {
assertStatus ( hc . t , w , http . StatusOK )
err := xml . NewDecoder ( w . Result ( ) . Body ) . Decode ( & policyStatus )
require . NoError ( hc . t , err )
} else {
assertS3Error ( hc . t , w , s3errors . GetAPIError ( errCode [ 0 ] ) )
}
return policyStatus
}
2023-12-08 07:44:13 +00:00
func putBucketPolicy ( hc * handlerContext , bktName string , bktPolicy engineiam . Policy , errCode ... s3errors . ErrorCode ) {
2022-11-09 14:25:02 +00:00
body , err := json . Marshal ( bktPolicy )
require . NoError ( hc . t , err )
w , r := prepareTestPayloadRequest ( hc , bktName , "" , bytes . NewReader ( body ) )
hc . Handler ( ) . PutBucketPolicyHandler ( w , r )
2023-12-08 07:44:13 +00:00
if len ( errCode ) == 0 {
assertStatus ( hc . t , w , http . StatusOK )
} else {
assertS3Error ( hc . t , w , s3errors . GetAPIError ( errCode [ 0 ] ) )
}
2022-11-09 14:25:02 +00:00
}
2022-09-06 07:43:04 +00:00
func checkLastRecords ( t * testing . T , tc * handlerContext , bktInfo * data . BucketInfo , action eacl . Action ) {
bktACL , err := tc . Layer ( ) . GetBucketACL ( tc . Context ( ) , bktInfo )
require . NoError ( t , err )
length := len ( bktACL . EACL . Records ( ) )
if length < 7 {
t . Fatalf ( "length of records is less than 7: '%d'" , length )
}
for _ , rec := range bktACL . EACL . Records ( ) [ length - 7 : ] {
if rec . Action ( ) != action || rec . Targets ( ) [ 0 ] . Role ( ) != eacl . RoleOthers {
t . Fatalf ( "inavid last record: '%s', '%s', '%s'," , rec . Action ( ) , rec . Operation ( ) , rec . Targets ( ) [ 0 ] . Role ( ) )
}
}
}
2022-11-09 14:25:02 +00:00
func createAccessBox ( t * testing . T ) ( * accessbox . Box , * keys . PrivateKey ) {
2022-09-06 07:43:04 +00:00
key , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
var bearerToken bearer . Token
err = bearerToken . Sign ( key . PrivateKey )
require . NoError ( t , err )
tok := new ( session . Container )
tok . ForVerb ( session . VerbContainerSetEACL )
2023-06-30 09:03:55 +00:00
err = tok . Sign ( key . PrivateKey )
require . NoError ( t , err )
2022-09-06 07:43:04 +00:00
tok2 := new ( session . Container )
tok2 . ForVerb ( session . VerbContainerPut )
2023-06-30 09:03:55 +00:00
err = tok2 . Sign ( key . PrivateKey )
require . NoError ( t , err )
2022-09-06 07:43:04 +00:00
box := & accessbox . Box {
Gate : & accessbox . GateData {
SessionTokens : [ ] * session . Container { tok , tok2 } ,
BearerToken : & bearerToken ,
} ,
}
2022-11-09 14:25:02 +00:00
return box , key
2022-09-06 07:43:04 +00:00
}
2024-02-12 14:29:36 +00:00
type createBucketInfo struct {
BktInfo * data . BucketInfo
Box * accessbox . Box
Key * keys . PrivateKey
}
func createBucket ( hc * handlerContext , bktName string ) * createBucketInfo {
box , key := createAccessBox ( hc . t )
2024-02-12 12:28:55 +00:00
2023-06-30 09:03:55 +00:00
w := createBucketBase ( hc , bktName , box )
2024-02-12 12:28:55 +00:00
assertStatus ( hc . t , w , http . StatusOK )
2022-09-06 07:43:04 +00:00
2023-06-30 09:03:55 +00:00
bktInfo , err := hc . Layer ( ) . GetBucketInfo ( hc . Context ( ) , bktName )
2024-02-12 12:28:55 +00:00
require . NoError ( hc . t , err )
2024-02-12 14:29:36 +00:00
return & createBucketInfo {
BktInfo : bktInfo ,
Box : box ,
Key : key ,
}
2024-02-12 12:28:55 +00:00
}
2023-06-30 09:03:55 +00:00
func createBucketAssertS3Error ( hc * handlerContext , bktName string , box * accessbox . Box , code s3errors . ErrorCode ) {
w := createBucketBase ( hc , bktName , box )
assertS3Error ( hc . t , w , s3errors . GetAPIError ( code ) )
}
func createBucketBase ( hc * handlerContext , bktName string , box * accessbox . Box ) * httptest . ResponseRecorder {
w , r := prepareTestRequest ( hc , bktName , "" , nil )
2023-08-14 15:34:41 +00:00
ctx := middleware . SetBoxData ( r . Context ( ) , box )
2023-06-30 09:03:55 +00:00
r = r . WithContext ( ctx )
hc . Handler ( ) . CreateBucketHandler ( w , r )
return w
}
2024-02-12 14:29:36 +00:00
func putBucketACL ( hc * handlerContext , bktName string , box * accessbox . Box , header map [ string ] string ) {
w := putBucketACLBase ( hc , bktName , box , header , nil )
assertStatus ( hc . t , w , http . StatusOK )
}
func putBucketACLAssertS3Error ( hc * handlerContext , bktName string , box * accessbox . Box , header map [ string ] string , body * AccessControlPolicy , code s3errors . ErrorCode ) {
w := putBucketACLBase ( hc , bktName , box , header , body )
assertS3Error ( hc . t , w , s3errors . GetAPIError ( code ) )
}
func putBucketACLBase ( hc * handlerContext , bktName string , box * accessbox . Box , header map [ string ] string , body * AccessControlPolicy ) * httptest . ResponseRecorder {
w , r := prepareTestRequest ( hc , bktName , "" , body )
2022-09-06 07:43:04 +00:00
for key , val := range header {
r . Header . Set ( key , val )
}
2023-08-14 15:34:41 +00:00
ctx := middleware . SetBoxData ( r . Context ( ) , box )
2022-09-06 07:43:04 +00:00
r = r . WithContext ( ctx )
2024-02-12 14:29:36 +00:00
hc . Handler ( ) . PutBucketACLHandler ( w , r )
return w
}
func getBucketACL ( hc * handlerContext , bktName string ) * AccessControlPolicy {
w := getBucketACLBase ( hc , bktName )
assertStatus ( hc . t , w , http . StatusOK )
res := & AccessControlPolicy { }
parseTestResponse ( hc . t , w , res )
return res
}
func getBucketACLBase ( hc * handlerContext , bktName string ) * httptest . ResponseRecorder {
w , r := prepareTestRequest ( hc , bktName , "" , nil )
hc . Handler ( ) . GetBucketACLHandler ( w , r )
return w
}
func putObjectACLAssertS3Error ( hc * handlerContext , bktName , objName string , box * accessbox . Box , header map [ string ] string , body * AccessControlPolicy , code s3errors . ErrorCode ) {
w := putObjectACLBase ( hc , bktName , objName , box , header , body )
assertS3Error ( hc . t , w , s3errors . GetAPIError ( code ) )
}
func putObjectACLBase ( hc * handlerContext , bktName , objName string , box * accessbox . Box , header map [ string ] string , body * AccessControlPolicy ) * httptest . ResponseRecorder {
w , r := prepareTestRequest ( hc , bktName , objName , body )
for key , val := range header {
r . Header . Set ( key , val )
}
ctx := middleware . SetBoxData ( r . Context ( ) , box )
r = r . WithContext ( ctx )
hc . Handler ( ) . PutObjectACLHandler ( w , r )
return w
}
2024-03-19 13:56:32 +00:00
func getObjectACL ( hc * handlerContext , bktName , objName string ) * AccessControlPolicy {
2024-02-12 14:29:36 +00:00
w := getObjectACLBase ( hc , bktName , objName )
2024-03-19 13:56:32 +00:00
assertStatus ( hc . t , w , http . StatusOK )
res := & AccessControlPolicy { }
parseTestResponse ( hc . t , w , res )
return res
2024-02-12 14:29:36 +00:00
}
func getObjectACLBase ( hc * handlerContext , bktName , objName string ) * httptest . ResponseRecorder {
w , r := prepareTestRequest ( hc , bktName , objName , nil )
hc . Handler ( ) . GetObjectACLHandler ( w , r )
return w
2022-09-06 07:43:04 +00:00
}
2024-03-19 13:56:32 +00:00
func putObjectWithHeaders ( hc * handlerContext , bktName , objName string , headers map [ string ] string ) http . Header {
w := putObjectWithHeadersBase ( hc , bktName , objName , headers , nil , nil )
assertStatus ( hc . t , w , http . StatusOK )
return w . Header ( )
}
func putObjectWithHeadersAssertS3Error ( hc * handlerContext , bktName , objName string , headers map [ string ] string , code s3errors . ErrorCode ) {
w := putObjectWithHeadersBase ( hc , bktName , objName , headers , nil , nil )
assertS3Error ( hc . t , w , s3errors . GetAPIError ( code ) )
}
func putObjectWithHeadersBase ( hc * handlerContext , bktName , objName string , headers map [ string ] string , box * accessbox . Box , data [ ] byte ) * httptest . ResponseRecorder {
body := bytes . NewReader ( data )
w , r := prepareTestPayloadRequest ( hc , bktName , objName , body )
for k , v := range headers {
r . Header . Set ( k , v )
}
ctx := middleware . SetBoxData ( r . Context ( ) , box )
r = r . WithContext ( ctx )
hc . Handler ( ) . PutObjectHandler ( w , r )
return w
}