Tenant Forms alignment. Components Page. (#1811)

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
This commit is contained in:
Daniel Valdivia
2022-04-07 20:06:28 -07:00
committed by GitHub
parent bfbaaf12fb
commit 62e270e95e
10 changed files with 1429 additions and 1258 deletions

View File

@@ -19,9 +19,8 @@ import { connect } from "react-redux";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import { Box } from "@mui/material";
import { Box, Grid } from "@mui/material";
import get from "lodash/get";
import Grid from "@mui/material/Grid";
import { AppState } from "../../../../store";
import { setErrorSnackMessage } from "../../../../actions";
import {
@@ -45,17 +44,18 @@ import api from "../../../../common/api";
import { setBucketDetailsLoad } from "../actions";
import { IAM_SCOPES } from "../../../../common/SecureComponent/permissions";
import {
SecureComponent,
hasPermission,
SecureComponent,
} from "../../../../common/SecureComponent";
import withSuspense from "../../Common/Components/withSuspense";
import LabelValuePair from "../../Common/UsageBarWrapper/LabelValuePair";
import LabelWithIcon from "./SummaryItems/LabelWithIcon";
import { EnabledIcon, DisabledIcon } from "../../../../icons";
import { DisabledIcon, EnabledIcon } from "../../../../icons";
import EditablePropertyItem from "./SummaryItems/EditablePropertyItem";
import ReportedUsage from "./SummaryItems/ReportedUsage";
import BucketQuotaSize from "./SummaryItems/BucketQuotaSize";
import SectionTitle from "../../Common/SectionTitle";
const SetAccessPolicy = withSuspense(
React.lazy(() => import("./SetAccessPolicy"))
@@ -415,264 +415,247 @@ const BucketSummary = ({
/>
)}
<Grid container>
<Grid item xs={12} className={classes.spacerBottom}>
<h3
style={{
marginTop: "0",
marginBottom: "0",
}}
<SectionTitle>Summary</SectionTitle>
<Grid container spacing={1}>
<SecureComponent
scopes={[IAM_SCOPES.S3_GET_BUCKET_POLICY]}
resource={bucketName}
>
<Grid item xs={12}>
<Box sx={{ ...twoColCssGridLayoutConfig }}>
<Box sx={{ ...twoColCssGridLayoutConfig }}>
<SecureComponent
scopes={[IAM_SCOPES.S3_GET_BUCKET_POLICY]}
resource={bucketName}
>
<EditablePropertyItem
iamScopes={[IAM_SCOPES.S3_PUT_BUCKET_POLICY]}
resourceName={bucketName}
property={"Access Policy:"}
value={accessPolicy.toLowerCase()}
onEdit={() => {
setAccessPolicyScreenOpen(true);
}}
isLoading={bucketLoading}
/>
</SecureComponent>
<SecureComponent
scopes={[IAM_SCOPES.S3_GET_BUCKET_ENCRYPTION_CONFIGURATION]}
resource={bucketName}
>
<EditablePropertyItem
iamScopes={[
IAM_SCOPES.S3_PUT_BUCKET_ENCRYPTION_CONFIGURATION,
]}
resourceName={bucketName}
property={"Encryption:"}
value={encryptionEnabled ? "Enabled" : "Disabled"}
onEdit={() => {
setEnableEncryptionScreenOpen(true);
}}
isLoading={loadingEncryption}
/>
</SecureComponent>
<SecureComponent
scopes={[IAM_SCOPES.S3_GET_REPLICATION_CONFIGURATION]}
resource={bucketName}
>
<LabelValuePair
label={"Replication:"}
value={
<LabelWithIcon
icon={
replicationRules ? <EnabledIcon /> : <DisabledIcon />
}
label={
<label className={classes.textMuted}>
{replicationRules ? "Enabled" : "Disabled"}
</label>
}
/>
}
/>
</SecureComponent>
<SecureComponent
scopes={[IAM_SCOPES.S3_GET_BUCKET_OBJECT_LOCK_CONFIGURATION]}
resource={bucketName}
>
<LabelValuePair
label={"Object Locking:"}
value={
<LabelWithIcon
icon={
hasObjectLocking ? <EnabledIcon /> : <DisabledIcon />
}
label={
<label className={classes.textMuted}>
{hasObjectLocking ? "Enabled" : "Disabled"}
</label>
}
/>
}
/>
</SecureComponent>
<Box className={classes.spacerTop}>
<LabelValuePair
label={"Tags:"}
value={
<BucketTags
setErrorSnackMessage={setErrorSnackMessage}
bucketName={bucketName}
/>
}
/>
</Box>
</Box>
<Box
sx={{
display: "grid",
gridTemplateColumns: "1fr",
alignItems: "flex-start",
}}
>
<ReportedUsage bucketSize={bucketSize} />
</Box>
</Box>
</Grid>
</SecureComponent>
{distributedSetup && (
<SecureComponent
scopes={[IAM_SCOPES.S3_GET_BUCKET_VERSIONING]}
resource={bucketName}
>
Summary
</h3>
</Grid>
<Grid item xs={12}>
<SectionTitle>Versioning</SectionTitle>
<Box
sx={{
...twoColCssGridLayoutConfig,
}}
>
<Box
sx={{
...twoColCssGridLayoutConfig,
}}
>
<EditablePropertyItem
iamScopes={[IAM_SCOPES.S3_PUT_BUCKET_VERSIONING]}
resourceName={bucketName}
property={"Versioning:"}
value={isVersioned ? "Enabled" : "Disabled"}
onEdit={setBucketVersioning}
isLoading={loadingVersioning}
/>
<EditablePropertyItem
iamScopes={[IAM_SCOPES.ADMIN_SET_BUCKET_QUOTA]}
resourceName={bucketName}
property={"Quota:"}
value={quotaEnabled ? "Enabled" : "Disabled"}
onEdit={setBucketQuota}
isLoading={loadingQuota}
/>
</Box>
<Box
sx={{
display: "grid",
gridTemplateColumns: "1fr",
alignItems: "flex-start",
}}
>
{quotaEnabled && quota ? (
<BucketQuotaSize quota={quota} />
) : null}
</Box>
</Box>
</Grid>
</SecureComponent>
)}
{hasObjectLocking && (
<SecureComponent
scopes={[IAM_SCOPES.S3_GET_OBJECT_RETENTION]}
resource={bucketName}
>
<Grid item xs={12}>
<SectionTitle>Retention</SectionTitle>
<Box
sx={{
display: "grid",
gridTemplateColumns: { xs: "1fr", sm: "2fr 1fr" },
gridAutoFlow: { xs: "dense", sm: "row" } /* NEW */,
gap: 2,
}}
>
<Box
sx={{
display: "grid",
gridTemplateColumns: { xs: "1fr", sm: "2fr 1fr" },
gridAutoFlow: { xs: "dense", sm: "row" } /* NEW */,
gap: 2,
}}
>
<EditablePropertyItem
iamScopes={[IAM_SCOPES.ADMIN_SET_BUCKET_QUOTA]}
resourceName={bucketName}
property={"Retention:"}
value={retentionEnabled ? "Enabled" : "Disabled"}
onEdit={() => {
setRetentionConfigOpen(true);
}}
isLoading={loadingRetention}
/>
<LabelValuePair
label={"Mode:"}
value={
<label
className={classes.textMuted}
style={{ textTransform: "capitalize" }}
>
{retentionConfig && retentionConfig.mode
? retentionConfig.mode
: "-"}
</label>
}
/>
<LabelValuePair
label={"Validity:"}
value={
<label
className={classes.textMuted}
style={{ textTransform: "capitalize" }}
>
{retentionConfig && retentionConfig.validity}{" "}
{retentionConfig &&
(retentionConfig.validity === 1
? retentionConfig.unit.slice(0, -1)
: retentionConfig.unit)}
</label>
}
/>
</Box>
<Box
sx={{
display: "grid",
gridTemplateColumns: "1fr",
alignItems: "flex-start",
}}
>
{/*Spacer*/}
</Box>
</Box>
</Grid>
</SecureComponent>
)}
</Grid>
<SecureComponent
scopes={[IAM_SCOPES.S3_GET_BUCKET_POLICY]}
resource={bucketName}
>
<Box sx={{ ...twoColCssGridLayoutConfig }}>
<Box sx={{ ...twoColCssGridLayoutConfig }}>
<SecureComponent
scopes={[IAM_SCOPES.S3_GET_BUCKET_POLICY]}
resource={bucketName}
>
<EditablePropertyItem
iamScopes={[IAM_SCOPES.S3_PUT_BUCKET_POLICY]}
resourceName={bucketName}
property={"Access Policy:"}
value={accessPolicy.toLowerCase()}
onEdit={() => {
setAccessPolicyScreenOpen(true);
}}
isLoading={bucketLoading}
/>
</SecureComponent>
<SecureComponent
scopes={[IAM_SCOPES.S3_GET_BUCKET_ENCRYPTION_CONFIGURATION]}
resource={bucketName}
>
<EditablePropertyItem
iamScopes={[IAM_SCOPES.S3_PUT_BUCKET_ENCRYPTION_CONFIGURATION]}
resourceName={bucketName}
property={"Encryption:"}
value={encryptionEnabled ? "Enabled" : "Disabled"}
onEdit={() => {
setEnableEncryptionScreenOpen(true);
}}
isLoading={loadingEncryption}
/>
</SecureComponent>
<SecureComponent
scopes={[IAM_SCOPES.S3_GET_REPLICATION_CONFIGURATION]}
resource={bucketName}
>
<LabelValuePair
label={"Replication:"}
value={
<LabelWithIcon
icon={replicationRules ? <EnabledIcon /> : <DisabledIcon />}
label={
<label className={classes.textMuted}>
{replicationRules ? "Enabled" : "Disabled"}
</label>
}
/>
}
/>
</SecureComponent>
<SecureComponent
scopes={[IAM_SCOPES.S3_GET_BUCKET_OBJECT_LOCK_CONFIGURATION]}
resource={bucketName}
>
<LabelValuePair
label={"Object Locking:"}
value={
<LabelWithIcon
icon={hasObjectLocking ? <EnabledIcon /> : <DisabledIcon />}
label={
<label className={classes.textMuted}>
{hasObjectLocking ? "Enabled" : "Disabled"}
</label>
}
/>
}
/>
</SecureComponent>
<Box className={classes.spacerTop}>
<LabelValuePair
label={"Tags:"}
value={
<BucketTags
setErrorSnackMessage={setErrorSnackMessage}
bucketName={bucketName}
/>
}
/>
</Box>
</Box>
<Box
sx={{
display: "grid",
gridTemplateColumns: "1fr",
alignItems: "flex-start",
}}
>
<ReportedUsage bucketSize={bucketSize} />
</Box>
</Box>
</SecureComponent>
{distributedSetup && (
<SecureComponent
scopes={[IAM_SCOPES.S3_GET_BUCKET_VERSIONING]}
resource={bucketName}
>
<Grid container>
<Grid item xs={12} className={classes.spacerBottom}>
<h3
style={{
marginTop: "25px",
marginBottom: "0",
}}
>
Versioning
</h3>
</Grid>
</Grid>
<Box
sx={{
...twoColCssGridLayoutConfig,
}}
>
<Box
sx={{
...twoColCssGridLayoutConfig,
}}
>
<EditablePropertyItem
iamScopes={[IAM_SCOPES.S3_PUT_BUCKET_VERSIONING]}
resourceName={bucketName}
property={"Versioning:"}
value={isVersioned ? "Enabled" : "Disabled"}
onEdit={setBucketVersioning}
isLoading={loadingVersioning}
/>
<EditablePropertyItem
iamScopes={[IAM_SCOPES.ADMIN_SET_BUCKET_QUOTA]}
resourceName={bucketName}
property={"Quota:"}
value={quotaEnabled ? "Enabled" : "Disabled"}
onEdit={setBucketQuota}
isLoading={loadingQuota}
/>
</Box>
<Box
sx={{
display: "grid",
gridTemplateColumns: "1fr",
alignItems: "flex-start",
}}
>
{quotaEnabled && quota ? <BucketQuotaSize quota={quota} /> : null}
</Box>
</Box>
</SecureComponent>
)}
{hasObjectLocking && (
<SecureComponent
scopes={[IAM_SCOPES.S3_GET_OBJECT_RETENTION]}
resource={bucketName}
>
<Grid container>
<Grid item xs={12} className={classes.spacerBottom}>
<h3
style={{
marginTop: "25px",
marginBottom: "0",
}}
>
Retention
</h3>
</Grid>
</Grid>
<Box
sx={{
display: "grid",
gridTemplateColumns: { xs: "1fr", sm: "2fr 1fr" },
gridAutoFlow: { xs: "dense", sm: "row" } /* NEW */,
gap: 2,
}}
>
<Box
sx={{
display: "grid",
gridTemplateColumns: { xs: "1fr", sm: "2fr 1fr" },
gridAutoFlow: { xs: "dense", sm: "row" } /* NEW */,
gap: 2,
}}
>
<EditablePropertyItem
iamScopes={[IAM_SCOPES.ADMIN_SET_BUCKET_QUOTA]}
resourceName={bucketName}
property={"Retention:"}
value={retentionEnabled ? "Enabled" : "Disabled"}
onEdit={() => {
setRetentionConfigOpen(true);
}}
isLoading={loadingRetention}
/>
<LabelValuePair
label={"Mode:"}
value={
<label
className={classes.textMuted}
style={{ textTransform: "capitalize" }}
>
{retentionConfig && retentionConfig.mode
? retentionConfig.mode
: "-"}
</label>
}
/>
<LabelValuePair
label={"Validity:"}
value={
<label
className={classes.textMuted}
style={{ textTransform: "capitalize" }}
>
{retentionConfig && retentionConfig.validity}{" "}
{retentionConfig &&
(retentionConfig.validity === 1
? retentionConfig.unit.slice(0, -1)
: retentionConfig.unit)}
</label>
}
/>
</Box>
<Box
sx={{
display: "grid",
gridTemplateColumns: "1fr",
alignItems: "flex-start",
}}
>
{/*Spacer*/}
</Box>
</Box>
</SecureComponent>
)}
</Fragment>
);
};

View File

@@ -0,0 +1,258 @@
// This file is part of MinIO Console Server
// Copyright (c) 2021 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 React, { Fragment, useState } from "react";
import { containerForHeader } from "../Common/FormComponents/common/styleLibrary";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import { Button, DialogContentText, Grid } from "@mui/material";
import PageHeader from "./PageHeader/PageHeader";
import PageLayout from "./Layout/PageLayout";
import SectionTitle from "./SectionTitle";
import RBIconButton from "../Buckets/BucketDetails/SummaryItems/RBIconButton";
import {
ArrowIcon,
ConfirmDeleteIcon,
EditIcon,
TrashIcon,
} from "../../../icons";
import ConfirmDialog from "./ModalWrapper/ConfirmDialog";
interface IComponentsScreen {
classes: any;
}
const styles = (theme: Theme) =>
createStyles({
...containerForHeader(theme.spacing(4)),
root: {
fontSize: 12,
wordWrap: "break-word",
"& .min-loader": {
width: 45,
height: 45,
},
},
def: {},
red: {
"& .min-icon": {
color: "red",
},
},
});
const ComponentsScreen = ({ classes }: IComponentsScreen) => {
const [dialogOpen, setDialogOpen] = useState<boolean>(false);
return (
<Fragment>
<PageHeader label={"Components"} />
<PageLayout>
<Grid container spacing={1}>
<Grid item xs={12}>
<SectionTitle>Buttons</SectionTitle>
</Grid>
<Grid item xs={12}>
<p>Buttons should always be of one of the following four types:</p>
</Grid>
<Grid item xs={12}>
<Grid container spacing={1}>
<Grid item>
<Button
type="button"
variant={"contained"}
className={classes.clearButton}
onClick={() => {}}
>
Primary
</Button>
</Grid>
<Grid item>
<Button
type="submit"
variant="contained"
color="primary"
onClick={() => {}}
disabled={true}
>
Primary Disabled
</Button>
</Grid>
<Grid item>
<Button type="button" variant={"outlined"} onClick={() => {}}>
Generic
</Button>
</Grid>
<Grid item>
<Button
type="button"
variant={"outlined"}
onClick={() => {}}
disabled={true}
>
Generic Disabled
</Button>
</Grid>
<Grid item>
<Button
type="button"
variant={"outlined"}
color={"secondary"}
onClick={() => {}}
>
Dangerous
</Button>
</Grid>
<Grid item>
<Button
type="button"
variant={"outlined"}
color={"secondary"}
onClick={() => {}}
disabled={true}
>
Dangerous Disabled
</Button>
</Grid>
</Grid>
</Grid>
<Grid item xs={12}>
<ul>
<li>
<b>Primary:</b> A call to action.
</li>
<li>
<b>Generic:</b> An optional action.
</li>
<li>
<b>Dangerous:</b> An irreversible action.
</li>
</ul>
</Grid>
<Grid item xs={12}>
<SectionTitle>Icon Buttons</SectionTitle>
</Grid>
<Grid item xs={12}>
<p>Icon Buttons should always be of one of the following types:</p>
</Grid>
<Grid item xs={12}>
<Grid container spacing={1}>
<Grid item>
<RBIconButton
tooltip={"Primary"}
onClick={() => {}}
text={"Primary"}
icon={<ArrowIcon />}
color={"primary"}
variant={"outlined"}
/>
</Grid>
<Grid item>
<RBIconButton
tooltip={"Primary Disabled"}
onClick={() => {}}
text={"Primary Disabled"}
icon={<ArrowIcon />}
color={"primary"}
variant={"outlined"}
disabled={true}
/>
</Grid>
<Grid item>
<RBIconButton
tooltip={"Delete Bucket"}
onClick={() => {}}
text={"Generic"}
icon={<EditIcon />}
variant={"outlined"}
/>
</Grid>
<Grid item>
<RBIconButton
tooltip={"Delete Bucket"}
onClick={() => {}}
text={"Generic Disabled"}
icon={<EditIcon />}
variant={"outlined"}
disabled={true}
/>
</Grid>
<Grid item>
<RBIconButton
tooltip={"Dangerous"}
onClick={() => {}}
text={"Dangerous"}
icon={<TrashIcon />}
color={"secondary"}
variant={"outlined"}
/>
</Grid>
<Grid item>
<RBIconButton
tooltip={"Dangerous"}
onClick={() => {}}
text={"Dangerous Disabled"}
icon={<TrashIcon />}
color={"secondary"}
variant={"outlined"}
disabled={true}
/>
</Grid>
</Grid>
</Grid>
<Grid item xs={12}>
<SectionTitle>Confirm Dialogs</SectionTitle>
</Grid>
<Grid item xs={12}>
<p>Used to confirm a non-idempotent action.</p>
</Grid>
<Grid item xs={12}>
<Button
type="button"
variant={"outlined"}
onClick={() => {
setDialogOpen(true);
}}
>
Open Dialog
</Button>
<ConfirmDialog
title={`Delete Bucket`}
confirmText={"Delete"}
isOpen={dialogOpen}
titleIcon={<ConfirmDeleteIcon />}
isLoading={false}
onConfirm={() => {
setDialogOpen(false);
}}
onClose={() => {
setDialogOpen(false);
}}
confirmationContent={
<DialogContentText>
Are you sure you want to delete bucket <b>bucket</b>
? <br />A bucket can only be deleted if it's empty.
</DialogContentText>
}
/>
</Grid>
</Grid>
</PageLayout>
</Fragment>
);
};
export default withStyles(styles)(ComponentsScreen);

View File

@@ -0,0 +1,54 @@
// 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 React from "react";
import Grid from "@mui/material/Grid";
type Props = {
separator?: boolean;
actions?: React.ReactNode;
};
const SectionTitle: React.FC<Props> = ({
children,
separator = true,
actions,
}) => {
return (
<Grid
container
alignItems={"center"}
justifyContent="space-between"
sx={{
borderBottom: separator ? "1px solid #eaeaea" : "",
}}
>
<Grid item xs>
<h3
style={{
margin: 0,
marginBottom: 10,
}}
>
{children}
</h3>
</Grid>
{actions && <Grid item> {actions}</Grid>}
</Grid>
);
};
export default SectionTitle;

View File

@@ -51,6 +51,7 @@ import { hasPermission } from "../../common/SecureComponent";
import { IRouteRule } from "./Menu/types";
import LoadingComponent from "../../common/LoadingComponent";
import EditPool from "./Tenants/TenantDetails/Pools/EditPool/EditPool";
import ComponentsScreen from "./Common/ComponentsScreen";
const Trace = React.lazy(() => import("./Trace/Trace"));
const Heal = React.lazy(() => import("./Heal/Heal"));
@@ -613,6 +614,11 @@ const Console = ({
<IconsScreen />
</Suspense>
</Route>
<Route key={"/components"} exact path={"/components"}>
<Suspense fallback={<LoadingComponent />}>
<ComponentsScreen />
</Suspense>
</Route>
{allowedRoutes.length > 0 ? (
<Redirect to={allowedRoutes[0].path} />
) : null}

View File

@@ -489,9 +489,7 @@ const PolicyDetails = ({
variant="standard"
/>
</Grid>
<Grid item xs={12} className={classes.actionsTray}>
<br />
</Grid>
<TableWrapper
itemActions={userTableActions}
columns={[{ label: "Name", elementKey: "name" }]}
@@ -533,9 +531,6 @@ const PolicyDetails = ({
variant="standard"
/>
</Grid>
<Grid item xs={12} className={classes.actionsTray}>
<br />
</Grid>
<TableWrapper
itemActions={groupTableActions}
columns={[{ label: "Name", elementKey: "name" }]}

View File

@@ -45,7 +45,7 @@ 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, Stack } from "@mui/material";
import { Button, DialogContentText } from "@mui/material";
import VisibilityOffIcon from "@mui/icons-material/VisibilityOff";
import RemoveRedEyeIcon from "@mui/icons-material/RemoveRedEye";
import { KeyPair } from "../ListTenants/utils";
@@ -56,7 +56,7 @@ import {
} from "../../../../utils/validationFunctions";
import ConfirmDialog from "../../Common/ModalWrapper/ConfirmDialog";
import TLSCertificate from "../../Common/TLSCertificate/TLSCertificate";
import StackRow from "../../Common/UsageBarWrapper/StackRow";
import SectionTitle from "../../Common/SectionTitle";
interface ITenantEncryption {
classes: any;
@@ -683,7 +683,7 @@ const TenantEncryption = ({
return (
<React.Fragment>
<Fragment>
<Grid container spacing={1}>
{confirmOpen && (
<ConfirmDialog
isOpen={confirmOpen}
@@ -705,33 +705,28 @@ const TenantEncryption = ({
}
/>
)}
<Grid container alignItems={"center"}>
<Grid item xs>
<h1 className={classes.sectionTitle}>Encryption</h1>
</Grid>
<Grid
item
xs={4}
justifyContent={"end"}
textAlign={"right"}
className={classes.formFieldRow}
>
<FormSwitchWrapper
label={""}
indicatorLabels={["Enabled", "Disabled"]}
checked={encryptionEnabled}
value={"tenant_encryption"}
id="tenant-encryption"
name="tenant-encryption"
onChange={() => {
setEncryptionEnabled(!encryptionEnabled);
}}
description=""
/>
</Grid>
<Grid item xs>
<h1 className={classes.sectionTitle}>Encryption</h1>
</Grid>
<Grid item xs={4} justifyContent={"end"} textAlign={"right"}>
<FormSwitchWrapper
label={""}
indicatorLabels={["Enabled", "Disabled"]}
checked={encryptionEnabled}
value={"tenant_encryption"}
id="tenant-encryption"
name="tenant-encryption"
onChange={() => {
setEncryptionEnabled(!encryptionEnabled);
}}
description=""
/>
</Grid>
<Grid xs={12}>
<hr className={classes.hrClass} />
</Grid>
{encryptionEnabled && (
<Grid container spacing={1}>
<Fragment>
<Grid item xs={12} className={classes.encryptionTypeOptions}>
<RadioGroupSelector
currentSelection={encryptionType}
@@ -752,7 +747,7 @@ const TenantEncryption = ({
</Grid>
{encryptionType === "vault" && (
<Fragment>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<InputBoxWrapper
id="vault_endpoint"
name="vault_endpoint"
@@ -768,7 +763,7 @@ const TenantEncryption = ({
required
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<InputBoxWrapper
id="vault_engine"
name="vault_engine"
@@ -782,7 +777,7 @@ const TenantEncryption = ({
value={vaultConfiguration?.engine || ""}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<InputBoxWrapper
id="vault_namespace"
name="vault_namespace"
@@ -796,7 +791,7 @@ const TenantEncryption = ({
value={vaultConfiguration?.namespace || ""}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<InputBoxWrapper
id="vault_prefix"
name="vault_prefix"
@@ -810,142 +805,110 @@ const TenantEncryption = ({
value={vaultConfiguration?.prefix || ""}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<Stack>
<StackRow
sx={{
borderBottom: "1px solid #eaeaea",
margin: 0,
marginBottom: 1,
}}
>
<h3
style={{
marginBottom: 8,
}}
>
App Role
</h3>
</StackRow>
<Grid container spacing={1}>
<Grid item xs={12}>
<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}>
<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}>
<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}>
<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>
</Grid>
</Stack>
<Grid item xs={12}>
<SectionTitle>App Role</SectionTitle>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<Stack>
<StackRow
sx={{
borderBottom: "1px solid #eaeaea",
margin: 0,
marginBottom: 1,
}}
>
<h3
style={{
marginBottom: 8,
}}
>
Vault Certificates (optional)
</h3>
</StackRow>
</Stack>
<Grid item xs={12}>
<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}>
<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}>
<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}>
<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>
<Grid item xs={12}>
<SectionTitle>Vault Certificates (optional)</SectionTitle>
</Grid>
<Grid item xs={12}>
<fieldset className={classes.fieldGroup}>
<legend className={classes.descriptionText}>
Mutual TLS authentication with Vault (optional)
@@ -1027,48 +990,34 @@ const TenantEncryption = ({
)}
</fieldset>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<Stack>
<StackRow
sx={{
borderBottom: "1px solid #eaeaea",
margin: 0,
marginBottom: 1,
}}
>
<h3
style={{
marginBottom: 8,
}}
>
Status
</h3>
</StackRow>
<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 || ""}
/>
</Stack>
<Grid item xs={12}>
<SectionTitle>Status</SectionTitle>
</Grid>
<Grid item xs={12}>
<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 || ""}
/>
</Grid>
</Fragment>
)}
{encryptionType === "azure" && (
<Fragment>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<InputBoxWrapper
id="azure_endpoint"
name="azure_endpoint"
@@ -1086,12 +1035,12 @@ const TenantEncryption = ({
value={azureConfiguration?.keyvault?.endpoint || ""}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<fieldset className={classes.fieldGroup}>
<legend className={classes.descriptionText}>
Credentials
</legend>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<InputBoxWrapper
id="azure_tenant_id"
name="azure_tenant_id"
@@ -1115,7 +1064,7 @@ const TenantEncryption = ({
error={validationErrors["azure_tenant_id"] || ""}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<InputBoxWrapper
id="azure_client_id"
name="azure_client_id"
@@ -1139,7 +1088,7 @@ const TenantEncryption = ({
error={validationErrors["azure_client_id"] || ""}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<InputBoxWrapper
id="azure_client_secret"
name="azure_client_secret"
@@ -1169,7 +1118,7 @@ const TenantEncryption = ({
)}
{encryptionType === "gcp" && (
<Fragment>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<InputBoxWrapper
id="gcp_project_id"
name="gcp_project_id"
@@ -1186,7 +1135,7 @@ const TenantEncryption = ({
value={gcpConfiguration?.secretmanager.project_id || ""}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<InputBoxWrapper
id="gcp_endpoint"
name="gcp_endpoint"
@@ -1203,12 +1152,12 @@ const TenantEncryption = ({
value={gcpConfiguration?.secretmanager.endpoint || ""}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<fieldset className={classes.fieldGroup}>
<legend className={classes.descriptionText}>
Credentials
</legend>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<InputBoxWrapper
id="gcp_client_email"
name="gcp_client_email"
@@ -1231,7 +1180,7 @@ const TenantEncryption = ({
}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<InputBoxWrapper
id="gcp_client_id"
name="gcp_client_id"
@@ -1254,7 +1203,7 @@ const TenantEncryption = ({
}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<InputBoxWrapper
id="gcp_private_key_id"
name="gcp_private_key_id"
@@ -1277,7 +1226,7 @@ const TenantEncryption = ({
}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<InputBoxWrapper
id="gcp_private_key"
name="gcp_private_key"
@@ -1306,7 +1255,7 @@ const TenantEncryption = ({
)}
{encryptionType === "aws" && (
<Fragment>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<InputBoxWrapper
id="aws_endpoint"
name="aws_endpoint"
@@ -1325,7 +1274,7 @@ const TenantEncryption = ({
error={validationErrors["aws_endpoint"] || ""}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<InputBoxWrapper
id="aws_region"
name="aws_region"
@@ -1344,7 +1293,7 @@ const TenantEncryption = ({
required
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<InputBoxWrapper
id="aws_kmsKey"
name="aws_kmsKey"
@@ -1361,12 +1310,12 @@ const TenantEncryption = ({
value={awsConfiguration?.secretsmanager?.kmskey || ""}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<fieldset className={classes.fieldGroup}>
<legend className={classes.descriptionText}>
Credentials
</legend>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<InputBoxWrapper
id="aws_accessKey"
name="aws_accessKey"
@@ -1392,7 +1341,7 @@ const TenantEncryption = ({
required
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<InputBoxWrapper
id="aws_secretKey"
name="aws_secretKey"
@@ -1418,7 +1367,7 @@ const TenantEncryption = ({
required
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<InputBoxWrapper
id="aws_token"
name="aws_token"
@@ -1448,7 +1397,7 @@ const TenantEncryption = ({
)}
{encryptionType === "gemalto" && (
<Fragment>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<InputBoxWrapper
id="gemalto_endpoint"
name="gemalto_endpoint"
@@ -1473,13 +1422,12 @@ const TenantEncryption = ({
style={{
marginBottom: 15,
}}
className={classes.formFieldRow}
>
<fieldset className={classes.fieldGroup}>
<legend className={classes.descriptionText}>
Credentials
</legend>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<InputBoxWrapper
id="gemalto_token"
name="gemalto_token"
@@ -1504,7 +1452,7 @@ const TenantEncryption = ({
required
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<InputBoxWrapper
id="gemalto_domain"
name="gemalto_domain"
@@ -1529,7 +1477,7 @@ const TenantEncryption = ({
required
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<InputBoxWrapper
type="number"
min="0"
@@ -1563,7 +1511,6 @@ const TenantEncryption = ({
style={{
marginBottom: 15,
}}
className={classes.formFieldRow}
>
<fieldset className={classes.fieldGroup}>
<legend className={classes.descriptionText}>
@@ -1599,39 +1546,24 @@ const TenantEncryption = ({
</Grid>
</Fragment>
)}
<Grid item xs={12} className={classes.formFieldRow}>
<Stack>
<StackRow
sx={{
borderBottom: "1px solid #eaeaea",
margin: 0,
marginBottom: 1,
}}
>
<h3
style={{
marginBottom: 8,
}}
>
Additional Configuration for KES
</h3>
</StackRow>
<FormSwitchWrapper
value="enableCustomCertsForKES"
id="enableCustomCertsForKES"
name="enableCustomCertsForKES"
checked={enabledCustomCertificates}
onChange={() =>
setEnabledCustomCertificates(!enabledCustomCertificates)
}
label={"Custom Certificates"}
/>
</Stack>
<Grid item xs={12}>
<SectionTitle>Additional Configuration for KES</SectionTitle>
</Grid>
<Grid item xs={12}>
<FormSwitchWrapper
value="enableCustomCertsForKES"
id="enableCustomCertsForKES"
name="enableCustomCertsForKES"
checked={enabledCustomCertificates}
onChange={() =>
setEnabledCustomCertificates(!enabledCustomCertificates)
}
label={"Custom Certificates"}
/>
</Grid>
{enabledCustomCertificates && (
<Fragment>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<fieldset className={classes.fieldGroup}>
<legend className={classes.descriptionText}>
KES server TLS Certificates (optional)
@@ -1684,7 +1616,7 @@ const TenantEncryption = ({
)}
</fieldset>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<fieldset className={classes.fieldGroup}>
<legend className={classes.descriptionText}>
Mutual TLS authentication with MinIO (optional)
@@ -1738,7 +1670,7 @@ const TenantEncryption = ({
</Grid>
</Fragment>
)}
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<InputBoxWrapper
type="text"
id="image"
@@ -1751,7 +1683,7 @@ const TenantEncryption = ({
value={image}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<Grid item xs={12}>
<InputBoxWrapper
type="number"
min="1"
@@ -1766,120 +1698,101 @@ const TenantEncryption = ({
error={validationErrors["replicas"] || ""}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<Stack>
<StackRow
sx={{
borderBottom: "1px solid #eaeaea",
margin: 0,
marginBottom: 1,
}}
<Grid item xs={12}>
<SectionTitle>SecurityContext for KES</SectionTitle>
</Grid>
<Grid item xs={12}>
<div
className={`${classes.multiContainer} ${classes.responsiveContainer}`}
>
<div
className={`${classes.formFieldRow} ${classes.rightSpacer}`}
>
<h3
style={{
marginBottom: 10,
}}
>
SecurityContext for KES
</h3>
</StackRow>
<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}>
<FormSwitchWrapper
value="kesSecurityContextRunAsNonRoot"
id="kes_securityContext_runAsNonRoot"
name="kes_securityContext_runAsNonRoot"
checked={securityContext.runAsNonRoot}
onChange={(e) => {
const targetD = e.target;
const checked = targetD.checked;
<InputBoxWrapper
type="number"
id="kes_securityContext_runAsUser"
name="kes_securityContext_runAsUser"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setSecurityContext({
...securityContext,
runAsNonRoot: checked,
runAsUser: e.target.value,
});
}}
label={"Do not run as Root"}
label="Run As User"
value={securityContext.runAsUser}
required
error={
validationErrors["kes_securityContext_runAsUser"] || ""
}
min="0"
/>
</Grid>
</Stack>
</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>
</Grid>
<Grid item xs={12}>
<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"}
/>
</Grid>
</Fragment>
)}
<Grid item xs={12} className={classes.buttonContainer}>
<Grid item xs={12} textAlign={"right"}>
<Button
type="submit"
variant="contained"
@@ -1890,7 +1803,7 @@ const TenantEncryption = ({
Save
</Button>
</Grid>
</Fragment>
</Grid>
</React.Fragment>
);
};

View File

@@ -28,7 +28,6 @@ import {
tenantDetailsStyles,
wizardCommon,
} from "../../Common/FormComponents/common/styleLibrary";
import Paper from "@mui/material/Paper";
import Grid from "@mui/material/Grid";
import React, { Fragment, useCallback, useEffect, useState } from "react";
import { Button, DialogContentText, Typography } from "@mui/material";
@@ -50,6 +49,7 @@ import VisibilityOffIcon from "@mui/icons-material/VisibilityOff";
import RemoveRedEyeIcon from "@mui/icons-material/RemoveRedEye";
import ConfirmDialog from "../../Common/ModalWrapper/ConfirmDialog";
import { ConfirmModalIcon } from "../../../../icons";
interface ITenantIdentityProvider {
classes: any;
loadingTenant: boolean;
@@ -298,304 +298,302 @@ const TenantIdentityProvider = ({
}
/>
{loadingTenant ? (
<Paper className={classes.paperContainer}>
<div className={classes.loaderAlign}>
<Loader />
</div>
</Paper>
<div className={classes.loaderAlign}>
<Loader />
</div>
) : (
<Fragment>
<h1 className={classes.sectionTitle}>Identity Provider</h1>
<Paper className={classes.paperContainer}>
<Grid item xs={12} className={classes.protocolRadioOptions}>
<label>Protocol</label>
<RadioGroupSelector
currentSelection={idpSelection}
id="idp-options"
name="idp-options"
label=" "
onChange={(e) => {
setIdpSelection(e.target.value);
}}
selectorOptions={[
{ label: "Built-in", value: "Built-in" },
{ label: "OpenID", value: "OpenID" },
{ label: "Active Directory", value: "AD" },
]}
/>
</Grid>
<Grid item xs={12}>
<h1 className={classes.sectionTitle}>Identity Provider</h1>
<hr className={classes.hrClass} />
</Grid>
<Grid item xs={12} className={classes.protocolRadioOptions}>
<RadioGroupSelector
currentSelection={idpSelection}
id="idp-options"
name="idp-options"
label="Protocol"
onChange={(e) => {
setIdpSelection(e.target.value);
}}
selectorOptions={[
{ label: "Built-in", value: "Built-in" },
{ label: "OpenID", value: "OpenID" },
{ label: "Active Directory", value: "AD" },
]}
/>
</Grid>
{idpSelection === "OpenID" && (
<Fragment>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="openID_CONFIGURATION_URL"
name="openID_CONFIGURATION_URL"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setOpenIDConfigurationURL(e.target.value);
cleanValidation("openID_CONFIGURATION_URL");
}}
label="Configuration URL"
value={openIDConfigurationURL}
placeholder="https://your-identity-provider.com/.well-known/openid-configuration"
error={validationErrors["openID_CONFIGURATION_URL"] || ""}
required
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="openID_clientID"
name="openID_clientID"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setOpenIDClientID(e.target.value);
cleanValidation("openID_clientID");
}}
label="Client ID"
value={openIDClientID}
error={validationErrors["openID_clientID"] || ""}
required
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
type={showOIDCSecretID ? "text" : "password"}
id="openID_secretID"
name="openID_secretID"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setOpenIDSecretID(e.target.value);
cleanValidation("openID_secretID");
}}
label="Secret ID"
value={openIDSecretID}
error={validationErrors["openID_secretID"] || ""}
required
overlayIcon={
showOIDCSecretID ? (
<VisibilityOffIcon />
) : (
<RemoveRedEyeIcon />
)
}
overlayAction={() => setShowOIDCSecretID(!showOIDCSecretID)}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="openID_callbackURL"
name="openID_callbackURL"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setOpenIDCallbackURL(e.target.value);
cleanValidation("openID_callbackURL");
}}
label="Callback URL"
value={openIDCallbackURL}
placeholder="https://your-console-endpoint:9443/oauth_callback"
error={validationErrors["openID_callbackURL"] || ""}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="openID_claimName"
name="openID_claimName"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setOpenIDClaimName(e.target.value);
cleanValidation("openID_claimName");
}}
label="Claim Name"
value={openIDClaimName}
error={validationErrors["openID_claimName"] || ""}
required
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="openID_scopes"
name="openID_scopes"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setOpenIDScopes(e.target.value);
cleanValidation("openID_scopes");
}}
label="Scopes"
value={openIDScopes}
/>
</Grid>
</Fragment>
)}
{idpSelection === "OpenID" && (
<Fragment>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="openID_CONFIGURATION_URL"
name="openID_CONFIGURATION_URL"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setOpenIDConfigurationURL(e.target.value);
cleanValidation("openID_CONFIGURATION_URL");
}}
label="Configuration URL"
value={openIDConfigurationURL}
placeholder="https://your-identity-provider.com/.well-known/openid-configuration"
error={validationErrors["openID_CONFIGURATION_URL"] || ""}
required
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="openID_clientID"
name="openID_clientID"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setOpenIDClientID(e.target.value);
cleanValidation("openID_clientID");
}}
label="Client ID"
value={openIDClientID}
error={validationErrors["openID_clientID"] || ""}
required
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
type={showOIDCSecretID ? "text" : "password"}
id="openID_secretID"
name="openID_secretID"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setOpenIDSecretID(e.target.value);
cleanValidation("openID_secretID");
}}
label="Secret ID"
value={openIDSecretID}
error={validationErrors["openID_secretID"] || ""}
required
overlayIcon={
showOIDCSecretID ? (
<VisibilityOffIcon />
) : (
<RemoveRedEyeIcon />
)
}
overlayAction={() => setShowOIDCSecretID(!showOIDCSecretID)}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="openID_callbackURL"
name="openID_callbackURL"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setOpenIDCallbackURL(e.target.value);
cleanValidation("openID_callbackURL");
}}
label="Callback URL"
value={openIDCallbackURL}
placeholder="https://your-console-endpoint:9443/oauth_callback"
error={validationErrors["openID_callbackURL"] || ""}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="openID_claimName"
name="openID_claimName"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setOpenIDClaimName(e.target.value);
cleanValidation("openID_claimName");
}}
label="Claim Name"
value={openIDClaimName}
error={validationErrors["openID_claimName"] || ""}
required
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="openID_scopes"
name="openID_scopes"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setOpenIDScopes(e.target.value);
cleanValidation("openID_scopes");
}}
label="Scopes"
value={openIDScopes}
/>
</Grid>
</Fragment>
)}
{idpSelection === "AD" && (
<Fragment>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="AD_URL"
name="AD_URL"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setADURL(e.target.value);
cleanValidation("AD_URL");
}}
label="LDAP Server Address"
value={ADURL}
placeholder="ldap-server:636"
error={validationErrors["AD_URL"] || ""}
required
/>
{idpSelection === "AD" && (
<Fragment>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="AD_URL"
name="AD_URL"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setADURL(e.target.value);
cleanValidation("AD_URL");
}}
label="LDAP Server Address"
value={ADURL}
placeholder="ldap-server:636"
error={validationErrors["AD_URL"] || ""}
required
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<FormSwitchWrapper
value="ad_skipTLS"
id="ad_skipTLS"
name="ad_skipTLS"
checked={ADSkipTLS}
onChange={(e) => {
const targetD = e.target;
const checked = targetD.checked;
setADSkipTLS(checked);
}}
label={"Skip TLS Verification"}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<FormSwitchWrapper
value="ad_serverInsecure"
id="ad_serverInsecure"
name="ad_serverInsecure"
checked={ADServerInsecure}
onChange={(e) => {
const targetD = e.target;
const checked = targetD.checked;
setADServerInsecure(checked);
}}
label={"Server Insecure"}
/>
</Grid>
{ADServerInsecure ? (
<Grid item xs={12}>
<Typography
className={classes.error}
variant="caption"
display="block"
gutterBottom
>
Warning: All traffic with Active Directory will be
unencrypted
</Typography>
<br />
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<FormSwitchWrapper
value="ad_skipTLS"
id="ad_skipTLS"
name="ad_skipTLS"
checked={ADSkipTLS}
onChange={(e) => {
const targetD = e.target;
const checked = targetD.checked;
setADSkipTLS(checked);
}}
label={"Skip TLS Verification"}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<FormSwitchWrapper
value="ad_serverInsecure"
id="ad_serverInsecure"
name="ad_serverInsecure"
checked={ADServerInsecure}
onChange={(e) => {
const targetD = e.target;
const checked = targetD.checked;
setADServerInsecure(checked);
}}
label={"Server Insecure"}
/>
</Grid>
{ADServerInsecure ? (
<Grid item xs={12}>
<Typography
className={classes.error}
variant="caption"
display="block"
gutterBottom
>
Warning: All traffic with Active Directory will be
unencrypted
</Typography>
<br />
</Grid>
) : null}
<Grid item xs={12} className={classes.formFieldRow}>
<FormSwitchWrapper
value="ad_serverStartTLS"
id="ad_serverStartTLS"
name="ad_serverStartTLS"
checked={ADServerStartTLS}
onChange={(e) => {
const targetD = e.target;
const checked = targetD.checked;
setADServerStartTLS(checked);
}}
label={"Start TLS connection to AD/LDAP server"}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="ad_lookupBindDN"
name="ad_lookupBindDN"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setADLookupBindDN(e.target.value);
cleanValidation("ad_lookupBindDN");
}}
label="Lookup Bind DN"
value={ADLookupBindDN}
placeholder="cn=admin,dc=min,dc=io"
error={validationErrors["ad_lookupBindDN"] || ""}
required
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
type={showADLookupBindPassword ? "text" : "password"}
id="ad_lookupBindPassword"
name="ad_lookupBindPassword"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setADLookupBindPassword(e.target.value);
}}
label="Lookup Bind Password"
value={ADLookupBindPassword}
placeholder="admin"
overlayIcon={
showADLookupBindPassword ? (
<VisibilityOffIcon />
) : (
<RemoveRedEyeIcon />
)
}
overlayAction={() =>
setShowADLookupBindPassword(!showADLookupBindPassword)
}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="ad_userDNSearchBaseDN"
name="ad_userDNSearchBaseDN"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setADUserDNSearchBaseDN(e.target.value);
}}
label="User DN Search Base DN"
value={ADUserDNSearchBaseDN}
placeholder="dc=min,dc=io"
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="ad_userDNSearchFilter"
name="ad_userDNSearchFilter"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setADUserDNSearchFilter(e.target.value);
}}
label="User DN Search Filter"
value={ADUserDNSearchFilter}
placeholder="(sAMAcountName=%s)"
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="ad_groupSearchBaseDN"
name="ad_groupSearchBaseDN"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setADGroupSearchBaseDN(e.target.value);
}}
label="Group Search Base DN"
value={ADGroupSearchBaseDN}
placeholder="ou=hwengg,dc=min,dc=io;ou=swengg,dc=min,dc=io"
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="ad_groupSearchFilter"
name="ad_groupSearchFilter"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setADGroupSearchFilter(e.target.value);
}}
label="Group Search Filter"
value={ADGroupSearchFilter}
placeholder="(&(objectclass=groupOfNames)(member=%s))"
/>
</Grid>
</Fragment>
)}
) : null}
<Grid item xs={12} className={classes.formFieldRow}>
<FormSwitchWrapper
value="ad_serverStartTLS"
id="ad_serverStartTLS"
name="ad_serverStartTLS"
checked={ADServerStartTLS}
onChange={(e) => {
const targetD = e.target;
const checked = targetD.checked;
setADServerStartTLS(checked);
}}
label={"Start TLS connection to AD/LDAP server"}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="ad_lookupBindDN"
name="ad_lookupBindDN"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setADLookupBindDN(e.target.value);
cleanValidation("ad_lookupBindDN");
}}
label="Lookup Bind DN"
value={ADLookupBindDN}
placeholder="cn=admin,dc=min,dc=io"
error={validationErrors["ad_lookupBindDN"] || ""}
required
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
type={showADLookupBindPassword ? "text" : "password"}
id="ad_lookupBindPassword"
name="ad_lookupBindPassword"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setADLookupBindPassword(e.target.value);
}}
label="Lookup Bind Password"
value={ADLookupBindPassword}
placeholder="admin"
overlayIcon={
showADLookupBindPassword ? (
<VisibilityOffIcon />
) : (
<RemoveRedEyeIcon />
)
}
overlayAction={() =>
setShowADLookupBindPassword(!showADLookupBindPassword)
}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="ad_userDNSearchBaseDN"
name="ad_userDNSearchBaseDN"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setADUserDNSearchBaseDN(e.target.value);
}}
label="User DN Search Base DN"
value={ADUserDNSearchBaseDN}
placeholder="dc=min,dc=io"
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="ad_userDNSearchFilter"
name="ad_userDNSearchFilter"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setADUserDNSearchFilter(e.target.value);
}}
label="User DN Search Filter"
value={ADUserDNSearchFilter}
placeholder="(sAMAcountName=%s)"
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="ad_groupSearchBaseDN"
name="ad_groupSearchBaseDN"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setADGroupSearchBaseDN(e.target.value);
}}
label="Group Search Base DN"
value={ADGroupSearchBaseDN}
placeholder="ou=hwengg,dc=min,dc=io;ou=swengg,dc=min,dc=io"
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBoxWrapper
id="ad_groupSearchFilter"
name="ad_groupSearchFilter"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setADGroupSearchFilter(e.target.value);
}}
label="Group Search Filter"
value={ADGroupSearchFilter}
placeholder="(&(objectclass=groupOfNames)(member=%s))"
/>
</Grid>
</Fragment>
)}
<Grid item xs={12} className={classes.buttonContainer}>
<Button
type="submit"
variant="contained"
color="primary"
disabled={!isFormValid || isSending}
onClick={() => setDialogOpen(true)}
>
Save
</Button>
</Grid>
</Paper>
<Grid item xs={12} className={classes.buttonContainer}>
<Button
type="submit"
variant="contained"
color="primary"
disabled={!isFormValid || isSending}
onClick={() => setDialogOpen(true)}
>
Save
</Button>
</Grid>
</Fragment>
)}
</React.Fragment>

View File

@@ -28,7 +28,6 @@ import {
tenantDetailsStyles,
wizardCommon,
} from "../../Common/FormComponents/common/styleLibrary";
import Paper from "@mui/material/Paper";
import Grid from "@mui/material/Grid";
import React, { Fragment, useCallback, useEffect, useState } from "react";
import FormSwitchWrapper from "../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper";
@@ -44,6 +43,7 @@ import ConfirmDialog from "../../Common/ModalWrapper/ConfirmDialog";
import { AddIcon, ConfirmModalIcon } from "../../../../icons";
import Loader from "../../Common/Loader/Loader";
import TLSCertificate from "../../Common/TLSCertificate/TLSCertificate";
import SectionTitle from "../../Common/SectionTitle";
interface ITenantSecurity {
classes: any;
@@ -78,12 +78,6 @@ const styles = (theme: Theme) =>
flexFlow: "column",
},
},
certInputRow: {
display: "flex",
alignItems: "center",
borderBottom: "1px solid #eaeaea",
marginBottom: 10,
},
caCertsRow: {
borderBottom: "1px solid #eaeaea",
display: "flex",
@@ -341,212 +335,209 @@ const TenantSecurity = ({
}
/>
{loadingTenant ? (
<Paper className={classes.paperContainer}>
<div className={classes.loaderAlign}>
<Loader />
</div>
</Paper>
<div className={classes.loaderAlign}>
<Loader />
</div>
) : (
<Fragment>
<h1 className={classes.sectionTitle}>Security</h1>
<Paper className={classes.paperContainer}>
<Grid item xs={12} className={classes.title}>
<Grid item xs={12} className={classes.formFieldRow}>
<FormSwitchWrapper
value="enableAutoCert"
id="enableAutoCert"
name="enableAutoCert"
checked={enableAutoCert}
onChange={(e) => {
const targetD = e.target;
const checked = targetD.checked;
setEnableAutoCert(checked);
}}
label={"TLS"}
description={
"The internode certificates will be generated and managed by MinIO Operator"
}
/>
<Grid container spacing={1}>
<Grid item xs={12}>
<h1 className={classes.sectionTitle}>Security</h1>
<hr className={classes.hrClass} />
</Grid>
<Grid item xs={12}>
<FormSwitchWrapper
value="enableAutoCert"
id="enableAutoCert"
name="enableAutoCert"
checked={enableAutoCert}
onChange={(e) => {
const targetD = e.target;
const checked = targetD.checked;
setEnableAutoCert(checked);
}}
label={"TLS"}
description={
"The internode certificates will be generated and managed by MinIO Operator"
}
/>
</Grid>
<Grid item xs={12}>
<FormSwitchWrapper
value="enableCustomCerts"
id="enableCustomCerts"
name="enableCustomCerts"
checked={enableCustomCerts}
onChange={(e) => {
const targetD = e.target;
const checked = targetD.checked;
setEnableCustomCerts(checked);
}}
label={"Custom Certificates"}
description={"Certificates used to terminated TLS at MinIO"}
/>
</Grid>
{enableCustomCerts && (
<Fragment>
<Grid item xs={12}>
<SectionTitle>MinIO Certificates</SectionTitle>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<FormSwitchWrapper
value="enableCustomCerts"
id="enableCustomCerts"
name="enableCustomCerts"
checked={enableCustomCerts}
onChange={(e) => {
const targetD = e.target;
const checked = targetD.checked;
setEnableCustomCerts(checked);
}}
label={"Custom Certificates"}
/>
<Grid item xs={12}>
{minioTLSCertificateSecrets.map(
(certificateInfo: ICertificateInfo) => (
<TLSCertificate
certificateInfo={certificateInfo}
onDelete={() => removeCertificate(certificateInfo)}
/>
)
)}
</Grid>
</Grid>
{enableCustomCerts && (
<Fragment>
<Grid container item xs={12} className={classes.formFieldRow}>
<h4>MinIO Certificates</h4>
</Grid>
<Grid container item xs={12} className={classes.formFieldRow}>
{minioTLSCertificateSecrets.map(
(certificateInfo: ICertificateInfo) => (
<TLSCertificate
certificateInfo={certificateInfo}
onDelete={() => removeCertificate(certificateInfo)}
/>
)
)}
</Grid>
<Grid container item xs={12} className={classes.formFieldRow}>
{minioCertificates.map((keyPair) => (
<Grid
item
xs={12}
key={keyPair.id}
className={classes.certInputRow}
>
<Grid item xs={9} className={classes.fileItem}>
<Grid item xs={6}>
<FileSelector
onChange={(encodedValue, fileName) =>
addFileToKeyPair(
"minio",
keyPair.id,
"cert",
fileName,
encodedValue
)
}
accept=".cer,.crt,.cert,.pem"
id="tlsCert"
name="tlsCert"
label="Cert"
value={keyPair.cert}
/>
</Grid>
<Grid item xs={6} className={classes.spacerLeft}>
<FileSelector
onChange={(encodedValue, fileName) =>
addFileToKeyPair(
"minio",
keyPair.id,
"key",
fileName,
encodedValue
)
}
accept=".key,.pem"
id="tlsKey"
name="tlsKey"
label="Key"
value={keyPair.key}
/>
</Grid>
</Grid>
<Grid item md={2} xs={1}>
<Button
variant="outlined"
color="secondary"
onClick={() => deleteKeyPair("minio", keyPair.id)}
>
Remove
</Button>
</Grid>
</Grid>
))}
</Grid>
<Grid container item xs={12} className={classes.formFieldRow}>
<Button
variant="outlined"
color="primary"
endIcon={<AddIcon />}
onClick={() => addKeyPair("minio")}
<Grid item xs={12}>
{minioCertificates.map((keyPair) => (
<Grid
container
key={keyPair.id}
alignItems={"center"}
style={{ borderBottom: "1px solid #eaeaea" }}
>
Add Certificate
</Button>
</Grid>
<Grid container item xs={12} className={classes.formFieldRow}>
<h4>MinIO CA Certificates</h4>
</Grid>
<Grid container item xs={12} className={classes.formFieldRow}>
{minioTLSCaCertificateSecrets.map(
(certificateInfo: ICertificateInfo) => (
<TLSCertificate
certificateInfo={certificateInfo}
onDelete={() => removeCertificate(certificateInfo)}
<Grid item xs={5}>
<FileSelector
onChange={(encodedValue, fileName) =>
addFileToKeyPair(
"minio",
keyPair.id,
"cert",
fileName,
encodedValue
)
}
accept=".cer,.crt,.cert,.pem"
id="tlsCert"
name="tlsCert"
label="Cert"
value={keyPair.cert}
/>
)
)}
</Grid>
<Grid container item xs={12} className={classes.formFieldRow}>
{minioCaCertificates.map((keyPair: KeyPair) => (
<Grid
item
xs={12}
className={classes.caCertsRow}
key={keyPair.id}
>
<Grid item xs={9} className={classes.fileItem}>
<FileSelector
onChange={(encodedValue, fileName) =>
addFileToKeyPair(
"minioCAs",
keyPair.id,
"cert",
fileName,
encodedValue
)
}
accept=".cer,.crt,.cert,.pem"
id="tlsCert"
name="tlsCert"
label="Cert"
value={keyPair.cert}
/>
</Grid>
<Grid item xs={1}>
<Button
variant="outlined"
color="secondary"
onClick={() => deleteKeyPair("minioCAs", keyPair.id)}
>
Remove
</Button>
</Grid>
</Grid>
))}
</Grid>
<Grid container item xs={12} className={classes.formFieldRow}>
<Button
variant="outlined"
color="primary"
endIcon={<AddIcon />}
onClick={() => addKeyPair("minioCAs")}
>
Add CA Certificate
</Button>
</Grid>
</Fragment>
)}
<Grid item xs={5}>
<FileSelector
onChange={(encodedValue, fileName) =>
addFileToKeyPair(
"minio",
keyPair.id,
"key",
fileName,
encodedValue
)
}
accept=".key,.pem"
id="tlsKey"
name="tlsKey"
label="Key"
value={keyPair.key}
/>
</Grid>
<Grid item xs={2}>
<Button
variant="outlined"
color="secondary"
onClick={() => deleteKeyPair("minio", keyPair.id)}
>
Remove
</Button>
</Grid>
</Grid>
))}
</Grid>
<Grid item xs={12} textAlign={"right"}>
<Button
variant="outlined"
color="primary"
endIcon={<AddIcon />}
onClick={() => addKeyPair("minio")}
>
Add Certificate
</Button>
</Grid>
<Grid item xs={12} className={classes.buttonContainer}>
<Button
type="submit"
variant="contained"
color="primary"
disabled={dialogOpen || isSending}
onClick={() => setDialogOpen(true)}
>
Save
</Button>
</Grid>
</Paper>
</Fragment>
<Grid item xs={12}>
<SectionTitle>MinIO CA Certificates</SectionTitle>
</Grid>
<Grid item xs={12}>
{minioTLSCaCertificateSecrets.map(
(certificateInfo: ICertificateInfo) => (
<TLSCertificate
certificateInfo={certificateInfo}
onDelete={() => removeCertificate(certificateInfo)}
/>
)
)}
</Grid>
<Grid item xs={12}>
{minioCaCertificates.map((keyPair: KeyPair) => (
<Grid
container
key={keyPair.id}
style={{ borderBottom: "1px solid #eaeaea" }}
alignItems={"center"}
justifyContent={"space-between"}
>
<Grid item xs={5} className={classes.fileItem}>
<FileSelector
onChange={(encodedValue, fileName) =>
addFileToKeyPair(
"minioCAs",
keyPair.id,
"cert",
fileName,
encodedValue
)
}
accept=".cer,.crt,.cert,.pem"
id="tlsCert"
name="tlsCert"
label="Cert"
value={keyPair.cert}
/>
</Grid>
<Grid item xs={2}>
<Button
variant="outlined"
color="secondary"
onClick={() => deleteKeyPair("minioCAs", keyPair.id)}
>
Remove
</Button>
</Grid>
</Grid>
))}
</Grid>
<Grid item xs={12} textAlign={"right"}>
<Button
variant="outlined"
color="primary"
endIcon={<AddIcon />}
onClick={() => addKeyPair("minioCAs")}
>
Add CA Certificate
</Button>
</Grid>
</Fragment>
)}
<Grid item xs={12} textAlign={"right"}>
<Button
type="submit"
variant="contained"
color="primary"
disabled={dialogOpen || isSending}
onClick={() => setDialogOpen(true)}
>
Save
</Button>
</Grid>
</Grid>
)}
</React.Fragment>
);

View File

@@ -24,17 +24,15 @@ import {
containerForHeader,
tenantDetailsStyles,
} from "../../Common/FormComponents/common/styleLibrary";
import { Box, Grid, Stack } from "@mui/material";
import Paper from "@mui/material/Paper";
import { Box, Grid } from "@mui/material";
import { ITenant } from "../ListTenants/types";
import UpdateTenantModal from "./UpdateTenantModal";
import { AppState } from "../../../../store";
import AButton from "../../Common/AButton/AButton";
import { styled } from "@mui/styles";
import SummaryUsageBar from "../../Common/UsageBarWrapper/SummaryUsageBar";
import LabelValuePair from "../../Common/UsageBarWrapper/LabelValuePair";
import FormSwitchWrapper from "../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper";
import StackRow from "../../Common/UsageBarWrapper/StackRow";
import SectionTitle from "../../Common/SectionTitle";
interface ITenantsSummary {
classes: any;
@@ -114,10 +112,6 @@ const styles = (theme: Theme) =>
...containerForHeader(theme.spacing(4)),
});
const StackItem = styled(Paper)(({ theme }) => ({
border: 0,
}));
const healthStatusToClass = (health_status: string = "red", classes: any) => {
return health_status === "red"
? classes.redState
@@ -226,15 +220,7 @@ const TenantSummary = ({
/>
)}
<Stack
direction={{ xs: "column-reverse", sm: "row" }}
justifyContent="space-between"
>
<StackItem>
<h3>Details</h3>
</StackItem>
<StackItem></StackItem>
</Stack>
<SectionTitle separator={false}>Details</SectionTitle>
<StorageSummary tenant={tenant} classes={classes} />
@@ -361,64 +347,49 @@ const TenantSummary = ({
</Grid>
</Grid>
<Stack>
<StackRow
sx={{
borderBottom: "1px solid #eaeaea",
margin: 0,
}}
>
<h3
style={{
marginBottom: 10,
}}
>
Features
</h3>
</StackRow>
<Box sx={{ ...featureRowStyle }}>
<LabelValuePair
orientation="row"
label="Logs:"
value={getToggle(logEnabled, "tenant-log")}
{...featureItemStyleProps}
/>
<SectionTitle>Features</SectionTitle>
<Box sx={{ ...featureRowStyle }}>
<LabelValuePair
orientation="row"
label="Logs:"
value={getToggle(logEnabled, "tenant-log")}
{...featureItemStyleProps}
/>
<LabelValuePair
orientation="row"
label={"AD/LDAP:"}
value={getToggle(adEnabled, "tenant-sts")}
{...featureItemStyleProps}
/>
<LabelValuePair
orientation="row"
label={"Encryption:"}
value={getToggle(encryptionEnabled, "tenant-enc")}
{...featureItemStyleProps}
/>
</Box>
<Box sx={{ ...featureRowStyle }}>
<LabelValuePair
orientation="row"
label="MinIO TLS:"
value={getToggle(minioTLS, "tenant-tls")}
{...featureItemStyleProps}
/>
<LabelValuePair
orientation="row"
label={"AD/LDAP:"}
value={getToggle(adEnabled, "tenant-sts")}
{...featureItemStyleProps}
/>
<LabelValuePair
orientation="row"
label={"Encryption:"}
value={getToggle(encryptionEnabled, "tenant-enc")}
{...featureItemStyleProps}
/>
</Box>
<Box sx={{ ...featureRowStyle }}>
<LabelValuePair
orientation="row"
label="MinIO TLS:"
value={getToggle(minioTLS, "tenant-tls")}
{...featureItemStyleProps}
/>
<LabelValuePair
orientation="row"
label={"Monitoring:"}
value={getToggle(monitoringEnabled, "tenant-monitor")}
{...featureItemStyleProps}
/>
<LabelValuePair
orientation="row"
label={"OpenID:"}
value={getToggle(oidcEnabled, "tenant-oidc")}
{...featureItemStyleProps}
/>
</Box>
</Stack>
<LabelValuePair
orientation="row"
label={"Monitoring:"}
value={getToggle(monitoringEnabled, "tenant-monitor")}
{...featureItemStyleProps}
/>
<LabelValuePair
orientation="row"
label={"OpenID:"}
value={getToggle(oidcEnabled, "tenant-oidc")}
{...featureItemStyleProps}
/>
</Box>
</Fragment>
);
};

View File

@@ -131,59 +131,61 @@ const TenantVolumes = ({
closeDeleteModalAndRefresh={closeDeleteModalAndRefresh}
/>
)}
<h1 className={classes.sectionTitle}>Volumes</h1>
<Grid item xs={12} className={classes.actionsTray}>
<TextField
placeholder="Search Volumes (PVCs)"
className={classes.searchField}
id="search-resource"
label=""
InputProps={{
disableUnderline: true,
startAdornment: (
<InputAdornment position="start">
<SearchIcon />
</InputAdornment>
),
}}
onChange={(e) => {
setFilter(e.target.value);
}}
variant="standard"
/>
</Grid>
<Grid item xs={12} className={classes.tableBlock}>
<TableWrapper
itemActions={[
{ type: "view", onClick: PVCViewAction },
{ type: "delete", onClick: confirmDeletePVC },
]}
columns={[
{
label: "Name",
elementKey: "name",
},
{
label: "Status",
elementKey: "status",
width: 120,
},
{
label: "Capacity",
elementKey: "capacity",
width: 120,
},
{
label: "Storage Class",
elementKey: "storageClass",
},
]}
isLoading={loading}
records={filteredRecords}
entityName="PVCs"
idField="name"
customPaperHeight={classes.tableWrapper}
/>
<Grid container spacing={1}>
<h1 className={classes.sectionTitle}>Volumes</h1>
<Grid item xs={12}>
<TextField
placeholder="Search Volumes (PVCs)"
className={classes.searchField}
id="search-resource"
label=""
InputProps={{
disableUnderline: true,
startAdornment: (
<InputAdornment position="start">
<SearchIcon />
</InputAdornment>
),
}}
onChange={(e) => {
setFilter(e.target.value);
}}
variant="standard"
/>
</Grid>
<Grid item xs={12} className={classes.tableBlock}>
<TableWrapper
itemActions={[
{ type: "view", onClick: PVCViewAction },
{ type: "delete", onClick: confirmDeletePVC },
]}
columns={[
{
label: "Name",
elementKey: "name",
},
{
label: "Status",
elementKey: "status",
width: 120,
},
{
label: "Capacity",
elementKey: "capacity",
width: 120,
},
{
label: "Storage Class",
elementKey: "storageClass",
},
]}
isLoading={loading}
records={filteredRecords}
entityName="PVCs"
idField="name"
customPaperHeight={classes.tableWrapper}
/>
</Grid>
</Grid>
</Fragment>
);