diff --git a/.github/workflows/test_k3s.yml b/.github/workflows/test_k3s.yml index 0a7f4aa..479270d 100644 --- a/.github/workflows/test_k3s.yml +++ b/.github/workflows/test_k3s.yml @@ -22,15 +22,44 @@ jobs: - k3s-version: "" k3s-channel: latest helm-version: "" + metrics-enabled: "true" + traefik-enabled: "true" + docker-enabled: "false" + + - k3s-version: "" + k3s-channel: latest + helm-version: "" + metrics-enabled: "false" + traefik-enabled: "false" + docker-enabled: "true" + - k3s-version: "" - k3s-channel: stable - helm-version: v3.9.0 + k3s-channel: latest + helm-version: "" + metrics-enabled: "true" + traefik-enabled: "true" + docker-enabled: "true" + - k3s-version: "" - k3s-channel: v1.21 - helm-version: v3.3.4 + k3s-channel: latest + helm-version: "" + metrics-enabled: "false" + traefik-enabled: "false" + docker-enabled: "false" + + - k3s-version: v1.20.15+k3s1 + k3s-channel: "" + helm-version: v3.5.0 + metrics-enabled: "true" + traefik-enabled: "true" + docker-enabled: "false" + - k3s-version: v1.20.15+k3s1 k3s-channel: "" helm-version: v3.5.0 + metrics-enabled: "false" + traefik-enabled: "false" + docker-enabled: "true" steps: - uses: actions/checkout@v3 @@ -41,11 +70,11 @@ jobs: k3s-version: ${{ matrix.k3s-version }} k3s-channel: ${{ matrix.k3s-channel }} helm-version: ${{ matrix.helm-version }} - metrics-enabled: true - traefik-enabled: true - docker-enabled: false + metrics-enabled: ${{ matrix.metrics-enabled }} + traefik-enabled: ${{ matrix.traefik-enabled }} + docker-enabled: ${{ matrix.docker-enabled }} - - name: Action's set outputs and env + - name: Verify action's outputs and env run: | echo "KUBECONFIG=${KUBECONFIG}" echo "kubeconfig=${{ steps.k3s.outputs.kubeconfig }}" @@ -88,9 +117,11 @@ jobs: kubectl version kubectl get storageclass kubectl get deploy,daemonset,pods --all-namespaces - # These options should be enabled - kubectl get --namespace kube-system deploy metrics-server - kubectl get --namespace kube-system deploy traefik + + - name: Information from docker + run: | + docker info + docker ps - name: Information from helm run: | @@ -102,64 +133,27 @@ jobs: exit 1 fi - - name: Install network policies test - run: helm install test-calico ./test-calico --wait - - - name: Run network policies test - run: helm test test-calico --logs - - # GitHub Action reference: https://github.com/jupyterhub/action-k8s-namespace-report - - name: Kubernetes namespace report - if: always() - uses: jupyterhub/action-k8s-namespace-report@v1 - with: - # NOTE: This modifies the kubeconfig's current context's default - # namespace as of v1.0.1... - namespace: kube-system - - test_install_k3s_options: - runs-on: ubuntu-latest - name: Test K3s options - steps: - - uses: actions/checkout@v3 - - name: Local action - id: k3s - uses: ./ - with: - k3s-version: "" - k3s-channel: "latest" - helm-version: "" - metrics-enabled: false - traefik-enabled: false - docker-enabled: true - - - name: Print kubectl info + - name: Verify deploy/metrics-server based on metrics-enabled input run: | - kubectl version - kubectl get deploy,daemonset,pods --all-namespaces - - - name: Print docker info - run: | - docker info - docker ps + kubectl get --namespace=kube-system deploy/metrics-server && enabled=true || enabled=false + if [[ "$enabled" != "${{ matrix.metrics-enabled }}" ]]; then + echo "ERROR: deploy/metrics-server detected or not, which broke an assumption" + exit 1 + fi - - name: Verify metrics-server and traefik is installed + - name: Verify deploy/traefik based on traefik-enabled input run: | - kubectl get --namespace kube-system deploy metrics-server || ret=$? - if [ $ret -eq 0 ]; then - echo "ERROR: metrics-server should be disabled" - exit 1 - fi - kubectl get --namespace kube-system deploy traefik || ret=$? - if [ $ret -eq 0 ]; then - echo "ERROR: traefik should be disabled" - exit 1 + kubectl get --namespace=kube-system deploy/traefik && enabled=true || enabled=false + if [[ "$enabled" != "${{ matrix.traefik-enabled }}" ]]; then + echo "ERROR: deploy/traefik detected or not, which broke an assumption" + exit 1 fi # When using `docker-enabled: true` locally built images with docker # should be available without loading them for use by the k3s CRI. # - name: Verify local image is available for the k8s cluster + if: matrix.docker-enabled == 'true' run: | docker pull busybox:latest docker tag busybox:latest jupyterhub/action-k3s-helm:available-locally @@ -178,8 +172,14 @@ jobs: kubectl wait pod image-available-locally --for condition=Ready --timeout=30s + - name: Install netpol enforcement test chart + run: helm install test-netpol-enforcement ./test-netpol-enforcement --wait + + - name: Run netpol enforcement test chart's tests + run: helm test test-netpol-enforcement --logs + # ref: https://github.com/jupyterhub/action-k8s-namespace-report - - name: Kubernetes namespace report + - name: Kubernetes namespace report (kube-system) uses: jupyterhub/action-k8s-namespace-report@v1 if: always() with: @@ -194,14 +194,12 @@ jobs: # protection rules instead of having to list each matrix job # https://github.community/t/status-check-for-a-matrix-jobs/127354/7 status_all: - if: ${{ always() }} - runs-on: ubuntu-latest name: Status matrix Test - needs: - - test_install_k3s - - test_install_k3s_options + if: always() + runs-on: ubuntu-latest + needs: [test_install_k3s] steps: - name: Check build matrix status - if: needs.test_install_k3s.result != 'success' || needs.test_install_k3s_options.result != 'success' + if: needs.test_install_k3s.result != 'success' run: exit 1 diff --git a/test-calico/Chart.yaml b/test-calico/Chart.yaml deleted file mode 100644 index 671a20d..0000000 --- a/test-calico/Chart.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -apiVersion: v2 -name: test-calico -description: A Helm chart for Kubernetes -type: application -version: 0.1.0 -appVersion: 1.16.0 diff --git a/test-calico/templates/deployment.yaml b/test-calico/templates/deployment.yaml deleted file mode 100644 index 0cf811a..0000000 --- a/test-calico/templates/deployment.yaml +++ /dev/null @@ -1,35 +0,0 @@ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: test-calico - labels: - app.kubernetes.io/name: test-calico -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: test-calico - template: - metadata: - labels: - app.kubernetes.io/name: test-calico - test-calico-access: protected - spec: - serviceAccountName: test-calico - containers: - - name: test-calico - image: "nginx:{{ .Chart.AppVersion }}" - imagePullPolicy: IfNotPresent - ports: - - name: http - containerPort: 80 - protocol: TCP - livenessProbe: - httpGet: - path: / - port: http - readinessProbe: - httpGet: - path: / - port: http diff --git a/test-calico/templates/networkpolicy.yaml b/test-calico/templates/networkpolicy.yaml deleted file mode 100644 index fcd7571..0000000 --- a/test-calico/templates/networkpolicy.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# https://docs.projectcalico.org/security/tutorials/kubernetes-policy-basic ---- -kind: NetworkPolicy -apiVersion: networking.k8s.io/v1 -metadata: - name: default-deny -spec: - podSelector: - matchLabels: {} - ---- -kind: NetworkPolicy -apiVersion: networking.k8s.io/v1 -metadata: - name: access-nginx -spec: - podSelector: - matchLabels: - test-calico-access: protected - ingress: - - from: - - podSelector: - matchLabels: - test-calico-access: allowed diff --git a/test-calico/templates/service.yaml b/test-calico/templates/service.yaml deleted file mode 100644 index 0be4c1c..0000000 --- a/test-calico/templates/service.yaml +++ /dev/null @@ -1,16 +0,0 @@ ---- -apiVersion: v1 -kind: Service -metadata: - name: test-calico - labels: - app.kubernetes.io/name: test-calico -spec: - type: ClusterIP - ports: - - port: 80 - targetPort: http - protocol: TCP - name: http - selector: - app.kubernetes.io/name: test-calico diff --git a/test-calico/templates/serviceaccount.yaml b/test-calico/templates/serviceaccount.yaml deleted file mode 100644 index ab34fe0..0000000 --- a/test-calico/templates/serviceaccount.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: test-calico - labels: - app.kubernetes.io/name: test-calico diff --git a/test-calico/templates/tests/test-connection.yaml b/test-calico/templates/tests/test-connection.yaml deleted file mode 100644 index 37d59f8..0000000 --- a/test-calico/templates/tests/test-connection.yaml +++ /dev/null @@ -1,41 +0,0 @@ ---- -apiVersion: v1 -kind: Pod -metadata: - name: "test-calico-test-allowed" - labels: - app.kubernetes.io/name: test-calico - test-calico-access: allowed - annotations: - "helm.sh/hook": test-success -spec: - containers: - - name: wget - image: busybox - command: ["wget"] - args: ["-T5", "test-calico:80"] - restartPolicy: Never - ---- -apiVersion: v1 -kind: Pod -metadata: - name: "test-calico-test-blocked" - labels: - app.kubernetes.io/name: test-calico - test-calico-access: blocked - annotations: - "helm.sh/hook": test-success -spec: - containers: - - name: wget - image: busybox - command: ["sh"] - args: [ - "-c", - "if wget -T5 test-calico:80; then - echo FAIL: should be blocked; - exit 1; - fi", - ] - restartPolicy: Never diff --git a/test-netpol-enforcement/Chart.yaml b/test-netpol-enforcement/Chart.yaml new file mode 100644 index 0000000..5fa5646 --- /dev/null +++ b/test-netpol-enforcement/Chart.yaml @@ -0,0 +1,4 @@ +apiVersion: v2 +name: test-netpol-enforcement +version: 0.1.0 +appVersion: 1.16.0 diff --git a/test-netpol-enforcement/templates/deployment.yaml b/test-netpol-enforcement/templates/deployment.yaml new file mode 100644 index 0000000..d92e5aa --- /dev/null +++ b/test-netpol-enforcement/templates/deployment.yaml @@ -0,0 +1,25 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: protected-webserver +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: protected-webserver + template: + metadata: + labels: + app.kubernetes.io/name: protected-webserver + spec: + containers: + - name: nginx + image: "nginx:{{ .Chart.AppVersion }}" + ports: + - name: http + containerPort: 80 + readinessProbe: + httpGet: + path: / + port: http diff --git a/test-netpol-enforcement/templates/networkpolicy.yaml b/test-netpol-enforcement/templates/networkpolicy.yaml new file mode 100644 index 0000000..8c731be --- /dev/null +++ b/test-netpol-enforcement/templates/networkpolicy.yaml @@ -0,0 +1,22 @@ +# This network policy targets the protected-webserver pod with regards to +# ingress, thereby disallowing all inbound network connections unless allowed by +# a rule. We provide one such rule, allowing access to the protected-webserer +# from pods with a certain label. +# +# Two different pods will attempt to connect to the protected-webserver, one +# with the label and one without, and we expect different results based on this +# network policy. +# +kind: NetworkPolicy +apiVersion: networking.k8s.io/v1 +metadata: + name: allow-ingress-from-labelled-pods +spec: + podSelector: + matchLabels: + app.kubernetes.io/name: protected-webserver + ingress: + - from: + - podSelector: + matchLabels: + access-to-protected-webserver: "true" diff --git a/test-netpol-enforcement/templates/service.yaml b/test-netpol-enforcement/templates/service.yaml new file mode 100644 index 0000000..67ce1c9 --- /dev/null +++ b/test-netpol-enforcement/templates/service.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Service +metadata: + name: protected-webserver +spec: + type: ClusterIP + selector: + app.kubernetes.io/name: protected-webserver + ports: + - port: 80 + targetPort: http diff --git a/test-netpol-enforcement/templates/tests/test-netpol-enforcement.yaml b/test-netpol-enforcement/templates/tests/test-netpol-enforcement.yaml new file mode 100644 index 0000000..3b184ac --- /dev/null +++ b/test-netpol-enforcement/templates/tests/test-netpol-enforcement.yaml @@ -0,0 +1,42 @@ +--- +apiVersion: v1 +kind: Pod +metadata: + name: "test-allowed-access" + labels: + access-to-protected-webserver: "true" + annotations: + helm.sh/hook: test-success +spec: + restartPolicy: Never + containers: + - name: busybox + image: busybox + command: + - sh + - -c + - | + if ! wget -T5 protected-webserver:80; then + echo "FAIL: was not allowed, but should be allowed" + exit 1 + fi +--- +apiVersion: v1 +kind: Pod +metadata: + name: "test-not-allowed-access" + annotations: + helm.sh/hook: test-success +spec: + restartPolicy: Never + containers: + - name: busybox + image: busybox + command: + - sh + - -c + - | + if wget -T5 protected-webserver:80; then + echo "FAIL: was allowed, and shouldn't be allowed" + exit 1 + fi