From bc428f7968089ad011c7e38477fb87bee79cde6f Mon Sep 17 00:00:00 2001 From: Timofey Titovets Date: Thu, 29 Jun 2023 17:50:58 +0200 Subject: [PATCH] feat(chart): store ssh keys in k8s secrets --- charts/k8s-ssh-bastion/Chart.yaml | 4 +- .../k8s-ssh-bastion/templates/deployment.yaml | 85 +++++++++++-------- charts/k8s-ssh-bastion/templates/jobs.yaml | 38 +++++++++ .../templates/role-binding.yaml | 12 +++ charts/k8s-ssh-bastion/templates/role.yaml | 12 +++ .../templates/service-account.yaml | 4 + charts/k8s-ssh-bastion/values.yaml | 2 - 7 files changed, 116 insertions(+), 41 deletions(-) create mode 100644 charts/k8s-ssh-bastion/templates/jobs.yaml create mode 100644 charts/k8s-ssh-bastion/templates/role-binding.yaml create mode 100644 charts/k8s-ssh-bastion/templates/role.yaml create mode 100644 charts/k8s-ssh-bastion/templates/service-account.yaml diff --git a/charts/k8s-ssh-bastion/Chart.yaml b/charts/k8s-ssh-bastion/Chart.yaml index 57dddad..a18821a 100644 --- a/charts/k8s-ssh-bastion/Chart.yaml +++ b/charts/k8s-ssh-bastion/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v1 -appVersion: 0.4.0 +appVersion: 0.4.1 description: A Helm chart for k8s bastion name: k8s-ssh-bastion -version: 0.4.0 +version: 0.5.0 diff --git a/charts/k8s-ssh-bastion/templates/deployment.yaml b/charts/k8s-ssh-bastion/templates/deployment.yaml index a67858d..cc17faa 100644 --- a/charts/k8s-ssh-bastion/templates/deployment.yaml +++ b/charts/k8s-ssh-bastion/templates/deployment.yaml @@ -23,18 +23,11 @@ spec: - /bin/bash - -ec - | - for file in /etc/ssh_origin/*; do - NAME=$(basename $file) - install -Dm0600 /etc/ssh_origin/$NAME /etc/ssh/$NAME - done - cd /etc/ssh - for key_type in dsa rsa ecdsa ed25519; do - lengh=4096 - [ $key_type == "dsa" ] && lengh=1024 - [ $key_type == "ecdsa" ] && lengh=256 - test -f ssh_host_${key_type}_key || \ - ssh-keygen -q -N "" -t ${key_type} -b $lengh -f ./ssh_host_${key_type}_key + for ssh_key in /etc/ssh/ssh_host_*_key; do + if [ ! -f ${ssh_key}.pub ]; then + ssh-keygen -y -f ${ssh_key} > ${ssh_key}.pub + fi done USER_UID=1000 @@ -56,6 +49,7 @@ spec: /usr/sbin/sshd -D -e -E /proc/1/fd/1 lifecycle: {{ .Values.lifecycle | toJson }} + resources: {{ .Values.resources | toJson }} ports: - name: ssh containerPort: 1022 @@ -63,14 +57,31 @@ spec: volumeMounts: - name: config-volume mountPath: /etc/users - - name: sshd-configs-persistent - mountPath: /etc/ssh - - name: sshd-configs-origin - mountPath: /etc/ssh_origin - name: usr-share-initscripts mountPath: /usr/share/initscripts - resources: -{{ toYaml .Values.resources | indent 12 }} + {{- range $key, $value := .Values.ssh }} + - name: sshd-configs + mountPath: /etc/ssh/{{ $key }} + subPath: {{ $key }} + {{- end }} + - name: {{ .Release.Name }}-rsa + mountPath: /etc/ssh/ssh_host_rsa_key + subPath: ssh_host_rsa_key + - name: {{ .Release.Name }}-ecdsa + mountPath: /etc/ssh/ssh_host_ecdsa_key + subPath: ssh_host_ecdsa_key + - name: {{ .Release.Name }}-ed25519 + mountPath: /etc/ssh/ssh_host_ed25519_key + subPath: ssh_host_ed25519_key + - name: {{ .Release.Name }}-rsa + mountPath: /etc/ssh/ssh_host_rsa_key.pub + subPath: ssh_host_rsa_key.pub + - name: {{ .Release.Name }}-ecdsa + mountPath: /etc/ssh/ssh_host_ecdsa_key.pub + subPath: ssh_host_ecdsa_key.pub + - name: {{ .Release.Name }}-ed25519 + mountPath: /etc/ssh/ssh_host_ed25519_key.pub + subPath: ssh_host_ed25519_key.pub hostNetwork: {{ .Values.hostNetwork }} {{- with .Values.dnsConfig }} dnsConfig: {{ . | toJson }} @@ -86,16 +97,30 @@ spec: - name: config-volume configMap: name: {{ .Release.Name }} - - name: sshd-configs-persistent - persistentVolumeClaim: - claimName: {{ .Release.Name }}-etc-ssh - - name: sshd-configs-origin + - name: sshd-configs configMap: - name: {{ .Release.Name }}-etc-ssh-origin + name: {{ .Release.Name }}-etc-ssh + defaultMode: 0600 - name: usr-share-initscripts configMap: name: {{ .Release.Name }}-usr-share-initscripts defaultMode: 0755 + - name: {{ .Release.Name }}-dsa + secret: + secretName: {{ .Release.Name }}-dsa + defaultMode: 0600 + - name: {{ .Release.Name }}-rsa + secret: + secretName: {{ .Release.Name }}-rsa + defaultMode: 0600 + - name: {{ .Release.Name }}-ecdsa + secret: + secretName: {{ .Release.Name }}-ecdsa + defaultMode: 0600 + - name: {{ .Release.Name }}-ed25519 + secret: + secretName: {{ .Release.Name }}-ed25519 + defaultMode: 0600 --- apiVersion: v1 kind: ConfigMap @@ -108,7 +133,7 @@ data: apiVersion: v1 kind: ConfigMap metadata: - name: {{ .Release.Name }}-etc-ssh-origin + name: {{ .Release.Name }}-etc-ssh data: {{ tpl (toYaml .Values.ssh) $ | indent 2 }} @@ -120,17 +145,3 @@ metadata: name: {{ .Release.Name }}-usr-share-initscripts data: {{ tpl (toYaml .Values.initscripts) $ | indent 2 }} - ---- -# Used to store ssh host keys & other stuff -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: {{ .Release.Name }}-etc-ssh -spec: - storageClassName: "{{ .Values.storageClass }}" # Empty string must be explicitly set otherwise default StorageClass will be set - accessModes: - - ReadWriteMany - resources: - requests: - storage: 1Gi diff --git a/charts/k8s-ssh-bastion/templates/jobs.yaml b/charts/k8s-ssh-bastion/templates/jobs.yaml new file mode 100644 index 0000000..8d9c48d --- /dev/null +++ b/charts/k8s-ssh-bastion/templates/jobs.yaml @@ -0,0 +1,38 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: "{{ .Release.Name }}-{{ .Release.Revision }}" +spec: + ttlSecondsAfterFinished: 300 + template: + spec: + serviceAccountName: {{ .Release.Name }} + containers: + - name: ssh-keygen + image: "{{ .Values.image.repository }}:{{ tpl .Values.image.tag $ }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: + - /bin/bash + - -ec + - | + cd /etc/ssh + for key_type in rsa ecdsa ed25519; do + if kubectl -n k8s-bastion get secrets {{ .Release.Name }}-${key_type} -o name; then + continue + fi + lengh=4096 + [ $key_type == "ecdsa" ] && lengh=256 + test -f ssh_host_${key_type}_key || \ + ssh-keygen -q -N "" -t ${key_type} -b $lengh -f ./ssh_host_${key_type}_key + kubectl create secret generic {{ .Release.Name }}-${key_type} \ + --from-file=ssh_host_${key_type}_key=./ssh_host_${key_type}_key \ + --from-file=ssh_host_${key_type}_key.pub=./ssh_host_${key_type}_key.pub + done + volumeMounts: + - name: opt + mountPath: /etc/ssh + volumes: + - name: opt + emptyDir: {} + restartPolicy: Never + backoffLimit: 4 diff --git a/charts/k8s-ssh-bastion/templates/role-binding.yaml b/charts/k8s-ssh-bastion/templates/role-binding.yaml new file mode 100644 index 0000000..86c6f96 --- /dev/null +++ b/charts/k8s-ssh-bastion/templates/role-binding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ .Release.Name }} +subjects: + - kind: ServiceAccount + name: {{ .Release.Name }} + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ .Release.Name }} diff --git a/charts/k8s-ssh-bastion/templates/role.yaml b/charts/k8s-ssh-bastion/templates/role.yaml new file mode 100644 index 0000000..67212bb --- /dev/null +++ b/charts/k8s-ssh-bastion/templates/role.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ .Release.Name }} +rules: + - verbs: + - create + - get + apiGroups: + - '' + resources: + - secrets diff --git a/charts/k8s-ssh-bastion/templates/service-account.yaml b/charts/k8s-ssh-bastion/templates/service-account.yaml new file mode 100644 index 0000000..cb203d6 --- /dev/null +++ b/charts/k8s-ssh-bastion/templates/service-account.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Release.Name }} diff --git a/charts/k8s-ssh-bastion/values.yaml b/charts/k8s-ssh-bastion/values.yaml index 00d0648..5b411e0 100644 --- a/charts/k8s-ssh-bastion/values.yaml +++ b/charts/k8s-ssh-bastion/values.yaml @@ -54,8 +54,6 @@ topologySpreadConstraints: matchLabels: app.kubernetes.io/instance: "{{ .Release.Name }}" -storageClass: "efs" - initscripts: {} # install-tools.sh: | # #!/bin/bash