change pw now works
This commit is contained in:
parent
e07d0021b2
commit
747755eb2c
5 changed files with 207 additions and 64 deletions
|
@ -6,4 +6,5 @@ RUN /tmp/install.sh
|
||||||
ADD local/ /usr/local/lib/dda-backup
|
ADD local/ /usr/local/lib/dda-backup
|
||||||
RUN init-bb.bb
|
RUN init-bb.bb
|
||||||
ADD resources2 /tmp/
|
ADD resources2 /tmp/
|
||||||
RUN install -m 0700 -o root -g root /tmp/test-me.bb /usr/local/bin/
|
RUN install -m 0700 -o root -g root /tmp/test.bb /usr/local/bin/
|
||||||
|
RUN test.bb
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
#!/usr/bin/env bb
|
#!/usr/bin/env bb
|
||||||
|
|
||||||
(println "initialized")
|
|
||||||
|
|
||||||
(require '[babashka.tasks :as tasks]
|
(require '[babashka.tasks :as tasks]
|
||||||
'[dda.backup.cred-rot :as cr]
|
'[dda.backup.cred-rot :as cr]
|
||||||
'[dda.backup.restic :as rc]
|
'[dda.backup.restic :as rc]
|
||||||
|
@ -14,24 +12,19 @@
|
||||||
:files ["test-backup"]
|
:files ["test-backup"]
|
||||||
:restore-target-directory "test-restore"}))
|
:restore-target-directory "test-restore"}))
|
||||||
|
|
||||||
(def db-config (merge restic-repo {:backup-path "db"
|
(def cred-config (merge restic-repo
|
||||||
:pg-db "mydb"
|
{:new-password-config {:new-password-file "new-pw"
|
||||||
:pg-user "user"
|
:valid-from "2024-12-12 00:00:00"}}))
|
||||||
:pg-password "password"}))
|
|
||||||
|
|
||||||
(def cred-config (merge restic-repo {:new-password-file "new-pw-file"}))
|
|
||||||
|
|
||||||
(def dry-run {:dry-run true :debug true})
|
(def dry-run {:dry-run true :debug true})
|
||||||
|
|
||||||
(defn prepare!
|
(defn prepare!
|
||||||
[]
|
[]
|
||||||
(spit "/tmp/file_password" "file-password")
|
(spit "restic-pwd" "thePassword")
|
||||||
(spit "restic-pwd" "ThePassword")
|
(spit "new-pw" "newPassword")
|
||||||
(tasks/shell "mkdir" "-p" "test-backup")
|
(tasks/shell "mkdir" "-p" "test-backup")
|
||||||
(spit "test-backup/file" "I was here")
|
(spit "test-backup/file" "I was here")
|
||||||
(spit "new-pw-file" "newpassword")
|
(tasks/shell "mkdir" "-p" "test-restore"))
|
||||||
(tasks/shell "mkdir" "-p" "test-restore")
|
|
||||||
(pg/create-pg-pass! db-config))
|
|
||||||
|
|
||||||
(defn restic-repo-init!
|
(defn restic-repo-init!
|
||||||
[]
|
[]
|
||||||
|
@ -39,6 +32,4 @@
|
||||||
|
|
||||||
(prepare!)
|
(prepare!)
|
||||||
(restic-repo-init!)
|
(restic-repo-init!)
|
||||||
(cr/list-passwords! cred-config)
|
(cr/change-password! cred-config)
|
||||||
(cr/maybe-add-new! cred-config)
|
|
||||||
(cr/list-passwords! cred-config)
|
|
|
@ -3,11 +3,13 @@
|
||||||
[orchestra.core :refer [defn-spec]]
|
[orchestra.core :refer [defn-spec]]
|
||||||
[clojure.spec.alpha :as s]
|
[clojure.spec.alpha :as s]
|
||||||
[dda.backup.cred-rot.domain :as domain]
|
[dda.backup.cred-rot.domain :as domain]
|
||||||
[dda.backup.infrastructure :as i]))
|
[dda.backup.infrastructure :as i]
|
||||||
|
[cljc.java-time.instant :as inst]
|
||||||
|
[cljc.java-time.local-date :as ld]))
|
||||||
|
|
||||||
(s/def ::valid-from domain/timestamp?)
|
(s/def ::replace-until domain/timestamp?)
|
||||||
(s/def ::new-password-file string?)
|
(s/def ::new-password-file string?)
|
||||||
(s/def ::new-password-config (s/keys :req-un [::new-password-file ::valid-from]))
|
(s/def ::new-password-config (s/keys :req-un [::new-password-file ::replace-until]))
|
||||||
|
|
||||||
(s/def ::cred-rot
|
(s/def ::cred-rot
|
||||||
(s/keys :req-un []
|
(s/keys :req-un []
|
||||||
|
@ -18,16 +20,60 @@
|
||||||
[config ::cred-rot]
|
[config ::cred-rot]
|
||||||
(i/execute-out! (domain/list-passwords-command config) config))
|
(i/execute-out! (domain/list-passwords-command config) config))
|
||||||
|
|
||||||
(defn-spec maybe-add-new! nil?
|
(defn-spec change-password-step! nil?
|
||||||
[config ::cred-rot]
|
[config ::cred-rot]
|
||||||
(let [{:keys [new-password-file valid-from]} (:new-password-config config)]
|
(when-some [new-password-config (:new-password-config config)]
|
||||||
|
(let [{:keys [new-password-file replace-until]} new-password-config
|
||||||
|
initial-passwords-list (domain/parse-response (list-passwords! config))
|
||||||
|
action (domain/set-new-password-action
|
||||||
|
(ld/now)
|
||||||
|
initial-passwords-list
|
||||||
|
config)]
|
||||||
|
(cond
|
||||||
|
(= action :wait-for-new-pwd)
|
||||||
|
(println "wait till new password is valid")
|
||||||
|
(= action :set-new-pwd)
|
||||||
|
(i/execute! (domain/add-password-command config) config)
|
||||||
|
(= action :remove-old-pwd)
|
||||||
|
(i/execute! (domain/remove-password-command
|
||||||
|
config
|
||||||
|
(:id (first initial-passwords-list))
|
||||||
|
(:id (last initial-passwords-list)))
|
||||||
|
config)
|
||||||
|
(= action :new-pwd-change-finished)
|
||||||
|
(println "pw-change sucessfull")
|
||||||
|
(= action :no-pwd-change-needed)
|
||||||
|
(println "nothing to do.")
|
||||||
|
:else
|
||||||
|
(throw (Exception. (str action)))
|
||||||
|
)
|
||||||
|
(println initial-passwords-list)
|
||||||
|
(println action)
|
||||||
|
(println (list-passwords! config))
|
||||||
|
action
|
||||||
|
)))
|
||||||
|
|
||||||
|
(defn-spec change-password! nil?
|
||||||
|
[config ::cred-rot]
|
||||||
|
(while (let [action (change-password-step! config) ]
|
||||||
|
(and (not= :no-pwd-change-needed action)
|
||||||
|
(not= :wait-for-new-pwd action)))
|
||||||
|
(println "call step")
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
|
(defn-spec set-new-password-old! nil?
|
||||||
|
[config ::cred-rot]
|
||||||
|
(let [{:keys [new-password-file replace-until]} (:new-password-config config)
|
||||||
|
replace-until-date (ld/parse "2024-10-19 13:16:54" domain/timestamp-formatter)]
|
||||||
(if (not (nil? new-password-file))
|
(if (not (nil? new-password-file))
|
||||||
(let [parsed-passwords (domain/parse-response (list-passwords! config))]
|
(let [parsed-passwords (domain/parse-response (list-passwords! config))]
|
||||||
(when (> 0 (compare
|
(println (str "add-new-password: relace until " replace-until))
|
||||||
|
(cond
|
||||||
|
(> 0 (compare
|
||||||
(:created (last parsed-passwords))
|
(:created (last parsed-passwords))
|
||||||
valid-from))
|
replace-until-date))
|
||||||
(i/execute! (domain/add-password-command config) config))))))
|
(do (println "add-new-password: set new pw")
|
||||||
|
(i/execute! (domain/add-password-command config) config))
|
||||||
(defn-spec replace-old-password! nil?
|
:else (println (str "else " (inst/now)))))
|
||||||
[]
|
(println "add-new-password: there was no new pw configured"))))
|
||||||
)
|
|
||||||
|
|
|
@ -27,20 +27,32 @@
|
||||||
(s/def ::hostName (fn [in] (every? #(re-matches lowercase-numeric %) (str/split in #"-"))))
|
(s/def ::hostName (fn [in] (every? #(re-matches lowercase-numeric %) (str/split in #"-"))))
|
||||||
; "2024-10-18 13:08:16"
|
; "2024-10-18 13:08:16"
|
||||||
(def timestamp-formatter (df/of-pattern "yyyy-MM-dd HH:mm:ss"))
|
(def timestamp-formatter (df/of-pattern "yyyy-MM-dd HH:mm:ss"))
|
||||||
(defn timestamp? [in]
|
(defn timestamp-string? [in]
|
||||||
(try
|
(try
|
||||||
(ld/parse in timestamp-formatter)
|
(ld/parse in timestamp-formatter)
|
||||||
true
|
true
|
||||||
(catch Exception _ false)))
|
(catch Exception _ false)))
|
||||||
|
(def timestamp? any?)
|
||||||
|
|
||||||
(s/def ::created timestamp?)
|
(s/def ::created timestamp?)
|
||||||
|
|
||||||
(s/def ::entry (s/keys :opt-un []
|
(s/def ::entry (s/keys :opt-un []
|
||||||
:req-un [::current ::id ::userName ::hostName ::created]))
|
:req-un [::current ::id ::userName ::hostName ::created]))
|
||||||
(s/def ::response (s/coll-of ::entry))
|
(s/def ::response (s/coll-of ::entry))
|
||||||
|
|
||||||
|
(s/def ::set-password-action #{:error-parse-password :error-undefined
|
||||||
|
:wait-for-new-pwd :set-new-pwd :remove-old-pwd
|
||||||
|
:new-pwd-change-finished :no-pwd-change-needed})
|
||||||
|
|
||||||
|
(s/def ::valid-from timestamp-string?)
|
||||||
|
(s/def ::new-password-file string?)
|
||||||
|
(s/def ::new-password-config (s/keys :req-un [::new-password-file ::valid-from]))
|
||||||
|
|
||||||
|
(s/def ::cred-rot
|
||||||
|
(s/keys :req-un []
|
||||||
|
:opt-un [::new-password-config]))
|
||||||
|
|
||||||
; Refer to "docs/CredentialRotation.md" for specifics
|
; Refer to "docs/CredentialRotation.md" for specifics
|
||||||
|
|
||||||
(defn-spec base-command ::cd/command
|
(defn-spec base-command ::cd/command
|
||||||
[config ::config
|
[config ::config
|
||||||
command ::cd/command]
|
command ::cd/command]
|
||||||
|
@ -75,4 +87,37 @@
|
||||||
|
|
||||||
(defn-spec parse-response ::response
|
(defn-spec parse-response ::response
|
||||||
[response string?]
|
[response string?]
|
||||||
(sort-by :created (cc/parse-string response #(keyword %))))
|
(->> (cc/parse-string response true)
|
||||||
|
(map #(merge % {:created (ld/parse (:created %) timestamp-formatter)}))
|
||||||
|
(sort-by :created)
|
||||||
|
))
|
||||||
|
|
||||||
|
(defn-spec set-new-password-action ::set-password-action
|
||||||
|
[current-date timestamp?
|
||||||
|
parsed-response ::response
|
||||||
|
config ::cred-rot]
|
||||||
|
(if-let [new-password-config (:new-password-config config)]
|
||||||
|
(let [valid-from (:valid-from new-password-config)
|
||||||
|
valid-from-date (ld/parse valid-from timestamp-formatter)]
|
||||||
|
(cond
|
||||||
|
(> 1 (count parsed-response))
|
||||||
|
:error-parse-password
|
||||||
|
(> 0 (compare current-date valid-from-date))
|
||||||
|
:wait-for-new-pwd
|
||||||
|
(and (<= 0 (compare current-date valid-from-date))
|
||||||
|
(= 1 (count parsed-response))
|
||||||
|
(> 0 (compare (:created (last parsed-response)) valid-from-date)))
|
||||||
|
:set-new-pwd
|
||||||
|
(and (<= 0 (compare current-date valid-from-date))
|
||||||
|
(= 2 (count parsed-response))
|
||||||
|
(<= 0 (compare (:created (last parsed-response)) valid-from-date))
|
||||||
|
(not (:current (last parsed-response))))
|
||||||
|
:remove-old-pwd
|
||||||
|
(and (<= 0 (compare current-date valid-from-date))
|
||||||
|
(= 1 (count parsed-response))
|
||||||
|
(<= 0 (compare (:created (last parsed-response)) valid-from-date))
|
||||||
|
(:current (last parsed-response)))
|
||||||
|
:new-pwd-change-finished
|
||||||
|
:else
|
||||||
|
:error-undefined))
|
||||||
|
:no-pwd-change-needed))
|
||||||
|
|
|
@ -3,37 +3,9 @@
|
||||||
[clojure.test :refer [deftest is]]
|
[clojure.test :refer [deftest is]]
|
||||||
[clojure.spec.alpha :as s]
|
[clojure.spec.alpha :as s]
|
||||||
[clojure.spec.test.alpha :as st]
|
[clojure.spec.test.alpha :as st]
|
||||||
|
[cljc.java-time.local-date :as ld]
|
||||||
[dda.backup.cred-rot.domain :as cut]))
|
[dda.backup.cred-rot.domain :as cut]))
|
||||||
|
|
||||||
(deftest test-parse-response
|
|
||||||
(is (=
|
|
||||||
[{:current true,
|
|
||||||
:id "b67161fb",
|
|
||||||
:userName "root",
|
|
||||||
:hostName "backup-restore-65bd9b6ff5-z69sn",
|
|
||||||
:created "2024-10-18 13:16:54"}
|
|
||||||
{:current false,
|
|
||||||
:id "521e0760",
|
|
||||||
:userName "root",
|
|
||||||
:hostName "backup-restore-65bd9b6ff5-z69sn",
|
|
||||||
:created "2024-11-18 13:08:16"}]
|
|
||||||
(cut/parse-response "[
|
|
||||||
{
|
|
||||||
\"current\": false,
|
|
||||||
\"id\": \"521e0760\",
|
|
||||||
\"userName\": \"root\",
|
|
||||||
\"hostName\": \"backup-restore-65bd9b6ff5-z69sn\",
|
|
||||||
\"created\": \"2024-11-18 13:08:16\"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
\"current\": true,
|
|
||||||
\"id\": \"b67161fb\",
|
|
||||||
\"userName\": \"root\",
|
|
||||||
\"hostName\": \"backup-restore-65bd9b6ff5-z69sn\",
|
|
||||||
\"created\": \"2024-10-18 13:16:54\"
|
|
||||||
}
|
|
||||||
]"))))
|
|
||||||
|
|
||||||
(deftest test-spec-id
|
(deftest test-spec-id
|
||||||
(is (s/valid? ::cut/id "521e0760"))
|
(is (s/valid? ::cut/id "521e0760"))
|
||||||
(is (s/valid? ::cut/id "test"))
|
(is (s/valid? ::cut/id "test"))
|
||||||
|
@ -54,9 +26,97 @@
|
||||||
(is (valid "backup-restore-65bd9b6ff5-z69sn"))))
|
(is (valid "backup-restore-65bd9b6ff5-z69sn"))))
|
||||||
|
|
||||||
(deftest test-spec-timestamp
|
(deftest test-spec-timestamp
|
||||||
(let [valid #(s/valid? cut/timestamp? %)]
|
(let [valid #(s/valid? cut/timestamp-string? %)]
|
||||||
(is (valid "2024-10-18 13:08:16"))
|
(is (valid "2024-10-18 13:08:16"))
|
||||||
(is (valid "2032-09-01 12:56:59"))
|
(is (valid "2032-09-01 12:56:59"))
|
||||||
(is (not (valid "2024-13-5 13:08:16")))
|
(is (not (valid "2024-13-5 13:08:16")))
|
||||||
(is (not (valid "2024-6-42 13:08:16")))
|
(is (not (valid "2024-6-42 13:08:16")))
|
||||||
(is (not (valid "test")))))
|
(is (not (valid "test")))))
|
||||||
|
|
||||||
|
(deftest test-parse-response
|
||||||
|
(is (=
|
||||||
|
(ld/parse "2024-10-19 13:16:54" cut/timestamp-formatter)
|
||||||
|
(:created
|
||||||
|
(first
|
||||||
|
(cut/parse-response "[
|
||||||
|
{
|
||||||
|
\"current\": false,
|
||||||
|
\"id\": \"521e0760\",
|
||||||
|
\"userName\": \"root\",
|
||||||
|
\"hostName\": \"backup-restore-65bd9b6ff5-z69sn\",
|
||||||
|
\"created\": \"2024-11-18 13:08:16\"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
\"current\": true,
|
||||||
|
\"id\": \"b67161fb\",
|
||||||
|
\"userName\": \"root\",
|
||||||
|
\"hostName\": \"backup-restore-65bd9b6ff5-z69sn\",
|
||||||
|
\"created\": \"2024-10-19 13:16:54\"
|
||||||
|
}
|
||||||
|
]"))))))
|
||||||
|
|
||||||
|
(deftest test-set-new-password-action
|
||||||
|
(is (= :error-parse-password
|
||||||
|
(cut/set-new-password-action
|
||||||
|
(ld/parse "2024-10-19 13:16:54" cut/timestamp-formatter)
|
||||||
|
[]
|
||||||
|
{:new-password-config {:new-password-file "new-pw-file"
|
||||||
|
:valid-from "2024-11-29 12:00:16"}})))
|
||||||
|
(is (= :wait-for-new-pwd
|
||||||
|
(cut/set-new-password-action
|
||||||
|
(ld/parse "2024-10-19 13:16:54" cut/timestamp-formatter)
|
||||||
|
[{:current true
|
||||||
|
:id "a1"
|
||||||
|
:userName "root"
|
||||||
|
:hostName "host"
|
||||||
|
:created (ld/parse "2023-01-01 00:00:00" cut/timestamp-formatter)}]
|
||||||
|
{:new-password-config {:new-password-file "new-pw-file"
|
||||||
|
:valid-from "2024-11-29 12:00:16"}})))
|
||||||
|
(is (= :set-new-pwd
|
||||||
|
(cut/set-new-password-action
|
||||||
|
(ld/parse "2024-11-29 13:16:54" cut/timestamp-formatter)
|
||||||
|
[{:current true
|
||||||
|
:id "a1"
|
||||||
|
:userName "root"
|
||||||
|
:hostName "host"
|
||||||
|
:created (ld/parse "2023-01-01 00:00:00" cut/timestamp-formatter)}]
|
||||||
|
{:new-password-config {:new-password-file "new-pw-file"
|
||||||
|
:valid-from "2024-11-29 12:00:16"}})))
|
||||||
|
|
||||||
|
(is (= :remove-old-pwd
|
||||||
|
(cut/set-new-password-action
|
||||||
|
(ld/parse "2024-11-29 13:16:55" cut/timestamp-formatter)
|
||||||
|
[{:current true
|
||||||
|
:id "a1"
|
||||||
|
:userName "root"
|
||||||
|
:hostName "host"
|
||||||
|
:created (ld/parse "2023-01-01 00:00:00" cut/timestamp-formatter)}
|
||||||
|
{:current false
|
||||||
|
:id "a2"
|
||||||
|
:userName "root"
|
||||||
|
:hostName "host"
|
||||||
|
:created (ld/parse "2024-11-29 13:16:54" cut/timestamp-formatter)}]
|
||||||
|
{:new-password-config {:new-password-file "new-pw-file"
|
||||||
|
:valid-from "2024-11-29 12:00:16"}})))
|
||||||
|
|
||||||
|
(is (= :new-pwd-change-finished
|
||||||
|
(cut/set-new-password-action
|
||||||
|
(ld/parse "2024-11-29 13:16:55" cut/timestamp-formatter)
|
||||||
|
[{:current true
|
||||||
|
:id "a2"
|
||||||
|
:userName "root"
|
||||||
|
:hostName "host"
|
||||||
|
:created (ld/parse "2024-11-29 13:16:54" cut/timestamp-formatter)}]
|
||||||
|
{:new-password-config {:new-password-file "new-pw-file"
|
||||||
|
:valid-from "2024-11-29 12:00:16"}})))
|
||||||
|
|
||||||
|
(is (= :no-pwd-change-needed
|
||||||
|
(cut/set-new-password-action
|
||||||
|
(ld/parse "2024-11-29 13:16:55" cut/timestamp-formatter)
|
||||||
|
[{:current true
|
||||||
|
:id "a2"
|
||||||
|
:userName "root"
|
||||||
|
:hostName "host"
|
||||||
|
:created (ld/parse "2024-11-29 13:16:54" cut/timestamp-formatter)}]
|
||||||
|
{})))
|
||||||
|
)
|
Loading…
Reference in a new issue