Writes a project's secrets as one encrypted file, the only way they leave the
vault. With no arguments it takes every profile the .monkeys file declares:
monkeys pack
wrote /tmp/a.monsecrets: +foo @test,production @production, 5 secretscopied its passphrase to your clipboard; send that the other way
Send the file however you like, and paste the passphrase into something else:
a different messenger, a call, a password manager's share. Both down one
channel is one leak away from being no encryption at all.
The file goes to /tmp, which is never inside a repository, and the message
shows the path. --path names a directory to write into, and the name before
--only names the file inside it. A name carries no directory of its own:
It carries the project's namespace, each profile's name, the keys the project
lists for it, and their secrets, sealed with ChaCha20-Poly1305 under a key
scrypt derives from the passphrase. The values of the packed profiles, the
KEY=value lines, ride along whole, since they are public anyway, and the
message counts them:
wrote /tmp/a.monsecrets: +foo @test, 2 secrets, 2 values
One bundle carries one project. The file is safe to send over whatever you
already use; the passphrase goes another way.
--open then reveals the file, in Finder with the file selected, or its
folder through xdg-open on Linux, since the next thing to do with a bundle
is to drag it somewhere.
A pack with a secret still missing refuses, since a bundle that fills half a
profile is a bug for whoever receives it.
A bundle that would carry @personal asks first, whichever way that profile
got in. The name is the convention for a key each person holds their own copy
of, so handing one over is a decision rather than a step, and the question
takes the word instead of a letter:
@personal is yours, not the team's, and a bundle hands it to whoever opens it. [UNDERSTOOD/N] UNDERSTOOD
Anything else answers no, and so does a pack with nobody to answer: the
question needs a terminal, which is what keeps a script from bundling one
person's keys by itself. The refusal names the profiles the file has besides
it:
monkeys: nothing written. to pack the rest: monkeys pack --only @test,production
Everything else about the file is fixed, so the passphrase is the only part
anyone decides, and the only part an attacker can work on. A stolen bundle is
guessed at offline for as long as someone cares to, and scrypt's 128 MB a
guess buys time only in proportion to how hard the passphrase is to guess.
So pack does not ask for one. It draws 24 random characters and puts them on
your clipboard, and they are never printed, never stored and never in your
shell history. Paste that into whatever carries it to the other person, which
is not the thing carrying the file.
A clipboard manager keeps what it is given, sometimes for good. If you run
one, take the passphrase out of its history once the bundle has arrived.
--ask prompts for one you choose instead, and leaves the clipboard alone:
Choose that way and the file is only as good as the passphrase, so take one
from a password manager rather than thinking one up. On a machine with no
clipboard tool pack says so and asks, since a file whose passphrase nobody
has is a file nobody can open. The passphrase is still read from standard
input when it is not a terminal, so a script that pipes one keeps working.
--only says which profiles and keys, and reads the way the file is written.
A @profile opens a block, @a,b opens one for several profiles at once, and
the keys after it belong to every profile in that block. A block with no keys
after it goes whole; keys before any @ come from the default profile, the
first the file mentions. That is how a teammate gets test and never
production, or one key on its own:
The bundle keeps that shape, block for block, and unpack writes it back as
the project file. The path goes before --only, which takes the rest of
the line. A key a profile does not list is refused rather than left
out.
Outside a project, --only @foo.test names a profile in full, and a bundle
made there carries its profiles under their full names, with no + line.
The passphrase is read from standard input when it is not a terminal, for the
rare script that needs to.