-
Notifications
You must be signed in to change notification settings - Fork 0
/
secret.mx
142 lines (113 loc) · 3 KB
/
secret.mx
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
137
138
139
140
141
config: define secret path {
"Description": "Path to store GPG encrypted secrets",
"DataType": "str",
"Global": true,
"Default": "~/.secrets"
}
config: define secret recipient {
"Description": "Key to sign secret with",
"DataType": "str",
"Global": true,
"Default": ""
}
function secret {
# Manage secrets securely with GPG
config: set index silent true
switch $PARAMS[0] {
case add { secret.add $PARAMS[1] }
case env { secret.get env $PARAMS[1] }
case print { secret.get print $PARAMS[1] }
case delete { secret.delete $PARAMS[1] }
case list { secret.list }
catch { secret.default }
}
}
autocomplete: set secret { [{
"FlagsDesc": {
"add": "Add a new secret",
"env": "Retrieve a secret and store it as an environmental variable with the same name",
"print": "Retrieve a secret and print it to STDOUT",
"delete": "Delete a secret",
"list": "List all secrets"
},
"FlagValues": {
"env": [{ "Dynamic": ({ secret: list -> cast json }) }],
"print": [{ "Dynamic": ({ secret: list -> cast json }) }],
"delete": [{ "Dynamic": ({ secret: list -> cast json }) }]
}
}] }
private secret.default {
# `secret` usage
err: "Usage: secret add id\n" \
" env id\n" \
" print id -> <stdout>\n" \
" delete\n" \
" list -> <stdout>"
}
private secret.get {
# Gets a secret
trypipe {
set name=$PARAMS[1]
set export=${ $(name) | tr [:lower:] [:upper:] }
set path=${ config: get secret path }
!if { g: $path/$(name).secret } then {
err: "Secret '$(name)' does not exist"
}
if { os linux } then {
base64 = %[ -d "$path/$(name).secret" ]
} else {
base64 = %[ -d -i "$path/$(name).secret" ]
}
gpg = %[ -q --pinentry-mode loopback --decrypt ]
switch $PARAMS[0] {
case env {
base64: @base64 -> gpg: @gpg -> export $export
}
case print {
base64: @base64 -> gpg: @gpg
}
catch {
err: "Unknown action '$PARAMS[0]'"
}
}
}
}
private secret.add {
# Stores a new secret
trypipe {
set name=$PARAMS[0]
set path=${ config: get secret path }
mkdir -p $path
set enc=${ config: get secret recipient }
if { g: $path/$(name).secret } then {
err: "Secret '$(name)' already exists! Please delete first"
}
if { $enc } then {
$enc -> prepend "-r" -> set enc
}
$enc -> prepend "--encrypt" -> set enc
read --prompt "Please input secret: " \
--variable secret \
--mask '*'
$secret -> tmp -> set tmpfile
open $tmpfile -> gpg: @enc -> base64 |> $path/$(name).secret
}
}
private secret.delete {
# Delete an existing secret
trypipe {
set name=$PARAMS[0]
set path=${ config: get secret path }
!if { g: $path/$(name).secret } then {
err: "Secret '$(name)' does not exist!"
}
rm -v $path/$(name).secret
}
}
private secret.list {
# List all the stored secrets
cast json
path = ${ config: get secret path }
mkdir -p $path
g: $path/*.secret -> regexp s:^.*/:: -> regexp s/\.secret$//
}