Skip to content

Commit 91c7c50

Browse files
committed
Add webhook handling for k8s components when v1alpha1 dws are used
Duplicate code for checking RBAC for Kubernetes/OpenShift components to accomodate v1alpha1 DevWorkspaces as well. Signed-off-by: Angel Misevski <[email protected]>
1 parent 041a18c commit 91c7c50

File tree

2 files changed

+72
-2
lines changed

2 files changed

+72
-2
lines changed

webhook/workspace/handler/kubernetes.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"fmt"
1919
"strings"
2020

21+
dwv1 "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha1"
2122
dwv2 "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
2223
authv1 "k8s.io/api/authorization/v1"
2324
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -168,3 +169,64 @@ func getKubeLikeComponent(component *dwv2.Component) (*dwv2.K8sLikeComponent, er
168169
}
169170
return nil, fmt.Errorf("component does not specify kubernetes or openshift fields")
170171
}
172+
173+
func (h *WebhookHandler) validateKubernetesObjectPermissionsOnCreate_v1alpha1(ctx context.Context, req admission.Request, wksp *dwv1.DevWorkspace) error {
174+
kubeComponents := getKubeComponentsFromWorkspace_v1alpha1(wksp)
175+
for componentName, component := range kubeComponents {
176+
if component.Uri != "" {
177+
return fmt.Errorf("kubenetes components specified via URI are unsupported")
178+
}
179+
if component.Inlined == "" {
180+
return fmt.Errorf("kubernetes component does not define inlined content")
181+
}
182+
if err := h.validatePermissionsOnObject(ctx, req, componentName, component.Inlined); err != nil {
183+
return err
184+
}
185+
}
186+
return nil
187+
}
188+
189+
func (h *WebhookHandler) validateKubernetesObjectPermissionsOnUpdate_v1alpha1(ctx context.Context, req admission.Request, newWksp, oldWksp *dwv1.DevWorkspace) error {
190+
newKubeComponents := getKubeComponentsFromWorkspace_v1alpha1(newWksp)
191+
oldKubeComponents := getKubeComponentsFromWorkspace_v1alpha1(oldWksp)
192+
193+
for componentName, newComponent := range newKubeComponents {
194+
if newComponent.Uri != "" {
195+
return fmt.Errorf("kubenetes components specified via URI are unsupported")
196+
}
197+
if newComponent.Inlined == "" {
198+
return fmt.Errorf("kubernetes component does not define inlined content")
199+
}
200+
201+
oldComponent, ok := oldKubeComponents[componentName]
202+
if !ok || oldComponent.Inlined != newComponent.Inlined {
203+
// Review new components
204+
if err := h.validatePermissionsOnObject(ctx, req, componentName, newComponent.Inlined); err != nil {
205+
return err
206+
}
207+
}
208+
}
209+
return nil
210+
}
211+
212+
func getKubeComponentsFromWorkspace_v1alpha1(wksp *dwv1.DevWorkspace) map[string]dwv1.K8sLikeComponent {
213+
kubeComponents := map[string]dwv1.K8sLikeComponent{}
214+
for _, component := range wksp.Spec.Template.Components {
215+
kubeComponent, err := getKubeLikeComponent_v1alpha1(&component)
216+
if err != nil {
217+
continue
218+
}
219+
kubeComponents[kubeComponent.Name] = *kubeComponent
220+
}
221+
return kubeComponents
222+
}
223+
224+
func getKubeLikeComponent_v1alpha1(component *dwv1.Component) (*dwv1.K8sLikeComponent, error) {
225+
if component.Kubernetes != nil {
226+
return &component.Kubernetes.K8sLikeComponent, nil
227+
}
228+
if component.Openshift != nil {
229+
return &component.Openshift.K8sLikeComponent, nil
230+
}
231+
return nil, fmt.Errorf("component does not specify kubernetes or openshift fields")
232+
}

webhook/workspace/handler/workspace.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import (
2929
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
3030
)
3131

32-
func (h *WebhookHandler) MutateWorkspaceV1alpha1OnCreate(_ context.Context, req admission.Request) admission.Response {
32+
func (h *WebhookHandler) MutateWorkspaceV1alpha1OnCreate(ctx context.Context, req admission.Request) admission.Response {
3333
wksp := &dwv1.DevWorkspace{}
3434
err := h.Decoder.Decode(req, wksp)
3535
if err != nil {
@@ -38,6 +38,10 @@ func (h *WebhookHandler) MutateWorkspaceV1alpha1OnCreate(_ context.Context, req
3838

3939
wksp.Labels = maputils.Append(wksp.Labels, constants.DevWorkspaceCreatorLabel, req.UserInfo.UID)
4040

41+
if err := h.validateKubernetesObjectPermissionsOnCreate_v1alpha1(ctx, req, wksp); err != nil {
42+
return admission.Denied(err.Error())
43+
}
44+
4145
return h.returnPatched(req, wksp)
4246
}
4347

@@ -65,7 +69,7 @@ func (h *WebhookHandler) MutateWorkspaceV1alpha2OnCreate(ctx context.Context, re
6569
return h.returnPatched(req, wksp)
6670
}
6771

68-
func (h *WebhookHandler) MutateWorkspaceV1alpha1OnUpdate(_ context.Context, req admission.Request) admission.Response {
72+
func (h *WebhookHandler) MutateWorkspaceV1alpha1OnUpdate(ctx context.Context, req admission.Request) admission.Response {
6973
newWksp := &dwv1.DevWorkspace{}
7074
oldWksp := &dwv1.DevWorkspace{}
7175
err := h.parse(req, oldWksp, newWksp)
@@ -82,6 +86,10 @@ func (h *WebhookHandler) MutateWorkspaceV1alpha1OnUpdate(_ context.Context, req
8286
return admission.Denied(msg)
8387
}
8488

89+
if err := h.validateKubernetesObjectPermissionsOnUpdate_v1alpha1(ctx, req, newWksp, oldWksp); err != nil {
90+
return admission.Denied(err.Error())
91+
}
92+
8593
oldCreator, found := oldWksp.Labels[constants.DevWorkspaceCreatorLabel]
8694
if !found {
8795
return admission.Denied(fmt.Sprintf("label '%s' is missing. Please recreate devworkspace to get it initialized", constants.DevWorkspaceCreatorLabel))

0 commit comments

Comments
 (0)