Skip to content

Commit

Permalink
Merge branch 'master' into vendorize
Browse files Browse the repository at this point in the history
Conflicts:
	analysis/analysis-engine.go
	analysis/analysis-engine_test.go
	cmd/activity-monitor/main.go
	cmd/boulder-start/main.go
  • Loading branch information
jsha committed Mar 25, 2015
2 parents ddc0d7d + 4b962b9 commit 0435e0f
Show file tree
Hide file tree
Showing 35 changed files with 1,034 additions and 1,102 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ _cgo_export.*

_testmain.go

*.sw?
*.exe
*.test
*.prof
Expand Down
20 changes: 15 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,25 +1,35 @@
FROM golang:1.4
FROM golang:1.4.2

MAINTAINER J.C. Jones "jjones@mozilla.com"
MAINTAINER J.C. Jones "jjones@letsencrypt.org"

# Boulder exposes its web application at port TCP 4000
EXPOSE 4000

# Assume the configuration is in /etc/boulder
ENV BOULDER_CONFIG=/boulder/config.json

# Load the dependencies
RUN go-wrapper download github.com/bifurcation/gose && \
go-wrapper download github.com/codegangsta/cli && \
go-wrapper download github.com/streadway/amqp && \
go-wrapper download github.com/mattn/go-sqlite3 && \
go-wrapper download github.com/go-sql-driver/mysql && \
go-wrapper download github.com/cloudflare/cfssl/auth && \
go-wrapper download github.com/cloudflare/cfssl/config && \
go-wrapper download github.com/cloudflare/cfssl/signer
#go-wrapper download github.com/cloudflare/cfssl/signer/remote && \

# Copy in the Boulder sources
RUN mkdir -p /go/src/github.com/letsencrypt/boulder
COPY . /go/src/github.com/letsencrypt/boulder

# Build Boulder
RUN go install github.com/letsencrypt/boulder/cmd/boulder-start
RUN go install \
github.com/letsencrypt/boulder/cmd/activity-monitor \
github.com/letsencrypt/boulder/cmd/boulder \
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

ENTRYPOINT ["/go/bin/boulder-start"]
CMD ["/go/bin/boulder"]
22 changes: 16 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,35 @@ This is an initial implementation of an ACME-based CA. The [ACME protocol](https
Docker
------

Boulder is available as a [Docker image from Quay.io](https://quay.io/repository/letsencrypt/boulder). The entrypoint is the Boulder main method; you can load and run it using in monolithic mode (without AMQP) like:
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.

(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`.)

The default command is the monolithic "boulder" executable, which does not require an AMQP service.

A quick-start method for running a Boulder instance is to use one of the example configurations:

```
docker run -p 4000:4000 quay.io/letsencrypt/boulder monolithic
> mkdir .boulder-config
> cp test/example-config.json .boulder-config/config.json
> docker run --name=boulder --rm=true -v $(pwd)/.boulder-config:/boulder:ro -p 4000:4000 quay.io/letsencrypt/boulder:latest boulder
```

To run a single module, specifying the AMQP server, you might use something more like:

```
docker run -p 4000:4000 quay.io/letsencrypt/boulder --amqp 'amqp://guest:guest@amqp-server:15672' wfe
> docker run --name=boulder --rm=true -v $(pwd)/.boulder-config:/boulder:ro quay.io/letsencrypt/boulder:latest boulder-ra
```

The submodules are under the `cmd/` directory.


Quickstart
----------

```
> go build github.com/letsencrypt/boulder/boulder-start
> ./boulder-start monolithic # without AMQP
> ./boulder-start monolithic-amqp # with AMQP
> go build github.com/letsencrypt/boulder/cmd/boulder
> ./boulder --config test/example-config.json
```


Expand Down
28 changes: 21 additions & 7 deletions analysis/analysis-engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package analysisengine

import (
"github.com/letsencrypt/boulder/log"
blog "github.com/letsencrypt/boulder/log"

"encoding/json"
"fmt"
"github.com/streadway/amqp"
"github.com/letsencrypt/boulder/vendor/_nuts/github.com/streadway/amqp"
)

Expand All @@ -14,20 +19,29 @@ import (

// Interface all Analysis Engines share
type AnalysisEngine interface {
ProcessMessage(amqp.Delivery)
ProcessMessage(amqp.Delivery) (err error)
}

// An Analysis Engine that just logs to the JSON Logger.
type LoggingAnalysisEngine struct {
jsonLogger *log.JsonLogger
log *blog.AuditLogger
}

func (eng *LoggingAnalysisEngine) ProcessMessage(delivery amqp.Delivery) {
func (eng *LoggingAnalysisEngine) ProcessMessage(delivery amqp.Delivery) (err error) {
// Send the entire message contents to the syslog server for debugging.
eng.jsonLogger.Debug("Message contents", delivery)
encoded, err := json.Marshal(delivery)

if err != nil {
return
}

err = eng.log.Debug(fmt.Sprintf("MONITOR: %s", encoded))
return
}

// Construct a new Analysis Engine.
func NewLoggingAnalysisEngine(logger *log.JsonLogger) AnalysisEngine {
return &LoggingAnalysisEngine{jsonLogger: logger}
func NewLoggingAnalysisEngine(logger *blog.AuditLogger) AnalysisEngine {
logger.Notice("Analysis Engine Starting")

return &LoggingAnalysisEngine{log: logger}
}
37 changes: 35 additions & 2 deletions analysis/analysis-engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package analysisengine

import (
"log/syslog"
"testing"

"github.com/letsencrypt/boulder/log"
"github.com/letsencrypt/boulder/vendor/_nuts/github.com/streadway/amqp"
"testing"
)

func TestNewLoggingAnalysisEngine(t *testing.T) {
log := log.NewJsonLogger("newEngine")
writer, _ := syslog.New(syslog.LOG_EMERG|syslog.LOG_KERN, "tag")
log, _ := log.NewAuditLogger(writer)
ae := NewLoggingAnalysisEngine(log)

// Trivially check an empty mock message
Expand All @@ -20,3 +24,32 @@ func TestNewLoggingAnalysisEngine(t *testing.T) {

// Nothing to assert
}

type MockAck struct {
// json.Marshall cannot represent a chan, so this will break
// the json.Marshal attempt in ProcessMessage and let us get
// coverage there.
JsonBreaker chan bool
}

func (m *MockAck) Ack(tag uint64, multiple bool) error {
return nil
}
func (m *MockAck) Nack(tag uint64, multiple bool, requeue bool) error {
return nil
}
func (m *MockAck) Reject(tag uint64, requeue bool) error {
return nil
}

func TestAnalysisEngineBadMessage(t *testing.T) {
writer, _ := syslog.New(syslog.LOG_EMERG|syslog.LOG_KERN, "tag")
log, _ := log.NewAuditLogger(writer)
ae := NewLoggingAnalysisEngine(log)

// Trivially check an empty mock message
d := &amqp.Delivery{Acknowledger: &MockAck{}}
ae.ProcessMessage(*d)

// Nothing to assert
}
15 changes: 12 additions & 3 deletions ca/certificate-authority.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"time"

"github.com/letsencrypt/boulder/core"
blog "github.com/letsencrypt/boulder/log"
"github.com/letsencrypt/boulder/policy"

"github.com/cloudflare/cfssl/auth"
Expand All @@ -25,6 +26,7 @@ type CertificateAuthorityImpl struct {
Signer signer.Signer
SA core.StorageAuthority
PA core.PolicyAuthority
log *blog.AuditLogger
}

// NewCertificateAuthorityImpl creates a CA that talks to a remote CFSSL
Expand All @@ -33,7 +35,9 @@ type CertificateAuthorityImpl struct {
// using CFSSL's authenticated signature scheme. A CA created in this way
// issues for a single profile on the remote signer, which is indicated
// by name in this constructor.
func NewCertificateAuthorityImpl(hostport string, authKey string, profile string) (ca *CertificateAuthorityImpl, err error) {
func NewCertificateAuthorityImpl(logger *blog.AuditLogger, hostport string, authKey string, profile string) (ca *CertificateAuthorityImpl, err error) {
logger.Notice("Certificate Authority Starting")

// Create the remote signer
localProfile := config.SigningProfile{
Expiry: time.Hour, // BOGUS: Required by CFSSL, but not used
Expand All @@ -51,9 +55,9 @@ func NewCertificateAuthorityImpl(hostport string, authKey string, profile string
return
}

pa := policy.NewPolicyAuthorityImpl()
pa := policy.NewPolicyAuthorityImpl(logger)

ca = &CertificateAuthorityImpl{Signer: signer, profile: profile, PA: pa}
ca = &CertificateAuthorityImpl{Signer: signer, profile: profile, PA: pa, log: logger}
return
}

Expand All @@ -68,6 +72,7 @@ func (ca *CertificateAuthorityImpl) IssueCertificate(csr x509.CertificateRequest
commonName = hostNames[0]
} else {
err = errors.New("Cannot issue a certificate without a hostname.")
ca.log.WarningErr(err)
return
}

Expand All @@ -78,12 +83,14 @@ func (ca *CertificateAuthorityImpl) IssueCertificate(csr x509.CertificateRequest
identifier := core.AcmeIdentifier{Type: core.IdentifierDNS, Value: commonName}
if err = ca.PA.WillingToIssue(identifier); err != nil {
err = errors.New("Policy forbids issuing for name " + commonName)
ca.log.AuditErr(err)
return
}
for _, name := range hostNames {
identifier = core.AcmeIdentifier{Type: core.IdentifierDNS, Value: name}
if err = ca.PA.WillingToIssue(identifier); err != nil {
err = errors.New("Policy forbids issuing for name " + name)
ca.log.AuditErr(err)
return
}
}
Expand All @@ -110,12 +117,14 @@ func (ca *CertificateAuthorityImpl) IssueCertificate(csr x509.CertificateRequest

if len(certPEM) == 0 {
err = errors.New("No certificate returned by server")
ca.log.WarningErr(err)
return
}

block, _ := pem.Decode(certPEM)
if block == nil || block.Type != "CERTIFICATE" {
err = errors.New("Invalid certificate value returned")
ca.log.WarningErr(err)
return
}
certDER := block.Bytes
Expand Down
8 changes: 6 additions & 2 deletions ca/certificate-authority_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/cloudflare/cfssl/signer/local"
_ "github.com/mattn/go-sqlite3"

blog "github.com/letsencrypt/boulder/log"
"github.com/letsencrypt/boulder/sa"
"github.com/letsencrypt/boulder/test"
)
Expand Down Expand Up @@ -219,6 +220,9 @@ var NO_NAME_CSR_HEX = "308202523082013a020100300d310b300906035504061302555330820
"1778a629b584f2bc059489a236131de9b444adca90218c31a499a485"

func TestIssueCertificate(t *testing.T) {
// Audit logger
audit, _ := blog.Dial("", "", "tag")

// Decode pre-generated values
caKeyPEM, _ := pem.Decode([]byte(CA_KEY_PEM))
caKey, _ := x509.ParsePKCS1PrivateKey(caKeyPEM.Bytes)
Expand All @@ -234,7 +238,7 @@ func TestIssueCertificate(t *testing.T) {
profileName := "ee"

// Create an SA
sa, err := sa.NewSQLStorageAuthority("sqlite3", ":memory:")
sa, err := sa.NewSQLStorageAuthority(audit, "sqlite3", ":memory:")
test.AssertNotError(t, err, "Failed to create SA")
sa.InitTables()

Expand Down Expand Up @@ -273,7 +277,7 @@ func TestIssueCertificate(t *testing.T) {

// Create a CA
// Uncomment to test with a remote signer
ca, err := NewCertificateAuthorityImpl(hostPort, authKey, profileName)
ca, err := NewCertificateAuthorityImpl(audit, hostPort, authKey, profileName)
test.AssertNotError(t, err, "Failed to create CA")
ca.SA = sa

Expand Down
Loading

0 comments on commit 0435e0f

Please sign in to comment.