@@ -13,27 +13,39 @@ import (
1313 "sigs.k8s.io/controller-runtime/pkg/webhook/admission"
1414)
1515
16+ // +kubebuilder:object:generate=false
17+ type ProjectWebhook struct {
18+ client.Client
19+
20+ // Identity is the name of the entity (usually a service account) the project-workspace-operator uses to access the onboarding cluster.
21+ // It is required to exclude the operator's own identity from validation checks.
22+ Identity string
23+ OverrideName string
24+ }
25+
1626// log is for logging in this package.
1727var projectlog = logf .Log .WithName ("project-resource" )
1828
19- func (p * Project ) SetupWebhookWithManager (mgr ctrl.Manager , memberOverridesName string ) error {
29+ func (p * Project ) SetupWebhookWithManager (ctx context.Context , mgr ctrl.Manager , memberOverridesName , identity string ) error {
30+ pwh := & ProjectWebhook {
31+ Client : mgr .GetClient (),
32+ OverrideName : memberOverridesName ,
33+ Identity : identity ,
34+ }
2035
2136 return ctrl .NewWebhookManagedBy (mgr ).
22- For (& Project {}).
23- WithDefaulter (& Project {}).
24- WithValidator (& projectValidator {
25- Client : mgr .GetClient (),
26- overrideName : memberOverridesName ,
27- }).
37+ For (p ).
38+ WithDefaulter (pwh ).
39+ WithValidator (pwh ).
2840 Complete ()
2941}
3042
31- // +kubebuilder:webhook:path=/mutate-core-openmcp-cloud-v1alpha1-project,mutating=true,failurePolicy=fail,sideEffects=None,groups=core.openmcp.cloud,resources=projects,verbs=create;update,versions=v1alpha1,name=mproject.kb.io ,admissionReviewVersions=v1
43+ // +kubebuilder:webhook:path=/mutate-core-openmcp-cloud-v1alpha1-project,mutating=true,failurePolicy=fail,sideEffects=None,groups=core.openmcp.cloud,resources=projects,verbs=create;update,versions=v1alpha1,name=mproject.openmcp.cloud ,admissionReviewVersions=v1
3244
33- var _ webhook.CustomDefaulter = & Project {}
45+ var _ webhook.CustomDefaulter = & ProjectWebhook {}
3446
3547// Default implements webhook.CustomDefaulter so a webhook will be registered for the type
36- func (p * Project ) Default (ctx context.Context , obj runtime.Object ) error {
48+ func (p * ProjectWebhook ) Default (ctx context.Context , obj runtime.Object ) error {
3749 project , err := expectProject (obj )
3850 if err != nil {
3951 return err
@@ -50,30 +62,12 @@ func (p *Project) Default(ctx context.Context, obj runtime.Object) error {
5062 return nil
5163}
5264
53- // Project must implement webhook.CustomValidator in order for it's Mutating/Validating Webhook configuration to be generated by "github.com/openmcp-project/controller-utils/pkg/init/webhooks"
54- var _ webhook.CustomValidator = & Project {}
55-
56- func (p * Project ) ValidateCreate (ctx context.Context , obj runtime.Object ) (warnings admission.Warnings , err error ) {
57- return
58- }
59- func (p * Project ) ValidateUpdate (ctx context.Context , oldObj , newObj runtime.Object ) (warnings admission.Warnings , err error ) {
60- return
61- }
62- func (p * Project ) ValidateDelete (ctx context.Context , obj runtime.Object ) (warnings admission.Warnings , err error ) {
63- return
64- }
65-
66- // +kubebuilder:webhook:path=/validate-core-openmcp-cloud-v1alpha1-project,mutating=false,failurePolicy=fail,sideEffects=None,groups=core.openmcp.cloud,resources=projects,verbs=create;update;delete,versions=v1alpha1,name=vproject.kb.io,admissionReviewVersions=v1
67-
68- var _ webhook.CustomValidator = & projectValidator {}
65+ // +kubebuilder:webhook:path=/validate-core-openmcp-cloud-v1alpha1-project,mutating=false,failurePolicy=fail,sideEffects=None,groups=core.openmcp.cloud,resources=projects,verbs=create;update;delete,versions=v1alpha1,name=vproject.openmcp.cloud,admissionReviewVersions=v1
6966
70- type projectValidator struct {
71- client.Client
72- overrideName string
73- }
67+ var _ webhook.CustomValidator = & ProjectWebhook {}
7468
7569// ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type
76- func (v * projectValidator ) ValidateCreate (ctx context.Context , obj runtime.Object ) (warnings admission.Warnings , err error ) {
70+ func (v * ProjectWebhook ) ValidateCreate (ctx context.Context , obj runtime.Object ) (warnings admission.Warnings , err error ) {
7771 project , err := expectProject (obj )
7872 if err != nil {
7973 return
@@ -97,7 +91,7 @@ func (v *projectValidator) ValidateCreate(ctx context.Context, obj runtime.Objec
9791}
9892
9993// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type
100- func (v * projectValidator ) ValidateUpdate (ctx context.Context , oldObj , newObj runtime.Object ) (warnings admission.Warnings , err error ) {
94+ func (v * ProjectWebhook ) ValidateUpdate (ctx context.Context , oldObj , newObj runtime.Object ) (warnings admission.Warnings , err error ) {
10195 oldProject , err := expectProject (oldObj )
10296 if err != nil {
10397 return
@@ -138,7 +132,7 @@ func (v *projectValidator) ValidateUpdate(ctx context.Context, oldObj, newObj ru
138132}
139133
140134// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type
141- func (v * projectValidator ) ValidateDelete (ctx context.Context , obj runtime.Object ) (warnings admission.Warnings , err error ) {
135+ func (v * ProjectWebhook ) ValidateDelete (ctx context.Context , obj runtime.Object ) (warnings admission.Warnings , err error ) {
142136 project , err := expectProject (obj )
143137 if err != nil {
144138 return
@@ -160,21 +154,21 @@ func expectProject(obj runtime.Object) (*Project, error) {
160154 return project , nil
161155}
162156
163- func (v * projectValidator ) ensureValidRole (ctx context.Context , project * Project ) (bool , error ) {
157+ func (v * ProjectWebhook ) ensureValidRole (ctx context.Context , project * Project ) (bool , error ) {
164158 userInfo , err := userInfoFromContext (ctx )
165159 if err != nil {
166160 return false , fmt .Errorf ("failed to get userInfo" )
167161 }
168- if project .UserInfoHasRole (userInfo , ProjectRoleAdmin ) || isOwnServiceAccount ( userInfo ) {
162+ if project .UserInfoHasRole (userInfo , ProjectRoleAdmin ) || userInfo . Username == v . Identity {
169163 return true , nil
170164 }
171165
172- if v .overrideName == "" {
166+ if v .OverrideName == "" {
173167 return false , nil
174168 }
175169
176170 overrides := & MemberOverrides {}
177- if err := v .Get (ctx , types.NamespacedName {Name : v .overrideName }, overrides ); err != nil {
171+ if err := v .Get (ctx , types.NamespacedName {Name : v .OverrideName }, overrides ); err != nil {
178172 return false , err
179173 }
180174 if overrides .HasAdminOverrideForResource (& userInfo , project .Name , project .Kind ) {
0 commit comments