mirror of
https://github.com/cubefs/cubefs.git
synced 2026-08-02 10:06:14 +00:00
1. sts federation token 2. signature auth code refactor Signed-off-by: yhjiango <jiangyunhua@oppo.com>
208 lines
5.9 KiB
Go
208 lines
5.9 KiB
Go
// Copyright 2023 The CubeFS Authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
// implied. See the License for the specific language governing
|
|
// permissions and limitations under the License.
|
|
|
|
package objectnode
|
|
|
|
import (
|
|
"encoding/xml"
|
|
"errors"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/cubefs/cubefs/util/log"
|
|
)
|
|
|
|
var (
|
|
InvalidModeErr = errors.New("Invalid Retention Mode")
|
|
RetentionPeriodsTooLargeErr = errors.New("Default retention period is too large")
|
|
NonPositiveRetentionPeriodsErr = errors.New("Default retention period must be a positive integer value")
|
|
BothDaysAndYearsSpecifiedErr = errors.New("Either Days or Years must be specified, cannot be specified both at the same time")
|
|
EitherDaysOrYearsSpecifiedErr = errors.New("Either Days or Years must be specified")
|
|
InvalidObjectLockEnabledErr = errors.New("Only Enabled value is allowd to ObjectLockEnabled element")
|
|
NilDefaultRetentionErr = errors.New("Default retention cannot be nil")
|
|
NilDefaultRuleErr = errors.New("Default rule cannot be nil")
|
|
)
|
|
|
|
const (
|
|
ComplianceMode = "COMPLIANCE"
|
|
Enabled = "Enabled"
|
|
|
|
MaxObjectLockSize = 1 << 12 // 16KB
|
|
maximumRetentionDays = 70 * 365
|
|
maximumRetentionYears = 70
|
|
nanosecondsPerDay = 24 * 60 * 60 * 1e9
|
|
)
|
|
|
|
type ObjectLockConfig struct {
|
|
XMLNS string `xml:"xmlns,attr,omitempty" json:"-" `
|
|
XMLName *xml.Name `xml:"ObjectLockConfiguration" json:"-" `
|
|
ObjectLockEnabled string `xml:"ObjectLockEnabled" json:"object_lock_enabled,omitempty" `
|
|
Rule *ObjectLockRule `xml:"Rule,omitempty" json:"rule,omitempty"`
|
|
}
|
|
|
|
type ObjectLockRule struct {
|
|
DefaultRetention *DefaultRetention `xml:"DefaultRetention" json:"default_retention" `
|
|
}
|
|
|
|
type DefaultRetention struct {
|
|
XMLName *xml.Name `xml:"DefaultRetention" json:"-"`
|
|
Mode string `xml:"Mode" json:"mode"`
|
|
Days *int64 `xml:"Days,omitempty" json:"days,omitempty" `
|
|
Years *int64 `xml:"Years,omitempty" json:"years,omitempty"`
|
|
}
|
|
|
|
func (c *ObjectLockConfig) CheckValid() error {
|
|
if c.IsEmpty() {
|
|
return nil
|
|
}
|
|
|
|
if c.ObjectLockEnabled != Enabled {
|
|
return InvalidObjectLockEnabledErr
|
|
}
|
|
|
|
if c.Rule == nil {
|
|
return NilDefaultRuleErr
|
|
}
|
|
|
|
if c.Rule != nil && c.Rule.DefaultRetention == nil {
|
|
return NilDefaultRetentionErr
|
|
}
|
|
|
|
if err := c.Rule.DefaultRetention.isValid(); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type Retention struct {
|
|
Mode string
|
|
Duration time.Duration
|
|
}
|
|
|
|
func (c ObjectLockConfig) ToRetention() (r *Retention) {
|
|
if c.Rule != nil {
|
|
r = &Retention{}
|
|
r.Mode = c.Rule.DefaultRetention.Mode
|
|
|
|
if c.Rule.DefaultRetention.Days != nil {
|
|
r.Duration = time.Duration(nanosecondsPerDay * (*c.Rule.DefaultRetention.Days))
|
|
} else {
|
|
r.Duration = time.Duration(nanosecondsPerDay*(*c.Rule.DefaultRetention.Years)) * 365
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// check whether ObjectLockConfig is empty
|
|
func (c ObjectLockConfig) IsEmpty() bool {
|
|
return c.ObjectLockEnabled == "" && c.Rule == nil
|
|
}
|
|
|
|
// parse ObjectLockConfig from xml
|
|
func ParseObjectLockConfigFromXML(data []byte) (*ObjectLockConfig, error) {
|
|
config := ObjectLockConfig{}
|
|
if err := xml.Unmarshal(data, &config); err != nil {
|
|
return nil, NewError("InvalidObjectLockConfiguration", err.Error(), 400)
|
|
}
|
|
err := config.CheckValid()
|
|
if err != nil {
|
|
return nil, NewError("InvalidObjectLockConfiguration", err.Error(), 400)
|
|
}
|
|
return &config, nil
|
|
}
|
|
|
|
// check valid of DefaultRetention
|
|
func (d DefaultRetention) isValid() error {
|
|
switch d.Mode {
|
|
case ComplianceMode:
|
|
default:
|
|
return InvalidModeErr
|
|
}
|
|
if d.Days == nil && d.Years == nil {
|
|
return EitherDaysOrYearsSpecifiedErr
|
|
}
|
|
|
|
if d.Days != nil && d.Years != nil {
|
|
return BothDaysAndYearsSpecifiedErr
|
|
}
|
|
|
|
if d.Days != nil {
|
|
if *d.Days <= 0 {
|
|
return NonPositiveRetentionPeriodsErr
|
|
}
|
|
if *d.Days > maximumRetentionDays {
|
|
return RetentionPeriodsTooLargeErr
|
|
}
|
|
}
|
|
if d.Years != nil {
|
|
if *d.Years <= 0 {
|
|
return NonPositiveRetentionPeriodsErr
|
|
}
|
|
if *d.Years > maximumRetentionYears {
|
|
return RetentionPeriodsTooLargeErr
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type ObjectRetention struct {
|
|
XMLNS string `xml:"xmlns,attr,omitempty"`
|
|
XMLName xml.Name `xml:"Retention"`
|
|
Mode string `xml:"Mode,omitempty"`
|
|
RetainUntilDate RetentionDate `xml:"RetainUntilDate,omitempty"`
|
|
}
|
|
|
|
type RetentionDate struct {
|
|
time.Time
|
|
}
|
|
|
|
func (r RetentionDate) MarshalXML(e *xml.Encoder, startElement xml.StartElement) error {
|
|
if r == (RetentionDate{time.Time{}}) {
|
|
return nil
|
|
}
|
|
return e.EncodeElement(r.Format(ISO8601Layout), startElement)
|
|
}
|
|
|
|
func storeObjectLock(bytes []byte, vol *Volume) (err error) {
|
|
return vol.store.Put(vol.name, bucketRootPath, XAttrKeyOSSLock, bytes)
|
|
}
|
|
|
|
func isObjectLocked(v *Volume, inode uint64, name, path string) error {
|
|
xattrInfo, err := v.mw.XAttrGet_ll(inode, XAttrKeyOSSLock)
|
|
if err != nil {
|
|
log.LogErrorf("isObjectLocked: check ObjectLock err(%v) volume(%v) path(%v) name(%v)",
|
|
err, v.name, path, name)
|
|
return err
|
|
}
|
|
retainUntilDate := xattrInfo.Get(XAttrKeyOSSLock)
|
|
if len(retainUntilDate) > 0 {
|
|
retainUntilDateInt64, err := strconv.ParseInt(string(retainUntilDate), 10, 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if retainUntilDateInt64 > time.Now().UnixNano() {
|
|
log.LogWarnf("isObjectLocked: object is locked, retainUntilDate(%v) volume(%v) path(%v) name(%v)",
|
|
retainUntilDateInt64, v.name, path, name)
|
|
return AccessDenied
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func formatRetentionDateStr(modifyTime time.Time, retention *Retention) string {
|
|
retentionDateUnixNano := modifyTime.Add(retention.Duration).UnixNano()
|
|
return strconv.FormatInt(retentionDateUnixNano, 10)
|
|
}
|