Operator-UI security context configuration (#1089)

- fix: check all pages are valid in  Add tenant wizard before enabling
  Create button
- Added: security context menu configuration for MinIO, logsearch api,
  postgres, prometheus and KES

Signed-off-by: Lenin Alevski <alevsk.8772@gmail.com>
This commit is contained in:
Lenin Alevski
2021-10-19 09:42:36 -07:00
committed by GitHub
parent ccebc17f3f
commit ff433549b6
16 changed files with 1162 additions and 43 deletions

View File

@@ -57,6 +57,9 @@ type EncryptionConfiguration struct {
// replicas
Replicas string `json:"replicas,omitempty"`
// security context
SecurityContext *SecurityContext `json:"securityContext,omitempty"`
// server
Server *KeyPairConfiguration `json:"server,omitempty"`
@@ -89,6 +92,8 @@ func (m *EncryptionConfiguration) UnmarshalJSON(raw []byte) error {
Replicas string `json:"replicas,omitempty"`
SecurityContext *SecurityContext `json:"securityContext,omitempty"`
Server *KeyPairConfiguration `json:"server,omitempty"`
Vault *VaultConfiguration `json:"vault,omitempty"`
@@ -111,6 +116,8 @@ func (m *EncryptionConfiguration) UnmarshalJSON(raw []byte) error {
m.Replicas = dataAO1.Replicas
m.SecurityContext = dataAO1.SecurityContext
m.Server = dataAO1.Server
m.Vault = dataAO1.Vault
@@ -142,6 +149,8 @@ func (m EncryptionConfiguration) MarshalJSON() ([]byte, error) {
Replicas string `json:"replicas,omitempty"`
SecurityContext *SecurityContext `json:"securityContext,omitempty"`
Server *KeyPairConfiguration `json:"server,omitempty"`
Vault *VaultConfiguration `json:"vault,omitempty"`
@@ -161,6 +170,8 @@ func (m EncryptionConfiguration) MarshalJSON() ([]byte, error) {
dataAO1.Replicas = m.Replicas
dataAO1.SecurityContext = m.SecurityContext
dataAO1.Server = m.Server
dataAO1.Vault = m.Vault
@@ -202,6 +213,10 @@ func (m *EncryptionConfiguration) Validate(formats strfmt.Registry) error {
res = append(res, err)
}
if err := m.validateSecurityContext(formats); err != nil {
res = append(res, err)
}
if err := m.validateServer(formats); err != nil {
res = append(res, err)
}
@@ -306,6 +321,24 @@ func (m *EncryptionConfiguration) validateGemalto(formats strfmt.Registry) error
return nil
}
func (m *EncryptionConfiguration) 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")
}
return err
}
}
return nil
}
func (m *EncryptionConfiguration) validateServer(formats strfmt.Registry) error {
if swag.IsZero(m.Server) { // not required
@@ -371,6 +404,10 @@ func (m *EncryptionConfiguration) ContextValidate(ctx context.Context, formats s
res = append(res, err)
}
if err := m.contextValidateSecurityContext(ctx, formats); err != nil {
res = append(res, err)
}
if err := m.contextValidateServer(ctx, formats); err != nil {
res = append(res, err)
}
@@ -455,6 +492,20 @@ func (m *EncryptionConfiguration) contextValidateGemalto(ctx context.Context, fo
return nil
}
func (m *EncryptionConfiguration) 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")
}
return err
}
}
return nil
}
func (m *EncryptionConfiguration) contextValidateServer(ctx context.Context, formats strfmt.Registry) error {
if m.Server != nil {

View File

@@ -25,6 +25,7 @@ package models
import (
"context"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
@@ -43,6 +44,12 @@ type LogSearchConfiguration struct {
// postgres init image
PostgresInitImage string `json:"postgres_init_image,omitempty"`
// postgres security context
PostgresSecurityContext *SecurityContext `json:"postgres_securityContext,omitempty"`
// security context
SecurityContext *SecurityContext `json:"securityContext,omitempty"`
// storage class
StorageClass string `json:"storageClass,omitempty"`
@@ -52,11 +59,99 @@ type LogSearchConfiguration struct {
// Validate validates this log search configuration
func (m *LogSearchConfiguration) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validatePostgresSecurityContext(formats); err != nil {
res = append(res, err)
}
if err := m.validateSecurityContext(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
// ContextValidate validates this log search configuration based on context it is used
func (m *LogSearchConfiguration) validatePostgresSecurityContext(formats strfmt.Registry) error {
if swag.IsZero(m.PostgresSecurityContext) { // not required
return nil
}
if m.PostgresSecurityContext != nil {
if err := m.PostgresSecurityContext.Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("postgres_securityContext")
}
return err
}
}
return nil
}
func (m *LogSearchConfiguration) 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")
}
return err
}
}
return nil
}
// ContextValidate validate this log search configuration based on the context it is used
func (m *LogSearchConfiguration) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
var res []error
if err := m.contextValidatePostgresSecurityContext(ctx, formats); err != nil {
res = append(res, err)
}
if err := m.contextValidateSecurityContext(ctx, formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *LogSearchConfiguration) contextValidatePostgresSecurityContext(ctx context.Context, formats strfmt.Registry) error {
if m.PostgresSecurityContext != nil {
if err := m.PostgresSecurityContext.ContextValidate(ctx, formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("postgres_securityContext")
}
return err
}
}
return nil
}
func (m *LogSearchConfiguration) 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")
}
return err
}
}
return nil
}

View File

@@ -48,6 +48,9 @@ type Pool struct {
// resources
Resources *PoolResources `json:"resources,omitempty"`
// security context
SecurityContext *SecurityContext `json:"securityContext,omitempty"`
// servers
// Required: true
Servers *int64 `json:"servers"`
@@ -76,6 +79,10 @@ func (m *Pool) Validate(formats strfmt.Registry) error {
res = append(res, err)
}
if err := m.validateSecurityContext(formats); err != nil {
res = append(res, err)
}
if err := m.validateServers(formats); err != nil {
res = append(res, err)
}
@@ -132,6 +139,23 @@ func (m *Pool) validateResources(formats strfmt.Registry) error {
return nil
}
func (m *Pool) 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")
}
return err
}
}
return nil
}
func (m *Pool) validateServers(formats strfmt.Registry) error {
if err := validate.Required("servers", "body", m.Servers); err != nil {
@@ -195,6 +219,10 @@ func (m *Pool) ContextValidate(ctx context.Context, formats strfmt.Registry) err
res = append(res, err)
}
if err := m.contextValidateSecurityContext(ctx, formats); err != nil {
res = append(res, err)
}
if err := m.contextValidateTolerations(ctx, formats); err != nil {
res = append(res, err)
}
@@ -237,6 +265,20 @@ func (m *Pool) contextValidateResources(ctx context.Context, formats strfmt.Regi
return nil
}
func (m *Pool) 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")
}
return err
}
}
return nil
}
func (m *Pool) contextValidateTolerations(ctx context.Context, formats strfmt.Registry) error {
if err := m.Tolerations.ContextValidate(ctx, formats); err != nil {

View File

@@ -38,11 +38,11 @@ type SecurityContext struct {
// fs group
// Required: true
FsGroup *int64 `json:"fsGroup"`
FsGroup *string `json:"fsGroup"`
// run as group
// Required: true
RunAsGroup *int64 `json:"runAsGroup"`
RunAsGroup *string `json:"runAsGroup"`
// run as non root
// Required: true
@@ -50,7 +50,7 @@ type SecurityContext struct {
// run as user
// Required: true
RunAsUser *int64 `json:"runAsUser"`
RunAsUser *string `json:"runAsUser"`
}
// Validate validates this security context

View File

@@ -1732,6 +1732,10 @@ func init() {
"replicas": {
"type": "string"
},
"securityContext": {
"type": "object",
"$ref": "#/definitions/securityContext"
},
"server": {
"type": "object",
"$ref": "#/definitions/keyPairConfiguration"
@@ -2136,6 +2140,14 @@ func init() {
"postgres_init_image": {
"type": "string"
},
"postgres_securityContext": {
"type": "object",
"$ref": "#/definitions/securityContext"
},
"securityContext": {
"type": "object",
"$ref": "#/definitions/securityContext"
},
"storageClass": {
"type": "string",
"default": ""
@@ -2445,6 +2457,10 @@ func init() {
"resources": {
"$ref": "#/definitions/poolResources"
},
"securityContext": {
"type": "object",
"$ref": "#/definitions/securityContext"
},
"servers": {
"type": "integer"
},
@@ -2778,19 +2794,16 @@ func init() {
],
"properties": {
"fsGroup": {
"type": "integer",
"format": "int64"
"type": "string"
},
"runAsGroup": {
"type": "integer",
"format": "int64"
"type": "string"
},
"runAsNonRoot": {
"type": "boolean"
},
"runAsUser": {
"type": "integer",
"format": "int64"
"type": "string"
}
}
},
@@ -5570,6 +5583,10 @@ func init() {
"replicas": {
"type": "string"
},
"securityContext": {
"type": "object",
"$ref": "#/definitions/securityContext"
},
"server": {
"type": "object",
"$ref": "#/definitions/keyPairConfiguration"
@@ -5962,6 +5979,14 @@ func init() {
"postgres_init_image": {
"type": "string"
},
"postgres_securityContext": {
"type": "object",
"$ref": "#/definitions/securityContext"
},
"securityContext": {
"type": "object",
"$ref": "#/definitions/securityContext"
},
"storageClass": {
"type": "string",
"default": ""
@@ -6205,6 +6230,10 @@ func init() {
"resources": {
"$ref": "#/definitions/poolResources"
},
"securityContext": {
"type": "object",
"$ref": "#/definitions/securityContext"
},
"servers": {
"type": "integer"
},
@@ -6469,19 +6498,16 @@ func init() {
],
"properties": {
"fsGroup": {
"type": "integer",
"format": "int64"
"type": "string"
},
"runAsGroup": {
"type": "integer",
"format": "int64"
"type": "string"
},
"runAsNonRoot": {
"type": "boolean"
},
"runAsUser": {
"type": "integer",
"format": "int64"
"type": "string"
}
}
},

View File

@@ -1147,6 +1147,14 @@ func getTenantCreatedResponse(session *models.Principal, params operator_api.Cre
minInst.Spec.KES.Labels = tenantReq.Encryption.Labels
minInst.Spec.KES.Annotations = tenantReq.Encryption.Annotations
minInst.Spec.KES.NodeSelector = tenantReq.Encryption.NodeSelector
if tenantReq.Encryption.SecurityContext != nil {
sc, err := parseSecurityContext(tenantReq.Encryption.SecurityContext)
if err != nil {
return nil, prepareError(err)
}
minInst.Spec.KES.SecurityContext = sc
}
}
// External TLS CA certificates for MinIO
if tenantReq.TLS != nil && len(tenantReq.TLS.CaCertificates) > 0 {
@@ -1229,6 +1237,8 @@ func getTenantCreatedResponse(session *models.Principal, params operator_api.Cre
logSearchImage := ""
logSearchPgImage := ""
logSearchPgInitImage := ""
var logSearchSecurityContext *corev1.PodSecurityContext
var logSearchPgSecurityContext *corev1.PodSecurityContext
if tenantReq.LogSearchConfiguration != nil {
if tenantReq.LogSearchConfiguration.StorageSize != nil {
@@ -1249,6 +1259,22 @@ func getTenantCreatedResponse(session *models.Principal, params operator_api.Cre
if tenantReq.LogSearchConfiguration.PostgresInitImage != "" {
logSearchPgInitImage = tenantReq.LogSearchConfiguration.PostgresInitImage
}
// if security context for logSearch is present, configure it.
if tenantReq.LogSearchConfiguration.SecurityContext != nil {
sc, err := parseSecurityContext(tenantReq.LogSearchConfiguration.SecurityContext)
if err != nil {
return nil, prepareError(err)
}
logSearchSecurityContext = sc
}
// if security context for logSearch is present, configure it.
if tenantReq.LogSearchConfiguration.PostgresSecurityContext != nil {
sc, err := parseSecurityContext(tenantReq.LogSearchConfiguration.PostgresSecurityContext)
if err != nil {
return nil, prepareError(err)
}
logSearchPgSecurityContext = sc
}
}
logSearchDiskSpace := resource.NewQuantity(diskSpaceFromAPI, resource.DecimalExponent)
@@ -1290,6 +1316,12 @@ func getTenantCreatedResponse(session *models.Principal, params operator_api.Cre
if logSearchPgInitImage != "" {
minInst.Spec.Log.Db.InitImage = logSearchPgInitImage
}
if logSearchSecurityContext != nil {
minInst.Spec.Log.SecurityContext = logSearchSecurityContext
}
if logSearchPgSecurityContext != nil {
minInst.Spec.Log.Db.SecurityContext = logSearchPgSecurityContext
}
prometheusDiskSpace := 5 // Default is 5 by API
prometheusStorageClass := "" // Default is ""
@@ -1336,13 +1368,11 @@ func getTenantCreatedResponse(session *models.Principal, params operator_api.Cre
}
// if security context for prometheus is present, configure it.
if tenantReq.PrometheusConfiguration != nil && tenantReq.PrometheusConfiguration.SecurityContext != nil {
sc := tenantReq.PrometheusConfiguration.SecurityContext
minInst.Spec.Prometheus.SecurityContext = &corev1.PodSecurityContext{
RunAsUser: sc.RunAsUser,
RunAsGroup: sc.RunAsGroup,
RunAsNonRoot: sc.RunAsNonRoot,
FSGroup: sc.FsGroup,
sc, err := parseSecurityContext(tenantReq.PrometheusConfiguration.SecurityContext)
if err != nil {
return nil, prepareError(err)
}
minInst.Spec.Prometheus.SecurityContext = sc
}
// expose services
@@ -1912,6 +1942,14 @@ func parseTenantPoolRequest(poolParams *models.Pool) (*miniov2.Pool, error) {
Affinity: affinity,
Tolerations: tolerations,
}
// if security context for Tenant is present, configure it.
if poolParams.SecurityContext != nil {
sc, err := parseSecurityContext(poolParams.SecurityContext)
if err != nil {
return nil, err
}
pool.SecurityContext = sc
}
return pool, nil
}

View File

@@ -38,6 +38,31 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// parseSecurityContext validate and return securityContext for pods
func parseSecurityContext(sc *models.SecurityContext) (*corev1.PodSecurityContext, error) {
if sc == nil {
return nil, errors.New("invalid security context")
}
runAsUser, err := strconv.ParseInt(*sc.RunAsUser, 10, 64)
if err != nil {
return nil, err
}
RunAsGroup, err := strconv.ParseInt(*sc.RunAsGroup, 10, 64)
if err != nil {
return nil, err
}
FsGroup, err := strconv.ParseInt(*sc.FsGroup, 10, 64)
if err != nil {
return nil, err
}
return &corev1.PodSecurityContext{
RunAsUser: &runAsUser,
RunAsGroup: &RunAsGroup,
RunAsNonRoot: sc.RunAsNonRoot,
FSGroup: &FsGroup,
}, nil
}
// tenantUpdateCertificates receives the keyPair certificates (public and private keys) for Minio and Console and will try
// to replace the existing kubernetes secrets with the new values, then will restart the affected pods so the new volumes can be mounted
func tenantUpdateCertificates(ctx context.Context, operatorClient OperatorClientI, clientSet K8sClientI, namespace string, params operator_api.TenantUpdateCertificateParams) error {

View File

@@ -14,7 +14,10 @@
// 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 { ILabelKeyPair } from "../screens/Console/Tenants/types";
import {
ILabelKeyPair,
ISecurityContext,
} from "../screens/Console/Tenants/types";
export interface ITenantsObject {
tenants: ITenant[];
@@ -323,6 +326,7 @@ export interface IPoolModel {
affinity?: IAffinityModel;
tolerations?: ITolerationModel[];
resources?: IResourceModel;
securityContext?: ISecurityContext | null;
}
export interface IUpdatePool {
@@ -370,6 +374,8 @@ export interface LogSearchConfiguration {
image: string;
postgres_image: string;
postgres_init_image: string;
securityContext?: ISecurityContext;
postgres_securityContext?: ISecurityContext;
}
export interface PrometheusConfiguration {
@@ -378,6 +384,7 @@ export interface PrometheusConfiguration {
image: string;
sidecar_image: string;
init_image: string;
securityContext?: ISecurityContext;
}
export interface AffinityConfiguration {

View File

@@ -39,7 +39,7 @@ import { getDefaultAffinity, getNodeSelector } from "../TenantDetails/utils";
import CredentialsPrompt from "../../Common/CredentialsPrompt/CredentialsPrompt";
import NameTenant from "./Steps/NameTenant";
import { AppState } from "../../../../store";
import { ICertificatesItems, IFieldStore } from "../types";
import { ICertificatesItems, IFieldStore, ISecurityContext } from "../types";
import { resetAddTenantForm, updateAddField } from "../actions";
import Configure from "./Steps/Configure";
import IdentityProvider from "./Steps/IdentityProvider";
@@ -172,6 +172,7 @@ const AddTenant = ({
const ecParity = fields.tenantSize.ecParity;
const distribution = fields.tenantSize.distribution;
const memorySize = fields.tenantSize.memorySize;
const tenantCustom = fields.configure.tenantCustom;
const logSearchCustom = fields.configure.logSearchCustom;
const prometheusCustom = fields.configure.prometheusCustom;
const logSearchVolumeSize = fields.configure.logSearchVolumeSize;
@@ -192,6 +193,15 @@ const AddTenant = ({
const nodeSelectorLabels = fields.affinity.nodeSelectorLabels;
const withPodAntiAffinity = fields.affinity.withPodAntiAffinity;
const tenantSecurityContext = fields.configure.tenantSecurityContext;
const logSearchSecurityContext = fields.configure.logSearchSecurityContext;
const logSearchPostgresSecurityContext =
fields.configure.logSearchPostgresSecurityContext;
const prometheusSecurityContext =
fields.configure.prometheusSecurityContext;
const kesSecurityContext = fields.encryption.kesSecurityContext;
const kesReplicas = fields.encryption.replicas;
if (addSending) {
const poolName = generatePoolName([]);
@@ -248,6 +258,7 @@ const AddTenant = ({
memory: memorySize.limit,
},
},
securityContext: tenantCustom ? tenantSecurityContext : null,
...affinityObject,
},
],
@@ -274,6 +285,8 @@ const AddTenant = ({
image: logSearchImage,
postgres_image: logSearchPostgresImage,
postgres_init_image: logSearchPostgresInitImage,
securityContext: logSearchSecurityContext,
postgres_securityContext: logSearchPostgresSecurityContext,
},
};
} else {
@@ -296,6 +309,7 @@ const AddTenant = ({
image: prometheusImage,
sidecar_image: prometheusSidecarImage,
init_image: prometheusInitImage,
securityContext: prometheusSecurityContext,
},
};
} else {
@@ -517,6 +531,8 @@ const AddTenant = ({
dataSend = {
...dataSend,
encryption: {
replicas: kesReplicas,
securityContext: kesSecurityContext,
image: kesImage,
...encryptionClientKeyPair,
...encryptionServerKeyPair,
@@ -626,14 +642,22 @@ const AddTenant = ({
history.push("/tenants");
},
};
const requiredPages = [
"nameTenant",
"tenantSize",
"configure",
"affinity",
"identityProvider",
"security",
"encryption",
];
const createButton = {
label: "Create",
type: "submit",
enabled:
!addSending &&
selectedStorageClass !== "" &&
validPages.includes("tenantSize"),
requiredPages.every((v) => validPages.includes(v)),
action: () => {
setAddSending(true);
},

View File

@@ -135,9 +135,6 @@ const Affinity = ({
.map((kvp) => `${kvp.key}=${kvp.value}`)
.filter((kvs, i, a) => a.indexOf(kvs) === i);
const vl = vlr.join("&");
console.log(vl);
updateField("nodeSelectorLabels", vl);
}
}, [keyValuePairs, updateField]);

View File

@@ -32,6 +32,7 @@ import {
import FormSwitchWrapper from "../../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper";
import InputBoxWrapper from "../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
import SelectWrapper from "../../../Common/FormComponents/SelectWrapper/SelectWrapper";
import { ISecurityContext } from "../../types";
interface IConfigureProps {
updateAddField: typeof updateAddField;
@@ -47,6 +48,7 @@ interface IConfigureProps {
exposeMinIO: boolean;
exposeConsole: boolean;
prometheusCustom: boolean;
tenantCustom: boolean;
logSearchCustom: boolean;
logSearchVolumeSize: string;
logSearchSizeFactor: string;
@@ -62,6 +64,10 @@ interface IConfigureProps {
prometheusSidecarImage: string;
prometheusInitImage: string;
selectedStorageClass: string;
tenantSecurityContext: ISecurityContext;
logSearchSecurityContext: ISecurityContext;
logSearchPostgresSecurityContext: ISecurityContext;
prometheusSecurityContext: ISecurityContext;
}
const styles = (theme: Theme) =>
@@ -85,6 +91,7 @@ const Configure = ({
exposeMinIO,
exposeConsole,
prometheusCustom,
tenantCustom,
logSearchCustom,
logSearchVolumeSize,
logSearchSizeFactor,
@@ -102,6 +109,10 @@ const Configure = ({
updateAddField,
isPageValid,
selectedStorageClass,
tenantSecurityContext,
logSearchSecurityContext,
logSearchPostgresSecurityContext,
prometheusSecurityContext,
}: IConfigureProps) => {
const [validationErrors, setValidationErrors] = useState<any>({});
@@ -116,7 +127,38 @@ const Configure = ({
// Validation
useEffect(() => {
let customAccountValidation: IValidation[] = [];
if (tenantCustom) {
customAccountValidation = [
...customAccountValidation,
{
fieldKey: "tenant_securityContext_runAsUser",
required: true,
value: tenantSecurityContext.runAsUser,
customValidation:
tenantSecurityContext.runAsUser === "" ||
parseInt(tenantSecurityContext.runAsUser) < 0,
customValidationMessage: `runAsUser must be present and be 0 or more`,
},
{
fieldKey: "tenant_securityContext_runAsGroup",
required: true,
value: tenantSecurityContext.runAsGroup,
customValidation:
tenantSecurityContext.runAsGroup === "" ||
parseInt(tenantSecurityContext.runAsGroup) < 0,
customValidationMessage: `runAsGroup must be present and be 0 or more`,
},
{
fieldKey: "tenant_securityContext_fsGroup",
required: true,
value: tenantSecurityContext.fsGroup,
customValidation:
tenantSecurityContext.fsGroup === "" ||
parseInt(tenantSecurityContext.fsGroup) < 0,
customValidationMessage: `fsGroup must be present and be 0 or more`,
},
];
}
if (prometheusCustom) {
customAccountValidation = [
...customAccountValidation,
@@ -133,7 +175,34 @@ const Configure = ({
value: prometheusVolumeSize,
customValidation:
prometheusVolumeSize === "" || parseInt(prometheusVolumeSize) <= 0,
customValidationMessage: `Volume size must be present and be greatter than 0`,
customValidationMessage: `Volume size must be present and be greater than 0`,
},
{
fieldKey: "prometheus_securityContext_runAsUser",
required: true,
value: prometheusSecurityContext.runAsUser,
customValidation:
prometheusSecurityContext.runAsUser === "" ||
parseInt(prometheusSecurityContext.runAsUser) < 0,
customValidationMessage: `runAsUser must be present and be 0 or more`,
},
{
fieldKey: "prometheus_securityContext_runAsGroup",
required: true,
value: prometheusSecurityContext.runAsGroup,
customValidation:
prometheusSecurityContext.runAsGroup === "" ||
parseInt(prometheusSecurityContext.runAsGroup) < 0,
customValidationMessage: `runAsGroup must be present and be 0 or more`,
},
{
fieldKey: "prometheus_securityContext_fsGroup",
required: true,
value: prometheusSecurityContext.fsGroup,
customValidation:
prometheusSecurityContext.fsGroup === "" ||
parseInt(prometheusSecurityContext.fsGroup) < 0,
customValidationMessage: `fsGroup must be present and be 0 or more`,
},
];
}
@@ -155,6 +224,60 @@ const Configure = ({
logSearchVolumeSize === "" || parseInt(logSearchVolumeSize) <= 0,
customValidationMessage: `Volume size must be present and be greatter than 0`,
},
{
fieldKey: "logSearch_securityContext_runAsUser",
required: true,
value: logSearchSecurityContext.runAsUser,
customValidation:
logSearchSecurityContext.runAsUser === "" ||
parseInt(logSearchSecurityContext.runAsUser) < 0,
customValidationMessage: `runAsUser must be present and be 0 or more`,
},
{
fieldKey: "logSearch_securityContext_runAsGroup",
required: true,
value: logSearchSecurityContext.runAsGroup,
customValidation:
logSearchSecurityContext.runAsGroup === "" ||
parseInt(logSearchSecurityContext.runAsGroup) < 0,
customValidationMessage: `runAsGroup must be present and be 0 or more`,
},
{
fieldKey: "logSearch_securityContext_fsGroup",
required: true,
value: logSearchSecurityContext.fsGroup,
customValidation:
logSearchSecurityContext.fsGroup === "" ||
parseInt(logSearchSecurityContext.fsGroup) < 0,
customValidationMessage: `fsGroup must be present and be 0 or more`,
},
{
fieldKey: "postgres_securityContext_runAsUser",
required: true,
value: logSearchPostgresSecurityContext.runAsUser,
customValidation:
logSearchPostgresSecurityContext.runAsUser === "" ||
parseInt(logSearchPostgresSecurityContext.runAsUser) < 0,
customValidationMessage: `runAsUser must be present and be 0 or more`,
},
{
fieldKey: "postgres_securityContext_runAsGroup",
required: true,
value: prometheusSecurityContext.runAsGroup,
customValidation:
logSearchPostgresSecurityContext.runAsGroup === "" ||
parseInt(logSearchPostgresSecurityContext.runAsGroup) < 0,
customValidationMessage: `runAsGroup must be present and be 0 or more`,
},
{
fieldKey: "postgres_securityContext_fsGroup",
required: true,
value: logSearchPostgresSecurityContext.fsGroup,
customValidation:
logSearchPostgresSecurityContext.fsGroup === "" ||
parseInt(logSearchPostgresSecurityContext.fsGroup) < 0,
customValidationMessage: `fsGroup must be present and be 0 or more`,
},
];
}
@@ -267,11 +390,16 @@ const Configure = ({
imageRegistryPassword,
isPageValid,
prometheusCustom,
tenantCustom,
logSearchCustom,
prometheusSelectedStorageClass,
prometheusVolumeSize,
logSearchSelectedStorageClass,
logSearchVolumeSize,
tenantSecurityContext,
logSearchSecurityContext,
logSearchPostgresSecurityContext,
prometheusSecurityContext,
]);
useEffect(() => {
@@ -351,10 +479,121 @@ const Configure = ({
<div className={classes.headerElement}>
<h3 className={classes.h3Section}>Additional Configurations</h3>
<span className={classes.descriptionText}>
Configure Storage Classes & Storage size for Log Search and Prometheus
add-ons
Configure SecurityContext, Storage Classes & Storage size for Log
Search, Prometheus add-ons and your Tenant
</span>
</div>
<Grid item xs={12}>
<FormSwitchWrapper
value="tenantConfig"
id="tenant_configuration"
name="tenant_configuration"
checked={tenantCustom}
onChange={(e) => {
const targetD = e.target;
const checked = targetD.checked;
updateField("tenantCustom", checked);
}}
label={"Override Tenant defaults"}
/>
</Grid>
{tenantCustom && (
<Fragment>
<span className={classes.descriptionText}>
SecurityContext for MinIO
</span>
<br />
<br />
<Grid item xs={12}>
<div className={classes.multiContainer}>
<div>
<InputBoxWrapper
type="number"
id="tenant_securityContext_runAsUser"
name="tenant_securityContext_runAsUser"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("tenantSecurityContext", {
...tenantSecurityContext,
runAsUser: e.target.value,
});
cleanValidation("tenant_securityContext_runAsUser");
}}
label="Run As User"
value={tenantSecurityContext.runAsUser}
required
error={
validationErrors["tenant_securityContext_runAsUser"] || ""
}
min="0"
/>
</div>
<div>
<InputBoxWrapper
type="number"
id="tenant_securityContext_runAsGroup"
name="tenant_securityContext_runAsGroup"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("tenantSecurityContext", {
...tenantSecurityContext,
runAsGroup: e.target.value,
});
cleanValidation("tenant_securityContext_runAsGroup");
}}
label="Run As Group"
value={tenantSecurityContext.runAsGroup}
required
error={
validationErrors["tenant_securityContext_runAsGroup"] || ""
}
min="0"
/>
</div>
<div>
<InputBoxWrapper
type="number"
id="tenant_securityContext_fsGroup"
name="tenant_securityContext_fsGroup"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("tenantSecurityContext", {
...tenantSecurityContext,
fsGroup: e.target.value,
});
cleanValidation("tenant_securityContext_fsGroup");
}}
label="FsGroup"
value={tenantSecurityContext.fsGroup}
required
error={
validationErrors["tenant_securityContext_fsGroup"] || ""
}
min="0"
/>
</div>
</div>
</Grid>
<br />
<Grid item xs={12}>
<div className={classes.multiContainer}>
<FormSwitchWrapper
value="tenantSecurityContextRunAsNonRoot"
id="tenant_securityContext_runAsNonRoot"
name="tenant_securityContext_runAsNonRoot"
checked={tenantSecurityContext.runAsNonRoot}
onChange={(e) => {
const targetD = e.target;
const checked = targetD.checked;
updateField("tenantSecurityContext", {
...tenantSecurityContext,
runAsNonRoot: checked,
});
}}
label={"Do not run as Root"}
/>
</div>
</Grid>
</Fragment>
)}
<Grid item xs={12}>
<FormSwitchWrapper
value="logSearchConfig"
@@ -408,7 +647,200 @@ const Configure = ({
</div>
</div>
</Grid>
<br />
<Fragment>
<span className={classes.descriptionText}>
SecurityContext for LogSearch
</span>
<br />
<br />
<Grid item xs={12}>
<div className={classes.multiContainer}>
<div>
<InputBoxWrapper
type="number"
id="logSearch_securityContext_runAsUser"
name="logSearch_securityContext_runAsUser"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("logSearchSecurityContext", {
...logSearchSecurityContext,
runAsUser: e.target.value,
});
cleanValidation("logSearch_securityContext_runAsUser");
}}
label="Run As User"
value={logSearchSecurityContext.runAsUser}
required
error={
validationErrors["logSearch_securityContext_runAsUser"] ||
""
}
min="0"
/>
</div>
<div>
<InputBoxWrapper
type="number"
id="logSearch_securityContext_runAsGroup"
name="logSearch_securityContext_runAsGroup"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("logSearchSecurityContext", {
...logSearchSecurityContext,
runAsGroup: e.target.value,
});
cleanValidation("logSearch_securityContext_runAsGroup");
}}
label="Run As Group"
value={logSearchSecurityContext.runAsGroup}
required
error={
validationErrors[
"logSearch_securityContext_runAsGroup"
] || ""
}
min="0"
/>
</div>
<div>
<InputBoxWrapper
type="number"
id="logSearch_securityContext_fsGroup"
name="logSearch_securityContext_fsGroup"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("logSearchSecurityContext", {
...logSearchSecurityContext,
fsGroup: e.target.value,
});
cleanValidation("logSearch_securityContext_fsGroup");
}}
label="FsGroup"
value={logSearchSecurityContext.fsGroup}
required
error={
validationErrors["logSearch_securityContext_fsGroup"] ||
""
}
min="0"
/>
</div>
</div>
</Grid>
<br />
<Grid item xs={12}>
<div className={classes.multiContainer}>
<FormSwitchWrapper
value="logSearchSecurityContextRunAsNonRoot"
id="logSearch_securityContext_runAsNonRoot"
name="logSearch_securityContext_runAsNonRoot"
checked={logSearchSecurityContext.runAsNonRoot}
onChange={(e) => {
const targetD = e.target;
const checked = targetD.checked;
updateField("logSearchSecurityContext", {
...logSearchSecurityContext,
runAsNonRoot: checked,
});
}}
label={"Do not run as Root"}
/>
</div>
</Grid>
</Fragment>
<Fragment>
<span className={classes.descriptionText}>
SecurityContext for PostgreSQL
</span>
<br />
<br />
<Grid item xs={12}>
<div className={classes.multiContainer}>
<div>
<InputBoxWrapper
type="number"
id="postgres_securityContext_runAsUser"
name="postgres_securityContext_runAsUser"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("logSearchPostgresSecurityContext", {
...logSearchPostgresSecurityContext,
runAsUser: e.target.value,
});
cleanValidation("postgres_securityContext_runAsUser");
}}
label="Run As User"
value={logSearchPostgresSecurityContext.runAsUser}
required
error={
validationErrors["postgres_securityContext_runAsUser"] ||
""
}
min="0"
/>
</div>
<div>
<InputBoxWrapper
type="number"
id="postgres_securityContext_runAsGroup"
name="postgres_securityContext_runAsGroup"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("logSearchPostgresSecurityContext", {
...logSearchPostgresSecurityContext,
runAsGroup: e.target.value,
});
cleanValidation("postgres_securityContext_runAsGroup");
}}
label="Run As Group"
value={logSearchPostgresSecurityContext.runAsGroup}
required
error={
validationErrors["postgres_securityContext_runAsGroup"] ||
""
}
min="0"
/>
</div>
<div>
<InputBoxWrapper
type="number"
id="postgres_securityContext_fsGroup"
name="postgres_securityContext_fsGroup"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("logSearchPostgresSecurityContext", {
...logSearchPostgresSecurityContext,
fsGroup: e.target.value,
});
cleanValidation("postgres_securityContext_fsGroup");
}}
label="FsGroup"
value={logSearchPostgresSecurityContext.fsGroup}
required
error={
validationErrors["postgres_securityContext_fsGroup"] || ""
}
min="0"
/>
</div>
</div>
</Grid>
<br />
<Grid item xs={12}>
<div className={classes.multiContainer}>
<FormSwitchWrapper
value="postgresSecurityContextRunAsNonRoot"
id="postgres_securityContext_runAsNonRoot"
name="postgres_securityContext_runAsNonRoot"
checked={logSearchPostgresSecurityContext.runAsNonRoot}
onChange={(e) => {
const targetD = e.target;
const checked = targetD.checked;
updateField("logSearchPostgresSecurityContext", {
...logSearchPostgresSecurityContext,
runAsNonRoot: checked,
});
}}
label={"Do not run as Root"}
/>
</div>
</Grid>
</Fragment>
</Fragment>
)}
<Grid item xs={12}>
@@ -464,7 +896,105 @@ const Configure = ({
</div>
</div>
</Grid>
<br />
<Fragment>
<span className={classes.descriptionText}>
SecurityContext for Prometheus
</span>
<br />
<br />
<Grid item xs={12}>
<div className={classes.multiContainer}>
<div>
<InputBoxWrapper
type="number"
id="prometheus_securityContext_runAsUser"
name="prometheus_securityContext_runAsUser"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("prometheusSecurityContext", {
...prometheusSecurityContext,
runAsUser: e.target.value,
});
cleanValidation("prometheus_securityContext_runAsUser");
}}
label="Run As User"
value={prometheusSecurityContext.runAsUser}
required
error={
validationErrors[
"prometheus_securityContext_runAsUser"
] || ""
}
min="0"
/>
</div>
<div>
<InputBoxWrapper
type="number"
id="prometheus_securityContext_runAsGroup"
name="prometheus_securityContext_runAsGroup"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("prometheusSecurityContext", {
...prometheusSecurityContext,
runAsGroup: e.target.value,
});
cleanValidation("prometheus_securityContext_runAsGroup");
}}
label="Run As Group"
value={prometheusSecurityContext.runAsGroup}
required
error={
validationErrors[
"prometheus_securityContext_runAsGroup"
] || ""
}
min="0"
/>
</div>
<div>
<InputBoxWrapper
type="number"
id="prometheus_securityContext_fsGroup"
name="prometheus_securityContext_fsGroup"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("prometheusSecurityContext", {
...prometheusSecurityContext,
fsGroup: e.target.value,
});
cleanValidation("prometheus_securityContext_fsGroup");
}}
label="FsGroup"
value={prometheusSecurityContext.fsGroup}
required
error={
validationErrors["prometheus_securityContext_fsGroup"] ||
""
}
min="0"
/>
</div>
</div>
</Grid>
<br />
<Grid item xs={12}>
<div className={classes.multiContainer}>
<FormSwitchWrapper
value="prometheusSecurityContextRunAsNonRoot"
id="prometheus_securityContext_runAsNonRoot"
name="prometheus_securityContext_runAsNonRoot"
checked={prometheusSecurityContext.runAsNonRoot}
onChange={(e) => {
const targetD = e.target;
const checked = targetD.checked;
updateField("prometheusSecurityContext", {
...prometheusSecurityContext,
runAsNonRoot: checked,
});
}}
label={"Do not run as Root"}
/>
</div>
</Grid>
</Fragment>
</Fragment>
)}
</Paper>
@@ -485,6 +1015,7 @@ const mapState = (state: AppState) => ({
exposeConsole: state.tenants.createTenant.fields.configure.exposeConsole,
prometheusCustom:
state.tenants.createTenant.fields.configure.prometheusCustom,
tenantCustom: state.tenants.createTenant.fields.configure.tenantCustom,
logSearchCustom: state.tenants.createTenant.fields.configure.logSearchCustom,
logSearchVolumeSize:
state.tenants.createTenant.fields.configure.logSearchVolumeSize,
@@ -511,6 +1042,15 @@ const mapState = (state: AppState) => ({
state.tenants.createTenant.fields.configure.prometheusInitImage,
selectedStorageClass:
state.tenants.createTenant.fields.nameTenant.selectedStorageClass,
tenantSecurityContext:
state.tenants.createTenant.fields.configure.tenantSecurityContext,
logSearchSecurityContext:
state.tenants.createTenant.fields.configure.logSearchSecurityContext,
logSearchPostgresSecurityContext:
state.tenants.createTenant.fields.configure
.logSearchPostgresSecurityContext,
prometheusSecurityContext:
state.tenants.createTenant.fields.configure.prometheusSecurityContext,
});
const connector = connect(mapState, {

View File

@@ -43,6 +43,7 @@ import {
IValidation,
} from "../../../../../utils/validationFunctions";
import { KeyPair } from "../../ListTenants/utils";
import { ISecurityContext } from "../../types";
interface IEncryptionProps {
classes: any;
@@ -94,6 +95,8 @@ interface IEncryptionProps {
vaultCertificate: KeyPair;
vaultCA: KeyPair;
gemaltoCA: KeyPair;
kesSecurityContext: ISecurityContext;
replicas: string;
}
const styles = (theme: Theme) =>
@@ -155,6 +158,8 @@ const Encryption = ({
vaultCertificate,
vaultCA,
gemaltoCA,
kesSecurityContext,
replicas,
}: IEncryptionProps) => {
const [validationErrors, setValidationErrors] = useState<any>({});
@@ -187,6 +192,44 @@ const Encryption = ({
let encryptionValidation: IValidation[] = [];
if (enableEncryption) {
encryptionValidation = [
...encryptionValidation,
{
fieldKey: "replicas",
required: true,
value: replicas,
customValidation: parseInt(replicas) < 1,
customValidationMessage: "Replicas needs to be 1 or greater",
},
{
fieldKey: "kes_securityContext_runAsUser",
required: true,
value: kesSecurityContext.runAsUser,
customValidation:
kesSecurityContext.runAsUser === "" ||
parseInt(kesSecurityContext.runAsUser) < 0,
customValidationMessage: `runAsUser must be present and be 0 or more`,
},
{
fieldKey: "kes_securityContext_runAsGroup",
required: true,
value: kesSecurityContext.runAsGroup,
customValidation:
kesSecurityContext.runAsGroup === "" ||
parseInt(kesSecurityContext.runAsGroup) < 0,
customValidationMessage: `runAsGroup must be present and be 0 or more`,
},
{
fieldKey: "kes_securityContext_fsGroup",
required: true,
value: kesSecurityContext.fsGroup,
customValidation:
kesSecurityContext.fsGroup === "" ||
parseInt(kesSecurityContext.fsGroup) < 0,
customValidationMessage: `fsGroup must be present and be 0 or more`,
},
];
if (enableCustomCerts) {
encryptionValidation = [
...encryptionValidation,
@@ -368,6 +411,8 @@ const Encryption = ({
serverCertificate.encoded_cert,
clientCertificate.encoded_key,
clientCertificate.encoded_cert,
kesSecurityContext,
replicas,
]);
return (
@@ -961,6 +1006,122 @@ const Encryption = ({
</Grid>
</Fragment>
)}
<div className={classes.headerElement}>
<h3 className={classes.h3Section}>Additional Configurations</h3>
</div>
<Grid item xs={12}>
<Fragment>
<Grid item xs={12}>
<InputBoxWrapper
type="number"
min="1"
id="replicas"
name="replicas"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("replicas", e.target.value);
cleanValidation("replicas");
}}
label="Replicas"
value={replicas}
required
error={validationErrors["replicas"] || ""}
/>
</Grid>
<Grid item xs={12}>
<span className={classes.descriptionText}>
SecurityContext for KES pods
</span>
</Grid>
<br />
<Grid item xs={12}>
<div className={classes.multiContainer}>
<div>
<InputBoxWrapper
type="number"
id="kes_securityContext_runAsUser"
name="kes_securityContext_runAsUser"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("kesSecurityContext", {
...kesSecurityContext,
runAsUser: e.target.value,
});
cleanValidation("kes_securityContext_runAsUser");
}}
label="Run As User"
value={kesSecurityContext.runAsUser}
required
error={
validationErrors["kes_securityContext_runAsUser"] || ""
}
min="0"
/>
</div>
<div>
<InputBoxWrapper
type="number"
id="kes_securityContext_runAsGroup"
name="kes_securityContext_runAsGroup"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("kesSecurityContext", {
...kesSecurityContext,
runAsGroup: e.target.value,
});
cleanValidation("kes_securityContext_runAsGroup");
}}
label="Run As Group"
value={kesSecurityContext.runAsGroup}
required
error={
validationErrors["kes_securityContext_runAsGroup"] || ""
}
min="0"
/>
</div>
<div>
<InputBoxWrapper
type="number"
id="kes_securityContext_fsGroup"
name="kes_securityContext_fsGroup"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateField("kesSecurityContext", {
...kesSecurityContext,
fsGroup: e.target.value,
});
cleanValidation("kes_securityContext_fsGroup");
}}
label="FsGroup"
value={kesSecurityContext.fsGroup}
required
error={
validationErrors["kes_securityContext_fsGroup"] || ""
}
min="0"
/>
</div>
</div>
</Grid>
<br />
<Grid item xs={12}>
<div className={classes.multiContainer}>
<FormSwitchWrapper
value="kesSecurityContextRunAsNonRoot"
id="kes_securityContext_runAsNonRoot"
name="kes_securityContext_runAsNonRoot"
checked={kesSecurityContext.runAsNonRoot}
onChange={(e) => {
const targetD = e.target;
const checked = targetD.checked;
updateField("kesSecurityContext", {
...kesSecurityContext,
runAsNonRoot: checked,
});
}}
label={"Do not run as Root"}
/>
</div>
</Grid>
</Fragment>
</Grid>
</Fragment>
)}
</Paper>
@@ -968,6 +1129,7 @@ const Encryption = ({
};
const mapState = (state: AppState) => ({
replicas: state.tenants.createTenant.fields.encryption.replicas,
enableEncryption:
state.tenants.createTenant.fields.encryption.enableEncryption,
encryptionType: state.tenants.createTenant.fields.encryption.encryptionType,
@@ -1014,6 +1176,8 @@ const mapState = (state: AppState) => ({
gemaltoCA: state.tenants.createTenant.certificates.gemaltoCA,
enableCustomCerts:
state.tenants.createTenant.fields.security.enableCustomCerts,
kesSecurityContext:
state.tenants.createTenant.fields.encryption.kesSecurityContext,
});
const connector = connect(mapState, {

View File

@@ -46,6 +46,7 @@ interface IImagesProps {
exposeMinIO: boolean;
exposeConsole: boolean;
prometheusCustom: boolean;
tenantCustom: boolean;
logSearchCustom: boolean;
logSearchVolumeSize: string;
logSearchSizeFactor: string;
@@ -84,6 +85,7 @@ const Images = ({
exposeMinIO,
exposeConsole,
prometheusCustom,
tenantCustom,
logSearchCustom,
logSearchVolumeSize,
logSearchSizeFactor,
@@ -266,6 +268,7 @@ const Images = ({
imageRegistryPassword,
isPageValid,
prometheusCustom,
tenantCustom,
logSearchCustom,
prometheusSelectedStorageClass,
prometheusVolumeSize,
@@ -507,6 +510,7 @@ const mapState = (state: AppState) => ({
exposeConsole: state.tenants.createTenant.fields.configure.exposeConsole,
prometheusCustom:
state.tenants.createTenant.fields.configure.prometheusCustom,
tenantCustom: state.tenants.createTenant.fields.configure.tenantCustom,
logSearchCustom: state.tenants.createTenant.fields.configure.logSearchCustom,
logSearchVolumeSize:
state.tenants.createTenant.fields.configure.logSearchVolumeSize,

View File

@@ -43,6 +43,7 @@ import {
TENANT_DETAILS_SET_CURRENT_TENANT,
TENANT_DETAILS_SET_TENANT,
TENANT_DETAILS_SET_TAB,
ISecurityContext,
} from "./types";
import { KeyPair } from "./ListTenants/utils";
import { getRandomString } from "./utils";
@@ -50,7 +51,16 @@ import { getRandomString } from "./utils";
const initialState: ITenantState = {
createTenant: {
page: 0,
validPages: [],
// We can assume all the other pages are valid with default configuration except for 'nameTenant'
// because the user still have to choose a namespace and a name for the tenant
validPages: [
"tenantSize",
"configure",
"affinity",
"identityProvider",
"security",
"encryption",
],
advancedModeOn: false,
storageClasses: [],
limitSize: {},
@@ -69,6 +79,7 @@ const initialState: ITenantState = {
imageRegistryPassword: "",
exposeMinIO: true,
exposeConsole: true,
tenantCustom: false,
logSearchCustom: false,
prometheusCustom: false,
logSearchVolumeSize: "5",
@@ -84,6 +95,30 @@ const initialState: ITenantState = {
prometheusImage: "",
prometheusSidecarImage: "",
prometheusInitImage: "",
tenantSecurityContext: {
runAsUser: "1000",
runAsGroup: "1000",
fsGroup: "1000",
runAsNonRoot: true,
},
logSearchSecurityContext: {
runAsUser: "1000",
runAsGroup: "1000",
fsGroup: "1000",
runAsNonRoot: true,
},
logSearchPostgresSecurityContext: {
runAsUser: "999",
runAsGroup: "999",
fsGroup: "999",
runAsNonRoot: true,
},
prometheusSecurityContext: {
runAsUser: "1000",
runAsGroup: "1000",
fsGroup: "1000",
runAsNonRoot: true,
},
},
identityProvider: {
idpSelection: "Built-in",
@@ -148,6 +183,13 @@ const initialState: ITenantState = {
gcpPrivateKeyID: "",
gcpPrivateKey: "",
enableCustomCertsForKES: false,
replicas: "1",
kesSecurityContext: {
runAsUser: "1000",
runAsGroup: "1000",
fsGroup: "1000",
runAsNonRoot: true,
},
},
tenantSize: {
volumeSize: "100",
@@ -523,7 +565,16 @@ export function tenantsReducer(
...state,
createTenant: {
page: 0,
validPages: [],
// We can assume all the other pages are valid with default configuration except for 'nameTenant'
// because the user still have to choose a namespace and a name for the tenant
validPages: [
"tenantSize",
"configure",
"affinity",
"identityProvider",
"security",
"encryption",
],
advancedModeOn: false,
storageClasses: [],
limitSize: {},
@@ -542,6 +593,7 @@ export function tenantsReducer(
imageRegistryPassword: "",
exposeMinIO: true,
exposeConsole: true,
tenantCustom: false,
logSearchCustom: false,
prometheusCustom: false,
logSearchVolumeSize: "5",
@@ -557,6 +609,30 @@ export function tenantsReducer(
prometheusImage: "",
prometheusSidecarImage: "",
prometheusInitImage: "",
tenantSecurityContext: {
runAsUser: "1000",
runAsGroup: "1000",
fsGroup: "1000",
runAsNonRoot: true,
},
logSearchSecurityContext: {
runAsUser: "1000",
runAsGroup: "1000",
fsGroup: "1000",
runAsNonRoot: true,
},
logSearchPostgresSecurityContext: {
runAsUser: "999",
runAsGroup: "999",
fsGroup: "999",
runAsNonRoot: true,
},
prometheusSecurityContext: {
runAsUser: "1000",
runAsGroup: "1000",
fsGroup: "1000",
runAsNonRoot: true,
},
},
identityProvider: {
idpSelection: "Built-in",
@@ -621,6 +697,13 @@ export function tenantsReducer(
gcpPrivateKeyID: "",
gcpPrivateKey: "",
enableCustomCertsForKES: false,
replicas: "1",
kesSecurityContext: {
runAsUser: "1000",
runAsGroup: "1000",
fsGroup: "1000",
runAsNonRoot: true,
},
},
tenantSize: {
volumeSize: "100",

View File

@@ -121,6 +121,13 @@ export interface INameTenantFields {
selectedStorageClass: string;
}
export interface ISecurityContext {
runAsUser: string;
runAsGroup: string;
runAsNonRoot: boolean;
fsGroup: string;
}
export interface IConfigureFields {
customImage: boolean;
imageName: string;
@@ -131,6 +138,7 @@ export interface IConfigureFields {
exposeMinIO: boolean;
exposeConsole: boolean;
prometheusCustom: boolean;
tenantCustom: boolean;
logSearchCustom: boolean;
logSearchVolumeSize: string;
logSearchSizeFactor: string;
@@ -145,6 +153,10 @@ export interface IConfigureFields {
prometheusImage: string;
prometheusSidecarImage: string;
prometheusInitImage: string;
tenantSecurityContext: ISecurityContext;
logSearchSecurityContext: ISecurityContext;
logSearchPostgresSecurityContext: ISecurityContext;
prometheusSecurityContext: ISecurityContext;
}
export interface IIdentityProviderFields {
@@ -212,6 +224,8 @@ export interface IEncryptionFields {
gcpPrivateKeyID: string;
gcpPrivateKey: string;
enableCustomCertsForKES: boolean;
replicas: string;
kesSecurityContext: ISecurityContext;
}
export interface ITenantSizeFields {

View File

@@ -1329,6 +1329,12 @@ definitions:
default: 5
image:
type: string
securityContext:
type: object
$ref: '#/definitions/securityContext'
postgres_securityContext:
type: object
$ref: '#/definitions/securityContext'
postgres_image:
type: string
postgres_init_image:
@@ -1452,6 +1458,9 @@ definitions:
azure:
type: object
$ref: "#/definitions/azureConfiguration"
securityContext:
type: object
$ref: '#/definitions/securityContext'
vaultConfiguration:
type: object
@@ -1696,6 +1705,9 @@ definitions:
$ref: "#/definitions/poolAffinity"
tolerations:
$ref: "#/definitions/poolTolerations"
securityContext:
type: object
$ref: '#/definitions/securityContext'
poolTolerations:
description: Tolerations allows users to set entries like effect,
@@ -2332,14 +2344,11 @@ definitions:
- fsGroup
properties:
runAsUser:
type: integer
format: int64
type: string
runAsGroup:
type: integer
format: int64
type: string
runAsNonRoot:
type: boolean
fsGroup:
type: integer
format: int64
type: string