From 619ac124b3105b71dd66181159f6cad328934bbf Mon Sep 17 00:00:00 2001 From: Lenin Alevski Date: Sun, 25 Oct 2020 12:56:23 -0700 Subject: [PATCH] Bucket encryption checkbox and endpoints for Console (#343) Co-authored-by: Daniel Valdivia --- models/bucket_encryption_info.go | 63 +++++ models/bucket_encryption_info_response.go | 129 +++++++++ models/bucket_encryption_request.go | 89 +++++++ models/bucket_encryption_type.go | 80 ++++++ .../ViewBucket/EnableBucketEncryption.tsx | 211 +++++++++++++++ .../Console/Buckets/ViewBucket/ViewBucket.tsx | 66 ++++- .../src/screens/Console/Buckets/types.tsx | 5 + restapi/client.go | 19 ++ restapi/embedded_spec.go | 250 ++++++++++++++++++ restapi/error.go | 2 + restapi/operations/console_api.go | 36 +++ .../user_api/disable_bucket_encryption.go | 90 +++++++ .../disable_bucket_encryption_parameters.go | 89 +++++++ .../disable_bucket_encryption_responses.go | 113 ++++++++ .../disable_bucket_encryption_urlbuilder.go | 116 ++++++++ .../user_api/enable_bucket_encryption.go | 90 +++++++ .../enable_bucket_encryption_parameters.go | 120 +++++++++ .../enable_bucket_encryption_responses.go | 113 ++++++++ .../enable_bucket_encryption_urlbuilder.go | 116 ++++++++ .../user_api/get_bucket_encryption_info.go | 90 +++++++ .../get_bucket_encryption_info_parameters.go | 89 +++++++ .../get_bucket_encryption_info_responses.go | 133 ++++++++++ .../get_bucket_encryption_info_urlbuilder.go | 116 ++++++++ restapi/user_buckets.go | 104 ++++++++ restapi/user_buckets_test.go | 200 +++++++++++++- swagger.yml | 87 ++++++ 26 files changed, 2614 insertions(+), 2 deletions(-) create mode 100644 models/bucket_encryption_info.go create mode 100644 models/bucket_encryption_info_response.go create mode 100644 models/bucket_encryption_request.go create mode 100644 models/bucket_encryption_type.go create mode 100644 portal-ui/src/screens/Console/Buckets/ViewBucket/EnableBucketEncryption.tsx create mode 100644 restapi/operations/user_api/disable_bucket_encryption.go create mode 100644 restapi/operations/user_api/disable_bucket_encryption_parameters.go create mode 100644 restapi/operations/user_api/disable_bucket_encryption_responses.go create mode 100644 restapi/operations/user_api/disable_bucket_encryption_urlbuilder.go create mode 100644 restapi/operations/user_api/enable_bucket_encryption.go create mode 100644 restapi/operations/user_api/enable_bucket_encryption_parameters.go create mode 100644 restapi/operations/user_api/enable_bucket_encryption_responses.go create mode 100644 restapi/operations/user_api/enable_bucket_encryption_urlbuilder.go create mode 100644 restapi/operations/user_api/get_bucket_encryption_info.go create mode 100644 restapi/operations/user_api/get_bucket_encryption_info_parameters.go create mode 100644 restapi/operations/user_api/get_bucket_encryption_info_responses.go create mode 100644 restapi/operations/user_api/get_bucket_encryption_info_urlbuilder.go diff --git a/models/bucket_encryption_info.go b/models/bucket_encryption_info.go new file mode 100644 index 000000000..23bd6fce9 --- /dev/null +++ b/models/bucket_encryption_info.go @@ -0,0 +1,63 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// BucketEncryptionInfo bucket encryption info +// +// swagger:model bucketEncryptionInfo +type BucketEncryptionInfo struct { + + // algorithm + Algorithm string `json:"algorithm,omitempty"` + + // kms master key ID + KmsMasterKeyID string `json:"kmsMasterKeyID,omitempty"` +} + +// Validate validates this bucket encryption info +func (m *BucketEncryptionInfo) Validate(formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *BucketEncryptionInfo) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *BucketEncryptionInfo) UnmarshalBinary(b []byte) error { + var res BucketEncryptionInfo + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/models/bucket_encryption_info_response.go b/models/bucket_encryption_info_response.go new file mode 100644 index 000000000..f4f5a581a --- /dev/null +++ b/models/bucket_encryption_info_response.go @@ -0,0 +1,129 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// BucketEncryptionInfoResponse bucket encryption info response +// +// swagger:model bucketEncryptionInfoResponse +type BucketEncryptionInfoResponse struct { + + // encryption + Encryption *BucketEncryptionInfoResponseEncryption `json:"encryption,omitempty"` + + // op + Op string `json:"op,omitempty"` + + // status + Status string `json:"status,omitempty"` + + // url + URL string `json:"url,omitempty"` +} + +// Validate validates this bucket encryption info response +func (m *BucketEncryptionInfoResponse) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateEncryption(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *BucketEncryptionInfoResponse) validateEncryption(formats strfmt.Registry) error { + + if swag.IsZero(m.Encryption) { // not required + return nil + } + + if m.Encryption != nil { + if err := m.Encryption.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("encryption") + } + return err + } + } + + return nil +} + +// MarshalBinary interface implementation +func (m *BucketEncryptionInfoResponse) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *BucketEncryptionInfoResponse) UnmarshalBinary(b []byte) error { + var res BucketEncryptionInfoResponse + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} + +// BucketEncryptionInfoResponseEncryption bucket encryption info response encryption +// +// swagger:model BucketEncryptionInfoResponseEncryption +type BucketEncryptionInfoResponseEncryption struct { + + // algorithm + Algorithm string `json:"algorithm,omitempty"` +} + +// Validate validates this bucket encryption info response encryption +func (m *BucketEncryptionInfoResponseEncryption) Validate(formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *BucketEncryptionInfoResponseEncryption) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *BucketEncryptionInfoResponseEncryption) UnmarshalBinary(b []byte) error { + var res BucketEncryptionInfoResponseEncryption + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/models/bucket_encryption_request.go b/models/bucket_encryption_request.go new file mode 100644 index 000000000..80e6b5127 --- /dev/null +++ b/models/bucket_encryption_request.go @@ -0,0 +1,89 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// BucketEncryptionRequest bucket encryption request +// +// swagger:model bucketEncryptionRequest +type BucketEncryptionRequest struct { + + // enc type + EncType BucketEncryptionType `json:"encType,omitempty"` + + // kms key ID + KmsKeyID string `json:"kmsKeyID,omitempty"` +} + +// Validate validates this bucket encryption request +func (m *BucketEncryptionRequest) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateEncType(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *BucketEncryptionRequest) validateEncType(formats strfmt.Registry) error { + + if swag.IsZero(m.EncType) { // not required + return nil + } + + if err := m.EncType.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("encType") + } + return err + } + + return nil +} + +// MarshalBinary interface implementation +func (m *BucketEncryptionRequest) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *BucketEncryptionRequest) UnmarshalBinary(b []byte) error { + var res BucketEncryptionRequest + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/models/bucket_encryption_type.go b/models/bucket_encryption_type.go new file mode 100644 index 000000000..0f85e9985 --- /dev/null +++ b/models/bucket_encryption_type.go @@ -0,0 +1,80 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "encoding/json" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" +) + +// BucketEncryptionType bucket encryption type +// +// swagger:model bucketEncryptionType +type BucketEncryptionType string + +const ( + + // BucketEncryptionTypeSseS3 captures enum value "sse-s3" + BucketEncryptionTypeSseS3 BucketEncryptionType = "sse-s3" + + // BucketEncryptionTypeSseKms captures enum value "sse-kms" + BucketEncryptionTypeSseKms BucketEncryptionType = "sse-kms" +) + +// for schema +var bucketEncryptionTypeEnum []interface{} + +func init() { + var res []BucketEncryptionType + if err := json.Unmarshal([]byte(`["sse-s3","sse-kms"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + bucketEncryptionTypeEnum = append(bucketEncryptionTypeEnum, v) + } +} + +func (m BucketEncryptionType) validateBucketEncryptionTypeEnum(path, location string, value BucketEncryptionType) error { + if err := validate.EnumCase(path, location, value, bucketEncryptionTypeEnum, true); err != nil { + return err + } + return nil +} + +// Validate validates this bucket encryption type +func (m BucketEncryptionType) Validate(formats strfmt.Registry) error { + var res []error + + // value enum + if err := m.validateBucketEncryptionTypeEnum("", "body", m); err != nil { + return err + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} diff --git a/portal-ui/src/screens/Console/Buckets/ViewBucket/EnableBucketEncryption.tsx b/portal-ui/src/screens/Console/Buckets/ViewBucket/EnableBucketEncryption.tsx new file mode 100644 index 000000000..8a2218809 --- /dev/null +++ b/portal-ui/src/screens/Console/Buckets/ViewBucket/EnableBucketEncryption.tsx @@ -0,0 +1,211 @@ +// This file is part of MinIO Console Server +// Copyright (c) 2020 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +import React, { ChangeEvent } from "react"; +import Grid from "@material-ui/core/Grid"; +import Typography from "@material-ui/core/Typography"; +import { Button, LinearProgress } from "@material-ui/core"; +import { createStyles, Theme, withStyles } from "@material-ui/core/styles"; +import api from "../../../../common/api"; +import TableHead from "@material-ui/core/TableHead"; +import TableRow from "@material-ui/core/TableRow"; +import TableCell from "@material-ui/core/TableCell"; +import TableBody from "@material-ui/core/TableBody"; +import Checkbox from "@material-ui/core/Checkbox"; +import Table from "@material-ui/core/Table"; +import { ArnList } from "../types"; +import { modalBasic } from "../../Common/FormComponents/common/styleLibrary"; +import ModalWrapper from "../../Common/ModalWrapper/ModalWrapper"; +import InputBoxWrapper from "../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper"; +import SelectWrapper from "../../Common/FormComponents/SelectWrapper/SelectWrapper"; + +const styles = (theme: Theme) => + createStyles({ + errorBlock: { + color: "red" + }, + minTableHeader: { + color: "#393939", + "& tr": { + "& th": { + fontWeight: "bold" + } + } + }, + buttonContainer: { + textAlign: "right" + }, + ...modalBasic + }); + +interface IEnableBucketEncryptionProps { + classes: any; + open: boolean; + selectedBucket: string; + closeModalAndRefresh: () => void; +} + +interface IEnableBucketEncryptionState { + loading: boolean; + encryptionError: string; + kmsKeyID: string; + suffix: string; + encryptionType: string; +} + +class EnableBucketEncryption extends React.Component< + IEnableBucketEncryptionProps, + IEnableBucketEncryptionState +> { + state: IEnableBucketEncryptionState = { + loading: false, + encryptionError: "", + kmsKeyID: "", + suffix: "", + encryptionType: "sse-s3", + }; + + enableBucketEncryption(event: React.FormEvent) { + event.preventDefault(); + const { kmsKeyID, loading, encryptionType } = this.state; + const { selectedBucket } = this.props; + if (loading) { + return; + } + api + .invoke("POST", `/api/v1/buckets/${selectedBucket}/encryption/enable`, { + encType: encryptionType, + kmsKeyID: kmsKeyID, + }) + .then(() => { + this.setState( + { + loading: false, + encryptionError: "", + }, + () => { + this.props.closeModalAndRefresh(); + } + ); + }) + .catch((err: any) => { + this.setState({ encryptionError: err }); + }); + } + + render() { + const { classes, open } = this.props; + const { + loading, + encryptionError, + kmsKeyID, + encryptionType + } = this.state; + + return ( + { + this.setState({ encryptionError: "" }, () => { + this.props.closeModalAndRefresh(); + }); + }} + title="Enable Bucket Encryption" + > +
) => { + this.enableBucketEncryption(e); + }} + > + + + {encryptionError !== "" && ( + + + {encryptionError} + + + )} + + ) => { + this.setState({ encryptionType: e.target.value as string}); + }} + id="select-encryption-type" + name="select-encryption-type" + label={"Encryption Type"} + value={encryptionType} + options={[ + { + label: "SSE-S3", + value: "sse-s3", + }, + { + label: "SSE-KMS", + value: "sse-kms", + } + ]} + /> + + +
+
+ {encryptionType === "sse-kms" && ( + + ) => { + this.setState({ kmsKeyID: e.target.value }); + }} + /> + + )} + +
+
+
+ + + + {loading && ( + + + + )} +
+
+
+ ); + } +} + +export default withStyles(styles)(EnableBucketEncryption); diff --git a/portal-ui/src/screens/Console/Buckets/ViewBucket/ViewBucket.tsx b/portal-ui/src/screens/Console/Buckets/ViewBucket/ViewBucket.tsx index ca4224a5f..300a29862 100644 --- a/portal-ui/src/screens/Console/Buckets/ViewBucket/ViewBucket.tsx +++ b/portal-ui/src/screens/Console/Buckets/ViewBucket/ViewBucket.tsx @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -import React from "react"; +import React, { ChangeEvent } from "react"; import get from "lodash/get"; import { createStyles, Theme, withStyles } from "@material-ui/core/styles"; import Paper from "@material-ui/core/Paper"; @@ -27,6 +27,7 @@ import { BucketEvent, BucketEventList, BucketInfo, + BucketEncryptionInfo, BucketList, BucketReplication, BucketReplicationDestination, @@ -45,6 +46,9 @@ import { niceBytes } from "../../../../common/utils"; import AddReplicationModal from "./AddReplicationModal"; import { containerForHeader } from "../../Common/FormComponents/common/styleLibrary"; import PageHeader from "../../Common/PageHeader/PageHeader"; +import Checkbox from "@material-ui/core/Checkbox"; +import TableCell from "@material-ui/core/TableCell"; +import EnableBucketEncryption from "./EnableBucketEncryption"; const styles = (theme: Theme) => createStyles({ @@ -190,6 +194,7 @@ interface IViewBucketState { rowsPerPage: number; curTab: number; addScreenOpen: boolean; + enableEncryptionScreenOpen: boolean; deleteOpen: boolean; selectedBucket: string; selectedEvent: BucketEvent | null; @@ -198,6 +203,7 @@ interface IViewBucketState { replicationSet: boolean; openSetReplication: boolean; isVersioned: boolean; + encryptionEnabled: boolean; } class ViewBucket extends React.Component { @@ -217,6 +223,7 @@ class ViewBucket extends React.Component { curTab: 0, rowsPerPage: 10, addScreenOpen: false, + enableEncryptionScreenOpen: false, deleteOpen: false, selectedBucket: "", selectedEvent: null, @@ -225,6 +232,7 @@ class ViewBucket extends React.Component { replicationSet: false, openSetReplication: false, isVersioned: false, + encryptionEnabled: false, }; fetchEvents() { @@ -324,6 +332,21 @@ class ViewBucket extends React.Component { }); } + fetchBucketEncryptionInfo() { + const { match } = this.props; + const bucketName = match.params["bucketName"]; + api + .invoke("GET", `/api/v1/buckets/${bucketName}/encryption/info`) + .then((res: BucketEncryptionInfo) => { + if (res.algorithm) { + this.setState({ encryptionEnabled: true }); + } + }) + .catch((err) => { + console.log(err); + }); + } + closeAddModalAndRefresh() { this.setState({ setAccessPolicyScreenOpen: false }, () => { this.loadInfo(); @@ -342,6 +365,7 @@ class ViewBucket extends React.Component { this.loadInfo(); this.fetchEvents(); this.fetchBucketsSize(); + this.fetchBucketEncryptionInfo(); } bucketFilter(): void {} @@ -359,6 +383,7 @@ class ViewBucket extends React.Component { rowsPerPage, deleteOpen, addScreenOpen, + enableEncryptionScreenOpen, selectedEvent, bucketSize, loadingSize, @@ -366,6 +391,7 @@ class ViewBucket extends React.Component { isVersioned, replicationRules, curTab, + encryptionEnabled, } = this.state; const offset = page * rowsPerPage; @@ -413,6 +439,23 @@ class ViewBucket extends React.Component { this.setState({ openSetReplication: open }); }; + const handleEncryptionCheckbox = ( + event: React.ChangeEvent + ) => { + if (event.target.checked) { + this.setState({ enableEncryptionScreenOpen: true }); + } else { + api + .invoke("POST", `/api/v1/buckets/${bucketName}/encryption/disable`) + .then(() => { + this.setState({ encryptionEnabled: false }); + }) + .catch((err: any) => { + this.setState({ error: err }); + }); + } + }; + const tableActions = [{ type: "delete", onClick: confirmDeleteEvent }]; const filteredRecords = records.slice(offset, offset + rowsPerPage); @@ -430,6 +473,16 @@ class ViewBucket extends React.Component { }} /> )} + {enableEncryptionScreenOpen && ( + { + this.setState({ enableEncryptionScreenOpen: false }); + this.fetchBucketEncryptionInfo(); + }} + /> + )} {setAccessPolicyScreenOpen && ( {
Versioning:
{isVersioned ? "Yes" : "No"} 
+
Encryption:
+
+ handleEncryptionCheckbox(event)} + checked={encryptionEnabled} + /> +
diff --git a/portal-ui/src/screens/Console/Buckets/types.tsx b/portal-ui/src/screens/Console/Buckets/types.tsx index 1bb64fee1..11e0361f4 100644 --- a/portal-ui/src/screens/Console/Buckets/types.tsx +++ b/portal-ui/src/screens/Console/Buckets/types.tsx @@ -19,6 +19,11 @@ export interface Bucket { creation_date: Date; } +export interface BucketEncryptionInfo { + algorithm: string; + kmsMasterKeyID: string; +} + export interface BucketInfo { name: string; access: string; diff --git a/restapi/client.go b/restapi/client.go index 47bc6d035..8fa4bf54f 100644 --- a/restapi/client.go +++ b/restapi/client.go @@ -24,6 +24,7 @@ import ( "time" "github.com/minio/minio-go/v7/pkg/replication" + "github.com/minio/minio-go/v7/pkg/sse" "errors" @@ -61,6 +62,9 @@ type MinioClient interface { putObject(ctx context.Context, bucketName, objectName string, reader io.Reader, objectSize int64, opts minio.PutObjectOptions) (info minio.UploadInfo, err error) putObjectLegalHold(ctx context.Context, bucketName, objectName string, opts minio.PutObjectLegalHoldOptions) error putObjectRetention(ctx context.Context, bucketName, objectName string, opts minio.PutObjectRetentionOptions) error + setBucketEncryption(ctx context.Context, bucketName string, config *sse.Configuration) error + removeBucketEncryption(ctx context.Context, bucketName string) error + getBucketEncryption(ctx context.Context, bucketName string) (*sse.Configuration, error) } // Interface implementation @@ -143,6 +147,21 @@ func (c minioClient) putObjectRetention(ctx context.Context, bucketName, objectN return c.client.PutObjectRetention(ctx, bucketName, objectName, opts) } +// implements minio.SetBucketEncryption(ctx, bucketName, config) +func (c minioClient) setBucketEncryption(ctx context.Context, bucketName string, config *sse.Configuration) error { + return c.client.SetBucketEncryption(ctx, bucketName, config) +} + +// implements minio.RemoveBucketEncryption(ctx, bucketName) +func (c minioClient) removeBucketEncryption(ctx context.Context, bucketName string) error { + return c.client.RemoveBucketEncryption(ctx, bucketName) +} + +// implements minio.GetBucketEncryption(ctx, bucketName, config) +func (c minioClient) getBucketEncryption(ctx context.Context, bucketName string) (*sse.Configuration, error) { + return c.client.GetBucketEncryption(ctx, bucketName) +} + // MCClient interface with all functions to be implemented // by mock when testing, it should include all mc/S3Client respective api calls // that are used within this project. diff --git a/restapi/embedded_spec.go b/restapi/embedded_spec.go index 4d65a23a5..39919ea45 100644 --- a/restapi/embedded_spec.go +++ b/restapi/embedded_spec.go @@ -222,6 +222,101 @@ func init() { } } }, + "/buckets/{bucket_name}/encryption/disable": { + "post": { + "tags": [ + "UserAPI" + ], + "summary": "Disable bucket encryption.", + "operationId": "DisableBucketEncryption", + "parameters": [ + { + "type": "string", + "name": "bucket_name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "A successful response." + }, + "default": { + "description": "Generic error response.", + "schema": { + "$ref": "#/definitions/error" + } + } + } + } + }, + "/buckets/{bucket_name}/encryption/enable": { + "post": { + "tags": [ + "UserAPI" + ], + "summary": "Enable bucket encryption.", + "operationId": "EnableBucketEncryption", + "parameters": [ + { + "type": "string", + "name": "bucket_name", + "in": "path", + "required": true + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/bucketEncryptionRequest" + } + } + ], + "responses": { + "200": { + "description": "A successful response." + }, + "default": { + "description": "Generic error response.", + "schema": { + "$ref": "#/definitions/error" + } + } + } + } + }, + "/buckets/{bucket_name}/encryption/info": { + "get": { + "tags": [ + "UserAPI" + ], + "summary": "Get bucket encryption information.", + "operationId": "GetBucketEncryptionInfo", + "parameters": [ + { + "type": "string", + "name": "bucket_name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/bucketEncryptionInfo" + } + }, + "default": { + "description": "Generic error response.", + "schema": { + "$ref": "#/definitions/error" + } + } + } + } + }, "/buckets/{bucket_name}/events": { "get": { "tags": [ @@ -2781,6 +2876,36 @@ func init() { "CUSTOM" ] }, + "bucketEncryptionInfo": { + "type": "object", + "properties": { + "algorithm": { + "type": "string" + }, + "kmsMasterKeyID": { + "type": "string" + } + } + }, + "bucketEncryptionRequest": { + "type": "object", + "properties": { + "encType": { + "$ref": "#/definitions/bucketEncryptionType" + }, + "kmsKeyID": { + "type": "string" + } + } + }, + "bucketEncryptionType": { + "type": "string", + "default": "sse-s3", + "enum": [ + "sse-s3", + "sse-kms" + ] + }, "bucketEventRequest": { "type": "object", "required": [ @@ -4902,6 +5027,101 @@ func init() { } } }, + "/buckets/{bucket_name}/encryption/disable": { + "post": { + "tags": [ + "UserAPI" + ], + "summary": "Disable bucket encryption.", + "operationId": "DisableBucketEncryption", + "parameters": [ + { + "type": "string", + "name": "bucket_name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "A successful response." + }, + "default": { + "description": "Generic error response.", + "schema": { + "$ref": "#/definitions/error" + } + } + } + } + }, + "/buckets/{bucket_name}/encryption/enable": { + "post": { + "tags": [ + "UserAPI" + ], + "summary": "Enable bucket encryption.", + "operationId": "EnableBucketEncryption", + "parameters": [ + { + "type": "string", + "name": "bucket_name", + "in": "path", + "required": true + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/bucketEncryptionRequest" + } + } + ], + "responses": { + "200": { + "description": "A successful response." + }, + "default": { + "description": "Generic error response.", + "schema": { + "$ref": "#/definitions/error" + } + } + } + } + }, + "/buckets/{bucket_name}/encryption/info": { + "get": { + "tags": [ + "UserAPI" + ], + "summary": "Get bucket encryption information.", + "operationId": "GetBucketEncryptionInfo", + "parameters": [ + { + "type": "string", + "name": "bucket_name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/bucketEncryptionInfo" + } + }, + "default": { + "description": "Generic error response.", + "schema": { + "$ref": "#/definitions/error" + } + } + } + } + }, "/buckets/{bucket_name}/events": { "get": { "tags": [ @@ -7984,6 +8204,36 @@ func init() { "CUSTOM" ] }, + "bucketEncryptionInfo": { + "type": "object", + "properties": { + "algorithm": { + "type": "string" + }, + "kmsMasterKeyID": { + "type": "string" + } + } + }, + "bucketEncryptionRequest": { + "type": "object", + "properties": { + "encType": { + "$ref": "#/definitions/bucketEncryptionType" + }, + "kmsKeyID": { + "type": "string" + } + } + }, + "bucketEncryptionType": { + "type": "string", + "default": "sse-s3", + "enum": [ + "sse-s3", + "sse-kms" + ] + }, "bucketEventRequest": { "type": "object", "required": [ diff --git a/restapi/error.go b/restapi/error.go index cef865059..1235d98aa 100644 --- a/restapi/error.go +++ b/restapi/error.go @@ -29,6 +29,8 @@ var ( errGroupNameNotInRequest = errors.New("error group name not in request") errPolicyNameNotInRequest = errors.New("error policy name not in request") errPolicyBodyNotInRequest = errors.New("error policy body not in request") + errInvalidEncryptionAlgorithm = errors.New("error invalid encryption algorithm") + errSSENotConfigured = errors.New("error server side encryption configuration was not found") ) // prepareError receives an error object and parse it against k8sErrors, returns the right error code paired with a generic error message diff --git a/restapi/operations/console_api.go b/restapi/operations/console_api.go index 08b32cbd4..37940da32 100644 --- a/restapi/operations/console_api.go +++ b/restapi/operations/console_api.go @@ -127,9 +127,18 @@ func NewConsoleAPI(spec *loads.Document) *ConsoleAPI { AdminAPIDeleteTenantHandler: admin_api.DeleteTenantHandlerFunc(func(params admin_api.DeleteTenantParams, principal *models.Principal) middleware.Responder { return middleware.NotImplemented("operation admin_api.DeleteTenant has not yet been implemented") }), + UserAPIDisableBucketEncryptionHandler: user_api.DisableBucketEncryptionHandlerFunc(func(params user_api.DisableBucketEncryptionParams, principal *models.Principal) middleware.Responder { + return middleware.NotImplemented("operation user_api.DisableBucketEncryption has not yet been implemented") + }), UserAPIDownloadObjectHandler: user_api.DownloadObjectHandlerFunc(func(params user_api.DownloadObjectParams, principal *models.Principal) middleware.Responder { return middleware.NotImplemented("operation user_api.DownloadObject has not yet been implemented") }), + UserAPIEnableBucketEncryptionHandler: user_api.EnableBucketEncryptionHandlerFunc(func(params user_api.EnableBucketEncryptionParams, principal *models.Principal) middleware.Responder { + return middleware.NotImplemented("operation user_api.EnableBucketEncryption has not yet been implemented") + }), + UserAPIGetBucketEncryptionInfoHandler: user_api.GetBucketEncryptionInfoHandlerFunc(func(params user_api.GetBucketEncryptionInfoParams, principal *models.Principal) middleware.Responder { + return middleware.NotImplemented("operation user_api.GetBucketEncryptionInfo has not yet been implemented") + }), UserAPIGetBucketQuotaHandler: user_api.GetBucketQuotaHandlerFunc(func(params user_api.GetBucketQuotaParams, principal *models.Principal) middleware.Responder { return middleware.NotImplemented("operation user_api.GetBucketQuota has not yet been implemented") }), @@ -383,8 +392,14 @@ type ConsoleAPI struct { UserAPIDeleteServiceAccountHandler user_api.DeleteServiceAccountHandler // AdminAPIDeleteTenantHandler sets the operation handler for the delete tenant operation AdminAPIDeleteTenantHandler admin_api.DeleteTenantHandler + // UserAPIDisableBucketEncryptionHandler sets the operation handler for the disable bucket encryption operation + UserAPIDisableBucketEncryptionHandler user_api.DisableBucketEncryptionHandler // UserAPIDownloadObjectHandler sets the operation handler for the download object operation UserAPIDownloadObjectHandler user_api.DownloadObjectHandler + // UserAPIEnableBucketEncryptionHandler sets the operation handler for the enable bucket encryption operation + UserAPIEnableBucketEncryptionHandler user_api.EnableBucketEncryptionHandler + // UserAPIGetBucketEncryptionInfoHandler sets the operation handler for the get bucket encryption info operation + UserAPIGetBucketEncryptionInfoHandler user_api.GetBucketEncryptionInfoHandler // UserAPIGetBucketQuotaHandler sets the operation handler for the get bucket quota operation UserAPIGetBucketQuotaHandler user_api.GetBucketQuotaHandler // UserAPIGetBucketReplicationHandler sets the operation handler for the get bucket replication operation @@ -630,9 +645,18 @@ func (o *ConsoleAPI) Validate() error { if o.AdminAPIDeleteTenantHandler == nil { unregistered = append(unregistered, "admin_api.DeleteTenantHandler") } + if o.UserAPIDisableBucketEncryptionHandler == nil { + unregistered = append(unregistered, "user_api.DisableBucketEncryptionHandler") + } if o.UserAPIDownloadObjectHandler == nil { unregistered = append(unregistered, "user_api.DownloadObjectHandler") } + if o.UserAPIEnableBucketEncryptionHandler == nil { + unregistered = append(unregistered, "user_api.EnableBucketEncryptionHandler") + } + if o.UserAPIGetBucketEncryptionInfoHandler == nil { + unregistered = append(unregistered, "user_api.GetBucketEncryptionInfoHandler") + } if o.UserAPIGetBucketQuotaHandler == nil { unregistered = append(unregistered, "user_api.GetBucketQuotaHandler") } @@ -978,10 +1002,22 @@ func (o *ConsoleAPI) initHandlerCache() { o.handlers["DELETE"] = make(map[string]http.Handler) } o.handlers["DELETE"]["/namespaces/{namespace}/tenants/{tenant}"] = admin_api.NewDeleteTenant(o.context, o.AdminAPIDeleteTenantHandler) + if o.handlers["POST"] == nil { + o.handlers["POST"] = make(map[string]http.Handler) + } + o.handlers["POST"]["/buckets/{bucket_name}/encryption/disable"] = user_api.NewDisableBucketEncryption(o.context, o.UserAPIDisableBucketEncryptionHandler) if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) } o.handlers["GET"]["/buckets/{bucket_name}/objects/download"] = user_api.NewDownloadObject(o.context, o.UserAPIDownloadObjectHandler) + if o.handlers["POST"] == nil { + o.handlers["POST"] = make(map[string]http.Handler) + } + o.handlers["POST"]["/buckets/{bucket_name}/encryption/enable"] = user_api.NewEnableBucketEncryption(o.context, o.UserAPIEnableBucketEncryptionHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } + o.handlers["GET"]["/buckets/{bucket_name}/encryption/info"] = user_api.NewGetBucketEncryptionInfo(o.context, o.UserAPIGetBucketEncryptionInfoHandler) if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) } diff --git a/restapi/operations/user_api/disable_bucket_encryption.go b/restapi/operations/user_api/disable_bucket_encryption.go new file mode 100644 index 000000000..72316752b --- /dev/null +++ b/restapi/operations/user_api/disable_bucket_encryption.go @@ -0,0 +1,90 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// + +package user_api + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" + + "github.com/minio/console/models" +) + +// DisableBucketEncryptionHandlerFunc turns a function with the right signature into a disable bucket encryption handler +type DisableBucketEncryptionHandlerFunc func(DisableBucketEncryptionParams, *models.Principal) middleware.Responder + +// Handle executing the request and returning a response +func (fn DisableBucketEncryptionHandlerFunc) Handle(params DisableBucketEncryptionParams, principal *models.Principal) middleware.Responder { + return fn(params, principal) +} + +// DisableBucketEncryptionHandler interface for that can handle valid disable bucket encryption params +type DisableBucketEncryptionHandler interface { + Handle(DisableBucketEncryptionParams, *models.Principal) middleware.Responder +} + +// NewDisableBucketEncryption creates a new http.Handler for the disable bucket encryption operation +func NewDisableBucketEncryption(ctx *middleware.Context, handler DisableBucketEncryptionHandler) *DisableBucketEncryption { + return &DisableBucketEncryption{Context: ctx, Handler: handler} +} + +/*DisableBucketEncryption swagger:route POST /buckets/{bucket_name}/encryption/disable UserAPI disableBucketEncryption + +Disable bucket encryption. + +*/ +type DisableBucketEncryption struct { + Context *middleware.Context + Handler DisableBucketEncryptionHandler +} + +func (o *DisableBucketEncryption) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + r = rCtx + } + var Params = NewDisableBucketEncryptionParams() + + uprinc, aCtx, err := o.Context.Authorize(r, route) + if err != nil { + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + if aCtx != nil { + r = aCtx + } + var principal *models.Principal + if uprinc != nil { + principal = uprinc.(*models.Principal) // this is really a models.Principal, I promise + } + + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params, principal) // actually handle the request + + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/restapi/operations/user_api/disable_bucket_encryption_parameters.go b/restapi/operations/user_api/disable_bucket_encryption_parameters.go new file mode 100644 index 000000000..17841a939 --- /dev/null +++ b/restapi/operations/user_api/disable_bucket_encryption_parameters.go @@ -0,0 +1,89 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// + +package user_api + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" +) + +// NewDisableBucketEncryptionParams creates a new DisableBucketEncryptionParams object +// no default values defined in spec. +func NewDisableBucketEncryptionParams() DisableBucketEncryptionParams { + + return DisableBucketEncryptionParams{} +} + +// DisableBucketEncryptionParams contains all the bound params for the disable bucket encryption operation +// typically these are obtained from a http.Request +// +// swagger:parameters DisableBucketEncryption +type DisableBucketEncryptionParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + BucketName string +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewDisableBucketEncryptionParams() beforehand. +func (o *DisableBucketEncryptionParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rBucketName, rhkBucketName, _ := route.Params.GetOK("bucket_name") + if err := o.bindBucketName(rBucketName, rhkBucketName, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindBucketName binds and validates parameter BucketName from path. +func (o *DisableBucketEncryptionParams) bindBucketName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + + o.BucketName = raw + + return nil +} diff --git a/restapi/operations/user_api/disable_bucket_encryption_responses.go b/restapi/operations/user_api/disable_bucket_encryption_responses.go new file mode 100644 index 000000000..7b5e15ea3 --- /dev/null +++ b/restapi/operations/user_api/disable_bucket_encryption_responses.go @@ -0,0 +1,113 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// + +package user_api + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/minio/console/models" +) + +// DisableBucketEncryptionOKCode is the HTTP code returned for type DisableBucketEncryptionOK +const DisableBucketEncryptionOKCode int = 200 + +/*DisableBucketEncryptionOK A successful response. + +swagger:response disableBucketEncryptionOK +*/ +type DisableBucketEncryptionOK struct { +} + +// NewDisableBucketEncryptionOK creates DisableBucketEncryptionOK with default headers values +func NewDisableBucketEncryptionOK() *DisableBucketEncryptionOK { + + return &DisableBucketEncryptionOK{} +} + +// WriteResponse to the client +func (o *DisableBucketEncryptionOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(200) +} + +/*DisableBucketEncryptionDefault Generic error response. + +swagger:response disableBucketEncryptionDefault +*/ +type DisableBucketEncryptionDefault struct { + _statusCode int + + /* + In: Body + */ + Payload *models.Error `json:"body,omitempty"` +} + +// NewDisableBucketEncryptionDefault creates DisableBucketEncryptionDefault with default headers values +func NewDisableBucketEncryptionDefault(code int) *DisableBucketEncryptionDefault { + if code <= 0 { + code = 500 + } + + return &DisableBucketEncryptionDefault{ + _statusCode: code, + } +} + +// WithStatusCode adds the status to the disable bucket encryption default response +func (o *DisableBucketEncryptionDefault) WithStatusCode(code int) *DisableBucketEncryptionDefault { + o._statusCode = code + return o +} + +// SetStatusCode sets the status to the disable bucket encryption default response +func (o *DisableBucketEncryptionDefault) SetStatusCode(code int) { + o._statusCode = code +} + +// WithPayload adds the payload to the disable bucket encryption default response +func (o *DisableBucketEncryptionDefault) WithPayload(payload *models.Error) *DisableBucketEncryptionDefault { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the disable bucket encryption default response +func (o *DisableBucketEncryptionDefault) SetPayload(payload *models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DisableBucketEncryptionDefault) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(o._statusCode) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} diff --git a/restapi/operations/user_api/disable_bucket_encryption_urlbuilder.go b/restapi/operations/user_api/disable_bucket_encryption_urlbuilder.go new file mode 100644 index 000000000..f43e02703 --- /dev/null +++ b/restapi/operations/user_api/disable_bucket_encryption_urlbuilder.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// + +package user_api + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// DisableBucketEncryptionURL generates an URL for the disable bucket encryption operation +type DisableBucketEncryptionURL struct { + BucketName string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DisableBucketEncryptionURL) WithBasePath(bp string) *DisableBucketEncryptionURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DisableBucketEncryptionURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *DisableBucketEncryptionURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/buckets/{bucket_name}/encryption/disable" + + bucketName := o.BucketName + if bucketName != "" { + _path = strings.Replace(_path, "{bucket_name}", bucketName, -1) + } else { + return nil, errors.New("bucketName is required on DisableBucketEncryptionURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/api/v1" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *DisableBucketEncryptionURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *DisableBucketEncryptionURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *DisableBucketEncryptionURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on DisableBucketEncryptionURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on DisableBucketEncryptionURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *DisableBucketEncryptionURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/restapi/operations/user_api/enable_bucket_encryption.go b/restapi/operations/user_api/enable_bucket_encryption.go new file mode 100644 index 000000000..62175e3b8 --- /dev/null +++ b/restapi/operations/user_api/enable_bucket_encryption.go @@ -0,0 +1,90 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// + +package user_api + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" + + "github.com/minio/console/models" +) + +// EnableBucketEncryptionHandlerFunc turns a function with the right signature into a enable bucket encryption handler +type EnableBucketEncryptionHandlerFunc func(EnableBucketEncryptionParams, *models.Principal) middleware.Responder + +// Handle executing the request and returning a response +func (fn EnableBucketEncryptionHandlerFunc) Handle(params EnableBucketEncryptionParams, principal *models.Principal) middleware.Responder { + return fn(params, principal) +} + +// EnableBucketEncryptionHandler interface for that can handle valid enable bucket encryption params +type EnableBucketEncryptionHandler interface { + Handle(EnableBucketEncryptionParams, *models.Principal) middleware.Responder +} + +// NewEnableBucketEncryption creates a new http.Handler for the enable bucket encryption operation +func NewEnableBucketEncryption(ctx *middleware.Context, handler EnableBucketEncryptionHandler) *EnableBucketEncryption { + return &EnableBucketEncryption{Context: ctx, Handler: handler} +} + +/*EnableBucketEncryption swagger:route POST /buckets/{bucket_name}/encryption/enable UserAPI enableBucketEncryption + +Enable bucket encryption. + +*/ +type EnableBucketEncryption struct { + Context *middleware.Context + Handler EnableBucketEncryptionHandler +} + +func (o *EnableBucketEncryption) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + r = rCtx + } + var Params = NewEnableBucketEncryptionParams() + + uprinc, aCtx, err := o.Context.Authorize(r, route) + if err != nil { + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + if aCtx != nil { + r = aCtx + } + var principal *models.Principal + if uprinc != nil { + principal = uprinc.(*models.Principal) // this is really a models.Principal, I promise + } + + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params, principal) // actually handle the request + + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/restapi/operations/user_api/enable_bucket_encryption_parameters.go b/restapi/operations/user_api/enable_bucket_encryption_parameters.go new file mode 100644 index 000000000..c3646e2c2 --- /dev/null +++ b/restapi/operations/user_api/enable_bucket_encryption_parameters.go @@ -0,0 +1,120 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// + +package user_api + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "io" + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + + "github.com/minio/console/models" +) + +// NewEnableBucketEncryptionParams creates a new EnableBucketEncryptionParams object +// no default values defined in spec. +func NewEnableBucketEncryptionParams() EnableBucketEncryptionParams { + + return EnableBucketEncryptionParams{} +} + +// EnableBucketEncryptionParams contains all the bound params for the enable bucket encryption operation +// typically these are obtained from a http.Request +// +// swagger:parameters EnableBucketEncryption +type EnableBucketEncryptionParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: body + */ + Body *models.BucketEncryptionRequest + /* + Required: true + In: path + */ + BucketName string +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewEnableBucketEncryptionParams() beforehand. +func (o *EnableBucketEncryptionParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.BucketEncryptionRequest + if err := route.Consumer.Consume(r.Body, &body); err != nil { + if err == io.EOF { + res = append(res, errors.Required("body", "body", "")) + } else { + res = append(res, errors.NewParseError("body", "body", "", err)) + } + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Body = &body + } + } + } else { + res = append(res, errors.Required("body", "body", "")) + } + rBucketName, rhkBucketName, _ := route.Params.GetOK("bucket_name") + if err := o.bindBucketName(rBucketName, rhkBucketName, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindBucketName binds and validates parameter BucketName from path. +func (o *EnableBucketEncryptionParams) bindBucketName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + + o.BucketName = raw + + return nil +} diff --git a/restapi/operations/user_api/enable_bucket_encryption_responses.go b/restapi/operations/user_api/enable_bucket_encryption_responses.go new file mode 100644 index 000000000..c1766b0b9 --- /dev/null +++ b/restapi/operations/user_api/enable_bucket_encryption_responses.go @@ -0,0 +1,113 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// + +package user_api + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/minio/console/models" +) + +// EnableBucketEncryptionOKCode is the HTTP code returned for type EnableBucketEncryptionOK +const EnableBucketEncryptionOKCode int = 200 + +/*EnableBucketEncryptionOK A successful response. + +swagger:response enableBucketEncryptionOK +*/ +type EnableBucketEncryptionOK struct { +} + +// NewEnableBucketEncryptionOK creates EnableBucketEncryptionOK with default headers values +func NewEnableBucketEncryptionOK() *EnableBucketEncryptionOK { + + return &EnableBucketEncryptionOK{} +} + +// WriteResponse to the client +func (o *EnableBucketEncryptionOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(200) +} + +/*EnableBucketEncryptionDefault Generic error response. + +swagger:response enableBucketEncryptionDefault +*/ +type EnableBucketEncryptionDefault struct { + _statusCode int + + /* + In: Body + */ + Payload *models.Error `json:"body,omitempty"` +} + +// NewEnableBucketEncryptionDefault creates EnableBucketEncryptionDefault with default headers values +func NewEnableBucketEncryptionDefault(code int) *EnableBucketEncryptionDefault { + if code <= 0 { + code = 500 + } + + return &EnableBucketEncryptionDefault{ + _statusCode: code, + } +} + +// WithStatusCode adds the status to the enable bucket encryption default response +func (o *EnableBucketEncryptionDefault) WithStatusCode(code int) *EnableBucketEncryptionDefault { + o._statusCode = code + return o +} + +// SetStatusCode sets the status to the enable bucket encryption default response +func (o *EnableBucketEncryptionDefault) SetStatusCode(code int) { + o._statusCode = code +} + +// WithPayload adds the payload to the enable bucket encryption default response +func (o *EnableBucketEncryptionDefault) WithPayload(payload *models.Error) *EnableBucketEncryptionDefault { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the enable bucket encryption default response +func (o *EnableBucketEncryptionDefault) SetPayload(payload *models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *EnableBucketEncryptionDefault) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(o._statusCode) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} diff --git a/restapi/operations/user_api/enable_bucket_encryption_urlbuilder.go b/restapi/operations/user_api/enable_bucket_encryption_urlbuilder.go new file mode 100644 index 000000000..f6c053f29 --- /dev/null +++ b/restapi/operations/user_api/enable_bucket_encryption_urlbuilder.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// + +package user_api + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// EnableBucketEncryptionURL generates an URL for the enable bucket encryption operation +type EnableBucketEncryptionURL struct { + BucketName string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *EnableBucketEncryptionURL) WithBasePath(bp string) *EnableBucketEncryptionURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *EnableBucketEncryptionURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *EnableBucketEncryptionURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/buckets/{bucket_name}/encryption/enable" + + bucketName := o.BucketName + if bucketName != "" { + _path = strings.Replace(_path, "{bucket_name}", bucketName, -1) + } else { + return nil, errors.New("bucketName is required on EnableBucketEncryptionURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/api/v1" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *EnableBucketEncryptionURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *EnableBucketEncryptionURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *EnableBucketEncryptionURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on EnableBucketEncryptionURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on EnableBucketEncryptionURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *EnableBucketEncryptionURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/restapi/operations/user_api/get_bucket_encryption_info.go b/restapi/operations/user_api/get_bucket_encryption_info.go new file mode 100644 index 000000000..c67c5233e --- /dev/null +++ b/restapi/operations/user_api/get_bucket_encryption_info.go @@ -0,0 +1,90 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// + +package user_api + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" + + "github.com/minio/console/models" +) + +// GetBucketEncryptionInfoHandlerFunc turns a function with the right signature into a get bucket encryption info handler +type GetBucketEncryptionInfoHandlerFunc func(GetBucketEncryptionInfoParams, *models.Principal) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetBucketEncryptionInfoHandlerFunc) Handle(params GetBucketEncryptionInfoParams, principal *models.Principal) middleware.Responder { + return fn(params, principal) +} + +// GetBucketEncryptionInfoHandler interface for that can handle valid get bucket encryption info params +type GetBucketEncryptionInfoHandler interface { + Handle(GetBucketEncryptionInfoParams, *models.Principal) middleware.Responder +} + +// NewGetBucketEncryptionInfo creates a new http.Handler for the get bucket encryption info operation +func NewGetBucketEncryptionInfo(ctx *middleware.Context, handler GetBucketEncryptionInfoHandler) *GetBucketEncryptionInfo { + return &GetBucketEncryptionInfo{Context: ctx, Handler: handler} +} + +/*GetBucketEncryptionInfo swagger:route GET /buckets/{bucket_name}/encryption/info UserAPI getBucketEncryptionInfo + +Get bucket encryption information. + +*/ +type GetBucketEncryptionInfo struct { + Context *middleware.Context + Handler GetBucketEncryptionInfoHandler +} + +func (o *GetBucketEncryptionInfo) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + r = rCtx + } + var Params = NewGetBucketEncryptionInfoParams() + + uprinc, aCtx, err := o.Context.Authorize(r, route) + if err != nil { + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + if aCtx != nil { + r = aCtx + } + var principal *models.Principal + if uprinc != nil { + principal = uprinc.(*models.Principal) // this is really a models.Principal, I promise + } + + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params, principal) // actually handle the request + + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/restapi/operations/user_api/get_bucket_encryption_info_parameters.go b/restapi/operations/user_api/get_bucket_encryption_info_parameters.go new file mode 100644 index 000000000..e701a0321 --- /dev/null +++ b/restapi/operations/user_api/get_bucket_encryption_info_parameters.go @@ -0,0 +1,89 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// + +package user_api + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" +) + +// NewGetBucketEncryptionInfoParams creates a new GetBucketEncryptionInfoParams object +// no default values defined in spec. +func NewGetBucketEncryptionInfoParams() GetBucketEncryptionInfoParams { + + return GetBucketEncryptionInfoParams{} +} + +// GetBucketEncryptionInfoParams contains all the bound params for the get bucket encryption info operation +// typically these are obtained from a http.Request +// +// swagger:parameters GetBucketEncryptionInfo +type GetBucketEncryptionInfoParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + BucketName string +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetBucketEncryptionInfoParams() beforehand. +func (o *GetBucketEncryptionInfoParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rBucketName, rhkBucketName, _ := route.Params.GetOK("bucket_name") + if err := o.bindBucketName(rBucketName, rhkBucketName, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindBucketName binds and validates parameter BucketName from path. +func (o *GetBucketEncryptionInfoParams) bindBucketName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + + o.BucketName = raw + + return nil +} diff --git a/restapi/operations/user_api/get_bucket_encryption_info_responses.go b/restapi/operations/user_api/get_bucket_encryption_info_responses.go new file mode 100644 index 000000000..18b734ca6 --- /dev/null +++ b/restapi/operations/user_api/get_bucket_encryption_info_responses.go @@ -0,0 +1,133 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// + +package user_api + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/minio/console/models" +) + +// GetBucketEncryptionInfoOKCode is the HTTP code returned for type GetBucketEncryptionInfoOK +const GetBucketEncryptionInfoOKCode int = 200 + +/*GetBucketEncryptionInfoOK A successful response. + +swagger:response getBucketEncryptionInfoOK +*/ +type GetBucketEncryptionInfoOK struct { + + /* + In: Body + */ + Payload *models.BucketEncryptionInfo `json:"body,omitempty"` +} + +// NewGetBucketEncryptionInfoOK creates GetBucketEncryptionInfoOK with default headers values +func NewGetBucketEncryptionInfoOK() *GetBucketEncryptionInfoOK { + + return &GetBucketEncryptionInfoOK{} +} + +// WithPayload adds the payload to the get bucket encryption info o k response +func (o *GetBucketEncryptionInfoOK) WithPayload(payload *models.BucketEncryptionInfo) *GetBucketEncryptionInfoOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get bucket encryption info o k response +func (o *GetBucketEncryptionInfoOK) SetPayload(payload *models.BucketEncryptionInfo) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetBucketEncryptionInfoOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} + +/*GetBucketEncryptionInfoDefault Generic error response. + +swagger:response getBucketEncryptionInfoDefault +*/ +type GetBucketEncryptionInfoDefault struct { + _statusCode int + + /* + In: Body + */ + Payload *models.Error `json:"body,omitempty"` +} + +// NewGetBucketEncryptionInfoDefault creates GetBucketEncryptionInfoDefault with default headers values +func NewGetBucketEncryptionInfoDefault(code int) *GetBucketEncryptionInfoDefault { + if code <= 0 { + code = 500 + } + + return &GetBucketEncryptionInfoDefault{ + _statusCode: code, + } +} + +// WithStatusCode adds the status to the get bucket encryption info default response +func (o *GetBucketEncryptionInfoDefault) WithStatusCode(code int) *GetBucketEncryptionInfoDefault { + o._statusCode = code + return o +} + +// SetStatusCode sets the status to the get bucket encryption info default response +func (o *GetBucketEncryptionInfoDefault) SetStatusCode(code int) { + o._statusCode = code +} + +// WithPayload adds the payload to the get bucket encryption info default response +func (o *GetBucketEncryptionInfoDefault) WithPayload(payload *models.Error) *GetBucketEncryptionInfoDefault { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get bucket encryption info default response +func (o *GetBucketEncryptionInfoDefault) SetPayload(payload *models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetBucketEncryptionInfoDefault) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(o._statusCode) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} diff --git a/restapi/operations/user_api/get_bucket_encryption_info_urlbuilder.go b/restapi/operations/user_api/get_bucket_encryption_info_urlbuilder.go new file mode 100644 index 000000000..e28e10cf9 --- /dev/null +++ b/restapi/operations/user_api/get_bucket_encryption_info_urlbuilder.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// This file is part of MinIO Console Server +// Copyright (c) 2020 MinIO, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// + +package user_api + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// GetBucketEncryptionInfoURL generates an URL for the get bucket encryption info operation +type GetBucketEncryptionInfoURL struct { + BucketName string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetBucketEncryptionInfoURL) WithBasePath(bp string) *GetBucketEncryptionInfoURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetBucketEncryptionInfoURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetBucketEncryptionInfoURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/buckets/{bucket_name}/encryption/info" + + bucketName := o.BucketName + if bucketName != "" { + _path = strings.Replace(_path, "{bucket_name}", bucketName, -1) + } else { + return nil, errors.New("bucketName is required on GetBucketEncryptionInfoURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/api/v1" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetBucketEncryptionInfoURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetBucketEncryptionInfoURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetBucketEncryptionInfoURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetBucketEncryptionInfoURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetBucketEncryptionInfoURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetBucketEncryptionInfoURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/restapi/user_buckets.go b/restapi/user_buckets.go index e1353f727..a9ba6c2ec 100644 --- a/restapi/user_buckets.go +++ b/restapi/user_buckets.go @@ -25,6 +25,7 @@ import ( "time" "github.com/minio/minio-go/v7/pkg/replication" + "github.com/minio/minio-go/v7/pkg/sse" "github.com/go-openapi/runtime/middleware" "github.com/go-openapi/swag" @@ -101,6 +102,28 @@ func registerBucketsHandlers(api *operations.ConsoleAPI) { } return user_api.NewAddBucketReplicationCreated() }) + // enable bucket encryption + api.UserAPIEnableBucketEncryptionHandler = user_api.EnableBucketEncryptionHandlerFunc(func(params user_api.EnableBucketEncryptionParams, session *models.Principal) middleware.Responder { + if err := enableBucketEncryptionResponse(session, params); err != nil { + return user_api.NewEnableBucketEncryptionDefault(int(err.Code)).WithPayload(err) + } + return user_api.NewEnableBucketEncryptionOK() + }) + // disable bucket encryption + api.UserAPIDisableBucketEncryptionHandler = user_api.DisableBucketEncryptionHandlerFunc(func(params user_api.DisableBucketEncryptionParams, session *models.Principal) middleware.Responder { + if err := disableBucketEncryptionResponse(session, params); err != nil { + return user_api.NewDisableBucketEncryptionDefault(int(err.Code)).WithPayload(err) + } + return user_api.NewDisableBucketEncryptionOK() + }) + // get bucket encryption info + api.UserAPIGetBucketEncryptionInfoHandler = user_api.GetBucketEncryptionInfoHandlerFunc(func(params user_api.GetBucketEncryptionInfoParams, session *models.Principal) middleware.Responder { + response, err := getBucketEncryptionInfoResponse(session, params) + if err != nil { + return user_api.NewGetBucketEncryptionInfoDefault(int(err.Code)).WithPayload(err) + } + return user_api.NewGetBucketEncryptionInfoOK().WithPayload(response) + }) } func getAddBucketReplicationdResponse(session *models.Principal, bucketName string, params *user_api.AddBucketReplicationParams) error { @@ -462,3 +485,84 @@ func consoleAccess2policyAccess(bucketAccess models.BucketAccess) (bucketPolicy } return bucketPolicy } + +// enableBucketEncryption will enable bucket encryption based on two encryption algorithms, sse-s3 (server side encryption with external KMS) or sse-kms (aws s3 kms key) +func enableBucketEncryption(ctx context.Context, client MinioClient, bucketName string, encryptionType models.BucketEncryptionType, kmsKeyID string) error { + var config *sse.Configuration + switch encryptionType { + case models.BucketEncryptionTypeSseKms: + config = sse.NewConfigurationSSEKMS(kmsKeyID) + case models.BucketEncryptionTypeSseS3: + config = sse.NewConfigurationSSES3() + default: + return errInvalidEncryptionAlgorithm + } + return client.setBucketEncryption(ctx, bucketName, config) +} + +// enableBucketEncryptionResponse calls enableBucketEncryption() to create new encryption configuration for provided bucket name +func enableBucketEncryptionResponse(session *models.Principal, params user_api.EnableBucketEncryptionParams) *models.Error { + ctx, cancel := context.WithTimeout(context.Background(), time.Second*20) + defer cancel() + mClient, err := newMinioClient(session) + if err != nil { + return prepareError(err) + } + // create a minioClient interface implementation + // defining the client to be used + minioClient := minioClient{client: mClient} + if err := enableBucketEncryption(ctx, minioClient, params.BucketName, params.Body.EncType, params.Body.KmsKeyID); err != nil { + return prepareError(err) + } + return nil +} + +// disableBucketEncryption will disable bucket for the provided bucket name +func disableBucketEncryption(ctx context.Context, client MinioClient, bucketName string) error { + return client.removeBucketEncryption(ctx, bucketName) +} + +// disableBucketEncryptionResponse calls disableBucketEncryption() +func disableBucketEncryptionResponse(session *models.Principal, params user_api.DisableBucketEncryptionParams) *models.Error { + ctx, cancel := context.WithTimeout(context.Background(), time.Second*20) + defer cancel() + mClient, err := newMinioClient(session) + if err != nil { + return prepareError(err) + } + // create a minioClient interface implementation + // defining the client to be used + minioClient := minioClient{client: mClient} + if err := disableBucketEncryption(ctx, minioClient, params.BucketName); err != nil { + return prepareError(err) + } + return nil +} + +func getBucketEncryptionInfo(ctx context.Context, client MinioClient, bucketName string) (*models.BucketEncryptionInfo, error) { + bucketInfo, err := client.getBucketEncryption(ctx, bucketName) + if err != nil { + return nil, err + } + if len(bucketInfo.Rules) == 0 { + return nil, errorGeneric + } + return &models.BucketEncryptionInfo{Algorithm: bucketInfo.Rules[0].Apply.SSEAlgorithm, KmsMasterKeyID: bucketInfo.Rules[0].Apply.KmsMasterKeyID}, nil +} + +func getBucketEncryptionInfoResponse(session *models.Principal, params user_api.GetBucketEncryptionInfoParams) (*models.BucketEncryptionInfo, *models.Error) { + ctx, cancel := context.WithTimeout(context.Background(), time.Second*20) + defer cancel() + mClient, err := newMinioClient(session) + if err != nil { + return nil, prepareError(err) + } + // create a minioClient interface implementation + // defining the client to be used + minioClient := minioClient{client: mClient} + bucketInfo, err := getBucketEncryptionInfo(ctx, minioClient, params.BucketName) + if err != nil { + return nil, prepareError(errSSENotConfigured, err) + } + return bucketInfo, nil +} diff --git a/restapi/user_buckets_test.go b/restapi/user_buckets_test.go index 09585f11f..036ac56db 100644 --- a/restapi/user_buckets_test.go +++ b/restapi/user_buckets_test.go @@ -20,6 +20,7 @@ import ( "context" "errors" "fmt" + "reflect" "testing" "time" @@ -27,6 +28,7 @@ import ( "github.com/go-openapi/swag" "github.com/minio/console/models" "github.com/minio/minio-go/v7" + "github.com/minio/minio-go/v7/pkg/sse" "github.com/minio/minio/pkg/madmin" "github.com/stretchr/testify/assert" ) @@ -37,6 +39,9 @@ var minioMakeBucketWithContextMock func(ctx context.Context, bucketName, locatio var minioSetBucketPolicyWithContextMock func(ctx context.Context, bucketName, policy string) error var minioRemoveBucketMock func(bucketName string) error var minioGetBucketPolicyMock func(bucketName string) (string, error) +var minioSetBucketEncryptionMock func(ctx context.Context, bucketName string, config *sse.Configuration) error +var minioRemoveBucketEncryptionMock func(ctx context.Context, bucketName string) error +var minioGetBucketEncryptionMock func(ctx context.Context, bucketName string) (*sse.Configuration, error) // Define a mock struct of minio Client interface implementation type minioClientMock struct { @@ -62,11 +67,23 @@ func (mc minioClientMock) removeBucket(ctx context.Context, bucketName string) e return minioRemoveBucketMock(bucketName) } -// imock function of getBucketPolicy() +// mock function of getBucketPolicy() func (mc minioClientMock) getBucketPolicy(ctx context.Context, bucketName string) (string, error) { return minioGetBucketPolicyMock(bucketName) } +func (mc minioClientMock) setBucketEncryption(ctx context.Context, bucketName string, config *sse.Configuration) error { + return minioSetBucketEncryptionMock(ctx, bucketName, config) +} + +func (mc minioClientMock) removeBucketEncryption(ctx context.Context, bucketName string) error { + return minioRemoveBucketEncryptionMock(ctx, bucketName) +} + +func (mc minioClientMock) getBucketEncryption(ctx context.Context, bucketName string) (*sse.Configuration, error) { + return minioGetBucketEncryptionMock(ctx, bucketName) +} + var minioAccountUsageInfoMock func(ctx context.Context) (madmin.AccountUsageInfo, error) // mock function of dataUsageInfo() needed for list bucket's usage @@ -317,3 +334,184 @@ func TestSetBucketAccess(t *testing.T) { } } + +func Test_enableBucketEncryption(t *testing.T) { + ctx := context.Background() + minClient := minioClientMock{} + type args struct { + ctx context.Context + client MinioClient + bucketName string + encryptionType models.BucketEncryptionType + kmsKeyID string + mockEnableBucketEncryptionFunc func(ctx context.Context, bucketName string, config *sse.Configuration) error + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Bucket encryption enabled correctly", + args: args{ + ctx: ctx, + client: minClient, + bucketName: "test", + encryptionType: "sse-s3", + mockEnableBucketEncryptionFunc: func(ctx context.Context, bucketName string, config *sse.Configuration) error { + return nil + }, + }, + wantErr: false, + }, + { + name: "Error when enabling bucket encryption", + args: args{ + ctx: ctx, + client: minClient, + bucketName: "test", + encryptionType: "sse-s3", + mockEnableBucketEncryptionFunc: func(ctx context.Context, bucketName string, config *sse.Configuration) error { + return errorGenericInvalidSession + }, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + minioSetBucketEncryptionMock = tt.args.mockEnableBucketEncryptionFunc + if err := enableBucketEncryption(tt.args.ctx, tt.args.client, tt.args.bucketName, tt.args.encryptionType, tt.args.kmsKeyID); (err != nil) != tt.wantErr { + t.Errorf("enableBucketEncryption() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func Test_disableBucketEncryption(t *testing.T) { + ctx := context.Background() + minClient := minioClientMock{} + type args struct { + ctx context.Context + client MinioClient + bucketName string + mockBucketDisableFunc func(ctx context.Context, bucketName string) error + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Bucket encryption disabled correctly", + args: args{ + ctx: ctx, + client: minClient, + bucketName: "test", + mockBucketDisableFunc: func(ctx context.Context, bucketName string) error { + return nil + }, + }, + wantErr: false, + }, + { + name: "Error when disabling bucket encryption", + args: args{ + ctx: ctx, + client: minClient, + bucketName: "test", + mockBucketDisableFunc: func(ctx context.Context, bucketName string) error { + return errorGeneric + }, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + minioRemoveBucketEncryptionMock = tt.args.mockBucketDisableFunc + if err := disableBucketEncryption(tt.args.ctx, tt.args.client, tt.args.bucketName); (err != nil) != tt.wantErr { + t.Errorf("disableBucketEncryption() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func Test_getBucketEncryptionInfo(t *testing.T) { + ctx := context.Background() + minClient := minioClientMock{} + type args struct { + ctx context.Context + client MinioClient + bucketName string + mockBucketEncryptionGet func(ctx context.Context, bucketName string) (*sse.Configuration, error) + } + tests := []struct { + name string + args args + want *models.BucketEncryptionInfo + wantErr bool + }{ + { + name: "Bucket encryption info returned correctly", + args: args{ + ctx: ctx, + client: minClient, + bucketName: "test", + mockBucketEncryptionGet: func(ctx context.Context, bucketName string) (*sse.Configuration, error) { + return &sse.Configuration{ + Rules: []sse.Rule{ + { + Apply: sse.ApplySSEByDefault{SSEAlgorithm: "AES256", KmsMasterKeyID: ""}, + }, + }, + }, nil + }, + }, + wantErr: false, + want: &models.BucketEncryptionInfo{ + Algorithm: "AES256", + KmsMasterKeyID: "", + }, + }, + { + name: "Bucket encryption info with no rules", + args: args{ + ctx: ctx, + client: minClient, + bucketName: "test", + mockBucketEncryptionGet: func(ctx context.Context, bucketName string) (*sse.Configuration, error) { + return &sse.Configuration{ + Rules: []sse.Rule{}, + }, nil + }, + }, + wantErr: true, + }, + { + name: "Error when obtaining bucket encryption info", + args: args{ + ctx: ctx, + client: minClient, + bucketName: "test", + mockBucketEncryptionGet: func(ctx context.Context, bucketName string) (*sse.Configuration, error) { + return nil, errSSENotConfigured + }, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + minioGetBucketEncryptionMock = tt.args.mockBucketEncryptionGet + got, err := getBucketEncryptionInfo(tt.args.ctx, tt.args.client, tt.args.bucketName) + if (err != nil) != tt.wantErr { + t.Errorf("getBucketEncryptionInfo() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("getBucketEncryptionInfo() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/swagger.yml b/swagger.yml index 5a3843244..a42714efe 100644 --- a/swagger.yml +++ b/swagger.yml @@ -674,6 +674,70 @@ paths: tags: - UserAPI + /buckets/{bucket_name}/encryption/enable: + post: + summary: Enable bucket encryption. + operationId: EnableBucketEncryption + parameters: + - name: bucket_name + in: path + required: true + type: string + - name: body + in: body + required: true + schema: + $ref: "#/definitions/bucketEncryptionRequest" + responses: + 200: + description: A successful response. + default: + description: Generic error response. + schema: + $ref: "#/definitions/error" + tags: + - UserAPI + + /buckets/{bucket_name}/encryption/disable: + post: + summary: Disable bucket encryption. + operationId: DisableBucketEncryption + parameters: + - name: bucket_name + in: path + required: true + type: string + responses: + 200: + description: A successful response. + default: + description: Generic error response. + schema: + $ref: "#/definitions/error" + tags: + - UserAPI + + /buckets/{bucket_name}/encryption/info: + get: + summary: Get bucket encryption information. + operationId: GetBucketEncryptionInfo + parameters: + - name: bucket_name + in: path + required: true + type: string + responses: + 200: + description: A successful response. + schema: + $ref: "#/definitions/bucketEncryptionInfo" + default: + description: Generic error response. + schema: + $ref: "#/definitions/error" + tags: + - UserAPI + /service-accounts: get: summary: List User's Service Accounts @@ -1755,6 +1819,13 @@ paths: - AdminAPI definitions: + bucketEncryptionType: + type: string + enum: + - sse-s3 + - sse-kms + default: sse-s3 + bucketAccess: type: string enum: @@ -1779,6 +1850,22 @@ definitions: creation_date: type: string + bucketEncryptionRequest: + type: object + properties: + encType: + $ref: "#/definitions/bucketEncryptionType" + kmsKeyID: + type: string + + bucketEncryptionInfo: + type: object + properties: + kmsMasterKeyID: + type: string + algorithm: + type: string + listBucketsResponse: type: object properties: