[#574] Produce deny records for private objects

Signed-off-by: Alex Vanin <alexey@nspcc.ru>
This commit is contained in:
Alex Vanin 2022-07-21 12:55:33 +03:00 committed by Alex Vanin
parent 7ba7e7dc4d
commit 66fe3fee7b
2 changed files with 38 additions and 4 deletions

View file

@ -1190,6 +1190,13 @@ func aclToPolicy(acl *AccessControlPolicy, resInfo *resourceInfo) (*bucketPolicy
getAllowStatement(resInfo, acl.Owner.ID, aclFullControl), getAllowStatement(resInfo, acl.Owner.ID, aclFullControl),
} }
// Expect to have at least 1 full control grant for owner which is set in
// parseACLHeaders(). If there is no other grants, then user sets private
// canned ACL, which is processed in this branch.
if len(acl.AccessControlList) < 2 {
results = append([]statement{getDenyStatement(resInfo, allUsersWildcard, aclFullControl)}, results...)
}
for _, grant := range acl.AccessControlList { for _, grant := range acl.AccessControlList {
if grant.Grantee.Type == acpAmazonCustomerByEmail || (grant.Grantee.Type == acpGroup && grant.Grantee.URI != allUsersGroup) { if grant.Grantee.Type == acpAmazonCustomerByEmail || (grant.Grantee.Type == acpGroup && grant.Grantee.URI != allUsersGroup) {
return nil, stderrors.New("unsupported grantee type") return nil, stderrors.New("unsupported grantee type")
@ -1227,6 +1234,23 @@ func getAllowStatement(resInfo *resourceInfo, id string, permission AWSACL) stat
return state return state
} }
func getDenyStatement(resInfo *resourceInfo, id string, permission AWSACL) statement {
state := statement{
Effect: "Deny",
Principal: principal{
CanonicalUser: id,
},
Action: getActions(permission, resInfo.IsBucket()),
Resource: []string{arnAwsPrefix + resInfo.Name()},
}
if id == allUsersWildcard {
state.Principal = principal{AWS: allUsersWildcard}
}
return state
}
func getActions(permission AWSACL, isBucket bool) []string { func getActions(permission AWSACL, isBucket bool) []string {
var res []string var res []string
switch permission { switch permission {

View file

@ -862,7 +862,7 @@ func TestObjectWithVersionAclToTable(t *testing.T) {
Bucket: "bucketName", Bucket: "bucketName",
Object: "object", Object: "object",
} }
expectedTable := allowedTableForObject(t, key, resInfoObject) expectedTable := allowedTableForPrivateObject(t, key, resInfoObject)
actualTable := tableFromACL(t, acl, resInfoObject) actualTable := tableFromACL(t, acl, resInfoObject)
checkTables(t, expectedTable, actualTable) checkTables(t, expectedTable, actualTable)
@ -871,12 +871,12 @@ func TestObjectWithVersionAclToTable(t *testing.T) {
Object: "objectVersion", Object: "objectVersion",
Version: "Gfrct4Afhio8pCGCCKVNTf1kyexQjMBeaUfvDtQCkAvg", Version: "Gfrct4Afhio8pCGCCKVNTf1kyexQjMBeaUfvDtQCkAvg",
} }
expectedTable = allowedTableForObject(t, key, resInfoObjectVersion) expectedTable = allowedTableForPrivateObject(t, key, resInfoObjectVersion)
actualTable = tableFromACL(t, acl, resInfoObjectVersion) actualTable = tableFromACL(t, acl, resInfoObjectVersion)
checkTables(t, expectedTable, actualTable) checkTables(t, expectedTable, actualTable)
} }
func allowedTableForObject(t *testing.T, key *keys.PrivateKey, resInfo *resourceInfo) *eacl.Table { func allowedTableForPrivateObject(t *testing.T, key *keys.PrivateKey, resInfo *resourceInfo) *eacl.Table {
var isVersion bool var isVersion bool
var objID oid.ID var objID oid.ID
if resInfo.Version != "" { if resInfo.Version != "" {
@ -886,7 +886,7 @@ func allowedTableForObject(t *testing.T, key *keys.PrivateKey, resInfo *resource
} }
expectedTable := eacl.NewTable() expectedTable := eacl.NewTable()
serviceRec := &ServiceRecord{Resource: resInfo.Name(), GroupRecordsLength: len(readOps)} serviceRec := &ServiceRecord{Resource: resInfo.Name(), GroupRecordsLength: len(readOps) * 2}
expectedTable.AddRecord(serviceRec.ToEACLRecord()) expectedTable.AddRecord(serviceRec.ToEACLRecord())
for i := len(readOps) - 1; i >= 0; i-- { for i := len(readOps) - 1; i >= 0; i-- {
@ -899,6 +899,16 @@ func allowedTableForObject(t *testing.T, key *keys.PrivateKey, resInfo *resource
} }
expectedTable.AddRecord(record) expectedTable.AddRecord(record)
} }
for i := len(readOps) - 1; i >= 0; i-- {
op := readOps[i]
record := getOthersRecord(op, eacl.ActionDeny)
if isVersion {
record.AddObjectIDFilter(eacl.MatchStringEqual, objID)
} else {
record.AddObjectAttributeFilter(eacl.MatchStringEqual, object.AttributeFileName, resInfo.Object)
}
expectedTable.AddRecord(record)
}
return expectedTable return expectedTable
} }