disallow sub-credentials based on root credentials to gain priviledges (#12947)

This happens because of a change added where any sub-credential
with parentUser == rootCredential i.e (MINIO_ROOT_USER) will
always be an owner, you cannot generate credentials with lower
session policy to restrict their access.

This doesn't affect user service accounts created with regular
users, LDAP or OpenID
This commit is contained in:
Harshavardhana 2021-08-12 18:07:08 -07:00 committed by GitHub
parent 89febdb3d6
commit 8f2a3efa85
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 70 additions and 135 deletions

View file

@ -155,12 +155,7 @@ func validateAdminSignature(ctx context.Context, r *http.Request, region string)
return cred, nil, owner, s3Err return cred, nil, owner, s3Err
} }
claims, s3Err := checkClaimsFromToken(r, cred) return cred, cred.Claims, owner, ErrNone
if s3Err != ErrNone {
return cred, nil, owner, s3Err
}
return cred, claims, owner, ErrNone
} }
// checkAdminRequestAuth checks for authentication and authorization for the incoming // checkAdminRequestAuth checks for authentication and authorization for the incoming
@ -318,12 +313,6 @@ func checkRequestAuthTypeCredential(ctx context.Context, r *http.Request, action
return cred, owner, s3Err return cred, owner, s3Err
} }
var claims map[string]interface{}
claims, s3Err = checkClaimsFromToken(r, cred)
if s3Err != ErrNone {
return cred, owner, s3Err
}
// LocationConstraint is valid only for CreateBucketAction. // LocationConstraint is valid only for CreateBucketAction.
var locationConstraint string var locationConstraint string
if action == policy.CreateBucketAction { if action == policy.CreateBucketAction {
@ -388,10 +377,10 @@ func checkRequestAuthTypeCredential(ctx context.Context, r *http.Request, action
Groups: cred.Groups, Groups: cred.Groups,
Action: iampolicy.Action(action), Action: iampolicy.Action(action),
BucketName: bucketName, BucketName: bucketName,
ConditionValues: getConditionValues(r, "", cred.AccessKey, claims), ConditionValues: getConditionValues(r, "", cred.AccessKey, cred.Claims),
ObjectName: objectName, ObjectName: objectName,
IsOwner: owner, IsOwner: owner,
Claims: claims, Claims: cred.Claims,
}) { }) {
// Request is allowed return the appropriate access key. // Request is allowed return the appropriate access key.
return cred, owner, ErrNone return cred, owner, ErrNone
@ -405,10 +394,10 @@ func checkRequestAuthTypeCredential(ctx context.Context, r *http.Request, action
Groups: cred.Groups, Groups: cred.Groups,
Action: iampolicy.ListBucketAction, Action: iampolicy.ListBucketAction,
BucketName: bucketName, BucketName: bucketName,
ConditionValues: getConditionValues(r, "", cred.AccessKey, claims), ConditionValues: getConditionValues(r, "", cred.AccessKey, cred.Claims),
ObjectName: objectName, ObjectName: objectName,
IsOwner: owner, IsOwner: owner,
Claims: claims, Claims: cred.Claims,
}) { }) {
// Request is allowed return the appropriate access key. // Request is allowed return the appropriate access key.
return cred, owner, ErrNone return cred, owner, ErrNone
@ -520,75 +509,39 @@ func setAuthHandler(h http.Handler) http.Handler {
}) })
} }
func validateSignature(atype authType, r *http.Request) (auth.Credentials, bool, map[string]interface{}, APIErrorCode) { func validateSignature(atype authType, r *http.Request) (auth.Credentials, bool, APIErrorCode) {
var cred auth.Credentials var cred auth.Credentials
var owner bool var owner bool
var s3Err APIErrorCode var s3Err APIErrorCode
switch atype { switch atype {
case authTypeUnknown, authTypeStreamingSigned: case authTypeUnknown, authTypeStreamingSigned:
return cred, owner, nil, ErrSignatureVersionNotSupported return cred, owner, ErrSignatureVersionNotSupported
case authTypeSignedV2, authTypePresignedV2: case authTypeSignedV2, authTypePresignedV2:
if s3Err = isReqAuthenticatedV2(r); s3Err != ErrNone { if s3Err = isReqAuthenticatedV2(r); s3Err != ErrNone {
return cred, owner, nil, s3Err return cred, owner, s3Err
} }
cred, owner, s3Err = getReqAccessKeyV2(r) cred, owner, s3Err = getReqAccessKeyV2(r)
case authTypePresigned, authTypeSigned: case authTypePresigned, authTypeSigned:
region := globalServerRegion region := globalServerRegion
if s3Err = isReqAuthenticated(GlobalContext, r, region, serviceS3); s3Err != ErrNone { if s3Err = isReqAuthenticated(GlobalContext, r, region, serviceS3); s3Err != ErrNone {
return cred, owner, nil, s3Err return cred, owner, s3Err
} }
cred, owner, s3Err = getReqAccessKeyV4(r, region, serviceS3) cred, owner, s3Err = getReqAccessKeyV4(r, region, serviceS3)
} }
if s3Err != ErrNone { if s3Err != ErrNone {
return cred, owner, nil, s3Err return cred, owner, s3Err
} }
claims, s3Err := checkClaimsFromToken(r, cred) return cred, owner, ErrNone
if s3Err != ErrNone {
return cred, owner, nil, s3Err
}
return cred, owner, claims, ErrNone
} }
func isPutRetentionAllowed(bucketName, objectName string, retDays int, retDate time.Time, retMode objectlock.RetMode, byPassSet bool, r *http.Request, cred auth.Credentials, owner bool, claims map[string]interface{}) (s3Err APIErrorCode) { func isPutRetentionAllowed(bucketName, objectName string, retDays int, retDate time.Time, retMode objectlock.RetMode, byPassSet bool, r *http.Request, cred auth.Credentials, owner bool) (s3Err APIErrorCode) {
var retSet bool var retSet bool
if cred.AccessKey == "" { if cred.AccessKey == "" {
conditions := getConditionValues(r, "", "", nil)
conditions["object-lock-mode"] = []string{string(retMode)}
conditions["object-lock-retain-until-date"] = []string{retDate.Format(time.RFC3339)}
if retDays > 0 {
conditions["object-lock-remaining-retention-days"] = []string{strconv.Itoa(retDays)}
}
if retMode == objectlock.RetGovernance && byPassSet {
byPassSet = globalPolicySys.IsAllowed(policy.Args{
AccountName: cred.AccessKey,
Groups: cred.Groups,
Action: policy.BypassGovernanceRetentionAction,
BucketName: bucketName,
ConditionValues: conditions,
IsOwner: false,
ObjectName: objectName,
})
}
if globalPolicySys.IsAllowed(policy.Args{
AccountName: cred.AccessKey,
Groups: cred.Groups,
Action: policy.PutObjectRetentionAction,
BucketName: bucketName,
ConditionValues: conditions,
IsOwner: false,
ObjectName: objectName,
}) {
retSet = true
}
if byPassSet || retSet {
return ErrNone
}
return ErrAccessDenied return ErrAccessDenied
} }
conditions := getConditionValues(r, "", cred.AccessKey, claims) conditions := getConditionValues(r, "", cred.AccessKey, cred.Claims)
conditions["object-lock-mode"] = []string{string(retMode)} conditions["object-lock-mode"] = []string{string(retMode)}
conditions["object-lock-retain-until-date"] = []string{retDate.Format(time.RFC3339)} conditions["object-lock-retain-until-date"] = []string{retDate.Format(time.RFC3339)}
if retDays > 0 { if retDays > 0 {
@ -603,7 +556,7 @@ func isPutRetentionAllowed(bucketName, objectName string, retDays int, retDate t
ObjectName: objectName, ObjectName: objectName,
ConditionValues: conditions, ConditionValues: conditions,
IsOwner: owner, IsOwner: owner,
Claims: claims, Claims: cred.Claims,
}) })
} }
if globalIAMSys.IsAllowed(iampolicy.Args{ if globalIAMSys.IsAllowed(iampolicy.Args{
@ -614,7 +567,7 @@ func isPutRetentionAllowed(bucketName, objectName string, retDays int, retDate t
ConditionValues: conditions, ConditionValues: conditions,
ObjectName: objectName, ObjectName: objectName,
IsOwner: owner, IsOwner: owner,
Claims: claims, Claims: cred.Claims,
}) { }) {
retSet = true retSet = true
} }
@ -643,11 +596,6 @@ func isPutActionAllowed(ctx context.Context, atype authType, bucketName, objectN
return s3Err return s3Err
} }
claims, s3Err := checkClaimsFromToken(r, cred)
if s3Err != ErrNone {
return s3Err
}
if cred.AccessKey != "" { if cred.AccessKey != "" {
logger.GetReqInfo(ctx).AccessKey = cred.AccessKey logger.GetReqInfo(ctx).AccessKey = cred.AccessKey
} }
@ -681,10 +629,10 @@ func isPutActionAllowed(ctx context.Context, atype authType, bucketName, objectN
Groups: cred.Groups, Groups: cred.Groups,
Action: action, Action: action,
BucketName: bucketName, BucketName: bucketName,
ConditionValues: getConditionValues(r, "", cred.AccessKey, claims), ConditionValues: getConditionValues(r, "", cred.AccessKey, cred.Claims),
ObjectName: objectName, ObjectName: objectName,
IsOwner: owner, IsOwner: owner,
Claims: claims, Claims: cred.Claims,
}) { }) {
return ErrNone return ErrNone
} }

View file

@ -19,7 +19,6 @@ package cmd
import ( import (
"bytes" "bytes"
"crypto/subtle"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"encoding/xml" "encoding/xml"
@ -345,9 +344,6 @@ func (api objectAPIHandlers) ListBucketsHandler(w http.ResponseWriter, r *http.R
// Set delimiter value for "s3:delimiter" policy conditionals. // Set delimiter value for "s3:delimiter" policy conditionals.
r.Header.Set("delimiter", SlashSeparator) r.Header.Set("delimiter", SlashSeparator)
// err will be nil here as we already called this function
// earlier in this request.
claims, _ := getClaimsFromToken(getSessionToken(r))
n := 0 n := 0
// Use the following trick to filter in place // Use the following trick to filter in place
// https://github.com/golang/go/wiki/SliceTricks#filter-in-place // https://github.com/golang/go/wiki/SliceTricks#filter-in-place
@ -357,10 +353,10 @@ func (api objectAPIHandlers) ListBucketsHandler(w http.ResponseWriter, r *http.R
Groups: cred.Groups, Groups: cred.Groups,
Action: iampolicy.ListBucketAction, Action: iampolicy.ListBucketAction,
BucketName: bucketInfo.Name, BucketName: bucketInfo.Name,
ConditionValues: getConditionValues(r, "", cred.AccessKey, claims), ConditionValues: getConditionValues(r, "", cred.AccessKey, cred.Claims),
IsOwner: owner, IsOwner: owner,
ObjectName: "", ObjectName: "",
Claims: claims, Claims: cred.Claims,
}) { }) {
bucketsInfo[n] = bucketInfo bucketsInfo[n] = bucketInfo
n++ n++
@ -899,41 +895,17 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
// Once signature is validated, check if the user has // Once signature is validated, check if the user has
// explicit permissions for the user. // explicit permissions for the user.
{ if !globalIAMSys.IsAllowed(iampolicy.Args{
token := formValues.Get(xhttp.AmzSecurityToken) AccountName: cred.AccessKey,
if token != "" && cred.AccessKey == "" { Action: iampolicy.PutObjectAction,
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNoAccessKey), r.URL) ConditionValues: getConditionValues(r, "", cred.AccessKey, cred.Claims),
return BucketName: bucket,
} ObjectName: object,
IsOwner: globalActiveCred.AccessKey == cred.AccessKey,
if cred.IsServiceAccount() && token == "" { Claims: cred.Claims,
token = cred.SessionToken }) {
} writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrAccessDenied), r.URL)
return
if subtle.ConstantTimeCompare([]byte(token), []byte(cred.SessionToken)) != 1 {
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrInvalidToken), r.URL)
return
}
// Extract claims if any.
claims, err := getClaimsFromToken(token)
if err != nil {
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
return
}
if !globalIAMSys.IsAllowed(iampolicy.Args{
AccountName: cred.AccessKey,
Action: iampolicy.PutObjectAction,
ConditionValues: getConditionValues(r, "", cred.AccessKey, claims),
BucketName: bucket,
ObjectName: object,
IsOwner: globalActiveCred.AccessKey == cred.AccessKey,
Claims: claims,
}) {
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrAccessDenied), r.URL)
return
}
} }
policyBytes, err := base64.StdEncoding.DecodeString(formValues.Get("Policy")) policyBytes, err := base64.StdEncoding.DecodeString(formValues.Get("Policy"))

View file

@ -175,7 +175,7 @@ func enforceRetentionBypassForDelete(ctx context.Context, r *http.Request, bucke
// For objects in "Governance" mode, overwrite is allowed if a) object retention date is past OR // For objects in "Governance" mode, overwrite is allowed if a) object retention date is past OR
// governance bypass headers are set and user has governance bypass permissions. // governance bypass headers are set and user has governance bypass permissions.
// Objects in compliance mode can be overwritten only if retention date is being extended. No mode change is permitted. // Objects in compliance mode can be overwritten only if retention date is being extended. No mode change is permitted.
func enforceRetentionBypassForPut(ctx context.Context, r *http.Request, bucket, object string, getObjectInfoFn GetObjectInfoFn, objRetention *objectlock.ObjectRetention, cred auth.Credentials, owner bool, claims map[string]interface{}) (ObjectInfo, APIErrorCode) { func enforceRetentionBypassForPut(ctx context.Context, r *http.Request, bucket, object string, getObjectInfoFn GetObjectInfoFn, objRetention *objectlock.ObjectRetention, cred auth.Credentials, owner bool) (ObjectInfo, APIErrorCode) {
byPassSet := objectlock.IsObjectLockGovernanceBypassSet(r.Header) byPassSet := objectlock.IsObjectLockGovernanceBypassSet(r.Header)
opts, err := getOpts(ctx, r, bucket, object) opts, err := getOpts(ctx, r, bucket, object)
if err != nil { if err != nil {
@ -203,7 +203,7 @@ func enforceRetentionBypassForPut(ctx context.Context, r *http.Request, bucket,
perm := isPutRetentionAllowed(bucket, object, perm := isPutRetentionAllowed(bucket, object,
days, objRetention.RetainUntilDate.Time, days, objRetention.RetainUntilDate.Time,
objRetention.Mode, byPassSet, r, cred, objRetention.Mode, byPassSet, r, cred,
owner, claims) owner)
return oi, perm return oi, perm
} }
@ -211,7 +211,7 @@ func enforceRetentionBypassForPut(ctx context.Context, r *http.Request, bucket,
case objectlock.RetGovernance: case objectlock.RetGovernance:
govPerm := isPutRetentionAllowed(bucket, object, days, govPerm := isPutRetentionAllowed(bucket, object, days,
objRetention.RetainUntilDate.Time, objRetention.Mode, objRetention.RetainUntilDate.Time, objRetention.Mode,
byPassSet, r, cred, owner, claims) byPassSet, r, cred, owner)
// Governance mode retention period cannot be shortened, if x-amz-bypass-governance is not set. // Governance mode retention period cannot be shortened, if x-amz-bypass-governance is not set.
if !byPassSet { if !byPassSet {
if objRetention.Mode != objectlock.RetGovernance || objRetention.RetainUntilDate.Before((ret.RetainUntilDate.Time)) { if objRetention.Mode != objectlock.RetGovernance || objRetention.RetainUntilDate.Before((ret.RetainUntilDate.Time)) {
@ -227,7 +227,7 @@ func enforceRetentionBypassForPut(ctx context.Context, r *http.Request, bucket,
} }
compliancePerm := isPutRetentionAllowed(bucket, object, compliancePerm := isPutRetentionAllowed(bucket, object,
days, objRetention.RetainUntilDate.Time, objRetention.Mode, days, objRetention.RetainUntilDate.Time, objRetention.Mode,
false, r, cred, owner, claims) false, r, cred, owner)
return oi, compliancePerm return oi, compliancePerm
} }
return oi, ErrNone return oi, ErrNone
@ -235,7 +235,7 @@ func enforceRetentionBypassForPut(ctx context.Context, r *http.Request, bucket,
perm := isPutRetentionAllowed(bucket, object, perm := isPutRetentionAllowed(bucket, object,
days, objRetention.RetainUntilDate.Time, days, objRetention.RetainUntilDate.Time,
objRetention.Mode, byPassSet, r, cred, owner, claims) objRetention.Mode, byPassSet, r, cred, owner)
return oi, perm return oi, perm
} }

View file

@ -3502,7 +3502,7 @@ func (api objectAPIHandlers) PutObjectRetentionHandler(w http.ResponseWriter, r
return return
} }
cred, owner, claims, s3Err := validateSignature(getRequestAuthType(r), r) cred, owner, s3Err := validateSignature(getRequestAuthType(r), r)
if s3Err != ErrNone { if s3Err != ErrNone {
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Err), r.URL) writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Err), r.URL)
return return
@ -3542,7 +3542,7 @@ func (api objectAPIHandlers) PutObjectRetentionHandler(w http.ResponseWriter, r
getObjectInfo = api.CacheAPI().GetObjectInfo getObjectInfo = api.CacheAPI().GetObjectInfo
} }
objInfo, s3Err := enforceRetentionBypassForPut(ctx, r, bucket, object, getObjectInfo, objRetention, cred, owner, claims) objInfo, s3Err := enforceRetentionBypassForPut(ctx, r, bucket, object, getObjectInfo, objRetention, cred, owner)
if s3Err != ErrNone { if s3Err != ErrNone {
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Err), r.URL) writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Err), r.URL)
return return

View file

@ -78,7 +78,9 @@ const (
// http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html#RESTAuthenticationStringToSign // http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html#RESTAuthenticationStringToSign
func doesPolicySignatureV2Match(formValues http.Header) (auth.Credentials, APIErrorCode) { func doesPolicySignatureV2Match(formValues http.Header) (auth.Credentials, APIErrorCode) {
accessKey := formValues.Get(xhttp.AmzAccessKeyID) accessKey := formValues.Get(xhttp.AmzAccessKeyID)
cred, _, s3Err := checkKeyValid(accessKey)
r := &http.Request{Header: formValues}
cred, _, s3Err := checkKeyValid(r, accessKey)
if s3Err != ErrNone { if s3Err != ErrNone {
return cred, s3Err return cred, s3Err
} }
@ -153,7 +155,7 @@ func doesPresignV2SignatureMatch(r *http.Request) APIErrorCode {
return ErrInvalidQueryParams return ErrInvalidQueryParams
} }
cred, _, s3Err := checkKeyValid(accessKey) cred, _, s3Err := checkKeyValid(r, accessKey)
if s3Err != ErrNone { if s3Err != ErrNone {
return s3Err return s3Err
} }
@ -184,7 +186,7 @@ func doesPresignV2SignatureMatch(r *http.Request) APIErrorCode {
func getReqAccessKeyV2(r *http.Request) (auth.Credentials, bool, APIErrorCode) { func getReqAccessKeyV2(r *http.Request) (auth.Credentials, bool, APIErrorCode) {
if accessKey := r.Form.Get(xhttp.AmzAccessKeyID); accessKey != "" { if accessKey := r.Form.Get(xhttp.AmzAccessKeyID); accessKey != "" {
return checkKeyValid(accessKey) return checkKeyValid(r, accessKey)
} }
// below is V2 Signed Auth header format, splitting on `space` (after the `AWS` string). // below is V2 Signed Auth header format, splitting on `space` (after the `AWS` string).
@ -200,7 +202,7 @@ func getReqAccessKeyV2(r *http.Request) (auth.Credentials, bool, APIErrorCode) {
return auth.Credentials{}, false, ErrMissingFields return auth.Credentials{}, false, ErrMissingFields
} }
return checkKeyValid(keySignFields[0]) return checkKeyValid(r, keySignFields[0])
} }
// Authorization = "AWS" + " " + AWSAccessKeyId + ":" + Signature; // Authorization = "AWS" + " " + AWSAccessKeyId + ":" + Signature;

View file

@ -63,7 +63,7 @@ func getReqAccessKeyV4(r *http.Request, region string, stype serviceType) (auth.
return auth.Credentials{}, false, s3Err return auth.Credentials{}, false, s3Err
} }
} }
return checkKeyValid(ch.accessKey) return checkKeyValid(r, ch.accessKey)
} }
// parse credentialHeader string into its structured form. // parse credentialHeader string into its structured form.

View file

@ -31,6 +31,7 @@ import (
"github.com/minio/minio/internal/auth" "github.com/minio/minio/internal/auth"
xhttp "github.com/minio/minio/internal/http" xhttp "github.com/minio/minio/internal/http"
"github.com/minio/minio/internal/logger" "github.com/minio/minio/internal/logger"
iampolicy "github.com/minio/pkg/iam/policy"
) )
// http Header "x-amz-content-sha256" == "UNSIGNED-PAYLOAD" indicates that the // http Header "x-amz-content-sha256" == "UNSIGNED-PAYLOAD" indicates that the
@ -120,7 +121,7 @@ func isValidRegion(reqRegion string, confRegion string) bool {
// check if the access key is valid and recognized, additionally // check if the access key is valid and recognized, additionally
// also returns if the access key is owner/admin. // also returns if the access key is owner/admin.
func checkKeyValid(accessKey string) (auth.Credentials, bool, APIErrorCode) { func checkKeyValid(r *http.Request, accessKey string) (auth.Credentials, bool, APIErrorCode) {
if !globalIAMSys.Initialized() && !globalIsGateway { if !globalIAMSys.Initialized() && !globalIsGateway {
// Check if server has initialized, then only proceed // Check if server has initialized, then only proceed
// to check for IAM users otherwise its okay for clients // to check for IAM users otherwise its okay for clients
@ -135,7 +136,17 @@ func checkKeyValid(accessKey string) (auth.Credentials, bool, APIErrorCode) {
if !ok { if !ok {
return cred, false, ErrInvalidAccessKeyID return cred, false, ErrInvalidAccessKeyID
} }
owner = cred.AccessKey == ucred.ParentUser claims, s3Err := checkClaimsFromToken(r, cred)
if s3Err != ErrNone {
return cred, false, s3Err
}
ucred.Claims = claims
// Now check if we have a sessionPolicy.
if _, ok = claims[iampolicy.SessionPolicyName]; ok {
owner = false
} else {
owner = cred.AccessKey == ucred.ParentUser
}
cred = ucred cred = ucred
} }
return cred, owner, ErrNone return cred, owner, ErrNone

View file

@ -181,7 +181,8 @@ func doesPolicySignatureV4Match(formValues http.Header) (auth.Credentials, APIEr
return auth.Credentials{}, s3Err return auth.Credentials{}, s3Err
} }
cred, _, s3Err := checkKeyValid(credHeader.accessKey) r := &http.Request{Header: formValues}
cred, _, s3Err := checkKeyValid(r, credHeader.accessKey)
if s3Err != ErrNone { if s3Err != ErrNone {
return cred, s3Err return cred, s3Err
} }
@ -214,7 +215,7 @@ func doesPresignedSignatureMatch(hashedPayload string, r *http.Request, region s
return err return err
} }
cred, _, s3Err := checkKeyValid(pSignValues.Credential.accessKey) cred, _, s3Err := checkKeyValid(r, pSignValues.Credential.accessKey)
if s3Err != ErrNone { if s3Err != ErrNone {
return s3Err return s3Err
} }
@ -349,7 +350,7 @@ func doesSignatureMatch(hashedPayload string, r *http.Request, region string, st
return errCode return errCode
} }
cred, _, s3Err := checkKeyValid(signV4Values.Credential.accessKey) cred, _, s3Err := checkKeyValid(r, signV4Values.Credential.accessKey)
if s3Err != ErrNone { if s3Err != ErrNone {
return s3Err return s3Err
} }

View file

@ -93,7 +93,7 @@ func calculateSeedSignature(r *http.Request) (cred auth.Credentials, signature s
return cred, "", "", time.Time{}, errCode return cred, "", "", time.Time{}, errCode
} }
cred, _, errCode = checkKeyValid(signV4Values.Credential.accessKey) cred, _, errCode = checkKeyValid(r, signV4Values.Credential.accessKey)
if errCode != ErrNone { if errCode != ErrNone {
return cred, "", "", time.Time{}, errCode return cred, "", "", time.Time{}, errCode
} }

View file

@ -94,13 +94,14 @@ const (
// Credentials holds access and secret keys. // Credentials holds access and secret keys.
type Credentials struct { type Credentials struct {
AccessKey string `xml:"AccessKeyId" json:"accessKey,omitempty"` AccessKey string `xml:"AccessKeyId" json:"accessKey,omitempty"`
SecretKey string `xml:"SecretAccessKey" json:"secretKey,omitempty"` SecretKey string `xml:"SecretAccessKey" json:"secretKey,omitempty"`
Expiration time.Time `xml:"Expiration" json:"expiration,omitempty"` Expiration time.Time `xml:"Expiration" json:"expiration,omitempty"`
SessionToken string `xml:"SessionToken" json:"sessionToken,omitempty"` SessionToken string `xml:"SessionToken" json:"sessionToken,omitempty"`
Status string `xml:"-" json:"status,omitempty"` Status string `xml:"-" json:"status,omitempty"`
ParentUser string `xml:"-" json:"parentUser,omitempty"` ParentUser string `xml:"-" json:"parentUser,omitempty"`
Groups []string `xml:"-" json:"groups,omitempty"` Groups []string `xml:"-" json:"groups,omitempty"`
Claims map[string]interface{} `xml:"-" json:"claims,omitempty"`
} }
func (cred Credentials) String() string { func (cred Credentials) String() string {