diff --git a/weed/s3api/s3api_acp.go b/weed/s3api/s3api_acp.go index 7a76c2a67..2894f0f6e 100644 --- a/weed/s3api/s3api_acp.go +++ b/weed/s3api/s3api_acp.go @@ -1,9 +1,14 @@ package s3api import ( + "github.com/aws/aws-sdk-go/service/s3" + "github.com/seaweedfs/seaweedfs/weed/glog" + "github.com/seaweedfs/seaweedfs/weed/pb/filer_pb" "github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants" "github.com/seaweedfs/seaweedfs/weed/s3api/s3account" + "github.com/seaweedfs/seaweedfs/weed/s3api/s3acl" "github.com/seaweedfs/seaweedfs/weed/s3api/s3err" + "github.com/seaweedfs/seaweedfs/weed/util" "net/http" ) @@ -27,3 +32,74 @@ func (s3a *S3ApiServer) checkAccessByOwnership(r *http.Request, bucket string) s } return s3err.ErrAccessDenied } + +//Check ObjectAcl-Read related access +// includes: +// - GetObjectAclHandler +func (s3a *S3ApiServer) checkAccessForReadObjectAcl(r *http.Request, bucket, object string) (acp *s3.AccessControlPolicy, errCode s3err.ErrorCode) { + bucketMetadata, errCode := s3a.bucketRegistry.GetBucketMetadata(bucket) + if errCode != s3err.ErrNone { + return nil, errCode + } + + getAcpFunc := func() (*s3.AccessControlPolicy, s3err.ErrorCode) { + entry, err := getObjectEntry(s3a, bucket, object) + if err != nil { + if err == filer_pb.ErrNotFound { + return nil, s3err.ErrNoSuchKey + } else { + return nil, s3err.ErrInternalError + } + } + + if entry.IsDirectory { + return nil, s3err.ErrExistingObjectIsDirectory + } + + acpOwnerId := s3acl.GetAcpOwner(entry.Extended, *bucketMetadata.Owner.ID) + acpOwnerName := s3a.accountManager.IdNameMapping[acpOwnerId] + acpGrants := s3acl.GetAcpGrants(entry.Extended) + acp = &s3.AccessControlPolicy{ + Owner: &s3.Owner{ + ID: &acpOwnerId, + DisplayName: &acpOwnerName, + }, + Grants: acpGrants, + } + return acp, s3err.ErrNone + } + + if bucketMetadata.ObjectOwnership == s3_constants.OwnershipBucketOwnerEnforced { + return getAcpFunc() + } else { + accountId := s3acl.GetAccountId(r) + + acp, errCode := getAcpFunc() + if errCode != s3err.ErrNone { + return nil, errCode + } + + if accountId == *acp.Owner.ID { + return acp, s3err.ErrNone + } + + //find in Grants + if acp.Grants != nil { + reqGrants := s3acl.DetermineReqGrants(accountId, s3_constants.PermissionReadAcp) + for _, requiredGrant := range reqGrants { + for _, grant := range acp.Grants { + if s3acl.GrantEquals(requiredGrant, grant) { + return acp, s3err.ErrNone + } + } + } + } + + glog.V(3).Infof("acl denied! request account id: %s", accountId) + return nil, s3err.ErrAccessDenied + } +} + +func getObjectEntry(s3a *S3ApiServer, bucket, object string) (*filer_pb.Entry, error) { + return s3a.getEntry(util.Join(s3a.option.BucketsPath, bucket), object) +} diff --git a/weed/s3api/s3api_object_handlers.go b/weed/s3api/s3api_object_handlers.go index 2fc0111a4..d14cc2896 100644 --- a/weed/s3api/s3api_object_handlers.go +++ b/weed/s3api/s3api_object_handlers.go @@ -6,6 +6,7 @@ import ( "encoding/json" "encoding/xml" "fmt" + "github.com/aws/aws-sdk-go/service/s3" "github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants" "github.com/seaweedfs/seaweedfs/weed/security" "github.com/seaweedfs/seaweedfs/weed/util/mem" @@ -174,6 +175,21 @@ func (s3a *S3ApiServer) GetObjectHandler(w http.ResponseWriter, r *http.Request) s3a.proxyToFiler(w, r, destUrl, false, passThroughResponse) } +// GetObjectAclHandler Put object ACL +// https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjecthtml +func (s3a *S3ApiServer) GetObjectAclHandler(w http.ResponseWriter, r *http.Request) { + bucket, object := s3_constants.GetBucketAndObject(r) + acp, errCode := s3a.checkAccessForReadObjectAcl(r, bucket, object) + if errCode != s3err.ErrNone { + s3err.WriteErrorResponse(w, r, errCode) + return + } + result := &s3.PutBucketAclInput{ + AccessControlPolicy: acp, + } + s3err.WriteAwsXMLResponse(w, r, http.StatusOK, &result) +} + func (s3a *S3ApiServer) HeadObjectHandler(w http.ResponseWriter, r *http.Request) { bucket, object := s3_constants.GetBucketAndObject(r) diff --git a/weed/s3api/s3api_object_skip_handlers.go b/weed/s3api/s3api_object_skip_handlers.go index 160d02475..935787fbb 100644 --- a/weed/s3api/s3api_object_skip_handlers.go +++ b/weed/s3api/s3api_object_skip_handlers.go @@ -4,14 +4,6 @@ import ( "net/http" ) -// GetObjectAclHandler Put object ACL -// https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectAcl.html -func (s3a *S3ApiServer) GetObjectAclHandler(w http.ResponseWriter, r *http.Request) { - - w.WriteHeader(http.StatusNoContent) - -} - // PutObjectAclHandler Put object ACL // https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectAcl.html func (s3a *S3ApiServer) PutObjectAclHandler(w http.ResponseWriter, r *http.Request) {