mirror of https://github.com/minio/minio.git
fix: object lock behavior when default lock config is enabled (#9305)
This commit is contained in:
parent
cc9b63eb51
commit
1fa65c7f2f
|
@ -151,6 +151,7 @@ const (
|
||||||
ErrBadRequest
|
ErrBadRequest
|
||||||
ErrKeyTooLongError
|
ErrKeyTooLongError
|
||||||
ErrInvalidBucketObjectLockConfiguration
|
ErrInvalidBucketObjectLockConfiguration
|
||||||
|
ErrObjectLockConfigurationNotFound
|
||||||
ErrObjectLockConfigurationNotAllowed
|
ErrObjectLockConfigurationNotAllowed
|
||||||
ErrNoSuchObjectLockConfiguration
|
ErrNoSuchObjectLockConfiguration
|
||||||
ErrObjectLocked
|
ErrObjectLocked
|
||||||
|
@ -765,9 +766,14 @@ var errorCodes = errorCodeMap{
|
||||||
Description: "Bucket is missing ObjectLockConfiguration",
|
Description: "Bucket is missing ObjectLockConfiguration",
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
|
ErrObjectLockConfigurationNotFound: {
|
||||||
|
Code: "ObjectLockConfigurationNotFoundError",
|
||||||
|
Description: "Object Lock configuration does not exist for this bucket",
|
||||||
|
HTTPStatusCode: http.StatusNotFound,
|
||||||
|
},
|
||||||
ErrObjectLockConfigurationNotAllowed: {
|
ErrObjectLockConfigurationNotAllowed: {
|
||||||
Code: "InvalidBucketState",
|
Code: "InvalidBucketState",
|
||||||
Description: "Object Lock configuration cannot be enabled on existing buckets.",
|
Description: "Object Lock configuration cannot be enabled on existing buckets",
|
||||||
HTTPStatusCode: http.StatusConflict,
|
HTTPStatusCode: http.StatusConflict,
|
||||||
},
|
},
|
||||||
ErrNoSuchObjectLockConfiguration: {
|
ErrNoSuchObjectLockConfiguration: {
|
||||||
|
|
|
@ -591,6 +591,15 @@ func isPutActionAllowed(atype authType, bucketName, objectName string, r *http.R
|
||||||
return s3Err
|
return s3Err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do not check for PutObjectRetentionAction permission,
|
||||||
|
// if mode and retain until date are not set.
|
||||||
|
// Can happen when bucket has default lock config set
|
||||||
|
if action == iampolicy.PutObjectRetentionAction &&
|
||||||
|
r.Header.Get(xhttp.AmzObjectLockMode) == "" &&
|
||||||
|
r.Header.Get(xhttp.AmzObjectLockRetainUntilDate) == "" {
|
||||||
|
return ErrNone
|
||||||
|
}
|
||||||
|
|
||||||
if cred.AccessKey == "" {
|
if cred.AccessKey == "" {
|
||||||
if globalPolicySys.IsAllowed(policy.Args{
|
if globalPolicySys.IsAllowed(policy.Args{
|
||||||
AccountName: cred.AccessKey,
|
AccountName: cred.AccessKey,
|
||||||
|
|
|
@ -1103,7 +1103,7 @@ func (api objectAPIHandlers) GetBucketObjectLockConfigHandler(w http.ResponseWri
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var aerr APIError
|
var aerr APIError
|
||||||
if err == errConfigNotFound {
|
if err == errConfigNotFound {
|
||||||
aerr = errorCodes.ToAPIErr(ErrMethodNotAllowed)
|
aerr = errorCodes.ToAPIErr(ErrObjectLockConfigurationNotFound)
|
||||||
} else {
|
} else {
|
||||||
aerr = toAPIError(ctx, err)
|
aerr = toAPIError(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1029,11 +1029,11 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re
|
||||||
// apply default bucket configuration/governance headers for dest side.
|
// apply default bucket configuration/governance headers for dest side.
|
||||||
retentionMode, retentionDate, legalHold, s3Err := checkPutObjectLockAllowed(ctx, r, dstBucket, dstObject, getObjectInfo, retPerms, holdPerms)
|
retentionMode, retentionDate, legalHold, s3Err := checkPutObjectLockAllowed(ctx, r, dstBucket, dstObject, getObjectInfo, retPerms, holdPerms)
|
||||||
if s3Err == ErrNone && retentionMode.Valid() {
|
if s3Err == ErrNone && retentionMode.Valid() {
|
||||||
srcInfo.UserDefined[xhttp.AmzObjectLockMode] = string(retentionMode)
|
srcInfo.UserDefined[strings.ToLower(xhttp.AmzObjectLockMode)] = string(retentionMode)
|
||||||
srcInfo.UserDefined[xhttp.AmzObjectLockRetainUntilDate] = retentionDate.UTC().Format(time.RFC3339)
|
srcInfo.UserDefined[strings.ToLower(xhttp.AmzObjectLockRetainUntilDate)] = retentionDate.UTC().Format(time.RFC3339)
|
||||||
}
|
}
|
||||||
if s3Err == ErrNone && legalHold.Status.Valid() {
|
if s3Err == ErrNone && legalHold.Status.Valid() {
|
||||||
srcInfo.UserDefined[xhttp.AmzObjectLockLegalHold] = string(legalHold.Status)
|
srcInfo.UserDefined[strings.ToLower(xhttp.AmzObjectLockLegalHold)] = string(legalHold.Status)
|
||||||
}
|
}
|
||||||
if s3Err != ErrNone {
|
if s3Err != ErrNone {
|
||||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Err), r.URL, guessIsBrowserReq(r))
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Err), r.URL, guessIsBrowserReq(r))
|
||||||
|
@ -2398,11 +2398,7 @@ func (api objectAPIHandlers) CompleteMultipartUploadHandler(w http.ResponseWrite
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enforce object lock governance in case a competing upload finalized first.
|
if _, _, _, s3Err := checkPutObjectLockAllowed(ctx, r, bucket, object, objectAPI.GetObjectInfo, ErrNone, ErrNone); s3Err != ErrNone {
|
||||||
retPerms := isPutActionAllowed(getRequestAuthType(r), bucket, object, r, iampolicy.PutObjectRetentionAction)
|
|
||||||
holdPerms := isPutActionAllowed(getRequestAuthType(r), bucket, object, r, iampolicy.PutObjectLegalHoldAction)
|
|
||||||
|
|
||||||
if _, _, _, s3Err := checkPutObjectLockAllowed(ctx, r, bucket, object, objectAPI.GetObjectInfo, retPerms, holdPerms); s3Err != ErrNone {
|
|
||||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Err), r.URL, guessIsBrowserReq(r))
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Err), r.URL, guessIsBrowserReq(r))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -335,7 +335,7 @@ func (web *webAPIHandlers) ListBuckets(r *http.Request, args *WebGenericArgs, re
|
||||||
for _, bucket := range buckets {
|
for _, bucket := range buckets {
|
||||||
if globalIAMSys.IsAllowed(iampolicy.Args{
|
if globalIAMSys.IsAllowed(iampolicy.Args{
|
||||||
AccountName: claims.AccessKey,
|
AccountName: claims.AccessKey,
|
||||||
Action: iampolicy.ListBucketAction,
|
Action: iampolicy.ListAllMyBucketsAction,
|
||||||
BucketName: bucket.Name,
|
BucketName: bucket.Name,
|
||||||
ConditionValues: getConditionValues(r, "", claims.AccessKey, claims.Map()),
|
ConditionValues: getConditionValues(r, "", claims.AccessKey, claims.Map()),
|
||||||
IsOwner: owner,
|
IsOwner: owner,
|
||||||
|
|
|
@ -459,10 +459,21 @@ func GetObjectRetentionMeta(meta map[string]string) ObjectRetention {
|
||||||
var mode RetMode
|
var mode RetMode
|
||||||
var retainTill RetentionDate
|
var retainTill RetentionDate
|
||||||
|
|
||||||
if modeStr, ok := meta[strings.ToLower(AmzObjectLockMode)]; ok {
|
var modeStr, tillStr string
|
||||||
|
ok := false
|
||||||
|
|
||||||
|
modeStr, ok = meta[strings.ToLower(AmzObjectLockMode)]
|
||||||
|
if !ok {
|
||||||
|
modeStr, ok = meta[AmzObjectLockMode]
|
||||||
|
}
|
||||||
|
if ok {
|
||||||
mode = parseRetMode(modeStr)
|
mode = parseRetMode(modeStr)
|
||||||
}
|
}
|
||||||
if tillStr, ok := meta[strings.ToLower(AmzObjectLockRetainUntilDate)]; ok {
|
tillStr, ok = meta[strings.ToLower(AmzObjectLockRetainUntilDate)]
|
||||||
|
if !ok {
|
||||||
|
tillStr, ok = meta[AmzObjectLockRetainUntilDate]
|
||||||
|
}
|
||||||
|
if ok {
|
||||||
if t, e := time.Parse(time.RFC3339, tillStr); e == nil {
|
if t, e := time.Parse(time.RFC3339, tillStr); e == nil {
|
||||||
retainTill = RetentionDate{t.UTC()}
|
retainTill = RetentionDate{t.UTC()}
|
||||||
}
|
}
|
||||||
|
@ -473,6 +484,9 @@ func GetObjectRetentionMeta(meta map[string]string) ObjectRetention {
|
||||||
// GetObjectLegalHoldMeta constructs ObjectLegalHold from metadata
|
// GetObjectLegalHoldMeta constructs ObjectLegalHold from metadata
|
||||||
func GetObjectLegalHoldMeta(meta map[string]string) ObjectLegalHold {
|
func GetObjectLegalHoldMeta(meta map[string]string) ObjectLegalHold {
|
||||||
holdStr, ok := meta[strings.ToLower(AmzObjectLockLegalHold)]
|
holdStr, ok := meta[strings.ToLower(AmzObjectLockLegalHold)]
|
||||||
|
if !ok {
|
||||||
|
holdStr, ok = meta[AmzObjectLockLegalHold]
|
||||||
|
}
|
||||||
if ok {
|
if ok {
|
||||||
return ObjectLegalHold{XMLNS: "http://s3.amazonaws.com/doc/2006-03-01/", Status: parseLegalHoldStatus(holdStr)}
|
return ObjectLegalHold{XMLNS: "http://s3.amazonaws.com/doc/2006-03-01/", Status: parseLegalHoldStatus(holdStr)}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue