api-object-lock.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  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. package minio
  18. import (
  19. "bytes"
  20. "context"
  21. "encoding/xml"
  22. "fmt"
  23. "net/http"
  24. "net/url"
  25. "time"
  26. "github.com/minio/minio-go/v7/pkg/s3utils"
  27. )
  28. // RetentionMode - object retention mode.
  29. type RetentionMode string
  30. const (
  31. // Governance - governance mode.
  32. Governance RetentionMode = "GOVERNANCE"
  33. // Compliance - compliance mode.
  34. Compliance RetentionMode = "COMPLIANCE"
  35. )
  36. func (r RetentionMode) String() string {
  37. return string(r)
  38. }
  39. // IsValid - check whether this retention mode is valid or not.
  40. func (r RetentionMode) IsValid() bool {
  41. return r == Governance || r == Compliance
  42. }
  43. // ValidityUnit - retention validity unit.
  44. type ValidityUnit string
  45. const (
  46. // Days - denotes no. of days.
  47. Days ValidityUnit = "DAYS"
  48. // Years - denotes no. of years.
  49. Years ValidityUnit = "YEARS"
  50. )
  51. func (unit ValidityUnit) String() string {
  52. return string(unit)
  53. }
  54. // IsValid - check whether this validity unit is valid or not.
  55. func (unit ValidityUnit) isValid() bool {
  56. return unit == Days || unit == Years
  57. }
  58. // Retention - bucket level retention configuration.
  59. type Retention struct {
  60. Mode RetentionMode
  61. Validity time.Duration
  62. }
  63. func (r Retention) String() string {
  64. return fmt.Sprintf("{Mode:%v, Validity:%v}", r.Mode, r.Validity)
  65. }
  66. // IsEmpty - returns whether retention is empty or not.
  67. func (r Retention) IsEmpty() bool {
  68. return r.Mode == "" || r.Validity == 0
  69. }
  70. // objectLockConfig - object lock configuration specified in
  71. // https://docs.aws.amazon.com/AmazonS3/latest/API/Type_API_ObjectLockConfiguration.html
  72. type objectLockConfig struct {
  73. XMLNS string `xml:"xmlns,attr,omitempty"`
  74. XMLName xml.Name `xml:"ObjectLockConfiguration"`
  75. ObjectLockEnabled string `xml:"ObjectLockEnabled"`
  76. Rule *struct {
  77. DefaultRetention struct {
  78. Mode RetentionMode `xml:"Mode"`
  79. Days *uint `xml:"Days"`
  80. Years *uint `xml:"Years"`
  81. } `xml:"DefaultRetention"`
  82. } `xml:"Rule,omitempty"`
  83. }
  84. func newObjectLockConfig(mode *RetentionMode, validity *uint, unit *ValidityUnit) (*objectLockConfig, error) {
  85. config := &objectLockConfig{
  86. ObjectLockEnabled: "Enabled",
  87. }
  88. if mode != nil && validity != nil && unit != nil {
  89. if !mode.IsValid() {
  90. return nil, fmt.Errorf("invalid retention mode `%v`", mode)
  91. }
  92. if !unit.isValid() {
  93. return nil, fmt.Errorf("invalid validity unit `%v`", unit)
  94. }
  95. config.Rule = &struct {
  96. DefaultRetention struct {
  97. Mode RetentionMode `xml:"Mode"`
  98. Days *uint `xml:"Days"`
  99. Years *uint `xml:"Years"`
  100. } `xml:"DefaultRetention"`
  101. }{}
  102. config.Rule.DefaultRetention.Mode = *mode
  103. if *unit == Days {
  104. config.Rule.DefaultRetention.Days = validity
  105. } else {
  106. config.Rule.DefaultRetention.Years = validity
  107. }
  108. return config, nil
  109. }
  110. if mode == nil && validity == nil && unit == nil {
  111. return config, nil
  112. }
  113. return nil, fmt.Errorf("all of retention mode, validity and validity unit must be passed")
  114. }
  115. // SetBucketObjectLockConfig sets object lock configuration in given bucket. mode, validity and unit are either all set or all nil.
  116. func (c Client) SetBucketObjectLockConfig(ctx context.Context, bucketName string, mode *RetentionMode, validity *uint, unit *ValidityUnit) error {
  117. // Input validation.
  118. if err := s3utils.CheckValidBucketName(bucketName); err != nil {
  119. return err
  120. }
  121. // Get resources properly escaped and lined up before
  122. // using them in http request.
  123. urlValues := make(url.Values)
  124. urlValues.Set("object-lock", "")
  125. config, err := newObjectLockConfig(mode, validity, unit)
  126. if err != nil {
  127. return err
  128. }
  129. configData, err := xml.Marshal(config)
  130. if err != nil {
  131. return err
  132. }
  133. reqMetadata := requestMetadata{
  134. bucketName: bucketName,
  135. queryValues: urlValues,
  136. contentBody: bytes.NewReader(configData),
  137. contentLength: int64(len(configData)),
  138. contentMD5Base64: sumMD5Base64(configData),
  139. contentSHA256Hex: sum256Hex(configData),
  140. }
  141. // Execute PUT bucket object lock configuration.
  142. resp, err := c.executeMethod(ctx, http.MethodPut, reqMetadata)
  143. defer closeResponse(resp)
  144. if err != nil {
  145. return err
  146. }
  147. if resp != nil {
  148. if resp.StatusCode != http.StatusOK {
  149. return httpRespToErrorResponse(resp, bucketName, "")
  150. }
  151. }
  152. return nil
  153. }
  154. // GetObjectLockConfig gets object lock configuration of given bucket.
  155. func (c Client) GetObjectLockConfig(ctx context.Context, bucketName string) (objectLock string, mode *RetentionMode, validity *uint, unit *ValidityUnit, err error) {
  156. // Input validation.
  157. if err := s3utils.CheckValidBucketName(bucketName); err != nil {
  158. return "", nil, nil, nil, err
  159. }
  160. urlValues := make(url.Values)
  161. urlValues.Set("object-lock", "")
  162. // Execute GET on bucket to list objects.
  163. resp, err := c.executeMethod(ctx, http.MethodGet, requestMetadata{
  164. bucketName: bucketName,
  165. queryValues: urlValues,
  166. contentSHA256Hex: emptySHA256Hex,
  167. })
  168. defer closeResponse(resp)
  169. if err != nil {
  170. return "", nil, nil, nil, err
  171. }
  172. if resp != nil {
  173. if resp.StatusCode != http.StatusOK {
  174. return "", nil, nil, nil, httpRespToErrorResponse(resp, bucketName, "")
  175. }
  176. }
  177. config := &objectLockConfig{}
  178. if err = xml.NewDecoder(resp.Body).Decode(config); err != nil {
  179. return "", nil, nil, nil, err
  180. }
  181. if config.Rule != nil {
  182. mode = &config.Rule.DefaultRetention.Mode
  183. if config.Rule.DefaultRetention.Days != nil {
  184. validity = config.Rule.DefaultRetention.Days
  185. days := Days
  186. unit = &days
  187. } else {
  188. validity = config.Rule.DefaultRetention.Years
  189. years := Years
  190. unit = &years
  191. }
  192. return config.ObjectLockEnabled, mode, validity, unit, nil
  193. }
  194. return config.ObjectLockEnabled, nil, nil, nil, nil
  195. }
  196. // GetBucketObjectLockConfig gets object lock configuration of given bucket.
  197. func (c Client) GetBucketObjectLockConfig(ctx context.Context, bucketName string) (mode *RetentionMode, validity *uint, unit *ValidityUnit, err error) {
  198. _, mode, validity, unit, err = c.GetObjectLockConfig(ctx, bucketName)
  199. return mode, validity, unit, err
  200. }
  201. // SetObjectLockConfig sets object lock configuration in given bucket. mode, validity and unit are either all set or all nil.
  202. func (c Client) SetObjectLockConfig(ctx context.Context, bucketName string, mode *RetentionMode, validity *uint, unit *ValidityUnit) error {
  203. return c.SetBucketObjectLockConfig(ctx, bucketName, mode, validity, unit)
  204. }