An ACME-based certificate authority, written in Go.
Go to file
Roland Bracewell Shoemaker d28f9b877b Switch CT import path (#2769)
Switches imports from `github.com/google/certificate-transparency` to `github.com/google/certificate-transparency-go` and vendors the new code. Also fixes a number of small breakages caused by API changes since the last time we vendored the code. Also updates `github.com/cloudflare/cfssl` since you can't vendor both `github.com/google/certificate-transparency` and `github.com/google/certificate-transparency-go`.

Side note: while doing this `godep` tried to pull in a number of imports under the `golang.org/x/text` repo that I couldn't find actually being used anywhere so I just dropped the changes to `Godeps/Godeps.json` and didn't add the vendored dir to the tree, let's see if this breaks any tests...

All tests pass

```
$ go test ./...
ok  	github.com/google/certificate-transparency-go	0.640s
ok  	github.com/google/certificate-transparency-go/asn1	0.005s
ok  	github.com/google/certificate-transparency-go/client	22.054s
?   	github.com/google/certificate-transparency-go/client/ctclient	[no test files]
ok  	github.com/google/certificate-transparency-go/fixchain	0.133s
?   	github.com/google/certificate-transparency-go/fixchain/main	[no test files]
ok  	github.com/google/certificate-transparency-go/fixchain/ratelimiter	27.752s
ok  	github.com/google/certificate-transparency-go/gossip	0.322s
?   	github.com/google/certificate-transparency-go/gossip/main	[no test files]
ok  	github.com/google/certificate-transparency-go/jsonclient	25.701s
ok  	github.com/google/certificate-transparency-go/merkletree	0.006s
?   	github.com/google/certificate-transparency-go/preload	[no test files]
?   	github.com/google/certificate-transparency-go/preload/dumpscts/main	[no test files]
?   	github.com/google/certificate-transparency-go/preload/main	[no test files]
ok  	github.com/google/certificate-transparency-go/scanner	0.013s
?   	github.com/google/certificate-transparency-go/scanner/main	[no test files]
ok  	github.com/google/certificate-transparency-go/tls	0.033s
ok  	github.com/google/certificate-transparency-go/x509	1.071s
?   	github.com/google/certificate-transparency-go/x509/pkix	[no test files]
?   	github.com/google/certificate-transparency-go/x509util	[no test files]
```
```
$ ./test.sh
...
ok  	github.com/cloudflare/cfssl/api	1.089s	coverage: 81.1% of statements
ok  	github.com/cloudflare/cfssl/api/bundle	1.548s	coverage: 87.2% of statements
ok  	github.com/cloudflare/cfssl/api/certadd	13.681s	coverage: 86.8% of statements
ok  	github.com/cloudflare/cfssl/api/client	1.314s	coverage: 55.2% of statements
ok  	github.com/cloudflare/cfssl/api/crl	1.124s	coverage: 75.0% of statements
ok  	github.com/cloudflare/cfssl/api/gencrl	1.067s	coverage: 72.5% of statements
ok  	github.com/cloudflare/cfssl/api/generator	2.809s	coverage: 33.3% of statements
ok  	github.com/cloudflare/cfssl/api/info	1.112s	coverage: 84.1% of statements
ok  	github.com/cloudflare/cfssl/api/initca	1.059s	coverage: 90.5% of statements
ok  	github.com/cloudflare/cfssl/api/ocsp	1.178s	coverage: 93.8% of statements
ok  	github.com/cloudflare/cfssl/api/revoke	2.282s	coverage: 75.0% of statements
ok  	github.com/cloudflare/cfssl/api/scan	2.729s	coverage: 62.1% of statements
ok  	github.com/cloudflare/cfssl/api/sign	2.483s	coverage: 83.3% of statements
ok  	github.com/cloudflare/cfssl/api/signhandler	1.137s	coverage: 26.3% of statements
ok  	github.com/cloudflare/cfssl/auth	1.030s	coverage: 68.2% of statements
ok  	github.com/cloudflare/cfssl/bundler	15.014s	coverage: 85.1% of statements
ok  	github.com/cloudflare/cfssl/certdb/dbconf	1.042s	coverage: 78.9% of statements
ok  	github.com/cloudflare/cfssl/certdb/ocspstapling	1.919s	coverage: 69.2% of statements
ok  	github.com/cloudflare/cfssl/certdb/sql	1.265s	coverage: 65.7% of statements
ok  	github.com/cloudflare/cfssl/cli	1.050s	coverage: 61.9% of statements
ok  	github.com/cloudflare/cfssl/cli/bundle	1.023s	coverage: 0.0% of statements
ok  	github.com/cloudflare/cfssl/cli/crl	1.669s	coverage: 57.8% of statements
ok  	github.com/cloudflare/cfssl/cli/gencert	9.278s	coverage: 83.6% of statements
ok  	github.com/cloudflare/cfssl/cli/gencrl	1.310s	coverage: 73.3% of statements
ok  	github.com/cloudflare/cfssl/cli/genkey	3.028s	coverage: 70.0% of statements
ok  	github.com/cloudflare/cfssl/cli/ocsprefresh	1.106s	coverage: 64.3% of statements
ok  	github.com/cloudflare/cfssl/cli/revoke	1.081s	coverage: 88.2% of statements
ok  	github.com/cloudflare/cfssl/cli/scan	1.217s	coverage: 36.0% of statements
ok  	github.com/cloudflare/cfssl/cli/selfsign	2.201s	coverage: 73.2% of statements
ok  	github.com/cloudflare/cfssl/cli/serve	1.133s	coverage: 39.0% of statements
ok  	github.com/cloudflare/cfssl/cli/sign	1.210s	coverage: 54.8% of statements
ok  	github.com/cloudflare/cfssl/cli/version	2.475s	coverage: 100.0% of statements
ok  	github.com/cloudflare/cfssl/cmd/cfssl	1.082s	coverage: 0.0% of statements
ok  	github.com/cloudflare/cfssl/cmd/cfssljson	1.016s	coverage: 4.0% of statements
ok  	github.com/cloudflare/cfssl/cmd/mkbundle	1.024s	coverage: 0.0% of statements
ok  	github.com/cloudflare/cfssl/config	2.754s	coverage: 67.7% of statements
ok  	github.com/cloudflare/cfssl/crl	1.063s	coverage: 68.3% of statements
ok  	github.com/cloudflare/cfssl/csr	27.016s	coverage: 89.6% of statements
ok  	github.com/cloudflare/cfssl/errors	1.081s	coverage: 81.2% of statements
ok  	github.com/cloudflare/cfssl/helpers	1.217s	coverage: 80.4% of statements
ok  	github.com/cloudflare/cfssl/helpers/testsuite	7.658s	coverage: 65.8% of statements
ok  	github.com/cloudflare/cfssl/initca	205.809s	coverage: 74.2% of statements
ok  	github.com/cloudflare/cfssl/log	1.016s	coverage: 59.3% of statements
ok  	github.com/cloudflare/cfssl/multiroot/config	1.107s	coverage: 77.4% of statements
ok  	github.com/cloudflare/cfssl/ocsp	1.524s	coverage: 77.7% of statements
ok  	github.com/cloudflare/cfssl/revoke	1.775s	coverage: 79.6% of statements
ok  	github.com/cloudflare/cfssl/scan	1.022s	coverage: 1.1% of statements
ok  	github.com/cloudflare/cfssl/selfsign	1.119s	coverage: 70.0% of statements
ok  	github.com/cloudflare/cfssl/signer	1.019s	coverage: 20.0% of statements
ok  	github.com/cloudflare/cfssl/signer/local	3.146s	coverage: 81.2% of statements
ok  	github.com/cloudflare/cfssl/signer/remote	2.328s	coverage: 71.8% of statements
ok  	github.com/cloudflare/cfssl/signer/universal	2.280s	coverage: 67.7% of statements
ok  	github.com/cloudflare/cfssl/transport	1.028s
ok  	github.com/cloudflare/cfssl/transport/ca/localca	1.056s	coverage: 94.9% of statements
ok  	github.com/cloudflare/cfssl/transport/core	1.538s	coverage: 90.9% of statements
ok  	github.com/cloudflare/cfssl/transport/kp	1.054s	coverage: 37.1% of statements
ok  	github.com/cloudflare/cfssl/ubiquity	1.042s	coverage: 88.3% of statements
ok  	github.com/cloudflare/cfssl/whitelist	2.304s	coverage: 100.0% of statements
```

Fixes #2746.
2017-05-17 13:41:33 -07:00
Godeps Switch CT import path (#2769) 2017-05-17 13:41:33 -07:00
akamai Fix akamai cache purger bugs (#2443) 2016-12-21 09:05:49 -05:00
bdns Rewords IPv6 -> IPv4 fallback error messages. 2017-05-11 10:35:30 -04:00
ca CA: Use Prometheus for counting issued certificates. (#2690) 2017-04-19 11:06:04 -07:00
cdr Properly close httptest Servers. (#2560) 2017-02-14 15:08:08 -05:00
cmd Switch CT import path (#2769) 2017-05-17 13:41:33 -07:00
core Prefer IPv6 addresses, fall back to IPv4. (#2715) 2017-05-08 13:00:16 -07:00
csr Improve error messages. (#2256) 2016-10-18 10:15:21 -07:00
data Fixes Mandrill UNSUB merge tag (#2524) 2017-01-25 10:53:17 -08:00
docs Remove statsd from Boulder (#2752) 2017-05-15 10:19:54 -04:00
errors Clean up `berrors` (#2724) 2017-05-04 10:56:26 +01:00
features Adds "meta" entry w/ ToS to /directory. 2017-05-09 15:43:16 -04:00
goodkey Overhaul internal error usage (#2583) 2017-03-22 23:27:31 -07:00
grpc Prefer IPv6 addresses, fall back to IPv4. (#2715) 2017-05-08 13:00:16 -07:00
log Remove statsd from Boulder (#2752) 2017-05-15 10:19:54 -04:00
mail Fix auth line in email test (#2499) 2017-01-17 09:46:58 -08:00
metrics Remove statsd from Boulder (#2752) 2017-05-15 10:19:54 -04:00
mocks Remove statsd from Boulder (#2752) 2017-05-15 10:19:54 -04:00
nonce Remove direct usages of go-statsd-client in favor of using metrics.Scope (#2136) 2016-09-07 19:35:13 -04:00
policy Removes outdated comment & unused errNotWhitelisted. (#2744) 2017-05-09 13:12:28 -04:00
prefixdb Change prefixdb semantics (#2674) 2017-04-12 21:57:58 -07:00
probs Clean up `berrors` (#2724) 2017-05-04 10:56:26 +01:00
publisher Switch CT import path (#2769) 2017-05-17 13:41:33 -07:00
ra Fixes RPC bug for CountCertificatesExact feature flag. (#2759) 2017-05-12 15:21:00 -04:00
ratelimit Add a limit on failed authorizations (#2513) 2017-01-23 11:22:51 -08:00
reloader Spelling (#2500) 2017-01-16 10:44:52 -05:00
revocation Fixes gofmt -s diffs 2016-11-30 13:30:03 -05:00
sa Fixes cert count rate limit for exact PSL matches. (#2703) 2017-05-02 13:43:35 -07:00
test Switch CT import path (#2769) 2017-05-17 13:41:33 -07:00
va Fix flakiness in VA test. (#2767) 2017-05-15 16:44:59 -07:00
vendor Switch CT import path (#2769) 2017-05-17 13:41:33 -07:00
wfe Avoids double type assert 2017-05-12 14:50:27 -04:00
.dockerignore Roll forward "Run Travis tests in Docker (#1830)" (#1838) 2016-05-24 15:11:22 -07:00
.gitignore Add “.idea” to .gitignore. (#2655) 2017-04-06 11:15:32 -07:00
.travis.yml Fixes test speeds by splitting `-race` from coverage runs. (#2721) 2017-05-02 14:57:32 -07:00
CODE_OF_CONDUCT.md Add Code of Conduct (#1961) 2016-06-22 14:05:25 -04:00
CONTRIBUTING.md Spelling (#2500) 2017-01-16 10:44:52 -05:00
DESIGN.md Remove some last traces of AMQP. (#2687) 2017-04-20 10:43:17 -07:00
Dockerfile Dockerfile/docker-compose.yml cleanups 2017-04-14 14:59:31 -07:00
LICENSE.txt Remove all stray copyright headers and appends the initial line to LICENSE.txt (#1853) 2016-05-31 12:32:04 -07:00
Makefile Switch back to go 1.5 in Travis. (#2261) 2016-10-20 14:11:26 -04:00
README.md Remove RabbitMQ + AMQP references from README (#2616) 2017-03-22 12:43:43 -07:00
docker-compose.yml Dockerfile/docker-compose.yml cleanups 2017-04-14 14:59:31 -07:00
docker-rebuild.sh Add tiny docker-compose rebuild script (#2039) 2016-07-13 13:33:22 -07:00
start.py Make restarting boulder in docker nicer. (#2492) 2017-01-13 11:55:28 -05:00
test.sh Fixes master's unit tests, test failure. (#2763) 2017-05-15 14:33:31 -04:00

README.md

Boulder - An ACME CA

This is an implementation of an ACME-based CA. The ACME protocol allows the CA to automatically verify that an applicant for a certificate actually controls an identifier, and allows domain holders to issue and revoke certificates for their domains.

Build Status Coverage Status

Quickstart

Boulder has a Dockerfile to make it easy to install and set up all its dependencies. This is how the maintainers work on Boulder, and is our main recommended way to run it.

Make sure you have a local copy of Boulder in your $GOPATH:

export GOPATH=~/gopath
git clone https://github.com/letsencrypt/boulder/ $GOPATH/src/github.com/letsencrypt/boulder

To start Boulder in a Docker container, run:

docker-compose up

To run tests:

docker-compose run boulder ./test.sh

To run a specific unittest:

docker-compose run boulder go test ./ra

The configuration in docker-compose.yml mounts your $GOPATH on top of its own $GOPATH. So you can edit code on your host and it will be immediately reflected inside Docker images run with docker-compose.

If docker-compose fails with an error message like "Cannot start service boulder: oci runtime error: no such file or directory" or "Cannot create container for service boulder" you should double check that your $GOPATH exists and doesn't contain any characters other than letters, numbers, - and _.

If you have problems with Docker, you may want to try removing all containers and volumes.

By default, Boulder uses a fake DNS resolver that resolves all hostnames to 127.0.0.1. This is suitable for running integration tests inside the Docker container. If you want Boulder to be able to communicate with a client running on your host instead, you should find your host's Docker IP with:

ifconfig docker0 | grep "inet addr:" | cut -d: -f2 | awk '{ print $1}'

And edit docker-compose.yml to change the FAKE_DNS environment variable to match.

Alternatively, you can override the docker-compose.yml default with an environmental variable using -e (replace 172.17.0.1 with the host IPv4 address found in the command above)

docker-compose run -e FAKE_DNS=172.17.0.1 --service-ports boulder ./start.py

Boulder's default VA configuration (test/config/va.json) is configured to connect to port 5002 to validate HTTP-01 challenges and port 5001 to validate TLS-SNI-01 challenges. If you want to solve challenges with a client running on your host you should make sure it uses these ports to respond to validation requests, or update the VA configuration's portConfig to use ports 80 and 443 to match how the VA operates in production and staging environments. If you use a host-based firewall (e.g. ufw or iptables) make sure you allow connections from the Docker instance to your host on the required ports.

If a base image changes (i.e. letsencrypt/boulder-tools) you will need to rebuild images for both the boulder and bhsm containers and re-create them. The quickest way to do this is with this command:

./docker-rebuild.sh

Slow start

If you can't use the Docker setup, here are instructions for setting up a Boulder development environment without it.

We recommend setting git's fsckObjects setting for better integrity guarantees when getting updates.

Boulder requires an installation of libtool-ltdl, goose, SoftHSM, and MariaDB 10.1 to work correctly. If you want to save some trouble installing MariaDB and SoftHSM you can run them using Docker:

docker-compose up -d bmysql bhsm

Also, Boulder requires Go 1.5. As of September 2015 this version is not yet available in OS repositories, so you will have to install from https://golang.org/dl/. Add ${GOPATH}/bin to your path.

Ubuntu:

sudo apt-get install libltdl3-dev mariadb-server rabbitmq-server

CentOS:

sudo yum install libtool-ltdl-devel MariaDB-server MariaDB-client rabbitmq-server

Arch Linux:

sudo pacman -S libtool mariadb rabbitmq --needed

OS X:

brew install libtool mariadb rabbitmq

or

sudo port install libtool mariadb-server rabbitmq-server

(On OS X, using port, you will have to add CGO_CFLAGS="-I/opt/local/include" CGO_LDFLAGS="-L/opt/local/lib" to your environment or go invocations.)

Edit /etc/hosts to add this line:

127.0.0.1 boulder boulder-rabbitmq boulder-mysql

Resolve Go-dependencies, set up a database:

./test/setup.sh

Note: setup.sh calls create_db.sh, which uses the root MariaDB user with the default password, so if you have disabled that account or changed the password you may have to adjust the file or recreate the commands.

Install SoftHSM to store the CA private key in a way that can be accessed using PKCS#11. Then run ./test/make-softhsm.sh and follow its instructions.

Install Python packages for integration test:

virtualenv venv
. venv/bin/activate
pip install -r test/requirements.txt
# If you want to develop against a locally modified Python acme package,
# this will install the package such that updates are reflected immediately:
pip install -e ~/certbot/acme[dev]

Start all boulder components with test configs (Ctrl-C kills all):

./start.py

Run tests:

./test.sh

Working with a client:

Check out the Certbot client from https://github.com/certbot/certbot and follow the setup instructions there. Once you've got the client set up, you'll probably want to run it against your local Boulder. There are a number of command line flags that are necessary to run the client against a local Boulder, and without root access. The simplest way to run the client locally is to source a file that provides an alias for certbot (certbot_test) that has all those flags:

source ~/certbot/tests/integration/_common.sh
certbot_test certonly -a standalone -d example.com

Your local Boulder instance uses a fake DNS server that returns 127.0.0.1 for any query, so you can use any value for the -d flag. You can also override that value by setting the environment variable FAKE_DNS=1.2.3.4

Component Model

The CA is divided into the following main components:

  1. Web Front End
  2. Registration Authority
  3. Validation Authority
  4. Certificate Authority
  5. Storage Authority
  6. OCSP Updater
  7. OCSP Responder

This component model lets us separate the function of the CA by security context. The Web Front End and Validation Authority need access to the Internet, which puts them at greater risk of compromise. The Registration Authority can live without Internet connectivity, but still needs to talk to the Web Front End and Validation Authority. The Certificate Authority need only receive instructions from the Registration Authority. All components talk to the SA for storage, so lines indicating SA RPCs are not shown here.


                             +--------- OCSP Updater
                             |               |
                             v               |
                            CA               |
                             ^               |
                             |               v
       Subscriber -> WFE --> RA --> SA --> MariaDB
                             |               ^
Subscriber server <- VA <----+               |
                                             |
          Browser ------------------>  OCSP Responder

Internally, the logic of the system is based around four types of objects: registrations, authorizations, challenges, and certificates, mapping directly to the resources of the same name in ACME.

Requests from ACME clients result in new objects and changes to objects. The Storage Authority maintains persistent copies of the current set of objects.

Objects are also passed from one component to another on change events. For example, when a client provides a successful response to a validation challenge, it results in a change to the corresponding validation object. The Validation Authority forwards the new validation object to the Storage Authority for storage, and to the Registration Authority for any updates to a related Authorization object.

Boulder uses gRPC for inter-component communication. For components that you want to be remote, it is necessary to instantiate a "client" and "server" for that component. The client implements the component's Go interface, while the server has the actual logic for the component. More details on this communication model can be found in the gRPC documentation.

The full details of how the various ACME operations happen in Boulder are laid out in DESIGN.md

Dependencies

All Go dependencies are vendored under the vendor directory, to make dependency management easier.

Local development also requires a MariaDB 10 installation. MariaDB should be run on port 3306 for the default integration tests.

To update the Go dependencies:

# Fetch godep
go get -u github.com/tools/godep
# Check out the currently vendorized version of each dependency.
godep restore
# Update to the latest version of a dependency. Alternately you can cd to the
# directory under GOPATH and check out a specific revision. Here's an example
# using cfssl:
go get -u github.com/cloudflare/cfssl/...
# Update the Godep config to the appropriate version.
godep update github.com/cloudflare/cfssl/...
# Save the dependencies
godep save ./...
git add Godeps vendor
git commit

NOTE: If you get "godep: no packages can be updated," there's a good chance you're trying to update a single package that belongs to a repo with other packages. For instance, godep update golang.org/x/crypto/ocsp will produce this error, because it's part of the golang.org/x/crypto repo, from which we also import the pkcs12 package. Godep requires that all packages from the same repo be on the same version, so it can't update just one. The error message is not particularly helpful. See https://github.com/tools/godep/issues/164 for the issue dedicated to fixing it.

NOTE: Updating cfssl in particular is tricky, because cfssl vendors github.com/google/certificate-transparency/... and golang.org/x/crypto/ocsp/..., which we also vendor. In practice this means you need to check out those two dependencies to the same version cfssl uses (available in vendor/manifest in the cfssl repo). If you fail to do this, you will get conflicting types between our vendored version and the cfssl vendored version.

godep update golang.org/x/crypto/...  github.com/cloudflare/cfssl/... github.com/google/certificate-transparency/...
godep save ./...

Adding RPCs

Boulder uses gRPC for all RPCs. To add a new RPC method, add it to the relevant .proto file, then run:

docker-compose run boulder go generate ./path/to/pkg/...