Fix Docker setup.
Add an easy script to build and run the Docker instance. Update some out-of-date information in the README. Add goose to the Docker image. Remove unnecessary go install step from Dockerfile. Allow dns-test-srv to return a hardcoded address other than localhost. This was preventing a Dockerized Boulder from answering requests from a letsencrypt client on the host. Change allowLoopbackAddresses to allowRestrictedAddresses and make it cover all the private IPv4 ranges. The host IP in Docker is commonly in the 172.* range. Fix a couple of references to lets-encrypt-preview. This was inspired by investigation into https://github.com/letsencrypt/boulder/issues/756. To try and reproduce, I tried running Boulder inside a container, and found some broken things.
This commit is contained in:
parent
566a8e4189
commit
19c68a01e0
13
Dockerfile
13
Dockerfile
|
@ -33,7 +33,7 @@ EXPOSE 4000
|
|||
ENV BOULDER_CONFIG /go/src/github.com/letsencrypt/boulder/test/boulder-config.json
|
||||
|
||||
# Get the Let's Encrypt client
|
||||
RUN git clone https://www.github.com/letsencrypt/lets-encrypt-preview.git /letsencrypt
|
||||
RUN git clone https://www.github.com/letsencrypt/letsencrypt.git /letsencrypt
|
||||
WORKDIR /letsencrypt
|
||||
RUN ./bootstrap/debian.sh && \
|
||||
apt-get clean && \
|
||||
|
@ -43,20 +43,13 @@ RUN ./bootstrap/debian.sh && \
|
|||
RUN virtualenv --no-site-packages -p python2 venv && \
|
||||
./venv/bin/pip install -r requirements.txt -e acme -e .[dev,docs,testing] -e letsencrypt-apache -e letsencrypt-nginx
|
||||
|
||||
RUN go get bitbucket.org/liamstask/goose/cmd/goose
|
||||
|
||||
ENV LETSENCRYPT_PATH /letsencrypt
|
||||
|
||||
# Copy in the Boulder sources
|
||||
COPY . /go/src/github.com/letsencrypt/boulder
|
||||
|
||||
# Build Boulder
|
||||
RUN go install \
|
||||
github.com/letsencrypt/boulder/cmd/activity-monitor \
|
||||
github.com/letsencrypt/boulder/cmd/boulder-ca \
|
||||
github.com/letsencrypt/boulder/cmd/boulder-ra \
|
||||
github.com/letsencrypt/boulder/cmd/boulder-sa \
|
||||
github.com/letsencrypt/boulder/cmd/boulder-va \
|
||||
github.com/letsencrypt/boulder/cmd/boulder-wfe
|
||||
|
||||
WORKDIR /go/src/github.com/letsencrypt/boulder
|
||||
CMD ["bash", "-c", "service mysql start && \
|
||||
service rsyslog start && \
|
||||
|
|
62
README.md
62
README.md
|
@ -7,49 +7,30 @@ This is an initial implementation of an ACME-based CA. The [ACME protocol](https
|
|||
[](https://travis-ci.org/letsencrypt/boulder)
|
||||
[](https://coveralls.io/r/letsencrypt/boulder)
|
||||
|
||||
Docker
|
||||
Quickstart
|
||||
------
|
||||
|
||||
Boulder is available as a [Docker image from Quay.io](https://quay.io/repository/letsencrypt/boulder). The Docker image expects the `config.json` file to be located at `/boulder/config.json` within the container.
|
||||
Boulder has a Dockerfile to make it easy to install and set up all its
|
||||
dependencies. This approach is most suitable if you just need to set up Boulder
|
||||
for the purpose of testing client software against it. To start Boulder
|
||||
in a Docker container, run:
|
||||
|
||||
(Note: You can override the `config.json` location by specifying a different BOULDER_CONFIG environment variable, such as with `-e BOULDER_CONFIG=mypath/myfile.config`.)
|
||||
./test/run-docker.sh
|
||||
|
||||
There are no default commands; you must choose one of the executables from the `cmd` path.
|
||||
|
||||
There are several tags available:
|
||||
- `stable` is maintained by the Let's Encrypt team as a fairly stable copy of Boulder.
|
||||
- `latest` is a more recent build of Boulder. It may lag behind the `master` ref, as automated builds are being reworked.
|
||||
- Tags for individual short-format git refs, representing those builds.
|
||||
|
||||
|
||||
A quick-start method for running a Boulder instance is to use one of the example configurations:
|
||||
|
||||
docker run -i --name=boulder --read-only=true --rm=true -p 4000:4000 quay.io/letsencrypt/boulder:latest
|
||||
|
||||
|
||||
Alternatively, to run all services locally, using AMQP to pass messages between them, you can use:
|
||||
|
||||
```
|
||||
> python start.py
|
||||
# start.py will use the configuration specified by BOULDER_CONFIG or test/boulder-config.json
|
||||
```
|
||||
|
||||
To run a single module, specifying the AMQP server, you might use something more like:
|
||||
|
||||
```
|
||||
> docker run --name=boulder --read-only=true --rm=true -v $(pwd)/.boulder-config:/boulder:ro quay.io/letsencrypt/boulder:stable boulder-ra
|
||||
```
|
||||
|
||||
|
||||
|
||||
Quickstart
|
||||
Slow start
|
||||
----------
|
||||
|
||||
Boulder requires an installation of RabbitMQ, libtool-ltdl, and
|
||||
This approach is better if you intend to develop on Boulder frequently, because
|
||||
it's challenging to develop inside the Docker container.
|
||||
|
||||
Boulder requires an installation of RabbitMQ, libtool-ltdl, goose, and
|
||||
MariaDB 10 to work correctly. On Ubuntu and CentOS, you may have to
|
||||
install RabbitMQ from https://rabbitmq.com/download.html to get a
|
||||
recent version.
|
||||
|
||||
Also, Boulder requires Go 1.5. As of September 2015 this version is not yet
|
||||
available in OS repostiories, so you will have to install from https://golang.org/dl/.
|
||||
|
||||
Ubuntu:
|
||||
|
||||
sudo apt-get install libltdl3-dev mariadb-server rabbitmq-server
|
||||
|
@ -69,19 +50,22 @@ or
|
|||
(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.)
|
||||
|
||||
```
|
||||
> go get bitbucket.org/liamstask/goose/cmd/goose
|
||||
> go get github.com/letsencrypt/boulder/ # Ignore errors about no buildable files
|
||||
> cd $GOPATH/src/github.com/letsencrypt/boulder
|
||||
> ./test/create_db.sh
|
||||
# This starts each Boulder component with test configs. Ctrl-C kills all.
|
||||
> ./start.py
|
||||
# Run tests
|
||||
> ./test.sh
|
||||
```
|
||||
|
||||
The databases that boulder requires to operate in development and
|
||||
testing can be created using test/create\_db.sh. It uses the root
|
||||
MariaDB user, so if you have disabled that account you may have to
|
||||
adjust the file or recreate the commands.
|
||||
Note: create\_db.sh it uses the root MariaDB user, so if you
|
||||
have disabled that account you may have to adjust the file or
|
||||
recreate the commands.
|
||||
|
||||
You can also check out the official client from
|
||||
https://github.com/letsencrypt/lets-encrypt-preview/ and follow the setup
|
||||
https://github.com/letsencrypt/letsencrypt/ and follow the setup
|
||||
instructions there.
|
||||
|
||||
Component Model
|
||||
|
@ -130,7 +114,7 @@ and to [avoid insecure fallback in go
|
|||
get](https://github.com/golang/go/issues/9637).
|
||||
|
||||
Local development also requires a RabbitMQ installation and MariaDB
|
||||
10 installation. MariaDB should be run on port 3306 for the
|
||||
10 or MySQL installation (see above). MariaDB should be run on port 3306 for the
|
||||
default integration tests.
|
||||
|
||||
To update the Go dependencies:
|
||||
|
|
20
core/dns.go
20
core/dns.go
|
@ -45,9 +45,9 @@ var (
|
|||
|
||||
// DNSResolverImpl represents a client that talks to an external resolver
|
||||
type DNSResolverImpl struct {
|
||||
DNSClient *dns.Client
|
||||
Servers []string
|
||||
allowLoopbackAddresses bool
|
||||
DNSClient *dns.Client
|
||||
Servers []string
|
||||
allowRestrictedAddresses bool
|
||||
}
|
||||
|
||||
// NewDNSResolverImpl constructs a new DNS resolver object that utilizes the
|
||||
|
@ -59,9 +59,9 @@ func NewDNSResolverImpl(dialTimeout time.Duration, servers []string) *DNSResolve
|
|||
dnsClient.DialTimeout = dialTimeout
|
||||
|
||||
return &DNSResolverImpl{
|
||||
DNSClient: dnsClient,
|
||||
Servers: servers,
|
||||
allowLoopbackAddresses: false,
|
||||
DNSClient: dnsClient,
|
||||
Servers: servers,
|
||||
allowRestrictedAddresses: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ func NewDNSResolverImpl(dialTimeout time.Duration, servers []string) *DNSResolve
|
|||
// This constructor should *only* be called from tests (unit or integration).
|
||||
func NewTestDNSResolverImpl(dialTimeout time.Duration, servers []string) *DNSResolverImpl {
|
||||
resolver := NewDNSResolverImpl(dialTimeout, servers)
|
||||
resolver.allowLoopbackAddresses = true
|
||||
resolver.allowRestrictedAddresses = true
|
||||
return resolver
|
||||
}
|
||||
|
||||
|
@ -120,8 +120,8 @@ func (dnsResolver *DNSResolverImpl) LookupTXT(hostname string) ([]string, time.D
|
|||
return txt, rtt, err
|
||||
}
|
||||
|
||||
func isPrivateV4(ip net.IP, allowLoopback bool) bool {
|
||||
return rfc1918_10.Contains(ip) || rfc1918_172_16.Contains(ip) || rfc1918_192_168.Contains(ip) || (!allowLoopback && rfc5735_127.Contains(ip))
|
||||
func isPrivateV4(ip net.IP) bool {
|
||||
return rfc1918_10.Contains(ip) || rfc1918_172_16.Contains(ip) || rfc1918_192_168.Contains(ip) || rfc5735_127.Contains(ip)
|
||||
}
|
||||
|
||||
// LookupHost sends a DNS query to find all A records associated with the provided
|
||||
|
@ -141,7 +141,7 @@ func (dnsResolver *DNSResolverImpl) LookupHost(hostname string) ([]net.IP, time.
|
|||
|
||||
for _, answer := range r.Answer {
|
||||
if answer.Header().Rrtype == dns.TypeA {
|
||||
if a, ok := answer.(*dns.A); ok && a.A.To4() != nil && !isPrivateV4(a.A, dnsResolver.allowLoopbackAddresses) {
|
||||
if a, ok := answer.(*dns.A); ok && a.A.To4() != nil && (!isPrivateV4(a.A) || dnsResolver.allowRestrictedAddresses) {
|
||||
addrs = append(addrs, a.A)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/miekg/dns"
|
||||
|
@ -19,6 +20,14 @@ func dnsHandler(w dns.ResponseWriter, r *dns.Msg) {
|
|||
m.SetReply(r)
|
||||
m.Compress = false
|
||||
|
||||
// Normally this test DNS server will return 127.0.0.1 for everything.
|
||||
// However, in some situations (for instance Docker), it's useful to return a
|
||||
// different hardcoded host. You can do so by setting the FAKE_DNS environment
|
||||
// variable.
|
||||
fakeDNS := os.Getenv("FAKE_DNS")
|
||||
if fakeDNS == "" {
|
||||
fakeDNS = "127.0.0.1"
|
||||
}
|
||||
for _, q := range r.Question {
|
||||
fmt.Printf("dns-srv: Query -- [%s] %s\n", q.Name, dns.TypeToString[q.Qtype])
|
||||
switch q.Qtype {
|
||||
|
@ -30,7 +39,7 @@ func dnsHandler(w dns.ResponseWriter, r *dns.Msg) {
|
|||
Class: dns.ClassINET,
|
||||
Ttl: 0,
|
||||
}
|
||||
record.A = net.ParseIP("127.0.0.1")
|
||||
record.A = net.ParseIP(fakeDNS)
|
||||
|
||||
m.Answer = append(m.Answer, record)
|
||||
case dns.TypeMX:
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Build and run a docker image for Boulder. This is suitable for running
|
||||
# repeatedly during development because Docker will cache the image it builds,
|
||||
# and will only re-do the minimum necessary.
|
||||
#
|
||||
# NOTE: Currently we're not able to effectively cache the DB setup steps,
|
||||
# because setting up the DB depends on source files in the Boulder repo. So any
|
||||
# time source files change, Docker treats that as potentially invalidating the
|
||||
# steps that came after the COPY. In theory we could add a step that copies only
|
||||
# the files necessary to do the migrations, run them, and then copy the rest of
|
||||
# the source.
|
||||
set -o errexit
|
||||
cd $(dirname $0)/..
|
||||
|
||||
# In order to talk to a letsencrypt client running on the host, the fake DNS
|
||||
# client used in Boulder's start.py needs to know what the host's IP is from the
|
||||
# perspective of the container. We try to figure it out automatically. If you'd
|
||||
# like your Boulder instance to always talk to some other host, you can set
|
||||
# FAKE_DNS to that host's IP address.
|
||||
if [ -z "${FAKE_DNS}" ] ; then
|
||||
FAKE_DNS=$(ifconfig docker0 | sed -n 's/ *inet addr:\([0-9.]\+\).*/\1/p')
|
||||
fi
|
||||
docker build --tag boulder .
|
||||
# The -i command makes the instance interactive, so you can kill start.py with Ctrl-C.
|
||||
docker run \
|
||||
--interactive \
|
||||
--tty \
|
||||
--rm=true \
|
||||
--publish 4000-4001:4000-4001 \
|
||||
--publish 8000-8100:8000-8100 \
|
||||
--env FAKE_DNS="${FAKE_DNS}" \
|
||||
boulder
|
Loading…
Reference in New Issue