Skip to content

Commit 142d1a2

Browse files
MLE-11464: Implementation for Securing MarkLogic Group deployment (#12)
* MLE-11464: Implementation for Securing MarkLogic Group deployment
1 parent 46ef309 commit 142d1a2

File tree

11 files changed

+1282
-1200
lines changed

11 files changed

+1282
-1200
lines changed

api/v1alpha1/marklogicgroup_types.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,12 @@ type MarklogicGroupSpec struct {
4747
TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty"`
4848
// +kubebuilder:validation:Enum=OnDelete;RollingUpdate
4949
// +kubebuilder:default:="OnDelete"
50-
UpdateStrategy appsv1.StatefulSetUpdateStrategyType `json:"updateStrategy,omitempty"`
51-
NetworkPolicy *networkingv1.NetworkPolicy `json:"networkPolicy,omitempty"`
52-
PodSecurityContext *corev1.PodSecurityContext `json:"securityContext,omitempty"`
53-
ContainerSecurityContext *corev1.SecurityContext `json:"containerSecurityContext,omitempty"`
50+
UpdateStrategy appsv1.StatefulSetUpdateStrategyType `json:"updateStrategy,omitempty"`
51+
NetworkPolicy *networkingv1.NetworkPolicy `json:"networkPolicy,omitempty"`
52+
// +kubebuilder:default:={fsGroup: 2, fsGroupChangePolicy: "OnRootMismatch"}
53+
PodSecurityContext *corev1.PodSecurityContext `json:"podSecurityContext,omitempty"`
54+
// +kubebuilder:default:={runAsUser: 1000, runAsNonRoot: true, allowPrivilegeEscalation: false}
55+
ContainerSecurityContext *corev1.SecurityContext `json:"securityContext,omitempty"`
5456

5557
Affinity *corev1.Affinity `json:"affinity,omitempty"`
5658
NodeSelector map[string]string `json:"nodeSelector,omitempty"`

bundle/manifests/database.marklogic.com_marklogicclusters.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1176,7 +1176,7 @@ spec:
11761176
type: string
11771177
type: object
11781178
image:
1179-
default: marklogicdb/marklogic-db:11.2.0-ubi
1179+
default: progressofficial/marklogic-db:11.3.0-ubi-rootless
11801180
type: string
11811181
imagePullPolicy:
11821182
default: IfNotPresent

bundle/manifests/database.marklogic.com_marklogicgroups.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1051,7 +1051,7 @@ spec:
10511051
type: string
10521052
type: object
10531053
image:
1054-
default: marklogicdb/marklogic-db:11.2.0-ubi
1054+
default: progressofficial/marklogic-db:11.3.0-ubi-rootless
10551055
type: string
10561056
imagePullPolicy:
10571057
default: IfNotPresent

charts/marklogic-operator/templates/marklogiccluster-crd.yaml

Lines changed: 302 additions & 295 deletions
Large diffs are not rendered by default.

charts/marklogic-operator/templates/marklogicgroup-crd.yaml

Lines changed: 299 additions & 292 deletions
Large diffs are not rendered by default.

config/crd/bases/database.marklogic.com_marklogicclusters.yaml

Lines changed: 303 additions & 296 deletions
Large diffs are not rendered by default.

config/crd/bases/database.marklogic.com_marklogicgroups.yaml

Lines changed: 299 additions & 292 deletions
Large diffs are not rendered by default.

config/samples/marklogicgroup.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ spec:
2121
updateStrategy: OnDelete
2222
groupConfig:
2323
name: "node"
24+
## Uncomment the following lines to specify the podSecurityContext and containerSecurityContext
25+
## Note: Below values are set to default, please update them as per your requirements
26+
# podSecurityContext:
27+
# fsGroup: 2
28+
# fsGroupChangePolicy: OnRootMismatch
29+
# securityContext:
30+
# runAsUser: 1000
31+
# runAsNonRoot: true
32+
# allowPrivilegeEscalation: false
33+
2434
logCollection:
2535
enabled: true
2636
image: fluent/fluent-bit:3.1.1

internal/controller/marklogicgroup_controller_test.go

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import (
2626
appsv1 "k8s.io/api/apps/v1"
2727
corev1 "k8s.io/api/core/v1"
2828
"k8s.io/apimachinery/pkg/api/resource"
29-
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3030
"k8s.io/apimachinery/pkg/types"
3131
"k8s.io/apimachinery/pkg/util/intstr"
3232
)
@@ -39,19 +39,24 @@ const (
3939
timeout = time.Second * 60
4040
duration = time.Second * 30
4141
interval = time.Millisecond * 250
42+
43+
imageName = "progressofficial/marklogic-db:11.3.0-ubi-rootless"
4244
)
4345

4446
var replicas = int32(2)
47+
var fsGroup = int64(2)
48+
var fsGroupChangePolicy = corev1.FSGroupChangeOnRootMismatch
49+
var runAsUser = int64(1000)
50+
var runAsNonRoot bool = true
51+
var allowPrivilegeEscalation bool = false
52+
var typeNamespaceName = types.NamespacedName{Name: Name, Namespace: Namespace}
4553

4654
const resourceCpuValue = int64(1)
4755
const resourceMemoryValue = int64(268435456)
4856

4957
// 100Mi
5058
const resourceHugepageValue = int64(104857600)
5159

52-
var typeNamespaceName = types.NamespacedName{Name: Name, Namespace: Namespace}
53-
54-
const imageName = "progressofficial/marklogic-db:11.3.0-ubi-rootless"
5560
const fluentBitImage = "fluent/fluent-bit:3.1.1"
5661

5762
var groupConfig = databasev1alpha1.GroupConfig{
@@ -70,17 +75,17 @@ var _ = Describe("MarkLogicGroup controller", func() {
7075
It("Should create a MarklogicGroup CR, StatefulSet and Service", func() {
7176
// Create the namespace
7277
ns := corev1.Namespace{
73-
ObjectMeta: v1.ObjectMeta{Name: Namespace},
78+
ObjectMeta: metav1.ObjectMeta{Name: Namespace},
7479
}
7580
Expect(k8sClient.Create(ctx, &ns)).Should(Succeed())
7681

7782
// Declaring the Marklogic Group object and create CR
7883
mlGroup := &databasev1alpha1.MarklogicGroup{
79-
TypeMeta: v1.TypeMeta{
84+
TypeMeta: metav1.TypeMeta{
8085
Kind: "MarklogicGroup",
8186
APIVersion: "database.marklogic.com/v1alpha1",
8287
},
83-
ObjectMeta: v1.ObjectMeta{
88+
ObjectMeta: metav1.ObjectMeta{
8489
Name: Name,
8590
Namespace: Namespace,
8691
},
@@ -97,7 +102,16 @@ var _ = Describe("MarkLogicGroup controller", func() {
97102
ClusterDomain: "cluster.local",
98103
TopologySpreadConstraints: []corev1.TopologySpreadConstraint{{MaxSkew: 2, TopologyKey: "kubernetes.io/hostname", WhenUnsatisfiable: corev1.ScheduleAnyway}},
99104
Affinity: &corev1.Affinity{PodAffinity: &corev1.PodAffinity{PreferredDuringSchedulingIgnoredDuringExecution: []corev1.WeightedPodAffinityTerm{{PodAffinityTerm: corev1.PodAffinityTerm{TopologyKey: "kubernetes.io/hostname"}, Weight: 100}}}},
100-
LogCollection: &databasev1alpha1.LogCollection{Enabled: true, Image: "fluent/fluent-bit:3.1.1", Files: databasev1alpha1.LogFilesConfig{ErrorLogs: true, AccessLogs: true, RequestLogs: true, CrashLogs: true, AuditLogs: true}, Outputs: "stdout"},
105+
PodSecurityContext: &corev1.PodSecurityContext{
106+
FSGroup: &fsGroup,
107+
FSGroupChangePolicy: &fsGroupChangePolicy,
108+
},
109+
ContainerSecurityContext: &corev1.SecurityContext{
110+
RunAsUser: &runAsUser,
111+
RunAsNonRoot: &runAsNonRoot,
112+
AllowPrivilegeEscalation: &allowPrivilegeEscalation,
113+
},
114+
LogCollection: &databasev1alpha1.LogCollection{Enabled: true, Image: "fluent/fluent-bit:3.1.1", Files: databasev1alpha1.LogFilesConfig{ErrorLogs: true, AccessLogs: true, RequestLogs: true, CrashLogs: true, AuditLogs: true}, Outputs: "stdout"},
101115
},
102116
}
103117
Expect(k8sClient.Create(ctx, mlGroup)).Should(Succeed())
@@ -130,6 +144,11 @@ var _ = Describe("MarkLogicGroup controller", func() {
130144
Expect(createdCR.Spec.TopologySpreadConstraints[0].TopologyKey).Should(Equal("kubernetes.io/hostname"))
131145
Expect(createdCR.Spec.TopologySpreadConstraints[0].WhenUnsatisfiable).Should(Equal(corev1.ScheduleAnyway))
132146
Expect(createdCR.Spec.Affinity.PodAffinity.PreferredDuringSchedulingIgnoredDuringExecution[0].Weight).Should(Equal(int32(100)))
147+
Expect(createdCR.Spec.PodSecurityContext.FSGroup).Should(Equal(&fsGroup))
148+
Expect(*createdCR.Spec.PodSecurityContext.FSGroupChangePolicy).Should(Equal(corev1.FSGroupChangeOnRootMismatch))
149+
Expect(*createdCR.Spec.ContainerSecurityContext.RunAsUser).Should(Equal(int64(1000)))
150+
Expect(createdCR.Spec.ContainerSecurityContext.RunAsNonRoot).Should(Equal(&runAsNonRoot))
151+
Expect(createdCR.Spec.ContainerSecurityContext.AllowPrivilegeEscalation).Should(Equal(&allowPrivilegeEscalation))
133152
Expect(createdCR.Spec.LogCollection.Enabled).Should(Equal(true))
134153
Expect(createdCR.Spec.LogCollection.Image).Should(Equal(fluentBitImage))
135154

pkg/k8sutil/marklogicServer.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ type markLogicServerParameters struct {
1212
Replicas *int32
1313
Name string
1414
Image string
15+
License *databasev1alpha1.License
1516
// PersistentVolumeClaim corev1.PersistentVolumeClaim
1617
TerminationGracePeriodSeconds *int64
1718
Resources *corev1.ResourceRequirements
@@ -22,6 +23,8 @@ type markLogicServerParameters struct {
2223
Affinity *corev1.Affinity
2324
NodeSelector map[string]string
2425
TopologySpreadConstraints []corev1.TopologySpreadConstraint
26+
PodSecurityContext *corev1.PodSecurityContext
27+
ContainerSecurityContext *corev1.SecurityContext
2528
}
2629

2730
func MarkLogicServerLogger(namespace string, name string) logr.Logger {
@@ -46,8 +49,19 @@ func ReconcileMarkLogicCluster(cr *databasev1alpha1.MarklogicCluster, index int)
4649
Replicas: params.Replicas,
4750
Name: params.Name,
4851
Image: params.Image,
52+
License: params.License,
4953
TerminationGracePeriodSeconds: params.TerminationGracePeriodSeconds,
5054
BootstrapHost: generateBootstrapHost(cr.Spec.MarkLogicGroups[index].IsBootstrap),
55+
Resources: params.Resources,
56+
EnableConverters: params.EnableConverters,
57+
PriorityClassName: params.PriorityClassName,
58+
ClusterDomain: params.ClusterDomain,
59+
UpdateStrategy: params.UpdateStrategy,
60+
Affinity: params.Affinity,
61+
NodeSelector: params.NodeSelector,
62+
TopologySpreadConstraints: params.TopologySpreadConstraints,
63+
PodSecurityContext: params.PodSecurityContext,
64+
ContainerSecurityContext: params.ContainerSecurityContext,
5165
},
5266
}
5367
AddOwnerRefToObject(MarkLogicServerDef, ownerDef)
@@ -67,6 +81,7 @@ func generateMarkLogicServerParams(cr *databasev1alpha1.MarklogicCluster, index
6781
Replicas: cr.Spec.MarkLogicGroups[index].Replicas,
6882
Name: cr.Spec.MarkLogicGroups[index].Name,
6983
Image: cr.Spec.MarkLogicGroups[index].Image,
84+
License: cr.Spec.MarkLogicGroups[index].License,
7085
TerminationGracePeriodSeconds: cr.Spec.MarkLogicGroups[index].TerminationGracePeriodSeconds,
7186
Resources: cr.Spec.MarkLogicGroups[index].Resources,
7287
EnableConverters: cr.Spec.MarkLogicGroups[index].EnableConverters,
@@ -76,6 +91,8 @@ func generateMarkLogicServerParams(cr *databasev1alpha1.MarklogicCluster, index
7691
Affinity: cr.Spec.MarkLogicGroups[index].Affinity,
7792
NodeSelector: cr.Spec.MarkLogicGroups[index].NodeSelector,
7893
TopologySpreadConstraints: cr.Spec.MarkLogicGroups[index].TopologySpreadConstraints,
94+
PodSecurityContext: cr.Spec.MarkLogicGroups[index].PodSecurityContext,
95+
ContainerSecurityContext: cr.Spec.MarkLogicGroups[index].ContainerSecurityContext,
7996
}
8097
// if cr.Spec.Storage != nil {
8198
// params.PersistentVolumeClaim = generatePVCTemplate(cr.Spec.Storage.Size)

0 commit comments

Comments
 (0)