From 6e78d9316d24887979b98b0f732f6e8dbcbb2999 Mon Sep 17 00:00:00 2001 From: ap4y Date: Wed, 27 Nov 2019 09:42:50 +1300 Subject: [PATCH] Add support for NetworkPolicy - Disabled by default - Default policy allow all ingress traffic within a local namespace and from all pods in namespaces with label 'name=gitlab-managed-apps' --- README.md | 2 + templates/network-policy.yaml | 13 ++++ test/template_test.go | 102 ++++++++++++++++++++++++++++ test/testdata/custom-policy.yaml | 13 ++++ test/testdata/full-spec-policy.yaml | 17 +++++ values.yaml | 16 +++++ 6 files changed, 163 insertions(+) create mode 100644 templates/network-policy.yaml create mode 100644 test/testdata/custom-policy.yaml create mode 100644 test/testdata/full-spec-policy.yaml diff --git a/README.md b/README.md index f49af46..653e137 100644 --- a/README.md +++ b/README.md @@ -59,3 +59,5 @@ | podDisruptionBudget.maxUnavailable | | `1` | | podDisruptionBudget.minAvailable | If present, this variable will configure minAvailable in the PodDisruptionBudget. :warning: if you have `replicaCount: 1` and `podDisruptionBudget.minAvailable: 1` `kubectl drain` will be blocked. | `nil` | | prometheus.metrics | Annotates the service for prometheus auto-discovery. Also denies access to the `/metrics` endpoint from external addresses with Ingress. | `false` | +| networkPolicy.enabled | Enable container network policy | `false` | +| networkPolicy.spec | [Network policy](https://kubernetes.io/docs/concepts/services-networking/network-policies/) definition | `{ podSelector: { matchLabels: {} }, ingress: [{ from: [{ podSelector: { matchLabels: {} } }, { namespaceSelector: { matchLabels: { name: gitlab-managed-apps } } }] }] }` | diff --git a/templates/network-policy.yaml b/templates/network-policy.yaml new file mode 100644 index 0000000..79c0ed6 --- /dev/null +++ b/templates/network-policy.yaml @@ -0,0 +1,13 @@ +{{- if .Values.networkPolicy.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ template "fullname" . }} + labels: + app: {{ template "appname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: +{{ toYaml .Values.networkPolicy.spec | indent 2 }} +{{- end -}} diff --git a/test/template_test.go b/test/template_test.go index d725d72..bc93ea9 100644 --- a/test/template_test.go +++ b/test/template_test.go @@ -9,6 +9,7 @@ import ( "github.com/gruntwork-io/terratest/modules/random" "github.com/stretchr/testify/require" extensions "k8s.io/api/extensions/v1beta1" + netV1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -198,6 +199,107 @@ func TestWorkerDeploymentTemplate(t *testing.T) { } } +func TestNetworkPolicyDeployment(t *testing.T) { + releaseName := "network-policy-test" + templates := []string{"templates/network-policy.yaml"} + expectedLabels := map[string]string{ + "app": releaseName, + "chart": chartName, + "release": releaseName, + "heritage": "Tiller", + } + + tcs := []struct { + name string + valueFiles []string + values map[string]string + + meta metav1.ObjectMeta + podSelector metav1.LabelSelector + policyTypes []netV1.PolicyType + ingress []netV1.NetworkPolicyIngressRule + egress []netV1.NetworkPolicyEgressRule + }{ + { + name: "defaults", + }, + { + name: "with default policy", + values: map[string]string{"networkPolicy.enabled": "true"}, + meta: metav1.ObjectMeta{Name: releaseName + "-auto-deploy", Labels: expectedLabels}, + podSelector: metav1.LabelSelector{MatchLabels: map[string]string{}}, + ingress: []netV1.NetworkPolicyIngressRule{ + { + From: []netV1.NetworkPolicyPeer{ + {PodSelector: &metav1.LabelSelector{MatchLabels: map[string]string{}}}, + {NamespaceSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"name": "gitlab-managed-apps"}, + }}, + }, + }, + }, + }, + { + name: "with custom policy", + valueFiles: []string{"./testdata/custom-policy.yaml"}, + meta: metav1.ObjectMeta{Name: releaseName + "-auto-deploy", Labels: expectedLabels}, + podSelector: metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, + ingress: []netV1.NetworkPolicyIngressRule{ + { + From: []netV1.NetworkPolicyPeer{ + {PodSelector: &metav1.LabelSelector{MatchLabels: map[string]string{}}}, + {NamespaceSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"name": "foo"}, + }}, + }, + }, + }, + }, + { + name: "with full spec policy", + valueFiles: []string{"./testdata/full-spec-policy.yaml"}, + meta: metav1.ObjectMeta{Name: releaseName + "-auto-deploy", Labels: expectedLabels}, + podSelector: metav1.LabelSelector{MatchLabels: map[string]string{}}, + policyTypes: []netV1.PolicyType{"Ingress", "Egress"}, + ingress: []netV1.NetworkPolicyIngressRule{ + { + From: []netV1.NetworkPolicyPeer{ + {PodSelector: &metav1.LabelSelector{MatchLabels: map[string]string{}}}, + }, + }, + }, + egress: []netV1.NetworkPolicyEgressRule{ + { + To: []netV1.NetworkPolicyPeer{ + {NamespaceSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"name": "gitlab-managed-apps"}, + }}, + }, + }, + }, + }, + } + + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + opts := &helm.Options{ + ValuesFiles: tc.valueFiles, + SetValues: tc.values, + } + output := helm.RenderTemplate(t, opts, helmChartPath, releaseName, templates) + + policy := new(netV1.NetworkPolicy) + helm.UnmarshalK8SYaml(t, output, policy) + + require.Equal(t, tc.meta, policy.ObjectMeta) + require.Equal(t, tc.podSelector, policy.Spec.PodSelector) + require.Equal(t, tc.policyTypes, policy.Spec.PolicyTypes) + require.Equal(t, tc.ingress, policy.Spec.Ingress) + require.Equal(t, tc.egress, policy.Spec.Egress) + }) + } +} + type workerDeploymentTestCase struct { ExpectedName string ExpectedCmd []string diff --git a/test/testdata/custom-policy.yaml b/test/testdata/custom-policy.yaml new file mode 100644 index 0000000..8cc487a --- /dev/null +++ b/test/testdata/custom-policy.yaml @@ -0,0 +1,13 @@ +networkPolicy: + enabled: true + spec: + podSelector: + matchLabels: + foo: bar + ingress: + - from: + - podSelector: + matchLabels: {} + - namespaceSelector: + matchLabels: + name: foo diff --git a/test/testdata/full-spec-policy.yaml b/test/testdata/full-spec-policy.yaml new file mode 100644 index 0000000..25254b5 --- /dev/null +++ b/test/testdata/full-spec-policy.yaml @@ -0,0 +1,17 @@ +networkPolicy: + enabled: true + spec: + podSelector: + matchLabels: {} + policyTypes: + - Ingress + - Egress + ingress: + - from: + - podSelector: + matchLabels: {} + egress: + - to: + - namespaceSelector: + matchLabels: + name: gitlab-managed-apps diff --git a/values.yaml b/values.yaml index 9c6a834..7c21c34 100644 --- a/values.yaml +++ b/values.yaml @@ -83,6 +83,22 @@ podDisruptionBudget: # minAvailable: 1 maxUnavailable: 1 +## Configure NetworkPolicy +## ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/ +# +networkPolicy: + enabled: false + spec: + podSelector: + matchLabels: {} + ingress: + - from: + - podSelector: + matchLabels: {} + - namespaceSelector: + matchLabels: + name: gitlab-managed-apps + workers: {} # worker: # replicaCount: 1 -- GitLab