diff --git a/.github/tests/common.sh b/.github/tests/common.sh index d833cf68d..cead98833 100755 --- a/.github/tests/common.sh +++ b/.github/tests/common.sh @@ -82,6 +82,16 @@ while true; do done ) +common_test_file_exists () ( +count=20 +while true; do + if [ -f "$1" ]; then exit 0; fi + sleep 2 + count=$((count-1)) + [ $count -le 0 ] && exit 1 +done +) + # Used just for testing. You should provide your own values as described in the install instructions. common_test_your_values () { cat > /tmp/$$.example-your-values.yaml < spiffe-step-ssh-password.txt +step ca init --helm --deployment-type=Standalone --name='My CA' --dns spiffe-step-ssh.example.org --ssh --address :8443 --provisioner default --password-file spiffe-step-ssh-password.txt > spiffe-step-ssh-values.yaml +``` + +ingress-values.yaml +```yaml +global: + spiffe: + ingressControllerType: ingress-nginx +stepIngress: + enabled: true +fetchCA: + ingress: + enabled: true +``` + +```shell +helm upgrade --install spiffe-step-ssh . --set caPassword=`cat spiffe-step-ssh-password.txt` -f spiffe-step-ssh-values.yaml -f ingress-values.yaml --set trustDomain=example.org +``` + + + +## Parameters diff --git a/charts/spiffe-step-ssh/ci/default-values.yaml b/charts/spiffe-step-ssh/ci/default-values.yaml new file mode 100644 index 000000000..3fe430bd4 --- /dev/null +++ b/charts/spiffe-step-ssh/ci/default-values.yaml @@ -0,0 +1 @@ +trustDomain: example.org diff --git a/charts/spiffe-step-ssh/files/ssh_x5c.tpl b/charts/spiffe-step-ssh/files/ssh_x5c.tpl new file mode 100644 index 000000000..292bcdbc0 --- /dev/null +++ b/charts/spiffe-step-ssh/files/ssh_x5c.tpl @@ -0,0 +1,13 @@ +{{- if eq (len .AuthorizationCrt.URIs) 1 }} +{{- $san := printf "%s" (index .AuthorizationCrt.URIs 0) }} +{{- if hasPrefix "spiffe://@TRUST_DOMAIN@/@PREFIX@/" $san }} +{{- $name := trimPrefix "spiffe://@TRUST_DOMAIN@/@PREFIX@/" $san }} +{ + "type": {{ toJson .Type }}, + "keyId": {{ toJson $name }}, + "principals": [{{ toJson $name }}], + "extensions": {{ toJson .Extensions }}, + "criticalOptions": {{ toJson .CriticalOptions }} +} +{{- end }} +{{- end }} diff --git a/charts/spiffe-step-ssh/templates/NOTES.txt b/charts/spiffe-step-ssh/templates/NOTES.txt new file mode 100644 index 000000000..1a8bc499b --- /dev/null +++ b/charts/spiffe-step-ssh/templates/NOTES.txt @@ -0,0 +1,5 @@ +Installed {{ .Chart.Name }}… + +Configure your ssh clients with known_hosts file with: + +@cert-authority *.{{ .Values.trustDomain }} {{ .Values.inject.certificates.ssh_host_ca }} diff --git a/charts/spiffe-step-ssh/templates/_helpers.tpl b/charts/spiffe-step-ssh/templates/_helpers.tpl new file mode 100644 index 000000000..415702b0b --- /dev/null +++ b/charts/spiffe-step-ssh/templates/_helpers.tpl @@ -0,0 +1,83 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "spiffe-step-ssh.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "spiffe-step-ssh.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "spiffe-step-ssh.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "spiffe-step-ssh.labels" -}} +helm.sh/chart: {{ include "spiffe-step-ssh.chart" . }} +{{ include "spiffe-step-ssh.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "spiffe-step-ssh.selectorLabels" -}} +app.kubernetes.io/name: {{ include "spiffe-step-ssh.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "spiffe-step-ssh.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "spiffe-step-ssh.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* Takes in a dictionary with keys: + * global - the standard global object + * ingress - a standard format ingress config object +*/}} +{{- define "spiffe-step-ssh.ingress-controller-type" }} +{{- $type := "" }} +{{- if ne (len (dig "spiffe" "ingressControllerType" "" .global)) 0 }} +{{- $type = .global.spiffe.ingressControllerType }} +{{- else if ne .ingress.controllerType "" }} +{{- $type = .ingress.controllerType }} +{{- else if (dig "openshift" false .global) }} +{{- $type = "openshift" }} +{{- else }} +{{- $type = "other" }} +{{- end }} +{{- if not (has $type (list "ingress-nginx" "openshift" "other")) }} +{{- fail "Unsupported ingress controller type specified. Must be one of [ingress-nginx, openshift, other]" }} +{{- end }} +{{- $type }} +{{- end }} diff --git a/charts/spiffe-step-ssh/templates/config-configmap.yaml b/charts/spiffe-step-ssh/templates/config-configmap.yaml new file mode 100644 index 000000000..ef40ee7d6 --- /dev/null +++ b/charts/spiffe-step-ssh/templates/config-configmap.yaml @@ -0,0 +1,25 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "spiffe-step-ssh.fullname" . }}-config-deployment + labels: + {{- include "spiffe-step-ssh.labels" . | nindent 4 }} +data: + spiffe-helper.conf: | + agent_address = "/spiffe-workload-api/spire-agent.sock" + cmd = "sh" + cmd_args = "/config-deployment/update.sh" + cert_dir = "/certs" + svid_file_name = "tls.crt" + svid_key_file_name = "tls.key" + svid_bundle_file_name = "ca.pem" + add_intermediates_to_bundle = false + update.sh: | + #!/bin/sh + export ROOTS=$(base64 /certs/ca.pem | tr '\n' ' ' | sed 's/ //g') + echo Updating Roots to "$ROOTS" + cat /config/ca.json > /work/ca.json + yq e -i -ojson '.authority.provisioners |= map(select(.name == "x5c@spiffe").roots = env(ROOTS))' /work/ca.json + /helper/kubectl create configmap {{ include "spiffe-step-ssh.fullname" . }}-config -n "{{ .Release.Namespace }}" --from-file=/work/ca.json --from-file=/config/defaults.json --from-file=/config/ssh_x5c.tpl --dry-run=client -o yaml | /helper/kubectl apply -f - + /helper/kubectl rollout restart statefulset {{ include "spiffe-step-ssh.fullname" . }} -n "{{ .Release.Namespace }}" + echo $? diff --git a/charts/spiffe-step-ssh/templates/config-deployment.yaml b/charts/spiffe-step-ssh/templates/config-deployment.yaml new file mode 100644 index 000000000..e8b51333f --- /dev/null +++ b/charts/spiffe-step-ssh/templates/config-deployment.yaml @@ -0,0 +1,143 @@ +{{- $configSum := (include (print $.Template.BasePath "/config-configmap.yaml") . | sha256sum) }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "spiffe-step-ssh.fullname" . }}-config + labels: + {{- include "spiffe-step-ssh.labels" . | nindent 4 }} + app: spiffe-step-ssh + component: config +spec: + replicas: 1 + selector: + matchLabels: + {{- include "spiffe-step-ssh.selectorLabels" . | nindent 6 }} + app: spiffe-step-ssh + component: config + template: + metadata: + annotations: + checksum/config: {{ $configSum }} + {{- with .Values.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "spiffe-step-ssh.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + app: spiffe-step-ssh + component: config + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "spiffe-step-ssh.serviceAccountName" . }}-svc-config + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + initContainers: + - name: setup-volume-p1 + image: {{ template "spire-lib.image" (dict "image" .Values.busybox.image "global" .Values.global) }} + imagePullPolicy: {{ .Values.busybox.image.pullPolicy }} + command: + - sh + - -c + - 'cp -a /bin/busybox /helper' + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + volumeMounts: + - name: spiffe-helper + mountPath: /helper + resources: + {{- toYaml .Values.config.resources | nindent 12 }} + - name: setup-volume-p2 + image: {{ template "spire-lib.kubectl-image" (dict "appVersion" $.Chart.AppVersion "image" .Values.kubectl.image "global" .Values.global "KubeVersion" .Capabilities.KubeVersion.Version) }} + imagePullPolicy: {{ .Values.kubectl.image.pullPolicy }} + command: + - /helper/busybox + - sh + - -c + - '/helper/busybox cp -a /bin/kubectl /helper' + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + volumeMounts: + - name: spiffe-helper + mountPath: /helper + resources: + {{- toYaml .Values.config.resources | nindent 12 }} + - name: setup-volume-p3 + image: {{ template "spire-lib.image" (dict "image" .Values.spiffeHelper.image "global" .Values.global) }} + imagePullPolicy: {{ .Values.spiffeHelper.image.pullPolicy }} + command: + - /helper/busybox + - sh + - -c + - '/helper/busybox cp -a /spiffe-helper /helper && /helper/busybox rm -f /helper/busybox' + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + volumeMounts: + - name: spiffe-helper + mountPath: /helper + resources: + {{- toYaml .Values.config.resources | nindent 12 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: {{ template "spire-lib.image" (dict "image" .Values.yq.image "global" .Values.global) }} + imagePullPolicy: {{ .Values.yq.image.pullPolicy }} + command: + - /helper/spiffe-helper + - -config + - /config-deployment/spiffe-helper.conf + resources: + {{- toYaml .Values.config.resources | nindent 12 }} + volumeMounts: + - name: spiffe-helper + mountPath: /helper + readOnly: true + - name: config + mountPath: /config + readOnly: true + - name: config-deployment + mountPath: /config-deployment + readOnly: true + - name: certdir + mountPath: /certs + - name: spiffe-workload-api + mountPath: /spiffe-workload-api + readOnly: true + - name: workdir + mountPath: /work + volumes: + - name: spiffe-workload-api + csi: + driver: {{ .Values.csiDriver | quote }} + readOnly: true + - name: config-deployment + configMap: + name: {{ include "spiffe-step-ssh.fullname" . }}-config-deployment + - name: config + configMap: + name: {{ include "spiffe-step-ssh.fullname" . }}-config-raw + - name: certdir + emptyDir: {} + - name: spiffe-helper-config + emptyDir: {} + - name: spiffe-helper + emptyDir: {} + - name: workdir + emptyDir: {} + {{- with .Values.config.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.config.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.config.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/charts/spiffe-step-ssh/templates/config-role.yaml b/charts/spiffe-step-ssh/templates/config-role.yaml new file mode 100644 index 000000000..f44f1209b --- /dev/null +++ b/charts/spiffe-step-ssh/templates/config-role.yaml @@ -0,0 +1,41 @@ +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "spiffe-step-ssh.fullname" . }}-svc-config +rules: + - apiGroups: [""] + resources: [configmaps] + verbs: + - create + - apiGroups: [""] + resources: [configmaps] + resourceNames: [{{ include "spiffe-step-ssh.fullname" . }}-config] + verbs: + - get + - update + - patch + - apiGroups: ["apps"] + resources: [statefulsets] + resourceNames: [{{ include "spiffe-step-ssh.fullname" . }}] + verbs: + - get + - patch + - apiGroups: ["apps"] + resources: [deployments] + resourceNames: [{{ include "spiffe-step-ssh.fullname" . }}-fetchca] + verbs: + - get + - patch +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "spiffe-step-ssh.fullname" . }}-svc-config +subjects: + - kind: ServiceAccount + name: {{ include "spiffe-step-ssh.fullname" . }}-svc-config + namespace: {{ .Release.Namespace }} +roleRef: + kind: Role + name: {{ include "spiffe-step-ssh.fullname" . }}-svc-config + apiGroup: rbac.authorization.k8s.io diff --git a/charts/spiffe-step-ssh/templates/config-serviceaccount.yaml b/charts/spiffe-step-ssh/templates/config-serviceaccount.yaml new file mode 100644 index 000000000..6a1f67f59 --- /dev/null +++ b/charts/spiffe-step-ssh/templates/config-serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "spiffe-step-ssh.serviceAccountName" . }}-svc-config + labels: + {{- include "spiffe-step-ssh.labels" . | nindent 4 }} + component: config + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/spiffe-step-ssh/templates/fetchca-configmap.yaml b/charts/spiffe-step-ssh/templates/fetchca-configmap.yaml new file mode 100644 index 000000000..f17d62364 --- /dev/null +++ b/charts/spiffe-step-ssh/templates/fetchca-configmap.yaml @@ -0,0 +1,28 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "spiffe-step-ssh.fullname" . }}-fetchca + labels: + {{- include "spiffe-step-ssh.labels" . | nindent 4 }} +data: + spiffe-helper-init.conf: | + agent_address = "/spiffe-workload-api/spire-agent.sock" + cmd = "" + cmd_args = "" + cert_dir = "/certs" + svid_file_name = "tls.crt" + svid_key_file_name = "tls.key" + svid_bundle_file_name = "ca.pem" + add_intermediates_to_bundle = false + spiffe-helper-sidecar.conf: | + agent_address = "/spiffe-workload-api/spire-agent.sock" + cmd = "/busybox/busybox" + cmd_args = "sh /update.sh" + cert_dir = "/certs" + svid_file_name = "tls.crt" + svid_key_file_name = "tls.key" + svid_bundle_file_name = "ca.pem" + add_intermediates_to_bundle = false + update.sh: | + #!/bin/sh + /busybox/busybox kill -HUP `/busybox/busybox busybox cat /pid/pid` diff --git a/charts/spiffe-step-ssh/templates/fetchca-deployment.yaml b/charts/spiffe-step-ssh/templates/fetchca-deployment.yaml new file mode 100644 index 000000000..5114c1c98 --- /dev/null +++ b/charts/spiffe-step-ssh/templates/fetchca-deployment.yaml @@ -0,0 +1,182 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "spiffe-step-ssh.fullname" . }}-fetchca + labels: + {{- include "spiffe-step-ssh.labels" . | nindent 4 }} + app: spiffe-step-ssh + component: fetchca +spec: + {{- if not .Values.fetchCA.autoscaling.enabled }} + replicas: {{ .Values.fetchCA.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "spiffe-step-ssh.selectorLabels" . | nindent 6 }} + app: spiffe-step-ssh + component: fetchca + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "spiffe-step-ssh.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + app: spiffe-step-ssh + component: fetchca + spec: + shareProcessNamespace: true + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "spiffe-step-ssh.serviceAccountName" . }}-fetchca + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + initContainers: + - name: busybox-volume + image: {{ template "spire-lib.image" (dict "image" .Values.busybox.image "global" .Values.global) }} + imagePullPolicy: {{ .Values.busybox.image.pullPolicy }} + command: + - sh + - -c + - 'cp -a /bin/busybox /busybox' + volumeMounts: + - name: busybox + mountPath: /busybox + resources: + {{- toYaml .Values.fetchCA.spiffeHelper.resources | nindent 12 }} + - name: init-tls + image: {{ template "spire-lib.image" (dict "image" .Values.spiffeHelper.image "global" .Values.global) }} + imagePullPolicy: {{ .Values.spiffeHelper.image.pullPolicy }} + command: + - /spiffe-helper + - -config + - /etc/spiffe-helper.conf + - -daemon-mode=false + volumeMounts: + - name: spiffe-workload-api + mountPath: /spiffe-workload-api + readOnly: true + - name: config + mountPath: /etc/spiffe-helper.conf + subPath: spiffe-helper-init.conf + readOnly: true + - name: certs + mountPath: /certs + resources: + {{- toYaml .Values.fetchCA.spiffeHelper.resources | nindent 12 }} + containers: + - name: {{ .Chart.Name }}-fetchca + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: {{ template "spire-lib.image" (dict "image" .Values.nginx.image "global" .Values.global) }} + imagePullPolicy: {{ .Values.nginx.image.pullPolicy }} + command: + - /bin/sh + - -c + - | + echo $$$$ > /pid/pid + cat > /etc/nginx/conf.d/ssl.conf </dev/null /dev/null || true + kubectl delete ns spire-server 2>/dev/null || true + kubectl delete ns spire-system 2>/dev/null || true + + helm uninstall --namespace mysql spire-root-server 2>/dev/null || true + kubectl delete ns spire-root-server 2>/dev/null || true + fi +} + +trap 'EC=$? && trap - SIGTERM && teardown $EC' SIGINT SIGTERM EXIT + +echo Network interfaces: +ip a + +HIP="$(ip -4 addr show docker0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}')" + +echo "Picked IP ${HIP}" + +echo "${HIP} test.production.other" | sudo bash -c 'cat >> /etc/hosts' + +sudo adduser spiffe-test +sudo -u spiffe-test mkdir -p /home/spiffe-test/.ssh +sudo chown spiffe-test --recursive /home/spiffe-test +sudo -u spiffe-test ssh-keygen -t ed25519 -f /home/spiffe-test/.ssh/id_ed25519 -q -N "" +sudo -u spiffe-test chmod 600 /home/spiffe-test/.ssh/id_ed25519 +sudo -u spiffe-test cp /home/spiffe-test/.ssh/id_ed25519.pub /home/spiffe-test/.ssh/authorized_keys +sudo -u spiffe-test ssh -T -n -i /home/spiffe-test/.ssh/id_ed25519 spiffe-test@test.production.other hostname || echo Expected fail here + +# Update deps +helm dep up charts/spire-nested + +# List nodes +kubectl get nodes + +# Deploy an ingress controller +IP=$(kubectl get nodes chart-testing-control-plane -o go-template='{{ range .status.addresses }}{{ if eq .type "InternalIP" }}{{ .address }}{{ end }}{{ end }}') +helm upgrade --install ingress-nginx ingress-nginx --version "$VERSION_INGRESS_NGINX" --repo "$HELM_REPO_INGRESS_NGINX" \ + --namespace ingress-nginx \ + --create-namespace \ + --set "controller.extraArgs.enable-ssl-passthrough=,controller.admissionWebhooks.enabled=false,controller.service.type=ClusterIP,controller.service.externalIPs[0]=$IP" \ + --set controller.ingressClassResource.default=true \ + --wait + +# Test the ingress controller. Should 404 as there is no services yet. +common_test_url "$IP" + +kubectl get configmap -n kube-system coredns -o yaml | grep hosts || kubectl get configmap -n kube-system coredns -o yaml | sed "/ready/a\ hosts {\n fallthrough\n }" | kubectl apply -f - +kubectl get configmap -n kube-system coredns -o yaml | grep test.production.other || kubectl get configmap -n kube-system coredns -o yaml | sed "/hosts/a\ $IP oidc-discovery.production.other\n $IP spire-server.production.other\n $HIP test.production.other\n" | kubectl apply -f - +kubectl rollout restart -n kube-system deployment/coredns +kubectl rollout status -n kube-system -w --timeout=1m deploy/coredns + +helm upgrade --install --create-namespace --namespace spire-mgmt --values "${COMMON_TEST_YOUR_VALUES},${SCRIPTPATH}/root-values.yaml" \ + --wait spire charts/spire-nested \ + --set "global.spire.namespaces.create=true" \ + --set "global.spire.ingressControllerType=ingress-nginx" + +kubectl get pods -n spire-server +kubectl exec -it -n spire-server spire-external-server-0 -- spire-server entry create -parentID spiffe://production.other/spire/agent/http_challenge/test.production.other -spiffeID spiffe://production.other/sshd/test.production.other -selector systemd:id:spiffe-step-ssh@main.service + +ENTRIES="$(kubectl exec -i -n spire-server spire-external-server-0 -- spire-server entry show)" + +if [[ "${ENTRIES}" == "Found 0 entries" ]]; then + echo "${ENTRIES}" + exit 1 +fi + +kubectl get ingress -n spire-server + +echo "${IP} spire-server.production.other spiffe-step-ssh.production.other spiffe-step-ssh-fetchca.production.other" | sudo bash -c 'cat >> /etc/hosts' +echo Hosts: +cat /etc/hosts + +curl -L https://raw.githubusercontent.com/kfox1111/spire-examples/refs/heads/spiffe-step-ssh/examples/spiffe-step-ssh/scripts/demo.sh | sudo bash + +sudo mkdir -p /usr/libexec/spiffe-step-ssh +sudo mkdir -p /etc/systemd/system/sshd.service.d +sudo curl -L -o /usr/libexec/spiffe-step-ssh/update.sh https://raw.githubusercontent.com/kfox1111/spire-examples/refs/heads/spiffe-step-ssh/examples/spiffe-step-ssh/scripts/update.sh +sudo curl -L -o /etc/systemd/system/spiffe-step-ssh@.service https://raw.githubusercontent.com/kfox1111/spire-examples/refs/heads/spiffe-step-ssh/examples/spiffe-step-ssh/systemd/spiffe-step-ssh@.service +sudo curl -L -o /etc/systemd/system/spiffe-step-ssh-cleanup.service https://raw.githubusercontent.com/kfox1111/spire-examples/refs/heads/spiffe-step-ssh/examples/spiffe-step-ssh/systemd/spiffe-step-ssh-cleanup.service +sudo curl -L -o /etc/systemd/system/sshd.service.d/10-spiffe-step-ssh.conf https://raw.githubusercontent.com/kfox1111/spire-examples/refs/heads/spiffe-step-ssh/examples/spiffe-step-ssh/conf/10-spiffe-step-ssh.conf + +sudo mkdir -p /etc/spire/agent +sudo cp "${SCRIPTPATH}/spire-agent.conf" /etc/spire/agent/main.conf + +PASSWORD=$(openssl rand -base64 48) +echo "$PASSWORD" > spiffe-step-ssh-password.txt +step ca init --helm --deployment-type=Standalone --name='My CA' --dns spiffe-step-ssh.production.other --ssh --address :8443 --provisioner default --password-file spiffe-step-ssh-password.txt > spiffe-step-ssh-values.yaml + +# Start things up +sudo systemctl daemon-reload +sudo systemctl enable spire-agent@main +sudo systemctl start spire-agent@main + +pushd charts/spiffe-step-ssh +helm dep up +popd + +helm upgrade --install spiffe-step-ssh charts/spiffe-step-ssh --set caPassword="$(cat spiffe-step-ssh-password.txt)" -f spiffe-step-ssh-values.yaml -f "${SCRIPTPATH}/ingress-values.yaml" --set trustDomain=production.other --wait --timeout 10m + +# Is fetchca responding. +kubectl get configmap -n spire-system spire-bundle-downstream -o go-template='{{ index .data "bundle.crt" }}' > /tmp/ca.pem +cat /tmp/ca.pem +curl https://spiffe-step-ssh-fetchca.production.other -s --cacert /tmp/ca.pem + +sudo systemctl start spiffe-step-ssh@main + +# This is bad, but only for testing. Don't do this at home +sudo chmod 777 "/var/run/spiffe/" +sudo chmod 777 "/var/run/spiffe/step-ssh/" +sudo chmod 777 "/var/run/spiffe/step-ssh/main/" +common_test_file_exists "/var/run/spiffe/step-ssh/main/ssh_host_rsa_key-cert.pub" + +kubectl get configmap spiffe-step-ssh-certs -o 'go-template={{ index .data "ssh_host_ca_key.pub" }}' | sed '/^$/d; s/^/@cert-authority *.production.other /' | sudo -u spiffe-test dd of=/home/spiffe-test/.ssh/known_hosts +sudo -u spiffe-test cat /home/spiffe-test/.ssh/known_hosts + +sudo -u spiffe-test ssh -T -n -i /home/spiffe-test/.ssh/id_ed25519 spiffe-test@test.production.other hostname diff --git a/tests/integration/spiffe-step-ssh/spire-agent.conf b/tests/integration/spiffe-step-ssh/spire-agent.conf new file mode 100644 index 000000000..4c5a9f441 --- /dev/null +++ b/tests/integration/spiffe-step-ssh/spire-agent.conf @@ -0,0 +1,25 @@ +agent { + log_level = "DEBUG" + trust_domain = "production.other" + server_address = "spire-server.production.other" + server_port = 443 + # Insecure bootstrap is NOT appropriate for production use but is ok for + # simple testing/evaluation purposes. + insecure_bootstrap = true +} +plugins { + KeyManager "disk" { + plugin_data { + directory = "./" + } + } + NodeAttestor "http_challenge" { + plugin_data { + hostname = "test.production.other" + port = 81 + } + } + WorkloadAttestor "systemd" { + plugin_data {} + } +}