1/*
2 * MinIO Go Library for Amazon S3 Compatible Cloud Storage
3 * Copyright 2020 MinIO, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package minio
18
19import (
20	"bytes"
21	"context"
22	"encoding/xml"
23	"net/http"
24	"net/url"
25
26	"github.com/minio/minio-go/v7/pkg/s3utils"
27	"github.com/minio/minio-go/v7/pkg/sse"
28)
29
30// SetBucketEncryption sets the default encryption configuration on an existing bucket.
31func (c *Client) SetBucketEncryption(ctx context.Context, bucketName string, config *sse.Configuration) error {
32	// Input validation.
33	if err := s3utils.CheckValidBucketName(bucketName); err != nil {
34		return err
35	}
36
37	if config == nil {
38		return errInvalidArgument("configuration cannot be empty")
39	}
40
41	buf, err := xml.Marshal(config)
42	if err != nil {
43		return err
44	}
45
46	// Get resources properly escaped and lined up before
47	// using them in http request.
48	urlValues := make(url.Values)
49	urlValues.Set("encryption", "")
50
51	// Content-length is mandatory to set a default encryption configuration
52	reqMetadata := requestMetadata{
53		bucketName:       bucketName,
54		queryValues:      urlValues,
55		contentBody:      bytes.NewReader(buf),
56		contentLength:    int64(len(buf)),
57		contentMD5Base64: sumMD5Base64(buf),
58	}
59
60	// Execute PUT to upload a new bucket default encryption configuration.
61	resp, err := c.executeMethod(ctx, http.MethodPut, reqMetadata)
62	defer closeResponse(resp)
63	if err != nil {
64		return err
65	}
66	if resp.StatusCode != http.StatusOK {
67		return httpRespToErrorResponse(resp, bucketName, "")
68	}
69	return nil
70}
71
72// RemoveBucketEncryption removes the default encryption configuration on a bucket with a context to control cancellations and timeouts.
73func (c *Client) RemoveBucketEncryption(ctx context.Context, bucketName string) error {
74	// Input validation.
75	if err := s3utils.CheckValidBucketName(bucketName); err != nil {
76		return err
77	}
78
79	// Get resources properly escaped and lined up before
80	// using them in http request.
81	urlValues := make(url.Values)
82	urlValues.Set("encryption", "")
83
84	// DELETE default encryption configuration on a bucket.
85	resp, err := c.executeMethod(ctx, http.MethodDelete, requestMetadata{
86		bucketName:       bucketName,
87		queryValues:      urlValues,
88		contentSHA256Hex: emptySHA256Hex,
89	})
90	defer closeResponse(resp)
91	if err != nil {
92		return err
93	}
94	if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusNoContent {
95		return httpRespToErrorResponse(resp, bucketName, "")
96	}
97	return nil
98}
99
100// GetBucketEncryption gets the default encryption configuration
101// on an existing bucket with a context to control cancellations and timeouts.
102func (c *Client) GetBucketEncryption(ctx context.Context, bucketName string) (*sse.Configuration, error) {
103	// Input validation.
104	if err := s3utils.CheckValidBucketName(bucketName); err != nil {
105		return nil, err
106	}
107
108	// Get resources properly escaped and lined up before
109	// using them in http request.
110	urlValues := make(url.Values)
111	urlValues.Set("encryption", "")
112
113	// Execute GET on bucket to get the default encryption configuration.
114	resp, err := c.executeMethod(ctx, http.MethodGet, requestMetadata{
115		bucketName:  bucketName,
116		queryValues: urlValues,
117	})
118
119	defer closeResponse(resp)
120	if err != nil {
121		return nil, err
122	}
123
124	if resp.StatusCode != http.StatusOK {
125		return nil, httpRespToErrorResponse(resp, bucketName, "")
126	}
127
128	encryptionConfig := &sse.Configuration{}
129	if err = xmlDecoder(resp.Body, encryptionConfig); err != nil {
130		return nil, err
131	}
132
133	return encryptionConfig, nil
134}
135