Skip to content

Commit

Permalink
Add default search for .secrets.edn file in the home directory
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewdowney committed Feb 4, 2022
1 parent 5043c27 commit b1d703b
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 22 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ Any one secrets file contains an encrypted version of a single
[EDN](https://github.com/edn-format/edn) map, with arbitrary levels of
labeled nesting.

By default, the secrets file lives at .secrets.edn in the working directory,
but this path can be changed explicitly via `with-path` (or via the `:path`
flag at the command line).
The path used for the secrets file, in priority order, is one of:

- the one explicitly specified via `with-path` (or `:path` at the command line),
- the `.secrets.edn` file in the working directory, or
- the `.secrets.edn` file in the home directory.


## Contents
Expand Down
Binary file removed secrets
Binary file not shown.
44 changes: 29 additions & 15 deletions src/io/sixtant/secrets.clj
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@
[EDN](https://github.com/edn-format/edn) map, with arbitrary levels of
labeled nesting.
By default, the secrets file lives at .secrets.edn in the working directory,
but this path can be changed explicitly via `with-path` (or via the `:path`
flag at the command line)."
The path used for the secrets file, in priority order, is one of:
- the one explicitly specified via `with-path` (or `:path` at the command
line),
- the `.secrets.edn` file in the working directory, or
- the `.secrets.edn` file in the home directory."
(:require [buddy.core.codecs :as codecs]
[buddy.core.nonce :as nonce]
[buddy.core.crypto :as crypto]
Expand All @@ -27,18 +30,27 @@
(set! *warn-on-reflection* true)


(def ^:dynamic *path*
"Location of saved secrets on disk."
".secrets.edn")
(defn default-secrets-path []
(if (.exists (io/file ".secrets.edn"))
".secrets.edn"
(let [home (System/getProperty "user.home")]
(.getCanonicalPath (io/file home ".secrets.edn")))))


(def ^:dynamic *path* "Explicitly bound path." nil)
(defmacro with-path
"Set the file path used for saved secrets."
[path & body]
`(binding [*path* ~path]
~@body))


(defn secrets-path
"Location of saved secrets on disk."
[]
(or *path* (default-secrets-path)))


;;; Primitives for key stretching & encryption


Expand Down Expand Up @@ -185,22 +197,24 @@
(defn read-secrets
"Prefer `with-secrets`."
[]
(if (.isFile (io/file *path*))
(let [p (or *password* (read-password "Password: "))]
{:data (decrypt-from-disk {:password p :path *path*})
:password p})
{:data {}
:password nil}))
(let [path (secrets-path)]
(if (.isFile (io/file path))
(let [p (or *password* (read-password (str "Password for " path ": ")))]
{:data (decrypt-from-disk {:password p :path path})
:password p})
{:data {}
:password nil})))


(defn write-secrets
"Prefer `swap-secrets!`."
[{:keys [data password]}]
(print "Encrypting data for writing...")
(flush)
(let [enc (encrypt-to-disk data {:password password :path *path*})]
(let [path (secrets-path)
enc (encrypt-to-disk data {:password password :path path})]
(println " Done.")
(println "Wrote" (count (.getBytes (prn-str enc))) "bytes.")
(println "Wrote" (count (.getBytes (prn-str enc))) "bytes to" (str path "."))
enc))


Expand Down Expand Up @@ -259,7 +273,7 @@
(defn rand-n [coll n] (repeatedly n #(nth coll (rng-int (count coll)))))
(def passphrase
(let [words (string/split-lines (slurp "/usr/share/dict/words"))]
(string/join " " (rand-n words 6))))
(string/join " " (rand-n words 5))))

;; Encrypt some data with the passphrase to send to somebody else
(encrypt (prn-str {:foo :bar}) passphrase)
Expand Down
6 changes: 3 additions & 3 deletions src/io/sixtant/secrets/main.clj
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"Given all of the leftover `args`, parse out a :path parameter if any,
otherwise use the default path for secrets."
[args]
(or (get (apply hash-map args) ":path") s/*path*))
(or (get (apply hash-map args) ":path") (s/secrets-path)))


(defcommand inspect
Expand Down Expand Up @@ -111,7 +111,7 @@
(let [args (rest args)
[path args] (if (= (first args) :path)
[(second args) (rest (rest args))]
[s/*path* args])
[(s/secrets-path) args])
[vname->path & args] args]
(assert (string? vname->path) "first parameter is an EDN string")
(let [vname->path (read-string vname->path)]
Expand All @@ -138,7 +138,7 @@
(flush)
(= (string/lower-case (read-line)) "y")))]
(if change?
(let [p (s/read-password "Set password: ")
(let [p (s/read-password (str "Set password for " (s/secrets-path) ": "))
p' (s/read-password "Confirm password: ")]
(if (= p p')
(assoc x :password p)
Expand Down
2 changes: 1 addition & 1 deletion test/io/sixtant/secrets_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
(let [temp (temp "encrypted" ".edn")
data {:bitso {:prod {:key "foo" :secret "bar"}}}]

; Write data to a temporary secrets fil
; Write data to a temporary secrets file
(with-path temp
(write-secrets {:data data :password "pass"}))

Expand Down

0 comments on commit b1d703b

Please sign in to comment.