109 Commits

Author SHA1 Message Date
Tom Limoncelli
25fd63f792 Update CHANGELOG.md 2017-06-11 08:34:57 -04:00
Tom Limoncelli
7c4fa4f4be tools/confidence_test.sh: Add explicit test for external tools. 2017-06-01 09:48:25 -04:00
Tom Limoncelli
9006c04c66 tools/auto_system_test: Add comments. 2017-06-01 09:48:13 -04:00
Tom Limoncelli
800fe098a6 "gpg --export" should export LANG=C.UTF-8 to be safe. 2017-05-29 19:39:01 -04:00
Tom Limoncelli
7029e44453 tools/confidence_test.sh: "export LANG=C.UTF-8" to be safe. 2017-05-29 19:37:56 -04:00
Tom Limoncelli
48cc17ac0a "make test" now uses "expect" to not prompt for passwords. 2017-05-29 19:31:26 -04:00
Tom Limoncelli
d78faf59d0 tools/confidence_test.sh: Set pinentry program to pinentry-tty 2017-05-29 19:09:36 -04:00
Robert Taylor
09a62cb1d2 Fixing physical_directory_of function for cases when target directory lives in root. (#194) 2017-05-29 18:00:06 -04:00
Tom Limoncelli
7649c9f00b Fix https://github.com/StackExchange/blackbox/issues/193
Add unit tests to tools/confidence_test.sh to verify admin operations work.
2017-05-15 11:10:01 -04:00
tlimoncelli@stackoverflow.com
1a22f77c82 Improve FreeBSD compatibility 2017-05-15 07:50:30 -04:00
tlimoncelli@stackoverflow.com
4bc97049ab tools/confidence_test.sh: now works with gnupg-2.0 and gnupg-2.1 2017-05-14 18:48:59 -04:00
tlimoncelli@stackoverflow.com
50ac1697c3 tools/confidence_test.sh: now works with gnupg-2.0 again 2017-05-14 17:52:27 -04:00
tlimoncelli@stackoverflow.com
eaa6d06b3e tools/confidence_test.sh: Handle gpg 2.1's new pubring filename. 2017-05-13 11:12:53 -04:00
tlimoncelli@stackoverflow.com
9c6f13fb80 blackbox_shred_all_files: BUGFIX: Does not shred files with spaces. 2017-05-13 11:12:05 -04:00
tlimoncelli@stackoverflow.com
849ec3138b blackbox_removeadmin: Disable gpg's confirmation. 2017-05-13 11:11:39 -04:00
Tom Limoncelli
49892c307c Sync mk_rpm_fpmdir from master 2017-05-04 10:23:10 -04:00
Tom Limoncelli
53ed9d601a Update CHANGELOG.md 2017-05-03 13:09:26 -04:00
Matthew
be425ed76c shred_file() outputs warning message to stderr. (#192) 2017-05-02 06:33:07 -04:00
Simon Gate
8728290122 Don't complain about GPG_AGENT_INFO if using newer gpg-agent (#189) 2017-04-26 08:34:20 -04:00
William Belle
2f2289b5e3 Fix typo on README (#187)
Thanks!
2017-03-24 09:04:25 -04:00
Graham Lyons
44c9934293 Use the rm command with -P as a shred fallback (#179)
* Use the `rm` command with `-P` as a shred fallback

The newer versions of OSX (Sierra) have neither `shred` nor `srm`.
They do have `rm` with the `-P` option, so we can fall back to that
before resorting to plain old `rm`.

* Add double-quotes and braces to the shell variable.

We should treat the variable as a string, and we should also be safe
when interpolating it.
2017-03-10 08:20:43 -05:00
Tom Limoncelli
cf984c26ee "make test" should be an alias for "make confidence". 2017-02-22 19:31:55 +00:00
Tom Limoncelli
5df0d21be6 make_tempdir must create shorter paths. 2017-02-20 12:15:05 -05:00
Tom Limoncelli
2d1410599d Fixing "make confidence" (HT to 98b928c0e8) 2017-02-20 16:47:33 +00:00
Tom Limoncelli
9bee252e24 README.md: Add info about our new mailing list. 2017-02-20 10:54:17 -05:00
Tom Limoncelli
e91344d404 Add a CHANGELOG.md 2017-02-16 15:41:59 -05:00
Tino Breddin
bd0fcd181c [FreeBSD] Fix use of chmod (#180)
LGTM

Thanks for the fix!
2017-01-20 17:12:57 -05:00
Ben Watson
818db98506 Requiring a file to be entered to finish editing (#175)
* Requiring a file to be entered to finish editing

Running blackbox_edit_end without an argument doesn't currently print out a warning that no files are being changed. A developer in my team who was new to Blackbox committed a decrypted file (and made no changes to the GPG file) as they didn't realise the command hadn't worked.

The check I've added should help to avoid these errors.

* Adding argument check to start editing
2016-12-12 14:07:33 +00:00
Joseph Herlant
1b7c8c880b Remove the key from the keyring when removing an admin (#173)
Thanks for the submission!
2016-11-22 13:43:08 -05:00
Tino Breddin
fba77f092a Add FreeBSD support (#172) 2016-11-08 13:49:42 -05:00
tlimoncelli@stackexchange.com
3e9091722c Merge branch 'jvanasco-feature-listadmins' 2016-10-07 16:19:41 -04:00
tlimoncelli@stackexchange.com
57dc69a928 Merge branch 'feature-listadmins' of https://github.com/jvanasco/blackbox into jvanasco-feature-listadmins 2016-10-07 16:19:13 -04:00
Jason Price
598896ef48 Add list admins commandline tool. (#170)
* adding a list_admins command

* updating README and V2 ideas to include list_admins

* fix documentation misses

* add list_admins to the toolchain
2016-10-06 11:26:43 -04:00
Dave Jachimiak
31cf506684 ignore backup files and secring.gpg in $BLACKBOXDATA (#169) 2016-09-23 09:26:22 -04:00
Jon Bardin
4fe27a04c9 Allow parallel shredding of files (#167)
* to log which files were shredded
* allow parallel shredding of files ot lower time to shred
2016-08-31 09:29:54 -04:00
Tom Limoncelli
f108d80027 Merge pull request #164 from josegonzalez/patch-1
Check return value contents
2016-05-26 13:47:41 -04:00
Jose Diaz-Gonzalez
21c0b68213 Check return value contents
Closes #156
2016-05-26 11:54:14 -04:00
Tom Limoncelli
65f40f8f6e Merge pull request #160 from dorfsmay/master
Use PKGNAME variable defined above.
2016-05-23 10:02:08 -04:00
Tom Limoncelli
f7a100fa8d Merge pull request #163 from amosshapira/master
#162: Added instructions to make "git diff" work
2016-05-23 10:00:58 -04:00
Amos Shapira
2be3ddaddf Added instructions to make "git diff" work
Added a paragraph about configuring `git` to decrypt files for diff/log
2016-05-22 11:45:41 +10:00
Yves Dorfsman
1ae578b7cf Tilde doesn't get expanded when in between quotes. 2016-05-20 16:15:15 -06:00
Yves Dorfsman
c3f7e12890 Use PKGNAME variable defined above. 2016-05-20 15:08:46 -06:00
Tom Limoncelli
eaadca8871 Merge pull request #158 from mettjus/patch-1
Improve command list in README
2016-05-16 09:32:51 -04:00
mettjus
4a32c95f53 Improve command list in README
Explicitly display for each command if it requires a target (a file or a key) or it doesn't.
2016-05-13 23:47:23 +02:00
tlimoncelli@stackexchange.com
1354628ed5 Version2-Ideas.md: Windows compatibility clarification. 2016-05-10 15:01:27 -04:00
jonathan vanasco
435a3c073f added blackbox_listadmins, which just displays active admins via cat "$BB_ADMINS" 2016-04-25 12:53:36 -04:00
tal@whatexit.org
1b6c6eadc9 Initial draft. 2016-04-24 09:14:56 -04:00
Tom Limoncelli
ead98b03ca Merge pull request #147 from billrawlinson/mingw-gpgagent
remove MinGW dependecy on GpG4Win (gpg-agent) in readme.md
2016-04-23 06:59:08 -04:00
Tom Limoncelli
93a01c82c8 Merge pull request #150 from jvanasco/fixes-subversion
Fixes for subversion
2016-04-23 06:58:22 -04:00
jonathan vanasco
4bb9c055ca added docs 2016-04-22 17:32:25 -04:00
jonathan vanasco
f8c1653e09 some updates for subversion 2016-04-22 17:30:28 -04:00
Bill Rawlinson
de05e1f8e7 remove MinGW dependecy on GpG4Win (gpg-agent)
The gpg-agent that ships with GpG4Win is a version 2 gpg agent and only works with gpg2.  The gpg in MinGW is gpg 1.x and it doesn't pick up this gpg-agent.

However, everything still works - you just have to enter your password for each file you decrypt.  Slightly onerous but not a huge deal breaker.

I notice there is  away to specify your own gpg versoin in the _blackbox_common.sh file but I don't really know how that works.  If someone were to specify to use gpg2 then they could probably use the agent in Gpg4Win but I don't know and don't know how to test that.
2016-04-15 14:28:15 -04:00
Tom Limoncelli
ef08dcc6b3 Merge pull request #145 from billrawlinson/MingwGpgAndMkTemp
Mingw gpg and mk temp
2016-04-14 11:07:54 -04:00
Bill Rawlinson
b9d5cd7716 specify git version
Older git for windows MinGW didn't support updating the plain text files in keyfiles/live/blackbox-admins.txt and blackbox-files.txt due to an error `cannot make pipe for process substitution function not supported`

The newer version of Git (which is also more secure) also resolves this issue.
2016-04-14 10:00:53 -04:00
Bill Rawlinson
fa68b56927 added link to git 2016-04-14 09:22:18 -04:00
Bill Rawlinson
8769474035 added documentation for MINGW users 2016-04-14 09:21:05 -04:00
tal@whatexit.org
1643ea7fd9 "make confidence": Use GID numbers, not names. Makes tests less fragile. 2016-03-15 21:22:29 -04:00
tal@whatexit.org
3a4a79284c Add more debugging output to "make confidence" 2016-03-15 19:14:09 -04:00
Tom Limoncelli
bf36197c5b Merge pull request #143 from danslimmon/noshredwarn
Warn user if there isn't a secure deletion utility
2016-03-14 15:02:06 -04:00
Dan Slimmon
fc63e24dcf Warn user if there isn't a secure deletion utility
Otherwise, somebody with neither shred nor srm installed could blithely
go on using Blackbox assuming that their working copies are getting
securely deleted.
2016-03-14 18:53:29 +00:00
Tom Limoncelli
ee1bbc8092 Merge pull request #142 from sobolevn/master
added git-secret into "Alternatives" section
2016-03-12 15:16:31 -08:00
sobolevn
3e8578d687 added git-secret into Alternatives 2016-03-10 17:26:39 +03:00
tlimoncelli@stackoverflow.com
a9dc14c7b0 _stack_lib.sh: Take upstream changes. 2016-02-29 17:22:12 +00:00
tlimoncelli@stackoverflow.com
d2fde2c2a9 Merge upstream mk_rpm_fpmdir 2016-02-29 16:53:33 +00:00
tlimoncelli@stackoverflow.com
7e175e5d9c Merge from upstream. 2016-02-29 16:25:27 +00:00
Tom Limoncelli
9f6c3f15c0 Merge pull request #140 from unixorn/make-package-iteration-iterate
Set release default to the number of commits in the repo instead of always using 1
2016-02-28 10:32:20 -05:00
Joe Block
673eaae95b Deal with being built within a burst tarball instead of a git clone 2016-02-27 06:50:50 -08:00
Joe Block
982f2f0045 Set release default to the number of commits in the repo instead of always using 1 2016-02-26 14:38:12 -08:00
Tom Limoncelli
aa68cd34ad Merge pull request #138 from unixorn/make-OUTPUTDIR-overridable
Make OUTPUTDIR overridable
2016-02-26 16:50:39 -05:00
Joe Block
e004ebb384 Make OUTPUTDIR overridable
Users (like me on my Jenkins server) may not want to put output debs and
rpms in ~.
2016-02-26 13:35:15 -08:00
Tom Limoncelli
9013350a68 Merge pull request #136 from trenton42/patch-1
Update README.md
2016-02-17 11:44:00 -05:00
Trenton Broughton
44e5ae6143 Update README.md
Added homebrew install method to Installation Instructions
2016-02-17 11:33:44 -05:00
tlimoncelli@stackoverflow.com
27a86758c7 Pass README.md and RELEASE_ENGINEERING.md through markdownfmt. Update TOC. 2016-01-21 23:42:57 -05:00
tlimoncelli@stackoverflow.com
f7a159d685 README.md: Add process for updating expired keys. HT @chishaku 2016-01-21 11:06:11 -05:00
Tom Limoncelli
63edd45499 Merge pull request #134 from pra85/patch-1
Update license year to 2016
2016-01-19 09:38:36 -05:00
Prayag Verma
d9064a9a26 Update license year to 2016 2016-01-16 17:50:03 +05:30
Tom Limoncelli
88e9e99f57 Merge pull request #132 from StackExchange/tlim_gitignore
When updating .gitignore, "git add" it.
2016-01-06 12:10:07 -05:00
Tom Limoncelli
46b44b4f19 Merge pull request #131 from chandlermelton/master
remove unencrypted file from .gitignore when deregistering
2016-01-06 11:05:25 -05:00
tlimoncelli@stackoverflow.com
34559499a2 Improve README.md for first timers 2016-01-06 10:11:34 -05:00
tlimoncelli@stackoverflow.com
c394b964e8 When updating .gitignore, "git add" it. 2015-12-30 14:41:22 +00:00
Chandler Melton
4ea164fbd3 remove unencrypted file from .gitignore when deregistering 2015-12-16 15:54:28 -06:00
Tom Limoncelli
921c5e6957 Merge pull request #130 from leowzukw/patch-1
Add alternative software to the Readme
2015-12-14 12:53:18 -05:00
Leo Wzukw
e03ef89332 Add alternative software to the Readme
Very similar program, would be interesting too.
2015-12-14 18:50:18 +01:00
tlimoncelli@stackexchange.com
a391c0abc6 Rename RELEASE_ENGINEERING.txt to RELEASE_ENGINEERING.md 2015-11-02 11:19:06 -05:00
Tom Limoncelli
384f04af48 Merge pull request #120 from ConnorAtherton/add-manual-install-steps
Add make rule for symlinking and removing /bin files
2015-11-01 14:14:25 -05:00
Connor Atherton
d83b2fbd21 Add manual install step to the Makefile 2015-11-01 10:03:02 -08:00
Tom Limoncelli
b11c918e4f Merge pull request #125 from snowpong/add-support-for-mingw
Add support for Git for Windows / MINGW users
2015-10-31 08:58:26 -04:00
Espen Riskedal
372a35036f Add support for Git for Windows / MINGW users
If you install Git for Windows (https://git-for-windows.github.io/) you get a console
,either CMD or MINTT, which returns MINGW* for uname -s. So if you run blackbox_addadmin
or the other commands, you'll get: "ERROR: Unknown OS. Exiting."

I've simply added MINGW* to the Linux and CYGWIN checks and it seems to work fine.

NOTE: I didn't touch tools/test_functions.sh allthough it should probably be updated as well.
2015-10-29 12:10:58 +01:00
Tom Limoncelli
074c0831c0 Merge pull request #124 from Gnouc/master
Fix some minor issues:
2015-10-19 10:08:51 -07:00
LE Manh Cuong
65ae375828 Fix some minor issues:
- Missing double quote
 - Replace `echo -n` with `printf "%s"` for more
 portability and reliability
2015-10-19 16:52:26 +07:00
Tom Limoncelli
3ec645fd13 Merge pull request #123 from Gnouc/master
Fix missing quote
2015-10-18 16:26:33 -07:00
LE Manh Cuong
0355095a59 Fix missing quote 2015-10-17 08:49:29 +07:00
Tom Limoncelli
733408a6b7 Merge pull request #122 from davidreuss/patch-1
Be consistent when creating tmpfiles in stacklib
2015-10-16 18:03:55 -07:00
David Reuss
ece750b710 Be consistent when creating tmpfiles in stacklib
Use same naming scheme as elsewhere when creating tempfiles.

This fixes deregistering files, when seeing:

```
mktemp: too few X's in template ‘_stacklib_’
```
2015-10-16 14:59:15 +02:00
tlimoncelli@stackexchange.com
54c6c2c037 README.md: Correct ToC 2015-09-23 13:31:21 -04:00
tlimoncelli@stackexchange.com
93bc410449 README.md: Add a table of contents 2015-09-23 13:11:52 -04:00
tlimoncelli@stackexchange.com
52e029a587 README.md: Improve indoctrination steps. 2015-09-23 12:41:48 -04:00
Tom Limoncelli
aa14bef555 Merge pull request #121 from serialdoom/master
Update README.md
2015-09-14 08:48:55 -04:00
Mike
b8ad2ba33d Update README.md
removed duplicate "work"
2015-09-14 10:10:32 +01:00
Tom Limoncelli
e637584d77 Merge pull request #117 from torarvid/editor-remove-quotes
Support having an $EDITOR value with arguments
2015-08-26 13:11:27 -04:00
Tor Arvid Lund
ca2cc76bcd Support having an $EDITOR value with arguments
If a user has $EDITOR set to e.g "subl --wait", then "$EDITOR" (with
quotes) will fail with error "command not found: subl --wait". In other
words, it looks for an executable containing the space and the --wait in
it.

Simply removing the quotes seems to work fine.
2015-08-26 16:15:29 +02:00
tlimoncelli@stackexchange.com
885a3a25b3 Document some common GPG error messages. 2015-08-10 11:44:27 -04:00
tlimoncelli@stackexchange.com
bb336a56fd Improve Developer Docs 2015-08-07 10:53:13 -04:00
Tom Limoncelli
0b637bb917 Merge pull request #116 from nextraztus/master
replace vcs_relative_path with non-python, fixes #115
2015-08-07 10:26:40 -04:00
Nextraztus
fd78fb5ed3 replace vcs_relative_path with non-python, fixes #115 2015-08-07 08:22:18 -06:00
tal@whatexit.org
7c73009461 Improve Cygwin compatibility. 2015-08-04 11:53:25 -04:00
tal@whatexit.org
159c3cc93b Improve installation instructions. 2015-08-04 11:53:03 -04:00
tlimoncelli@stackexchange.com
8fab12de6b Improve MacPorts update script and documentation based on feedback in https://trac.macports.org/ticket/48464 2015-07-31 15:36:55 -04:00
tlimoncelli@stackexchange.com
dd494be320 RELEASE_ENGINEERING.txt: Clarify comments. 2015-07-30 13:52:04 -04:00
32 changed files with 1102 additions and 539 deletions

26
CHANGELOG.md Normal file
View File

@@ -0,0 +1,26 @@
Release v1.20170127
* Starting CHANGELOG.
Release v1.20170309
* "make test" is an alias for "make confidence"
* macOS: make_tempdir must create shorter paths
* Fix "make confidence" for newer version of Git
* README.md: Add info about our new mailing list
Release v1.20170611
* confidence_test.sh verifies external tools exist
* confidence_test.sh more reliable for non-UTF8 users
* "make test" no longer prompts for passwords
* blackbox works better when target directory lives in root (#194)
* Add confidence_test.sh tests for admin operations
* blackbox_list_admins fails (#193)
* confidence_test.sh works better on FreeBSD
* tools/confidence_test.sh: now works with gnupg-2.0 and gnupg-2.1
* Blackbox now officially supports both gnupg-2.0 and gnupg-2.1
* blackbox_shred_all_files: BUGFIX: Does not shred files with spaces
* blackbox_removeadmin: disable gpg's confirmation
* Sync mk_rpm_fpmdir from master

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2014-2015 Stack Exchange, Inc.
Copyright (c) 2014-2016 Stack Exchange, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,12 +1,15 @@
SHELL=/bin/sh
PKGNAME=stack_blackbox
BASEDIR?=$(HOME)
OUTPUTDIR?="$(BASEDIR)/debbuild-${PKGNAME}"
all:
@echo 'Menu:'
@echo ' make update Update any generated files'
@echo ' make packages Make RPM packages'
@echo ' make packages-deb Make DEB packages'
@echo ' make test Run tests'
@echo ' make install (incomplete)'
install:
@@ -30,14 +33,14 @@ packages-rpm-debug:
@echo BUILD:
@PKGRELEASE=99 make packages
@echo ITEMS TO BE PACKAGED:
find ~/rpmbuild-$(PKGNAME)/installroot -type f
find $(BASEDIR)/rpmbuild-$(PKGNAME)/installroot -type f
@echo ITEMS ACTUALLY IN PACKAGE:
@rpm -qpl $$(cat ~/rpmbuild-$(PKGNAME)/bin-packages.txt)
@rpm -qpl $$(cat $(BASEDIR)/rpmbuild-$(PKGNAME)/bin-packages.txt)
local-rpm:
@PKGRELEASE=1 make packages
-@sudo rpm -e $(PKGNAME)
sudo rpm -i $$(cat ~/rpmbuild-$(PKGNAME)/bin-packages.txt)
sudo rpm -i $$(cat $(BASEDIR)/rpmbuild-$(PKGNAME)/bin-packages.txt)
lock-rpm:
sudo yum versionlock add $(PKGNAME)
@@ -45,12 +48,25 @@ lock-rpm:
unlock-rpm:
sudo yum versionlock clear
#
# Manual install
#
manual-install:
@echo 'Symlinking files from ./bin to /usr/local/bin'
@cd bin && for f in `find . -type f -iname "*" ! -iname "Makefile"`; do ln -fs `pwd`/$$f /usr/local/bin/$$f; done
@echo 'Done.'
manual-uninstall:
@echo 'Removing blackbox files from /usr/local/bin'
@cd bin && for f in `find . -type f -iname "*" ! -iname "Makefile"`; do rm /usr/local/bin/$$f; done
@echo 'Done.'
#
# DEB builds
#
packages-deb: tools/mk_deb_fpmdir.stack_blackbox.txt
cd tools && PKGRELEASE="$${PKGRELEASE}" PKGDESCRIPTION="Safely store secrets in git/hg/svn repos using GPG encryption" ./mk_deb_fpmdir stack_blackbox mk_deb_fpmdir.stack_blackbox.txt
cd tools && OUTPUTDIR=$(OUTPUTDIR) PKGRELEASE="$${PKGRELEASE}" PKGDESCRIPTION="Safely store secrets in git/hg/svn repos using GPG encryption" ./mk_deb_fpmdir stack_blackbox mk_deb_fpmdir.stack_blackbox.txt
# Make mk_deb_fpmdir.vcs_blackbox.txt from mk_rpm_fpmdir.stack_blackbox.txt:
tools/mk_deb_fpmdir.stack_blackbox.txt: tools/mk_rpm_fpmdir.stack_blackbox.txt
@@ -62,12 +78,12 @@ packages-deb-debug: tools/mk_deb_fpmdir.stack_blackbox.txt
@echo ITEMS TO BE PACKAGED:
find ~/debbuild-$(PKGNAME)/installroot -type f
@echo ITEMS ACTUALLY IN PACKAGE:
@dpkg --contents $$(cat ~/debbuild-$(PKGNAME)/bin-packages.txt)
@dpkg --contents $$(cat $(BASEDIR)/debbuild-$(PKGNAME)/bin-packages.txt)
local-deb:
@PKGRELEASE=1 make packages
-@sudo dpkg -e $(PKGNAME)
sudo dpkg -i $$(cat ~/rpmbuild-$(PKGNAME)/bin-packages.txt)
sudo dpkg -i $$(cat $(BASEDIR)/rpmbuild-$(PKGNAME)/bin-packages.txt)
#
# MacPorts builds
@@ -107,10 +123,10 @@ clean:
#
# System Test:
#
test: confidence
confidence:
@if [ -e ~/.gnupg ]; then echo ERROR: '~/.gnupg should not exist. If it does, bugs may polute your .gnupg configuration. If the code has no bugs everything will be fine. Do you feel lucky?'; false ; fi
@if which >/dev/null gpg-agent ; then pkill gpg-agent ; rm -rf /tmp/tmp.* ; fi
@export PATH="$(PWD)/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/local/bin:$(PATH)" ; tools/confidence_test.sh
tools/confidence_test.sh
@export PATH="$(PWD)/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/local/bin:$(PATH)" ; tools/auto_system_test
@if which >/dev/null gpg-agent ; then pkill gpg-agent ; fi
@if [ -e ~/.gnupg ]; then echo ERROR: '~/.gnupg was created which means the scripts might be poluting GnuPG configuration. Fix this bug.'; false ; fi

575
README.md
View File

@@ -1,229 +1,182 @@
BlackBox
========
Safely store secrets in a VCS repo (i.e. Git, Mercurial, Subversion or Perforce). These
commands make it easy
for you to Gnu Privacy Guard (GPG) encrypt specific files in a repo so they are
"encrypted at rest" in your repository. However, the scripts
make it easy to decrypt them when you need to view or edit them,
and decrypt them for use in production. Originally written
for Puppet, BlackBox now works with any Git or Mercurial repository.
Safely store secrets in a VCS repo (i.e. Git, Mercurial, Subversion or Perforce). These commands make it easy for you to Gnu Privacy Guard (GPG) encrypt specific files in a repo so they are "encrypted at rest" in your repository. However, the scripts make it easy to decrypt them when you need to view or edit them, and decrypt them for use in production. Originally written for Puppet, BlackBox now works with any Git or Mercurial repository.
A slide presentation about an older release [is on SlideShare](http://www.slideshare.net/TomLimoncelli/the-blackbox-project-sfae).
Join our mailing list: [https://groups.google.com/d/forum/blackbox-project](https://groups.google.com/d/forum/blackbox-project)
Table of Contents
=================
- [BlackBox](#blackbox)
- [Table of Contents](#table-of-contents)
- [Overview](#overview)
- [Why is this important?](#why-is-this-important)
- [Installation Instructions:](#installation-instructions)
- [Commands:](#commands)
- [Compatibility:](#compatibility)
- [How is the encryption done?](#how-is-the-encryption-done)
- [What does this look like to the typical user?](#what-does-this-look-like-to-the-typical-user)
- [How to use the secrets with Puppet?](#how-to-use-the-secrets-with-puppet)
- [Entire files:](#entire-files)
- [Small strings:](#small-strings)
- [How to enroll a new file into the system?](#how-to-enroll-a-new-file-into-the-system)
- [How to remove a file from the system?](#how-to-remove-a-file-from-the-system)
- [How to indoctrinate a new user into the system?](#how-to-indoctrinate-a-new-user-into-the-system)
- [How to remove a user from the system?](#how-to-remove-a-user-from-the-system)
- [Enabling Blackbox For a Repo](#enabling-blackbox-for-a-repo)
- [Set up automated users or “role accounts”](#set-up-automated-users-or-role-accounts)
- [Replace expired keys:](#replace-expired-keys)
- [Some common errors:](#some-common-errors)
- [Using Blackbox without a repo](#using-blackbox-without-a-repo)
- [Some Subversion gotchas:](#some-subversion-gotchas)
- [How to submit bugs or ask questions?](#how-to-submit-bugs-or-ask-questions)
- [Developer Info](#developer-info)
- [Alternatives](#alternatives)
- [License](#license)
Overview
========
Suppose you have a VCS repository (i.e. a Git or Mercurial repo)
and certain files contain secrets such as passwords or SSL private
keys. Often people just store such files "and hope that nobody finds
them in the repo". That's not safe.
Suppose you have a VCS repository (i.e. a Git or Mercurial repo) and certain files contain secrets such as passwords or SSL private keys. Often people just store such files "and hope that nobody finds them in the repo". That's not safe.
With BlackBox, those files are stored encrypted using GPG. Access to
the VCS repo without also having the right GPG keys
makes it worthless to have the files. As long as you keep your GPG keys
safe, you don't have to worry about storing your VCS repo on an untrusted
server. Heck, even if you trust your server, now you don't have to trust
the people that do backups of that server, or the people that handle the
backup tapes!
With BlackBox, those files are stored encrypted using GPG. Access to the VCS repo without also having the right GPG keys makes it worthless to have the files. As long as you keep your GPG keys safe, you don't have to worry about storing your VCS repo on an untrusted server. Heck, even if you trust your server, now you don't have to trust the people that do backups of that server, or the people that handle the backup tapes!
Rather than one GPG passphrase for all the files, each person with access
has their own GPG keys in the system. Any file can be decrypted by
anyone with their GPG key. This way, if one person leaves the company,
you don't have to communicate a new password to everyone with access.
Simply disable the one key that should no longer have access.
The process for doing this is as easy as running 2 commands (1 to
disable their key, 1 to re-encrypt all files.)
Rather than one GPG passphrase for all the files, each person with access has their own GPG keys in the system. Any file can be decrypted by anyone with their GPG key. This way, if one person leaves the company, you don't have to communicate a new password to everyone with access. Simply disable the one key that should no longer have access. The process for doing this is as easy as running 2 commands (1 to disable their key, 1 to re-encrypt all files.)
Automated processes often need access to all the decrypted files.
This is easy too. For example, suppose Git is being used for Puppet
files. The master needs access to the decrypted version of all the
files. Simply set up a GPG key for the Puppet master (or the role
account that pushes new files to the Puppet master) and have that
user run `blackbox_postdeploy` after any files are updated.
Getting started is easy. Just `cd` into a Git, Mercurial, Subversion or
Perforce repository and run `blackbox_initialize`. After that, if a file is to
be encrypted, run `blackbox_register_new_file` and you are done. Add
and remove keys with `blackbox_addadmin` and `blackbox_removeadmin`.
To view and/or edit a file, run `blackbox_edit`; this will decrypt the
file and open with whatever is specified by your $EDITOR environment
variable. When you close the editor the file will automatically be
encrypted again and the temporary plaintext file will be shredded. If
you need to leave the file decrypted while you update you can use the
`blackbox_edit_start` to decrypt the file and `blackbox_edit_end` when
you want to "put it back in the box."
Automated processes often need access to all the decrypted files. This is easy too. For example, suppose Git is being used for Puppet files. The master needs access to the decrypted version of all the files. Simply set up a GPG key for the Puppet master (or the role account that pushes new files to the Puppet master) and have that user run `blackbox_postdeploy` after any files are updated.
Getting started is easy. Just `cd` into a Git, Mercurial, Subversion or Perforce repository and run `blackbox_initialize`. After that, if a file is to be encrypted, run `blackbox_register_new_file` and you are done. Add and remove keys with `blackbox_addadmin` and `blackbox_removeadmin`. To view and/or edit a file, run `blackbox_edit`; this will decrypt the file and open with whatever is specified by your $EDITOR environment variable. When you close the editor the file will automatically be encrypted again and the temporary plaintext file will be shredded. If you need to leave the file decrypted while you update you can use the`blackbox_edit_start` to decrypt the file and `blackbox_edit_end` when you want to "put it back in the box."
Why is this important?
============================
======================
OBVIOUSLY we don't want secret things like SSL private keys
and passwords to be leaked.
OBVIOUSLY we don't want secret things like SSL private keys and passwords to be leaked.
NOT SO OBVIOUSLY when we store "secrets" in a VCS repo like Git or
Mercurial, suddenly we are less able to share our code with other
people. Communication between subteams of an organization is hurt.
You can't collaborate as well. Either you find yourself emailing
individual files around (yuck!), making a special repo with just
the files needed by your collaborators (yuck!!), or just deciding that
collaboration isn't worth all that effort (yuck!!!).
NOT SO OBVIOUSLY when we store "secrets" in a VCS repo like Git or Mercurial, suddenly we are less able to share our code with other people. Communication between subteams of an organization is hurt. You can't collaborate as well. Either you find yourself emailing individual files around (yuck!), making a special repo with just the files needed by your collaborators (yuck!!), or just deciding that collaboration isn't worth all that effort (yuck!!!).
The ability to be open and transparent about our code, with the
exception of a few specific files, is key to the kind of
collaboration that DevOps and modern IT practitioniers
need to do.
The ability to be open and transparent about our code, with the exception of a few specific files, is key to the kind of collaboration that DevOps and modern IT practitioners need to do.
Installation Instructions:
==========================
* *The MacPorts Way*: `sudo port install vcs_blackbox`
* *The RPM way*: `make packages-rpm` and now you have an RPM you can install.
* *The Debian/Ubuntu way*: Install [fpm](https://github.com/jordansissel/fpm), then `make packages-deb` and now you have a DEB you can install.
* *The hard way*: Copy all the files in "bin" to your "bin".
* *The Antigen Way*: Add `antigen bundle StackExchange/blackbox` to your .zshrc
* *The Zgen Way*: Add `zgen load StackExchange/blackbox` to your .zshrc where you're loading your other plugins.
- *The MacPorts Way*: `sudo port install vcs_blackbox`
- *The Homebrew Way*: `brew install blackbox`
- *The RPM way*: Check out the repo and make an RPM via `make packages-rpm`; now you can distribute the RPM via local methods.
- *The Debian/Ubuntu way*: Check out the repo and install [fpm](https://github.com/jordansissel/fpm). Now you can make a DEB `make packages-deb` that can be distributed via local methods.
- *The hard way*: Copy all the files in "bin" to your "bin".
- *The manual way*: `make manual-install` to install. `make manual-uninstall` to uninstall.
- *The Antigen Way*: Add `antigen bundle StackExchange/blackbox` to your .zshrc
- *The Zgen Way*: Add `zgen load StackExchange/blackbox` to your .zshrc where you're loading your other plugins.
Commands:
============================
=========
| Name: | Description: |
| --- | --- |
| `blackbox_edit` | Decrypt, run $EDITOR, re-encrypt a file |
| `blackbox_edit_start` | Decrypt a file so it can be updated |
| `blackbox_edit_end` | Encrypt a file after blackbox_edit_start was used |
| `blackbox_cat` | Decrypt and view the contents of a file |
|-------------------------------------|-------------------------------------------------------------------------|
| `blackbox_edit <file>` | Decrypt, run $EDITOR, re-encrypt a file |
| `blackbox_edit_start <file>` | Decrypt a file so it can be updated |
| `blackbox_edit_end <file>` | Encrypt a file after blackbox_edit_start was used |
| `blackbox_cat <file>` | Decrypt and view the contents of a file |
| `blackbox_diff` | Diff decrypted files against their original crypted version |
| `blackbox_initialize` | Enable blackbox for a GIT or HG repo |
| `blackbox_register_new_file` | Encrypt a file for the first time |
| `blackbox_deregister_file` | Remove a file from blackbox |
| `blackbox_register_new_file <file>` | Encrypt a file for the first time |
| `blackbox_deregister_file <file>` | Remove a file from blackbox |
| `blackbox_list_files` | List the files maintained by blackbox |
| `blackbox_list_admins` | List admins currently authorized for blackbox |
| `blackbox_decrypt_all_files` | Decrypt all managed files (INTERACTIVE) |
| `blackbox_postdeploy` | Decrypt all managed files (batch) |
| `blackbox_addadmin` | Add someone to the list of people that can encrypt/decrypt secrets |
| `blackbox_removeadmin` | Remove someone from the list of people that can encrypt/decrypt secrets |
| `blackbox_addadmin <gpg-key>` | Add someone to the list of people that can encrypt/decrypt secrets |
| `blackbox_removeadmin <gpg-key>` | Remove someone from the list of people that can encrypt/decrypt secrets |
| `blackbox_shred_all_files` | Safely delete any decrypted files |
| `blackbox_update_all_files` | Decrypt then re-encrypt all files. Useful after keys are changed |
| `blackbox_whatsnew` | show what has changed in the last commit for a given file |
| `blackbox_whatsnew <file>` | show what has changed in the last commit for a given file |
Compatibility:
============================
==============
Blackbox automatically determines which VCS you are using
and does the right thing. It has a plug-in architecture
to make it easy to extend to work with other systems.
It has been tested to work with many operating systems.
Blackbox automatically determines which VCS you are using and does the right thing. It has a plug-in architecture to make it easy to extend to work with other systems. It has been tested to work with many operating systems.
* Version Control systems
* `git` -- The Git
* `hg` -- Mercurial
* `svn` -- SubVersion (Thanks, Ben Drasin!)
* `p4` -- Perforce
* none -- The files can be decrypted outside of a repo if the keyrings directory is intact
* Operating system
* CentOS / RedHat
* MacOS X
* Cygwin (Thanks, Ben Drasin!)
- Version Control systems
- `git` -- The Git
- `hg` -- Mercurial
- `svn` -- SubVersion (Thanks, Ben Drasin!)
- `p4` -- Perforce
- none -- The files can be decrypted outside of a repo if the keyrings directory is intact
- Operating system
- CentOS / RedHat
- MacOS X
- Cygwin (Thanks, Ben Drasin!)
- MinGW (git bash on windows) **See Note Below**
To add or fix support for a VCS system, look for code at the end
of `bin/_blackbox_common.sh`
To add or fix support for a VCS system, look for code at the end of `bin/_blackbox_common.sh`
To add or fix support for a new operating system, look for the case
statements in `bin/_blackbox_common.sh` and `bin/_stack_lib.sh` and
maybe `tools/confidence_test.sh`
To add or fix support for a new operating system, look for the case statements in `bin/_blackbox_common.sh` and `bin/_stack_lib.sh` and maybe `tools/confidence_test.sh`
Note: Cywin support requires the following packages:
* Normal operation:
* gnupg
* git or mercurial or subversion or perforce (as appropriate)
* Development (if you will be adding code and want to run the confidence test)
* procps
* make
* git (the confidence test currently only tests git)
- Normal operation:
- gnupg
- git or mercurial or subversion or perforce (as appropriate)
- Development (if you will be adding code and want to run the confidence test)
- procps
- make
- git (the confidence test currently only tests git)
Note: MinGW (comes with Git for Windows) support requires the following additional installations
- Normal operation:
- [Git for Windows](https://git-scm.com/) (not tested with Mercurial)
- Git Bash MINTTY returns a MinGW console. So when you install make sure you pick `MINTTY` instead of windows console. You'll be executing blackbox from the Git Bash prompt.
- You need at least version 2.8.1 of Git for Windows.
- [GnuWin32](https://sourceforge.net/projects/getgnuwin32/files/) - needed for various tools not least of which is mktemp which is used by blackbox
- after downloading the install just provides you with some batch files. Because of prior issues at sourceforge and to make sure you get the latest version of each package the batch files handle the brunt of the work of getting the correct packages and installing them for you.
- from a **windows command prompt** run `download.bat` once it has completed run `install.bat` then add the path for those tools to your PATH (ex: `PATH=%PATH%;c:\GnuWin32\bin`)
- Development:
- unknown
How is the encryption done?
============================
===========================
GPG has many different ways to encrypt a file. BlackBox uses
the mode that lets you specify a list of keys that can decrypt
the messsage.
GPG has many different ways to encrypt a file. BlackBox uses the mode that lets you specify a list of keys that can decrypt the messsage.
If you have 5 people ("admins") that should be able to access
the secrets, each creates a GPG key and adds their public key
to the keychain. The GPG command used to encrypt the file lists
all 5 key names, and therefore any 1 key can decrypt the file.
If you have 5 people ("admins") that should be able to access the secrets, each creates a GPG key and adds their public key to the keychain. The GPG command used to encrypt the file lists all 5 key names, and therefore any 1 key can decrypt the file.
To remove someone's access, remove that admin's key name (i.e. email
address) from the list of admins and re-encrypt all the files.
They can still read the .gpg file (assuming they have access
to the repository) but they can't decrypt it any more.
To remove someone's access, remove that admin's key name (i.e. email address) from the list of admins and re-encrypt all the files. They can still read the .gpg file (assuming they have access to the repository) but they can't decrypt it any more.
*What if they kept a copy of the old repo before you removed
access?* Yes, they can decrypt old versions of the file. This
is why when an admin leaves the team, you should change all
your passwords, SSL certs, and so on. You should have been
doing that before BlackBox, right?
*What if they kept a copy of the old repo before you removed access?* Yes, they can decrypt old versions of the file. This is why when an admin leaves the team, you should change all your passwords, SSL certs, and so on. You should have been doing that before BlackBox, right?
*Why don't you use symmetric keys?* In other words, why mess
with all this GPG key stuff and instead why don't we just encrypt
all the files with a single passphrase. Yes, GPG supports that,
but then we are managing a shared password, which is fraught with problems.
If someone "leaves the team" we would have to communicate to everyone
a new password. Now we just have to remove their key. This scales
better.
*Why don't you use symmetric keys?* In other words, why mess with all this GPG key stuff and instead why don't we just encrypt all the files with a single passphrase. Yes, GPG supports that, but then we are managing a shared password, which is fraught with problems. If someone "leaves the team" we would have to communicate to everyone a new password. Now we just have to remove their key. This scales better.
*How do automated processes decrypt without asking for a password?*
GPG requires a passphrase on a private key. However, it permits
the creation of subkeys that have no passphrase. For automated
processes, create a subkey that is only stored on the machine
that needs to decrypt the files. For example, at Stack Exchange,
when our Continuous Integration (CI) system pushes
a code change to our Puppet masters, they run `blackbox_postdeploy`
to decrypt all the files. The user that runs this code has a subkey
that doesn't require a passphrase. Since we have many masters,
each has its own key. And, yes, this means our Puppet Masters
have to be very secure. However, they were already secure because,
like, dude... if you can break into someone's puppet master you own
their network.
*How do automated processes decrypt without asking for a password?* GPG requires a passphrase on a private key. However, it permits the creation of subkeys that have no passphrase. For automated processes, create a subkey that is only stored on the machine that needs to decrypt the files. For example, at Stack Exchange, when our Continuous Integration (CI) system pushes a code change to our Puppet masters, they run `blackbox_postdeploy` to decrypt all the files. The user that runs this code has a subkey that doesn't require a passphrase. Since we have many masters, each has its own key. And, yes, this means our Puppet Masters have to be very secure. However, they were already secure because, like, dude... if you can break into someone's puppet master you own their network.
*If you use Puppet, why didn't you just use hiera-eyaml?*
There are 4 reasons:
1. This works works with any Git or Mercurial repo, even if you aren't using Puppet.
2. hiera-eyaml decrypts "on demand" which means your Puppet Master now uses a lot of CPU to decrypt keys every time it is contacted. It slows down your master, which, in my case, is already slow enough.
3. This works with binary files, without having to ASCIIify them and paste them into a YAML file. Have you tried to do this with a cert that is 10K long and changes every few weeks? Ick.
4. hiera-eyaml didn't exist when I wrote this.
*If you use Puppet, why didn't you just use hiera-eyaml?* There are 4 reasons:
1. This works with any Git or Mercurial repo, even if you aren't using Puppet.
2. hiera-eyaml decrypts "on demand" which means your Puppet Master now uses a lot of CPU to decrypt keys every time it is contacted. It slows down your master, which, in my case, is already slow enough.
3. This works with binary files, without having to ASCIIify them and paste them into a YAML file. Have you tried to do this with a cert that is 10K long and changes every few weeks? Ick.
4. hiera-eyaml didn't exist when I wrote this.
What does this look like to the typical user?
================================
=============================================
* If you need to, start the GPG Agent: `eval $(gpg-agent --daemon)`
* Decrypt the file so it is editable: `blackbox_edit_start FILENAME`
* (You will need to enter your GPG passphrase.)
* Edit FILENAME as you desire: `vim FILENAME`
* Re-encrypt the file: `blackbox_edit_end FILENAME`
* Commit the changes. `git commit -a` or `hg commit`
Wait... it can be even easier than that!
Run `blackbox_edit FILENAME`, and it'll decrypt the file
in a temp file and call `$EDITOR` on it, re-encrypting again after the editor
is closed.
- If you need to, start the GPG Agent: `eval $(gpg-agent --daemon)`
- Decrypt the file so it is editable: `blackbox_edit_start FILENAME`
- (You will need to enter your GPG passphrase.)
- Edit FILENAME as you desire: `vim FILENAME`
- Re-encrypt the file: `blackbox_edit_end FILENAME`
- Commit the changes. `git commit -a` or `hg commit`
Wait... it can be even easier than that! Run `blackbox_edit FILENAME`, and it'll decrypt the file in a temp file and call `$EDITOR` on it, re-encrypting again after the editor is closed.
How to use the secrets with Puppet?
================================
===================================
### Entire files:
Entire files, such as SSL certs and private keys, are treated just like
regular files. You decrypt them any time you push a new release
to the puppet master.
Entire files, such as SSL certs and private keys, are treated just like regular files. You decrypt them any time you push a new release to the puppet master.
Puppet example for an encrypted file: `secret_file.key.gpg`
@@ -237,13 +190,9 @@ file { '/etc/my_little_secret.key':
}
```
### Small strings:
Small strings, such as passwords and API keys, are stored in a hiera
yaml file, which you encrypt with `blackbox_register_new_file`. For
example, we use a file called `blackbox.yaml`. You can access them
using the hiera() function.
Small strings, such as passwords and API keys, are stored in a hiera yaml file, which you encrypt with `blackbox_register_new_file`. For example, we use a file called `blackbox.yaml`. You can access them using the hiera() function.
*Setup:* Configure `hiera.yaml` by adding "blackbox" to the search hierarchy:
@@ -274,15 +223,14 @@ file {'/tmp/debug-blackbox.txt':
}
```
The variable `$the_password` will contain "my secret password" and
can be used anywhere strings are used.
The variable `$the_password` will contain "my secret password" and can be used anywhere strings are used.
How to enroll a new file into the system?
============================
=========================================
- If you need to, start the GPG Agent: `eval $(gpg-agent --daemon)`
- Add the file to the system:
* If you need to, start the GPG Agent: `eval $(gpg-agent --daemon)`
* Add the file to the system:
```
blackbox_register_new_file path/to/file.name.key
```
@@ -291,38 +239,43 @@ Multiple file names can be specified on the command line:
Example 1: Register 2 files:
blackbox_register_new_file file1.txt file2.txt
```
blackbox_register_new_file file1.txt file2.txt
```
Example 2: Register all the files in `$DIR`:
find $DIR -type f -not -name '*.gpg' -print0 | xargs -0 blackbox_register_new_file
```
find $DIR -type f -not -name '*.gpg' -print0 | xargs -0 blackbox_register_new_file
```
How to remove a file from the system?
============================
=====================================
This happens quite rarely, but we've got it covered:
```
blackbox_deregister_file path/to/file.name.key
```
How to indoctrinate a new user into the system?
============================
===============================================
``keyrings/live/blackbox-admins.txt`` is a file that
lists which users are able to decrypt files.
(More pedantically, it is a list of the GnuPG key
names that the file is encrypted for.)
`keyrings/live/blackbox-admins.txt` is a file that lists which users are able to decrypt files. (More pedantically, it is a list of the GnuPG key names that the file is encrypted for.)
To join the list of people that can edit the file requires three steps; You create a GPG key and add it to the key ring. Then, someone that already has access adds you to the system. Lastly, you should test your access.
### Step 1: YOU create a GPG key pair on a secure machine and add to public keychain.
If you don't already have a GPG key, here's how to generate one:
```
gpg --gen-key
```
Pick defaults for encryption settings, 0 expiration. Pick a VERY GOOD passphrase.
Pick defaults for encryption settings, 0 expiration. Pick a VERY GOOD passphrase. Store the private key securely. Tip: Store it on a secure machine, or one with little or no internet access, with full-disk-encryption, etc. Your employer problably has rules about how to store such things.
Now that you have a GPG key, add yourself as an admin:
```
blackbox_addadmin KEYNAME
@@ -334,23 +287,39 @@ blackbox_addadmin KEYNAME
blackbox_addadmin tal@example.com
```
When the command completes successfully, instructions on how to
commit these changes will be output. Run the command as give.
When the command completes successfully, instructions on how to commit these changes will be output. Run the command as given to commit the changes. It will look like this:
```
NEXT STEP: Check these into the repo. Probably with a command like...
git commit -m'NEW ADMIN: tal@example.com' keyrings/live/pubring.gpg keyrings/live/trustdb.gpg keyrings/live/blackbox-admins.txt
```
Role accounts: If you are adding the pubring.gpg of a role account, you can specify the directory where the pubring.gpg file can be found as a 2nd parameter:
Then push it to the repo:
```
blackbox_addadmin puppetmaster@puppet-master-1.example.com /path/to/the/dir
git push
or
ht push
(or whatever is appropriate)
```
NOTE: Creating a Role Account? If you are adding the pubring.gpg of a role account, you can specify the directory where the pubring.gpg file can be found as a 2nd parameter: `blackbox_addadmin puppetmaster@puppet-master-1.example.com /path/to/the/dir`
### Step 2: SOMEONE ELSE adds you to the system.
Ask someone that already has access to re-encrypt the data files. This gives you access. They simply decrypt and re-encrypt the data without making any changes:
Ask someone that already has access to re-encrypt the data files. This gives you access. They simply decrypt and re-encrypt the data without making any changes.
Pre-check: Verify the new keys look good.
```
$ gpg --homedir=keyrings/live --list-keys
```
For example, examine the key name (email address) to make sure it conforms to corporate standards.
Import the keychain into your personal keychain and reencrypt:
```
gpg --import keyrings/live/pubring.gpg
@@ -374,7 +343,7 @@ hg push
Make sure you can decrypt a file. (Suggestion: Keep a dummy file in VCS just for new people to practice on.)
How to remove a user from the system?
============================
=====================================
Simply run `blackbox_removeadmin` with their keyname then re-encrypt:
@@ -387,9 +356,7 @@ blackbox_update_all_files
When the command completes, you will be given a reminder to check in the change and push it.
Note that their keys will still be in the key ring, but they will
go unused. If you'd like to clean up the keyring, use the normal
GPG commands and check in the file.
Note that their keys will still be in the key ring, but they will go unused. If you'd like to clean up the keyring, use the normal GPG commands and check in the file.
```
gpg --homedir=keyrings/live --list-keys
@@ -399,24 +366,19 @@ git commit -m'Cleaned olduser@example.com from keyring' keyrings/live/*
The key ring only has public keys. There are no secret keys to delete.
Remember that this person did have access to all the secrets at one
time. They could have made a copy. Therefore, to be completely
secure, you should change all passwords, generate new SSL keys, and
so on just like when anyone that had privileged access leaves an
organization.
Remember that this person did have access to all the secrets at one time. They could have made a copy. Therefore, to be completely secure, you should change all passwords, generate new SSL keys, and so on just like when anyone that had privileged access leaves an organization.
First Time Setup (enabling Blackbox for a repo)
===========================
Enabling Blackbox For a Repo
============================
Overview:
To add "blackbox" to a git or mercurial repo, you'll need to do the following:
1. Run the initialize script. This adds a few files to your repo in a directory called "keyrings".
2. For the first user, create a GPG key and add it to the key ring.
3. Encrypt the files you want to be "secret".
4. For any automated user (one that must be able to decrypt without a passphrase), create a GPG key and create a subkey with an empty passphrase.
1. Run the initialize script. This adds a few files to your repo in a directory called "keyrings".
2. For the first user, create a GPG key and add it to the key ring.
3. Encrypt the files you want to be "secret".
4. For any automated user (one that must be able to decrypt without a passphrase), create a GPG key and create a subkey with an empty passphrase.
### Run the initialize script.
@@ -427,17 +389,13 @@ export PATH=$PATH:/the/path/to/blackbox/bin
blackbox_initialize
```
If you're using antigen, adding `antigen bundle StackExchange/blackbox` to
your .zshrc will download this repository and add it to your $PATH.
If you're using antigen, adding `antigen bundle StackExchange/blackbox` to your .zshrc will download this repository and add it to your $PATH.
### For the first user, create a GPG key and add it to the key ring.
Follow the instructions for "How to indoctrinate a new user into
the system?". Only do Step 1.
Follow the instructions for "[How to indoctrinate a new user into the system?](#how-to-indoctrinate-a-new-user-into-the-system)". Only do Step 1.
Once that is done, is a good idea to test the system by making sure
a file can be added to the system (see "How to enroll a new file
into the system?"), and a different user can decrypt the file.
Once that is done, is a good idea to test the system by making sure a file can be added to the system (see "How to enroll a new file into the system?"), and a different user can decrypt the file.
Make a new file and register it:
@@ -456,51 +414,36 @@ echo This is the new file contents. >foo.txt
```
Re-encrypt it:
```
blackbox_edit_end foo.txt.gpg
ls -l foo.txt*
```
Push these changes to the repo. Make sure another user can
check out and change the contents of the file.
You should only see `foo.txt.gpg` as `foo.txt` should be gone.
The next step is to commit `foo.txt.gpg` and make sure another user can check out, view, and change the contents of the file. That is left as an exercise for the reader. If you are feel like taking a risk, don't commit `foo.txt.gpg` and delete it instead.
Set up automated users or "role accounts"
=========================================
i.e. This is how a Puppet Master can have access to the unencrypted data.
An automated user (a "role account") is one that that must be able to decrypt without a passphrase. In general you'll want to do this for the user that pulls the files from the repo to the master. This may be automated with Jenkins CI or other CI system.
An automated user (a "role account") is one that that must be able
to decrypt without a passphrase. In general you'll want to do this
for the user that pulls the files from the repo to the master. This
may be automated with Jenkins CI or other CI system.
GPG keys have to have a passphrase. However, passphrases are optional on subkeys. Therefore, we will create a key with a passphrase then create a subkey without a passphrase. Since the subkey is very powerful, it should be created on a very secure machine.
GPG keys have to have a passphrase. However, passphrases are optional
on subkeys. Therefore, we will create a key with a passphrase then
create a subkey without a passphrase.
Since the subkey is very powerful, it should be created on a very
secure machine.
There's another catch. The role account probably can't check files into Git/Mercurial. It probably only has read-only access to the repo. That's a good security policy. This means that the role account can't be used to upload the subkey public bits into the repo.
There's another catch. The role account probably can't check files
into Git/Mercurial. It probably only has read-only access to the repo. That's
a good security policy. This means that the role account can't
be used to upload the subkey public bits into the repo.
Therefore, we will create the key/subkey on a secure machine as yourself. From there we can commit the public portions into the repo. Also from this account we will export the parts that the role account needs, copy them to where the role account can access them, and import them as the role account.
Therefore, we will create the key/subkey on a secure machine
as yourself. From there we can commit the public portions into
the repo. Also from this account we will export the parts
that the role account needs, copy them to where the role account
can access them, and import them as the role account.
ProTip: If asked to generate entropy, consider running this on the
same machine in another window: `sudo dd if=/dev/sda of=/dev/null`
ProTip: If asked to generate entropy, consider running this on the same machine in another window: `sudo dd if=/dev/sda of=/dev/null`
For the rest of this doc, you'll need to make the following substitutions:
- ROLEUSER: svc_deployacct or whatever your role account's name is.
- NEWMASTER: the machine this role account exists on.
- SECUREHOST: The machine you use to create the keys.
- ROLEUSER: svc_deployacct or whatever your role account's name is.
- NEWMASTER: the machine this role account exists on.
- SECUREHOST: The machine you use to create the keys.
NOTE: This should be more automated/scripted. Patches welcome.
@@ -519,11 +462,7 @@ Key is valid for? (0) DEFAULT
# Email address: svc_deployacct@hostname.domain.name
```
NOTE: Rather than a real email address, use the username@FQDN of
the host the key will be used on. If you use this role account on
many machines, each should have its own key. By using the FQDN of
the host, you will be able to know which key is which.
In this doc, we'll refer to username@FQDN as $KEYNAME
NOTE: Rather than a real email address, use the username@FQDN of the host the key will be used on. If you use this role account on many machines, each should have its own key. By using the FQDN of the host, you will be able to know which key is which. In this doc, we'll refer to username@FQDN as $KEYNAME
Save the passphrase somewhere safe!
@@ -581,8 +520,7 @@ cd /path/to/the/repo
blackbox_addadmin $KEYNAME /tmp/NEWMASTER
```
Verify that secring.gpg is a zero-length file. If it isn't, you have
somehow added a private key to the keyring. Start over.
Verify that secring.gpg is a zero-length file. If it isn't, you have somehow added a private key to the keyring. Start over.
```
$ cd keyrings/live
@@ -630,54 +568,151 @@ rm -rf /tmp/NEWMASTER
Also shred any other temporary files you may have made.
Replace expired keys:
=====================
If any one admin's key expires, you can no longer encrypt files. You will need to replace the key and re-encrypt.
- Step 0: You see this error:
```
$ blackbox_edit_end modified_file.txt
--> Error: can't re-encrypt because a key has expired.
```
- Step 1. Administrator removes expired user:
Warning: This process will erase any unencrypted files that you were in the process of editing. Copy them elsewhere and restore the changes when done.
```
blackbox_removeadmin expired_user@example.com
# This next command overwrites any changed unencrypted files. See warning above.
blackbox_update_all_files
git commit -m "Re-encrypt all files"
gpg --homedir=keyrings/live --delete-key expired_user@example.com
git commit -m 'Cleaned expired_user@example.com from keyring' keyrings/live/*
git push
```
- Step 2. Expired user adds an updated key:
```
git pull
blackbox_addadmin updated_user@example.com
git commit -m'NEW ADMIN: updated_user@example.com keyrings/live/pubring.gpg keyrings/live/trustdb.gpg keyrings/live/blackbox-admins.txt
git push
```
- Step 3. Administrator re-encrypts all files with the updated key of the expired user:
```
git pull
gpg --import keyrings/live/pubring.gpg
blackbox_update_all_files
git commit -m "Re-encrypt all files"
git push
```
- Step 4: Clean up:
Any files that were temporarily copied in the first step so as to not be overwritten can now be copied back and re-encrypted with the `blackbox_edit_end` command.
(Thanks to @chishaku for finding a solution to this problem!)
### Configure git to show diffs in encrypted files
It's possible to tell Git to decrypt versions of the file before running them through `git diff` or `git log`. To achieve this do:
- Add the following to `.gitattributes` at the top of the git repository:
```
*.gpg diff=blackbox
```
- Add the following to `.git/config`:
```
[diff "blackbox"]
textconv = gpg --use-agent -q --batch --decrypt
````
And now commands like `git log -p file.gpg` will show a nice log of the changes in the encrypted file.
Some common errors:
===================
`gpg: filename: skipped: No public key` -- Usually this means there is an item in `keyrings/live/blackbox-admins.txt` that is not the name of the key. Either something invalid was inserted (like a filename instead of a username) or a user has left the organization and their key was removed from the keychain, but their name wasn't removed from the blackbox-admins.txt file.
`gpg: decryption failed: No secret key` -- Usually means you forgot to re-encrypt the file with the new key.
`Error: can't re-encrypt because a key has expired.` -- A user's key has expired and can't be used to encrypt any more. Follow the[Replace expired keys](#replace-expired-keys) tip.
Using Blackbox without a repo
===========================
If the files are copied out of a repo they can still be decrypted
and edited. Obviously edits, changes to keys, and such will be lost
if they are made outside the repo. Also note that commands are most
likely to only work if run from the base directory (i.e. the parent to
the keyrings directory).
=============================
If the files are copied out of a repo they can still be decrypted and edited. Obviously edits, changes to keys, and such will be lost if they are made outside the repo. Also note that commands are most likely to only work if run from the base directory (i.e. the parent to the keyrings directory).
The following commands have been tested outside a repo:
* `blackbox_postdeploy`
* `blackbox_edit_start`
* `blackbox_edit_end`
- `blackbox_postdeploy`
- `blackbox_edit_start`
- `blackbox_edit_end`
Some Subversion gotchas:
========================
Help out: Submit bugs, pull requests and ideas:
============
The current implementation will store the blackbox in `/keyrings` at the root of the entire repo. this will create an issue between environments that have different roots (ie, checking out `/` on development vs `/releases/foo` in production). To get around this, you can `export BLACKBOX_REPOBASE=/path/to/repo` and set a specific base for your repo.
I welcome code changes, questions, bug reports and feedback!
This was originally written for git and supports a two-phase commit, in which `commit` is a local commit and "push" sends the change upstream to the version control server when something is registered or deregistered with the system. The current implementation will immediately `commit` a file (to the upstream subversion server) when you execute a `blackbox_*` command.
* Submit code: https://github.com/StackExchange/blackbox
* Report bugs/questions: https://github.com/StackExchange/blackbox/issues
How to submit bugs or ask questions?
====================================
Tip for submitting code:
We welcome questions, bug reports and feedback!
After you make a change, please re-run the confidence tests. This
runs through various procedures and checks the results.
The best place to start is to join the [blackbox-project mailing list](https://groups.google.com/d/forum/blackbox-project) and ask there.
To run the tests:
Bugs are tracked here in Github. Please feel free to files bugs yourself:
- https://github.com/StackExchange/blackbox/issues
Developer Info
==============
Code submissions are gladly welcomed! The code is fairly easy to read.
Get the code:
```
git clone git@github.com:StackExchange/blackbox.git
```
Test your changes:
```
make confidence
```
Note: The tests currently assume "git" and have been tested
on CentOS and Cygwin.
This runs through a number of system tests. It creates a repo, encrypts files, decrypts files, and so on. You can run these tests to verify that the changes you made didn't break anything. You can also use these tests to verify that the system works with a new operating system.
Please submit tests with code changes:
The best way to change Blackbox is via Test Driven Development. First add a test to `tools/confidence.sh`. This test should fail, and demonstrate the need for the change you are about to make. Then fix the bug or add the feature you want. When you are done, `make confidence` should pass all tests. The PR you submit should include your code as well as the new test. This way the confidence tests accumulate as the system grows as we know future changes don't break old features.
Note: The tests currently assume "git" and have been tested only on CentOS, Mac OS X, and Cygwin. Patches welcome!
Alternatives
============
Here are other open source packages that do something similar to Blackbox. If you like them better than Blackbox, please use them.
* Pass: http://www.zx2c4.com/projects/password-store/
* Transcrypt: https://github.com/elasticdog/transcrypt
* git-crypt: https://www.agwa.name/projects/git-crypt/
- git-crypt: https://www.agwa.name/projects/git-crypt/
- Pass: http://www.zx2c4.com/projects/password-store/
- Transcrypt: https://github.com/elasticdog/transcrypt
- Keyringer: https://keyringer.pw/
- git-secret: https://github.com/sobolevn/git-secret
git-crypt has the best git integration. Once set up it is nearly transparent to the users. However it only works with git.
License
=======
This content is released under the MIT License. See the LICENSE.txt file.

152
RELEASE_ENGINEERING.md Normal file
View File

@@ -0,0 +1,152 @@
Table of Contents:
==================
- [Branches and Tags:](#branches-and-tags)
- [Build Tasks](#build-tasks)
- [Stable Releases](#stable-releases)
- [Production Releases](#production-releases)
- [Updating MacPorts (automatic)](#updating-macports-automatic)
- [Updating MacPorts (manual)](#updating-macports-manual)
Branches and Tags:
==================
There are 3 branches/tags:
- **HEAD:** The cutting edge of development.
- **tag stable:** Stable enough for use by most people.
- **tag production:** Burned in long enough that we are confident it can be widely adopted.
If you are packaging Blackbox for distribution, you should track the *tag production*. You might also want to provide a separate package that tracks *tag stable:* for early adopters.
Build Tasks
===========
Stable Releases
===============
Marking the software to be "stable":
Step 1. Update CHANGELOG.md
Use "git log" to see what has changed and update CHANGELOG.md.
For a new release, add:
```
echo Release v1.$(date +%Y%m%d)
```
Commit with:
```
git commit -m'Update CHANGELOG.md' CHANGELOG.md
```
Step 2. Tag it.
```
git pull
git tag -d stable
git push origin :stable
git tag stable
git push origin tag stable
```
Step 3. Mark your calendar 1 week from today to check to see if this should be promoted to production.
Production Releases
===================
If no bugs have been reported a full week after a stable tag has been pushed, mark the release to be "production".
```
git fetch
git checkout stable
git tag -d production
git push origin :production
git tag production
git push origin tag production
R="v1.$(date +%Y%m%d)"
git tag "$R"
git push origin tag "$R"
```
Updating MacPorts (automatic)
=============================
Step 1: Generate the Portfile
```
tools/macports_report_upgrade.sh 1.20150222
```
This script will generate a file called `Portfile-vcs_blackbox.diff` and instructions on how to submit it as a update request.
Step 2: Submit the update request.
Submit the diff file as a bug as instructed. The instructions should look like this:
- PLEASE OPEN A TICKET WITH THIS INFORMATION: https://trac.macports.org/newticket
- Summary: `vcs_blackbox @1.20150222 Update to latest upstream`
- Description: `New upstream of vcs_blackbox.
github.setup and checksums updated.`
- Type: `update`
- Component: `ports`
- Port: `vcs_blackbox`
- Keywords: `maintainer haspatch`
- Attach this file: `Portfile-vcs_blackbox.diff`
Step 3: Watch for the update to happen.
Updating MacPorts (manual)
==========================
This is the old, manual, procedure. If the automated procedure fails to work, these notes may or may not be helpful.
The ultimate result of the script should be the output of `diff -u Portfile.orig Portfile` which is sent as an attachment to MacPorts. The new `Portfile` should have these changes:
1. The `github.setup` line should have a new version number.
2. The `checksums` line(s) should have updated checksums.
How to generate the checksums?
The easiest way is to to make a Portfile with incorrect checksums, then run `sudo port -v checksum vcs_blackbox` to see what they should have been. Fix the file, and try again until the checksum command works.
Next run `port lint vcs_blackbox` and make sure it has no errors.
Some useful commands:
Change repos in sources.conf:
```
sudo vi /opt/local/etc/macports/sources.conf
Add this line early in the file:
file:///var/tmp/ports
```
Add a local repo:
```
fgrep >/dev/null -x 'file:///var/tmp/ports' /opt/local/etc/macports/sources.conf || sudo sed -i -e '1s@^@file:///var/tmp/ports\'$'\n@' /opt/local/etc/macports/sources.conf
```
Remove the local repo:
```
sudo sed -i -e '\@^file:///var/tmp/ports@d' /opt/local/etc/macports/sources.conf
```
Test a Portfile:
```
sudo port uninstall vcs_blackbox
sudo port clean --all vcs_blackbox
rm -rf ~/.macports/opt/local/var/macports/sources/rsync.macports.org/release/tarballs/ports/security/vcs_blackbox/
rm -rf /var/tmp/ports
mkdir -p /var/tmp/ports/security/vcs_blackbox
cp Portfile /var/tmp/ports/security/vcs_blackbox
cd /var/tmp/ports && portindex
sudo port -v checksum vcs_blackbox
sudo port install vcs_blackbox
```

View File

@@ -1,119 +0,0 @@
# Branches and Tags:
There are 3 branches/tags:
* **HEAD:** The cutting edge of development.
* **tag stable:** Stable enough for use by most people.
* **tag production:** Burned in long enough that we are confident it can be widely adopted.
If you are packaging Blackbox for distribution, you should track the *tag production*. You might also want to provide a separate package that tracks *tag stable:* for early adopters.
# Build Tasks
# Stable Releases
Marking the software to be "stable":
Step 1. Tag it.
```
git pull
git tag -d stable
git push origin :stable
git tag stable
git push origin tag stable
```
Step 2. Mark your calendar 1 week from today to check
to see if this should be promoted to production.
# Production Releases
If no bugs have been reported a full week after a stable tag has been pushed, mark the release to be "production".
```
git fetch
git checkout stable
git tag -d production
git push origin :production
git tag production
git push origin tag production
R="v1.$(date +%Y%m%d)"
git tag "$R"
git push origin tag "$R"
```
# Updating MacPorts (automatic)
Step 1: Generate the Portfile
```
tools/macports_report_upgrade.sh 1.20150222
```
This script will generate a file called `Portfile-vcs_blackbox.diff` and instructions on how to submit it as a update request.
Step 2: Submit the update request.
Submit the diff file as a bug as instructed. The instructions should look like this:
* PLEASE OPEN A TICKET WITH THIS INFORMATION:
https://trac.macports.org/newticket
* Summary: `vcs_blackbox @1.20150222 Update to latest upstream`
* Description: ```New upstream of vcs_blackbox.
github.setup and checksums updated.```
* Type: `update`
* Component: `ports`
* Port: `vcs_blackbox`
* Keywords: `maintainer`
* Attach this file: `Portfile-vcs_blackbox.diff`
Step 3: Watch for the update to happen.
# Updating MacPorts (manual)
This is the old, manual, procedure. If the automated procedure work, these notes may or may not be helpful.
The ultimate result of the script should be a `diff -u Portfile.orig Portfile`. The new `Portfile` should have these changes:
1. The `github.setup` line should have a new version number.
2. The `checksums` line(s) should have updated checksums.
How to generate the checksums?
The easiest way is to to make a Portfile with incorrect checksums, then run `sudo port -v checksum vcs_blackbox` to see what they should have been. Fix the file, and try again.
When the the checksum command works, run `port lint vcs_blackbox` and make sure it has no errors.
Some useful commands:
Change repos in sources.conf:
```
sudo vi /opt/local/etc/macports/sources.conf
Add this line early in the file:
file:///var/tmp/ports
```
Add a local repo in an automated manner:
```
fgrep >/dev/null -x 'file:///var/tmp/ports' /opt/local/etc/macports/sources.conf || sudo sed -i -e '1s@^@file:///var/tmp/ports\'$'\n@' /opt/local/etc/macports/sources.conf
```
Remove the local repo in an automated manner:
```
sudo sed -i -e '\@^file:///var/tmp/ports@d' /opt/local/etc/macports/sources.conf
```
Test a Portfile:
```
sudo port uninstall vcs_blackbox
sudo port clean --all vcs_blackbox
rm -rf ~/.macports/opt/local/var/macports/sources/rsync.macports.org/release/tarballs/ports/security/vcs_blackbox/
rm -rf /var/tmp/ports
mkdir -p /var/tmp/ports/security/vcs_blackbox
cp Portfile /var/tmp/ports/security/vcs_blackbox
cd /var/tmp/ports && portindex
sudo port -v checksum vcs_blackbox
sudo port install vcs_blackbox
```

97
Version2-Ideas.md Normal file
View File

@@ -0,0 +1,97 @@
# Ideas for blackbox Version 2
I'm writing this to solicit feedback and encourage discussion.
Here are my thoughts on a "verison 2" of blackbox. This is where
I list ideas that would require major changes to the system. They
might break backwards compatibility, though usually not.
Blackbox grew from a few simple shell scripts used at StackOverflow.com
to a larger system used by dozens (hundreds?) of organizations. Not
all the design decisions were "forward looking".
These are the things I'd like to change someday.
[TOC]
## Change the commmand names
There should be one program, with subcommands that have names that make more sense:
* `blackbox init`
* `blackbox register <filename> <...>`
* `blackbox deregister <filename> <...>`
* `blackbox edit <filename> <...>`
* `blackbox decrypt <filename> <...>`
* `blackbox encrypt <filename> <...>`
* `blackbox decrypt_all`
* `blackbox addadmin <key>`
* `blackbox removeadmin <key>`
* `blackbox cat <filename> <...>`
* `blackbox diff <filename> <...>`
* `blackbox list_files`
* `blackbox list_admins`
* `blackbox shred_all`
* `blackbox update_all`
* `blackbox whatsnew`
Backwards compatibility: The old commands would simply call the new commands.
## Change the "keyrings" directory
The name "keyrings" was unfortunate. First, it should probably begin with a ".". Second, it stores more than just keyrings. Lastly, I'm finding that in most cases we want many repos to refer to the same keyring, which is not supported very well.
A better system would be:
1. If `$BLACKBOX_CONFIG` is set, use that directory.
2. If the repo base directory has a file called ".blackbox_external", read that file as if you are reading `$BLACKBOX_CONFIG`
3. If the repo base directory has a "keyrings" directory, use that.
4. If the repo base directory has a ".blackboxconfig" directory, use that.
Some thoughts on .blackbox_external:
I'm not sure what the format should be, but I want it to be simple and expandable. It should support support "../../dir/name" and "/long/path". However some day we may want to include a Git URL and have the system automatically get the keychain from it. That means the format has to be something like directory:../dir/name so that later we can add git:the_url.
Backwards compatibility: "keyrings" would be checked before .blackbox
## Repo-less mode
I can't imagine storing files that aren't in a repo. I just put everything in repos lately. I use it more than I use NFS. That said, I have received feedback that people would like the ability to disable automatic committing of files.
I prefer the file commits to be automatic because when they were manual, people often accidentally committed the plaintext file instead of the GPG file. Fixing such mistakes is a PITA and, of yeah, a big security nightmare.
That said, I'm willing to have a "repo-less" mode.
When this mode is triggered, no add/commit/ignore tasks are done. The search for the keyrings directory still uses `$BLACKBOX_CONFIG` but if that is unset it looks for .blackbox_config in the current directory, then recursively ".." until we hit "/".
I think (but I'm not sure) this would benefit the entire system because it would force us to re-think what VCS actions are done when.
I think (but I'm not sure) that a simple way to implement this would be to add an environment variable that overrides the automatic VCS detection. When set to "none", all VCS operations would basically become no-ops. (This could be done by writing a plug-in that does nothing for all the vcs_* calls)
Backwards compatibility: This would add a "none" VCS, not remove any existing functionality.
## Is "bash" the right language?
`bash` is fairly universal. It even exists on Windows. However it is not the right language for large systems. Writing the acceptance tests is quite a bear. Managing ".gitignore" files in bash is impossible and the current implementation fails in many cases.
`python` is my second favorite langauge. It would make the code cleaner and more testable. However it is not installed everywhere. I would also want to write it in Python3 (why start a new project in Python2?) but sadly Python3 is less common. It is a chicken vs. egg situation.
`go` is my favorite language. I could probably rewrite this in go in a weekend. However, now the code is compiled, not interpreted. Therefore we lose the ability to just "git clone" and have the tools you want. Not everyone has a Go compiler installed on every machine.
The system is basically unusable on Windows without Cygwin or MINGW. A rewrite in python or go would make it work better on Windows, which currently requires Cygwin or MinGW (which is a bigger investment than installing Python). On the other hand, maybe Ubuntu-on-Windows makes that a non-issue.
As long as the code is in `bash` the configuration files like `blackbox-files.txt` and `blackbox-admins.txt` have problems. Filenames with carriage returns aren't supported. If this was in Python/Go/etc. those files could be json or some format with decent quoting and we could handle funny file names better. On the other hand, maybe it is best that we don't support funny filenames... we shouldn't enable bad behavior.
How important is itto blackbox users that the system is written in "bash"?
## ditch the project and use git-crypt
People tell me that git-crypt is better because, as a plug-in, automagically supports "git diff", "git log" and "git blame".
However, I've never used it so I don't have any idea whether git-crypt is any better than blackbox.
Of course, git-crypt doesn't work with SVN, HG, or any other VCS. Is blackbox's strong point the fact that it support so many VCS systems? To be honest, it originally only supported HG and GIT because I was at a company that used HG but then changed to GIT. Supporting anything else was thanks to contributors. Heck, HG support hasn't even been tested recently (by me) since we've gone all git where I work.
How important is this to blackbox users?

View File

@@ -28,7 +28,7 @@ source "${0%/*}"/_stack_lib.sh
function physical_directory_of() {
local d=$(dirname "$1")
local f=$(basename "$1")
(cd "$d" && echo $(pwd -P)"/$f" )
(cd "$d" && echo "$(pwd -P | sed 's/\/$//')/$f" )
}
# Set REPOBASE to the top of the repository
@@ -62,6 +62,11 @@ export REPOBASE=$(physical_directory_of "$REPOBASE")
# FIXME: Verify this function by checking for .hg or .git
# after determining what we believe to be the answer.
if [[ -n "$BLACKBOX_REPOBASE" ]]; then
echo "Using custom repobase: $BLACKBOX_REPOBASE"
export REPOBASE="$BLACKBOX_REPOBASE"
fi
KEYRINGDIR="$REPOBASE/$BLACKBOXDATA"
BB_ADMINS_FILE="blackbox-admins.txt"
BB_ADMINS="${KEYRINGDIR}/${BB_ADMINS_FILE}"
@@ -158,8 +163,16 @@ function get_encrypted_filename() {
# Prepare keychain for use.
function prepare_keychain() {
local keyringasc
echo '========== Importing keychain: START' >&2
$GPG --import "$(get_pubring_path)" 2>&1 | egrep -v 'not changed$' >&2
# Works with gpg 2.0
#$GPG --import "$(get_pubring_path)" 2>&1 | egrep -v 'not changed$' >&2
# Works with gpg 2.0 and 2.1
# NB: We must export the keys to a format that can be imported.
make_self_deleting_tempfile keyringasc
export LANG="C.UTF-8"
$GPG --export --keyring "$(get_pubring_path)" >"$keyringasc"
$GPG --import "$keyringasc"
echo '========== Importing keychain: DONE' >&2
}
@@ -272,7 +285,11 @@ function shred_file() {
#NOTE: srm by default uses 35-pass Gutmann algorithm
CMD=srm
OPT=-f
elif _F=$(mktemp); rm -P "${_F}" >/dev/null 2>/dev/null ; then
CMD=rm
OPT=-Pf
else
echo "shred_file: WARNING: No secure deletion utility (shred or srm) present; using insecure rm" >&2
CMD=rm
OPT=-f
fi
@@ -329,7 +346,11 @@ function enumerate_blackbox_repos() {
function vcs_relative_path() {
# Usage: vcs_relative_path file
local name="$1"
python -c 'import os ; print(os.path.relpath("'"$(pwd -P)"'/'"$name"'", "'"$REPOBASE"'"))'
#python -c 'import os ; print(os.path.relpath("'"$(pwd -P)"'/'"$name"'", "'"$REPOBASE"'"))'
local p=$( printf "%s" "$( pwd -P )/${1}" | sed 's#//*#/#g' )
local name="${p#$REPOBASE}"
name=$( printf "%s" "$name" | sed 's#^/##g' | sed 's#/$##g' )
printf "%s" "$name"
}
# Removes a line from a text file
@@ -364,17 +385,14 @@ function file_contains_line() {
function md5sum_file() {
# Portably generate the MD5 hash of file $1.
case $(uname -s) in
Darwin )
Darwin | FreeBSD )
md5 -r "$1" | awk '{ print $1 }'
;;
Linux )
md5sum "$1" | awk '{ print $1 }'
;;
CYGWIN* )
Linux | CYGWIN* | MINGW* )
md5sum "$1" | awk '{ print $1 }'
;;
* )
echo 'ERROR: Unknown OS. Exiting.'
echo 'ERROR: Unknown OS. Exiting. (md5sum_file)'
exit 1
;;
esac
@@ -386,11 +404,14 @@ function cp_permissions() {
Darwin )
chmod $( stat -f '%p' "$1" ) "${@:2}"
;;
Linux | CYGWIN* )
FreeBSD )
chmod $( stat -f '%p' "$1" | sed -e "s/^100//" ) "${@:2}"
;;
Linux | CYGWIN* | MINGW* )
chmod --reference "$1" "${@:2}"
;;
* )
echo 'ERROR: Unknown OS. Exiting.'
echo 'ERROR: Unknown OS. Exiting. (cp_permissions)'
exit 1
;;
esac
@@ -561,10 +582,11 @@ function vcs_ignore_hg() {
# Git
function vcs_ignore_git() {
vcs_ignore_generic_file "$(vcs_ignore_file_path)" "$file"
git add "$REPOBASE/.gitignore"
}
# Subversion
function vcs_ignore_svn() {
svn propset svn:ignore "$(vcs_relative_path "$file")"
svn propset svn:ignore "$file" "$(vcs_relative_path)"
}
# Perforce
function vcs_ignore_p4() {
@@ -602,6 +624,7 @@ function vcs_notice_hg() {
# Git
function vcs_notice_git() {
vcs_notice_generic_file "$REPOBASE/.gitignore" "$file"
git add "$REPOBASE/.gitignore"
}
# Subversion
function vcs_notice_svn() {
@@ -631,3 +654,20 @@ function vcs_notice_generic_file() {
echo "WARNING: If so, manually update the ignore file"
fi
}
function gpg_agent_version_check() {
if ! hash 'gpg-agent' &> /dev/null; then
return 1
fi
local gpg_agent_version=$(gpg-agent --version | head -1 | awk '{ print $3 }' | tr -d '\n')
semverLT $gpg_agent_version "2.1.0"
}
function gpg_agent_notice() {
if [[ $(gpg_agent_version_check) == '0' && -z $GPG_AGENT_INFO ]];then
echo 'WARNING: You probably want to run gpg-agent as'
echo 'you will be asked for your passphrase many times.'
echo 'Example: $ eval $(gpg-agent --daemon)'
read -r -p 'Press CTRL-C now to stop. ENTER to continue: '
fi
}

View File

@@ -53,15 +53,15 @@ function create_self_deleting_tempfile() {
local filename
case $(uname -s) in
Darwin )
: ${TMPDIR:=/tmp} ;
Darwin | FreeBSD )
: "${TMPDIR:=/tmp}" ;
filename=$(mktemp -t _stacklib_.XXXXXXXX )
;;
Linux )
Linux | CYGWIN* | MINGW* )
filename=$(mktemp)
;;
* )
echo 'ERROR: Unknown OS. Exiting.'
echo 'ERROR: Unknown OS. Exiting. (create_self_deleting_tempfile)'
exit 1
;;
esac
@@ -74,15 +74,15 @@ function create_self_deleting_tempdir() {
local filename
case $(uname -s) in
Darwin )
: ${TMPDIR:=/tmp} ;
filename=$(mktemp -d -t _stacklib_ )
Darwin | FreeBSD )
: "${TMPDIR:=/tmp}" ;
filename=$(mktemp -d -t _stacklib_.XXXXXXXX )
;;
Linux )
Linux | CYGWIN* | MINGW* )
filename=$(mktemp -d)
;;
* )
echo 'ERROR: Unknown OS. Exiting.'
echo 'ERROR: Unknown OS. Exiting. (create_self_deleting_tempdir)'
exit 1
;;
esac
@@ -98,15 +98,15 @@ function make_self_deleting_tempfile() {
local name
case $(uname -s) in
Darwin )
: ${TMPDIR:=/tmp} ;
name=$(mktemp -t _stacklib_ )
Darwin | FreeBSD )
: "${TMPDIR:=/tmp}" ;
name=$(mktemp -t _stacklib_.XXXXXXXX )
;;
Linux )
Linux | CYGWIN* | MINGW* )
name=$(mktemp)
;;
* )
echo 'ERROR: Unknown OS. Exiting.'
echo 'ERROR: Unknown OS. Exiting. (make_self_deleting_tempfile)'
exit 1
;;
esac
@@ -120,15 +120,18 @@ function make_tempdir() {
local name
case $(uname -s) in
Darwin )
: ${TMPDIR:=/tmp} ;
name=$(mktemp -d -t _stacklib_ )
Darwin | FreeBSD )
: "${TMPDIR:=/tmp}" ;
# The full path to the temp directory must be short.
# This is used by blackbox's testing suite to make a fake GNUPGHOME,
# which needs to fit within sockaddr_un.sun_path (see unix(7)).
name=$(mktemp -d -t SO )
;;
Linux )
Linux | CYGWIN* | MINGW* )
name=$(mktemp -d)
;;
* )
echo 'ERROR: Unknown OS. Exiting.'
echo 'ERROR: Unknown OS. Exiting. (make_tempdir)'
exit 1
;;
esac
@@ -157,21 +160,14 @@ function fail_if_not_running_as_root() {
function fail_if_in_root_directory() {
# Verify nobody has tricked us into being in "/".
case $(uname -s) in
Darwin )
Darwin | FreeBSD )
if [[ $(stat -f'%i' / ) == $(stat -f'%i' . ) ]] ; then
echo 'SECURITY ALERT: The current directory is the root directory.'
echo 'Exiting...'
exit 1
fi
;;
Linux )
if [[ $(stat -c'%i' / ) == $(stat -c'%i' . ) ]] ; then
echo 'SECURITY ALERT: The current directory is the root directory.'
echo 'Exiting...'
exit 1
fi
;;
CYGWIN* )
Linux | CYGWIN* | MINGW* )
if [[ $(stat -c'%i' / ) == $(stat -c'%i' . ) ]] ; then
echo 'SECURITY ALERT: The current directory is the root directory.'
echo 'Exiting...'
@@ -179,8 +175,114 @@ function fail_if_in_root_directory() {
fi
;;
* )
echo 'ERROR: Unknown OS. Exiting.'
echo 'ERROR: Unknown OS. Exiting. (fail_if_in_root_directory)'
exit 1
;;
esac
}
function semverParseInto() {
local RE='[^0-9]*\([0-9]*\)[.]\([0-9]*\)[.]\([0-9]*\)\([0-9A-Za-z-]*\)'
#MAJOR
eval $2=`echo $1 | sed -e "s#$RE#\1#"`
#MINOR
eval $3=`echo $1 | sed -e "s#$RE#\2#"`
#MINOR
eval $4=`echo $1 | sed -e "s#$RE#\3#"`
#SPECIAL
eval $5=`echo $1 | sed -e "s#$RE#\4#"`
}
function semverEQ() {
local MAJOR_A=0
local MINOR_A=0
local PATCH_A=0
local SPECIAL_A=0
local MAJOR_B=0
local MINOR_B=0
local PATCH_B=0
local SPECIAL_B=0
semverParseInto $1 MAJOR_A MINOR_A PATCH_A SPECIAL_A
semverParseInto $2 MAJOR_B MINOR_B PATCH_B SPECIAL_B
if [ $MAJOR_A -ne $MAJOR_B ]; then
return 1
fi
if [ $MINOR_A -ne $MINOR_B ]; then
return 1
fi
if [ $PATCH_A -ne $PATCH_B ]; then
return 1
fi
if [[ "_$SPECIAL_A" != "_$SPECIAL_B" ]]; then
return 1
fi
return 0
}
function semverLT() {
local MAJOR_A=0
local MINOR_A=0
local PATCH_A=0
local SPECIAL_A=0
local MAJOR_B=0
local MINOR_B=0
local PATCH_B=0
local SPECIAL_B=0
semverParseInto $1 MAJOR_A MINOR_A PATCH_A SPECIAL_A
semverParseInto $2 MAJOR_B MINOR_B PATCH_B SPECIAL_B
if [ $MAJOR_A -lt $MAJOR_B ]; then
return 0
fi
if [[ $MAJOR_A -le $MAJOR_B && $MINOR_A -lt $MINOR_B ]]; then
return 0
fi
if [[ $MAJOR_A -le $MAJOR_B && $MINOR_A -le $MINOR_B && $PATCH_A -lt $PATCH_B ]]; then
return 0
fi
if [[ "_$SPECIAL_A" == "_" ]] && [[ "_$SPECIAL_B" == "_" ]] ; then
return 1
fi
if [[ "_$SPECIAL_A" == "_" ]] && [[ "_$SPECIAL_B" != "_" ]] ; then
return 1
fi
if [[ "_$SPECIAL_A" != "_" ]] && [[ "_$SPECIAL_B" == "_" ]] ; then
return 0
fi
if [[ "_$SPECIAL_A" < "_$SPECIAL_B" ]]; then
return 0
fi
return 1
}
function semverGT() {
semverEQ $1 $2
local EQ=$?
semverLT $1 $2
local LT=$?
if [ $EQ -ne 0 ] && [ $LT -ne 0 ]; then
return 0
else
return 1
fi
}

View File

@@ -14,9 +14,7 @@
export PATH=/usr/bin:/bin:"$PATH"
set -e
source "${0%/*}/_blackbox_common.sh"
if [[ -z $GPG_AGENT_INFO ]]; then
eval $(gpg-agent --daemon)
fi
gpg_agent_notice
exec blackbox_postdeploy "$@"

View File

@@ -26,6 +26,7 @@ fail_if_not_exists "$encrypted_file" "Please specify an existing file."
prepare_keychain
remove_filename_from_cryptlist "$unencrypted_file"
vcs_remove "$encrypted_file"
vcs_notice "$unencrypted_file"
vcs_add "$BB_FILES"
vcs_commit "Removing from blackbox: ${unencrypted_file}" "$BB_FILES" "$encrypted_file"

View File

@@ -7,13 +7,7 @@
set -e
source "${0%/*}/_blackbox_common.sh"
if [[ -z $GPG_AGENT_INFO ]]; then
echo 'WARNING: You probably want to run gpg-agent as'
echo 'you will be asked for your passphrase many times.'
echo 'Example: $ eval $(gpg-agent --daemon)'
read -r -p 'Press CTRL-C now to stop. ENTER to continue: '
fi
gpg_agent_notice
prepare_keychain
modified_files=()

View File

@@ -27,7 +27,7 @@ for param in "$@" ; do
esac
fi
"${BLACKBOX_HOME}/blackbox_edit_start" "$unencrypted_file"
"$EDITOR" "$(get_unencrypted_filename "$unencrypted_file")"
$EDITOR "$(get_unencrypted_filename "$unencrypted_file")"
"${BLACKBOX_HOME}/blackbox_edit_end" "$unencrypted_file"
done

View File

@@ -9,6 +9,11 @@ source "${0%/*}/_blackbox_common.sh"
next_steps=()
if [ $# -eq 0 ]; then
echo >&2 "Please provide at least one file for which editing has finished"
exit 1
fi
for param in "$@" ; do
unencrypted_file=$(get_unencrypted_filename "$param")

View File

@@ -7,6 +7,11 @@
set -e
source "${0%/*}/_blackbox_common.sh"
if [ $# -eq 0 ]; then
echo >&2 "Please provide at least one file to start editing"
exit 1
fi
for param in "$@" ; do
unencrypted_file=$(get_unencrypted_filename "$param")

View File

@@ -19,10 +19,15 @@ if [[ $1 != 'yes' ]]; then
fi
fi
if [[ $VCS_TYPE = "unknown" ]]; then
echo 'Not in a known VCS directory'
exit 1
fi
change_to_vcs_root
echo VCS_TYPE: $VCS_TYPE
vcs_ignore keyrings/live/pubring.gpg~ keyrings/live/pubring.kbx~ keyrings/live/secring.gpg
vcs_ignore "${BLACKBOXDATA}/pubring.gpg~" "${BLACKBOXDATA}/pubring.kbx~" "${BLACKBOXDATA}/secring.gpg"
# Make directories
mkdir -p "${KEYRINGDIR}"
@@ -30,11 +35,17 @@ vcs_add "${KEYRINGDIR}"
touch "$BLACKBOXDATA/$BB_ADMINS_FILE" "$BLACKBOXDATA/$BB_FILES_FILE"
vcs_add "$BLACKBOXDATA/$BB_ADMINS_FILE" "$BLACKBOXDATA/$BB_FILES_FILE"
IGNOREFILE="$(vcs_ignore_file_path)"
test -f "$IGNOREFILE" && vcs_add "$IGNOREFILE"
if [[ $VCS_TYPE = "svn" ]]; then
echo
echo
echo '`subversion` automatically tracks the ignored files; you just need to commit.'
else
IGNOREFILE="$(vcs_ignore_file_path)"
test -f "$IGNOREFILE" && vcs_add "$IGNOREFILE"
# Make a suggestion:
echo
echo
echo 'NEXT STEP: You need to manually check these in:'
echo ' ' $VCS_TYPE commit -m\'INITIALIZE BLACKBOX\' keyrings "$IGNOREFILE"
# Make a suggestion:
echo
echo
echo 'NEXT STEP: You need to manually check these in:'
echo ' ' $VCS_TYPE commit -m\'INITIALIZE BLACKBOX\' keyrings "$IGNOREFILE"
fi

8
bin/blackbox_list_admins Executable file
View File

@@ -0,0 +1,8 @@
#!/usr/bin/env bash
#
# blackbox_list_admins -- List authorized admins
#
set -e
source "${0%/*}/_blackbox_common.sh"
cat "$BB_ADMINS"

18
bin/blackbox_listadmins Executable file
View File

@@ -0,0 +1,18 @@
#!/usr/bin/env bash
#
# blackbox_listadmins -- List active admins for keyring
#
# Example:
# blackbox_listadmins
#
set -e
source "${0%/*}/_blackbox_common.sh"
fail_if_not_in_repo
# simply display the contents of the admins file
cat "$BB_ADMINS"

View File

@@ -36,7 +36,7 @@ function register_new_file() {
echo "========== UPDATING REPO:"
shred_file "$unencrypted_file"
if "$SECRETSEXPOSED" ; then
if [[ "$SECRETSEXPOSED" == "true" ]] ; then
vcs_remove "$unencrypted_file"
vcs_add "$encrypted_file"
fi
@@ -52,5 +52,9 @@ for target in "$@"; do
done
echo "========== UPDATING VCS: DONE"
echo "Local repo updated. Please push when ready."
echo " $VCS_TYPE push"
if [[ $VCS_TYPE = "svn" ]]; then
echo "Local repo updated and file pushed to source control (unless an error was displayed)."
else
echo "Local repo updated. Please push when ready."
echo " $VCS_TYPE push"
fi

View File

@@ -20,8 +20,15 @@ KEYNAME="$1"
# Remove the email address from the BB_ADMINS file.
remove_line "$BB_ADMINS" "$KEYNAME"
# remove the admin key from the pubring
$GPG --no-permission-warning --homedir="$KEYRINGDIR" --batch --yes --delete-key "$KEYNAME" || true
pubring_path=$(get_pubring_path)
vcs_add "$pubring_path" "$KEYRINGDIR/trustdb.gpg" "$BB_ADMINS"
# Make a suggestion:
echo
echo
echo 'NEXT STEP: Check these into the repo. Probably with a command like...'
echo $VCS_TYPE commit -m\'REMOVED ADMIN: $KEYNAME\' "$BLACKBOXDATA/$BB_ADMINS_FILE"
echo $VCS_TYPE commit -m\'REMOVED ADMIN: $KEYNAME\' "$BLACKBOXDATA/trustdb.gpg" "$BLACKBOXDATA/$BB_ADMINS_FILE"

View File

@@ -21,13 +21,24 @@ source "${0%/*}/_blackbox_common.sh"
change_to_vcs_root
echo '========== FILES BEING SHREDDED:'
while IFS= read <&99 -r unencrypted_file; do
unencrypted_file=$(get_unencrypted_filename "$unencrypted_file")
encrypted_file=$(get_encrypted_filename "$unencrypted_file")
exported_internal_shred_file() {
source "$1/_blackbox_common.sh"
unencrypted_file="$2"
if [[ -f "$unencrypted_file" ]]; then
echo " $unencrypted_file"
echo " SHRED: $unencrypted_file"
shred_file "$unencrypted_file"
else
echo "NOT FOUND: $unencrypted_file"
fi
done 99<"$BB_FILES"
}
export -f exported_internal_shred_file
DEREFERENCED_BIN_DIR="${0%/*}"
MAX_PARALLEL_SHRED=10
export IFS=
tr '\n' '\0' <"$BB_FILES" | xargs -0 -I{} -n 1 -P $MAX_PARALLEL_SHRED bash -c "exported_internal_shred_file $DEREFERENCED_BIN_DIR \"{}\"" $DEREFERENCED_BIN_DIR/fake
echo '========== DONE.'

View File

@@ -7,13 +7,7 @@
set -e
source "${0%/*}/_blackbox_common.sh"
if [[ -z $GPG_AGENT_INFO ]]; then
echo 'WARNING: You probably want to run gpg-agent as'
echo 'you will be asked for your passphrase many times.'
echo 'Example: $ eval $(gpg-agent --daemon)'
read -r -p 'Press CTRL-C now to stop. ENTER to continue: '
fi
gpg_agent_notice
disclose_admins
prepare_keychain

View File

@@ -14,13 +14,7 @@ then
fi
fail_if_not_in_repo
if [[ -z $GPG_AGENT_INFO ]]; then
echo 'WARNING: You probably want to run gpg-agent as'
echo 'you will be asked for your passphrase many times.'
echo 'Example: $ eval $(gpg-agent --daemon)'
read -r -p 'Press CTRL-C now to stop. ENTER to continue: '
fi
gpg_agent_notice
COLUMNS=`tput cols`
FILE=$1

25
tools/auto_system_test Executable file
View File

@@ -0,0 +1,25 @@
#!/usr/bin/env expect
# Run the confidence test non-interactively. Since the script
# asks for passphrases, we use "expect" to simulate keyboard data entry.
# Run the test:
spawn tools/confidence_test.sh
# As we run the confidence test, respond with the right password.
# We do this for up to 300 times to prevent an infinite loop.
set times 0;
while { $times < 300 } {
expect {
# The script outputs what the password will be, and we save
# that info in $pw any time we see the text.
"my password is the lowercase letter a" { set pw "a\n" ; exp_continue }
"my password is the lowercase letter b" { set pw "b\n" ; exp_continue }
# If the passphrase is requested, send it.
"Passphrase:" { send $pw ; exp_continue }
# If we reach EOF, exit this loop.
eof { break }
}
set times [ expr $times+1];
}

View File

@@ -1,7 +1,27 @@
#!/usr/bin/env bash
blackbox_home=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/../bin
export PATH="${blackbox_home}:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/local/bin"
export PATH="${blackbox_home}:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/local/bin:${blackbox_home}"
export LANG=C.UTF-8 # Required ro "gpg --export" to work properly.
# This script requires many utilities, some are not
# required by the usual blackbox scripts. Test to make
# sure we have them all.
e=false
for i in blackbox_addadmin blackbox_list_admins blackbox_register_new_file \
cat git gpg gpg-agent mkdir pinentry pinentry-tty rm tar which ; do
if ! which >/dev/null 2>&1 $i ; then
echo ERROR: Command not in PATH: $i
e=true
fi
done
if $e ; then
echo 'Exiting. Please install the above commands.'
echo 'This script requires many utilities not required by blackbox itself.'
echo PATH="$PATH"
exit 1
fi
set -e
. _stack_lib.sh
@@ -19,10 +39,15 @@ cd "$test_repository"
make_self_deleting_tempdir fake_alice_home
make_self_deleting_tempdir fake_bob_home
export GNUPGHOME="$fake_alice_home"
#echo 'pinentry-program' "$(which pinentry-insecure-fake)" >> "$GNUPGHOME/gpg-agent.conf"
echo 'pinentry-program' "$(which pinentry-tty)" >> "$GNUPGHOME/gpg-agent.conf"
#pinentry-program "${blackbox_home}/pinentry-fake-insecure"
eval "$(gpg-agent --homedir "$fake_alice_home" --daemon)"
GPG_AGENT_INFO_ALICE="$GPG_AGENT_INFO"
export GNUPGHOME="$fake_bob_home"
#echo 'pinentry-program' "$(which pinentry-insecure-fake)" >> "$GNUPGHOME/gpg-agent.conf"
echo 'pinentry-program' "$(which pinentry-tty)" >> "$GNUPGHOME/gpg-agent.conf"
eval "$(gpg-agent --homedir "$fake_bob_home" --daemon)"
GPG_AGENT_INFO_BOB="$GPG_AGENT_INFO"
@@ -31,6 +56,7 @@ function become_alice() {
export GPG_AGENT_INFO="$GPG_AGENT_INFO_ALICE"
echo BECOMING ALICE: GNUPGHOME="$GNUPGHOME AGENT=$GPG_AGENT_INFO"
mkdir -p .git ; touch .git/config
git init
git config user.name "Alice Example"
git config user.email alice@example.com
}
@@ -46,7 +72,6 @@ function become_bob() {
PHASE 'Alice creates a repo. She creates secret.txt.'
become_alice
git init
echo 'this is my secret' >secret.txt
@@ -82,7 +107,11 @@ git commit -m'INITIALIZE BLACKBOX' keyrings .gitignore
PHASE 'and adds herself as an admin.'
blackbox_addadmin alice@example.com
git commit -m'NEW ADMIN: alice@example.com' keyrings/live/pubring.gpg keyrings/live/trustdb.gpg keyrings/live/blackbox-admins.txt
git commit -m'NEW ADMIN: alice@example.com' keyrings/live/pubring.??? keyrings/live/trustdb.gpg keyrings/live/blackbox-admins.txt
make_self_deleting_tempfile adminlist1
blackbox_list_admins >"$adminlist1"
assert_file_md5hash "$adminlist1" "aa1db827772e1d51d453b844394b7617"
PHASE 'Bob arrives.'
@@ -110,14 +139,18 @@ gpg --no-permission-warning --batch --gen-key "$gpgconfig"
echo '========== Bob enrolls himself too.'
blackbox_addadmin bob@example.com
git commit -m'NEW ADMIN: alice@example.com' keyrings/live/pubring.gpg keyrings/live/trustdb.gpg keyrings/live/blackbox-admins.txt
git commit -m'NEW ADMIN: alice@example.com' keyrings/live/pubring.??? keyrings/live/trustdb.gpg keyrings/live/blackbox-admins.txt
make_self_deleting_tempfile adminlist2
blackbox_list_admins >"$adminlist2"
assert_file_md5hash "$adminlist2" "0b82b0b3c96e6e5dd5faf60493fe5cf7"
PHASE 'Alice does the second part to enroll bob.'
become_alice
PHASE 'She enrolls bob.'
gpg --import keyrings/live/pubring.gpg
# TODO(tlim) That --import can be eliminated... maybe?
#gpg --import $(get_pubring_path)
## TODO(tlim) That --import can be eliminated... maybe?
PHASE 'She enrolls secrets.txt.'
blackbox_register_new_file secret.txt
@@ -185,33 +218,30 @@ assert_file_md5hash secret.txt "d3e6bbdfc76fae7fd0a921f3408db1d1"
PHASE 'appears.'
become_bob
PHASE 'Bob makes sure he has all new keys.'
gpg --import keyrings/live/pubring.gpg
#PHASE 'Bob makes sure he has all new keys.'
#gpg --import keyrings/live/pubring.???
# Pick a GID to use:
# This users's default group:
DEFAULT_GID_NAME=$(id -gn)
DEFAULT_GID_NUM=$(id -g)
# Pick a group that is not the default group:
TEST_GID_NUM=$(id -G | fmt -1 | tail -n +2 | grep -xv "$(id -u)" | head -n 1)
TEST_GID_NAME=$(python -c 'import grp; print grp.getgrgid('"$TEST_GID_NUM"').gr_name')
echo "DEFAULT_GID_NAME=$DEFAULT_GID_NAME"
TEST_GID_NUM=$(id -G | fmt -1 | sort -rn | grep -xv "$(id -u)" | grep -xv "$(id -g)" | head -1)
echo "DEFAULT_GID_NUM=$DEFAULT_GID_NUM"
echo "TEST_GID_NUM=$TEST_GID_NUM"
echo "TEST_GID_NAME=$TEST_GID_NAME"
PHASE 'Bob postdeploys... default.'
blackbox_postdeploy
assert_file_exists secret.txt
assert_file_exists secret.txt.gpg
assert_file_md5hash secret.txt "08a3fa763a05c018a38e9924363b97e7"
assert_file_group secret.txt "$DEFAULT_GID_NAME"
assert_file_group secret.txt "$DEFAULT_GID_NUM"
PHASE 'Bob postdeploys... with a GID.'
blackbox_postdeploy "$TEST_GID_NUM"
assert_file_exists secret.txt
assert_file_exists secret.txt.gpg
assert_file_md5hash secret.txt "08a3fa763a05c018a38e9924363b97e7"
assert_file_group secret.txt "$TEST_GID_NAME"
assert_file_group secret.txt "$TEST_GID_NUM"
PHASE 'Bob cleans up the secret.'
rm secret.txt
@@ -220,6 +250,10 @@ PHASE 'Bob removes Alice.'
blackbox_removeadmin alice@example.com
assert_line_not_exists 'alice@example.com' keyrings/live/blackbox-admins.txt
make_self_deleting_tempfile adminlist3
blackbox_list_admins >"$adminlist3"
assert_file_md5hash "$adminlist3" "aadbfafd76ea66ff40dbfd239a69067f"
PHASE 'Bob reencrypts files so alice can not access them.'
blackbox_update_all_files
@@ -316,6 +350,7 @@ PHASE 'Bob shreds all exposed files.'
assert_file_exists 'my/path/to/relsecrets.txt'
assert_file_exists 'secret.txt'
blackbox_shred_all_files
which blackbox_shred_all_files
assert_file_missing '!important!.txt'
assert_file_missing '#andpounds.txt'
assert_file_missing 'mistake.txt'
@@ -393,6 +428,10 @@ fi
# Cleanup:
blackbox_removeadmin abba@notarealuser.com
make_self_deleting_tempfile adminlist4
blackbox_list_admins >"$adminlist4"
assert_file_md5hash "$adminlist4" "aadbfafd76ea66ff40dbfd239a69067f"
# TODO: Create a new directory. "git clone" the repo into it.

View File

@@ -43,7 +43,7 @@ fi
# Generate the diff
cp /opt/local/var/macports/sources/rsync.macports.org/release/tarballs/ports/security/vcs_blackbox/Portfile /var/tmp/ports/security/vcs_blackbox/Portfile.orig
( cd /var/tmp/ports/security/vcs_blackbox && diff -u Portfile.orig Portfile ) > Portfile-vcs_blackbox.diff
( cd /var/tmp/ports/security/vcs_blackbox && diff --ignore-matching-lines='Id:' -u Portfile.orig Portfile ) > Portfile-vcs_blackbox.diff
open -R Portfile-vcs_blackbox.diff
echo
@@ -62,6 +62,6 @@ github.setup and checksums updated.
Type: update
Component: ports
Port: vcs_blackbox
Keywords: maintainer
Keywords: maintainer haspatch
"
echo 'Attach: Portfile-vcs_blackbox.diff'

View File

@@ -22,13 +22,27 @@ shift
# Defaults that can be overridden:
# All packages are 1.0 unless otherwise specifed:
: ${PKGVERSION:=1.0} ;
# If there is no iteration setting, assume "1":
: ${PKGRELEASE:=1}
# If there is no iteration set, default to use the number of commits in the repository:
if [[ -z "${PKGRELEASE}" ]]; then
PKGRELEASE=$(git rev-list HEAD --count)
if [[ $? != 0 ]]; then
# We're not in a git repo, fall back to 1 so we cope with being built from
# a tarball
PKGRELEASE=1
fi
fi
# If there is no epoch, assume 0
: ${PKGEPOCH:=0}
# The DEB is output here: (should be a place that can be wiped)
OUTPUTDIR="${HOME}/debbuild-$PACKAGENAME"
# Allow us to set a different OUTPUTDIR if we're building in CI/CD
if [[ -z "${OUTPUTDIR}" ]]; then
# The DEB is output here: (should be a place that can be wiped)
OUTPUTDIR="${HOME}/debbuild-${PACKAGENAME}"
else
echo "Using $OUTPUTDIR for OUTPUTDIR instead of ${HOME}/debbuild-${PACKAGENAME}"
fi
# The TeamCity templates expect to find the list of artifacts here:
DEB_BIN_LIST="${OUTPUTDIR}/bin-packages.txt"
@@ -36,6 +50,7 @@ DEB_BIN_LIST="${OUTPUTDIR}/bin-packages.txt"
# Clean the output dir.
rm -rf "$OUTPUTDIR"
mkdir -p "$OUTPUTDIR/installroot"
# Copy the files into place:

View File

@@ -9,7 +9,9 @@ exec /usr/bin/blackbox_edit ../bin/blackbox_edit
exec /usr/bin/blackbox_edit_end ../bin/blackbox_edit_end
exec /usr/bin/blackbox_edit_start ../bin/blackbox_edit_start
exec /usr/bin/blackbox_initialize ../bin/blackbox_initialize
exec /usr/bin/blackbox_listadmins ../bin/blackbox_listadmins
exec /usr/bin/blackbox_list_files ../bin/blackbox_list_files
exec /usr/bin/blackbox_list_admins ../bin/blackbox_list_admins
exec /usr/bin/blackbox_postdeploy ../bin/blackbox_postdeploy
exec /usr/bin/blackbox_register_new_file ../bin/blackbox_register_new_file
exec /usr/bin/blackbox_removeadmin ../bin/blackbox_removeadmin

View File

@@ -9,7 +9,9 @@ exec bin/blackbox_edit ../bin/blackbox_edit
exec bin/blackbox_edit_end ../bin/blackbox_edit_end
exec bin/blackbox_edit_start ../bin/blackbox_edit_start
exec bin/blackbox_initialize ../bin/blackbox_initialize
exec bin/blackbox_listadmins ../bin/blackbox_listadmins
exec bin/blackbox_list_files ../bin/blackbox_list_files
exec bin/blackbox_list_admins ../bin/blackbox_list_admins
exec bin/blackbox_postdeploy ../bin/blackbox_postdeploy
exec bin/blackbox_register_new_file ../bin/blackbox_register_new_file
exec bin/blackbox_removeadmin ../bin/blackbox_removeadmin

View File

@@ -19,28 +19,78 @@ set -e
PACKAGENAME=${1?"First arg must be the package name."}
shift
# What is my name?
CMDNAME=$(basename $0)
# Defaults that can be overridden:
# All packages are 1.0 unless otherwise specifed:
# Packages are 1.0 unless otherwise specifed:
: ${PKGVERSION:=1.0} ;
# If there is no iteration setting, assume "1":
: ${PKGRELEASE:=1}
# If there is no iteration set, default to use the number of commits in the repository:
if [[ -z "${PKGRELEASE}" ]]; then
PKGRELEASE=$(git rev-list HEAD --count)
if [[ $? != 0 ]]; then
# We're not in a git repo, fall back to 1 so we cope with being built from
# a tarball
PKGRELEASE=1
fi
fi
# If there is no epoch, assume 0
: ${PKGEPOCH:=0}
# The RPM is output here: (should be a place that can be wiped)
OUTPUTDIR="${HOME}/rpmbuild-$PACKAGENAME"
# The TeamCity templates expect to find the list of artifacts here:
# If no arch defined, assume any. Other good values include "native".
: ${PKGARCH:=all}
# NOTE: If we later compile code, we set this to "native", which
# FPM will translate to the correct value for local conditions.
# Allow us to set a different OUTPUTDIR if we're building in CI/CD
if [[ -z "${OUTPUTDIR}" ]]; then
# The RPM is output here: (should be a place that can be wiped)
OUTPUTDIR="${HOME}/rpmbuild-${PACKAGENAME}"
else
echo "Using ${OUTPUTDIR} for OUTPUTDIR instead of ${HOME}/rpmbuild-${PACKAGENAME}"
fi
INSTALLROOT="$OUTPUTDIR/installroot"
# StackOverflow's TeamCity templates expect to find the list of artifacts here:
RPM_BIN_LIST="${OUTPUTDIR}/bin-packages.txt"
# -- Now the real work can be done.
# Clean the output dir.
rm -rf "$OUTPUTDIR"
mkdir -p "$OUTPUTDIR/installroot"
mkdir -p "$INSTALLROOT"
# Copy the files into place:
# If there is a build script, execute it.
BUILDSCRIPTNAME="./build.${PACKAGENAME}.sh"
if [[ -x $BUILDSCRIPTNAME ]]; then
echo "========== $BUILDSCRIPTNAME FOUND. Running."
if [[ $PKGARCH == "all" ]]; then
echo 'WARNING: PKGARCH=all (which may not what you want)'
# If you are using a build.*.sh script, you probably want to
# set PKGARCH to "native" before you run mk_rpm_fpmdir.
fi
$BUILDSCRIPTNAME "$INSTALLROOT" "${PKGVERSION}"
# If we used the build build.*.sh script, it must do all compilation.
# Therefore, we disable the automagic GO build feature.
GO_COMPILE=false
else
GO_COMPILE=true
fi
# If there are additional args for fpm, read them into a variable. There is
# a chdir later, therefore we can't rely on the file path working at that time.
FPM_OPTIONS_FILE="./fpm_opts.${PACKAGENAME}.sh"
if [[ -f $FPM_OPTIONS_FILE ]]; then
echo "========== $FPM_OPTIONS_FILE FOUND. Loading."
FPM_OPTIONS=$(<$FPM_OPTIONS_FILE)
fi
# Warning: The contents of the file are evaluated therefore
# quotes and special chars must be quoted.
# Copy any static files into place:
set -o pipefail # Error out if any manifest is not found.
cat """$@""" | while read -a arr ; do
cat "$@" | while read -a arr ; do
PERM="${arr[0]}"
case $PERM in
\#*) continue ;; # Skip comments.
@@ -48,24 +98,39 @@ cat """$@""" | while read -a arr ; do
read) PERM=0744 ;;
*) ;;
esac
DST="$OUTPUTDIR/installroot/${arr[1]}"
DST="$INSTALLROOT/${arr[1]}"
SRC="${arr[2]}"
if [[ $SRC == "cmd/"* || $SRC == *"/cmd/"* ]]; then
( cd $(dirname "$SRC" ) && go build -a -v )
if [[ ${#arr[@]} != 3 ]] ; then
echo "ERROR: Line must contain 3 items."
echo "DEBUG NUM=${#arr[@]} PERM=$PERM DST=$DST SRC=$SRC"
exit 1
fi
if $GO_COMPILE && [[ $SRC == "cmd/"* || $SRC == *"/cmd/"* ]]; then
echo "========== BUILD&COPY $SRC"
( cd $(dirname "$SRC" ) && go get -d && go build )
PKGARCH=native
else
echo "========== COPY $SRC"
fi
if [[ ! -f "$SRC" ]]; then
echo "${CMDNAME}: ERROR: File not found: $SRC"
exit 1
fi
install -D -T -b -m "$PERM" -T "$SRC" "$DST"
done
# Build the RPM:
set -x
# Build the RPM out of what is found in $INSTALLROOT:
cd "$OUTPUTDIR" && fpm -s dir -t rpm \
-a all \
-a "${PKGARCH}" \
-n "${PACKAGENAME}" \
--epoch "${PKGEPOCH}" \
--version "${PKGVERSION}" \
--iteration "${PKGRELEASE}" \
${PKGDESCRIPTION:+ --description="${PKGDESCRIPTION}"} \
${PKGVENDOR:+ --vendor="${PKGVENDOR}"} \
-C "$OUTPUTDIR/installroot" \
${FPM_OPTIONS:+ $FPM_OPTIONS} \
-C "$INSTALLROOT" \
.
# TeamCity templates for RPMS expect to find

View File

@@ -11,7 +11,9 @@ exec /usr/blackbox/bin/blackbox_edit ../bin/blackbox_edit
exec /usr/blackbox/bin/blackbox_edit_end ../bin/blackbox_edit_end
exec /usr/blackbox/bin/blackbox_edit_start ../bin/blackbox_edit_start
exec /usr/blackbox/bin/blackbox_initialize ../bin/blackbox_initialize
exec /usr/blackbox/bin/blackbox_listadmins ../bin/blackbox_listadmins
exec /usr/blackbox/bin/blackbox_list_files ../bin/blackbox_list_files
exec /usr/blackbox/bin/blackbox_list_admins ../bin/blackbox_list_admins
exec /usr/blackbox/bin/blackbox_postdeploy ../bin/blackbox_postdeploy
exec /usr/blackbox/bin/blackbox_register_new_file ../bin/blackbox_register_new_file
exec /usr/blackbox/bin/blackbox_removeadmin ../bin/blackbox_removeadmin

View File

@@ -1,5 +1,15 @@
#!/usr/bin/env bash
# NB: This is copied from _blackbox_common.sh
function get_pubring_path() {
: "${KEYRINGDIR:=keyrings/live}" ;
if [[ -f "${KEYRINGDIR}/pubring.gpg" ]]; then
echo "${KEYRINGDIR}/pubring.gpg"
else
echo "${KEYRINGDIR}/pubring.kbx"
fi
}
function PHASE() {
echo '********************'
echo '********************'
@@ -11,7 +21,7 @@ function PHASE() {
function md5sum_file() {
# Portably generate the MD5 hash of file $1.
case $(uname -s) in
Darwin )
Darwin | FreeBSD )
md5 -r "$1" | awk '{ print $1 }'
;;
Linux )
@@ -63,10 +73,10 @@ function assert_file_group() {
case $(uname -s) in
Darwin|FreeBSD )
found=$(stat -f '%Sg' "$file")
found=$(stat -f '%Dg' "$file")
;;
Linux )
found=$(stat -c '%G' "$file")
found=$(stat -c '%g' "$file")
;;
CYGWIN* )
echo "ASSERT_FILE_GROUP: Running on Cygwin. Not being tested."
@@ -78,8 +88,10 @@ function assert_file_group() {
;;
esac
echo "DEBUG: assert_file_group X${wanted}X vs. X${found}X"
echo "DEBUG:" $(which stat)
if [[ "$wanted" != "$found" ]]; then
echo "ASSERT FAILED: $file chgrp wanted=$wanted found=$found"
echo "ASSERT FAILED: $file chgrp group wanted=$wanted found=$found"
exit 1
fi
}
@@ -103,8 +115,10 @@ function assert_file_perm() {
;;
esac
echo "DEBUG: assert_file_perm X${wanted}X vs. X${found}X"
echo "DEBUG:" $(which stat)
if [[ "$wanted" != "$found" ]]; then
echo "ASSERT FAILED: $file chgrp wanted=$wanted found=$found"
echo "ASSERT FAILED: $file chgrp perm wanted=$wanted found=$found"
exit 1
fi
}