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

Commit 07a8a95

Browse files
committed
Better webhook structure
1 parent f04e447 commit 07a8a95

File tree

5 files changed

+20
-53
lines changed

5 files changed

+20
-53
lines changed

config/webhook/manifests.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ webhooks:
8484
- apiGroups:
8585
- rbac.authorization.k8s.io
8686
apiVersions:
87-
- v1
87+
- '*'
8888
operations:
8989
- CREATE
9090
- UPDATE

internal/hncconfig/reconciler.go

Lines changed: 12 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import (
1515
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1616
"k8s.io/apimachinery/pkg/runtime/schema"
1717
"k8s.io/apimachinery/pkg/types"
18-
"k8s.io/utils/pointer"
1918
ctrl "sigs.k8s.io/controller-runtime"
2019
"sigs.k8s.io/controller-runtime/pkg/client"
2120
"sigs.k8s.io/controller-runtime/pkg/event"
@@ -25,7 +24,6 @@ import (
2524

2625
api "sigs.k8s.io/hierarchical-namespaces/api/v1alpha2"
2726
"sigs.k8s.io/hierarchical-namespaces/internal/apimeta"
28-
"sigs.k8s.io/hierarchical-namespaces/internal/config"
2927
"sigs.k8s.io/hierarchical-namespaces/internal/crd"
3028
"sigs.k8s.io/hierarchical-namespaces/internal/forest"
3129
"sigs.k8s.io/hierarchical-namespaces/internal/objects"
@@ -241,21 +239,24 @@ func (r *Reconciler) writeSingleton(ctx context.Context, inst *api.HNCConfigurat
241239
}
242240

243241
func (r *Reconciler) syncObjectWebhookConfigs(ctx context.Context) error {
244-
namespacedScope := apiadmissionregistrationv1.NamespacedScope
242+
// Group GR by group
243+
groups := make(map[string][]string)
244+
for gr := range r.activeGVKMode {
245+
groups[gr.Group] = append(groups[gr.Group], gr.Resource)
246+
}
245247

246248
var rules []apiadmissionregistrationv1.RuleWithOperations
247-
for gr := range r.activeGVKMode {
249+
for g, res := range groups {
248250
rule := apiadmissionregistrationv1.RuleWithOperations{}
249-
rule.APIGroups = []string{gr.Group}
250-
rule.Resources = []string{gr.Resource}
251+
rule.APIGroups = []string{g}
252+
rule.Resources = res
251253
rule.APIVersions = []string{"*"}
252-
rule.Scope = &namespacedScope
253254
rule.Operations = []apiadmissionregistrationv1.OperationType{apiadmissionregistrationv1.Create, apiadmissionregistrationv1.Update, apiadmissionregistrationv1.Delete}
254255
rules = append(rules, rule)
255256
}
256257

257258
vwc := &apiadmissionregistrationv1.ValidatingWebhookConfiguration{}
258-
if err := r.Get(ctx, client.ObjectKey{Name: webhooks.ValidatingWebhookName}, vwc); err != nil {
259+
if err := r.Get(ctx, client.ObjectKey{Name: webhooks.ValidatingWebhookConfigurationName}, vwc); err != nil {
259260
if errors.IsNotFound(err) {
260261
// todo(erikgb): See if the tests can/should be bootstrapped with this webhook
261262
// Webhook not found; nothing to reconcile
@@ -265,49 +266,13 @@ func (r *Reconciler) syncObjectWebhookConfigs(ctx context.Context) error {
265266
}
266267
cleanVWC := vwc.DeepCopy()
267268

268-
webhookFound := false
269269
for i, wh := range vwc.Webhooks {
270-
if wh.Name == "objects.hnc.x-k8s.io" {
270+
if wh.Name == webhooks.ObjectsWebhookName {
271271
vwc.Webhooks[i].Rules = rules
272-
webhookFound = true
273-
break
272+
return r.Patch(ctx, vwc, client.MergeFrom(cleanVWC))
274273
}
275274
}
276-
if !webhookFound {
277-
failurePolicy := apiadmissionregistrationv1.Fail
278-
sideEffects := apiadmissionregistrationv1.SideEffectClassNone
279-
vw := apiadmissionregistrationv1.ValidatingWebhook{
280-
Name: "objects.hnc.x-k8s.io",
281-
ClientConfig: apiadmissionregistrationv1.WebhookClientConfig{
282-
Service: &apiadmissionregistrationv1.ServiceReference{
283-
Namespace: config.GetHNCNamespace(),
284-
Name: "webhook-service",
285-
Path: pointer.String("/validate-objects"),
286-
},
287-
},
288-
Rules: rules,
289-
FailurePolicy: &failurePolicy,
290-
SideEffects: &sideEffects,
291-
TimeoutSeconds: pointer.Int32(2),
292-
AdmissionReviewVersions: []string{"v1"},
293-
// We only apply this object validator on non-excluded namespaces, which have
294-
// the "included-namespace" label set by the HC reconciler, so that when HNC
295-
// (webhook service specifically) is down, operations in the excluded
296-
// namespaces won't be affected. Validators on HNC CRs are not filtered because
297-
// they are supposed to prevent abuse of HNC CRs in excluded namespaces.
298-
// Namespace validator is not filtered to prevent abuse of the included-namespace
299-
// label on excluded namespaces. Unfortunately, this means that when HNC is
300-
// down, we will block updates on all namespaces, even "excluded" ones, but
301-
// anyone who can update namespaces like `kube-system` should likely be able to
302-
// delete the VWHConfiguration to make the updates.
303-
NamespaceSelector: &metav1.LabelSelector{
304-
MatchLabels: map[string]string{"hnc.x-k8s.io/included-namespace": "true"},
305-
},
306-
}
307-
vwc.Webhooks = append(vwc.Webhooks, vw)
308-
}
309-
310-
return r.Patch(ctx, vwc, client.MergeFrom(cleanVWC))
275+
return fmt.Errorf("webhook %q not found in ValidatingWebhookConfiguration %q", webhooks.ObjectsWebhookName, webhooks.ValidatingWebhookConfigurationName)
311276
}
312277

313278
// syncObjectReconcilers creates or syncs ObjectReconcilers.

internal/objects/validator.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ const (
3636
// down, all further changes are forbidden. The initial webhook configuration contains
3737
// just enforced types, and will be dynamically updated when reconciling the HNC configuration.
3838
//
39-
// +kubebuilder:webhook:admissionReviewVersions=v1,path=/validate-objects,mutating=false,failurePolicy=fail,groups="rbac.authorization.k8s.io",resources=roles;rolebindings,sideEffects=None,verbs=create;update;delete,versions=v1,name=objects.hnc.x-k8s.io
39+
// +kubebuilder:webhook:admissionReviewVersions=v1,path=/validate-objects,mutating=false,failurePolicy=fail,groups="rbac.authorization.k8s.io",resources=roles;rolebindings,sideEffects=None,verbs=create;update;delete,versions="*",name=objects.hnc.x-k8s.io
4040

4141
type Validator struct {
4242
Log logr.Logger

internal/setup/webhooks.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,10 @@ func ManageCerts(mgr ctrl.Manager, setupFinished chan struct{}, restartOnSecretR
4848
IsReady: setupFinished,
4949
Webhooks: []cert.WebhookInfo{{
5050
Type: cert.Validating,
51-
Name: webhooks.ValidatingWebhookName,
51+
Name: webhooks.ValidatingWebhookConfigurationName,
5252
}, {
5353
Type: cert.Mutating,
54-
Name: webhooks.MutatingWebhookName,
54+
Name: webhooks.MutatingWebhookConfigurationName,
5555
}},
5656
RestartOnSecretRefresh: restartOnSecretRefresh,
5757
})

internal/webhooks/webhooks.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@ import (
1515
)
1616

1717
const (
18-
ValidatingWebhookName = "hnc-validating-webhook-configuration"
19-
MutatingWebhookName = "hnc-mutating-webhook-configuration"
18+
ValidatingWebhookConfigurationName = "hnc-validating-webhook-configuration"
19+
MutatingWebhookConfigurationName = "hnc-mutating-webhook-configuration"
20+
21+
ObjectsWebhookName = "objects.hnc.x-k8s.io"
2022
)
2123

2224
// IsHNCServiceAccount is inspired by isGKServiceAccount from open-policy-agent/gatekeeper.

0 commit comments

Comments
 (0)