diff --git a/docker/step-ca-badger/Dockerfile b/docker/step-ca-badger/Dockerfile new file mode 100644 index 0000000..92a9b5f --- /dev/null +++ b/docker/step-ca-badger/Dockerfile @@ -0,0 +1,38 @@ +# syntax=docker/dockerfile:1 + +## +## Build +## +FROM golang:1.18-buster AS build + +# Version must match the badger used by step-ca, see helm chart +# ca.db.type: badgerv2 +#ENV version=2.2007.4 +# defaults to version 1.6.2 +ENV version=1.6.2 +ENV CGO_ENABLED=0 + +WORKDIR /go/src/ +ADD . /go/src + +RUN curl https://github.com/dgraph-io/badger/archive/refs/tags/v$version.tar.gz -L -O + +RUN tar xf v$version.tar.gz +WORKDIR /go/src/badger-$version + +RUN go get github.com/dgraph-io/badger/v3 + +RUN go install + +WORKDIR /go/src/badger-$version/badger +RUN go build -o /badger + +## +## Runtime-image +## +FROM alpine:3.15.3 + +WORKDIR / + +COPY ./backup-restore.sh /usr/local/bin/backup-restore.sh +COPY --from=build /badger /usr/local/bin/badger diff --git a/docker/step-ca-badger/README.md b/docker/step-ca-badger/README.md new file mode 100644 index 0000000..11b7613 --- /dev/null +++ b/docker/step-ca-badger/README.md @@ -0,0 +1,34 @@ +# step-certificates-badger + +Image for backup/restore of Badger database running inside step-certificates pod. + +# Usage + +## Configuration + +Add init-container to step-certificates Statefulset: +``` +- name: {{ .Chart.Name }}-backuprestore + image: {{ .Values.image.backupRestoreRepository }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: ["/usr/local/bin/backup-restore.sh" ] + volumeMounts: + - name: database + mountPath: /home/step/db + readOnly: false +``` + +## Backup + +The init-container does a back-up of the Badger database every time the pod restarts. Note, Badger backup/restore does not operate on a database in use. + +The backup can be extracted by use of for example `kubectl cp :/home/step/db/backup/badger-db.bak badger-db.bak -c step-certificates -n ` or by using Kubernetes CSI `VolumeSnapshot`. + +A Kubernetes job or similar cronjob can schedule restart of the pod. + +## Restore + +Copy a backup file into the folder `/home/step/db/restore/badger-db.bak` inside the step-certicates pod and then restart the pod. +The init-container will take a backup of the existing database, remove existing database (all files in `/home/step/db`) and then restore the database. + + diff --git a/docker/step-ca-badger/backup-restore.sh b/docker/step-ca-badger/backup-restore.sh new file mode 100755 index 0000000..0070d3a --- /dev/null +++ b/docker/step-ca-badger/backup-restore.sh @@ -0,0 +1,23 @@ +#!/bin/sh -e + +export DB_HOME=/home/step/db +export RESTORE_FILE=$DB_HOME/restore/badger-db.bak + +mkdir -p $DB_HOME/backup +echo Backup of database +badger backup --dir $DB_HOME -f $DB_HOME/backup/badger-db.bak +echo Backup done. + +if [ -e $RESTORE_FILE ] +then + echo Found restore file. Starting restore of database + echo Remove old database if any + if [ -e $DB_HOME/*.vlog ] + then + rm $DB_HOME/* || true + fi + badger restore --dir $DB_HOME -f $RESTORE_FILE + # Move restore file after update of database to avoid restoring database more than once + mv $RESTORE_FILE $DB_HOME/restore/badger-db-restored.bak + echo "Restore done. Restore file moved to $DB_HOME/restore/badger-db-restored.bak" +fi \ No newline at end of file diff --git a/step-certificates/examples/backup_restore/values.yaml b/step-certificates/examples/backup_restore/values.yaml new file mode 100644 index 0000000..5e80128 --- /dev/null +++ b/step-certificates/examples/backup_restore/values.yaml @@ -0,0 +1,13 @@ + + +ca: + name: "demo" + db: + backupRestore: + badger: + enabled: true + + + +inject: + enabled: true \ No newline at end of file diff --git a/step-certificates/templates/ca.yaml b/step-certificates/templates/ca.yaml index 63eb040..5270382 100644 --- a/step-certificates/templates/ca.yaml +++ b/step-certificates/templates/ca.yaml @@ -26,13 +26,23 @@ spec: checksum/secret: {{ include (print $.Template.BasePath "/secrets.yaml") . | sha256sum }} {{- end }} spec: - {{- if and .Release.IsInstall (not (or .Values.inject.enabled .Values.existingSecrets.enabled )) }} initContainers: + {{- if and .Release.IsInstall (not (or .Values.inject.enabled .Values.existingSecrets.enabled )) }} - name: {{ .Chart.Name }}-init image: {{ .Values.image.initContainerRepository }} imagePullPolicy: {{ .Values.image.pullPolicy }} command: ["sleep", "20"] {{- end }} + {{- if and .Values.ca.db.enabled (hasKey .Values.ca.db.backupRestore "badger") }} + - name: {{ .Chart.Name }}-backuprestore + image: {{ .Values.image.backupRestoreRepository }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: ["/usr/local/bin/backup-restore.sh" ] + volumeMounts: + - name: database + mountPath: /home/step/db + readOnly: false + {{- end }} securityContext: {{- if .Values.ca.runAsRoot }} runAsUser: 0 diff --git a/step-certificates/values.yaml b/step-certificates/values.yaml index 11cc4de..3d5f125 100644 --- a/step-certificates/values.yaml +++ b/step-certificates/values.yaml @@ -17,6 +17,8 @@ fullnameOverride: "" image: repository: cr.step.sm/smallstep/step-ca initContainerRepository: busybox:latest + # TODO: update with proper image reference + backupRestoreRepository: badger:latest pullPolicy: IfNotPresent # Overrides the image tag whose default is the chart appVersion. tag: "" @@ -250,6 +252,8 @@ ca: db: # enabled defines if the database is enabled. enabled: true + # backup/restore of internal database + backupRestore: {} # persistent defines if a Persistent Volume Claim is used, if false and emptyDir will be used. persistent: true # storeageClass is Persistent Volume Storage Class