kasi.el

This package provides an easy way to manage secrets via M-x kasi.
Log | Files | Refs | LICENSE

convert.sh (2493B)


      1 #!/bin/sh
      2 # converts kasi.sh key-value pairs to kasi.el sexps
      3 
      4 # kasi.sh format
      5 # password_on_first_line
      6 # Username: someone
      7 # Email: bob@example.org
      8 # TOTP: some_base32_string
      9 # anything else can go here too
     10 
     11 # kasi.el format
     12 # -*- mode: lisp -*-
     13 # ((password "password_here")
     14 #  (username "someone")
     15 #  (email "bob@example.org")
     16 #  (totp "some_base32_string")
     17 #  (extra-content "\
     18 #    anything not matched
     19 #    goes in here")
     20 #
     21 # if any of the fields are not parsed/found in original, it will be
     22 # set to nil in sexp
     23 
     24 KASI_DIR="/data/kasi"
     25 KASI_EXT=".age"
     26 KASI_DECRYPT="age -d -i $HOME/.ssh/id_ed25519"
     27 KASI_ENCRYPT="age -R $HOME/.ssh/id_ed25519.pub"
     28 
     29 lisp_val() {
     30     if [ -z "$1" ]; then
     31         printf 'nil'
     32     else
     33         printf '"%s"' "$(printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g')"
     34     fi
     35 }
     36 
     37 convert() {
     38     f="${KASI_DIR}/${1}${KASI_EXT}"
     39     contents="$($KASI_DECRYPT "$f")" || {
     40         printf 'error: failed to decrypt %s\n' "$f" >&2
     41         return 1
     42     }
     43 
     44     first_line=$(printf '%s\n' "$contents" | sed -n '1p')
     45     second_line=$(printf '%s\n' "$contents" | sed -n '2p')
     46     last_char=$(printf '%s' "$contents" | tail -c 1)
     47     if [ "$first_line" = "; -*- mode: lisp -*-" ] && [ "${second_line#((}" != "$second_line" ] && [ "$last_char" = ")" ]; then
     48         printf 'skipping %s (already converted)\n' "$1" >&2
     49         return 0
     50     fi
     51 
     52     password=$(printf '%s\n' "$contents" | sed -n '1p')
     53     username=$(printf '%s\n' "$contents" | sed -n 's/^Username:[[:space:]]*//p' | sed 's/[[:space:]]*$//' | head -1)
     54     email=$(printf '%s\n'    "$contents" | sed -n 's/^Email:[[:space:]]*//p'    | sed 's/[[:space:]]*$//' | head -1)
     55     totp=$(printf '%s\n'     "$contents" | sed -n 's/^TOTP:[[:space:]]*//p'     | sed 's/[[:space:]]*$//' | head -1)
     56 
     57     extra=$(printf '%s\n' "$contents" | awk 'NR > 1 && !/^(Username|Email|TOTP):/ && NF')
     58 
     59     printf '; -*- mode: lisp -*-\n'
     60     printf '((password %s)\n'  "$(lisp_val "$password")"
     61     printf ' (username %s)\n'  "$(lisp_val "$username")"
     62     printf ' (email %s)\n'     "$(lisp_val "$email")"
     63     printf ' (totp %s)\n'      "$(lisp_val "$totp")"
     64 
     65     if [ -z "$extra" ]; then
     66         printf ' (extra-content nil))\n'
     67     else
     68         esc=$(printf '%s' "$extra" | sed 's/\\/\\\\/g; s/"/\\"/g')
     69         printf ' (extra-content "\\\n%s"))\n' "$esc"
     70     fi
     71 }
     72 
     73 cd "$KASI_DIR"
     74 for i in */*"$KASI_EXT"; do
     75     i="${i%%$KASI_EXT}"
     76     j="$(mktemp)"
     77     convert "$i" > "$j"
     78     $KASI_ENCRYPT <"$j" >"$i""$KASI_EXT"
     79     rm "$j"
     80 done