diff --git a/models/tenant_monitoring_info.go b/models/tenant_monitoring_info.go index 4e9d4fe35..b3770458a 100644 --- a/models/tenant_monitoring_info.go +++ b/models/tenant_monitoring_info.go @@ -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 { diff --git a/operatorapi/embedded_spec.go b/operatorapi/embedded_spec.go index dd7278418..bf28e0028 100644 --- a/operatorapi/embedded_spec.go +++ b/operatorapi/embedded_spec.go @@ -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" }, diff --git a/operatorapi/tenants.go b/operatorapi/tenants.go index 0971acb79..659944656 100644 --- a/operatorapi/tenants.go +++ b/operatorapi/tenants.go @@ -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 } diff --git a/portal-ui/src/screens/Console/Tenants/ListTenants/types.ts b/portal-ui/src/screens/Console/Tenants/ListTenants/types.ts index 94cc6d7b9..8012de4fc 100644 --- a/portal-ui/src/screens/Console/Tenants/ListTenants/types.ts +++ b/portal-ui/src/screens/Console/Tenants/ListTenants/types.ts @@ -199,6 +199,7 @@ export interface ITenantMonitoringStruct { prometheusEnabled: boolean; monitoringCPURequest: string; monitoringMemRequest: string; + securityContext: ISecurityContext; } export interface IKeyValue { diff --git a/portal-ui/src/screens/Console/Tenants/TenantDetails/EditTenantMonitoringScreen.tsx b/portal-ui/src/screens/Console/Tenants/TenantDetails/EditTenantMonitoringScreen.tsx index 9d17d2012..f767bb4b5 100644 --- a/portal-ui/src/screens/Console/Tenants/TenantDetails/EditTenantMonitoringScreen.tsx +++ b/portal-ui/src/screens/Console/Tenants/TenantDetails/EditTenantMonitoringScreen.tsx @@ -14,7 +14,6 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -//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({}); const [nodeSelectorError, setNodeSelectorError] = useState({}); + 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="" /> - +
@@ -518,6 +544,21 @@ const TenantMonitoring = ({ classes }: ITenantMonitoring) => { /> )} + + dispatch(setFSGroup(value))} + setRunAsUser={(value: string) => dispatch(setRunAsUser(value))} + setRunAsGroup={(value: string) => dispatch(setRunAsGroup(value))} + setRunAsNonRoot={(value: boolean) => + dispatch(setRunAsNonRoot(value)) + } + /> +