Compare commits
No commits in common. "credential-rotation" and "main" have entirely different histories.
credential
...
main
6 changed files with 3 additions and 176 deletions
4
deps.edn
4
deps.edn
|
@ -11,9 +11,7 @@
|
||||||
{;; Application
|
{;; Application
|
||||||
org.clojure/clojure {:mvn/version "1.11.4"}
|
org.clojure/clojure {:mvn/version "1.11.4"}
|
||||||
org.clojure/spec.alpha {:mvn/version "0.5.238"}
|
org.clojure/spec.alpha {:mvn/version "0.5.238"}
|
||||||
orchestra/orchestra {:mvn/version "2021.01.01-1"}
|
orchestra/orchestra {:mvn/version "2021.01.01-1"}}
|
||||||
cheshire/cheshire {:mvn/version "5.13.0"}
|
|
||||||
com.widdindustries/cljc.java-time {:mvn/version "0.1.21"}}
|
|
||||||
;; ---------------------------------------------------------
|
;; ---------------------------------------------------------
|
||||||
|
|
||||||
;; ---------------------------------------------------------
|
;; ---------------------------------------------------------
|
||||||
|
|
|
@ -1,42 +1,3 @@
|
||||||
#!/usr/bin/env bb
|
#!/usr/bin/env bb
|
||||||
|
|
||||||
(require '[babashka.tasks :as tasks]
|
(println "initialized")
|
||||||
'[dda.backup.cred-rot :as cr]
|
|
||||||
'[dda.backup.restic :as rc]
|
|
||||||
'[dda.backup.postgresql :as pg])
|
|
||||||
|
|
||||||
(def restic-repo {:password-file "restic-pwd"
|
|
||||||
:restic-repository "restic-repo"})
|
|
||||||
|
|
||||||
(def file-config (merge restic-repo {:backup-path "files"
|
|
||||||
:files ["test-backup"]
|
|
||||||
:restore-target-directory "test-restore"}))
|
|
||||||
|
|
||||||
(def db-config (merge restic-repo {:backup-path "db"
|
|
||||||
:pg-db "mydb"
|
|
||||||
:pg-user "user"
|
|
||||||
:pg-password "password"}))
|
|
||||||
|
|
||||||
(def cred-config (merge restic-repo {:new-password-file "new-pw-file"}))
|
|
||||||
|
|
||||||
(def dry-run {:dry-run true :debug true})
|
|
||||||
|
|
||||||
(defn prepare!
|
|
||||||
[]
|
|
||||||
(spit "/tmp/file_password" "file-password")
|
|
||||||
(spit "restic-pwd" "ThePassword")
|
|
||||||
(tasks/shell "mkdir" "-p" "test-backup")
|
|
||||||
(spit "test-backup/file" "I was here")
|
|
||||||
(spit "new-pw-file" "newpassword")
|
|
||||||
(tasks/shell "mkdir" "-p" "test-restore")
|
|
||||||
(pg/create-pg-pass! db-config))
|
|
||||||
|
|
||||||
(defn restic-repo-init!
|
|
||||||
[]
|
|
||||||
(rc/init! restic-repo))
|
|
||||||
|
|
||||||
(prepare!)
|
|
||||||
(restic-repo-init!)
|
|
||||||
(cr/list-passwords! cred-config)
|
|
||||||
(cr/maybe-add-new! cred-config)
|
|
||||||
(cr/list-passwords! cred-config)
|
|
||||||
|
|
|
@ -18,12 +18,12 @@ function main() {
|
||||||
apt-get install -qqy ca-certificates curl gnupg postgresql-client-16 restic openjdk-21-jre-headless nano
|
apt-get install -qqy ca-certificates curl gnupg postgresql-client-16 restic openjdk-21-jre-headless nano
|
||||||
curl -Ss --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | tee /etc/apt/trusted.gpg.d/postgresql-common_pgdg_archive_keyring.gpg
|
curl -Ss --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | tee /etc/apt/trusted.gpg.d/postgresql-common_pgdg_archive_keyring.gpg
|
||||||
sh -c 'echo "deb [signed-by=/etc/apt/trusted.gpg.d/postgresql-common_pgdg_archive_keyring.gpg] https://apt.postgresql.org/pub/repos/apt jammy-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
|
sh -c 'echo "deb [signed-by=/etc/apt/trusted.gpg.d/postgresql-common_pgdg_archive_keyring.gpg] https://apt.postgresql.org/pub/repos/apt jammy-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
|
||||||
|
upgradeSystem
|
||||||
babashka_install
|
babashka_install
|
||||||
} > /dev/null
|
} > /dev/null
|
||||||
|
|
||||||
update-ca-certificates
|
update-ca-certificates
|
||||||
install -m 0700 -o root -g root /tmp/init-bb.bb /usr/local/bin/
|
install -m 0700 -o root -g root /tmp/init-bb.bb /usr/local/bin/
|
||||||
install -m 0600 -o root -g root /tmp/bb.edn /usr/local/bin/
|
|
||||||
cleanupDocker
|
cleanupDocker
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
(ns dda.backup.cred-rot
|
|
||||||
(:require
|
|
||||||
[orchestra.core :refer [defn-spec]]
|
|
||||||
[clojure.spec.alpha :as s]
|
|
||||||
[dda.backup.cred-rot.domain :as domain]
|
|
||||||
[dda.backup.infrastructure :as i]))
|
|
||||||
|
|
||||||
(s/def ::new-password-file string?)
|
|
||||||
|
|
||||||
(s/def ::cred-rot
|
|
||||||
(s/keys :req-un []
|
|
||||||
:opt-un [::new-password-file]))
|
|
||||||
|
|
||||||
; Refer to "docs/CredentialRotation.md" for specifics
|
|
||||||
|
|
||||||
(defn-spec maybe-add-new! nil?
|
|
||||||
[config ::cred-rot]
|
|
||||||
(let [{:keys [new-password-file]} config]
|
|
||||||
(if (not (nil? new-password-file))
|
|
||||||
(i/execute! (domain/add-password-command config) config))))
|
|
||||||
|
|
||||||
(defn-spec list-passwords! nil?
|
|
||||||
[config ::cred-rot]
|
|
||||||
(i/execute! (domain/list-passwords-command config) config))
|
|
||||||
|
|
||||||
(defn-spec replace-old-password! nil?
|
|
||||||
[]
|
|
||||||
)
|
|
|
@ -1,71 +0,0 @@
|
||||||
(ns dda.backup.cred-rot.domain
|
|
||||||
(:require
|
|
||||||
[orchestra.core :refer [defn-spec]]
|
|
||||||
[clojure.spec.alpha :as s]
|
|
||||||
[clojure.string :as str]
|
|
||||||
[dda.backup.core.domain :as cd]
|
|
||||||
[dda.backup.restic.domain :as rd]
|
|
||||||
[cljc.java-time.local-date :as ld]
|
|
||||||
[cljc.java-time.format.date-time-formatter :as df]))
|
|
||||||
|
|
||||||
(s/def ::new-password-file string?)
|
|
||||||
(s/def ::config (s/keys :req-un [::rd/restic-repository
|
|
||||||
::rd/password-file]
|
|
||||||
:opt-un [::rd/certificate-file
|
|
||||||
::new-password-file]))
|
|
||||||
|
|
||||||
(def lowercase-numeric #"[a-z0-9]+")
|
|
||||||
(def alphanumeric #"[a-zA-Z0-9]+")
|
|
||||||
; true | false
|
|
||||||
(s/def ::current boolean?)
|
|
||||||
; 521e0760
|
|
||||||
(s/def ::id (s/and string? #(re-matches lowercase-numeric %)))
|
|
||||||
; root
|
|
||||||
(s/def ::userName #(re-matches alphanumeric %))
|
|
||||||
; backup-restore-65bd9b6ff5-z69sn
|
|
||||||
(s/def ::hostName (fn [in] (every? #(re-matches lowercase-numeric %) (str/split in #"-"))))
|
|
||||||
; "2024-10-18 13:08:16"
|
|
||||||
(def timestamp-formatter (df/of-pattern "yyyy-MM-dd HH:mm:ss"))
|
|
||||||
(s/def ::created #(try
|
|
||||||
(ld/parse % timestamp-formatter)
|
|
||||||
true
|
|
||||||
(catch Exception _ false)))
|
|
||||||
|
|
||||||
(s/def ::entry (s/keys :opt-un []
|
|
||||||
:req-un [::current ::id ::userName ::hostName ::created]))
|
|
||||||
(s/def ::response (s/coll-of ::entry))
|
|
||||||
|
|
||||||
|
|
||||||
; Refer to "docs/CredentialRotation.md" for specifics
|
|
||||||
|
|
||||||
(defn-spec base-command ::cd/command
|
|
||||||
[config ::config
|
|
||||||
command ::cd/command]
|
|
||||||
(let [{:keys [restic-repository password-file
|
|
||||||
certificate-file new-password-file]} config]
|
|
||||||
(into
|
|
||||||
[]
|
|
||||||
(concat ["restic" "-r" restic-repository]
|
|
||||||
(cond
|
|
||||||
(some? certificate-file)
|
|
||||||
["--cacert" certificate-file]
|
|
||||||
(some? password-file)
|
|
||||||
["--password-file" password-file]
|
|
||||||
:else
|
|
||||||
[])
|
|
||||||
command))))
|
|
||||||
|
|
||||||
(defn-spec list-passwords-command ::cd/command
|
|
||||||
[config ::config]
|
|
||||||
[(base-command config ["key" "list" "--json"])])
|
|
||||||
|
|
||||||
(defn-spec add-password-command ::cd/command
|
|
||||||
[config ::config]
|
|
||||||
(let [{:keys [new-password-file]} config]
|
|
||||||
[(base-command config ["key" "add" "--new-password-file" new-password-file])]))
|
|
||||||
|
|
||||||
(defn-spec remove-password-command ::cd/command
|
|
||||||
[config ::config
|
|
||||||
new-id ::id
|
|
||||||
old-id ::id]
|
|
||||||
[(base-command config ["key" "remove" "--key-hint" new-id old-id])])
|
|
|
@ -1,33 +0,0 @@
|
||||||
(ns dda.backup.cred-rot.domain-test
|
|
||||||
(:require
|
|
||||||
[clojure.test :refer [deftest is]]
|
|
||||||
[clojure.spec.alpha :as s]
|
|
||||||
[clojure.spec.test.alpha :as st]
|
|
||||||
[dda.backup.cred-rot.domain :as cut]))
|
|
||||||
|
|
||||||
(deftest test-spec-id
|
|
||||||
(is (s/valid? ::cut/id "521e0760"))
|
|
||||||
(is (s/valid? ::cut/id "test"))
|
|
||||||
(is (s/valid? ::cut/id "123456"))
|
|
||||||
(is (not (s/valid? ::cut/id "ROOT")))
|
|
||||||
(is (not (s/valid? ::cut/id "Test!"))))
|
|
||||||
|
|
||||||
(deftest test-spec-username
|
|
||||||
(is (s/valid? ::cut/userName "521e0760"))
|
|
||||||
(is (s/valid? ::cut/userName "Testuser"))
|
|
||||||
(is (s/valid? ::cut/userName "root"))
|
|
||||||
(is (s/valid? ::cut/userName "ROOT"))
|
|
||||||
(is (not (s/valid? ::cut/userName "test-user"))))
|
|
||||||
|
|
||||||
(deftest test-spec-hostName
|
|
||||||
(let [valid #(s/valid? ::cut/hostName %)]
|
|
||||||
(is (valid "test-some-combination-2"))
|
|
||||||
(is (valid "backup-restore-65bd9b6ff5-z69sn"))))
|
|
||||||
|
|
||||||
(deftest test-spec-created
|
|
||||||
(let [valid #(s/valid? ::cut/created %)]
|
|
||||||
(is (valid "2024-10-18 13:08:16"))
|
|
||||||
(is (valid "2032-09-01 12:56:59"))
|
|
||||||
(is (not (valid "2024-13-5 13:08:16")))
|
|
||||||
(is (not (valid "2024-6-42 13:08:16")))
|
|
||||||
(is (not (valid "test")))))
|
|
Loading…
Reference in a new issue