Skip to content

Commit d2f0323

Browse files
committed
Validations
1 parent aa5cea7 commit d2f0323

File tree

6 files changed

+96
-4
lines changed

6 files changed

+96
-4
lines changed

api/v1/mdb/mongodb_roles_validation.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,9 @@ func validateAuthenticationRestriction(ar AuthenticationRestriction) v1.Validati
163163
// and returns true if the first one is greater or equal the second
164164
// false otherwise
165165
func isVersionAtLeast(mdbVersion string, expectedVersion string) (bool, error) {
166+
if mdbVersion == "" {
167+
return true, nil
168+
}
166169
currentV, err := semver.Make(mdbVersion)
167170
if err != nil {
168171
return false, xerrors.Errorf("error parsing mdbVersion %s with semver: %w", mdbVersion, err)
@@ -270,7 +273,7 @@ func isValidCIDR(cidr string) bool {
270273
return err == nil
271274
}
272275

273-
func roleIsCorrectlyConfigured(role MongoDbRole, mdbVersion string) v1.ValidationResult {
276+
func RoleIsCorrectlyConfigured(role MongoDBRole, mdbVersion string) v1.ValidationResult {
274277
// Extensive validation of the roles attribute
275278

276279
if role.Role == "" {
@@ -305,10 +308,10 @@ func roleIsCorrectlyConfigured(role MongoDbRole, mdbVersion string) v1.Validatio
305308
return v1.ValidationSuccess()
306309
}
307310

308-
func rolesAttributeisCorrectlyConfigured(d DbCommonSpec) v1.ValidationResult {
311+
func rolesAttributeIsCorrectlyConfigured(d DbCommonSpec) v1.ValidationResult {
309312
// Validate every single entry and return error on the first one that fails validation
310313
for _, role := range d.Security.Roles {
311-
if res := roleIsCorrectlyConfigured(role, d.Version); res.Level == v1.ErrorLevel {
314+
if res := RoleIsCorrectlyConfigured(role, d.Version); res.Level == v1.ErrorLevel {
312315
return v1.ValidationError("Error validating role - %s", res.Msg)
313316
}
314317
}

api/v1/mdb/mongodb_types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,7 @@ type SharedConnectionSpec struct {
736736
CloudManagerConfig *PrivateCloudConfig `json:"cloudManager,omitempty"`
737737
}
738738

739+
// +kubebuilder:validation:XValidation:rule="!(has(self.roles) && has(self.roleRefs)) || !(self.roles.size() > 0 && self.roleRefs.size() > 0)",message="At most one of roles or roleRefs can be non-empty"
739740
type Security struct {
740741
TLSConfig *TLSConfig `json:"tls,omitempty"`
741742
Authentication *Authentication `json:"authentication,omitempty"`

api/v1/mdb/mongodb_validation.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ func CommonValidators() []func(d DbCommonSpec) v1.ValidationResult {
195195
deploymentsMustHaveAgentModeInAuthModes,
196196
scramSha1AuthValidation,
197197
ldapAuthRequiresEnterprise,
198-
rolesAttributeisCorrectlyConfigured,
198+
rolesAttributeIsCorrectlyConfigured,
199199
agentModeIsSetIfMoreThanADeploymentAuthModeIsSet,
200200
ldapGroupDnIsSetIfLdapAuthzIsEnabledAndAgentsAreExternal,
201201
specWithExactlyOneSchema,
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package role
2+
3+
import (
4+
"golang.org/x/xerrors"
5+
"k8s.io/apimachinery/pkg/runtime"
6+
"sigs.k8s.io/controller-runtime/pkg/webhook"
7+
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
8+
9+
v1 "github.com/mongodb/mongodb-kubernetes/api/v1"
10+
"github.com/mongodb/mongodb-kubernetes/api/v1/mdb"
11+
)
12+
13+
var _ webhook.Validator = &ClusterMongoDBRole{}
14+
15+
func (r *ClusterMongoDBRole) ValidateCreate() (warnings admission.Warnings, err error) {
16+
return nil, r.ProcessValidationsOnReconcile(nil)
17+
}
18+
19+
func (r *ClusterMongoDBRole) ValidateUpdate(old runtime.Object) (warnings admission.Warnings, err error) {
20+
return nil, r.ProcessValidationsOnReconcile(old.(*ClusterMongoDBRole))
21+
}
22+
23+
func (r *ClusterMongoDBRole) ValidateDelete() (warnings admission.Warnings, err error) {
24+
return nil, nil
25+
}
26+
27+
func (r *ClusterMongoDBRole) ProcessValidationsOnReconcile(_ *ClusterMongoDBRole) error {
28+
if res := mdb.RoleIsCorrectlyConfigured(r.Spec.MongoDBRole, ""); res.Level == v1.ErrorLevel {
29+
return xerrors.Errorf("Error validating role - %s", res.Msg)
30+
}
31+
return nil
32+
}

config/webhooks/webhooks.yaml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,26 @@ webhooks:
7373
failurePolicy: Ignore
7474
sideEffects: None
7575
timeoutSeconds: 5
76+
77+
- name: validate-clustermongodbroles.mongodb.com
78+
admissionReviewVersions:
79+
- v1
80+
clientConfig:
81+
caBundle: Cg==
82+
service:
83+
name: mongodb-kubernetes-operator
84+
namespace: placeholder
85+
path: /validate-mongodb-com-v1-clustermongodbrole
86+
rules:
87+
- apiGroups:
88+
- mongodb.com
89+
apiVersions:
90+
- v1
91+
operations:
92+
- CREATE
93+
- UPDATE
94+
resources:
95+
- clustermongodbroles
96+
failurePolicy: Ignore
97+
sideEffects: None
98+
timeoutSeconds: 5

pkg/webhook/setup.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,14 @@ func GetWebhookConfig(serviceLocation types.NamespacedName) admissionv1.Validati
7676

7777
// need to make variables as one can't take the address of a constant
7878
scope := admissionv1.NamespacedScope
79+
clusterScope := admissionv1.ClusterScope
7980
sideEffects := admissionv1.SideEffectClassNone
8081
failurePolicy := admissionv1.Ignore
8182
var port int32 = 443
8283
dbPath := "/validate-mongodb-com-v1-mongodb"
8384
dbmultiPath := "/validate-mongodb-com-v1-mongodbmulticluster"
8485
omPath := "/validate-mongodb-com-v1-mongodbopsmanager"
86+
clusterrolePath := "/validate-mongodb-com-v1-clustermongodbrole"
8587
return admissionv1.ValidatingWebhookConfiguration{
8688
ObjectMeta: metav1.ObjectMeta{
8789
Name: "mdbpolicy.mongodb.com",
@@ -178,6 +180,37 @@ func GetWebhookConfig(serviceLocation types.NamespacedName) admissionv1.Validati
178180
SideEffects: &sideEffects,
179181
FailurePolicy: &failurePolicy,
180182
},
183+
{
184+
Name: "clustermdbrolepolicy.mongodb.com",
185+
ClientConfig: admissionv1.WebhookClientConfig{
186+
Service: &admissionv1.ServiceReference{
187+
Name: serviceLocation.Name,
188+
Namespace: serviceLocation.Namespace,
189+
Path: &clusterrolePath,
190+
// NOTE: port isn't supported in k8s 1.11 and lower. It works in
191+
// 1.15 but I am unsure about the intervening versions.
192+
Port: &port,
193+
},
194+
CABundle: caBytes,
195+
},
196+
Rules: []admissionv1.RuleWithOperations{
197+
{
198+
Operations: []admissionv1.OperationType{
199+
admissionv1.Create,
200+
admissionv1.Update,
201+
},
202+
Rule: admissionv1.Rule{
203+
APIGroups: []string{"mongodb.com"},
204+
APIVersions: []string{"*"},
205+
Resources: []string{"clustermongodbroles"},
206+
Scope: &clusterScope,
207+
},
208+
},
209+
},
210+
AdmissionReviewVersions: []string{"v1"},
211+
SideEffects: &sideEffects,
212+
FailurePolicy: &failurePolicy,
213+
},
181214
},
182215
}
183216
}

0 commit comments

Comments
 (0)