Skip to content

Commit

Permalink
Don't deploy PSPs when PodSecurityPolicy plugin is disabled (#56)
Browse files Browse the repository at this point in the history
* Don't deploy PSPs if it's disabled in the shoot

* Always reconcile gvisor managedresource

* Fix unit tests
  • Loading branch information
shafeeqes authored Aug 23, 2022
1 parent d72a1e5 commit 00c4cce
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 44 deletions.
4 changes: 3 additions & 1 deletion charts/internal/gvisor/templates/psp-gvisor.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{{- if not .Values.pspDisabled }}
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
Expand All @@ -21,4 +22,5 @@ spec:
supplementalGroups:
rule: 'RunAsAny'
fsGroup:
rule: 'RunAsAny'
rule: 'RunAsAny'
{{- end }}
2 changes: 2 additions & 0 deletions charts/internal/gvisor/templates/rbac-gvisor.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{{- if not .Values.pspDisabled }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
Expand Down Expand Up @@ -25,3 +26,4 @@ subjects:
- kind: ServiceAccount
name: gvisor
namespace: kube-system
{{- end }}
4 changes: 3 additions & 1 deletion charts/internal/gvisor/values.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
config:
kubernetesVersion: 1.16.1
kubernetesVersion: 1.16.1

pspDisabled: false
3 changes: 2 additions & 1 deletion pkg/charts/charts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ var _ = Describe("Chart package test", func() {
"config": map[string]interface{}{
"kubernetesVersion": kubernetesVersion,
},
"pspDisabled": true,
}

mockChartRenderer.EXPECT().Render(gvisor.ChartPath, gvisor.ReleaseName, metav1.NamespaceSystem, gomock.Eq(renderedValues)).Return(&chartrenderer.RenderedChart{
Expand All @@ -82,7 +83,7 @@ var _ = Describe("Chart package test", func() {
},
}, nil)

_, err := charts.RenderGVisorChart(mockChartRenderer, kubernetesVersion)
_, err := charts.RenderGVisorChart(mockChartRenderer, kubernetesVersion, true)
Expect(err).NotTo(HaveOccurred())
})

Expand Down
5 changes: 3 additions & 2 deletions pkg/charts/values.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,14 @@ func RenderGVisorInstallationChart(renderer chartrenderer.Interface, cr *extensi
}

// RenderGVisorChart renders the gVisor chart
func RenderGVisorChart(renderer chartrenderer.Interface, kubernetesVersion string) ([]byte, error) {
func RenderGVisorChart(renderer chartrenderer.Interface, kubernetesVersion string, pspDisabled bool) ([]byte, error) {
configChartValues := map[string]interface{}{
"kubernetesVersion": kubernetesVersion,
}

gvisorChartValues := map[string]interface{}{
"config": configChartValues,
"config": configChartValues,
"pspDisabled": pspDisabled,
}

release, err := renderer.Render(gvisor.ChartPath, gvisor.ReleaseName, metav1.NamespaceSystem, gvisorChartValues)
Expand Down
54 changes: 23 additions & 31 deletions pkg/controller/actuator_reconcile.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,10 @@ import (
"github.com/go-logr/logr"

extensionscontroller "github.com/gardener/gardener/extensions/pkg/controller"
gardencorev1beta1helper "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper"
extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1"
resourcesv1alpha1 "github.com/gardener/gardener/pkg/apis/resources/v1alpha1"
kutil "github.com/gardener/gardener/pkg/utils/kubernetes"
"github.com/gardener/gardener/pkg/utils/managedresources/builder"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"sigs.k8s.io/controller-runtime/pkg/client"
)

Expand All @@ -49,48 +47,42 @@ func (a *actuator) Reconcile(ctx context.Context, log logr.Logger, cr *extension
return fmt.Errorf("could not create chart renderer for shoot '%s', %w", cr.Namespace, err)
}

// if the managed resource containing the prerequisites is not available yet, create it.
mr := &resourcesv1alpha1.ManagedResource{}
if err := a.client.Get(ctx, kutil.Key(cr.Namespace, GVisorManagedResourceName), mr); err != nil {
if !apierrors.IsNotFound(err) {
return err
}
log.Info("Preparing gVisor installation", "shoot", cluster.Shoot.Name, "shootNamespace", cluster.Shoot.Namespace)
// create MR containing the prerequisites for the installation DaemonSet
gVisorChart, err := charts.RenderGVisorChart(chartRenderer, cluster.Shoot.Spec.Kubernetes.Version)
if err != nil {
return err
}
log.Info("Preparing gVisor installation", "shoot", cluster.Shoot.Name, "shootNamespace", cluster.Shoot.Namespace)
// create MR containing the prerequisites for the installation DaemonSet
pspDisabled := gardencorev1beta1helper.IsPSPDisabled(cluster.Shoot)
gVisorChart, err := charts.RenderGVisorChart(chartRenderer, cluster.Shoot.Spec.Kubernetes.Version, pspDisabled)
if err != nil {
return err
}

secret, secretRefs := gvisorSecret(a.client, gVisorChart, cr.Namespace, GVisorSecretName)
if err := secret.Reconcile(ctx); err != nil {
return err
}
gvisorSecret, gvisorSecretRefs := buildSecret(a.client, gVisorChart, cr.Namespace, GVisorSecretName)
if err := gvisorSecret.Reconcile(ctx); err != nil {
return err
}

if err := builder.
NewManagedResource(a.client).
WithNamespacedName(cr.Namespace, GVisorManagedResourceName).
WithSecretRefs(secretRefs).
Reconcile(ctx); err != nil {
return fmt.Errorf("failed to create managed resource - prerequisite for the installation of gVisor, %w", err)
}
if err := builder.
NewManagedResource(a.client).
WithNamespacedName(cr.Namespace, GVisorManagedResourceName).
WithSecretRefs(gvisorSecretRefs).
Reconcile(ctx); err != nil {
return fmt.Errorf("failed to create managed resource - prerequisite for the installation of gVisor, %w", err)
}

log.Info("Installing gVisor", "shoot", cluster.Shoot.Name, "shootNamespace", cluster.Shoot.Namespace, "workerPoolName", cr.Spec.WorkerPool.Name)
gVisorChart, err := charts.RenderGVisorInstallationChart(chartRenderer, cr)
gVisorInstallationChart, err := charts.RenderGVisorInstallationChart(chartRenderer, cr)
if err != nil {
return err
}

secret, secretRefs := gvisorSecret(a.client, gVisorChart, cr.Namespace, fmt.Sprintf("%s-%s", GVisorInstallationSecretName, cr.Spec.WorkerPool.Name))
if err := secret.Reconcile(ctx); err != nil {
gVisorInstallationSecret, gVisorInstallationSecretRefs := buildSecret(a.client, gVisorInstallationChart, cr.Namespace, fmt.Sprintf("%s-%s", GVisorInstallationSecretName, cr.Spec.WorkerPool.Name))
if err := gVisorInstallationSecret.Reconcile(ctx); err != nil {
return err
}

return builder.
NewManagedResource(a.client).
WithNamespacedName(cr.Namespace, GetGVisorInstallationManagedResourceName(cr)).
WithSecretRefs(secretRefs).
WithSecretRefs(gVisorInstallationSecretRefs).
Reconcile(ctx)
}

Expand All @@ -107,7 +99,7 @@ func withLocalObjectRefs(refs ...string) []corev1.LocalObjectReference {
return localObjectRefs
}

func gvisorSecret(cl client.Client, gVisorConfig []byte, namespace, secretName string) (*builder.Secret, []corev1.LocalObjectReference) {
func buildSecret(cl client.Client, gVisorConfig []byte, namespace, secretName string) (*builder.Secret, []corev1.LocalObjectReference) {
return builder.NewSecret(cl).
WithKeyValues(map[string][]byte{charts.GVisorConfigKey: gVisorConfig}).
WithNamespacedName(namespace, secretName), withLocalObjectRefs(secretName)
Expand Down
30 changes: 22 additions & 8 deletions pkg/controller/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,6 @@ var _ = Describe("Chart package test", func() {
}

// ---------- gVisor Preparation -------------------
// mockClient retrieves extension-runtime-gvisor managed resource - not found
mockClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(errNotFound)
// chart renderer renders chart with path "gvisor"
chartRenderer.EXPECT().Render(gvisor.ChartPath, gvisor.ReleaseName, metav1.NamespaceSystem, gomock.Any()).Return(renderedChart, nil)
// mockClient creates or update secret for managed resource "extension-runtime-gvisor"
Expand Down Expand Up @@ -176,8 +174,27 @@ var _ = Describe("Chart package test", func() {
Manifests: []manifest.Manifest{{Content: manifestContent}},
}

// mockClient retrieves extension-runtime-gvisor managed resource - already exists
mockClient.EXPECT().Get(context.TODO(), gomock.Any(), gomock.Any()).Return(nil)
// ---------- gVisor Preparation -------------------
// chart renderer renders chart with path "gvisor"
mockChartRenderer.EXPECT().Render(gvisor.ChartPath, gvisor.ReleaseName, metav1.NamespaceSystem, gomock.Any()).Return(renderedChart, nil)
secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{Name: controller.GVisorSecretName, Namespace: namespaceName},
Data: map[string][]byte{charts.GVisorConfigKey: renderedChart.Manifest()},
Type: corev1.SecretTypeOpaque,
}
mockClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(errNotFound)
mockClient.EXPECT().Create(ctx, secret).Return(nil)
// Validate deployed managed resource "extension-runtime-gvisor"
managedResource := &resourcesv1alpha1.ManagedResource{
ObjectMeta: metav1.ObjectMeta{Name: controller.GVisorManagedResourceName, Namespace: namespaceName},
Spec: resourcesv1alpha1.ManagedResourceSpec{
SecretRefs: []corev1.LocalObjectReference{
{Name: controller.GVisorSecretName},
},
},
}
mockClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(errNotFound)
mockClient.EXPECT().Create(ctx, managedResource).Return(nil)

// ---------- gVisor Installation -------------------
mockChartRenderer.EXPECT().Render(gvisor.InstallationChartPath, gvisor.InstallationReleaseName, metav1.NamespaceSystem, gomock.Any()).Return(renderedChart, nil)
Expand Down Expand Up @@ -271,10 +288,7 @@ var _ = Describe("Chart package test", func() {
obj.(*resourcesv1alpha1.ManagedResource).ObjectMeta.DeletionTimestamp = &now
return nil
}
mockClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(managedResourceStillAvailable)
mockClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(managedResourceStillAvailable)
mockClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(managedResourceStillAvailable)
mockClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(managedResourceStillAvailable)
mockClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(managedResourceStillAvailable).Times(4)
mockClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(errNotFound)

// Create mock mockClient
Expand Down

0 comments on commit 00c4cce

Please sign in to comment.