Skip to content

Commit

Permalink
Fix eacl issue in copyobject (#1061)
Browse files Browse the repository at this point in the history
Closes #1055
  • Loading branch information
roman-khimov authored Jan 24, 2025
2 parents 50a1cc1 + 36cd8ab commit 32979dc
Show file tree
Hide file tree
Showing 9 changed files with 180 additions and 30 deletions.
37 changes: 22 additions & 15 deletions api/handler/acl.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ func (h *handler) PutBucketACLHandler(w http.ResponseWriter, r *http.Request) {
return
}

if isBucketOwnerForced(eacl.EACL) {
if IsBucketOwnerForced(eacl.EACL) {
if !isValidOwnerEnforced(r) {
h.logAndSendError(w, "access control list not supported", reqInfo, s3errors.GetAPIError(s3errors.ErrAccessControlListNotSupported))
return
Expand Down Expand Up @@ -430,15 +430,15 @@ func (h *handler) PutObjectACLHandler(w http.ResponseWriter, r *http.Request) {
return
}

if isBucketOwnerForced(eacl.EACL) {
if IsBucketOwnerForced(eacl.EACL) {
if !isValidOwnerEnforced(r) {
h.logAndSendError(w, "access control list not supported", reqInfo, s3errors.GetAPIError(s3errors.ErrAccessControlListNotSupported))
return
}
r.Header.Set(api.AmzACL, "")
}

if isBucketOwnerPreferredAndRestricted(eacl.EACL) {
if IsBucketOwnerPreferredAndRestricted(eacl.EACL) {
if !isValidOwnerPreferred(r) {
h.logAndSendError(w, "header x-amz-acl:bucket-owner-full-control must be set", reqInfo, s3errors.GetAPIError(s3errors.ErrAccessDenied))
return
Expand Down Expand Up @@ -1026,13 +1026,13 @@ func formRecords(resource *astResource) ([]*eacl.Record, error) {

switch astOp.Users[0] {
case ownerEnforcedUserID:
markerRecord = bucketOwnerEnforcedRecord()
markerRecord = BucketOwnerEnforcedRecord()
case ownerPreferredUserID:
markerRecord = bucketOwnerPreferredRecord()
markerRecord = BucketOwnerPreferredRecord()
case ownerObjectWriterUserID:
markerRecord = bucketACLObjectWriterRecord()
markerRecord = BucketACLObjectWriterRecord()
case ownerPreferredAndRestrictedUserID:
markerRecord = bucketOwnerPreferredAndRestrictedRecord()
markerRecord = BucketOwnerPreferredAndRestrictedRecord()
}

if markerRecord != nil {
Expand Down Expand Up @@ -1687,7 +1687,7 @@ func bucketACLToTable(acp *AccessControlPolicy) (*eacl.Table, error) {
table.AddRecord(getOthersRecord(op, eacl.ActionDeny))
}

table.AddRecord(bucketOwnerEnforcedRecord())
table.AddRecord(BucketOwnerEnforcedRecord())

return table, nil
}
Expand Down Expand Up @@ -1720,7 +1720,8 @@ func getOthersRecord(op eacl.Operation, action eacl.Action) *eacl.Record {
return record
}

func bucketOwnerEnforcedRecord() *eacl.Record {
// BucketOwnerEnforcedRecord generates special marker record for OwnerEnforced policy.
func BucketOwnerEnforcedRecord() *eacl.Record {
var markerRecord = eacl.CreateRecord(eacl.ActionDeny, eacl.OperationPut)
markerRecord.AddFilter(
eacl.HeaderFromRequest,
Expand Down Expand Up @@ -1751,7 +1752,8 @@ func isValidOwnerEnforced(r *http.Request) bool {
return true
}

func bucketACLObjectWriterRecord() *eacl.Record {
// BucketACLObjectWriterRecord generates special marker record for OwnerWriter policy.
func BucketACLObjectWriterRecord() *eacl.Record {
var markerRecord = eacl.CreateRecord(eacl.ActionDeny, eacl.OperationPut)
markerRecord.AddFilter(
eacl.HeaderFromRequest,
Expand All @@ -1767,7 +1769,8 @@ func bucketACLObjectWriterRecord() *eacl.Record {
return markerRecord
}

func isBucketOwnerForced(table *eacl.Table) bool {
// IsBucketOwnerForced checks special marker record for OwnerForced policy.
func IsBucketOwnerForced(table *eacl.Table) bool {
if table == nil {
return false
}
Expand All @@ -1790,7 +1793,8 @@ func isBucketOwnerForced(table *eacl.Table) bool {
return false
}

func bucketOwnerPreferredRecord() *eacl.Record {
// BucketOwnerPreferredRecord generates special marker record for OwnerPreferred policy.
func BucketOwnerPreferredRecord() *eacl.Record {
var markerRecord = eacl.CreateRecord(eacl.ActionDeny, eacl.OperationPut)
markerRecord.AddFilter(
eacl.HeaderFromRequest,
Expand All @@ -1806,7 +1810,8 @@ func bucketOwnerPreferredRecord() *eacl.Record {
return markerRecord
}

func isBucketOwnerPreferred(table *eacl.Table) bool {
// IsBucketOwnerPreferred checks special marker record for OwnerPreferred policy.
func IsBucketOwnerPreferred(table *eacl.Table) bool {
if table == nil {
return false
}
Expand All @@ -1829,7 +1834,8 @@ func isBucketOwnerPreferred(table *eacl.Table) bool {
return false
}

func bucketOwnerPreferredAndRestrictedRecord() *eacl.Record {
// BucketOwnerPreferredRecord generates special marker record for OwnerPreferred policy and sets flag for bucket owner full control acl restriction.
func BucketOwnerPreferredAndRestrictedRecord() *eacl.Record {
var markerRecord = eacl.CreateRecord(eacl.ActionDeny, eacl.OperationPut)
markerRecord.AddFilter(
eacl.HeaderFromObject,
Expand All @@ -1845,7 +1851,8 @@ func bucketOwnerPreferredAndRestrictedRecord() *eacl.Record {
return markerRecord
}

func isBucketOwnerPreferredAndRestricted(table *eacl.Table) bool {
// IsBucketOwnerPreferredAndRestricted checks special marker record and check ALC bucket owner full control flag for OwnerPreferred policy.
func IsBucketOwnerPreferredAndRestricted(table *eacl.Table) bool {
if table == nil {
return false
}
Expand Down
2 changes: 1 addition & 1 deletion api/handler/acl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1185,7 +1185,7 @@ func TestBucketAclToTable(t *testing.T) {
for _, op := range fullOps {
expectedTable.AddRecord(getOthersRecord(op, eacl.ActionDeny))
}
expectedTable.AddRecord(bucketOwnerEnforcedRecord())
expectedTable.AddRecord(BucketOwnerEnforcedRecord())

actualTable, err := bucketACLToTable(acl)
require.NoError(t, err)
Expand Down
7 changes: 4 additions & 3 deletions api/handler/copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func (h *handler) CopyObjectHandler(w http.ResponseWriter, r *http.Request) {
}

if containsACL {
if isBucketOwnerForced(eacl.EACL) {
if IsBucketOwnerForced(eacl.EACL) {
if !isValidOwnerEnforced(r) {
h.logAndSendError(w, "access control list not supported", reqInfo, s3errors.GetAPIError(s3errors.ErrAccessControlListNotSupported))
return
Expand All @@ -111,7 +111,7 @@ func (h *handler) CopyObjectHandler(w http.ResponseWriter, r *http.Request) {
}
}

if isBucketOwnerPreferredAndRestricted(eacl.EACL) {
if IsBucketOwnerPreferredAndRestricted(eacl.EACL) {
if !isValidOwnerPreferred(r) {
h.logAndSendError(w, "header x-amz-acl:bucket-owner-full-control must be set", reqInfo, s3errors.GetAPIError(s3errors.ErrAccessDenied))
return
Expand Down Expand Up @@ -225,7 +225,8 @@ func (h *handler) CopyObjectHandler(w http.ResponseWriter, r *http.Request) {
return
}

if containsACL {
// In some cases upper in the code, we change ACL headers. We have to check all headers one more time.
if containsACLHeaders(r) {
newEaclTable, err := h.getNewEAclTable(r, dstBktInfo, dstObjInfo)
if err != nil {
h.logAndSendError(w, "could not get new eacl table", reqInfo, err)
Expand Down
4 changes: 2 additions & 2 deletions api/handler/multipart_upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ func (h *handler) CreateMultipartUploadHandler(w http.ResponseWriter, r *http.Re
}

if containsACLHeaders(r) {
if isBucketOwnerForced(eacl.EACL) {
if IsBucketOwnerForced(eacl.EACL) {
if !isValidOwnerEnforced(r) {
h.logAndSendError(w, "access control list not supported", reqInfo, s3errors.GetAPIError(s3errors.ErrAccessControlListNotSupported))
return
Expand All @@ -139,7 +139,7 @@ func (h *handler) CreateMultipartUploadHandler(w http.ResponseWriter, r *http.Re
p.Data.ACLHeaders = formACLHeadersForMultipart(r.Header)
}

if isBucketOwnerPreferredAndRestricted(eacl.EACL) {
if IsBucketOwnerPreferredAndRestricted(eacl.EACL) {
if !isValidOwnerPreferred(r) {
h.logAndSendError(w, "header x-amz-acl:bucket-owner-full-control must be set", reqInfo, s3errors.GetAPIError(s3errors.ErrAccessDenied))
return
Expand Down
10 changes: 5 additions & 5 deletions api/handler/ownership.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,11 @@ func (h *handler) PutBucketOwnershipControlsHandler(w http.ResponseWriter, r *ht

switch params.Rules[0].ObjectOwnership {
case amzBucketOwnerEnforced:
rec = bucketOwnerEnforcedRecord()
rec = BucketOwnerEnforcedRecord()
case amzBucketOwnerPreferred:
rec = bucketOwnerPreferredRecord()
rec = BucketOwnerPreferredRecord()
case amzBucketOwnerObjectWriter:
rec = bucketACLObjectWriterRecord()
rec = BucketACLObjectWriterRecord()
default:
h.logAndSendError(w, "invalid ownership", reqInfo, s3errors.GetAPIError(s3errors.ErrBadRequest))
return
Expand Down Expand Up @@ -135,11 +135,11 @@ func (h *handler) GetBucketOwnershipControlsHandler(w http.ResponseWriter, r *ht
return
}

if isBucketOwnerForced(bucketACL.EACL) {
if IsBucketOwnerForced(bucketACL.EACL) {
response = &putBucketOwnershipControlsParams{
Rules: []objectOwnershipRules{{ObjectOwnership: amzBucketOwnerEnforced}},
}
} else if isBucketOwnerPreferred(bucketACL.EACL) {
} else if IsBucketOwnerPreferred(bucketACL.EACL) {
response = &putBucketOwnershipControlsParams{
Rules: []objectOwnershipRules{{ObjectOwnership: amzBucketOwnerPreferred}},
}
Expand Down
8 changes: 4 additions & 4 deletions api/handler/put.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ func (h *handler) PutObjectHandler(w http.ResponseWriter, r *http.Request) {
}

if containsACL {
if isBucketOwnerForced(eacl.EACL) {
if IsBucketOwnerForced(eacl.EACL) {
if !isValidOwnerEnforced(r) {
h.logAndSendError(w, "access control list not supported", reqInfo, s3errors.GetAPIError(s3errors.ErrAccessControlListNotSupported))
return
Expand All @@ -225,7 +225,7 @@ func (h *handler) PutObjectHandler(w http.ResponseWriter, r *http.Request) {
}
}

if isBucketOwnerPreferredAndRestricted(eacl.EACL) {
if IsBucketOwnerPreferredAndRestricted(eacl.EACL) {
if !isValidOwnerPreferred(r) {
h.logAndSendError(w, "header x-amz-acl:bucket-owner-full-control must be set", reqInfo, s3errors.GetAPIError(s3errors.ErrAccessDenied))
return
Expand Down Expand Up @@ -474,7 +474,7 @@ func (h *handler) PostObject(w http.ResponseWriter, r *http.Request) {
}

if containsACL {
if isBucketOwnerForced(eacl.EACL) {
if IsBucketOwnerForced(eacl.EACL) {
if !isValidOwnerEnforced(r) {
h.logAndSendError(w, "access control list not supported", reqInfo, s3errors.GetAPIError(s3errors.ErrAccessControlListNotSupported))
return
Expand All @@ -483,7 +483,7 @@ func (h *handler) PostObject(w http.ResponseWriter, r *http.Request) {
}
}

if isBucketOwnerPreferredAndRestricted(eacl.EACL) {
if IsBucketOwnerPreferredAndRestricted(eacl.EACL) {
if !isValidOwnerPreferred(r) {
h.logAndSendError(w, "header x-amz-acl:bucket-owner-full-control must be set", reqInfo, s3errors.GetAPIError(s3errors.ErrAccessDenied))
return
Expand Down
6 changes: 6 additions & 0 deletions authmate/authmate.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ type NeoFS interface {
//
// It returns any error encountered which prevented computing epochs.
TimeToEpoch(context.Context, time.Time) (uint64, uint64, error)

// SetContainerEACL updates container EACL.
SetContainerEACL(ctx context.Context, table eacl.Table, sessionToken *session.Container) error

// ContainerEACL gets container EACL.
ContainerEACL(ctx context.Context, containerID cid.ID) (*eacl.Table, error)
}

// Agent contains client communicating with NeoFS and logger.
Expand Down
Loading

0 comments on commit 32979dc

Please sign in to comment.