Create security context component and add to edit Prometheus Monitoring (#2115)
This commit is contained in:
@@ -63,6 +63,9 @@ type TenantMonitoringInfo struct {
|
||||
// prometheus enabled
|
||||
PrometheusEnabled bool `json:"prometheusEnabled,omitempty"`
|
||||
|
||||
// security context
|
||||
SecurityContext *SecurityContext `json:"securityContext,omitempty"`
|
||||
|
||||
// service account name
|
||||
ServiceAccountName string `json:"serviceAccountName,omitempty"`
|
||||
|
||||
@@ -92,6 +95,10 @@ func (m *TenantMonitoringInfo) Validate(formats strfmt.Registry) error {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateSecurityContext(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
@@ -176,6 +183,25 @@ func (m *TenantMonitoringInfo) validateNodeSelector(formats strfmt.Registry) err
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *TenantMonitoringInfo) validateSecurityContext(formats strfmt.Registry) error {
|
||||
if swag.IsZero(m.SecurityContext) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
if m.SecurityContext != nil {
|
||||
if err := m.SecurityContext.Validate(formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("securityContext")
|
||||
} else if ce, ok := err.(*errors.CompositeError); ok {
|
||||
return ce.ValidateName("securityContext")
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContextValidate validate this tenant monitoring info based on the context it is used
|
||||
func (m *TenantMonitoringInfo) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||
var res []error
|
||||
@@ -192,6 +218,10 @@ func (m *TenantMonitoringInfo) ContextValidate(ctx context.Context, formats strf
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.contextValidateSecurityContext(ctx, formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
@@ -258,6 +288,22 @@ func (m *TenantMonitoringInfo) contextValidateNodeSelector(ctx context.Context,
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *TenantMonitoringInfo) contextValidateSecurityContext(ctx context.Context, formats strfmt.Registry) error {
|
||||
|
||||
if m.SecurityContext != nil {
|
||||
if err := m.SecurityContext.ContextValidate(ctx, formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("securityContext")
|
||||
} else if ce, ok := err.(*errors.CompositeError); ok {
|
||||
return ce.ValidateName("securityContext")
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *TenantMonitoringInfo) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
|
||||
@@ -4301,6 +4301,10 @@ func init() {
|
||||
"prometheusEnabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"securityContext": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/securityContext"
|
||||
},
|
||||
"serviceAccountName": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -9678,6 +9682,10 @@ func init() {
|
||||
"prometheusEnabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"securityContext": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/securityContext"
|
||||
},
|
||||
"serviceAccountName": {
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
@@ -2137,11 +2137,10 @@ func getTenantMonitoringResponse(session *models.Principal, params operator_api.
|
||||
client: opClientClientSet,
|
||||
}
|
||||
|
||||
minInst, err := opClient.TenantGet(ctx, params.Namespace, params.Tenant, metav1.GetOptions{})
|
||||
minInst, err := getTenant(ctx, opClient, params.Namespace, params.Tenant)
|
||||
if err != nil {
|
||||
return nil, restapi.ErrorWithContext(ctx, err)
|
||||
}
|
||||
|
||||
monitoringInfo := &models.TenantMonitoringInfo{}
|
||||
|
||||
if minInst.Spec.Prometheus != nil {
|
||||
@@ -2212,7 +2211,9 @@ func getTenantMonitoringResponse(session *models.Principal, params operator_api.
|
||||
if len(minInst.Spec.Prometheus.SideCarImage) != 0 {
|
||||
monitoringInfo.SidecarImage = minInst.Spec.Prometheus.SideCarImage
|
||||
}
|
||||
|
||||
if minInst.Spec.Prometheus.SecurityContext != nil {
|
||||
monitoringInfo.SecurityContext = convertK8sSCToModelSC(minInst.Spec.Prometheus.SecurityContext)
|
||||
}
|
||||
return monitoringInfo, nil
|
||||
}
|
||||
|
||||
@@ -2306,12 +2307,16 @@ func setTenantMonitoringResponse(session *models.Principal, params operator_api.
|
||||
if err == nil {
|
||||
*minTenant.Spec.Prometheus.DiskCapacityDB = diskCapacityGB
|
||||
}
|
||||
|
||||
minTenant.Spec.Prometheus.ServiceAccountName = params.Data.ServiceAccountName
|
||||
minTenant.Spec.Prometheus.SecurityContext, err = convertModelSCToK8sSC(params.Data.SecurityContext)
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err)
|
||||
}
|
||||
_, err = opClient.TenantUpdate(ctx, minTenant, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
return false, restapi.ErrorWithContext(ctx, err)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -199,6 +199,7 @@ export interface ITenantMonitoringStruct {
|
||||
prometheusEnabled: boolean;
|
||||
monitoringCPURequest: string;
|
||||
monitoringMemRequest: string;
|
||||
securityContext: ISecurityContext;
|
||||
}
|
||||
|
||||
export interface IKeyValue {
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
// 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 { ISecurityContext} from "../types";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
@@ -56,9 +55,13 @@ import {
|
||||
setServiceAccountName,
|
||||
setCPURequest,
|
||||
setMemRequest,
|
||||
setRunAsGroup,
|
||||
setFSGroup,
|
||||
setRunAsUser,
|
||||
setRunAsNonRoot,
|
||||
} from "../TenantDetails/tenantMonitoringSlice";
|
||||
|
||||
import { clearValidationError } from "../utils";
|
||||
import SecurityContextSelector from "../securityContextSelector";
|
||||
|
||||
interface ITenantMonitoring {
|
||||
classes: any;
|
||||
@@ -135,6 +138,18 @@ const TenantMonitoring = ({ classes }: ITenantMonitoring) => {
|
||||
const [annotationsError, setAnnotationsError] = useState<any>({});
|
||||
const [nodeSelectorError, setNodeSelectorError] = useState<any>({});
|
||||
|
||||
const runAsGroup = useSelector(
|
||||
(state: AppState) => state.editTenantMonitoring.runAsGroup
|
||||
);
|
||||
const runAsUser = useSelector(
|
||||
(state: AppState) => state.editTenantMonitoring.runAsUser
|
||||
);
|
||||
const fsGroup = useSelector(
|
||||
(state: AppState) => state.editTenantMonitoring.fsGroup
|
||||
);
|
||||
const runAsNonRoot = useSelector(
|
||||
(state: AppState) => state.editTenantMonitoring.runAsNonRoot
|
||||
);
|
||||
const cleanValidation = (fieldName: string) => {
|
||||
setValidationErrors(clearValidationError(validationErrors, fieldName));
|
||||
};
|
||||
@@ -167,6 +182,10 @@ const TenantMonitoring = ({ classes }: ITenantMonitoring) => {
|
||||
res.nodeSelector != null
|
||||
? setNodeSelector(res.nodeSelector)
|
||||
: setNodeSelector([{ key: "", value: "" }]);
|
||||
dispatch(setRunAsGroup(res.securityContext.runAsGroup));
|
||||
dispatch(setRunAsUser(res.securityContext.runAsUser));
|
||||
dispatch(setRunAsNonRoot(res.securityContext.runAsNonRoot));
|
||||
dispatch(setFSGroup(res.securityContext.fsGroup));
|
||||
};
|
||||
|
||||
const trim = (x: IKeyValue[]): IKeyValue[] => {
|
||||
@@ -221,6 +240,12 @@ const TenantMonitoring = ({ classes }: ITenantMonitoring) => {
|
||||
|
||||
const submitMonitoringInfo = () => {
|
||||
if (checkValid()) {
|
||||
const securityContext = {
|
||||
runAsGroup: runAsGroup != null ? runAsGroup : "0",
|
||||
runAsUser: runAsUser != null ? runAsUser : "0",
|
||||
fsGroup: fsGroup != null ? fsGroup : "0",
|
||||
runAsNonRoot: runAsNonRoot != null ? runAsNonRoot : true,
|
||||
};
|
||||
api
|
||||
.invoke(
|
||||
"PUT",
|
||||
@@ -237,6 +262,7 @@ const TenantMonitoring = ({ classes }: ITenantMonitoring) => {
|
||||
storageClassName: storageClassName,
|
||||
monitoringCPURequest: cpuRequest,
|
||||
monitoringMemRequest: memRequest + "Gi",
|
||||
securityContext: securityContext,
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
@@ -312,7 +338,7 @@ const TenantMonitoring = ({ classes }: ITenantMonitoring) => {
|
||||
description=""
|
||||
/>
|
||||
</Grid>
|
||||
<Grid xs={12}>
|
||||
<Grid item xs={12}>
|
||||
<hr className={classes.hrClass} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
@@ -518,6 +544,21 @@ const TenantMonitoring = ({ classes }: ITenantMonitoring) => {
|
||||
/>
|
||||
</Grid>
|
||||
)}
|
||||
<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"
|
||||
|
||||
@@ -29,6 +29,10 @@ export interface IEditTenantMonitoring {
|
||||
serviceAccountName: string;
|
||||
monitoringCPURequest: string;
|
||||
monitoringMemRequest: string;
|
||||
runAsUser: string;
|
||||
runAsGroup: string;
|
||||
fsGroup: string;
|
||||
runAsNonRoot: boolean;
|
||||
}
|
||||
|
||||
const initialState: IEditTenantMonitoring = {
|
||||
@@ -44,6 +48,10 @@ const initialState: IEditTenantMonitoring = {
|
||||
serviceAccountName: "",
|
||||
monitoringCPURequest: "",
|
||||
monitoringMemRequest: "",
|
||||
runAsUser: "1000",
|
||||
runAsGroup: "1000",
|
||||
fsGroup: "1000",
|
||||
runAsNonRoot: true,
|
||||
};
|
||||
|
||||
export const editTenantMonitoringSlice = createSlice({
|
||||
@@ -86,6 +94,18 @@ export const editTenantMonitoringSlice = createSlice({
|
||||
setMemRequest: (state, action: PayloadAction<string>) => {
|
||||
state.monitoringMemRequest = action.payload;
|
||||
},
|
||||
setRunAsUser: (state, action: PayloadAction<string>) => {
|
||||
state.runAsUser = action.payload;
|
||||
},
|
||||
setRunAsGroup: (state, action: PayloadAction<string>) => {
|
||||
state.runAsGroup = action.payload;
|
||||
},
|
||||
setFSGroup: (state, action: PayloadAction<string>) => {
|
||||
state.fsGroup = action.payload;
|
||||
},
|
||||
setRunAsNonRoot: (state, action: PayloadAction<boolean>) => {
|
||||
state.runAsNonRoot = action.payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -102,6 +122,10 @@ export const {
|
||||
setServiceAccountName,
|
||||
setCPURequest,
|
||||
setMemRequest,
|
||||
setRunAsUser,
|
||||
setRunAsGroup,
|
||||
setFSGroup,
|
||||
setRunAsNonRoot,
|
||||
} = editTenantMonitoringSlice.actions;
|
||||
|
||||
export default editTenantMonitoringSlice.reducer;
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
// 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 { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||
import { IEditMonitoringSecurityContext } from "./types";
|
||||
|
||||
const initialState: IEditMonitoringSecurityContext = {
|
||||
securityContextEnabled: false,
|
||||
runAsUser: "1000",
|
||||
runAsGroup: "1000",
|
||||
fsGroup: "1000",
|
||||
runAsNonRoot: true,
|
||||
};
|
||||
|
||||
export const editMonitoringSecurityContextSlice = createSlice({
|
||||
name: "editMonitoringSecurityContext",
|
||||
initialState,
|
||||
reducers: {
|
||||
setSecurityContextEnabled: (state, action: PayloadAction<boolean>) => {
|
||||
state.securityContextEnabled = action.payload;
|
||||
},
|
||||
setRunAsUser: (state, action: PayloadAction<string>) => {
|
||||
state.runAsUser = action.payload;
|
||||
},
|
||||
setRunAsGroup: (state, action: PayloadAction<string>) => {
|
||||
state.runAsGroup = action.payload;
|
||||
},
|
||||
setFSGroup: (state, action: PayloadAction<string>) => {
|
||||
state.fsGroup = action.payload;
|
||||
},
|
||||
setRunAsNonRoot: (state, action: PayloadAction<boolean>) => {
|
||||
state.runAsNonRoot = action.payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const {
|
||||
setSecurityContextEnabled,
|
||||
setRunAsUser,
|
||||
setRunAsGroup,
|
||||
setFSGroup,
|
||||
setRunAsNonRoot,
|
||||
} = editMonitoringSecurityContextSlice.actions;
|
||||
|
||||
export default editMonitoringSecurityContextSlice.reducer;
|
||||
@@ -338,3 +338,11 @@ export interface ITenantIdentityProviderResponse {
|
||||
user_dn_search_filter: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface IEditMonitoringSecurityContext {
|
||||
securityContextEnabled: boolean;
|
||||
runAsUser: string;
|
||||
runAsGroup: string;
|
||||
fsGroup: string;
|
||||
runAsNonRoot: boolean;
|
||||
}
|
||||
|
||||
@@ -3272,6 +3272,9 @@ definitions:
|
||||
type: string
|
||||
monitoringMemRequest:
|
||||
type: string
|
||||
securityContext:
|
||||
type: object
|
||||
$ref: "#/definitions/securityContext"
|
||||
|
||||
label:
|
||||
type: object
|
||||
|
||||
Reference in New Issue
Block a user