github.com/minio/minio-go/v6@v6.0.57/api-object-lock.go (about)

     1  /*
     2   * MinIO Go Library for Amazon S3 Compatible Cloud Storage
     3   * Copyright 2019 MinIO, Inc.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  
    18  package minio
    19  
    20  import (
    21  	"bytes"
    22  	"context"
    23  	"encoding/xml"
    24  	"fmt"
    25  	"net/http"
    26  	"net/url"
    27  	"time"
    28  
    29  	"github.com/minio/minio-go/v6/pkg/s3utils"
    30  )
    31  
    32  // RetentionMode - object retention mode.
    33  type RetentionMode string
    34  
    35  const (
    36  	// Governance - governance mode.
    37  	Governance RetentionMode = "GOVERNANCE"
    38  
    39  	// Compliance - compliance mode.
    40  	Compliance RetentionMode = "COMPLIANCE"
    41  )
    42  
    43  func (r RetentionMode) String() string {
    44  	return string(r)
    45  }
    46  
    47  // IsValid - check whether this retention mode is valid or not.
    48  func (r RetentionMode) IsValid() bool {
    49  	return r == Governance || r == Compliance
    50  }
    51  
    52  // ValidityUnit - retention validity unit.
    53  type ValidityUnit string
    54  
    55  const (
    56  	// Days - denotes no. of days.
    57  	Days ValidityUnit = "DAYS"
    58  
    59  	// Years - denotes no. of years.
    60  	Years ValidityUnit = "YEARS"
    61  )
    62  
    63  func (unit ValidityUnit) String() string {
    64  	return string(unit)
    65  }
    66  
    67  // IsValid - check whether this validity unit is valid or not.
    68  func (unit ValidityUnit) isValid() bool {
    69  	return unit == Days || unit == Years
    70  }
    71  
    72  // Retention - bucket level retention configuration.
    73  type Retention struct {
    74  	Mode     RetentionMode
    75  	Validity time.Duration
    76  }
    77  
    78  func (r Retention) String() string {
    79  	return fmt.Sprintf("{Mode:%v, Validity:%v}", r.Mode, r.Validity)
    80  }
    81  
    82  // IsEmpty - returns whether retention is empty or not.
    83  func (r Retention) IsEmpty() bool {
    84  	return r.Mode == "" || r.Validity == 0
    85  }
    86  
    87  // objectLockConfig - object lock configuration specified in
    88  // https://docs.aws.amazon.com/AmazonS3/latest/API/Type_API_ObjectLockConfiguration.html
    89  type objectLockConfig struct {
    90  	XMLNS             string   `xml:"xmlns,attr,omitempty"`
    91  	XMLName           xml.Name `xml:"ObjectLockConfiguration"`
    92  	ObjectLockEnabled string   `xml:"ObjectLockEnabled"`
    93  	Rule              *struct {
    94  		DefaultRetention struct {
    95  			Mode  RetentionMode `xml:"Mode"`
    96  			Days  *uint         `xml:"Days"`
    97  			Years *uint         `xml:"Years"`
    98  		} `xml:"DefaultRetention"`
    99  	} `xml:"Rule,omitempty"`
   100  }
   101  
   102  func newObjectLockConfig(mode *RetentionMode, validity *uint, unit *ValidityUnit) (*objectLockConfig, error) {
   103  	config := &objectLockConfig{
   104  		ObjectLockEnabled: "Enabled",
   105  	}
   106  
   107  	if mode != nil && validity != nil && unit != nil {
   108  		if !mode.IsValid() {
   109  			return nil, fmt.Errorf("invalid retention mode `%v`", mode)
   110  		}
   111  
   112  		if !unit.isValid() {
   113  			return nil, fmt.Errorf("invalid validity unit `%v`", unit)
   114  		}
   115  
   116  		config.Rule = &struct {
   117  			DefaultRetention struct {
   118  				Mode  RetentionMode `xml:"Mode"`
   119  				Days  *uint         `xml:"Days"`
   120  				Years *uint         `xml:"Years"`
   121  			} `xml:"DefaultRetention"`
   122  		}{}
   123  
   124  		config.Rule.DefaultRetention.Mode = *mode
   125  		if *unit == Days {
   126  			config.Rule.DefaultRetention.Days = validity
   127  		} else {
   128  			config.Rule.DefaultRetention.Years = validity
   129  		}
   130  
   131  		return config, nil
   132  	}
   133  
   134  	if mode == nil && validity == nil && unit == nil {
   135  		return config, nil
   136  	}
   137  
   138  	return nil, fmt.Errorf("all of retention mode, validity and validity unit must be passed")
   139  }
   140  
   141  // SetBucketObjectLockConfig sets object lock configuration in given bucket. mode, validity and unit are either all set or all nil.
   142  func (c Client) SetBucketObjectLockConfig(bucketName string, mode *RetentionMode, validity *uint, unit *ValidityUnit) error {
   143  	// Input validation.
   144  	if err := s3utils.CheckValidBucketName(bucketName); err != nil {
   145  		return err
   146  	}
   147  
   148  	// Get resources properly escaped and lined up before
   149  	// using them in http request.
   150  	urlValues := make(url.Values)
   151  	urlValues.Set("object-lock", "")
   152  
   153  	config, err := newObjectLockConfig(mode, validity, unit)
   154  	if err != nil {
   155  		return err
   156  	}
   157  
   158  	configData, err := xml.Marshal(config)
   159  	if err != nil {
   160  		return err
   161  	}
   162  
   163  	reqMetadata := requestMetadata{
   164  		bucketName:       bucketName,
   165  		queryValues:      urlValues,
   166  		contentBody:      bytes.NewReader(configData),
   167  		contentLength:    int64(len(configData)),
   168  		contentMD5Base64: sumMD5Base64(configData),
   169  		contentSHA256Hex: sum256Hex(configData),
   170  	}
   171  
   172  	// Execute PUT bucket object lock configuration.
   173  	resp, err := c.executeMethod(context.Background(), "PUT", reqMetadata)
   174  	defer closeResponse(resp)
   175  	if err != nil {
   176  		return err
   177  	}
   178  	if resp != nil {
   179  		if resp.StatusCode != http.StatusOK {
   180  			return httpRespToErrorResponse(resp, bucketName, "")
   181  		}
   182  	}
   183  	return nil
   184  }
   185  
   186  // GetObjectLockConfig gets object lock configuration of given bucket.
   187  func (c Client) GetObjectLockConfig(bucketName string) (objectLock string, mode *RetentionMode, validity *uint, unit *ValidityUnit, err error) {
   188  	// Input validation.
   189  	if err := s3utils.CheckValidBucketName(bucketName); err != nil {
   190  		return "", nil, nil, nil, err
   191  	}
   192  
   193  	urlValues := make(url.Values)
   194  	urlValues.Set("object-lock", "")
   195  
   196  	// Execute GET on bucket to list objects.
   197  	resp, err := c.executeMethod(context.Background(), "GET", requestMetadata{
   198  		bucketName:       bucketName,
   199  		queryValues:      urlValues,
   200  		contentSHA256Hex: emptySHA256Hex,
   201  	})
   202  	defer closeResponse(resp)
   203  	if err != nil {
   204  		return "", nil, nil, nil, err
   205  	}
   206  	if resp != nil {
   207  		if resp.StatusCode != http.StatusOK {
   208  			return "", nil, nil, nil, httpRespToErrorResponse(resp, bucketName, "")
   209  		}
   210  	}
   211  	config := &objectLockConfig{}
   212  	if err = xml.NewDecoder(resp.Body).Decode(config); err != nil {
   213  		return "", nil, nil, nil, err
   214  	}
   215  
   216  	if config.Rule != nil {
   217  		mode = &config.Rule.DefaultRetention.Mode
   218  		if config.Rule.DefaultRetention.Days != nil {
   219  			validity = config.Rule.DefaultRetention.Days
   220  			days := Days
   221  			unit = &days
   222  		} else {
   223  			validity = config.Rule.DefaultRetention.Years
   224  			years := Years
   225  			unit = &years
   226  		}
   227  		return config.ObjectLockEnabled, mode, validity, unit, nil
   228  	}
   229  	return config.ObjectLockEnabled, nil, nil, nil, nil
   230  }
   231  
   232  // GetBucketObjectLockConfig gets object lock configuration of given bucket.
   233  func (c Client) GetBucketObjectLockConfig(bucketName string) (mode *RetentionMode, validity *uint, unit *ValidityUnit, err error) {
   234  	_, mode, validity, unit, err = c.GetObjectLockConfig(bucketName)
   235  	return mode, validity, unit, err
   236  }
   237  
   238  // SetObjectLockConfig sets object lock configuration in given bucket. mode, validity and unit are either all set or all nil.
   239  func (c Client) SetObjectLockConfig(bucketName string, mode *RetentionMode, validity *uint, unit *ValidityUnit) error {
   240  	return c.SetBucketObjectLockConfig(bucketName, mode, validity, unit)
   241  }