/
akm
executable file
·136 lines (112 loc) · 3.51 KB
/
akm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#!/usr/bin/env bash
set -euo pipefail
shopt -s nullglob
version="0.3.2"
: "${AKM_PROFILE:=${HOME}/.akm}"
: "${AKM_DEFAULT_KEY_FILENAME:=${AKM_PROFILE}/default.key}"
profile="${AKM_PROFILE}"
default_key="${AKM_DEFAULT_KEY_FILENAME}"
skip_create_profile="${AKM_PROFILE_SKIP_CREATE:-}"
skip_create_sops="${AKM_PROFILE_SKIP_SOPS:-}"
display_manual () {
cat <<EOF
akm: age key manager and wrapper
Options:
-r {recipient}: read recipient key from ~/.akm/{recipient}.pub
--recipient {recipient}: same as -r
-h, --help: display this help
--version: display akm version
rest of args: passed to age unmodified
This program wraps age(1). For every --recipient passed it will read the
correspondent ~/.akm/{recipient}.pub and pass the key from there. When -d is
specified, it will add --identity ~/.akm/default.key if no identities have been
specified on the command line.
Environment variables AKM_PROFILE and AKM_DEFAULT_KEY_FILENAME can be used to
override ~/.akm and ~/.akm/default.key, respectively. If AKM_PROFILE_SKIP_CREATE
is set, akm will skip creating AKM_PROFILE on first run.
akm manages a list of all age keys in ~/.akm/*.key for use with sops in
~/.akm/sops-keys.txt, which can be used to link ~/.config/sops/age/keys.txt to.
If this is undesirable, set AKM_PROFILE_SKIP_SOPS to a non-empty value.
For list of age(1) options, see age --help.
EOF
}
display_version () {
echo "akm ${version}"
}
log () {
echo "akm: $*" >&2
}
sync_sops_keys () {
if [ -n "$skip_create_sops" ]; then
return
fi
# shellcheck disable=SC2155
local keys=$(echo "$profile"/*.key) dest="$profile/sops-keys.txt"
if [ -z "$keys" ]; then
log "emptying out $dest"
truncate -s0 "$dest"
return
fi
log "syncing sops keys"
# shellcheck disable=SC2086
cat $keys > $dest
}
initialize_profile () {
if [ -n "$skip_create_profile" ]; then
return
fi
if [ ! -d "$profile" ]; then
log "creating $profile"
mkdir -p "$profile"
chmod 700 "$profile"
log "created $profile, remember to run ln -s {key} $default_key"
fi
}
main () {
if [ $# -eq "0" ]; then
display_manual
exit 1
fi
local age_cmdline=() age_pre_cmdline="" set_identity=1 decrypt_mode=0
for (( i=1; i <= $#; i++ )); do
local arg=${!i}
case $arg in
"--version")
display_version
exit 0 ;;
"-h") ;&
"--help")
display_manual
exit 0 ;;
"-r") ;&
"--recipient")
local next_arg_pos=$(( i+1 ))
local next_arg=${!next_arg_pos}
pubkey_path="$profile/$next_arg.pub"
pubkey=$(cat "$pubkey_path")
age_cmdline+=('--recipient')
age_cmdline+=("$pubkey")
i=$(( i+1 ))
;;
"-i") ;&
"--identity")
set_identity=0
;&
"-d") ;&
"--decrypt")
decrypt_mode=1
;&
*)
age_cmdline+=("$arg")
esac
done
if [ "$set_identity" -eq 1 ] && [ "$decrypt_mode" -eq 1 ]; then
# identity flag should always come first
age_pre_cmdline="--identity $default_key"
fi
initialize_profile
sync_sops_keys
# shellcheck disable=SC2086
exec age ${age_pre_cmdline} "${age_cmdline[@]}" # make sure to expand the args
}
main "$@"