Skip to content
An ACME-based certificate authority, written in Go.
Go Python TSQL Other
Branch: master
Clone or download

Latest commit

rolandshoemaker cmd/ceremony: support qualified CPS policies (#4811)
Adds support for qualified CPS policies to root/intermediate generation.
This changes the existing policy-oids fields to a policies field which covers both bare policies and id-qt-cps qualified policies.

Fixes #4724
Latest commit 69a3baa May 21, 2020

Files

Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
akamai Upgrade to latest protoc and protoc-gen-go (#4794) Apr 24, 2020
bdns Remove newlines from log messages. (#4777) Apr 16, 2020
ca Upgrade to latest protoc and protoc-gen-go (#4794) Apr 24, 2020
canceled tidy: typo fixes flagged by codespell (#4634) Jan 7, 2020
cmd cmd/ceremony: support qualified CPS policies (#4811) May 21, 2020
core Upgrade to latest protoc and protoc-gen-go (#4794) Apr 24, 2020
csr Add a blocked keys table, and use it (#4773) Apr 15, 2020
ctpolicy Switch away from old style statsd metrics wrappers (#4606) Dec 18, 2019
data Fixes Mandrill UNSUB merge tag (#2524) Jan 25, 2017
db Switch to godoc-style comments. (#4760) Apr 9, 2020
docs docs: update multi-va.md for prod deploy (#4767) Apr 9, 2020
errors gofmt code with -s (simplify) flag (#4763) Apr 9, 2020
features Add bad-key-revoker daemon (#4788) Apr 23, 2020
goodkey goodkey: early rejection of unsupported key types (#4809) May 19, 2020
grpc Upgrade to latest protoc and protoc-gen-go (#4794) Apr 24, 2020
iana Require email domains end in a IANA suffix (#4037) Jan 29, 2019
identifier core: split identifier types into separate package. (#4225) May 23, 2019
log Replace clock.Default() with clock.New() (#4761) Apr 9, 2020
mail Replace clock.Default() with clock.New() (#4761) Apr 9, 2020
metrics Switch away from old style statsd metrics wrappers (#4606) Dec 18, 2019
mocks Add a blocked keys table, and use it (#4773) Apr 15, 2020
nonce Upgrade to latest protoc and protoc-gen-go (#4794) Apr 24, 2020
ocsp Fix nits found by staticcheck (#4726) Mar 30, 2020
pkcs11helpers Ceremony monolith (#4678) Mar 27, 2020
policy Remove unused code. (#4722) Mar 27, 2020
probs Use explicit fmt.Sprintf for ProblemDetails (#4787) Apr 21, 2020
publisher Upgrade to latest protoc and protoc-gen-go (#4794) Apr 24, 2020
ra Handful of revocation pkg cleanups (#4801) May 1, 2020
ratelimit va: exempt multi-va enforcement by domain/acct ID. (#4458) Oct 7, 2019
reloader Spelling (#2500) Jan 16, 2017
revocation Handful of revocation pkg cleanups (#4801) May 1, 2020
sa Upgrade to latest protoc and protoc-gen-go (#4794) Apr 24, 2020
test Move multiva to config/ (#4808) May 14, 2020
va Upgrade to latest protoc and protoc-gen-go (#4794) Apr 24, 2020
vendor Upgrade to latest protoc and protoc-gen-go (#4794) Apr 24, 2020
web Use explicit fmt.Sprintf for ProblemDetails (#4787) Apr 21, 2020
wfe Handful of revocation pkg cleanups (#4801) May 1, 2020
wfe2 Handful of revocation pkg cleanups (#4801) May 1, 2020
.codespell.ignore.txt CI: Add codespell to detect common typos. (#4637) Jan 8, 2020
.dockerignore Roll forward "Run Travis tests in Docker (#1830)" (#1838) May 24, 2016
.gitignore Add PKCS#11 certificate generation tool (#3729) Jun 12, 2018
.golangci.yml Switch to golangci-lint for our lints. (#4766) Apr 9, 2020
.travis.yml Test with Go 1.14.1 only. (#4785) Apr 16, 2020
CODEOWNERS Update CODEOWNERS (#3446) Feb 14, 2018
CODE_OF_CONDUCT.md Add Code of Conduct (#1961) Jun 22, 2016
CONTRIBUTING.md Update review policy in CONTRIBUTING.md. (#4684) Feb 21, 2020
LICENSE.txt Remove all stray copyright headers and appends the initial line to LI… May 31, 2016
Makefile Switch to modules (#4211) May 23, 2019
README.md Fix link to test PKI info (#4750) Apr 8, 2020
docker-compose.yml Upgrade to latest protoc and protoc-gen-go (#4794) Apr 24, 2020
go.mod Upgrade to latest protoc and protoc-gen-go (#4794) Apr 24, 2020
go.sum Upgrade to latest protoc and protoc-gen-go (#4794) Apr 24, 2020
start.py integration: use python3 (#4582) Nov 28, 2019
test.sh Port v1 integration tests to v2. (#4807) May 13, 2020

README.md

Boulder - An ACME CA

Build Status Coverage Status

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. Boulder is the software that runs Let's Encrypt.

Contents

Overview

Boulder is divided into the following main components:

  1. Web Front Ends (one per API version)
  2. Registration Authority
  3. Validation Authority
  4. Certificate Authority
  5. Storage Authority
  6. Publisher
  7. OCSP Updater
  8. OCSP Responder

This component model lets us separate the function of the CA by security context. The Web Front End, Validation Authority, OCSP Responder and Publisher 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 most lines indicating SA RPCs are not shown here.

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

Internally, the logic of the system is based around five types of objects: accounts, authorizations, challenges, orders (for ACME v2) and certificates, mapping directly to the resources of the same name in ACME.

We run two Web Front Ends, one for each ACME API version. Only the front end components differentiate between API version. 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. A high level overview for 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.

Setting up Boulder

Development

Boulder has a Dockerfile and uses Docker Compose 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 for development/experimentation. It is not suitable for use as a production environment.

While we aim to make Boulder easy to setup ACME client developers may find Pebble, a miniature version of Boulder, to be better suited for continuous integration and quick experimentation.

We recommend setting git's fsckObjects setting before getting a copy of Boulder to have better integrity guarantees for updates.

Make sure you have a local copy of Boulder in your $GOPATH, and that you are in that directory:

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

Additionally, make sure you have Docker Engine 1.13.0+ and Docker Compose 1.10.0+ installed. If you do not, you can follow Docker's installation instructions.

We recommend having at least 2GB of RAM available on your Docker host. In practice using less RAM may result in the MariaDB container failing in non-obvious ways.

To start Boulder in a Docker container, run:

docker-compose up

To run tests:

docker-compose run --use-aliases boulder ./test.sh

To run a specific unittest:

docker-compose run --use-aliases 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 the Docker containers 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 _, and that it doesn't contain any dangling symlinks.

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. This will cause Boulder's stubbed-out DNS resolver (sd-test-srv) to respond to all A queries with the address in FAKE_DNS.

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 --use-aliases -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-ALPN-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.

Working with Certbot

Check out the Certbot client from https://github.com/certbot/certbot and follow their setup instructions. 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 use a convenient alias for certbot (certbot_test) with a custom SERVER environment variable:

SERVER=http://localhost:4001/directory certbot_test certonly --standalone -d test.example.com

Your local Boulder instance uses a fake DNS resolver that returns 127.0.0.1 for any query, so you can use any value for the -d flag. To return an answer other than 127.0.0.1 change the Boulder FAKE_DNS environment variable to another IP address.

To use the legacy ACME v1 API over change SERVER to http://localhost:4000/directory.

Working with another ACME Client

Once you have followed the Boulder development environment instructions and have started the containers you will find the ACME endpoints exposed to your host at the following URLs:

  • ACME v1, HTTP: http://localhost:4000/directory
  • ACME v2, HTTP: http://localhost:4001/directory
  • ACME v1, HTTPS: https://localhost:4430/directory
  • ACME v2, HTTPS: https://localhost:4431/directory

To access the HTTPS versions of the endpoints you will need to configure your ACME client software to use a CA truststore that contains the test/wfe-tls/minica.pem CA certificate. See test/PKI.md for more information.

Your local Boulder instance uses a fake DNS resolver that returns 127.0.0.1 for any query, allowing you to issue certificates for any domain as if it resolved to your localhost. To return an answer other than 127.0.0.1 change the Boulder FAKE_DNS environment variable to another IP address.

Most often you will want to configure FAKE_DNS to point to your host machine where you run an ACME client. Remember to also configure the ACME client to use ports 5002 and 5001 instead of 80 and 443 for HTTP-01 and TLS-ALPN-01 challenge servers (or customize the Boulder VA configuration to match your port choices).

Production

Boulder is custom built for Let's Encrypt and is intended only to support the Web PKI and the CA/Browser forum's baseline requirements. In our experience often Boulder is not the right fit for organizations that are evaluating it for production usage. In most cases a centrally managed PKI that doesn't require domain-authorization with ACME is a better choice. For this environment we recommend evaluating cfssl or a project other than Boulder.

We offer a brief deployment and implementation guide that describes some of the required work and security considerations involved in using Boulder in a production environment. As-is the docker based Boulder development environment is not suitable for production usage. It uses private key material that is publicly available, exposes debug ports and is brittle to component failure.

While we are supportive of other organization's deploying Boulder in a production setting we prioritize support and development work that favors Let's Encrypt's mission. This means we may not be able to provide timely support or accept pull-requests that deviate significantly from our first line goals. If you've thoroughly evaluated the alternatives and Boulder is definitely the best fit we're happy to answer questions to the best of our ability.

Contributing

Please take a look at CONTRIBUTING.md for our guidelines on submitting patches, code review process, code of conduct, and various other tips related to working on the codebase.

License

This project is licensed under the Mozilla Public License 2.0, the full text of which can be found in the LICENSE.txt file.

You can’t perform that action at this time.