Add NTP retention time (#8548)

master
Harshavardhana 5 years ago committed by Nitish Tiwari
parent 4e9de58675
commit fd0fa4e5c5
  1. 74
      cmd/object-lock.go
  2. 12
      cmd/utils.go
  3. 1
      go.mod
  4. 2
      go.sum

@ -28,6 +28,8 @@ import (
"time" "time"
xhttp "github.com/minio/minio/cmd/http" xhttp "github.com/minio/minio/cmd/http"
"github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/env"
) )
// RetentionMode - object retention mode. // RetentionMode - object retention mode.
@ -65,6 +67,14 @@ var (
errObjectLockInvalidHeaders = errors.New("x-amz-object-lock-retain-until-date and x-amz-object-lock-mode must both be supplied") errObjectLockInvalidHeaders = errors.New("x-amz-object-lock-retain-until-date and x-amz-object-lock-mode must both be supplied")
) )
const (
ntpServerEnv = "MINIO_NTP_SERVER"
)
var (
ntpServer = env.Get(ntpServerEnv, "")
)
// Retention - bucket level retention configuration. // Retention - bucket level retention configuration.
type Retention struct { type Retention struct {
Mode RetentionMode Mode RetentionMode
@ -78,7 +88,13 @@ func (r Retention) IsEmpty() bool {
// Retain - check whether given date is retainable by validity time. // Retain - check whether given date is retainable by validity time.
func (r Retention) Retain(created time.Time) bool { func (r Retention) Retain(created time.Time) bool {
return globalWORMEnabled || created.Add(r.Validity).After(time.Now()) t, err := UTCNowNTP()
if err != nil {
logger.LogIf(context.Background(), err)
// Retain
return true
}
return globalWORMEnabled || created.Add(r.Validity).After(t)
} }
// BucketObjectLockConfig - map of bucket and retention configuration. // BucketObjectLockConfig - map of bucket and retention configuration.
@ -205,11 +221,19 @@ func (config *ObjectLockConfig) UnmarshalXML(d *xml.Decoder, start xml.StartElem
func (config *ObjectLockConfig) ToRetention() (r Retention) { func (config *ObjectLockConfig) ToRetention() (r Retention) {
if config.Rule != nil { if config.Rule != nil {
r.Mode = config.Rule.DefaultRetention.Mode r.Mode = config.Rule.DefaultRetention.Mode
utcNow := time.Now().UTC()
t, err := UTCNowNTP()
if err != nil {
logger.LogIf(context.Background(), err)
// Do not change any configuration
// upon NTP failure.
return r
}
if config.Rule.DefaultRetention.Days != nil { if config.Rule.DefaultRetention.Days != nil {
r.Validity = utcNow.AddDate(0, 0, int(*config.Rule.DefaultRetention.Days)).Sub(utcNow) r.Validity = t.AddDate(0, 0, int(*config.Rule.DefaultRetention.Days)).Sub(t)
} else { } else {
r.Validity = utcNow.AddDate(int(*config.Rule.DefaultRetention.Years), 0, 0).Sub(utcNow) r.Validity = t.AddDate(int(*config.Rule.DefaultRetention.Years), 0, 0).Sub(t)
} }
} }
@ -282,9 +306,17 @@ func parseObjectRetention(reader io.Reader) (*ObjectRetention, error) {
if ret.Mode != Compliance && ret.Mode != Governance { if ret.Mode != Compliance && ret.Mode != Governance {
return &ret, errUnknownWORMModeDirective return &ret, errUnknownWORMModeDirective
} }
if ret.RetainUntilDate.Before(time.Now()) {
t, err := UTCNowNTP()
if err != nil {
logger.LogIf(context.Background(), err)
return &ret, errPastObjectLockRetainDate
}
if ret.RetainUntilDate.Before(t) {
return &ret, errPastObjectLockRetainDate return &ret, errPastObjectLockRetainDate
} }
return &ret, nil return &ret, nil
} }
@ -334,7 +366,14 @@ func parseObjectLockRetentionHeaders(h http.Header) (rmode RetentionMode, r Rete
if err != nil { if err != nil {
return rmode, r, errInvalidRetentionDate return rmode, r, errInvalidRetentionDate
} }
if retDate.Before(time.Now()) {
t, err := UTCNowNTP()
if err != nil {
logger.LogIf(context.Background(), err)
return rmode, r, errPastObjectLockRetainDate
}
if retDate.Before(t) {
return rmode, r, errPastObjectLockRetainDate return rmode, r, errPastObjectLockRetainDate
} }
} }
@ -392,7 +431,12 @@ func checkGovernanceBypassAllowed(ctx context.Context, r *http.Request, bucket,
} }
if ret.Mode == Governance { if ret.Mode == Governance {
if !isObjectLockGovernanceBypassSet(r.Header) { if !isObjectLockGovernanceBypassSet(r.Header) {
if ret.RetainUntilDate.After(UTCNow()) { t, err := UTCNowNTP()
if err != nil {
logger.LogIf(ctx, err)
return oi, ErrObjectLocked
}
if ret.RetainUntilDate.After(t) {
return oi, ErrObjectLocked return oi, ErrObjectLocked
} }
return oi, ErrNone return oi, ErrNone
@ -440,7 +484,12 @@ func checkPutObjectRetentionAllowed(ctx context.Context, r *http.Request, bucket
return mode, retainDate, toAPIErrorCode(ctx, err) return mode, retainDate, toAPIErrorCode(ctx, err)
} }
// AWS S3 just creates a new version of object when an object is being overwritten. // AWS S3 just creates a new version of object when an object is being overwritten.
if objExists && retainDate.After(UTCNow()) { t, err := UTCNowNTP()
if err != nil {
logger.LogIf(ctx, err)
return mode, retainDate, ErrObjectLocked
}
if objExists && retainDate.After(t) {
return mode, retainDate, ErrObjectLocked return mode, retainDate, ErrObjectLocked
} }
if rMode == Invalid { if rMode == Invalid {
@ -455,12 +504,17 @@ func checkPutObjectRetentionAllowed(ctx context.Context, r *http.Request, bucket
if retentionPermErr != ErrNone { if retentionPermErr != ErrNone {
return mode, retainDate, retentionPermErr return mode, retainDate, retentionPermErr
} }
t, err := UTCNowNTP()
if err != nil {
logger.LogIf(ctx, err)
return mode, retainDate, ErrObjectLocked
}
// AWS S3 just creates a new version of object when an object is being overwritten. // AWS S3 just creates a new version of object when an object is being overwritten.
if objExists && retainDate.After(UTCNow()) { if objExists && retainDate.After(t) {
return mode, retainDate, ErrObjectLocked return mode, retainDate, ErrObjectLocked
} }
// inherit retention from bucket configuration // inherit retention from bucket configuration
return retention.Mode, RetentionDate{UTCNow().Add(retention.Validity)}, ErrNone return retention.Mode, RetentionDate{t.Add(retention.Validity)}, ErrNone
} }
return mode, retainDate, ErrNone return mode, retainDate, ErrNone
} }

@ -35,6 +35,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/beevik/ntp"
xhttp "github.com/minio/minio/cmd/http" xhttp "github.com/minio/minio/cmd/http"
"github.com/minio/minio/cmd/logger" "github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/handlers" "github.com/minio/minio/pkg/handlers"
@ -314,6 +315,17 @@ func UTCNow() time.Time {
return time.Now().UTC() return time.Now().UTC()
} }
// UTCNowNTP - is similar in functionality to UTCNow()
// but only used when we do not wish to rely on system
// time.
func UTCNowNTP() (time.Time, error) {
// ntp server is disabled
if ntpServer == "" {
return UTCNow(), nil
}
return ntp.Time(ntpServer)
}
// GenETag - generate UUID based ETag // GenETag - generate UUID based ETag
func GenETag() string { func GenETag() string {
return ToS3ETag(getMD5Hash([]byte(mustGetUUID()))) return ToS3ETag(getMD5Hash([]byte(mustGetUUID())))

@ -11,6 +11,7 @@ require (
github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5 github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5
github.com/aws/aws-sdk-go v1.20.21 github.com/aws/aws-sdk-go v1.20.21
github.com/bcicen/jstream v0.0.0-20190220045926-16c1f8af81c2 github.com/bcicen/jstream v0.0.0-20190220045926-16c1f8af81c2
github.com/beevik/ntp v0.2.0
github.com/cheggaaa/pb v1.0.28 github.com/cheggaaa/pb v1.0.28
github.com/coredns/coredns v1.4.0 github.com/coredns/coredns v1.4.0
github.com/coreos/etcd v3.3.12+incompatible github.com/coreos/etcd v3.3.12+incompatible

@ -63,6 +63,8 @@ github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f h1:ZNv7
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc= github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc=
github.com/bcicen/jstream v0.0.0-20190220045926-16c1f8af81c2 h1:M+TYzBcNIRyzPRg66ndEqUMd7oWDmhvdQmaPC6EZNwM= github.com/bcicen/jstream v0.0.0-20190220045926-16c1f8af81c2 h1:M+TYzBcNIRyzPRg66ndEqUMd7oWDmhvdQmaPC6EZNwM=
github.com/bcicen/jstream v0.0.0-20190220045926-16c1f8af81c2/go.mod h1:RDu/qcrnpEdJC/p8tx34+YBFqqX71lB7dOX9QE+ZC4M= github.com/bcicen/jstream v0.0.0-20190220045926-16c1f8af81c2/go.mod h1:RDu/qcrnpEdJC/p8tx34+YBFqqX71lB7dOX9QE+ZC4M=
github.com/beevik/ntp v0.2.0 h1:sGsd+kAXzT0bfVfzJfce04g+dSRfrs+tbQW8lweuYgw=
github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=

Loading…
Cancel
Save