Skip to content
This repository was archived by the owner on Dec 12, 2025. It is now read-only.

Commit 75bfad8

Browse files
authored
CLOUDP-79918: Support custom MongoDB roles (#286)
* CLOUDP-79918: Support custom MongoDB roles * Fixed decoding in e2e test * Address PR comments * Refactor to reuse getAdminSetting code * Address PR comments II * Address PR comments
1 parent d77211f commit 75bfad8

File tree

11 files changed

+620
-39
lines changed

11 files changed

+620
-39
lines changed

.evergreen.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ task_groups:
180180
- e2e_test_statefulset_arbitrary_config_update
181181
- e2e_test_replica_set_mongod_config
182182
- e2e_test_replica_set_cross_namespace_deploy
183+
- e2e_test_replica_set_custom_role
183184
teardown_task:
184185
- func: upload_e2e_logs
185186

@@ -332,6 +333,12 @@ tasks:
332333
test: replica_set_cross_namespace_deploy
333334
clusterwide: true
334335

336+
- name: e2e_test_replica_set_custom_role
337+
commands:
338+
- func: run_e2e_test
339+
vars:
340+
test: replica_set_custom_role
341+
335342
- name: release_blocker
336343
commands:
337344
- func: clone

deploy/crds/mongodb.com_mongodb_crd.yaml

Lines changed: 105 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,15 @@ spec:
5050
description: Members is the number of members in the replica set
5151
type: integer
5252
replicaSetHorizons:
53-
description: Add this parameter and values if you need your database
54-
to be accessed outside of Kubernetes. This setting allows you to
55-
provide different DNS settings within the Kubernetes cluster and
56-
to the Kubernetes cluster. The Kubernetes Operator uses split horizon
57-
DNS for replica set members. This feature allows communication both
58-
within the Kubernetes cluster and from outside Kubernetes.
53+
description: ReplicaSetHorizons Add this parameter and values if you
54+
need your database to be accessed outside of Kubernetes. This setting
55+
allows you to provide different DNS settings within the Kubernetes
56+
cluster and to the Kubernetes cluster. The Kubernetes Operator uses
57+
split horizon DNS for replica set members. This feature allows communication
58+
both within the Kubernetes cluster and from outside Kubernetes.
5959
items:
60-
properties: {}
60+
additionalProperties:
61+
type: string
6162
type: object
6263
type: array
6364
security:
@@ -74,6 +75,93 @@ spec:
7475
- SCRAM
7576
type: string
7677
type: array
78+
roles:
79+
description: User-specified custom MongoDB roles that should
80+
be configured in the deployment.
81+
items:
82+
description: CustomRole defines a custom MongoDB role.
83+
properties:
84+
authenticationRestrictions:
85+
description: The authentication restrictions the server
86+
enforces on the role.
87+
items:
88+
description: AuthenticationRestriction specifies a list
89+
of IP addresses and CIDR ranges users are allowed
90+
to connect to or from.
91+
properties:
92+
clientSource:
93+
items:
94+
type: string
95+
type: array
96+
serverAddress:
97+
items:
98+
type: string
99+
type: array
100+
required:
101+
- clientSource
102+
- serverAddress
103+
type: object
104+
type: array
105+
db:
106+
description: The database of the role.
107+
type: string
108+
privileges:
109+
description: The privileges to grant the role.
110+
items:
111+
description: Privilege defines the actions a role is
112+
allowed to perform on a given resource.
113+
properties:
114+
actions:
115+
items:
116+
type: string
117+
type: array
118+
resource:
119+
description: Resource specifies specifies the resources
120+
upon which a privilege permits actions. See https://docs.mongodb.com/manual/reference/resource-document
121+
for more.
122+
properties:
123+
anyResource:
124+
type: boolean
125+
cluster:
126+
type: boolean
127+
collection:
128+
type: string
129+
db:
130+
type: string
131+
type: object
132+
required:
133+
- actions
134+
- resource
135+
type: object
136+
type: array
137+
role:
138+
description: The name of the role.
139+
type: string
140+
roles:
141+
description: An array of roles from which this role inherits
142+
privileges.
143+
items:
144+
description: Role is the database role this user should
145+
have
146+
properties:
147+
db:
148+
description: DB is the database the role can act
149+
on
150+
type: string
151+
name:
152+
description: Name is the name of the role
153+
type: string
154+
required:
155+
- db
156+
- name
157+
type: object
158+
type: array
159+
required:
160+
- db
161+
- privileges
162+
- role
163+
type: object
164+
type: array
77165
required:
78166
- modes
79167
type: object
@@ -169,8 +257,9 @@ spec:
169257
type: object
170258
type: array
171259
scramCredentialsSecretName:
172-
description: ScramCredentialsSecretName appended by string "scram-credentials" is the name of the secret object
173-
created by the mongoDB operator for storing SCRAM credentials
260+
description: ScramCredentialsSecretName appended by string "scram-credentials"
261+
is the name of the secret object created by the mongoDB operator
262+
for storing SCRAM credentials
174263
type: string
175264
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
176265
required:
@@ -192,16 +281,21 @@ spec:
192281
status:
193282
description: MongoDBStatus defines the observed state of MongoDB
194283
properties:
195-
currentStatefulSetReplicas:
196-
type: integer
197284
currentMongoDBMembers:
198285
type: integer
286+
currentStatefulSetReplicas:
287+
type: integer
199288
message:
200289
type: string
201290
mongoUri:
202291
type: string
203292
phase:
204293
type: string
294+
required:
295+
- currentMongoDBMembers
296+
- currentStatefulSetReplicas
297+
- mongoUri
298+
- phase
205299
type: object
206300
type: object
207301
version: v1
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
---
2+
apiVersion: mongodb.com/v1
3+
kind: MongoDB
4+
metadata:
5+
name: custom-role-mongodb
6+
spec:
7+
members: 3
8+
type: ReplicaSet
9+
version: "4.2.6"
10+
security:
11+
authentication:
12+
modes: ["SCRAM"]
13+
roles: # custom roles are defined here
14+
- role: testRole
15+
db: admin
16+
privileges:
17+
- resource:
18+
db: "test"
19+
collection: "" # an empty string indicates any collection
20+
actions:
21+
- find
22+
roles: []
23+
users:
24+
- name: my-user
25+
db: admin
26+
passwordSecretRef: # a reference to the secret that will be used to generate the user's password
27+
name: my-user-password
28+
roles:
29+
- name: clusterAdmin
30+
db: admin
31+
- name: userAdminAnyDatabase
32+
db: admin
33+
- name: testRole # apply the custom role to the user
34+
db: admin
35+
scramCredentialsSecretName: my-scram
36+
37+
# the user credentials will be generated from this secret
38+
# once the credentials are generated, this secret is no longer required
39+
---
40+
apiVersion: v1
41+
kind: Secret
42+
metadata:
43+
name: my-user-password
44+
type: Opaque
45+
stringData:
46+
password: 58LObjiMpxcjP1sMDW

pkg/apis/mongodb/v1/mongodb_types.go

Lines changed: 100 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,12 @@ type MongoDBSpec struct {
5151
// +optional
5252
FeatureCompatibilityVersion string `json:"featureCompatibilityVersion,omitempty"`
5353

54-
// ReplicaSetHorizons allows providing different DNS settings within the
55-
// Kubernetes cluster and to the Kubernetes cluster.
54+
// ReplicaSetHorizons Add this parameter and values if you need your database
55+
// to be accessed outside of Kubernetes. This setting allows you to
56+
// provide different DNS settings within the Kubernetes cluster and
57+
// to the Kubernetes cluster. The Kubernetes Operator uses split horizon
58+
// DNS for replica set members. This feature allows communication both
59+
// within the Kubernetes cluster and from outside Kubernetes.
5660
// +optional
5761
ReplicaSetHorizons ReplicaSetHorizonConfiguration `json:"replicaSetHorizons,omitempty"`
5862

@@ -78,6 +82,96 @@ type MongoDBSpec struct {
7882
// replica set members.
7983
type ReplicaSetHorizonConfiguration []automationconfig.ReplicaSetHorizons
8084

85+
// CustomRole defines a custom MongoDB role.
86+
type CustomRole struct {
87+
// The name of the role.
88+
Role string `json:"role"`
89+
// The database of the role.
90+
DB string `json:"db"`
91+
// The privileges to grant the role.
92+
Privileges []Privilege `json:"privileges"`
93+
// An array of roles from which this role inherits privileges.
94+
// +optional
95+
Roles []Role `json:"roles"`
96+
// The authentication restrictions the server enforces on the role.
97+
// +optional
98+
AuthenticationRestrictions []AuthenticationRestriction `json:"authenticationRestrictions,omitempty"`
99+
}
100+
101+
// ConvertToAutomationConfigCustomRole converts between a custom role defined by the crd and a custom role
102+
// that can be used in the automation config.
103+
func (c CustomRole) ConvertToAutomationConfigCustomRole() automationconfig.CustomRole {
104+
ac := automationconfig.CustomRole{Role: c.Role, DB: c.DB, Roles: []automationconfig.Role{}}
105+
106+
// Add privileges.
107+
for _, privilege := range c.Privileges {
108+
ac.Privileges = append(ac.Privileges, automationconfig.Privilege{
109+
Resource: automationconfig.Resource{
110+
DB: privilege.Resource.DB,
111+
Collection: privilege.Resource.Collection,
112+
AnyResource: privilege.Resource.AnyResource,
113+
Cluster: privilege.Resource.Cluster,
114+
},
115+
Actions: privilege.Actions,
116+
})
117+
}
118+
119+
// Add roles.
120+
for _, dbRole := range c.Roles {
121+
ac.Roles = append(ac.Roles, automationconfig.Role{
122+
Role: dbRole.Name,
123+
Database: dbRole.DB,
124+
})
125+
}
126+
127+
// Add authentication restrictions (if any).
128+
for _, restriction := range c.AuthenticationRestrictions {
129+
ac.AuthenticationRestrictions = append(ac.AuthenticationRestrictions,
130+
automationconfig.AuthenticationRestriction{
131+
ClientSource: restriction.ClientSource,
132+
ServerAddress: restriction.ServerAddress,
133+
})
134+
}
135+
136+
return ac
137+
}
138+
139+
// ConvertCustomRolesToAutomationConfigCustomRole converts custom roles to custom roles
140+
// that can be used in the automation config.
141+
func ConvertCustomRolesToAutomationConfigCustomRole(roles []CustomRole) []automationconfig.CustomRole {
142+
acRoles := []automationconfig.CustomRole{}
143+
for _, role := range roles {
144+
acRoles = append(acRoles, role.ConvertToAutomationConfigCustomRole())
145+
}
146+
return acRoles
147+
}
148+
149+
// Privilege defines the actions a role is allowed to perform on a given resource.
150+
type Privilege struct {
151+
Resource Resource `json:"resource"`
152+
Actions []string `json:"actions"`
153+
}
154+
155+
// Resource specifies specifies the resources upon which a privilege permits actions.
156+
// See https://docs.mongodb.com/manual/reference/resource-document for more.
157+
type Resource struct {
158+
// +optional
159+
DB *string `json:"db,omitempty"`
160+
// +optional
161+
Collection *string `json:"collection,omitempty"`
162+
// +optional
163+
Cluster bool `json:"cluster,omitempty"`
164+
// +optional
165+
AnyResource bool `json:"anyResource,omitempty"`
166+
}
167+
168+
// AuthenticationRestriction specifies a list of IP addresses and CIDR ranges users
169+
// are allowed to connect to or from.
170+
type AuthenticationRestriction struct {
171+
ClientSource []string `json:"clientSource"`
172+
ServerAddress []string `json:"serverAddress"`
173+
}
174+
81175
// StatefulSetConfiguration holds the optional custom StatefulSet
82176
// that should be merged into the operator created one.
83177
type StatefulSetConfiguration struct {
@@ -212,6 +306,10 @@ type LocalObjectReference struct {
212306
type Authentication struct {
213307
// Modes is an array specifying which authentication methods should be enabled
214308
Modes []AuthMode `json:"modes"`
309+
310+
// User-specified custom MongoDB roles that should be configured in the deployment.
311+
// +optional
312+
Roles []CustomRole `json:"roles,omitempty"`
215313
}
216314

217315
// +kubebuilder:validation:Enum=SCRAM

0 commit comments

Comments
 (0)