From 7c2a3488ab5ccccca094f3da1a6363bcc5acfc85 Mon Sep 17 00:00:00 2001 From: Andreas Gruhler Date: Sat, 7 Sep 2024 16:57:54 +0200 Subject: [PATCH 01/10] feat: bump vault version to 1.16.3 Bump vault version to 1.16.3, the latest community release: https://github.com/hashicorp/vault/blob/main/CHANGELOG.md#1163 --- kubernetes/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kubernetes/Dockerfile b/kubernetes/Dockerfile index a766c0e..3821382 100644 --- a/kubernetes/Dockerfile +++ b/kubernetes/Dockerfile @@ -1,6 +1,6 @@ FROM alpine -ARG VAULT_VERSION=1.13.2 +ARG VAULT_VERSION=1.16.3 COPY vault-snapshot.sh / From 83514f9ddb0748c294a5129d55a3e702b71199d0 Mon Sep 17 00:00:00 2001 From: Andreas Gruhler Date: Sat, 7 Sep 2024 17:00:40 +0200 Subject: [PATCH 02/10] feat(kubernetes): add S3_EXPIRE_DAYS This adds the variable S3_EXPIRE_DAYS. The idea of this feature is to allow the script to prune expired snapshot files on the S3 compatible remote storage. Files are considered expired once they exceed the threshold defined by S3_EXPIRE_DAYS. This feature is usefull for S3 compatible storage where there exist no lifecycle rules to clean up the storage of expired or old files, such as: * cloudscale object storage * Exoscale simple object storage (SOS) It is recommended to also configure a "Governance" lock on the files, to ensure no files are deleted by accident before the defined S3_EXPIRE_DAYS threshold. --- kubernetes/README.md | 15 +++++++++++++++ kubernetes/cronjob.yaml | 3 +++ kubernetes/vault-snapshot.sh | 16 +++++++++++++++- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/kubernetes/README.md b/kubernetes/README.md index adf2b14..b95576b 100644 --- a/kubernetes/README.md +++ b/kubernetes/README.md @@ -15,5 +15,20 @@ After the snapshot is created in a temporary directory, `s3cmd` is used to sync * `S3_URI` - S3 URI to use to upload (s3://xxx) * `S3_BUCKET` - S3 bucket to point to * `S3_HOST` - S3 endpoint +* `S3_EXPIRE_DAYS` - Delete files older than this threshold (expired) * `AWS_ACCESS_KEY_ID` - Access key to use to access S3 * `AWS_SECRET_ACCESS_KEY` - Secret access key to use to access S3 + +## Configuration of file retention (pruning) + +With AWS S3, use [lifecycle +rules](https://docs.aws.amazon.com/AmazonS3/latest/userguide/lifecycle-expire-general-considerations.html) +to configure retention and automatic cleanup action (prune) for expired files. + +For other S3 compatible storage, ensure to set [Governance +lock](https://community.exoscale.com/documentation/storage/versioning/#set-up-the-lock-configuration-for-a-bucket) +to avoid any modification before `$S3_EXPIRE_DAYS`: + +``` +mc retention set --default GOVERNANCE "${S3_EXPIRE_DAYS}d" my-s3-remote/my-bucket +``` diff --git a/kubernetes/cronjob.yaml b/kubernetes/cronjob.yaml index a52ee49..0de469b 100644 --- a/kubernetes/cronjob.yaml +++ b/kubernetes/cronjob.yaml @@ -32,6 +32,9 @@ spec: value: bucketname - name: S3_URI value: s3://bucketname + # leave empty to retain snapshot files (default) + - name: S3_EXPIRE_DAYS + value: - name: VAULT_ROLE value: vault-snapshot - name: VAULT_ADDR diff --git a/kubernetes/vault-snapshot.sh b/kubernetes/vault-snapshot.sh index 3eca57e..fa02506 100644 --- a/kubernetes/vault-snapshot.sh +++ b/kubernetes/vault-snapshot.sh @@ -7,8 +7,22 @@ VAULT_TOKEN=$(vault write -field=token auth/kubernetes/login role="${VAULT_ROLE export VAULT_TOKEN # create snapshot - vault operator raft snapshot save /vault-snapshots/vault_"$(date +%F-%H%M)".snapshot # upload to s3 s3cmd put /vault-snapshots/* "${S3_URI}" --host="${S3_HOST}" --host-bucket="${S3_BUCKET}" + +# remove expired snapshots +if [ "${S3_EXPIRE_DAYS}" ]; then + s3cmd ls "${S3_URI}" --host="${S3_HOST}" --host-bucket="${S3_BUCKET}" | while read -r line; do + createDate=$(echo $line | awk {'print $1" "$2'}) + createDate=$(date -d"$createDate" +%s) + olderThan=$(date --date "${S3_EXPIRE_DAYS} days ago" +%s) + if [[ $createDate -lt $olderThan ]]; then + fileName=$(echo $line | awk {'print $4'}) + if [[ $fileName != "" ]]; then + s3cmd del "${S3_URI}/$fileName" --host="${S3_HOST}" --host-bucket="${S3_BUCKET}" + fi + fi + done; +fi From 570d8847f03f9fd4b71eef460d3b116fa7ec6770 Mon Sep 17 00:00:00 2001 From: Andreas Gruhler Date: Mon, 9 Sep 2024 09:17:13 +0200 Subject: [PATCH 03/10] doc: describe deletion marker --- kubernetes/README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/kubernetes/README.md b/kubernetes/README.md index b95576b..b34f24d 100644 --- a/kubernetes/README.md +++ b/kubernetes/README.md @@ -32,3 +32,13 @@ to avoid any modification before `$S3_EXPIRE_DAYS`: ``` mc retention set --default GOVERNANCE "${S3_EXPIRE_DAYS}d" my-s3-remote/my-bucket ``` + +On removal by the `vault-snapshot.sh` script, [`DEL` deletion marker +(tombstone)](https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-lock-managing.html#object-lock-managing-delete-markers) +is set: + +``` +mc ls --versions my-snapshots/vault-snapshots-2f848f +[2024-09-09 09:07:46 CEST] 0B X/1031980658232456253 v2 DEL vault_2024-09-06-1739.snapshot +[2024-09-06 19:39:49 CEST] 28KiB Standard 1031052557042383613 v1 PUT vault_2024-09-06-1739.snapshot +``` From e340c4ada6efe3dd4d17ccfa37ab48c29084c4f8 Mon Sep 17 00:00:00 2001 From: Andreas Gruhler Date: Mon, 9 Sep 2024 09:29:55 +0200 Subject: [PATCH 04/10] doc: describe undo --- kubernetes/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/kubernetes/README.md b/kubernetes/README.md index b34f24d..f357983 100644 --- a/kubernetes/README.md +++ b/kubernetes/README.md @@ -42,3 +42,12 @@ mc ls --versions my-snapshots/vault-snapshots-2f848f [2024-09-09 09:07:46 CEST] 0B X/1031980658232456253 v2 DEL vault_2024-09-06-1739.snapshot [2024-09-06 19:39:49 CEST] 28KiB Standard 1031052557042383613 v1 PUT vault_2024-09-06-1739.snapshot ``` + +Use [`mc +undo`](https://min.io/docs/minio/linux/reference/minio-mc/mc-undo.html) to undo +the `DEL` operation: +``` +mc undo my-snapshots/vault-snapshots-2f848f/vault_2024-09-06-1739.snapshot +mc ls --versions my-snapshots/vault-snapshots-2f848f +[2024-09-06 19:39:49 CEST] 28KiB Standard 1031052557042383613 v1 PUT vault_2024-09-06-1739.snapshot +``` From 44d1ca453c9e4264c06468355a09075940bb32e5 Mon Sep 17 00:00:00 2001 From: Andreas Gruhler Date: Mon, 9 Sep 2024 10:43:21 +0200 Subject: [PATCH 05/10] fix: shellcheck --- kubernetes/vault-snapshot.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kubernetes/vault-snapshot.sh b/kubernetes/vault-snapshot.sh index fa02506..cfbd4f9 100644 --- a/kubernetes/vault-snapshot.sh +++ b/kubernetes/vault-snapshot.sh @@ -15,12 +15,12 @@ s3cmd put /vault-snapshots/* "${S3_URI}" --host="${S3_HOST}" --host-bucket="${S3 # remove expired snapshots if [ "${S3_EXPIRE_DAYS}" ]; then s3cmd ls "${S3_URI}" --host="${S3_HOST}" --host-bucket="${S3_BUCKET}" | while read -r line; do - createDate=$(echo $line | awk {'print $1" "$2'}) + createDate=$(echo "$line" | awk '{print $1" "$2}') createDate=$(date -d"$createDate" +%s) olderThan=$(date --date "${S3_EXPIRE_DAYS} days ago" +%s) - if [[ $createDate -lt $olderThan ]]; then - fileName=$(echo $line | awk {'print $4'}) - if [[ $fileName != "" ]]; then + if [ $createDate -lt $olderThan ]; then + fileName=$(echo "$line" | awk '{print $4}') + if [ $fileName != "" ]; then s3cmd del "${S3_URI}/$fileName" --host="${S3_HOST}" --host-bucket="${S3_BUCKET}" fi fi From 56214a5fec98ef76ada7f75a8f25c41836336469 Mon Sep 17 00:00:00 2001 From: Andreas Gruhler Date: Mon, 9 Sep 2024 10:46:11 +0200 Subject: [PATCH 06/10] fix(shellcheck): double quotes --- kubernetes/vault-snapshot.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kubernetes/vault-snapshot.sh b/kubernetes/vault-snapshot.sh index cfbd4f9..dc29958 100644 --- a/kubernetes/vault-snapshot.sh +++ b/kubernetes/vault-snapshot.sh @@ -18,9 +18,9 @@ if [ "${S3_EXPIRE_DAYS}" ]; then createDate=$(echo "$line" | awk '{print $1" "$2}') createDate=$(date -d"$createDate" +%s) olderThan=$(date --date "${S3_EXPIRE_DAYS} days ago" +%s) - if [ $createDate -lt $olderThan ]; then + if [ "$createDate" -lt "$olderThan" ]; then fileName=$(echo "$line" | awk '{print $4}') - if [ $fileName != "" ]; then + if [ "$fileName" != "" ]; then s3cmd del "${S3_URI}/$fileName" --host="${S3_HOST}" --host-bucket="${S3_BUCKET}" fi fi From 1e3ad4545921013986589b4e3f52d8340f64dcb4 Mon Sep 17 00:00:00 2001 From: Andreas Gruhler Date: Thu, 12 Sep 2024 17:17:46 +0200 Subject: [PATCH 07/10] fix: busybox compatible date manipulation The date manipulation did not work in my tests with busybox on OpenShift. This should work even in the busybox environments. It simply subtracts seconds. --- kubernetes/vault-snapshot.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kubernetes/vault-snapshot.sh b/kubernetes/vault-snapshot.sh index dc29958..c37387d 100644 --- a/kubernetes/vault-snapshot.sh +++ b/kubernetes/vault-snapshot.sh @@ -17,7 +17,7 @@ if [ "${S3_EXPIRE_DAYS}" ]; then s3cmd ls "${S3_URI}" --host="${S3_HOST}" --host-bucket="${S3_BUCKET}" | while read -r line; do createDate=$(echo "$line" | awk '{print $1" "$2}') createDate=$(date -d"$createDate" +%s) - olderThan=$(date --date "${S3_EXPIRE_DAYS} days ago" +%s) + olderThan=$(date --date @$((`date +%s` - 86400*$S3_EXPIRE_DAYS)) +%s) if [ "$createDate" -lt "$olderThan" ]; then fileName=$(echo "$line" | awk '{print $4}') if [ "$fileName" != "" ]; then From 9823e9cf9a8579668d80d92dcd88404826c215b1 Mon Sep 17 00:00:00 2001 From: Andreas Gruhler Date: Thu, 12 Sep 2024 17:31:39 +0200 Subject: [PATCH 08/10] fix: shellcheck --- kubernetes/vault-snapshot.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kubernetes/vault-snapshot.sh b/kubernetes/vault-snapshot.sh index c37387d..dde567d 100644 --- a/kubernetes/vault-snapshot.sh +++ b/kubernetes/vault-snapshot.sh @@ -17,7 +17,7 @@ if [ "${S3_EXPIRE_DAYS}" ]; then s3cmd ls "${S3_URI}" --host="${S3_HOST}" --host-bucket="${S3_BUCKET}" | while read -r line; do createDate=$(echo "$line" | awk '{print $1" "$2}') createDate=$(date -d"$createDate" +%s) - olderThan=$(date --date @$((`date +%s` - 86400*$S3_EXPIRE_DAYS)) +%s) + olderThan=$(date --date @$(($(date +%s$) - 86400*$S3_EXPIRE_DAYS)) +%s) if [ "$createDate" -lt "$olderThan" ]; then fileName=$(echo "$line" | awk '{print $4}') if [ "$fileName" != "" ]; then From 63364616424d11cd641be376e98a9ab91be10f2a Mon Sep 17 00:00:00 2001 From: Andreas Gruhler Date: Thu, 12 Sep 2024 17:39:49 +0200 Subject: [PATCH 09/10] fix: shell syntax and filename --- kubernetes/vault-snapshot.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kubernetes/vault-snapshot.sh b/kubernetes/vault-snapshot.sh index dde567d..84f96bb 100644 --- a/kubernetes/vault-snapshot.sh +++ b/kubernetes/vault-snapshot.sh @@ -17,11 +17,11 @@ if [ "${S3_EXPIRE_DAYS}" ]; then s3cmd ls "${S3_URI}" --host="${S3_HOST}" --host-bucket="${S3_BUCKET}" | while read -r line; do createDate=$(echo "$line" | awk '{print $1" "$2}') createDate=$(date -d"$createDate" +%s) - olderThan=$(date --date @$(($(date +%s$) - 86400*$S3_EXPIRE_DAYS)) +%s) + olderThan=$(date --date @$(($(date +%s) - 86400*$S3_EXPIRE_DAYS)) +%s) if [ "$createDate" -lt "$olderThan" ]; then fileName=$(echo "$line" | awk '{print $4}') if [ "$fileName" != "" ]; then - s3cmd del "${S3_URI}/$fileName" --host="${S3_HOST}" --host-bucket="${S3_BUCKET}" + s3cmd del "$fileName" --host="${S3_HOST}" --host-bucket="${S3_BUCKET}" fi fi done; From b271d0d656787ac07acff5ee05cddeeeee4b3614 Mon Sep 17 00:00:00 2001 From: Andreas Gruhler Date: Thu, 12 Sep 2024 17:43:00 +0200 Subject: [PATCH 10/10] fix(shellcheck): SC2004, no $ on arithmetic var --- kubernetes/vault-snapshot.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kubernetes/vault-snapshot.sh b/kubernetes/vault-snapshot.sh index 84f96bb..fb71654 100644 --- a/kubernetes/vault-snapshot.sh +++ b/kubernetes/vault-snapshot.sh @@ -17,7 +17,7 @@ if [ "${S3_EXPIRE_DAYS}" ]; then s3cmd ls "${S3_URI}" --host="${S3_HOST}" --host-bucket="${S3_BUCKET}" | while read -r line; do createDate=$(echo "$line" | awk '{print $1" "$2}') createDate=$(date -d"$createDate" +%s) - olderThan=$(date --date @$(($(date +%s) - 86400*$S3_EXPIRE_DAYS)) +%s) + olderThan=$(date --date @$(($(date +%s) - 86400*S3_EXPIRE_DAYS)) +%s) if [ "$createDate" -lt "$olderThan" ]; then fileName=$(echo "$line" | awk '{print $4}') if [ "$fileName" != "" ]; then