From 1f6d8b451227bf0b95e1ffa242ff7cc0fb8d9fb2 Mon Sep 17 00:00:00 2001
From: Sheogorath <sheogorath@shivering-isles.com>
Date: Sun, 18 Feb 2024 23:56:20 +0100
Subject: [PATCH] feat(dashboard): Add Kubernetes dashboard

---
 .../dashboard/kubernetes-dashboard.yaml       | 397 ++++++++++++++++++
 infrastructure/dashboard/kustomization.yaml   |  12 +
 infrastructure/dashboard/namespace.yaml       |  12 +
 infrastructure/kustomization.yaml             |   1 +
 4 files changed, 422 insertions(+)
 create mode 100644 infrastructure/dashboard/kubernetes-dashboard.yaml
 create mode 100644 infrastructure/dashboard/kustomization.yaml
 create mode 100644 infrastructure/dashboard/namespace.yaml

diff --git a/infrastructure/dashboard/kubernetes-dashboard.yaml b/infrastructure/dashboard/kubernetes-dashboard.yaml
new file mode 100644
index 000000000..15bee85ab
--- /dev/null
+++ b/infrastructure/dashboard/kubernetes-dashboard.yaml
@@ -0,0 +1,397 @@
+# Copyright 2017 The Kubernetes Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+---
+
+################################
+### Service Accounts
+################################
+
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: kubernetes-dashboard
+  labels:
+    app.kubernetes.io/part-of: kubernetes-dashboard
+
+---
+
+################################
+### Secrets & Config Maps
+################################
+
+apiVersion: v1
+kind: Secret
+metadata:
+  name: kubernetes-dashboard-csrf
+  labels:
+    app.kubernetes.io/part-of: kubernetes-dashboard
+type: Opaque
+data:
+  csrf: ""
+
+---
+
+apiVersion: v1
+kind: Secret
+metadata:
+  name: kubernetes-dashboard-key-holder
+  labels:
+    app.kubernetes.io/part-of: kubernetes-dashboard
+type: Opaque
+
+---
+
+kind: ConfigMap
+apiVersion: v1
+metadata:
+  name: kubernetes-dashboard-settings
+  labels:
+    app.kubernetes.io/part-of: kubernetes-dashboard
+
+---
+
+################################
+### Roles & Bindings
+################################
+
+kind: Role
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: kubernetes-dashboard
+  labels:
+    app.kubernetes.io/part-of: kubernetes-dashboard
+rules:
+  # Allow Dashboard to get, update and delete Dashboard exclusive secrets.
+  - apiGroups: [ "" ]
+    resources: [ "secrets" ]
+    resourceNames: [ "kubernetes-dashboard-key-holder", "kubernetes-dashboard-csrf" ]
+    verbs: [ "get", "update", "delete" ]
+    # Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map.
+  - apiGroups: [ "" ]
+    resources: [ "configmaps" ]
+    resourceNames: [ "kubernetes-dashboard-settings" ]
+    verbs: [ "get", "update" ]
+    # Allow Dashboard to get metrics.
+  - apiGroups: [ "" ]
+    resources: [ "services/proxy" ]
+    resourceNames: [ "kubernetes-dashboard-metrics-scraper", "http:kubernetes-dashboard-metrics-scraper" ]
+    verbs: [ "get" ]
+
+---
+
+kind: ClusterRole
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: kubernetes-dashboard
+  labels:
+    app.kubernetes.io/part-of: kubernetes-dashboard
+rules:
+  # Allow Metrics Scraper to get metrics from the Metrics server
+  - apiGroups: [ "metrics.k8s.io" ]
+    resources: [ "pods", "nodes" ]
+    verbs: [ "get", "list", "watch" ]
+
+---
+
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+  name: kubernetes-dashboard
+  labels:
+    app.kubernetes.io/part-of: kubernetes-dashboard
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: Role
+  name: kubernetes-dashboard
+subjects:
+  - kind: ServiceAccount
+    name: kubernetes-dashboard
+---
+
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+  name: kubernetes-dashboard
+  labels:
+    app.kubernetes.io/part-of: kubernetes-dashboard
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: kubernetes-dashboard
+subjects:
+  - kind: ServiceAccount
+    name: kubernetes-dashboard
+---
+
+################################
+### Services & Ingresses
+################################
+
+kind: Service
+apiVersion: v1
+metadata:
+  name: kubernetes-dashboard-web
+  labels:
+    app.kubernetes.io/name: kubernetes-dashboard-web
+    app.kubernetes.io/part-of: kubernetes-dashboard
+    app.kubernetes.io/component: web
+    app.kubernetes.io/version: "v1.0.0"
+spec:
+  ports:
+    - name: web
+      port: 8000
+  selector:
+    app.kubernetes.io/name: kubernetes-dashboard-web
+    app.kubernetes.io/part-of: kubernetes-dashboard
+
+---
+
+kind: Service
+apiVersion: v1
+metadata:
+  name: kubernetes-dashboard-api
+  labels:
+    app.kubernetes.io/name: kubernetes-dashboard-api
+    app.kubernetes.io/part-of: kubernetes-dashboard
+    app.kubernetes.io/component: api
+    app.kubernetes.io/version: "v1.0.0"
+spec:
+  ports:
+    - name: api
+      port: 9000
+  selector:
+    app.kubernetes.io/name: kubernetes-dashboard-api
+    app.kubernetes.io/part-of: kubernetes-dashboard
+
+---
+
+kind: Service
+apiVersion: v1
+metadata:
+  name: kubernetes-dashboard-metrics-scraper
+  labels:
+    app.kubernetes.io/name: kubernetes-dashboard-metrics-scraper
+    app.kubernetes.io/part-of: kubernetes-dashboard
+    app.kubernetes.io/component: metrics
+    app.kubernetes.io/version: "v1.0.9"
+spec:
+  ports:
+    - port: 8000
+      targetPort: 8000
+  selector:
+    app.kubernetes.io/name: kubernetes-dashboard-metrics-scraper
+    app.kubernetes.io/part-of: kubernetes-dashboard
+
+---
+
+kind: Ingress
+apiVersion: networking.k8s.io/v1
+metadata:
+  name: kubernetes-dashboard
+  labels:
+    app.kubernetes.io/name: nginx-ingress
+    app.kubernetes.io/part-of: kubernetes-dashboard
+  annotations:
+    nginx.ingress.kubernetes.io/ssl-redirect: "true"
+    cert-manager.io/cluster-issuer: letsencrypt
+spec:
+  ingressClassName: nginx
+  tls:
+    - hosts:
+        - localhost
+      secretName: kubernetes-dashboard-certs
+  rules:
+    - host: localhost
+      http:
+        paths:
+          - path: /
+            pathType: Prefix
+            backend:
+              service:
+                name: kubernetes-dashboard-web
+                port:
+                  name: web
+          - path: /api
+            pathType: Prefix
+            backend:
+              service:
+                name: kubernetes-dashboard-api
+                port:
+                  name: api
+
+---
+
+################################
+### Deployments
+################################
+
+kind: Deployment
+apiVersion: apps/v1
+metadata:
+  name: kubernetes-dashboard-api
+  labels:
+    app.kubernetes.io/name: kubernetes-dashboard-api
+    app.kubernetes.io/part-of: kubernetes-dashboard
+    app.kubernetes.io/component: api
+    app.kubernetes.io/version: "v1.0.0"
+spec:
+  replicas: 1
+  revisionHistoryLimit: 10
+  selector:
+    matchLabels:
+      app.kubernetes.io/name: kubernetes-dashboard-api
+      app.kubernetes.io/part-of: kubernetes-dashboard
+  template:
+    metadata:
+      labels:
+        app.kubernetes.io/name: kubernetes-dashboard-api
+        app.kubernetes.io/part-of: kubernetes-dashboard
+        app.kubernetes.io/component: api
+        app.kubernetes.io/version: "v1.0.0"
+    spec:
+      securityContext:
+        seccompProfile:
+          type: RuntimeDefault
+      containers:
+        - name: kubernetes-dashboard-api
+          image: docker.io/kubernetesui/dashboard-api:v1.0.0
+          imagePullPolicy: IfNotPresent
+          ports:
+            - containerPort: 9000
+              name: api
+              protocol: TCP
+          args:
+            - --enable-insecure-login
+            - --namespace=kubernetes-dashboard
+          volumeMounts:
+              # Create on-disk volume to store exec logs
+            - mountPath: /tmp
+              name: tmp-volume
+          securityContext:
+            allowPrivilegeEscalation: false
+            readOnlyRootFilesystem: true
+            runAsUser: 1001
+            runAsGroup: 2001
+      volumes:
+        - name: tmp-volume
+          emptyDir: {}
+      serviceAccountName: kubernetes-dashboard
+
+---
+
+kind: Deployment
+apiVersion: apps/v1
+metadata:
+  name: kubernetes-dashboard-web
+  labels:
+    app.kubernetes.io/name: kubernetes-dashboard-web
+    app.kubernetes.io/part-of: kubernetes-dashboard
+    app.kubernetes.io/component: web
+    app.kubernetes.io/version: "v1.0.0"
+spec:
+  replicas: 1
+  revisionHistoryLimit: 10
+  selector:
+    matchLabels:
+      app.kubernetes.io/name: kubernetes-dashboard-web
+      app.kubernetes.io/part-of: kubernetes-dashboard
+  template:
+    metadata:
+      labels:
+        app.kubernetes.io/name: kubernetes-dashboard-web
+        app.kubernetes.io/part-of: kubernetes-dashboard
+        app.kubernetes.io/component: web
+        app.kubernetes.io/version: "v1.0.0"
+    spec:
+      securityContext:
+        seccompProfile:
+          type: RuntimeDefault
+      containers:
+        - name: kubernetes-dashboard-web
+          image: docker.io/kubernetesui/dashboard-web:v1.0.0
+          imagePullPolicy: IfNotPresent
+          ports:
+            - containerPort: 8000
+              name: web
+              protocol: TCP
+          volumeMounts:
+              # Create on-disk volume to store exec logs
+            - mountPath: /tmp
+              name: tmp-volume
+          securityContext:
+            allowPrivilegeEscalation: false
+            readOnlyRootFilesystem: true
+            runAsUser: 1001
+            runAsGroup: 2001
+      volumes:
+        - name: tmp-volume
+          emptyDir: {}
+      serviceAccountName: kubernetes-dashboard
+
+---
+
+kind: Deployment
+apiVersion: apps/v1
+metadata:
+  name: kubernetes-dashboard-metrics-scraper
+  labels:
+    app.kubernetes.io/name: kubernetes-dashboard-metrics-scraper
+    app.kubernetes.io/part-of: kubernetes-dashboard
+    app.kubernetes.io/component: metrics
+    app.kubernetes.io/version: "v1.0.9"
+spec:
+  replicas: 1
+  revisionHistoryLimit: 10
+  selector:
+    matchLabels:
+      app.kubernetes.io/name: kubernetes-dashboard-metrics-scraper
+      app.kubernetes.io/part-of: kubernetes-dashboard
+  template:
+    metadata:
+      labels:
+        app.kubernetes.io/name: kubernetes-dashboard-metrics-scraper
+        app.kubernetes.io/part-of: kubernetes-dashboard
+        app.kubernetes.io/component: metrics
+        app.kubernetes.io/version: "v1.0.9"
+    spec:
+      securityContext:
+        seccompProfile:
+          type: RuntimeDefault
+      containers:
+        - name: kubernetes-dashboard-metrics-scraper
+          image: docker.io/kubernetesui/metrics-scraper:v1.0.9
+          imagePullPolicy: IfNotPresent
+          ports:
+            - containerPort: 8000
+              protocol: TCP
+          livenessProbe:
+            httpGet:
+              scheme: HTTP
+              path: /
+              port: 8000
+            initialDelaySeconds: 30
+            timeoutSeconds: 30
+          volumeMounts:
+            - mountPath: /tmp
+              name: tmp-volume
+          securityContext:
+            allowPrivilegeEscalation: false
+            readOnlyRootFilesystem: true
+            runAsUser: 1001
+            runAsGroup: 2001
+      volumes:
+        - name: tmp-volume
+          emptyDir: {}
+      serviceAccountName: kubernetes-dashboard
diff --git a/infrastructure/dashboard/kustomization.yaml b/infrastructure/dashboard/kustomization.yaml
new file mode 100644
index 000000000..f7f41fab4
--- /dev/null
+++ b/infrastructure/dashboard/kustomization.yaml
@@ -0,0 +1,12 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+namespace: dashboard-system
+resources:
+  - namespace.yaml
+  - kubernetes-dashboard.yaml
+  - ../../shared/networkpolicies/deny-by-default-ingress.yaml
+  - ../../shared/networkpolicies/allow-from-same-namespace.yaml
+  - ../../shared/networkpolicies/allow-from-ingress.yaml
+  
+commonLabels:
+  app.kubernetes.io/instance: kubernetes-dashboard
\ No newline at end of file
diff --git a/infrastructure/dashboard/namespace.yaml b/infrastructure/dashboard/namespace.yaml
new file mode 100644
index 000000000..669aa0e26
--- /dev/null
+++ b/infrastructure/dashboard/namespace.yaml
@@ -0,0 +1,12 @@
+apiVersion: v1
+kind: Namespace
+metadata:
+  name: dashboard-system
+  labels:
+    pod-security.kubernetes.io/audit: restricted
+    pod-security.kubernetes.io/enforce: restricted
+    pod-security.kubernetes.io/warn: restricted
+    pod-security.kubernetes.io/audit-version: v1.28
+    pod-security.kubernetes.io/enforce-version: v1.28
+    pod-security.kubernetes.io/warn-version: v1.28
+    kyverno.shivering-isles.com/class: "system"
diff --git a/infrastructure/kustomization.yaml b/infrastructure/kustomization.yaml
index bb3eab013..90de65edb 100644
--- a/infrastructure/kustomization.yaml
+++ b/infrastructure/kustomization.yaml
@@ -14,4 +14,5 @@ resources:
   - flux-system
   - postgres
   - redis
+  - dashboard
   - vpa
-- 
GitLab