From f696a221af84fcff27266fd934a427d346547b93 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Sun, 2 Oct 2022 12:29:29 -0700 Subject: [PATCH] allow tagging policy condition for GetObject (#15777) --- cmd/admin-handlers-users_test.go | 28 +++++++ cmd/auth-handler.go | 131 ++++++++++++++++++++----------- cmd/authtype_string.go | 32 ++++++++ cmd/bucket-handlers.go | 4 +- cmd/object-handlers.go | 43 +++++++--- cmd/sts-handlers_test.go | 112 ++++++++++++++++++++++++++ cmd/utils.go | 4 - go.mod | 2 +- go.sum | 4 +- internal/logger/reqinfo.go | 29 ++++--- 10 files changed, 311 insertions(+), 78 deletions(-) create mode 100644 cmd/authtype_string.go diff --git a/cmd/admin-handlers-users_test.go b/cmd/admin-handlers-users_test.go index eef238494..4b66b7b78 100644 --- a/cmd/admin-handlers-users_test.go +++ b/cmd/admin-handlers-users_test.go @@ -1203,6 +1203,34 @@ func (c *check) mustNotListObjects(ctx context.Context, client *minio.Client, bu } } +func (c *check) mustPutObjectWithTags(ctx context.Context, client *minio.Client, bucket, object string) { + c.Helper() + _, err := client.PutObject(ctx, bucket, object, bytes.NewBuffer([]byte("stuff")), 5, minio.PutObjectOptions{ + UserTags: map[string]string{ + "security": "public", + "virus": "true", + }, + }) + if err != nil { + c.Fatalf("user was unable to upload the object: %v", err) + } +} + +func (c *check) mustGetObject(ctx context.Context, client *minio.Client, bucket, object string) { + c.Helper() + + r, err := client.GetObject(ctx, bucket, object, minio.GetObjectOptions{}) + if err != nil { + c.Fatalf("user was unable to download the object: %v", err) + } + defer r.Close() + + _, err = io.Copy(io.Discard, r) + if err != nil { + c.Fatalf("user was unable to download the object: %v", err) + } +} + func (c *check) mustListObjects(ctx context.Context, client *minio.Client, bucket string) { c.Helper() res := client.ListObjects(ctx, bucket, minio.ListObjectsOptions{}) diff --git a/cmd/auth-handler.go b/cmd/auth-handler.go index b72a53aac..cad2d3715 100644 --- a/cmd/auth-handler.go +++ b/cmd/auth-handler.go @@ -84,6 +84,8 @@ func isRequestSignStreamingV4(r *http.Request) bool { } // Authorization type. +// +//go:generate stringer -type=authType -trimprefix=authType $GOFILE type authType int // List of all supported auth types. @@ -293,24 +295,27 @@ func checkClaimsFromToken(r *http.Request, cred auth.Credentials) (map[string]in // // returns APIErrorCode if any to be replied to the client. func checkRequestAuthType(ctx context.Context, r *http.Request, action policy.Action, bucketName, objectName string) (s3Err APIErrorCode) { - _, _, s3Err = checkRequestAuthTypeCredential(ctx, r, action, bucketName, objectName) + logger.GetReqInfo(ctx).BucketName = bucketName + logger.GetReqInfo(ctx).ObjectName = objectName + + _, _, s3Err = checkRequestAuthTypeCredential(ctx, r, action) return s3Err } -// Check request auth type verifies the incoming http request -// - validates the request signature -// - validates the policy action if anonymous tests bucket policies if any, -// for authenticated requests validates IAM policies. -// -// returns APIErrorCode if any to be replied to the client. -// Additionally returns the accessKey used in the request, and if this request is by an admin. -func checkRequestAuthTypeCredential(ctx context.Context, r *http.Request, action policy.Action, bucketName, objectName string) (cred auth.Credentials, owner bool, s3Err APIErrorCode) { +func authenticateRequest(ctx context.Context, r *http.Request, action policy.Action) (s3Err APIErrorCode) { + if logger.GetReqInfo(ctx) == nil { + logger.LogIf(ctx, errors.New("unexpected context.Context does not have a logger.ReqInfo"), logger.Minio) + return ErrAccessDenied + } + + var cred auth.Credentials + var owner bool switch getRequestAuthType(r) { case authTypeUnknown, authTypeStreamingSigned: - return cred, owner, ErrSignatureVersionNotSupported + return ErrSignatureVersionNotSupported case authTypePresignedV2, authTypeSignedV2: if s3Err = isReqAuthenticatedV2(r); s3Err != ErrNone { - return cred, owner, s3Err + return s3Err } cred, owner, s3Err = getReqAccessKeyV2(r) case authTypeSigned, authTypePresigned: @@ -320,52 +325,67 @@ func checkRequestAuthTypeCredential(ctx context.Context, r *http.Request, action region = "" } if s3Err = isReqAuthenticated(ctx, r, region, serviceS3); s3Err != ErrNone { - return cred, owner, s3Err + return s3Err } cred, owner, s3Err = getReqAccessKeyV4(r, region, serviceS3) } if s3Err != ErrNone { - return cred, owner, s3Err + return s3Err } - // LocationConstraint is valid only for CreateBucketAction. - var locationConstraint string + logger.GetReqInfo(ctx).Cred = cred + logger.GetReqInfo(ctx).Owner = owner + + // region is valid only for CreateBucketAction. + var region string if action == policy.CreateBucketAction { // To extract region from XML in request body, get copy of request body. payload, err := io.ReadAll(io.LimitReader(r.Body, maxLocationConstraintSize)) if err != nil { logger.LogIf(ctx, err, logger.Application) - return cred, owner, ErrMalformedXML + return ErrMalformedXML } // Populate payload to extract location constraint. r.Body = io.NopCloser(bytes.NewReader(payload)) - - var s3Error APIErrorCode - locationConstraint, s3Error = parseLocationConstraint(r) - if s3Error != ErrNone { - return cred, owner, s3Error + region, s3Err = parseLocationConstraint(r) + if s3Err != ErrNone { + return s3Err } // Populate payload again to handle it in HTTP handler. r.Body = io.NopCloser(bytes.NewReader(payload)) } - if cred.AccessKey != "" { - logger.GetReqInfo(ctx).AccessKey = cred.AccessKey + + logger.GetReqInfo(ctx).Region = region + + return s3Err +} + +func authorizeRequest(ctx context.Context, r *http.Request, action policy.Action) (s3Err APIErrorCode) { + reqInfo := logger.GetReqInfo(ctx) + if reqInfo == nil { + return ErrAccessDenied } + cred := reqInfo.Cred + owner := reqInfo.Owner + region := reqInfo.Region + bucket := reqInfo.BucketName + object := reqInfo.ObjectName + if action != policy.ListAllMyBucketsAction && cred.AccessKey == "" { - // Anonymous checks are not meant for ListBuckets action + // Anonymous checks are not meant for ListAllBuckets action if globalPolicySys.IsAllowed(policy.Args{ AccountName: cred.AccessKey, Action: action, - BucketName: bucketName, - ConditionValues: getConditionValues(r, locationConstraint, "", nil), + BucketName: bucket, + ConditionValues: getConditionValues(r, region, "", nil), IsOwner: false, - ObjectName: objectName, + ObjectName: object, }) { // Request is allowed return the appropriate access key. - return cred, owner, ErrNone + return ErrNone } if action == policy.ListBucketVersionsAction { @@ -374,31 +394,31 @@ func checkRequestAuthTypeCredential(ctx context.Context, r *http.Request, action if globalPolicySys.IsAllowed(policy.Args{ AccountName: cred.AccessKey, Action: policy.ListBucketAction, - BucketName: bucketName, - ConditionValues: getConditionValues(r, locationConstraint, "", nil), + BucketName: bucket, + ConditionValues: getConditionValues(r, region, "", nil), IsOwner: false, - ObjectName: objectName, + ObjectName: object, }) { // Request is allowed return the appropriate access key. - return cred, owner, ErrNone + return ErrNone } } - return cred, owner, ErrAccessDenied + return ErrAccessDenied } if globalIAMSys.IsAllowed(iampolicy.Args{ AccountName: cred.AccessKey, Groups: cred.Groups, Action: iampolicy.Action(action), - BucketName: bucketName, + BucketName: bucket, ConditionValues: getConditionValues(r, "", cred.AccessKey, cred.Claims), - ObjectName: objectName, + ObjectName: object, IsOwner: owner, Claims: cred.Claims, }) { // Request is allowed return the appropriate access key. - return cred, owner, ErrNone + return ErrNone } if action == policy.ListBucketVersionsAction { @@ -408,18 +428,41 @@ func checkRequestAuthTypeCredential(ctx context.Context, r *http.Request, action AccountName: cred.AccessKey, Groups: cred.Groups, Action: iampolicy.ListBucketAction, - BucketName: bucketName, + BucketName: bucket, ConditionValues: getConditionValues(r, "", cred.AccessKey, cred.Claims), - ObjectName: objectName, + ObjectName: object, IsOwner: owner, Claims: cred.Claims, }) { // Request is allowed return the appropriate access key. - return cred, owner, ErrNone + return ErrNone } } - return cred, owner, ErrAccessDenied + return ErrAccessDenied +} + +// Check request auth type verifies the incoming http request +// - validates the request signature +// - validates the policy action if anonymous tests bucket policies if any, +// for authenticated requests validates IAM policies. +// +// returns APIErrorCode if any to be replied to the client. +// Additionally returns the accessKey used in the request, and if this request is by an admin. +func checkRequestAuthTypeCredential(ctx context.Context, r *http.Request, action policy.Action) (cred auth.Credentials, owner bool, s3Err APIErrorCode) { + s3Err = authenticateRequest(ctx, r, action) + reqInfo := logger.GetReqInfo(ctx) + if reqInfo == nil { + return cred, owner, ErrAccessDenied + } + + cred = reqInfo.Cred + owner = reqInfo.Owner + if s3Err != ErrNone { + return cred, owner, s3Err + } + + return cred, owner, authorizeRequest(ctx, r, action) } // Verify if request has valid AWS Signature Version '2'. @@ -623,22 +666,22 @@ func isPutRetentionAllowed(bucketName, objectName string, retDays int, retDate t 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 + region := globalSite.Region switch atype { case authTypeUnknown: return ErrSignatureVersionNotSupported case authTypeSignedV2, authTypePresignedV2: cred, owner, s3Err = getReqAccessKeyV2(r) case authTypeStreamingSigned, authTypePresigned, authTypeSigned: - region := globalSite.Region cred, owner, s3Err = getReqAccessKeyV4(r, region, serviceS3) } if s3Err != ErrNone { return s3Err } - if cred.AccessKey != "" { - logger.GetReqInfo(ctx).AccessKey = cred.AccessKey - } + logger.GetReqInfo(ctx).Cred = cred + logger.GetReqInfo(ctx).Owner = owner + logger.GetReqInfo(ctx).Region = region // Do not check for PutObjectRetentionAction permission, // if mode and retain until date are not set. diff --git a/cmd/authtype_string.go b/cmd/authtype_string.go new file mode 100644 index 000000000..0123db75b --- /dev/null +++ b/cmd/authtype_string.go @@ -0,0 +1,32 @@ +// Code generated by "stringer -type=authType -trimprefix=authType auth-handler.go"; DO NOT EDIT. + +package cmd + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[authTypeUnknown-0] + _ = x[authTypeAnonymous-1] + _ = x[authTypePresigned-2] + _ = x[authTypePresignedV2-3] + _ = x[authTypePostPolicy-4] + _ = x[authTypeStreamingSigned-5] + _ = x[authTypeSigned-6] + _ = x[authTypeSignedV2-7] + _ = x[authTypeJWT-8] + _ = x[authTypeSTS-9] +} + +const _authType_name = "UnknownAnonymousPresignedPresignedV2PostPolicyStreamingSignedSignedSignedV2JWTSTS" + +var _authType_index = [...]uint8{0, 7, 16, 25, 36, 46, 61, 67, 75, 78, 81} + +func (i authType) String() string { + if i < 0 || i >= authType(len(_authType_index)-1) { + return "authType(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _authType_name[_authType_index[i]:_authType_index[i+1]] +} diff --git a/cmd/bucket-handlers.go b/cmd/bucket-handlers.go index 9c4300366..b0afca206 100644 --- a/cmd/bucket-handlers.go +++ b/cmd/bucket-handlers.go @@ -300,7 +300,7 @@ func (api objectAPIHandlers) ListBucketsHandler(w http.ResponseWriter, r *http.R listBuckets := objectAPI.ListBuckets - cred, owner, s3Error := checkRequestAuthTypeCredential(ctx, r, policy.ListAllMyBucketsAction, "", "") + cred, owner, s3Error := checkRequestAuthTypeCredential(ctx, r, policy.ListAllMyBucketsAction) if s3Error != ErrNone && s3Error != ErrAccessDenied { writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL) return @@ -731,7 +731,7 @@ func (api objectAPIHandlers) PutBucketHandler(w http.ResponseWriter, r *http.Req } } - cred, owner, s3Error := checkRequestAuthTypeCredential(ctx, r, policy.CreateBucketAction, bucket, "") + cred, owner, s3Error := checkRequestAuthTypeCredential(ctx, r, policy.CreateBucketAction) if s3Error != ErrNone { writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL) return diff --git a/cmd/object-handlers.go b/cmd/object-handlers.go index 2454526b6..1b1626fec 100644 --- a/cmd/object-handlers.go +++ b/cmd/object-handlers.go @@ -187,23 +187,25 @@ func (api objectAPIHandlers) SelectObjectContentHandler(w http.ResponseWriter, r return } + // Take read lock on object, here so subsequent lower-level + // calls do not need to. + lock := objectAPI.NewNSLock(bucket, object) + lkctx, err := lock.GetRLock(ctx, globalOperationTimeout) + if err != nil { + writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL) + return + } + ctx = lkctx.Context() + defer lock.RUnlock(lkctx.Cancel) + getObjectNInfo := objectAPI.GetObjectNInfo if api.CacheAPI() != nil { getObjectNInfo = api.CacheAPI().GetObjectNInfo - } else { - // Take read lock on object, here so subsequent lower-level - // calls do not need to. - lock := objectAPI.NewNSLock(bucket, object) - lkctx, err := lock.GetRLock(ctx, globalOperationTimeout) - if err != nil { - writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL) - return - } - ctx = lkctx.Context() - defer lock.RUnlock(lkctx.Cancel) } - objInfo, err := getObjectInfo(ctx, bucket, object, opts) + gopts := opts + gopts.NoLock = true // We already have a lock, we can live with it. + objInfo, err := getObjectInfo(ctx, bucket, object, gopts) if err != nil { if globalBucketVersioningSys.PrefixEnabled(bucket, object) { // Versioning enabled quite possibly object is deleted might be delete-marker @@ -342,7 +344,7 @@ func (api objectAPIHandlers) getObjectHandler(ctx context.Context, objectAPI Obj // Check for auth type to return S3 compatible error. // type to return the correct error (NoSuchKey vs AccessDenied) - if s3Error := checkRequestAuthType(ctx, r, policy.GetObjectAction, bucket, object); s3Error != ErrNone { + if s3Error := authenticateRequest(ctx, r, policy.GetObjectAction); s3Error != ErrNone { if getRequestAuthType(r) == authTypeAnonymous { // As per "Permission" section in // https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectGET.html @@ -442,6 +444,12 @@ func (api objectAPIHandlers) getObjectHandler(ctx context.Context, objectAPI Obj } } if reader == nil || !proxy.Proxy { + // validate if the request indeed was authorized, if it wasn't we need to return "ErrAccessDenied" + // instead of any namespace related error. + if s3Error := authorizeRequest(ctx, r, policy.GetObjectAction); s3Error != ErrNone { + writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL) + return + } if isErrPreconditionFailed(err) { return } @@ -474,6 +482,15 @@ func (api objectAPIHandlers) getObjectHandler(ctx context.Context, objectAPI Obj objInfo := gr.ObjInfo + if objInfo.UserTags != "" { + r.Header.Set(xhttp.AmzObjectTagging, objInfo.UserTags) + } + + if s3Error := authorizeRequest(ctx, r, policy.GetObjectAction); s3Error != ErrNone { + writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL) + return + } + if !proxy.Proxy { // apply lifecycle rules only for local requests // Automatically remove the object/version is an expiry lifecycle rule can be applied if lc, err := globalLifecycleSys.Get(bucket); err == nil { diff --git a/cmd/sts-handlers_test.go b/cmd/sts-handlers_test.go index c470861f4..dd3ad6132 100644 --- a/cmd/sts-handlers_test.go +++ b/cmd/sts-handlers_test.go @@ -36,6 +36,7 @@ func runAllIAMSTSTests(suite *TestSuiteIAM, c *check) { // The STS for root test needs to be the first one after setup. suite.TestSTSForRoot(c) suite.TestSTS(c) + suite.TestSTSWithTags(c) suite.TestSTSWithGroupPolicy(c) suite.TearDownSuite(c) } @@ -72,6 +73,117 @@ func TestIAMInternalIDPSTSServerSuite(t *testing.T) { } } +func (s *TestSuiteIAM) TestSTSWithTags(c *check) { + ctx, cancel := context.WithTimeout(context.Background(), testDefaultTimeout) + defer cancel() + + bucket := getRandomBucketName() + object := getRandomObjectName() + err := s.client.MakeBucket(ctx, bucket, minio.MakeBucketOptions{}) + if err != nil { + c.Fatalf("bucket creat error: %v", err) + } + + // Create policy, user and associate policy + policy := "mypolicy" + policyBytes := []byte(fmt.Sprintf(`{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": "s3:GetObject", + "Resource": "arn:aws:s3:::%s/*", + "Condition": { "StringEquals": {"s3:ExistingObjectTag/security": "public" } } + }, + { + "Effect": "Allow", + "Action": "s3:DeleteObjectTagging", + "Resource": "arn:aws:s3:::%s/*", + "Condition": { "StringEquals": {"s3:ExistingObjectTag/security": "public" } } + }, + { + "Effect": "Allow", + "Action": "s3:DeleteObject", + "Resource": "arn:aws:s3:::%s/*" + }, + { + "Effect": "Allow", + "Action": [ + "s3:PutObject" + ], + "Resource": [ + "arn:aws:s3:::%s/*" + ], + "Condition": { + "ForAllValues:StringLike": { + "s3:RequestObjectTagKeys": [ + "security", + "virus" + ] + } + } + } + ] +}`, bucket, bucket, bucket, bucket)) + err = s.adm.AddCannedPolicy(ctx, policy, policyBytes) + if err != nil { + c.Fatalf("policy add error: %v", err) + } + + accessKey, secretKey := mustGenerateCredentials(c) + err = s.adm.SetUser(ctx, accessKey, secretKey, madmin.AccountEnabled) + if err != nil { + c.Fatalf("Unable to set user: %v", err) + } + + err = s.adm.SetPolicy(ctx, policy, accessKey, false) + if err != nil { + c.Fatalf("Unable to set policy: %v", err) + } + + // confirm that the user is able to access the bucket + uClient := s.getUserClient(c, accessKey, secretKey, "") + c.mustPutObjectWithTags(ctx, uClient, bucket, object) + c.mustGetObject(ctx, uClient, bucket, object) + + assumeRole := cr.STSAssumeRole{ + Client: s.TestSuiteCommon.client, + STSEndpoint: s.endPoint, + Options: cr.STSAssumeRoleOptions{ + AccessKey: accessKey, + SecretKey: secretKey, + Location: "", + }, + } + + value, err := assumeRole.Retrieve() + if err != nil { + c.Fatalf("err calling assumeRole: %v", err) + } + + minioClient, err := minio.New(s.endpoint, &minio.Options{ + Creds: cr.NewStaticV4(value.AccessKeyID, value.SecretAccessKey, value.SessionToken), + Secure: s.secure, + Transport: s.TestSuiteCommon.client.Transport, + }) + if err != nil { + c.Fatalf("Error initializing client: %v", err) + } + + // Validate sts creds can access the object + c.mustPutObjectWithTags(ctx, uClient, bucket, object) + c.mustGetObject(ctx, uClient, bucket, object) + + // Validate that the client can remove objects + if err = minioClient.RemoveObjectTagging(ctx, bucket, object, minio.RemoveObjectTaggingOptions{}); err != nil { + c.Fatalf("user is unable to delete the object tags: %v", err) + } + + if err = minioClient.RemoveObject(ctx, bucket, object, minio.RemoveObjectOptions{}); err != nil { + c.Fatalf("user is unable to delete the object: %v", err) + } +} + func (s *TestSuiteIAM) TestSTS(c *check) { ctx, cancel := context.WithTimeout(context.Background(), testDefaultTimeout) defer cancel() diff --git a/cmd/utils.go b/cmd/utils.go index b5fddb848..e487c9cc7 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -810,10 +810,6 @@ func newContext(r *http.Request, w http.ResponseWriter, api string) context.Cont vars := mux.Vars(r) bucket := vars["bucket"] object := likelyUnescapeGeneric(vars["object"], url.PathUnescape) - prefix := likelyUnescapeGeneric(vars["prefix"], url.QueryUnescape) - if prefix != "" { - object = prefix - } reqInfo := &logger.ReqInfo{ DeploymentID: globalDeploymentID, RequestID: w.Header().Get(xhttp.AmzRequestID), diff --git a/go.mod b/go.mod index bd7b5a582..854dd673f 100644 --- a/go.mod +++ b/go.mod @@ -49,7 +49,7 @@ require ( github.com/minio/kes v0.21.0 github.com/minio/madmin-go v1.4.29 github.com/minio/minio-go/v7 v7.0.40-0.20220928095841-8848d8affe8a - github.com/minio/pkg v1.4.2 + github.com/minio/pkg v1.4.3 github.com/minio/selfupdate v0.5.0 github.com/minio/sha256-simd v1.0.0 github.com/minio/simdjson-go v0.4.2 diff --git a/go.sum b/go.sum index 8b85629f1..2a5ccf7bd 100644 --- a/go.sum +++ b/go.sum @@ -660,8 +660,8 @@ github.com/minio/minio-go/v7 v7.0.23/go.mod h1:ei5JjmxwHaMrgsMrn4U/+Nmg+d8MKS1U2 github.com/minio/minio-go/v7 v7.0.40-0.20220928095841-8848d8affe8a h1:COFh7S3tOKmJNYtKKFAuHQFH7MAaXxg4aAluXC9KQgc= github.com/minio/minio-go/v7 v7.0.40-0.20220928095841-8848d8affe8a/go.mod h1:nCrRzjoSUQh8hgKKtu3Y708OLvRLtuASMg2/nvmbarw= github.com/minio/pkg v1.1.20/go.mod h1:Xo7LQshlxGa9shKwJ7NzQbgW4s8T/Wc1cOStR/eUiMY= -github.com/minio/pkg v1.4.2 h1:QEToJld+cy+mMLDv084kIOgzjJQMbM+ioI/WotHeYQY= -github.com/minio/pkg v1.4.2/go.mod h1:mxCLAG+fOGIQr6odQ5Ukqc6qv9Zj6v1d6TD3NP82B7Y= +github.com/minio/pkg v1.4.3 h1:RJdhFj+5qK/oYuTuLGtTzn6GKniwI57eJ0LxrZ7xpw4= +github.com/minio/pkg v1.4.3/go.mod h1:mxCLAG+fOGIQr6odQ5Ukqc6qv9Zj6v1d6TD3NP82B7Y= github.com/minio/selfupdate v0.5.0 h1:0UH1HlL49+2XByhovKl5FpYTjKfvrQ2sgL1zEXK6mfI= github.com/minio/selfupdate v0.5.0/go.mod h1:mcDkzMgq8PRcpCRJo/NlPY7U45O5dfYl2Y0Rg7IustY= github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= diff --git a/internal/logger/reqinfo.go b/internal/logger/reqinfo.go index 05c012883..ccc094393 100644 --- a/internal/logger/reqinfo.go +++ b/internal/logger/reqinfo.go @@ -21,6 +21,8 @@ import ( "context" "fmt" "sync" + + "github.com/minio/minio/internal/auth" ) // Key used for Get/SetReqInfo @@ -43,18 +45,21 @@ type ObjectVersion struct { // ReqInfo stores the request info. // Reading/writing directly to struct requires appropriate R/W lock. type ReqInfo struct { - RemoteHost string // Client Host/IP - Host string // Node Host/IP - UserAgent string // User Agent - DeploymentID string // x-minio-deployment-id - RequestID string // x-amz-request-id - API string // API name - GetObject PutObject NewMultipartUpload etc. - BucketName string `json:",omitempty"` // Bucket name - ObjectName string `json:",omitempty"` // Object name - VersionID string `json:",omitempty"` // corresponding versionID for the object - Objects []ObjectVersion `json:",omitempty"` // Only set during MultiObject delete handler. - AccessKey string // Access Key - tags []KeyVal // Any additional info not accommodated by above fields + RemoteHost string // Client Host/IP + Host string // Node Host/IP + UserAgent string // User Agent + DeploymentID string // x-minio-deployment-id + RequestID string // x-amz-request-id + API string // API name - GetObject PutObject NewMultipartUpload etc. + BucketName string `json:",omitempty"` // Bucket name + ObjectName string `json:",omitempty"` // Object name + VersionID string `json:",omitempty"` // corresponding versionID for the object + Objects []ObjectVersion `json:",omitempty"` // Only set during MultiObject delete handler. + Cred auth.Credentials `json:"-"` + Region string `json:"-"` + Owner bool `json:"-"` + AuthType string `json:"-"` + tags []KeyVal // Any additional info not accommodated by above fields sync.RWMutex }