]> Dogcows Code - chaz/groupsecret/blob - bin/groupsecret
add the last remaining miss pod
[chaz/groupsecret] / bin / groupsecret
1 #!perl
2 # PODNAME: groupsecret
3 # ABSTRACT: A simple tool for maintaining a shared group secret
4
5 =head1 SYNOPSIS
6
7 groupsecret [--version] [--help] [-f <filepath>] [-k <privatekey_path>]
8 <command> [<args>]
9
10 groupsecret add-key [--embed] [--update] <publickey_path> ...
11
12 groupsecret delete-key <fingerprint>|<publickey_path> ...
13
14 groupsecret list-keys
15
16 groupsecret set-secret [--keep-passphrase] <path>|-|rand:<num_bytes>
17
18 groupsecret [print-secret] [--no-decrypt]
19
20 =head1 DESCRIPTION
21
22 L<groupsecret> is a program that makes it easy for groups to share a secret between themselves
23 without exposing the secret to anyone else. It could be used, for example, by a team to share an
24 L<ansible-vault(1)> password; see L</ansible-vault> for more about this particular use case.
25
26 The goal of this program is to be easy to use and have few dependencies (or only have dependencies
27 users are likely to already have installed).
28
29 L<groupsecret> works by encrypting a secret with a symmetric cipher protected by a secure random
30 passphrase which is itself encrypted by one or more SSH2 RSA public keys. Only those who have access
31 to one of the corresponding private keys are able to decrypt the passphrase and access the secret.
32
33 The encrypted secret and passphrase are stored in a single keyfile. You can even commit the keyfile
34 in a public repo or in a private repo where some untrusted users may have read access; the secret is
35 locked away to all except those with a private key to a corresponding public key that has been added
36 to the keyfile.
37
38 The keyfile is just a YAML file, so it's human-readable (except of course for the encrypted parts).
39 This make it easy to add to version control and work with diffs. You can edit the keyfile by hand if
40 you learn its very simple structure, but this program makes it even easier to manage the keyfile.
41
42 =head1 OPTIONS
43
44 =head2 --version
45
46 Print the program name and version to C<STDOUT>, and exit.
47
48 Alias: C<-v>
49
50 =head2 --help
51
52 Print the synopsis to C<STDOUT>, and exit.
53
54 Alias: C<-h>
55
56 =head2 --file=path
57
58 Specify a path to a keyfile which stores a secret and keys.
59
60 Defaults to the value of the environment variable C<GROUPSECRET_KEYFILE> or F<groupsecret.yml>.
61
62 Alias: C<-f>
63
64 =head2 --private-key=path
65
66 Specify a path to a PEM private key. This is used by some commands to decrypt the passphrase that
67 protects the secret and is ignored by commands that don't need it.
68
69 Defaults to the value of the environment variable L</GROUPSECRET_PRIVATE_KEY>. If that is unset, it
70 defaults to F<~/.ssh/id_rsa>.
71
72 Alias: C<-k>
73
74 =head1 COMMANDS
75
76 =head2 add-key
77
78 groupsecret add-key path/to/mykey_rsa.pub
79
80 Adds one or more SSH2 RSA public keys to a keyfile. This allows the secret contained within the
81 keyfile to be accessed by whoever has the corresponding private key.
82
83 If the C<--embed> option is used, the public keys will be embeded in the keyfile. This may be
84 a useful way to make sure the actual keys are available in the future since they could be needed to
85 encrypt a new passphrase if it ever needs to be changed. Keys that are not embedded will be searched
86 for in the filesystem; see L</GROUPSECRET_PATH>.
87
88 If the C<--update> option is used and a key with the same fingerprint is added, the new key will
89 replaced the existing key. The default behavior is to skip existing keys.
90
91 If the keyfile is storing a secret, the passphrase protecting the secret will need to be decrypted
92 so that access to the secret can be shared with the new key(s).
93
94 Alias: C<add-keys>
95
96 =head2 delete-key
97
98 groupsecret delete-key MD5:89:b3:fb:76:6c:f9:56:8e:a8:1a:df:ba:1c:ba:7d:05
99 groupsecret delete-key path/to/mykey_rsa.pub
100
101 Deletes one or more keys from a keyfile. This prevents the secret contained within the keyfile from
102 being accessed by whoever has the corresponding private key.
103
104 Of course, if the owners of the key(s) being removed have already had access to the keyfile prior to
105 their keys being removed, the secret is already exposed to them. It usually makes sense to follow up
106 this command with a L</set-secret> command in order to change the secret.
107
108 Aliases: C<delete-keys>, C<remove-key>, C<remove-keys>
109
110 =head2 list-keys
111
112 groupsecret list-keys
113
114 Prints the keys that have access to the secret contained in the keyfile to C<STDOUT>, one per line
115 in the following format:
116
117 <fingerprint> <comment>
118
119 =head2 set-secret
120
121 groupsecret set-secret path/to/secretfile.txt
122 groupsecret set-secret - <<END
123 > it's a secret to everybody
124 > END
125 groupsecret set-secret rand:48
126
127 Set or update the secret contained in a keyfile. The argument allows you to add a secret from
128 a file, from <STDIN>, or from a stream of secure random bytes.
129
130 If the keyfile already contains a secret, it will be replaced by the new secret. A keyfile can only
131 contain one secret at a time. If you think you want to store more than one secret at a time, store
132 a tarball instead.
133
134 By default, this will also change the passphrase protecting the secret and re-encrypt the passphrase
135 for each key currently in the keyfile. This requires all of the public keys to be available (see
136 L</GROUPSECRET_PATH>). If for some reason you want to protect the new secret with the current
137 passphrase, use the C<--keep-passphrase> option; this can be done without the public keys being
138 available, but it will require a private key to decrypt the passphrase.
139
140 Aliases: C<change-secret>, C<update-secret>
141
142 =head2 print-secret
143
144 groupsecret print-secret
145 groupsecret print-secret --no-decrypt
146
147 Print the secret contained in the keyfile to C<STDOUT>.
148
149 If the C<--no-decrypt> option is used, the secret will be printed in its encrypted form.
150
151 This requires a private key.
152
153 Aliases: (no command), C<show-secret>
154
155 =head1 REQUIREMENTS
156
157 =for :list
158 * L<OpenSSH|https://www.openssh.com> (commands: L<ssh-keygen(1)>)
159 * L<OpenSSL|https://www.openssl.org> (commands: L<openssl(1)>)
160
161 =head1 INSTALL
162
163 There are several ways to install groupsecret to your system. First, make sure you first have the
164 L</REQUIREMENTS> installed.
165
166 =head2 Using cpanm
167
168 You can install groupsecret using L<cpanm>. If you have a local perl (plenv, perlbrew, etc.), you
169 can just do this:
170
171 cpanm App::GroupSecret
172
173 to install the F<groupsecret> executable and its Perl module dependencies. The executable will be
174 installed to your perl's bin path, like F<~/perl5/perlbrew/bin/groupsecret>.
175
176 If you're installing to your system perl, you can do:
177
178 cpanm --sudo App::GroupSecret
179
180 to install the F<groupsecret> executable to a system directory, like F</usr/local/bin/groupsecret>
181 (depending on your perl).
182
183 =head2 Downloading just the executable
184
185 You may also choose to download F<groupsecret> as a single executable, like this:
186
187 curl -OL https://raw.githubusercontent.com/chazmcgarvey/groupsecret/solo/groupsecret
188 chmod +x groupsecret
189
190 This executable is fat-packed and includes all the non-core Perl module dependencies built-in.
191
192 =head2 For developers
193
194 If you're a developer and want to hack on the source, clone the repository and pull the
195 dependencies:
196
197 git clone https://github.com/chazmcgarvey/groupsecret.git
198 cd groupsecret
199 cpanm Dist::Zilla
200 dzil authordeps --missing | cpanm
201 dzil listdeps --author --develop --missing | cpanm
202
203 =head1 ENVIRONMENT
204
205 =head2 GROUPSECRET_KEYFILE
206
207 If set, this program will use the value as a path to the keyfile. The L</--file=path> option takes
208 precedence if it is used.
209
210 =head2 GROUPSECRET_PRIVATE_KEY
211
212 If set, this program will use the value as a path to the keyfile. The L</--private-key=path> option
213 takes precedence if it is used.
214
215 =head2 GROUPSECRET_PATH
216
217 The value of this variable should be a colon-separated list of directories in which to search for
218 public keys. By default, the actual keys are not embedded in keyfiles, but they may be needed to
219 encrypt a new passphrase if it ever needs to be changed. Keys that are not embedded will be searched
220 for in the filesystem based on the value of this environment variable.
221
222 Defaults to C<.:keys:$HOME/.ssh>.
223
224 =head1 EXAMPLES
225
226 =head2 ansible-vault
227
228 TODO
229
230 =cut
231
232 use warnings FATAL => 'all';
233 use strict;
234
235 our $VERSION = '9999.999'; # VERSION
236
237 use App::GroupSecret;
238
239 App::GroupSecret->new->main(@ARGV);
240 exit;
This page took 0.046117 seconds and 4 git commands to generate.