mirror of
https://github.com/OpenMaxIO/openmaxio-object-browser
synced 2026-07-01 07:41:18 -07:00
2069 lines
84 KiB
TypeScript
2069 lines
84 KiB
TypeScript
// This file is part of MinIO Console Server
|
|
// Copyright (c) 2022 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 <http://www.gnu.org/licenses/>.
|
|
|
|
import { ITenant } from "../ListTenants/types";
|
|
import {
|
|
ICertificateInfo,
|
|
ITenantEncryptionResponse,
|
|
ISecurityContext,
|
|
} from "../types";
|
|
import { Theme } from "@mui/material/styles";
|
|
import createStyles from "@mui/styles/createStyles";
|
|
import withStyles from "@mui/styles/withStyles";
|
|
import {
|
|
containerForHeader,
|
|
createTenantCommon,
|
|
formFieldStyles,
|
|
modalBasic,
|
|
spacingUtils,
|
|
tenantDetailsStyles,
|
|
wizardCommon,
|
|
} from "../../Common/FormComponents/common/styleLibrary";
|
|
import Paper from "@mui/material/Paper";
|
|
import React, { Fragment, useEffect, useState } from "react";
|
|
import { setErrorSnackMessage } from "../../../../actions";
|
|
import { connect } from "react-redux";
|
|
import { AppState } from "../../../../store";
|
|
import { setTenantDetailsLoad } from "../actions";
|
|
import api from "../../../../common/api";
|
|
import { ErrorResponseHandler } from "../../../../common/types";
|
|
|
|
import FormSwitchWrapper from "../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper";
|
|
import Grid from "@mui/material/Grid";
|
|
import FileSelector from "../../Common/FormComponents/FileSelector/FileSelector";
|
|
import InputBoxWrapper from "../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
|
|
import RadioGroupSelector from "../../Common/FormComponents/RadioGroupSelector/RadioGroupSelector";
|
|
import { Button, DialogContentText, Typography } from "@mui/material";
|
|
import Chip from "@mui/material/Chip";
|
|
import Moment from "react-moment";
|
|
import VisibilityOffIcon from "@mui/icons-material/VisibilityOff";
|
|
import RemoveRedEyeIcon from "@mui/icons-material/RemoveRedEye";
|
|
import { KeyPair } from "../ListTenants/utils";
|
|
import { clearValidationError } from "../utils";
|
|
import {
|
|
commonFormValidation,
|
|
IValidation,
|
|
} from "../../../../utils/validationFunctions";
|
|
import ConfirmDialog from "../../Common/ModalWrapper/ConfirmDialog";
|
|
|
|
interface ITenantEncryption {
|
|
classes: any;
|
|
loadingTenant: boolean;
|
|
tenant: ITenant | null;
|
|
setErrorSnackMessage: typeof setErrorSnackMessage;
|
|
setTenantDetailsLoad: typeof setTenantDetailsLoad;
|
|
}
|
|
|
|
const styles = (theme: Theme) =>
|
|
createStyles({
|
|
...tenantDetailsStyles,
|
|
...spacingUtils,
|
|
loaderAlign: {
|
|
textAlign: "center",
|
|
},
|
|
title: {
|
|
marginTop: 35,
|
|
},
|
|
bold: { fontWeight: "bold" },
|
|
italic: { fontStyle: "italic" },
|
|
paperContainer: {
|
|
padding: "15px 15px 15px 50px",
|
|
},
|
|
certificateInfo: {
|
|
height: "auto",
|
|
margin: 5,
|
|
},
|
|
fileItem: {
|
|
marginRight: 10,
|
|
display: "flex",
|
|
"& div label": {
|
|
minWidth: 50,
|
|
},
|
|
|
|
"@media (max-width: 900px)": {
|
|
flexFlow: "column",
|
|
},
|
|
},
|
|
certInputRow: {
|
|
display: "flex",
|
|
alignItems: "center",
|
|
borderBottom: "1px solid #eaeaea",
|
|
marginBottom: 10,
|
|
},
|
|
caCertsRow: {
|
|
borderBottom: "1px solid #eaeaea",
|
|
display: "flex",
|
|
alignItems: "center",
|
|
marginBottom: 10,
|
|
},
|
|
...containerForHeader(theme.spacing(4)),
|
|
...createTenantCommon,
|
|
...formFieldStyles,
|
|
...modalBasic,
|
|
...wizardCommon,
|
|
});
|
|
|
|
const TenantEncryption = ({
|
|
classes,
|
|
tenant,
|
|
setErrorSnackMessage,
|
|
}: ITenantEncryption) => {
|
|
const [encryptionEnabled, setEncryptionEnabled] = useState<boolean>(false);
|
|
const [encryptionType, setEncryptionType] = useState<string>("vault");
|
|
const [replicas, setReplicas] = useState<string>("2");
|
|
const [image, setImage] = useState<string>("");
|
|
const [refreshEncryptionInfo, setRefreshEncryptionInfo] =
|
|
useState<boolean>(false);
|
|
const [securityContext, setSecurityContext] = useState<ISecurityContext>({
|
|
fsGroup: "1000",
|
|
runAsGroup: "1000",
|
|
runAsNonRoot: true,
|
|
runAsUser: "1000",
|
|
});
|
|
const [vaultConfiguration, setVaultConfiguration] = useState<any>(null);
|
|
const [awsConfiguration, setAWSConfiguration] = useState<any>(null);
|
|
const [gemaltoConfiguration, setGemaltoConfiguration] = useState<any>(null);
|
|
const [azureConfiguration, setAzureConfiguration] = useState<any>(null);
|
|
const [gcpConfiguration, setGCPConfiguration] = useState<any>(null);
|
|
const [enabledCustomCertificates, setEnabledCustomCertificates] =
|
|
useState<boolean>(false);
|
|
const [updatingEncryption, setUpdatingEncryption] = useState<boolean>(false);
|
|
const [serverTLSCertificateSecret, setServerTLSCertificateSecret] =
|
|
useState<ICertificateInfo | null>(null);
|
|
const [mTLSCertificateSecret, setMTLSCertificateSecret] =
|
|
useState<ICertificateInfo | null>(null);
|
|
const [mTLSCertificate, setMTLSCertificate] = useState<KeyPair | null>(null);
|
|
const [certificatesToBeRemoved, setCertificatesToBeRemoved] = useState<
|
|
string[]
|
|
>([]);
|
|
const [showVaultAppRoleID, setShowVaultAppRoleID] = useState<boolean>(false);
|
|
const [isFormValid, setIsFormValid] = useState<boolean>(false);
|
|
const [showVaultAppRoleSecret, setShowVaultAppRoleSecret] =
|
|
useState<boolean>(false);
|
|
const [vaultClientCertificateSecret, setVaultClientCertificateSecret] =
|
|
useState<ICertificateInfo | null>(null);
|
|
const [vaultCACertificateSecret, setVaultCACertificateSecret] =
|
|
useState<ICertificateInfo | null>(null);
|
|
const [vaultClientCertificate, setVaultClientCertificate] =
|
|
useState<KeyPair | null>(null);
|
|
const [serverCertificate, setServerCertificate] = useState<KeyPair | null>(
|
|
null
|
|
);
|
|
const [vaultCACertificate, setVaultCACertificate] = useState<KeyPair | null>(
|
|
null
|
|
);
|
|
const [gemaltoCACertificateSecret, setGemaltoCACertificateSecret] =
|
|
useState<ICertificateInfo | null>(null);
|
|
const [gemaltoCACertificate, setGemaltotCACertificate] =
|
|
useState<KeyPair | null>(null);
|
|
const [validationErrors, setValidationErrors] = useState<any>({});
|
|
const cleanValidation = (fieldName: string) => {
|
|
setValidationErrors(clearValidationError(validationErrors, fieldName));
|
|
};
|
|
const [confirmOpen, setConfirmOpen] = useState<boolean>(false);
|
|
|
|
// Validation
|
|
useEffect(() => {
|
|
let encryptionValidation: IValidation[] = [];
|
|
|
|
if (encryptionEnabled) {
|
|
encryptionValidation = [
|
|
...encryptionValidation,
|
|
{
|
|
fieldKey: "replicas",
|
|
required: true,
|
|
value: replicas,
|
|
customValidation: parseInt(replicas) < 1,
|
|
customValidationMessage: "Replicas needs to be 1 or greater",
|
|
},
|
|
{
|
|
fieldKey: "kes_securityContext_runAsUser",
|
|
required: true,
|
|
value: securityContext.runAsUser,
|
|
customValidation:
|
|
securityContext.runAsUser === "" ||
|
|
parseInt(securityContext.runAsUser) < 0,
|
|
customValidationMessage: `runAsUser must be present and be 0 or more`,
|
|
},
|
|
{
|
|
fieldKey: "kes_securityContext_runAsGroup",
|
|
required: true,
|
|
value: securityContext.runAsGroup,
|
|
customValidation:
|
|
securityContext.runAsGroup === "" ||
|
|
parseInt(securityContext.runAsGroup) < 0,
|
|
customValidationMessage: `runAsGroup must be present and be 0 or more`,
|
|
},
|
|
{
|
|
fieldKey: "kes_securityContext_fsGroup",
|
|
required: true,
|
|
value: securityContext.fsGroup,
|
|
customValidation:
|
|
securityContext.fsGroup === "" ||
|
|
parseInt(securityContext.fsGroup) < 0,
|
|
customValidationMessage: `fsGroup must be present and be 0 or more`,
|
|
},
|
|
];
|
|
|
|
if (enabledCustomCertificates) {
|
|
encryptionValidation = [
|
|
...encryptionValidation,
|
|
{
|
|
fieldKey: "serverKey",
|
|
required: false,
|
|
value: serverCertificate?.encoded_key || "",
|
|
},
|
|
{
|
|
fieldKey: "serverCert",
|
|
required: false,
|
|
value: serverCertificate?.encoded_cert || "",
|
|
},
|
|
{
|
|
fieldKey: "clientKey",
|
|
required: false,
|
|
value: mTLSCertificate?.encoded_key || "",
|
|
},
|
|
{
|
|
fieldKey: "clientCert",
|
|
required: false,
|
|
value: mTLSCertificate?.encoded_cert || "",
|
|
},
|
|
];
|
|
}
|
|
|
|
if (encryptionType === "vault") {
|
|
encryptionValidation = [
|
|
...encryptionValidation,
|
|
{
|
|
fieldKey: "vault_endpoint",
|
|
required: true,
|
|
value: vaultConfiguration?.endpoint,
|
|
},
|
|
{
|
|
fieldKey: "vault_id",
|
|
required: true,
|
|
value: vaultConfiguration?.approle?.id,
|
|
},
|
|
{
|
|
fieldKey: "vault_secret",
|
|
required: true,
|
|
value: vaultConfiguration?.approle?.secret,
|
|
},
|
|
{
|
|
fieldKey: "vault_ping",
|
|
required: false,
|
|
value: vaultConfiguration?.status?.ping,
|
|
customValidation: parseInt(vaultConfiguration?.status?.ping) < 0,
|
|
customValidationMessage: "Value needs to be 0 or greater",
|
|
},
|
|
{
|
|
fieldKey: "vault_retry",
|
|
required: false,
|
|
value: vaultConfiguration?.approle?.retry,
|
|
customValidation: parseInt(vaultConfiguration?.approle?.retry) < 0,
|
|
customValidationMessage: "Value needs to be 0 or greater",
|
|
},
|
|
];
|
|
}
|
|
|
|
if (encryptionType === "aws") {
|
|
encryptionValidation = [
|
|
...encryptionValidation,
|
|
{
|
|
fieldKey: "aws_endpoint",
|
|
required: true,
|
|
value: awsConfiguration?.secretsmanager?.endpoint,
|
|
},
|
|
{
|
|
fieldKey: "aws_region",
|
|
required: true,
|
|
value: awsConfiguration?.secretsmanager?.region,
|
|
},
|
|
{
|
|
fieldKey: "aws_accessKey",
|
|
required: true,
|
|
value: awsConfiguration?.secretsmanager?.credentials?.accesskey,
|
|
},
|
|
{
|
|
fieldKey: "aws_secretKey",
|
|
required: true,
|
|
value: awsConfiguration?.secretsmanager?.credentials?.secretkey,
|
|
},
|
|
];
|
|
}
|
|
|
|
if (encryptionType === "gemalto") {
|
|
encryptionValidation = [
|
|
...encryptionValidation,
|
|
{
|
|
fieldKey: "gemalto_endpoint",
|
|
required: true,
|
|
value: gemaltoConfiguration?.keysecure?.endpoint,
|
|
},
|
|
{
|
|
fieldKey: "gemalto_token",
|
|
required: true,
|
|
value: gemaltoConfiguration?.keysecure?.credentials?.token,
|
|
},
|
|
{
|
|
fieldKey: "gemalto_domain",
|
|
required: true,
|
|
value: gemaltoConfiguration?.keysecure?.credentials?.domain,
|
|
},
|
|
{
|
|
fieldKey: "gemalto_retry",
|
|
required: false,
|
|
value: gemaltoConfiguration?.keysecure?.credentials?.retry,
|
|
customValidation:
|
|
parseInt(gemaltoConfiguration?.keysecure?.credentials?.retry) < 0,
|
|
customValidationMessage: "Value needs to be 0 or greater",
|
|
},
|
|
];
|
|
}
|
|
|
|
if (encryptionType === "azure") {
|
|
encryptionValidation = [
|
|
...encryptionValidation,
|
|
{
|
|
fieldKey: "azure_endpoint",
|
|
required: true,
|
|
value: azureConfiguration?.keyvault?.endpoint,
|
|
},
|
|
{
|
|
fieldKey: "azure_tenant_id",
|
|
required: true,
|
|
value: azureConfiguration?.keyvault?.credentials?.tenant_id,
|
|
},
|
|
{
|
|
fieldKey: "azure_client_id",
|
|
required: true,
|
|
value: azureConfiguration?.keyvault?.credentials?.client_id,
|
|
},
|
|
{
|
|
fieldKey: "azure_client_secret",
|
|
required: true,
|
|
value: azureConfiguration?.keyvault?.credentials?.client_secret,
|
|
},
|
|
];
|
|
}
|
|
}
|
|
|
|
const commonVal = commonFormValidation(encryptionValidation);
|
|
|
|
setIsFormValid(Object.keys(commonVal).length === 0);
|
|
|
|
setValidationErrors(commonVal);
|
|
}, [
|
|
enabledCustomCertificates,
|
|
encryptionEnabled,
|
|
encryptionType,
|
|
serverCertificate?.encoded_key,
|
|
serverCertificate?.encoded_cert,
|
|
mTLSCertificate?.encoded_key,
|
|
mTLSCertificate?.encoded_cert,
|
|
vaultClientCertificate?.encoded_key,
|
|
vaultClientCertificate?.encoded_cert,
|
|
vaultCACertificate?.encoded_key,
|
|
vaultCACertificate?.encoded_cert,
|
|
securityContext,
|
|
vaultConfiguration,
|
|
awsConfiguration,
|
|
gemaltoConfiguration,
|
|
azureConfiguration,
|
|
gcpConfiguration,
|
|
replicas,
|
|
]);
|
|
|
|
const fetchEncryptionInfo = () => {
|
|
if (!refreshEncryptionInfo) {
|
|
setRefreshEncryptionInfo(true);
|
|
api
|
|
.invoke(
|
|
"GET",
|
|
`/api/v1/namespaces/${tenant?.namespace}/tenants/${tenant?.name}/encryption`
|
|
)
|
|
.then((resp: ITenantEncryptionResponse) => {
|
|
if (resp.vault) {
|
|
setEncryptionType("vault");
|
|
setVaultConfiguration(resp.vault);
|
|
if (resp.vault.tls) {
|
|
setVaultClientCertificateSecret(resp.vault.tls.crt);
|
|
setVaultCACertificateSecret(resp.vault.tls.ca);
|
|
}
|
|
} else if (resp.aws) {
|
|
setEncryptionType("aws");
|
|
setAWSConfiguration(resp.aws);
|
|
} else if (resp.gemalto) {
|
|
setEncryptionType("gemalto");
|
|
setGemaltoConfiguration(resp.gemalto);
|
|
if (resp.gemalto.keysecure.tls) {
|
|
setGemaltoCACertificateSecret(resp.gemalto.keysecure.tls.ca);
|
|
}
|
|
} else if (resp.gcp) {
|
|
setEncryptionType("gcp");
|
|
setGCPConfiguration(resp.gcp);
|
|
} else if (resp.azure) {
|
|
setEncryptionType("azure");
|
|
setAzureConfiguration(resp.azure);
|
|
}
|
|
|
|
setEncryptionEnabled(true);
|
|
setImage(resp.image);
|
|
setReplicas(resp.replicas);
|
|
if (resp.securityContext) {
|
|
setSecurityContext(resp.securityContext);
|
|
}
|
|
if (resp.server || resp.mtls_client) {
|
|
setEnabledCustomCertificates(true);
|
|
}
|
|
if (resp.server) {
|
|
setServerTLSCertificateSecret(resp.server);
|
|
}
|
|
if (resp.mtls_client) {
|
|
setMTLSCertificateSecret(resp.mtls_client);
|
|
}
|
|
setRefreshEncryptionInfo(false);
|
|
})
|
|
.catch((err: ErrorResponseHandler) => {
|
|
console.log(err);
|
|
setRefreshEncryptionInfo(false);
|
|
});
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
fetchEncryptionInfo();
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, []);
|
|
|
|
const removeCertificate = (certificateInfo: ICertificateInfo) => {
|
|
setCertificatesToBeRemoved([
|
|
...certificatesToBeRemoved,
|
|
certificateInfo.name,
|
|
]);
|
|
if (certificateInfo.name === serverTLSCertificateSecret?.name) {
|
|
setServerTLSCertificateSecret(null);
|
|
}
|
|
if (certificateInfo.name === mTLSCertificateSecret?.name) {
|
|
setMTLSCertificateSecret(null);
|
|
}
|
|
if (certificateInfo.name === vaultClientCertificateSecret?.name) {
|
|
setVaultClientCertificateSecret(null);
|
|
}
|
|
if (certificateInfo.name === vaultCACertificateSecret?.name) {
|
|
setVaultCACertificateSecret(null);
|
|
}
|
|
if (certificateInfo.name === gemaltoCACertificateSecret?.name) {
|
|
setGemaltoCACertificateSecret(null);
|
|
}
|
|
};
|
|
|
|
const updateEncryptionConfiguration = () => {
|
|
if (encryptionEnabled) {
|
|
let insertEncrypt = {};
|
|
switch (encryptionType) {
|
|
case "gemalto":
|
|
let gemaltoCAIntroduce = {};
|
|
|
|
if (gemaltoCACertificate?.encoded_cert) {
|
|
gemaltoCAIntroduce = {
|
|
tls: {
|
|
ca: gemaltoCACertificate?.encoded_cert,
|
|
},
|
|
};
|
|
}
|
|
insertEncrypt = {
|
|
gemalto: {
|
|
keysecure: {
|
|
endpoint: gemaltoConfiguration?.keysecure?.endpoint || "",
|
|
credentials: {
|
|
token:
|
|
gemaltoConfiguration?.keysecure?.credentials?.token || "",
|
|
domain:
|
|
gemaltoConfiguration?.keysecure?.credentials?.domain || "",
|
|
retry: parseInt(
|
|
gemaltoConfiguration?.keysecure?.credentials?.retry
|
|
),
|
|
},
|
|
...gemaltoCAIntroduce,
|
|
},
|
|
},
|
|
};
|
|
break;
|
|
case "aws":
|
|
insertEncrypt = {
|
|
aws: {
|
|
secretsmanager: {
|
|
endpoint: awsConfiguration?.secretsmanager?.endpoint || "",
|
|
region: awsConfiguration?.secretsmanager?.region || "",
|
|
kmskey: awsConfiguration?.secretsmanager?.kmskey || "",
|
|
credentials: {
|
|
accesskey:
|
|
awsConfiguration?.secretsmanager?.credentials?.accesskey ||
|
|
"",
|
|
secretkey:
|
|
awsConfiguration?.secretsmanager?.credentials?.secretkey ||
|
|
"",
|
|
token:
|
|
awsConfiguration?.secretsmanager?.credentials?.token || "",
|
|
},
|
|
},
|
|
},
|
|
};
|
|
break;
|
|
case "azure":
|
|
insertEncrypt = {
|
|
azure: {
|
|
keyvault: {
|
|
endpoint: azureConfiguration?.keyvault?.endpoint || "",
|
|
credentials: {
|
|
tenant_id:
|
|
azureConfiguration?.keyvault?.credentials?.tenant_id || "",
|
|
client_id:
|
|
azureConfiguration?.keyvault?.credentials?.client_id || "",
|
|
client_secret:
|
|
azureConfiguration?.keyvault?.credentials?.client_secret ||
|
|
"",
|
|
},
|
|
},
|
|
},
|
|
};
|
|
break;
|
|
case "gcp":
|
|
insertEncrypt = {
|
|
gcp: {
|
|
secretmanager: {
|
|
project_id: gcpConfiguration?.secretmanager?.project_id || "",
|
|
endpoint: gcpConfiguration?.secretmanager?.endpoint || "",
|
|
credentials: {
|
|
client_email:
|
|
gcpConfiguration?.secretmanager?.credentials
|
|
?.client_email || "",
|
|
client_id:
|
|
gcpConfiguration?.secretmanager?.credentials?.client_id ||
|
|
"",
|
|
private_key_id:
|
|
gcpConfiguration?.secretmanager?.credentials
|
|
?.private_key_id || "",
|
|
private_key:
|
|
gcpConfiguration?.secretmanager?.credentials?.private_key ||
|
|
"",
|
|
},
|
|
},
|
|
},
|
|
};
|
|
break;
|
|
case "vault":
|
|
let vaultKeyPair = null;
|
|
let vaultCAInsert = null;
|
|
if (
|
|
vaultClientCertificate?.encoded_key &&
|
|
vaultClientCertificate?.encoded_cert
|
|
) {
|
|
vaultKeyPair = {
|
|
key: vaultClientCertificate?.encoded_key,
|
|
crt: vaultClientCertificate?.encoded_cert,
|
|
};
|
|
}
|
|
if (vaultCACertificate?.encoded_cert) {
|
|
vaultCAInsert = {
|
|
ca: vaultCACertificate?.encoded_cert,
|
|
};
|
|
}
|
|
let vaultTLS = null;
|
|
if (vaultKeyPair || vaultCAInsert) {
|
|
vaultTLS = {
|
|
tls: {
|
|
...vaultKeyPair,
|
|
...vaultCAInsert,
|
|
},
|
|
};
|
|
}
|
|
insertEncrypt = {
|
|
vault: {
|
|
endpoint: vaultConfiguration?.endpoint || "",
|
|
engine: vaultConfiguration?.engine || "",
|
|
namespace: vaultConfiguration?.namespace || "",
|
|
prefix: vaultConfiguration?.prefix || "",
|
|
approle: {
|
|
engine: vaultConfiguration?.approle?.engine || "",
|
|
id: vaultConfiguration?.approle?.id || "",
|
|
secret: vaultConfiguration?.approle?.secret || "",
|
|
retry: parseInt(vaultConfiguration?.approle?.retry),
|
|
},
|
|
...vaultTLS,
|
|
status: {
|
|
ping: parseInt(vaultConfiguration?.status?.ping),
|
|
},
|
|
},
|
|
};
|
|
break;
|
|
}
|
|
|
|
let encryptionServerKeyPair: any = {};
|
|
let encryptionClientKeyPair: any = {};
|
|
|
|
if (mTLSCertificate?.encoded_key && mTLSCertificate?.encoded_cert) {
|
|
encryptionClientKeyPair = {
|
|
client: {
|
|
key: mTLSCertificate?.encoded_key,
|
|
crt: mTLSCertificate?.encoded_cert,
|
|
},
|
|
};
|
|
}
|
|
|
|
if (serverCertificate?.encoded_key && serverCertificate?.encoded_cert) {
|
|
encryptionServerKeyPair = {
|
|
server: {
|
|
key: serverCertificate?.encoded_key,
|
|
crt: serverCertificate?.encoded_cert,
|
|
},
|
|
};
|
|
}
|
|
const dataSend = {
|
|
secretsToBeDeleted: certificatesToBeRemoved || [],
|
|
replicas: replicas,
|
|
securityContext: securityContext,
|
|
image: image,
|
|
...encryptionClientKeyPair,
|
|
...encryptionServerKeyPair,
|
|
...insertEncrypt,
|
|
};
|
|
if (!updatingEncryption) {
|
|
setUpdatingEncryption(true);
|
|
api
|
|
.invoke(
|
|
"PUT",
|
|
`/api/v1/namespaces/${tenant?.namespace}/tenants/${tenant?.name}/encryption`,
|
|
dataSend
|
|
)
|
|
.then(() => {
|
|
setConfirmOpen(false);
|
|
setUpdatingEncryption(false);
|
|
fetchEncryptionInfo();
|
|
})
|
|
.catch((err: ErrorResponseHandler) => {
|
|
setUpdatingEncryption(false);
|
|
setConfirmOpen(false);
|
|
setErrorSnackMessage(err);
|
|
});
|
|
}
|
|
} else {
|
|
if (!updatingEncryption) {
|
|
setUpdatingEncryption(true);
|
|
api
|
|
.invoke(
|
|
"DELETE",
|
|
`/api/v1/namespaces/${tenant?.namespace}/tenants/${tenant?.name}/encryption`,
|
|
{}
|
|
)
|
|
.then(() => {
|
|
fetchEncryptionInfo();
|
|
setUpdatingEncryption(false);
|
|
})
|
|
.catch((err: ErrorResponseHandler) => {
|
|
setUpdatingEncryption(false);
|
|
setErrorSnackMessage(err);
|
|
});
|
|
}
|
|
}
|
|
};
|
|
|
|
return (
|
|
<React.Fragment>
|
|
<Fragment>
|
|
{confirmOpen && (
|
|
<ConfirmDialog
|
|
isOpen={confirmOpen}
|
|
title={
|
|
encryptionEnabled
|
|
? "Enable encryption at rest for tenant?"
|
|
: "Disable encryption at rest for tenant?"
|
|
}
|
|
confirmText={encryptionEnabled ? "Enable" : "Disable"}
|
|
cancelText="Cancel"
|
|
onClose={() => setConfirmOpen(false)}
|
|
onConfirm={updateEncryptionConfiguration}
|
|
confirmationContent={
|
|
<DialogContentText>
|
|
{encryptionEnabled
|
|
? "Data will be encrypted using and external KMS"
|
|
: "Current encrypted information will not be accessible"}
|
|
</DialogContentText>
|
|
}
|
|
/>
|
|
)}
|
|
<h1 className={classes.sectionTitle}>Encryption</h1>
|
|
<div className={classes.actionsTray}>
|
|
<FormSwitchWrapper
|
|
label={"Encryption at rest"}
|
|
indicatorLabels={["Enabled", "Disabled"]}
|
|
checked={encryptionEnabled}
|
|
value={"tenant_encryption"}
|
|
id="tenant-encryption"
|
|
name="tenant-encryption"
|
|
onChange={(e) => {
|
|
setEncryptionEnabled(!encryptionEnabled);
|
|
}}
|
|
description=""
|
|
/>
|
|
</div>
|
|
{encryptionEnabled && (
|
|
<Paper className={classes.paperWrapper} style={{ marginBottom: 15 }}>
|
|
<Grid container style={{}}>
|
|
<Grid item xs={12} className={classes.encryptionTypeOptions}>
|
|
<RadioGroupSelector
|
|
currentSelection={encryptionType}
|
|
id="encryptionType"
|
|
name="encryptionType"
|
|
label="Encryption Options"
|
|
onChange={(e) => {
|
|
setEncryptionType(e.target.value);
|
|
}}
|
|
selectorOptions={[
|
|
{ label: "Vault", value: "vault" },
|
|
{ label: "AWS", value: "aws" },
|
|
{ label: "Gemalto", value: "gemalto" },
|
|
{ label: "GCP", value: "gcp" },
|
|
{ label: "Azure", value: "azure" },
|
|
]}
|
|
/>
|
|
</Grid>
|
|
{encryptionType === "vault" && (
|
|
<Fragment>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
id="vault_endpoint"
|
|
name="vault_endpoint"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setVaultConfiguration({
|
|
...vaultConfiguration,
|
|
endpoint: e.target.value,
|
|
})
|
|
}
|
|
label="Endpoint"
|
|
value={vaultConfiguration?.endpoint || ""}
|
|
error={validationErrors["vault_ping"] || ""}
|
|
required
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
id="vault_engine"
|
|
name="vault_engine"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setVaultConfiguration({
|
|
...vaultConfiguration,
|
|
engine: e.target.value,
|
|
})
|
|
}
|
|
label="Engine"
|
|
value={vaultConfiguration?.engine || ""}
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
id="vault_namespace"
|
|
name="vault_namespace"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setVaultConfiguration({
|
|
...vaultConfiguration,
|
|
namespace: e.target.value,
|
|
})
|
|
}
|
|
label="Namespace"
|
|
value={vaultConfiguration?.namespace || ""}
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
id="vault_prefix"
|
|
name="vault_prefix"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setVaultConfiguration({
|
|
...vaultConfiguration,
|
|
prefix: e.target.value,
|
|
})
|
|
}
|
|
label="Prefix"
|
|
value={vaultConfiguration?.prefix || ""}
|
|
/>
|
|
</Grid>
|
|
|
|
<Grid item xs={12}>
|
|
<fieldset className={classes.fieldGroup}>
|
|
<legend className={classes.descriptionText}>
|
|
App Role
|
|
</legend>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
id="vault_approle_engine"
|
|
name="vault_approle_engine"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setVaultConfiguration({
|
|
...vaultConfiguration,
|
|
approle: {
|
|
...vaultConfiguration?.approle,
|
|
engine: e.target.value,
|
|
},
|
|
})
|
|
}
|
|
label="Engine"
|
|
value={vaultConfiguration?.approle?.engine || ""}
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
type={showVaultAppRoleID ? "text" : "password"}
|
|
id="vault_id"
|
|
name="vault_id"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setVaultConfiguration({
|
|
...vaultConfiguration,
|
|
approle: {
|
|
...vaultConfiguration?.approle,
|
|
id: e.target.value,
|
|
},
|
|
})
|
|
}
|
|
label="AppRole ID"
|
|
value={vaultConfiguration?.approle?.id || ""}
|
|
required
|
|
error={validationErrors["vault_id"] || ""}
|
|
overlayIcon={
|
|
showVaultAppRoleID ? (
|
|
<VisibilityOffIcon />
|
|
) : (
|
|
<RemoveRedEyeIcon />
|
|
)
|
|
}
|
|
overlayAction={() =>
|
|
setShowVaultAppRoleID(!showVaultAppRoleID)
|
|
}
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
type={showVaultAppRoleSecret ? "text" : "password"}
|
|
id="vault_secret"
|
|
name="vault_secret"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setVaultConfiguration({
|
|
...vaultConfiguration,
|
|
approle: {
|
|
...vaultConfiguration?.approle,
|
|
secret: e.target.value,
|
|
},
|
|
})
|
|
}
|
|
label="AppRole Secret"
|
|
value={vaultConfiguration?.approle?.secret || ""}
|
|
required
|
|
error={validationErrors["vault_secret"] || ""}
|
|
overlayIcon={
|
|
showVaultAppRoleSecret ? (
|
|
<VisibilityOffIcon />
|
|
) : (
|
|
<RemoveRedEyeIcon />
|
|
)
|
|
}
|
|
overlayAction={() =>
|
|
setShowVaultAppRoleSecret(!showVaultAppRoleSecret)
|
|
}
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
type="number"
|
|
min="0"
|
|
id="vault_retry"
|
|
name="vault_retry"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setVaultConfiguration({
|
|
...vaultConfiguration,
|
|
approle: {
|
|
...vaultConfiguration?.approle,
|
|
retry: e.target.value,
|
|
},
|
|
})
|
|
}
|
|
label="Retry (Seconds)"
|
|
error={validationErrors["vault_retry"] || ""}
|
|
value={vaultConfiguration?.approle?.retry || ""}
|
|
/>
|
|
</Grid>
|
|
</fieldset>
|
|
</Grid>
|
|
<Grid container className={classes.mutualTlsConfig}>
|
|
<fieldset className={classes.fieldGroup}>
|
|
<legend className={classes.descriptionText}>
|
|
Mutual TLS authentication with KMS (optional)
|
|
</legend>
|
|
{vaultClientCertificateSecret ? (
|
|
<Chip
|
|
key={vaultClientCertificateSecret.name}
|
|
variant="outlined"
|
|
color="primary"
|
|
className={classes.certificateInfo}
|
|
label={
|
|
<div>
|
|
<Typography
|
|
variant="subtitle1"
|
|
display="block"
|
|
gutterBottom
|
|
>
|
|
{vaultClientCertificateSecret.name}
|
|
</Typography>
|
|
<Typography
|
|
className={classes.italic}
|
|
variant="caption"
|
|
display="block"
|
|
gutterBottom
|
|
>
|
|
{vaultClientCertificateSecret.domains &&
|
|
vaultClientCertificateSecret.domains.map(
|
|
(dom) => {
|
|
return <div>{dom}</div>;
|
|
}
|
|
)}
|
|
</Typography>
|
|
<Typography
|
|
className={classes.bold}
|
|
variant="overline"
|
|
gutterBottom
|
|
>
|
|
Expiry:
|
|
</Typography>
|
|
<Typography variant="caption" gutterBottom>
|
|
<Moment format="YYYY-MM-DD">
|
|
{vaultClientCertificateSecret.expiry}
|
|
</Moment>
|
|
</Typography>
|
|
</div>
|
|
}
|
|
onDelete={() =>
|
|
removeCertificate(vaultClientCertificateSecret)
|
|
}
|
|
/>
|
|
) : (
|
|
<Fragment>
|
|
<FileSelector
|
|
onChange={(encodedValue, fileName) =>
|
|
setVaultClientCertificate({
|
|
encoded_key: encodedValue || "",
|
|
id: vaultClientCertificate?.id || "",
|
|
key: fileName || "",
|
|
cert: vaultClientCertificate?.cert || "",
|
|
encoded_cert:
|
|
vaultClientCertificate?.encoded_cert || "",
|
|
})
|
|
}
|
|
accept=".key,.pem"
|
|
id="vault_key"
|
|
name="vault_key"
|
|
label="Key"
|
|
value={vaultClientCertificate?.key || ""}
|
|
/>
|
|
<FileSelector
|
|
onChange={(encodedValue, fileName) =>
|
|
setVaultClientCertificate({
|
|
encoded_key:
|
|
vaultClientCertificate?.encoded_key || "",
|
|
id: vaultClientCertificate?.id || "",
|
|
key: vaultClientCertificate?.key || "",
|
|
cert: fileName || "",
|
|
encoded_cert: encodedValue || "",
|
|
})
|
|
}
|
|
accept=".cer,.crt,.cert,.pem"
|
|
id="vault_cert"
|
|
name="vault_cert"
|
|
label="Cert"
|
|
value={vaultClientCertificate?.cert || ""}
|
|
/>
|
|
</Fragment>
|
|
)}
|
|
</fieldset>
|
|
<fieldset className={classes.fieldGroup}>
|
|
<legend className={classes.descriptionText}>
|
|
KMS CA certificate (optional)
|
|
</legend>
|
|
{vaultCACertificateSecret ? (
|
|
<Chip
|
|
key={vaultCACertificateSecret.name}
|
|
variant="outlined"
|
|
color="primary"
|
|
className={classes.certificateInfo}
|
|
label={
|
|
<div>
|
|
<Typography
|
|
variant="subtitle1"
|
|
display="block"
|
|
gutterBottom
|
|
>
|
|
{vaultCACertificateSecret.name}
|
|
</Typography>
|
|
<Typography
|
|
className={classes.italic}
|
|
variant="caption"
|
|
display="block"
|
|
gutterBottom
|
|
>
|
|
{vaultCACertificateSecret.domains &&
|
|
vaultCACertificateSecret.domains.map(
|
|
(dom) => {
|
|
return <div>{dom}</div>;
|
|
}
|
|
)}
|
|
</Typography>
|
|
<Typography
|
|
className={classes.bold}
|
|
variant="overline"
|
|
gutterBottom
|
|
>
|
|
Expiry:
|
|
</Typography>
|
|
<Typography variant="caption" gutterBottom>
|
|
<Moment format="YYYY-MM-DD">
|
|
{vaultCACertificateSecret.expiry}
|
|
</Moment>
|
|
</Typography>
|
|
</div>
|
|
}
|
|
onDelete={() =>
|
|
removeCertificate(vaultCACertificateSecret)
|
|
}
|
|
/>
|
|
) : (
|
|
<FileSelector
|
|
onChange={(encodedValue, fileName) =>
|
|
setVaultCACertificate({
|
|
encoded_key:
|
|
vaultCACertificate?.encoded_key || "",
|
|
id: vaultCACertificate?.id || "",
|
|
key: vaultCACertificate?.key || "",
|
|
cert: fileName || "",
|
|
encoded_cert: encodedValue || "",
|
|
})
|
|
}
|
|
accept=".cer,.crt,.cert,.pem"
|
|
id="vault_ca"
|
|
name="vault_ca"
|
|
label="CA"
|
|
value={vaultCACertificate?.cert || ""}
|
|
/>
|
|
)}
|
|
</fieldset>
|
|
</Grid>
|
|
<Grid
|
|
item
|
|
xs={12}
|
|
className={classes.formFieldRow}
|
|
style={{ marginTop: 15 }}
|
|
>
|
|
<fieldset className={classes.fieldGroup}>
|
|
<legend className={classes.descriptionText}>
|
|
Status
|
|
</legend>
|
|
<InputBoxWrapper
|
|
type="number"
|
|
min="0"
|
|
id="vault_ping"
|
|
name="vault_ping"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setVaultConfiguration({
|
|
...vaultConfiguration,
|
|
status: {
|
|
...vaultConfiguration?.status,
|
|
ping: e.target.value,
|
|
},
|
|
})
|
|
}
|
|
label="Ping (Seconds)"
|
|
error={validationErrors["vault_ping"] || ""}
|
|
value={vaultConfiguration?.status?.ping || ""}
|
|
/>
|
|
</fieldset>
|
|
</Grid>
|
|
</Fragment>
|
|
)}
|
|
{encryptionType === "azure" && (
|
|
<Fragment>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
id="azure_endpoint"
|
|
name="azure_endpoint"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setAzureConfiguration({
|
|
...azureConfiguration,
|
|
keyvault: {
|
|
...azureConfiguration?.keyvault,
|
|
endpoint: e.target.value,
|
|
},
|
|
})
|
|
}
|
|
label="Endpoint"
|
|
error={validationErrors["azure_endpoint"] || ""}
|
|
value={azureConfiguration?.keyvault?.endpoint || ""}
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12}>
|
|
<fieldset className={classes.fieldGroup}>
|
|
<legend className={classes.descriptionText}>
|
|
Credentials
|
|
</legend>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
id="azure_tenant_id"
|
|
name="azure_tenant_id"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setAzureConfiguration({
|
|
...azureConfiguration,
|
|
keyvault: {
|
|
...azureConfiguration?.keyvault,
|
|
credentials: {
|
|
...azureConfiguration?.keyvault?.credentials,
|
|
tenant_id: e.target.value,
|
|
},
|
|
},
|
|
})
|
|
}
|
|
label="Tenant ID"
|
|
value={
|
|
azureConfiguration?.keyvault?.credentials
|
|
?.tenant_id || ""
|
|
}
|
|
error={validationErrors["azure_tenant_id"] || ""}
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
id="azure_client_id"
|
|
name="azure_client_id"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setAzureConfiguration({
|
|
...azureConfiguration,
|
|
keyvault: {
|
|
...azureConfiguration?.keyvault,
|
|
credentials: {
|
|
...azureConfiguration?.keyvault?.credentials,
|
|
client_id: e.target.value,
|
|
},
|
|
},
|
|
})
|
|
}
|
|
label="Client ID"
|
|
value={
|
|
azureConfiguration?.keyvault?.credentials
|
|
?.client_id || ""
|
|
}
|
|
error={validationErrors["azure_client_id"] || ""}
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
id="azure_client_secret"
|
|
name="azure_client_secret"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setAzureConfiguration({
|
|
...azureConfiguration,
|
|
keyvault: {
|
|
...azureConfiguration?.keyvault,
|
|
credentials: {
|
|
...azureConfiguration?.keyvault?.credentials,
|
|
client_secret: e.target.value,
|
|
},
|
|
},
|
|
})
|
|
}
|
|
label="Client Secret"
|
|
value={
|
|
azureConfiguration?.keyvault?.credentials
|
|
?.client_secret || ""
|
|
}
|
|
error={validationErrors["azure_client_secret"] || ""}
|
|
/>
|
|
</Grid>
|
|
</fieldset>
|
|
</Grid>
|
|
</Fragment>
|
|
)}
|
|
{encryptionType === "gcp" && (
|
|
<Fragment>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
id="gcp_project_id"
|
|
name="gcp_project_id"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setGCPConfiguration({
|
|
...gcpConfiguration,
|
|
secretmanager: {
|
|
...gcpConfiguration?.secretmanager,
|
|
project_id: e.target.value,
|
|
},
|
|
})
|
|
}
|
|
label="Project ID"
|
|
value={gcpConfiguration?.secretmanager.project_id || ""}
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
id="gcp_endpoint"
|
|
name="gcp_endpoint"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setGCPConfiguration({
|
|
...gcpConfiguration,
|
|
secretmanager: {
|
|
...gcpConfiguration?.secretmanager,
|
|
endpoint: e.target.value,
|
|
},
|
|
})
|
|
}
|
|
label="Endpoint"
|
|
value={gcpConfiguration?.secretmanager.endpoint || ""}
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12}>
|
|
<fieldset className={classes.fieldGroup}>
|
|
<legend className={classes.descriptionText}>
|
|
Credentials
|
|
</legend>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
id="gcp_client_email"
|
|
name="gcp_client_email"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setGCPConfiguration({
|
|
...gcpConfiguration,
|
|
secretmanager: {
|
|
...gcpConfiguration?.secretmanager,
|
|
credentials: {
|
|
...gcpConfiguration?.secretmanager
|
|
.credentials,
|
|
client_email: e.target.value,
|
|
},
|
|
},
|
|
})
|
|
}
|
|
label="Client Email"
|
|
value={
|
|
gcpConfiguration?.secretmanager.credentials
|
|
?.client_email || ""
|
|
}
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
id="gcp_client_id"
|
|
name="gcp_client_id"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setGCPConfiguration({
|
|
...gcpConfiguration,
|
|
secretmanager: {
|
|
...gcpConfiguration?.secretmanager,
|
|
credentials: {
|
|
...gcpConfiguration?.secretmanager
|
|
.credentials,
|
|
client_id: e.target.value,
|
|
},
|
|
},
|
|
})
|
|
}
|
|
label="Client ID"
|
|
value={
|
|
gcpConfiguration?.secretmanager.credentials
|
|
?.client_id || ""
|
|
}
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
id="gcp_private_key_id"
|
|
name="gcp_private_key_id"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setGCPConfiguration({
|
|
...gcpConfiguration,
|
|
secretmanager: {
|
|
...gcpConfiguration?.secretmanager,
|
|
credentials: {
|
|
...gcpConfiguration?.secretmanager
|
|
.credentials,
|
|
private_key_id: e.target.value,
|
|
},
|
|
},
|
|
})
|
|
}
|
|
label="Private Key ID"
|
|
value={
|
|
gcpConfiguration?.secretmanager.credentials
|
|
?.private_key_id || ""
|
|
}
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
id="gcp_private_key"
|
|
name="gcp_private_key"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setGCPConfiguration({
|
|
...gcpConfiguration,
|
|
secretmanager: {
|
|
...gcpConfiguration?.secretmanager,
|
|
credentials: {
|
|
...gcpConfiguration?.secretmanager
|
|
.credentials,
|
|
private_key: e.target.value,
|
|
},
|
|
},
|
|
})
|
|
}
|
|
label="Private Key"
|
|
value={
|
|
gcpConfiguration?.secretmanager.credentials
|
|
?.private_key || ""
|
|
}
|
|
/>
|
|
</Grid>
|
|
</fieldset>
|
|
</Grid>
|
|
</Fragment>
|
|
)}
|
|
{encryptionType === "aws" && (
|
|
<Fragment>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
id="aws_endpoint"
|
|
name="aws_endpoint"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setAWSConfiguration({
|
|
...awsConfiguration,
|
|
secretsmanager: {
|
|
...awsConfiguration?.secretsmanager,
|
|
endpoint: e.target.value,
|
|
},
|
|
})
|
|
}
|
|
label="Endpoint"
|
|
value={awsConfiguration?.secretsmanager?.endpoint || ""}
|
|
required
|
|
error={validationErrors["aws_endpoint"] || ""}
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
id="aws_region"
|
|
name="aws_region"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setAWSConfiguration({
|
|
...awsConfiguration,
|
|
secretsmanager: {
|
|
...awsConfiguration?.secretsmanager,
|
|
region: e.target.value,
|
|
},
|
|
})
|
|
}
|
|
label="Region"
|
|
value={awsConfiguration?.secretsmanager?.region || ""}
|
|
error={validationErrors["aws_region"] || ""}
|
|
required
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
id="aws_kmsKey"
|
|
name="aws_kmsKey"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setAWSConfiguration({
|
|
...awsConfiguration,
|
|
secretsmanager: {
|
|
...awsConfiguration?.secretsmanager,
|
|
kmskey: e.target.value,
|
|
},
|
|
})
|
|
}
|
|
label="KMS Key"
|
|
value={awsConfiguration?.secretsmanager?.kmskey || ""}
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12}>
|
|
<fieldset className={classes.fieldGroup}>
|
|
<legend className={classes.descriptionText}>
|
|
Credentials
|
|
</legend>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
id="aws_accessKey"
|
|
name="aws_accessKey"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setAWSConfiguration({
|
|
...awsConfiguration,
|
|
secretsmanager: {
|
|
...awsConfiguration?.secretsmanager,
|
|
credentials: {
|
|
...awsConfiguration?.secretsmanager
|
|
?.credentials,
|
|
accesskey: e.target.value,
|
|
},
|
|
},
|
|
})
|
|
}
|
|
label="Access Key"
|
|
value={
|
|
awsConfiguration?.secretsmanager?.credentials
|
|
?.accesskey || ""
|
|
}
|
|
error={validationErrors["aws_accessKey"] || ""}
|
|
required
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
id="aws_secretKey"
|
|
name="aws_secretKey"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setAWSConfiguration({
|
|
...awsConfiguration,
|
|
secretsmanager: {
|
|
...awsConfiguration?.secretsmanager,
|
|
credentials: {
|
|
...awsConfiguration?.secretsmanager
|
|
?.credentials,
|
|
secretkey: e.target.value,
|
|
},
|
|
},
|
|
})
|
|
}
|
|
label="Secret Key"
|
|
value={
|
|
awsConfiguration?.secretsmanager?.credentials
|
|
?.secretkey || ""
|
|
}
|
|
error={validationErrors["aws_secretKey"] || ""}
|
|
required
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
id="aws_token"
|
|
name="aws_token"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setAWSConfiguration({
|
|
...awsConfiguration,
|
|
secretsmanager: {
|
|
...awsConfiguration?.secretsmanager,
|
|
credentials: {
|
|
...awsConfiguration?.secretsmanager
|
|
?.credentials,
|
|
token: e.target.value,
|
|
},
|
|
},
|
|
})
|
|
}
|
|
label="Token"
|
|
value={
|
|
awsConfiguration?.secretsmanager?.credentials
|
|
?.token || ""
|
|
}
|
|
/>
|
|
</Grid>
|
|
</fieldset>
|
|
</Grid>
|
|
</Fragment>
|
|
)}
|
|
{encryptionType === "gemalto" && (
|
|
<Fragment>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
id="gemalto_endpoint"
|
|
name="gemalto_endpoint"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setGemaltoConfiguration({
|
|
...gemaltoConfiguration,
|
|
keysecure: {
|
|
...gemaltoConfiguration?.keysecure,
|
|
endpoint: e.target.value,
|
|
},
|
|
})
|
|
}
|
|
label="Endpoint"
|
|
value={gemaltoConfiguration?.keysecure?.endpoint || ""}
|
|
error={validationErrors["gemalto_endpoint"] || ""}
|
|
required
|
|
/>
|
|
</Grid>
|
|
<Grid
|
|
item
|
|
xs={12}
|
|
style={{
|
|
marginBottom: 15,
|
|
}}
|
|
>
|
|
<fieldset className={classes.fieldGroup}>
|
|
<legend className={classes.descriptionText}>
|
|
Credentials
|
|
</legend>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
id="gemalto_token"
|
|
name="gemalto_token"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setGemaltoConfiguration({
|
|
...gemaltoConfiguration,
|
|
keysecure: {
|
|
...gemaltoConfiguration?.keysecure,
|
|
credentials: {
|
|
...gemaltoConfiguration?.keysecure
|
|
?.credentials,
|
|
token: e.target.value,
|
|
},
|
|
},
|
|
})
|
|
}
|
|
label="Token"
|
|
value={
|
|
gemaltoConfiguration?.keysecure?.credentials
|
|
?.token || ""
|
|
}
|
|
error={validationErrors["gemalto_token"] || ""}
|
|
required
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
id="gemalto_domain"
|
|
name="gemalto_domain"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setGemaltoConfiguration({
|
|
...gemaltoConfiguration,
|
|
keysecure: {
|
|
...gemaltoConfiguration?.keysecure,
|
|
credentials: {
|
|
...gemaltoConfiguration?.keysecure
|
|
?.credentials,
|
|
domain: e.target.value,
|
|
},
|
|
},
|
|
})
|
|
}
|
|
label="Domain"
|
|
value={
|
|
gemaltoConfiguration?.keysecure?.credentials
|
|
?.domain || ""
|
|
}
|
|
error={validationErrors["gemalto_domain"] || ""}
|
|
required
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} className={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
type="number"
|
|
min="0"
|
|
id="gemalto_retry"
|
|
name="gemalto_retry"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setGemaltoConfiguration({
|
|
...gemaltoConfiguration,
|
|
keysecure: {
|
|
...gemaltoConfiguration?.keysecure,
|
|
credentials: {
|
|
...gemaltoConfiguration?.keysecure
|
|
?.credentials,
|
|
retry: e.target.value,
|
|
},
|
|
},
|
|
})
|
|
}
|
|
label="Retry (seconds)"
|
|
value={
|
|
gemaltoConfiguration?.keysecure?.credentials
|
|
?.retry || ""
|
|
}
|
|
error={validationErrors["gemalto_retry"] || ""}
|
|
/>
|
|
</Grid>
|
|
</fieldset>
|
|
</Grid>
|
|
<Grid
|
|
item
|
|
xs={12}
|
|
style={{
|
|
marginBottom: 15,
|
|
}}
|
|
>
|
|
<fieldset className={classes.fieldGroup}>
|
|
<legend className={classes.descriptionText}>
|
|
Custom CA Root certificate verification
|
|
</legend>
|
|
<FileSelector
|
|
onChange={(encodedValue, fileName) => {}}
|
|
accept=".cer,.crt,.cert,.pem"
|
|
id="gemalto_ca"
|
|
name="gemalto_ca"
|
|
label="CA"
|
|
value={""}
|
|
/>
|
|
{gemaltoCACertificateSecret ? (
|
|
<Chip
|
|
key={gemaltoCACertificateSecret.name}
|
|
variant="outlined"
|
|
color="primary"
|
|
className={classes.certificateInfo}
|
|
label={
|
|
<div>
|
|
<Typography
|
|
variant="subtitle1"
|
|
display="block"
|
|
gutterBottom
|
|
>
|
|
{gemaltoCACertificateSecret.name}
|
|
</Typography>
|
|
<Typography
|
|
className={classes.italic}
|
|
variant="caption"
|
|
display="block"
|
|
gutterBottom
|
|
>
|
|
{gemaltoCACertificateSecret.domains &&
|
|
gemaltoCACertificateSecret.domains.map(
|
|
(dom) => {
|
|
return <div>{dom}</div>;
|
|
}
|
|
)}
|
|
</Typography>
|
|
<Typography
|
|
className={classes.bold}
|
|
variant="overline"
|
|
gutterBottom
|
|
>
|
|
Expiry:
|
|
</Typography>
|
|
<Typography variant="caption" gutterBottom>
|
|
<Moment format="YYYY-MM-DD">
|
|
{gemaltoCACertificateSecret.expiry}
|
|
</Moment>
|
|
</Typography>
|
|
</div>
|
|
}
|
|
onDelete={() =>
|
|
removeCertificate(gemaltoCACertificateSecret)
|
|
}
|
|
/>
|
|
) : (
|
|
<FileSelector
|
|
onChange={(encodedValue, fileName) =>
|
|
setGemaltotCACertificate({
|
|
encoded_key:
|
|
gemaltoCACertificate?.encoded_key || "",
|
|
id: gemaltoCACertificate?.id || "",
|
|
key: gemaltoCACertificate?.key || "",
|
|
cert: fileName || "",
|
|
encoded_cert: encodedValue || "",
|
|
})
|
|
}
|
|
accept=".cer,.crt,.cert,.pem"
|
|
id="gemalto_ca"
|
|
name="gemalto_ca"
|
|
label="CA"
|
|
value={gemaltoCACertificate?.cert || ""}
|
|
/>
|
|
)}
|
|
</fieldset>
|
|
</Grid>
|
|
</Fragment>
|
|
)}
|
|
<div className={classes.headerElement}>
|
|
<h4 className={classes.h3Section}>Additional Configurations</h4>
|
|
</div>
|
|
<Grid item xs={12}>
|
|
<FormSwitchWrapper
|
|
value="enableCustomCertsForKES"
|
|
id="enableCustomCertsForKES"
|
|
name="enableCustomCertsForKES"
|
|
checked={enabledCustomCertificates}
|
|
onChange={(e) =>
|
|
setEnabledCustomCertificates(!enabledCustomCertificates)
|
|
}
|
|
label={"Custom Certificates"}
|
|
/>
|
|
</Grid>
|
|
{enabledCustomCertificates && (
|
|
<Fragment>
|
|
<Grid container>
|
|
<Grid item xs={12} style={{ marginBottom: 15 }}>
|
|
<fieldset className={classes.fieldGroup}>
|
|
<legend className={classes.descriptionText}>
|
|
Encryption Service Certificates
|
|
</legend>
|
|
{serverTLSCertificateSecret ? (
|
|
<Chip
|
|
key={serverTLSCertificateSecret.name}
|
|
variant="outlined"
|
|
color="primary"
|
|
className={classes.certificateInfo}
|
|
label={
|
|
<div>
|
|
<Typography
|
|
variant="subtitle1"
|
|
display="block"
|
|
gutterBottom
|
|
>
|
|
{serverTLSCertificateSecret.name}
|
|
</Typography>
|
|
<Typography
|
|
className={classes.italic}
|
|
variant="caption"
|
|
display="block"
|
|
gutterBottom
|
|
>
|
|
{serverTLSCertificateSecret.domains &&
|
|
serverTLSCertificateSecret.domains.map(
|
|
(dom) => {
|
|
return <div>{dom}</div>;
|
|
}
|
|
)}
|
|
</Typography>
|
|
<Typography
|
|
className={classes.bold}
|
|
variant="overline"
|
|
gutterBottom
|
|
>
|
|
Expiry:
|
|
</Typography>
|
|
<Typography variant="caption" gutterBottom>
|
|
<Moment format="YYYY-MM-DD">
|
|
{serverTLSCertificateSecret.expiry}
|
|
</Moment>
|
|
</Typography>
|
|
</div>
|
|
}
|
|
onDelete={() =>
|
|
removeCertificate(serverTLSCertificateSecret)
|
|
}
|
|
/>
|
|
) : (
|
|
<Fragment>
|
|
<FileSelector
|
|
onChange={(encodedValue, fileName) => {
|
|
setServerCertificate({
|
|
encoded_key: encodedValue || "",
|
|
id: serverCertificate?.id || "",
|
|
key: fileName || "",
|
|
cert: serverCertificate?.cert || "",
|
|
encoded_cert:
|
|
serverCertificate?.encoded_cert || "",
|
|
});
|
|
cleanValidation("serverKey");
|
|
}}
|
|
accept=".key,.pem"
|
|
id="serverKey"
|
|
name="serverKey"
|
|
label="Key"
|
|
value={serverCertificate?.key}
|
|
/>
|
|
<FileSelector
|
|
onChange={(encodedValue, fileName) => {
|
|
setServerCertificate({
|
|
encoded_key:
|
|
serverCertificate?.encoded_key || "",
|
|
id: serverCertificate?.id || "",
|
|
key: serverCertificate?.key || "",
|
|
cert: fileName || "",
|
|
encoded_cert: encodedValue || "",
|
|
});
|
|
cleanValidation("serverCert");
|
|
}}
|
|
accept=".cer,.crt,.cert,.pem"
|
|
id="serverCert"
|
|
name="serverCert"
|
|
label="Cert"
|
|
value={serverCertificate?.cert}
|
|
/>
|
|
</Fragment>
|
|
)}
|
|
</fieldset>
|
|
</Grid>
|
|
</Grid>
|
|
<Grid container style={{ marginBottom: 15 }}>
|
|
<Grid item xs={12}>
|
|
<fieldset className={classes.fieldGroup}>
|
|
<legend className={classes.descriptionText}>
|
|
Mutual TLS authentication with MinIO
|
|
</legend>
|
|
{mTLSCertificateSecret ? (
|
|
<Chip
|
|
key={mTLSCertificateSecret.name}
|
|
variant="outlined"
|
|
color="primary"
|
|
className={classes.certificateInfo}
|
|
label={
|
|
<div>
|
|
<Typography
|
|
variant="subtitle1"
|
|
display="block"
|
|
gutterBottom
|
|
>
|
|
{mTLSCertificateSecret.name}
|
|
</Typography>
|
|
<Typography
|
|
className={classes.italic}
|
|
variant="caption"
|
|
display="block"
|
|
gutterBottom
|
|
>
|
|
{mTLSCertificateSecret.domains &&
|
|
mTLSCertificateSecret.domains.map((dom) => {
|
|
return <div>{dom}</div>;
|
|
})}
|
|
</Typography>
|
|
<Typography
|
|
className={classes.bold}
|
|
variant="overline"
|
|
gutterBottom
|
|
>
|
|
Expiry:
|
|
</Typography>
|
|
<Typography variant="caption" gutterBottom>
|
|
<Moment format="YYYY-MM-DD">
|
|
{mTLSCertificateSecret.expiry}
|
|
</Moment>
|
|
</Typography>
|
|
</div>
|
|
}
|
|
onDelete={() =>
|
|
removeCertificate(mTLSCertificateSecret)
|
|
}
|
|
/>
|
|
) : (
|
|
<Fragment>
|
|
<FileSelector
|
|
onChange={(encodedValue, fileName) => {
|
|
setMTLSCertificate({
|
|
encoded_key: encodedValue || "",
|
|
id: mTLSCertificate?.id || "",
|
|
key: fileName || "",
|
|
cert: mTLSCertificate?.cert || "",
|
|
encoded_cert:
|
|
mTLSCertificate?.encoded_cert || "",
|
|
});
|
|
cleanValidation("clientKey");
|
|
}}
|
|
accept=".key,.pem"
|
|
id="clientKey"
|
|
name="clientKey"
|
|
label="Key"
|
|
value={mTLSCertificate?.key}
|
|
/>
|
|
<FileSelector
|
|
onChange={(encodedValue, fileName) => {
|
|
setMTLSCertificate({
|
|
encoded_key:
|
|
mTLSCertificate?.encoded_key || "",
|
|
id: mTLSCertificate?.id || "",
|
|
key: mTLSCertificate?.key || "",
|
|
cert: fileName || "",
|
|
encoded_cert: encodedValue || "",
|
|
});
|
|
cleanValidation("clientCert");
|
|
}}
|
|
accept=".cer,.crt,.cert,.pem"
|
|
id="clientCert"
|
|
name="clientCert"
|
|
label="Cert"
|
|
value={mTLSCertificate?.cert}
|
|
/>
|
|
</Fragment>
|
|
)}
|
|
</fieldset>
|
|
</Grid>
|
|
</Grid>
|
|
</Fragment>
|
|
)}
|
|
<Grid item xs={12}>
|
|
<Grid item xs={12} classes={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
type="text"
|
|
id="image"
|
|
name="image"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setImage(e.target.value)
|
|
}
|
|
label="Image"
|
|
placeholder="minio/kes:v0.17.6"
|
|
value={image}
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} classes={classes.formFieldRow}>
|
|
<InputBoxWrapper
|
|
type="number"
|
|
min="1"
|
|
id="replicas"
|
|
name="replicas"
|
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
setReplicas(e.target.value)
|
|
}
|
|
label="Replicas"
|
|
value={replicas}
|
|
required
|
|
error={validationErrors["replicas"] || ""}
|
|
/>
|
|
</Grid>
|
|
|
|
<fieldset
|
|
className={classes.fieldGroup}
|
|
style={{ marginTop: 15 }}
|
|
>
|
|
<legend className={classes.descriptionText}>
|
|
SecurityContext for KES pods
|
|
</legend>
|
|
<Grid item xs={12} className={classes.kesSecurityContext}>
|
|
<div
|
|
className={`${classes.multiContainer} ${classes.responsiveContainer}`}
|
|
>
|
|
<div
|
|
className={`${classes.formFieldRow} ${classes.rightSpacer}`}
|
|
>
|
|
<InputBoxWrapper
|
|
type="number"
|
|
id="kes_securityContext_runAsUser"
|
|
name="kes_securityContext_runAsUser"
|
|
onChange={(
|
|
e: React.ChangeEvent<HTMLInputElement>
|
|
) => {
|
|
setSecurityContext({
|
|
...securityContext,
|
|
runAsUser: e.target.value,
|
|
});
|
|
}}
|
|
label="Run As User"
|
|
value={securityContext.runAsUser}
|
|
required
|
|
error={
|
|
validationErrors["kes_securityContext_runAsUser"] ||
|
|
""
|
|
}
|
|
min="0"
|
|
/>
|
|
</div>
|
|
<div
|
|
className={`${classes.formFieldRow} ${classes.rightSpacer}`}
|
|
>
|
|
<InputBoxWrapper
|
|
type="number"
|
|
id="kes_securityContext_runAsGroup"
|
|
name="kes_securityContext_runAsGroup"
|
|
onChange={(
|
|
e: React.ChangeEvent<HTMLInputElement>
|
|
) => {
|
|
setSecurityContext({
|
|
...securityContext,
|
|
runAsGroup: e.target.value,
|
|
});
|
|
}}
|
|
label="Run As Group"
|
|
value={securityContext.runAsGroup}
|
|
required
|
|
error={
|
|
validationErrors[
|
|
"kes_securityContext_runAsGroup"
|
|
] || ""
|
|
}
|
|
min="0"
|
|
/>
|
|
</div>
|
|
<div
|
|
className={`${classes.formFieldRow} ${classes.rightSpacer}`}
|
|
>
|
|
<InputBoxWrapper
|
|
type="number"
|
|
id="kes_securityContext_fsGroup"
|
|
name="kes_securityContext_fsGroup"
|
|
onChange={(
|
|
e: React.ChangeEvent<HTMLInputElement>
|
|
) => {
|
|
setSecurityContext({
|
|
...securityContext,
|
|
fsGroup: e.target.value,
|
|
});
|
|
}}
|
|
label="FsGroup"
|
|
value={securityContext.fsGroup}
|
|
required
|
|
error={
|
|
validationErrors["kes_securityContext_fsGroup"] ||
|
|
""
|
|
}
|
|
min="0"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</Grid>
|
|
<br />
|
|
<Grid item xs={12}>
|
|
<div className={classes.multiContainer}>
|
|
<FormSwitchWrapper
|
|
value="kesSecurityContextRunAsNonRoot"
|
|
id="kes_securityContext_runAsNonRoot"
|
|
name="kes_securityContext_runAsNonRoot"
|
|
checked={securityContext.runAsNonRoot}
|
|
onChange={(e) => {
|
|
const targetD = e.target;
|
|
const checked = targetD.checked;
|
|
setSecurityContext({
|
|
...securityContext,
|
|
runAsNonRoot: checked,
|
|
});
|
|
}}
|
|
label={"Do not run as Root"}
|
|
/>
|
|
</div>
|
|
</Grid>
|
|
</fieldset>
|
|
</Grid>
|
|
</Grid>
|
|
</Paper>
|
|
)}
|
|
<Grid item xs={12} className={classes.buttonContainer}>
|
|
<Button
|
|
type="submit"
|
|
variant="contained"
|
|
color="primary"
|
|
disabled={!isFormValid}
|
|
onClick={() => setConfirmOpen(true)}
|
|
>
|
|
Save
|
|
</Button>
|
|
</Grid>
|
|
</Fragment>
|
|
</React.Fragment>
|
|
);
|
|
};
|
|
|
|
const mapState = (state: AppState) => ({
|
|
loadingTenant: state.tenants.tenantDetails.loadingTenant,
|
|
selectedTenant: state.tenants.tenantDetails.currentTenant,
|
|
tenant: state.tenants.tenantDetails.tenantInfo,
|
|
});
|
|
|
|
const mapDispatchToProps = {
|
|
setErrorSnackMessage,
|
|
setTenantDetailsLoad,
|
|
};
|
|
|
|
const connector = connect(mapState, mapDispatchToProps);
|
|
|
|
export default withStyles(styles)(connector(TenantEncryption));
|