Fixes and improvements for Tenant Security page (#2252)
- Tenant securityContext was only being applied to first pool - Fixed style issues on tenant security page to be more consistent - Added missing FsGroupChangePolicy in the SecurityContextSelector component Signed-off-by: Lenin Alevski <alevsk.8772@gmail.com>
This commit is contained in:
@@ -1096,8 +1096,13 @@ func updateTenantSecurity(ctx context.Context, operatorClient OperatorClientI, c
|
||||
|
||||
// set Security Context
|
||||
var newTenantSecurityContext *corev1.PodSecurityContext
|
||||
newTenantSecurityContext, _ = convertModelSCToK8sSC(params.Body.SecurityContext)
|
||||
minInst.Spec.Pools[0].SecurityContext = newTenantSecurityContext
|
||||
newTenantSecurityContext, err = convertModelSCToK8sSC(params.Body.SecurityContext)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for index := range minInst.Spec.Pools {
|
||||
minInst.Spec.Pools[index].SecurityContext = newTenantSecurityContext
|
||||
}
|
||||
|
||||
// Update External Certificates
|
||||
minInst.Spec.ExternalCertSecret = newMinIOExternalCertSecret
|
||||
|
||||
@@ -58,8 +58,10 @@ func convertModelSCToK8sSC(sc *models.SecurityContext) (*corev1.PodSecurityConte
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
FSGroupChangePolicy := corev1.PodFSGroupChangePolicy(sc.FsGroupChangePolicy)
|
||||
|
||||
FSGroupChangePolicy := corev1.PodFSGroupChangePolicy("Always")
|
||||
if sc.FsGroupChangePolicy != "" {
|
||||
FSGroupChangePolicy = corev1.PodFSGroupChangePolicy(sc.FsGroupChangePolicy)
|
||||
}
|
||||
return &corev1.PodSecurityContext{
|
||||
RunAsUser: &runAsUser,
|
||||
RunAsGroup: &runAsGroup,
|
||||
@@ -74,10 +76,10 @@ func convertK8sSCToModelSC(sc *corev1.PodSecurityContext) *models.SecurityContex
|
||||
runAsUser := strconv.FormatInt(*sc.RunAsUser, 10)
|
||||
runAsGroup := strconv.FormatInt(*sc.RunAsGroup, 10)
|
||||
fsGroup := strconv.FormatInt(*sc.FSGroup, 10)
|
||||
fsGroupPolicy := ""
|
||||
fsGroupChangePolicy := "Always"
|
||||
|
||||
if sc.FSGroupChangePolicy != nil {
|
||||
fsGroupPolicy = string(*sc.FSGroupChangePolicy)
|
||||
fsGroupChangePolicy = string(*sc.FSGroupChangePolicy)
|
||||
}
|
||||
|
||||
return &models.SecurityContext{
|
||||
@@ -85,7 +87,7 @@ func convertK8sSCToModelSC(sc *corev1.PodSecurityContext) *models.SecurityContex
|
||||
RunAsGroup: &runAsGroup,
|
||||
RunAsNonRoot: sc.RunAsNonRoot,
|
||||
FsGroup: fsGroup,
|
||||
FsGroupChangePolicy: fsGroupPolicy,
|
||||
FsGroupChangePolicy: fsGroupChangePolicy,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,8 @@ import {
|
||||
} from "../TenantDetails/tenantMonitoringSlice";
|
||||
import { clearValidationError, imagePattern, numericPattern } from "../utils";
|
||||
import SecurityContextSelector from "../securityContextSelector";
|
||||
import { setFSGroupChangePolicy } from "../tenantSecurityContextSlice";
|
||||
import { fsGroupChangePolicyType } from "../types";
|
||||
|
||||
interface ITenantMonitoring {
|
||||
classes: any;
|
||||
@@ -150,6 +152,10 @@ const TenantMonitoring = ({ classes }: ITenantMonitoring) => {
|
||||
const runAsNonRoot = useSelector(
|
||||
(state: AppState) => state.editTenantMonitoring.runAsNonRoot
|
||||
);
|
||||
const fsGroupChangePolicy = useSelector(
|
||||
(state: AppState) => state.editTenantSecurityContext.fsGroupChangePolicy
|
||||
);
|
||||
|
||||
const cleanValidation = (fieldName: string) => {
|
||||
setValidationErrors(clearValidationError(validationErrors, fieldName));
|
||||
};
|
||||
@@ -551,12 +557,16 @@ const TenantMonitoring = ({ classes }: ITenantMonitoring) => {
|
||||
runAsUser={runAsUser}
|
||||
fsGroup={fsGroup}
|
||||
runAsNonRoot={runAsNonRoot}
|
||||
fsGroupChangePolicy={fsGroupChangePolicy}
|
||||
setFSGroup={(value: string) => dispatch(setFSGroup(value))}
|
||||
setRunAsUser={(value: string) => dispatch(setRunAsUser(value))}
|
||||
setRunAsGroup={(value: string) => dispatch(setRunAsGroup(value))}
|
||||
setRunAsNonRoot={(value: boolean) =>
|
||||
dispatch(setRunAsNonRoot(value))
|
||||
}
|
||||
setFSGroupChangePolicy={(value: fsGroupChangePolicyType) =>
|
||||
dispatch(setFSGroupChangePolicy(value))
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} textAlign={"right"}>
|
||||
|
||||
@@ -50,14 +50,16 @@ import {
|
||||
setDBMemRequest,
|
||||
setDBRunAsUser,
|
||||
setDBFSGroup,
|
||||
setDBFSGroupChangePolicy,
|
||||
setDBRunAsGroup,
|
||||
setDBRunAsNonRoot,
|
||||
setRefreshLoggingInfo,
|
||||
} from "../TenantDetails/tenantAuditLogSlice";
|
||||
} from "./tenantAuditLogSlice";
|
||||
|
||||
import SecurityContextSelector from "../securityContextSelector";
|
||||
|
||||
import { clearValidationError, imagePattern, numericPattern } from "../utils";
|
||||
import { fsGroupChangePolicyType } from "../types";
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
@@ -116,6 +118,10 @@ const LoggingDBDetails = ({
|
||||
const dbFSGroup = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.dbSecurityContext.fsGroup
|
||||
);
|
||||
const dbFSGroupChangePolicy = useSelector(
|
||||
(state: AppState) =>
|
||||
state.editTenantLogging.dbSecurityContext.fsGroupChangePolicy
|
||||
);
|
||||
const dbRunAsNonRoot = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.dbSecurityContext.runAsNonRoot
|
||||
);
|
||||
@@ -178,6 +184,8 @@ const LoggingDBDetails = ({
|
||||
runAsUser: dbRunAsUser != null ? dbRunAsUser : "",
|
||||
fsGroup: dbFSGroup != null ? dbFSGroup : "",
|
||||
runAsNonRoot: dbRunAsNonRoot != null ? dbRunAsNonRoot : true,
|
||||
fsGroupChangePolicy:
|
||||
dbFSGroupChangePolicy != null ? dbFSGroupChangePolicy : "Always",
|
||||
};
|
||||
api
|
||||
.invoke(
|
||||
@@ -328,6 +336,7 @@ const LoggingDBDetails = ({
|
||||
runAsGroup={dbRunAsGroup}
|
||||
runAsUser={dbRunAsUser}
|
||||
fsGroup={dbFSGroup}
|
||||
fsGroupChangePolicy={dbFSGroupChangePolicy}
|
||||
runAsNonRoot={dbRunAsNonRoot}
|
||||
setFSGroup={(value: string) => dispatch(setDBFSGroup(value))}
|
||||
setRunAsUser={(value: string) => dispatch(setDBRunAsUser(value))}
|
||||
@@ -335,6 +344,9 @@ const LoggingDBDetails = ({
|
||||
setRunAsNonRoot={(value: boolean) =>
|
||||
dispatch(setDBRunAsNonRoot(value))
|
||||
}
|
||||
setFSGroupChangePolicy={(value: fsGroupChangePolicyType) =>
|
||||
dispatch(setDBFSGroupChangePolicy(value))
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} textAlign={"right"}>
|
||||
|
||||
@@ -57,6 +57,8 @@ import {
|
||||
setRunAsNonRoot,
|
||||
setRefreshLoggingInfo,
|
||||
} from "../TenantDetails/tenantAuditLogSlice";
|
||||
import { setFSGroupChangePolicy } from "../tenantSecurityContextSlice";
|
||||
import { fsGroupChangePolicyType } from "../types";
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
@@ -118,6 +120,9 @@ const TenantAuditLogging = ({
|
||||
const runAsNonRoot = useSelector(
|
||||
(state: AppState) => state.editTenantLogging.securityContext.runAsNonRoot
|
||||
);
|
||||
const fsGroupChangePolicy = useSelector(
|
||||
(state: AppState) => state.editTenantSecurityContext.fsGroupChangePolicy
|
||||
);
|
||||
|
||||
const [validationErrors, setValidationErrors] = useState<any>({});
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
@@ -332,12 +337,16 @@ const TenantAuditLogging = ({
|
||||
runAsUser={runAsUser}
|
||||
fsGroup={fsGroup}
|
||||
runAsNonRoot={runAsNonRoot}
|
||||
fsGroupChangePolicy={fsGroupChangePolicy}
|
||||
setFSGroup={(value: string) => dispatch(setFSGroup(value))}
|
||||
setRunAsUser={(value: string) => dispatch(setRunAsUser(value))}
|
||||
setRunAsGroup={(value: string) => dispatch(setRunAsGroup(value))}
|
||||
setRunAsNonRoot={(value: boolean) =>
|
||||
dispatch(setRunAsNonRoot(value))
|
||||
}
|
||||
setFSGroupChangePolicy={(value: fsGroupChangePolicyType) =>
|
||||
dispatch(setFSGroupChangePolicy(value))
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
|
||||
@@ -17,11 +17,15 @@
|
||||
import React, { Fragment, useCallback, useEffect, useState } from "react";
|
||||
import { connect, useSelector } from "react-redux";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import { Button, DialogContentText } from "@mui/material";
|
||||
import { Button, DialogContentText, IconButton } from "@mui/material";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import { ICertificateInfo, ITenantSecurityResponse } from "../types";
|
||||
import {
|
||||
fsGroupChangePolicyType,
|
||||
ICertificateInfo,
|
||||
ITenantSecurityResponse,
|
||||
} from "../types";
|
||||
import {
|
||||
containerForHeader,
|
||||
createTenantCommon,
|
||||
@@ -50,7 +54,9 @@ import {
|
||||
setFSGroup,
|
||||
setRunAsGroup,
|
||||
setRunAsNonRoot,
|
||||
setFSGroupChangePolicy,
|
||||
} from "../tenantSecurityContextSlice";
|
||||
import RemoveIcon from "../../../../icons/RemoveIcon";
|
||||
|
||||
interface ITenantSecurity {
|
||||
classes: any;
|
||||
@@ -60,6 +66,55 @@ const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
...tenantDetailsStyles,
|
||||
...spacingUtils,
|
||||
minioCertificateRows: {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "flex-start",
|
||||
borderBottom: "1px solid #EAEAEA",
|
||||
"&:last-child": {
|
||||
borderBottom: 0,
|
||||
},
|
||||
"@media (max-width: 900px)": {
|
||||
flex: 1,
|
||||
},
|
||||
},
|
||||
minioCertsContainer: {
|
||||
marginBottom: 15,
|
||||
},
|
||||
minioCACertsRow: {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "flex-start",
|
||||
|
||||
borderBottom: "1px solid #EAEAEA",
|
||||
"&:last-child": {
|
||||
borderBottom: 0,
|
||||
},
|
||||
"@media (max-width: 900px)": {
|
||||
flex: 1,
|
||||
|
||||
"& div label": {
|
||||
minWidth: 50,
|
||||
},
|
||||
},
|
||||
},
|
||||
rowActions: {
|
||||
display: "flex",
|
||||
justifyContent: "flex-end",
|
||||
"@media (max-width: 900px)": {
|
||||
flex: 1,
|
||||
},
|
||||
},
|
||||
overlayAction: {
|
||||
marginLeft: 10,
|
||||
"& svg": {
|
||||
maxWidth: 15,
|
||||
maxHeight: 15,
|
||||
},
|
||||
"& button": {
|
||||
background: "#EAEAEA",
|
||||
},
|
||||
},
|
||||
loaderAlign: {
|
||||
textAlign: "center",
|
||||
},
|
||||
@@ -93,14 +148,31 @@ const TenantSecurity = ({ classes }: ITenantSecurity) => {
|
||||
|
||||
const [isSending, setIsSending] = useState<boolean>(false);
|
||||
const [dialogOpen, setDialogOpen] = useState<boolean>(false);
|
||||
const [enableTLS, setEnableTLS] = useState<boolean>(false);
|
||||
const [enableAutoCert, setEnableAutoCert] = useState<boolean>(false);
|
||||
const [enableCustomCerts, setEnableCustomCerts] = useState<boolean>(false);
|
||||
const [certificatesToBeRemoved, setCertificatesToBeRemoved] = useState<
|
||||
string[]
|
||||
>([]);
|
||||
// MinIO certificates
|
||||
const [minioCertificates, setMinioCertificates] = useState<KeyPair[]>([]);
|
||||
const [minioCaCertificates, setMinioCaCertificates] = useState<KeyPair[]>([]);
|
||||
const [minioCertificates, setMinioCertificates] = useState<KeyPair[]>([
|
||||
{
|
||||
id: Date.now().toString(),
|
||||
key: "",
|
||||
cert: "",
|
||||
encoded_key: "",
|
||||
encoded_cert: "",
|
||||
},
|
||||
]);
|
||||
const [minioCaCertificates, setMinioCaCertificates] = useState<KeyPair[]>([
|
||||
{
|
||||
id: Date.now().toString(),
|
||||
key: "",
|
||||
cert: "",
|
||||
encoded_key: "",
|
||||
encoded_cert: "",
|
||||
},
|
||||
]);
|
||||
const [minioTLSCertificateSecrets, setMinioTLSCertificateSecrets] = useState<
|
||||
ICertificateInfo[]
|
||||
>([]);
|
||||
@@ -119,6 +191,9 @@ const TenantSecurity = ({ classes }: ITenantSecurity) => {
|
||||
const runAsNonRoot = useSelector(
|
||||
(state: AppState) => state.editTenantSecurityContext.runAsNonRoot
|
||||
);
|
||||
const fsGroupChangePolicy = useSelector(
|
||||
(state: AppState) => state.editTenantSecurityContext.fsGroupChangePolicy
|
||||
);
|
||||
|
||||
const getTenantSecurityInfo = useCallback(() => {
|
||||
api
|
||||
@@ -128,8 +203,10 @@ const TenantSecurity = ({ classes }: ITenantSecurity) => {
|
||||
)
|
||||
.then((res: ITenantSecurityResponse) => {
|
||||
setEnableAutoCert(res.autoCert);
|
||||
setEnableTLS(res.autoCert);
|
||||
if (res.customCertificates.minio || res.customCertificates.minioCAs) {
|
||||
setEnableCustomCerts(true);
|
||||
setEnableTLS(true);
|
||||
}
|
||||
setMinioTLSCertificateSecrets(res.customCertificates.minio || []);
|
||||
setMinioTLSCaCertificateSecrets(res.customCertificates.minioCAs || []);
|
||||
@@ -137,6 +214,9 @@ const TenantSecurity = ({ classes }: ITenantSecurity) => {
|
||||
dispatch(setRunAsUser(res.securityContext.runAsUser));
|
||||
dispatch(setFSGroup(res.securityContext.fsGroup));
|
||||
dispatch(setRunAsNonRoot(res.securityContext.runAsNonRoot));
|
||||
dispatch(
|
||||
setFSGroupChangePolicy(res.securityContext.fsGroupChangePolicy)
|
||||
);
|
||||
})
|
||||
.catch((err: ErrorResponseHandler) => {
|
||||
dispatch(setErrorSnackMessage(err));
|
||||
@@ -159,6 +239,7 @@ const TenantSecurity = ({ classes }: ITenantSecurity) => {
|
||||
runAsUser: runAsUser,
|
||||
runAsNonRoot: runAsNonRoot,
|
||||
fsGroup: fsGroup,
|
||||
fsGroupChangePolicy: fsGroupChangePolicy,
|
||||
},
|
||||
};
|
||||
if (enableCustomCerts) {
|
||||
@@ -361,212 +442,253 @@ const TenantSecurity = ({ classes }: ITenantSecurity) => {
|
||||
<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>
|
||||
<Grid container spacing={1}>
|
||||
<Grid item xs={12}>
|
||||
<FormSwitchWrapper
|
||||
value="enableTLS"
|
||||
id="enableTLS"
|
||||
name="enableTLS"
|
||||
checked={enableTLS}
|
||||
onChange={(e) => {
|
||||
const targetD = e.target;
|
||||
const checked = targetD.checked;
|
||||
setEnableTLS(checked);
|
||||
}}
|
||||
label={"TLS"}
|
||||
description={
|
||||
"Securing all the traffic using TLS. This is required for Encryption Configuration"
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
{enableTLS && (
|
||||
<Fragment>
|
||||
<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={"AutoCert"}
|
||||
description={
|
||||
"The internode certificates will be generated and managed by MinIO Operator"
|
||||
}
|
||||
/>
|
||||
</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"}
|
||||
description={"Certificates used to terminated TLS at MinIO"}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
{enableCustomCerts && (
|
||||
<Fragment>
|
||||
<Grid item xs={12}>
|
||||
<SectionTitle>MinIO Certificates</SectionTitle>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
{minioTLSCertificateSecrets.map(
|
||||
(certificateInfo: ICertificateInfo) => (
|
||||
<TLSCertificate
|
||||
certificateInfo={certificateInfo}
|
||||
onDelete={() => removeCertificate(certificateInfo)}
|
||||
/>
|
||||
)
|
||||
{enableCustomCerts && (
|
||||
<Fragment>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<SectionTitle>MinIO Certificates</SectionTitle>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
{minioTLSCertificateSecrets.map(
|
||||
(certificateInfo: ICertificateInfo) => (
|
||||
<TLSCertificate
|
||||
certificateInfo={certificateInfo}
|
||||
onDelete={() => removeCertificate(certificateInfo)}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
{minioCertificates.map((keyPair, index) => (
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
key={keyPair.id}
|
||||
className={classes.minioCertificateRows}
|
||||
>
|
||||
<Grid item xs={10} className={classes.fileItem}>
|
||||
<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}
|
||||
/>
|
||||
<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} className={classes.rowActions}>
|
||||
<div className={classes.overlayAction}>
|
||||
<IconButton
|
||||
size={"small"}
|
||||
onClick={() => addKeyPair("minio")}
|
||||
disabled={
|
||||
index !== minioCertificates.length - 1
|
||||
}
|
||||
>
|
||||
<AddIcon />
|
||||
</IconButton>
|
||||
</div>
|
||||
<div className={classes.overlayAction}>
|
||||
<IconButton
|
||||
size={"small"}
|
||||
onClick={() =>
|
||||
deleteKeyPair("minio", keyPair.id)
|
||||
}
|
||||
disabled={minioCertificates.length <= 1}
|
||||
>
|
||||
<RemoveIcon />
|
||||
</IconButton>
|
||||
</div>
|
||||
</Grid>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
<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, index) => (
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
key={keyPair.id}
|
||||
className={classes.minioCACertsRow}
|
||||
>
|
||||
<Grid item xs={10}>
|
||||
<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}>
|
||||
<div className={classes.rowActions}>
|
||||
<div className={classes.overlayAction}>
|
||||
<IconButton
|
||||
size={"small"}
|
||||
onClick={() => addKeyPair("minioCAs")}
|
||||
disabled={
|
||||
index !== minioCaCertificates.length - 1
|
||||
}
|
||||
>
|
||||
<AddIcon />
|
||||
</IconButton>
|
||||
</div>
|
||||
<div className={classes.overlayAction}>
|
||||
<IconButton
|
||||
size={"small"}
|
||||
onClick={() =>
|
||||
deleteKeyPair("minioCAs", keyPair.id)
|
||||
}
|
||||
disabled={minioCaCertificates.length <= 1}
|
||||
>
|
||||
<RemoveIcon />
|
||||
</IconButton>
|
||||
</div>
|
||||
</div>
|
||||
</Grid>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
</Fragment>
|
||||
)}
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12}>
|
||||
{minioCertificates.map((keyPair) => (
|
||||
<Grid
|
||||
container
|
||||
key={keyPair.id}
|
||||
alignItems={"center"}
|
||||
style={{ borderBottom: "1px solid #eaeaea" }}
|
||||
>
|
||||
<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 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}>
|
||||
<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} className={classes.formFieldRow}>
|
||||
<SecurityContextSelector
|
||||
classes={classes}
|
||||
runAsGroup={runAsGroup}
|
||||
runAsUser={runAsUser}
|
||||
fsGroup={fsGroup}
|
||||
runAsNonRoot={runAsNonRoot}
|
||||
setFSGroup={(value: string) => dispatch(setFSGroup(value))}
|
||||
setRunAsUser={(value: string) => dispatch(setRunAsUser(value))}
|
||||
setRunAsGroup={(value: string) => dispatch(setRunAsGroup(value))}
|
||||
setRunAsNonRoot={(value: boolean) =>
|
||||
dispatch(setRunAsNonRoot(value))
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} textAlign={"right"}>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
disabled={dialogOpen || isSending}
|
||||
onClick={() => setDialogOpen(true)}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</Fragment>
|
||||
)}
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<h1 className={classes.sectionTitle}>Security Context</h1>
|
||||
<hr className={classes.hrClass} />
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<SecurityContextSelector
|
||||
classes={classes}
|
||||
runAsGroup={runAsGroup}
|
||||
runAsUser={runAsUser}
|
||||
fsGroup={fsGroup}
|
||||
runAsNonRoot={runAsNonRoot}
|
||||
fsGroupChangePolicy={fsGroupChangePolicy}
|
||||
setFSGroup={(value: string) => dispatch(setFSGroup(value))}
|
||||
setRunAsUser={(value: string) => dispatch(setRunAsUser(value))}
|
||||
setRunAsGroup={(value: string) =>
|
||||
dispatch(setRunAsGroup(value))
|
||||
}
|
||||
setRunAsNonRoot={(value: boolean) =>
|
||||
dispatch(setRunAsNonRoot(value))
|
||||
}
|
||||
setFSGroupChangePolicy={(value: fsGroupChangePolicyType) =>
|
||||
dispatch(setFSGroupChangePolicy(value))
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} textAlign={"right"}>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
disabled={dialogOpen || isSending}
|
||||
onClick={() => setDialogOpen(true)}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
)}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||
import { IKeyValue } from "../ListTenants/types";
|
||||
import { ISecurityContext } from "../types";
|
||||
import { fsGroupChangePolicyType, ISecurityContext } from "../types";
|
||||
|
||||
export interface IEditTenantAuditLogging {
|
||||
auditLoggingEnabled: boolean;
|
||||
@@ -151,6 +151,12 @@ export const editTenantAuditLoggingSlice = createSlice({
|
||||
setDBFSGroup: (state, action: PayloadAction<string>) => {
|
||||
state.dbSecurityContext.fsGroup = action.payload;
|
||||
},
|
||||
setDBFSGroupChangePolicy: (
|
||||
state,
|
||||
action: PayloadAction<fsGroupChangePolicyType>
|
||||
) => {
|
||||
state.dbSecurityContext.fsGroupChangePolicy = action.payload;
|
||||
},
|
||||
setDBRunAsNonRoot: (state, action: PayloadAction<boolean>) => {
|
||||
state.dbSecurityContext.runAsNonRoot = action.payload;
|
||||
},
|
||||
@@ -185,6 +191,7 @@ export const {
|
||||
setRunAsNonRoot,
|
||||
setDBRunAsUser,
|
||||
setDBFSGroup,
|
||||
setDBFSGroupChangePolicy,
|
||||
setDBRunAsGroup,
|
||||
setDBRunAsNonRoot,
|
||||
setRefreshLoggingInfo,
|
||||
|
||||
@@ -17,30 +17,51 @@
|
||||
import React, { Fragment } from "react";
|
||||
import InputBoxWrapper from "../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
|
||||
import FormSwitchWrapper from "../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper";
|
||||
import { Grid } from "@mui/material";
|
||||
import SelectWrapper from "../Common/FormComponents/SelectWrapper/SelectWrapper";
|
||||
import { Grid, SelectChangeEvent } from "@mui/material";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import { fsGroupChangePolicyType } from "./types";
|
||||
|
||||
interface IEditSecurityContextProps {
|
||||
classes: any;
|
||||
runAsUser: string;
|
||||
runAsGroup: string;
|
||||
fsGroup: string;
|
||||
fsGroupChangePolicy: fsGroupChangePolicyType;
|
||||
runAsNonRoot: boolean;
|
||||
setRunAsUser: any;
|
||||
setRunAsGroup: any;
|
||||
setFSGroup: any;
|
||||
setRunAsNonRoot: any;
|
||||
setFSGroupChangePolicy: any;
|
||||
}
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
configSectionItem: {
|
||||
marginRight: 15,
|
||||
marginBottom: 15,
|
||||
"& .multiContainer": {
|
||||
border: "1px solid red",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const SecurityContextSelector = ({
|
||||
classes,
|
||||
runAsGroup,
|
||||
runAsUser,
|
||||
fsGroup,
|
||||
fsGroupChangePolicy,
|
||||
runAsNonRoot,
|
||||
setRunAsUser,
|
||||
setRunAsGroup,
|
||||
setFSGroup,
|
||||
setRunAsNonRoot,
|
||||
setFSGroupChangePolicy,
|
||||
}: IEditSecurityContextProps) => {
|
||||
const dispatch = useDispatch();
|
||||
return (
|
||||
@@ -78,6 +99,10 @@ const SecurityContextSelector = ({
|
||||
min="0"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<div className={`${classes.multiContainerStackNarrow} `}>
|
||||
<div className={classes.configSectionItem}>
|
||||
<InputBoxWrapper
|
||||
type="number"
|
||||
@@ -92,9 +117,30 @@ const SecurityContextSelector = ({
|
||||
min="0"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={classes.configSectionItem}>
|
||||
<SelectWrapper
|
||||
label="FsGroupChangePolicy"
|
||||
id="securityContext_fsGroupChangePolicy"
|
||||
name="securityContext_fsGroupChangePolicy"
|
||||
onChange={(e: SelectChangeEvent<string>) => {
|
||||
dispatch(setFSGroupChangePolicy(e.target.value));
|
||||
}}
|
||||
value={fsGroupChangePolicy}
|
||||
options={[
|
||||
{
|
||||
label: "Always",
|
||||
value: "Always",
|
||||
},
|
||||
{
|
||||
label: "OnRootMismatch",
|
||||
value: "OnRootMismatch",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Grid>
|
||||
<br />
|
||||
<Grid item xs={12}>
|
||||
<div className={classes.multiContainer}>
|
||||
<FormSwitchWrapper
|
||||
@@ -113,4 +159,5 @@ const SecurityContextSelector = ({
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
export default SecurityContextSelector;
|
||||
|
||||
export default withStyles(styles)(SecurityContextSelector);
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// 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 { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||
import { IEditTenantSecurityContext } from "./types";
|
||||
import { fsGroupChangePolicyType, IEditTenantSecurityContext } from "./types";
|
||||
|
||||
const initialState: IEditTenantSecurityContext = {
|
||||
securityContextEnabled: false,
|
||||
@@ -22,6 +22,7 @@ const initialState: IEditTenantSecurityContext = {
|
||||
runAsGroup: "1000",
|
||||
fsGroup: "1000",
|
||||
runAsNonRoot: true,
|
||||
fsGroupChangePolicy: "Always",
|
||||
};
|
||||
|
||||
export const editTenantSecurityContextSlice = createSlice({
|
||||
@@ -43,6 +44,12 @@ export const editTenantSecurityContextSlice = createSlice({
|
||||
setRunAsNonRoot: (state, action: PayloadAction<boolean>) => {
|
||||
state.runAsNonRoot = action.payload;
|
||||
},
|
||||
setFSGroupChangePolicy: (
|
||||
state,
|
||||
action: PayloadAction<fsGroupChangePolicyType>
|
||||
) => {
|
||||
state.fsGroupChangePolicy = action.payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -52,6 +59,7 @@ export const {
|
||||
setRunAsGroup,
|
||||
setFSGroup,
|
||||
setRunAsNonRoot,
|
||||
setFSGroupChangePolicy,
|
||||
} = editTenantSecurityContextSlice.actions;
|
||||
|
||||
export default editTenantSecurityContextSlice.reducer;
|
||||
|
||||
@@ -132,12 +132,14 @@ export interface LabelKeyPair {
|
||||
value: string;
|
||||
}
|
||||
|
||||
export type fsGroupChangePolicyType = "Always" | "OnRootMismatch";
|
||||
|
||||
export interface ISecurityContext {
|
||||
runAsUser: string;
|
||||
runAsGroup: string;
|
||||
runAsNonRoot: boolean;
|
||||
fsGroup: string;
|
||||
fsGroupChangePolicy: "Always" | "OnRootMismatch";
|
||||
fsGroupChangePolicy: fsGroupChangePolicyType;
|
||||
}
|
||||
|
||||
export interface IConfigureFields {
|
||||
@@ -360,5 +362,6 @@ export interface IEditTenantSecurityContext {
|
||||
runAsUser: string;
|
||||
runAsGroup: string;
|
||||
fsGroup: string;
|
||||
fsGroupChangePolicy: fsGroupChangePolicyType;
|
||||
runAsNonRoot: boolean;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user