From cce054bbe8b6db93c58ae64a23ee3288f5497547 Mon Sep 17 00:00:00 2001
From: jinapurapu <65002498+jinapurapu@users.noreply.github.com>
Date: Thu, 7 Jul 2022 12:52:30 -0700
Subject: [PATCH] Create security context component and add to edit Prometheus
Monitoring (#2115)
---
models/tenant_monitoring_info.go | 46 +++++++++++++++
operatorapi/embedded_spec.go | 8 +++
operatorapi/tenants.go | 13 +++--
.../Console/Tenants/ListTenants/types.ts | 1 +
.../EditTenantMonitoringScreen.tsx | 47 ++++++++++++++-
.../TenantDetails/tenantMonitoringSlice.ts | 24 ++++++++
.../Tenants/monitoringSecurityContextSlice.ts | 57 +++++++++++++++++++
.../src/screens/Console/Tenants/types.ts | 8 +++
swagger-operator.yml | 3 +
9 files changed, 200 insertions(+), 7 deletions(-)
create mode 100644 portal-ui/src/screens/Console/Tenants/monitoringSecurityContextSlice.ts
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))
+ }
+ />
+