From 4a1efabda4c97dcd17f0b75abc654e93a7bec250 Mon Sep 17 00:00:00 2001 From: Bill Thorp Date: Wed, 4 Nov 2020 12:13:34 -0500 Subject: [PATCH] Context based AccessKey passing (#10615) A new field called AccessKey is added to the ReqInfo struct and populated. Because ReqInfo is added to the context, this allows the AccessKey to be accessed from 3rd-party code, such as a custom ObjectLayer. Co-authored-by: Harshavardhana Co-authored-by: Kaloyan Raev --- cmd/auth-handler.go | 9 ++++++++- cmd/bucket-handlers.go | 4 ++++ cmd/bucket-replication.go | 2 +- cmd/logger/reqinfo.go | 1 + cmd/object-handlers.go | 18 +++++++++--------- 5 files changed, 23 insertions(+), 11 deletions(-) diff --git a/cmd/auth-handler.go b/cmd/auth-handler.go index 8408d0515..38971a2e1 100644 --- a/cmd/auth-handler.go +++ b/cmd/auth-handler.go @@ -333,6 +333,9 @@ func checkRequestAuthTypeToAccessKey(ctx context.Context, r *http.Request, actio // Populate payload again to handle it in HTTP handler. r.Body = ioutil.NopCloser(bytes.NewReader(payload)) } + if cred.AccessKey != "" { + logger.GetReqInfo(ctx).AccessKey = cred.AccessKey + } if action != policy.ListAllMyBucketsAction && cred.AccessKey == "" { // Anonymous checks are not meant for ListBuckets action @@ -616,7 +619,7 @@ func isPutRetentionAllowed(bucketName, objectName string, retDays int, retDate t // isPutActionAllowed - check if PUT operation is allowed on the resource, this // call verifies bucket policies and IAM policies, supports multi user // checks etc. -func isPutActionAllowed(atype authType, bucketName, objectName string, r *http.Request, action iampolicy.Action) (s3Err APIErrorCode) { +func isPutActionAllowed(ctx context.Context, atype authType, bucketName, objectName string, r *http.Request, action iampolicy.Action) (s3Err APIErrorCode) { var cred auth.Credentials var owner bool switch atype { @@ -637,6 +640,10 @@ func isPutActionAllowed(atype authType, bucketName, objectName string, r *http.R return s3Err } + if cred.AccessKey != "" { + logger.GetReqInfo(ctx).AccessKey = cred.AccessKey + } + // Do not check for PutObjectRetentionAction permission, // if mode and retain until date are not set. // Can happen when bucket has default lock config set diff --git a/cmd/bucket-handlers.go b/cmd/bucket-handlers.go index ddfedecea..20ac50c8f 100644 --- a/cmd/bucket-handlers.go +++ b/cmd/bucket-handlers.go @@ -383,6 +383,10 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter, return } + // Call checkRequestAuthType to populate ReqInfo.AccessKey before GetBucketInfo() + // Ignore errors here to preserve the S3 error behavior of GetBucketInfo() + checkRequestAuthType(ctx, r, policy.DeleteObjectAction, bucket, "") + // Before proceeding validate if bucket exists. _, err := objectAPI.GetBucketInfo(ctx, bucket) if err != nil { diff --git a/cmd/bucket-replication.go b/cmd/bucket-replication.go index c69539d3f..045d9de99 100644 --- a/cmd/bucket-replication.go +++ b/cmd/bucket-replication.go @@ -88,7 +88,7 @@ func mustReplicateWeb(ctx context.Context, r *http.Request, bucket, object strin // mustReplicate returns true if object meets replication criteria. func mustReplicate(ctx context.Context, r *http.Request, bucket, object string, meta map[string]string, replStatus string) bool { - if s3Err := isPutActionAllowed(getRequestAuthType(r), bucket, "", r, iampolicy.GetReplicationConfigurationAction); s3Err != ErrNone { + if s3Err := isPutActionAllowed(ctx, getRequestAuthType(r), bucket, "", r, iampolicy.GetReplicationConfigurationAction); s3Err != ErrNone { return false } return mustReplicater(ctx, r, bucket, object, meta, replStatus) diff --git a/cmd/logger/reqinfo.go b/cmd/logger/reqinfo.go index 535b20201..36bc01ecf 100644 --- a/cmd/logger/reqinfo.go +++ b/cmd/logger/reqinfo.go @@ -43,6 +43,7 @@ type ReqInfo struct { API string // API name - GetObject PutObject NewMultipartUpload etc. BucketName string // Bucket name ObjectName string // Object name + AccessKey string // Access Key tags []KeyVal // Any additional info not accommodated by above fields sync.RWMutex } diff --git a/cmd/object-handlers.go b/cmd/object-handlers.go index ca3433adc..e84ab763a 100644 --- a/cmd/object-handlers.go +++ b/cmd/object-handlers.go @@ -1159,8 +1159,8 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re srcInfo.UserDefined = filterReplicationStatusMetadata(srcInfo.UserDefined) srcInfo.UserDefined = objectlock.FilterObjectLockMetadata(srcInfo.UserDefined, true, true) - retPerms := isPutActionAllowed(getRequestAuthType(r), dstBucket, dstObject, r, iampolicy.PutObjectRetentionAction) - holdPerms := isPutActionAllowed(getRequestAuthType(r), dstBucket, dstObject, r, iampolicy.PutObjectLegalHoldAction) + retPerms := isPutActionAllowed(ctx, getRequestAuthType(r), dstBucket, dstObject, r, iampolicy.PutObjectRetentionAction) + holdPerms := isPutActionAllowed(ctx, getRequestAuthType(r), dstBucket, dstObject, r, iampolicy.PutObjectLegalHoldAction) getObjectInfo := objectAPI.GetObjectInfo if api.CacheAPI() != nil { @@ -1403,7 +1403,7 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req reader = r.Body // Check if put is allowed - if s3Err = isPutActionAllowed(rAuthType, bucket, object, r, iampolicy.PutObjectAction); s3Err != ErrNone { + if s3Err = isPutActionAllowed(ctx, rAuthType, bucket, object, r, iampolicy.PutObjectAction); s3Err != ErrNone { writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Err), r.URL, guessIsBrowserReq(r)) return } @@ -1488,8 +1488,8 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req putObject = api.CacheAPI().PutObject } - retPerms := isPutActionAllowed(getRequestAuthType(r), bucket, object, r, iampolicy.PutObjectRetentionAction) - holdPerms := isPutActionAllowed(getRequestAuthType(r), bucket, object, r, iampolicy.PutObjectLegalHoldAction) + retPerms := isPutActionAllowed(ctx, getRequestAuthType(r), bucket, object, r, iampolicy.PutObjectRetentionAction) + holdPerms := isPutActionAllowed(ctx, getRequestAuthType(r), bucket, object, r, iampolicy.PutObjectLegalHoldAction) getObjectInfo := objectAPI.GetObjectInfo if api.CacheAPI() != nil { @@ -1512,7 +1512,7 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req metadata[xhttp.AmzBucketReplicationStatus] = replication.Pending.String() } if r.Header.Get(xhttp.AmzBucketReplicationStatus) == replication.Replica.String() { - if s3Err = isPutActionAllowed(getRequestAuthType(r), bucket, object, r, iampolicy.ReplicateObjectAction); s3Err != ErrNone { + if s3Err = isPutActionAllowed(ctx, getRequestAuthType(r), bucket, object, r, iampolicy.ReplicateObjectAction); s3Err != ErrNone { writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Err), r.URL, guessIsBrowserReq(r)) return } @@ -1668,8 +1668,8 @@ func (api objectAPIHandlers) NewMultipartUploadHandler(w http.ResponseWriter, r return } - retPerms := isPutActionAllowed(getRequestAuthType(r), bucket, object, r, iampolicy.PutObjectRetentionAction) - holdPerms := isPutActionAllowed(getRequestAuthType(r), bucket, object, r, iampolicy.PutObjectLegalHoldAction) + retPerms := isPutActionAllowed(ctx, getRequestAuthType(r), bucket, object, r, iampolicy.PutObjectRetentionAction) + holdPerms := isPutActionAllowed(ctx, getRequestAuthType(r), bucket, object, r, iampolicy.PutObjectLegalHoldAction) getObjectInfo := objectAPI.GetObjectInfo if api.CacheAPI() != nil { @@ -2134,7 +2134,7 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http s3Error APIErrorCode ) reader = r.Body - if s3Error = isPutActionAllowed(rAuthType, bucket, object, r, iampolicy.PutObjectAction); s3Error != ErrNone { + if s3Error = isPutActionAllowed(ctx, rAuthType, bucket, object, r, iampolicy.PutObjectAction); s3Error != ErrNone { writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r)) return }