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

Commit cc462da

Browse files
committed
Better webhook structure
1 parent 273634d commit cc462da

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"
@@ -238,21 +236,24 @@ func (r *Reconciler) writeSingleton(ctx context.Context, inst *api.HNCConfigurat
238236
}
239237

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

243245
var rules []apiadmissionregistrationv1.RuleWithOperations
244-
for gr := range r.activeGVKMode {
246+
for g, res := range groups {
245247
rule := apiadmissionregistrationv1.RuleWithOperations{}
246-
rule.APIGroups = []string{gr.Group}
247-
rule.Resources = []string{gr.Resource}
248+
rule.APIGroups = []string{g}
249+
rule.Resources = res
248250
rule.APIVersions = []string{"*"}
249-
rule.Scope = &namespacedScope
250251
rule.Operations = []apiadmissionregistrationv1.OperationType{apiadmissionregistrationv1.Create, apiadmissionregistrationv1.Update, apiadmissionregistrationv1.Delete}
251252
rules = append(rules, rule)
252253
}
253254

254255
vwc := &apiadmissionregistrationv1.ValidatingWebhookConfiguration{}
255-
if err := r.Get(ctx, client.ObjectKey{Name: webhooks.ValidatingWebhookName}, vwc); err != nil {
256+
if err := r.Get(ctx, client.ObjectKey{Name: webhooks.ValidatingWebhookConfigurationName}, vwc); err != nil {
256257
if errors.IsNotFound(err) {
257258
// todo(erikgb): See if the tests can/should be bootstrapped with this webhook
258259
// Webhook not found; nothing to reconcile
@@ -262,49 +263,13 @@ func (r *Reconciler) syncObjectWebhookConfigs(ctx context.Context) error {
262263
}
263264
cleanVWC := vwc.DeepCopy()
264265

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

310275
// 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
@@ -45,10 +45,10 @@ func ManageCerts(mgr ctrl.Manager, setupFinished chan struct{}, restartOnSecretR
4545
IsReady: setupFinished,
4646
Webhooks: []cert.WebhookInfo{{
4747
Type: cert.Validating,
48-
Name: webhooks.ValidatingWebhookName,
48+
Name: webhooks.ValidatingWebhookConfigurationName,
4949
}, {
5050
Type: cert.Mutating,
51-
Name: webhooks.MutatingWebhookName,
51+
Name: webhooks.MutatingWebhookConfigurationName,
5252
}},
5353
RestartOnSecretRefresh: restartOnSecretRefresh,
5454
})

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)