Create security context component and add to edit Prometheus Monitoring (#2115)

This commit is contained in:
jinapurapu
2022-07-07 12:52:30 -07:00
committed by GitHub
parent cf0e326b82
commit cce054bbe8
9 changed files with 200 additions and 7 deletions

View File

@@ -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 {

View File

@@ -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"
},

View File

@@ -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
}

View File

@@ -199,6 +199,7 @@ export interface ITenantMonitoringStruct {
prometheusEnabled: boolean;
monitoringCPURequest: string;
monitoringMemRequest: string;
securityContext: ISecurityContext;
}
export interface IKeyValue {

View File

@@ -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"

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -3272,6 +3272,9 @@ definitions:
type: string
monitoringMemRequest:
type: string
securityContext:
type: object
$ref: "#/definitions/securityContext"
label:
type: object