An ACME-based certificate authority, written in Go.
Go to file
Daniel b64e51fe51
Adds reconnect handling for SMTP 421 events.
This commit allows the mailer to treat a SMTP 421 err as an event that
should produce a reconnect attempt. Issue #2249 describes a case where
we see this SMTP error code from the remote server when our connection
has been idle for too long. We now reconnect when this happens rather
than failing ungracefully.

The logic in the `mail-test-srv` used to force a number of initial
connections to be disconnected is changed such that half of these forced
disconnects are the normal clean connection close and half are a SMTP
421. This allows the existing integration test for server disconnects to
be reused to test the 421 reconnect logic.
2016-10-19 16:07:49 -04:00
Godeps Revert "Update google/certificate-transparency dependency. (#2242)" 2016-10-17 15:20:08 -07:00
akamai Remove direct usages of go-statsd-client in favor of using metrics.Scope (#2136) 2016-09-07 19:35:13 -04:00
bdns Retires `LookupIPv6` VA flag. (#2205) 2016-09-26 18:00:01 -07:00
ca Add gRPC support to CA (#2193) 2016-09-21 14:13:43 -07:00
cdr Properly close test servers (#2110) 2016-08-05 15:04:42 -07:00
cmd Moves `mailer.Connect()` closer to `mailer.SendMail()`. 2016-10-19 14:33:05 -04:00
core `certificateStatus` table optimizations (Part One) (#2177) 2016-09-30 14:52:19 -04:00
csr Improve error messages. (#2256) 2016-10-18 10:15:21 -07:00
data Add link to expiration email doc in emails. (#2121) 2016-08-12 15:31:57 -04:00
docs Re-apply 2138 with proper gating (#2199) 2016-09-29 17:16:03 -04:00
features Add IDN support (#2215) 2016-10-06 13:05:37 -04:00
goodkey Simplify KeyPolicy code (#2092) 2016-07-30 16:15:19 -07:00
grpc Cleanup gRPC metric formatting (#2218) 2016-10-14 10:26:13 -07:00
log Remove audit comments -- closes #2129 (#2139) 2016-08-25 18:23:42 -07:00
mail Adds reconnect handling for SMTP 421 events. 2016-10-19 16:07:49 -04:00
metrics Remove pid from stats. (#2182) 2016-09-16 10:56:45 -07:00
mocks Re-apply 2138 with proper gating (#2199) 2016-09-29 17:16:03 -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 Add IDN support (#2215) 2016-10-06 13:05:37 -04:00
probs Adds RejectedIdentifierError on Blacklisted error. (#1944) 2016-06-29 13:53:38 -07:00
publisher Add stats to Publisher (#2083) 2016-08-17 16:25:33 -07:00
ra Improve error messages. (#2256) 2016-10-18 10:15:21 -07:00
ratelimit Add certificatesPerName rate limit to integration test (#1940) 2016-06-17 16:10:05 -07:00
reloader Increase timeout to fix test failures on Mac OSX (#1966) 2016-06-23 14:13:05 -07:00
revocation Allow user specified revocation reason (#2089) 2016-08-08 14:26:52 -07:00
rpc Re-apply 2138 with proper gating (#2199) 2016-09-29 17:16:03 -04:00
sa Adds "SelectFoo" functions for each DB type. (#2259) 2016-10-19 13:44:37 -04:00
test Adds reconnect handling for SMTP 421 events. 2016-10-19 16:07:49 -04:00
va Remove direct usages of go-statsd-client in favor of using metrics.Scope (#2136) 2016-09-07 19:35:13 -04:00
vendor Revert "Update google/certificate-transparency dependency. (#2242)" 2016-10-17 15:20:08 -07:00
wfe Factor out JSON writing in WFE (#2226) 2016-10-11 14:29:57 -04:00
.dockerignore Roll forward "Run Travis tests in Docker (#1830)" (#1838) 2016-05-24 15:11:22 -07:00
.gitignore Docker improvements. 2016-04-04 16:05:08 -07:00
.travis.yml Switch to Golang 1.6.3 (#2105) 2016-08-05 16:35:43 -04:00
CODE_OF_CONDUCT.md Add Code of Conduct (#1961) 2016-06-22 14:05:25 -04:00
CONTRIBUTING.md Change review approval to use GitHub's mechanism. (#2210) 2016-09-28 11:56:13 -04:00
DESIGN.md Add documentation of the Boulder divergences from ACME (#2071) 2016-07-25 10:36:04 -04:00
Dockerfile Very basic feature flag impl (#1705) 2016-09-20 16:29:01 -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 to Golang 1.6.3 (#2105) 2016-08-05 16:35:43 -04:00
README.md Add `$GOPATH` troubleshooting to docker quickstart. (#2153) 2016-09-06 13:31:21 -04:00
docker-compose.yml Very basic feature flag impl (#1705) 2016-09-20 16:29:01 -07:00
docker-rebuild.sh Add tiny docker-compose rebuild script (#2039) 2016-07-13 13:33:22 -07:00
start.py Speed up start.py and integration test. 2015-07-28 18:07:22 -07:00
test.sh Check out a specific tag for Certbot integration tests. 2016-10-11 15:00:55 -07: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.

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 _.

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

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 RabbitMQ, libtool-ltdl, goose, and MariaDB 10.1 to work correctly. On Ubuntu and CentOS, you may have to install RabbitMQ from https://rabbitmq.com/download.html to get a recent version. If you want to save some trouble installing MariaDB and RabbitMQ you can run them using Docker:

docker-compose up -d bmysql brabbitmq 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 and RabbitMQ:

./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.

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 AMQP as a message bus. 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 in amqp-rpc.go.

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 RabbitMQ installation and MariaDB 10 installation (see above). 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