From aa0d8d3a2e08c61b158b6c21f7a4a9ad625c769b Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Mon, 13 Jan 2025 17:20:58 +0100
Subject: [PATCH] add password rotation to generation

---
 src/main/cljc/dda/c4k_forgejo/backup.cljc     | 38 ++++++++++---------
 src/main/cljc/dda/c4k_forgejo/core.cljc       |  1 +
 .../cljc/dda/c4k_forgejo/backup_test.cljc     | 15 +++++++-
 .../resources/forgejo-test/valid-auth.yaml    |  3 +-
 4 files changed, 38 insertions(+), 19 deletions(-)

diff --git a/src/main/cljc/dda/c4k_forgejo/backup.cljc b/src/main/cljc/dda/c4k_forgejo/backup.cljc
index e52f04b..bb884ea 100644
--- a/src/main/cljc/dda/c4k_forgejo/backup.cljc
+++ b/src/main/cljc/dda/c4k_forgejo/backup.cljc
@@ -1,17 +1,18 @@
 (ns dda.c4k-forgejo.backup
- (:require
-  [clojure.spec.alpha :as s]
-  #?(:clj [orchestra.core :refer [defn-spec]]
-     :cljs [orchestra.core :refer-macros [defn-spec]])
-  [dda.c4k-common.yaml :as yaml]
-  [dda.c4k-common.base64 :as b64]
-  [dda.c4k-common.common :as cm]
-  [dda.c4k-common.predicate :as p]
-  #?(:cljs [dda.c4k-common.macros :refer-macros [inline-resources]])))
+  (:require
+   [clojure.spec.alpha :as s]
+   #?(:clj [orchestra.core :refer [defn-spec]]
+      :cljs [orchestra.core :refer-macros [defn-spec]])
+   [dda.c4k-common.yaml :as yaml]
+   [dda.c4k-common.base64 :as b64]
+   [dda.c4k-common.common :as cm]
+   [dda.c4k-common.predicate :as p]
+   #?(:cljs [dda.c4k-common.macros :refer-macros [inline-resources]])))
 
 (s/def ::aws-access-key-id p/bash-env-string?)
 (s/def ::aws-secret-access-key p/bash-env-string?)
 (s/def ::restic-password p/bash-env-string?)
+(s/def ::restic-new-password p/bash-env-string?)
 (s/def ::restic-repository p/bash-env-string?)
 
 (s/def ::config (s/keys :req-un [::restic-repository]))
@@ -32,17 +33,20 @@
 
 (defn-spec generate-cron p/map-or-seq?
   []
-   (yaml/from-string (yaml/load-resource "backup/cron.yaml")))
+  (yaml/from-string (yaml/load-resource "backup/cron.yaml")))
 
 (defn-spec generate-backup-restore-deployment p/map-or-seq?
   [my-conf ::config]
   (yaml/from-string (yaml/load-resource "backup/backup-restore-deployment.yaml")))
 
 (defn-spec generate-secret p/map-or-seq?
-  [my-auth ::auth]
-  (let [{:keys [aws-access-key-id aws-secret-access-key restic-password]} my-auth]
-    (->
-     (yaml/from-string (yaml/load-resource "backup/secret.yaml"))
-     (cm/replace-key-value :aws-access-key-id (b64/encode aws-access-key-id))
-     (cm/replace-key-value :aws-secret-access-key (b64/encode aws-secret-access-key))
-     (cm/replace-key-value :restic-password (b64/encode restic-password)))))
+  [auth ::auth]
+  (let [{:keys [aws-access-key-id aws-secret-access-key 
+                restic-password restic-new-password]} auth]
+    (as-> (yaml/from-string (yaml/load-resource "backup/secret.yaml")) res
+      (cm/replace-key-value res :aws-access-key-id (b64/encode aws-access-key-id))
+      (cm/replace-key-value res :aws-secret-access-key (b64/encode aws-secret-access-key))
+      (cm/replace-key-value res :restic-password (b64/encode restic-password))
+      (if (contains? auth :restic-new-password)
+        (assoc-in res [:data :restic-new-password] (b64/encode restic-new-password))
+        res))))
diff --git a/src/main/cljc/dda/c4k_forgejo/core.cljc b/src/main/cljc/dda/c4k_forgejo/core.cljc
index acfa473..2a1d136 100644
--- a/src/main/cljc/dda/c4k_forgejo/core.cljc
+++ b/src/main/cljc/dda/c4k_forgejo/core.cljc
@@ -43,6 +43,7 @@
                             ::forgejo/mailer-user ::forgejo/mailer-pw
                             ::backup/aws-access-key-id ::backup/aws-secret-access-key]
                    :opt-un [::backup/restic-password
+                            ::backup/restic-new-password
                             ::mon/mon-auth]))
 
 (defn-spec config-objects p/map-or-seq?
diff --git a/src/test/cljc/dda/c4k_forgejo/backup_test.cljc b/src/test/cljc/dda/c4k_forgejo/backup_test.cljc
index 876614a..3faee7e 100644
--- a/src/test/cljc/dda/c4k_forgejo/backup_test.cljc
+++ b/src/test/cljc/dda/c4k_forgejo/backup_test.cljc
@@ -19,7 +19,20 @@
            :restic-password "cmVzdGljLXB3"}}
          (cut/generate-secret {:aws-access-key-id "aws-id"
                                :aws-secret-access-key "aws-secret"
-                               :restic-password "restic-pw"}))))
+                               :restic-password "restic-pw"})))
+  (is (= {:apiVersion "v1",
+          :kind "Secret",
+          :metadata {:name "backup-secret", :namespace "forgejo"},
+          :type "Opaque",
+          :data
+          {:aws-access-key-id "YXdzLWlk",
+           :aws-secret-access-key "YXdzLXNlY3JldA==",
+           :restic-password "b2xk",
+           :restic-new-password "bmV3"}}
+         (cut/generate-secret {:aws-access-key-id "aws-id"
+                               :aws-secret-access-key "aws-secret"
+                               :restic-password "old"
+                               :restic-new-password "new"}))))
 
 (deftest should-generate-backup-config
   (testing "federated"
diff --git a/src/test/resources/forgejo-test/valid-auth.yaml b/src/test/resources/forgejo-test/valid-auth.yaml
index cf1efb9..0f8fca6 100644
--- a/src/test/resources/forgejo-test/valid-auth.yaml
+++ b/src/test/resources/forgejo-test/valid-auth.yaml
@@ -4,7 +4,8 @@ mailer-user: ""
 mailer-pw: ""
 aws-access-key-id: "AWS_KEY_ID"
 aws-secret-access-key: "AWS_KEY_SECRET"
-restic-password: ""
+restic-password: "old"
+restic-new-password: "new"
 mon-auth: 
   grafana-cloud-user: "user"
   grafana-cloud-password: "password"