From 1a2825138d4fe2aea46695374309c5c83f08f7ee Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Thu, 6 Aug 2015 16:57:38 -0700 Subject: [PATCH] Actually wire everything into the PADB --- ca/certificate-authority.go | 49 ++++-------------------- ca/certificate-authority_test.go | 36 ++++++++++-------- cmd/boulder-ca/main.go | 2 +- cmd/boulder-ra/main.go | 3 +- cmd/shell.go | 63 +++++++++++++++++++++++++------ policy/policy-authority.go | 13 +++++-- policy/policy-authority_test.go | 7 +++- ra/registration-authority.go | 14 +++++-- ra/registration-authority_test.go | 10 ++++- test/boulder-config.json | 5 ++- wfe/web-front-end_test.go | 7 +++- 11 files changed, 125 insertions(+), 84 deletions(-) diff --git a/ca/certificate-authority.go b/ca/certificate-authority.go index 0b274e6d7..7c6265c90 100644 --- a/ca/certificate-authority.go +++ b/ca/certificate-authority.go @@ -15,6 +15,7 @@ import ( "io/ioutil" "time" + "github.com/letsencrypt/boulder/cmd" "github.com/letsencrypt/boulder/core" blog "github.com/letsencrypt/boulder/log" "github.com/letsencrypt/boulder/policy" @@ -27,43 +28,6 @@ import ( "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer/local" ) -// Config defines the JSON configuration file schema -type Config struct { - Profile string - TestMode bool - DBDriver string - DBConnect string - SerialPrefix int - Key KeyConfig - // LifespanOCSP is how long OCSP responses are valid for; It should be longer - // than the minTimeToExpiry field for the OCSP Updater. - LifespanOCSP string - // How long issued certificates are valid for, should match expiry field - // in cfssl config. - Expiry string - // The maximum number of subjectAltNames in a single certificate - MaxNames int - CFSSL cfsslConfig.Config - - // DebugAddr is the address to run the /debug handlers on. - DebugAddr string -} - -// KeyConfig should contain either a File path to a PEM-format private key, -// or a PKCS11Config defining how to load a module for an HSM. -type KeyConfig struct { - File string - PKCS11 PKCS11Config -} - -// PKCS11Config defines how to load a module for an HSM. -type PKCS11Config struct { - Module string - Token string - PIN string - Label string -} - // This map is used to detect algorithms in crypto/x509 that // are no longer considered sufficiently strong. // * No MD2, MD5, or SHA-1 @@ -103,7 +67,7 @@ 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(cadb core.CertificateAuthorityDatabase, config Config, issuerCert string) (*CertificateAuthorityImpl, error) { +func NewCertificateAuthorityImpl(cadb core.CertificateAuthorityDatabase, config cmd.CAConfig, commonConfig cmd.CommonConfig) (*CertificateAuthorityImpl, error) { var ca *CertificateAuthorityImpl var err error logger := blog.GetAuditLogger() @@ -131,7 +95,7 @@ func NewCertificateAuthorityImpl(cadb core.CertificateAuthorityDatabase, config return nil, err } - issuer, err := loadIssuer(issuerCert) + issuer, err := loadIssuer(commonConfig.IssuerCert) if err != nil { return nil, err } @@ -156,7 +120,10 @@ func NewCertificateAuthorityImpl(cadb core.CertificateAuthorityDatabase, config return nil, err } - pa := policy.NewPolicyAuthorityImpl() + pa, err := policy.NewPolicyAuthorityImpl(commonConfig.PolicyDBDriver, commonConfig.PolicyDBConnect) + if err != nil { + return nil, err + } ca = &CertificateAuthorityImpl{ Signer: signer, @@ -182,7 +149,7 @@ func NewCertificateAuthorityImpl(cadb core.CertificateAuthorityDatabase, config return ca, nil } -func loadKey(keyConfig KeyConfig) (priv crypto.Signer, err error) { +func loadKey(keyConfig cmd.KeyConfig) (priv crypto.Signer, err error) { if keyConfig.File != "" { var keyBytes []byte keyBytes, err = ioutil.ReadFile(keyConfig.File) diff --git a/ca/certificate-authority_test.go b/ca/certificate-authority_test.go index 2b41246bc..9a5572c11 100644 --- a/ca/certificate-authority_test.go +++ b/ca/certificate-authority_test.go @@ -18,6 +18,7 @@ import ( cfsslConfig "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/config" ocspConfig "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp/config" _ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/mattn/go-sqlite3" + "github.com/letsencrypt/boulder/cmd" "github.com/letsencrypt/boulder/mocks" "github.com/letsencrypt/boulder/core" @@ -337,14 +338,19 @@ var log = mocks.UseMockLog() // CFSSL config const profileName = "ee" const caKeyFile = "../test/test-ca.key" -const caCertFile = "../test/test-ca.pem" + +var exCommon = cmd.CommonConfig{ + IssuerCert: "../test/test-ca.pem", + PolicyDBDriver: "sqlite3", + PolicyDBConnect: ":memory:", +} func TestMain(m *testing.M) { os.Exit(m.Run()) } -func setup(t *testing.T) (cadb core.CertificateAuthorityDatabase, storageAuthority core.StorageAuthority, caConfig Config) { +func setup(t *testing.T) (cadb core.CertificateAuthorityDatabase, storageAuthority core.StorageAuthority, caConfig cmd.CAConfig) { // Create an SA ssa, err := sa.NewSQLStorageAuthority("sqlite3", ":memory:") test.AssertNotError(t, err, "Failed to create SA") @@ -354,10 +360,10 @@ func setup(t *testing.T) (cadb core.CertificateAuthorityDatabase, storageAuthori cadb, _ = mocks.NewMockCertificateAuthorityDatabase() // Create a CA - caConfig = Config{ + caConfig = cmd.CAConfig{ Profile: profileName, SerialPrefix: 17, - Key: KeyConfig{ + Key: cmd.KeyConfig{ File: caKeyFile, }, TestMode: true, @@ -393,8 +399,8 @@ func setup(t *testing.T) (cadb core.CertificateAuthorityDatabase, storageAuthori }, }, OCSP: &ocspConfig.Config{ - CACertFile: caCertFile, - ResponderCertFile: caCertFile, + CACertFile: exCommon.IssuerCert, + ResponderCertFile: exCommon.IssuerCert, KeyFile: caKeyFile, }, }, @@ -405,13 +411,13 @@ func setup(t *testing.T) (cadb core.CertificateAuthorityDatabase, storageAuthori func TestFailNoSerial(t *testing.T) { cadb, _, caConfig := setup(t) caConfig.SerialPrefix = 0 - _, err := NewCertificateAuthorityImpl(cadb, caConfig, caCertFile) + _, err := NewCertificateAuthorityImpl(cadb, caConfig, exCommon) test.AssertError(t, err, "CA should have failed with no SerialPrefix") } func TestRevoke(t *testing.T) { cadb, storageAuthority, caConfig := setup(t) - ca, err := NewCertificateAuthorityImpl(cadb, caConfig, caCertFile) + ca, err := NewCertificateAuthorityImpl(cadb, caConfig, exCommon) test.AssertNotError(t, err, "Failed to create CA") if err != nil { return @@ -443,7 +449,7 @@ func TestRevoke(t *testing.T) { func TestIssueCertificate(t *testing.T) { cadb, storageAuthority, caConfig := setup(t) - ca, err := NewCertificateAuthorityImpl(cadb, caConfig, caCertFile) + ca, err := NewCertificateAuthorityImpl(cadb, caConfig, exCommon) test.AssertNotError(t, err, "Failed to create CA") ca.SA = storageAuthority ca.MaxKeySize = 4096 @@ -519,7 +525,7 @@ func TestIssueCertificate(t *testing.T) { func TestRejectNoName(t *testing.T) { cadb, storageAuthority, caConfig := setup(t) - ca, err := NewCertificateAuthorityImpl(cadb, caConfig, caCertFile) + ca, err := NewCertificateAuthorityImpl(cadb, caConfig, exCommon) test.AssertNotError(t, err, "Failed to create CA") ca.SA = storageAuthority ca.MaxKeySize = 4096 @@ -535,7 +541,7 @@ func TestRejectNoName(t *testing.T) { func TestRejectTooManyNames(t *testing.T) { cadb, storageAuthority, caConfig := setup(t) - ca, err := NewCertificateAuthorityImpl(cadb, caConfig, caCertFile) + ca, err := NewCertificateAuthorityImpl(cadb, caConfig, exCommon) test.AssertNotError(t, err, "Failed to create CA") ca.SA = storageAuthority @@ -548,7 +554,7 @@ func TestRejectTooManyNames(t *testing.T) { func TestDeduplication(t *testing.T) { cadb, storageAuthority, caConfig := setup(t) - ca, err := NewCertificateAuthorityImpl(cadb, caConfig, caCertFile) + ca, err := NewCertificateAuthorityImpl(cadb, caConfig, exCommon) test.AssertNotError(t, err, "Failed to create CA") ca.SA = storageAuthority ca.MaxKeySize = 4096 @@ -577,7 +583,7 @@ func TestDeduplication(t *testing.T) { func TestRejectValidityTooLong(t *testing.T) { cadb, storageAuthority, caConfig := setup(t) - ca, err := NewCertificateAuthorityImpl(cadb, caConfig, caCertFile) + ca, err := NewCertificateAuthorityImpl(cadb, caConfig, exCommon) test.AssertNotError(t, err, "Failed to create CA") ca.SA = storageAuthority ca.MaxKeySize = 4096 @@ -598,7 +604,7 @@ func TestRejectValidityTooLong(t *testing.T) { func TestShortKey(t *testing.T) { cadb, storageAuthority, caConfig := setup(t) - ca, err := NewCertificateAuthorityImpl(cadb, caConfig, caCertFile) + ca, err := NewCertificateAuthorityImpl(cadb, caConfig, exCommon) ca.SA = storageAuthority ca.MaxKeySize = 4096 @@ -611,7 +617,7 @@ func TestShortKey(t *testing.T) { func TestRejectBadAlgorithm(t *testing.T) { cadb, storageAuthority, caConfig := setup(t) - ca, err := NewCertificateAuthorityImpl(cadb, caConfig, caCertFile) + ca, err := NewCertificateAuthorityImpl(cadb, caConfig, exCommon) ca.SA = storageAuthority ca.MaxKeySize = 4096 diff --git a/cmd/boulder-ca/main.go b/cmd/boulder-ca/main.go index 300bbd589..2a94b6a15 100644 --- a/cmd/boulder-ca/main.go +++ b/cmd/boulder-ca/main.go @@ -40,7 +40,7 @@ func main() { cmd.FailOnError(err, "Failed to create CA tables") } - cai, err := ca.NewCertificateAuthorityImpl(cadb, c.CA, c.Common.IssuerCert) + cai, err := ca.NewCertificateAuthorityImpl(cadb, c.CA, c.Common) cmd.FailOnError(err, "Failed to create CA impl") cai.MaxKeySize = c.Common.MaxKeySize diff --git a/cmd/boulder-ra/main.go b/cmd/boulder-ra/main.go index ba9b45bbd..48f4f3b86 100644 --- a/cmd/boulder-ra/main.go +++ b/cmd/boulder-ra/main.go @@ -35,7 +35,8 @@ func main() { go cmd.DebugServer(c.RA.DebugAddr) - rai := ra.NewRegistrationAuthorityImpl() + rai, err := ra.NewRegistrationAuthorityImpl(c.Common) + cmd.FailOnError(err, "Couldn't create RA") rai.AuthzBase = c.Common.BaseURL + wfe.AuthzPath rai.MaxKeySize = c.Common.MaxKeySize raDNSTimeout, err := time.ParseDuration(c.Common.DNSTimeout) diff --git a/cmd/shell.go b/cmd/shell.go index 370b3f009..74583e9c3 100644 --- a/cmd/shell.go +++ b/cmd/shell.go @@ -36,8 +36,8 @@ import ( "time" "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd" + cfsslConfig "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/config" "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/codegangsta/cli" - "github.com/letsencrypt/boulder/ca" "github.com/letsencrypt/boulder/core" ) @@ -76,7 +76,7 @@ type Config struct { DebugAddr string } - CA ca.Config + CA CAConfig Monolith struct { // DebugAddr is the address to run the /debug handlers on. @@ -162,19 +162,60 @@ type Config struct { DebugAddr string } - Common struct { - BaseURL string - // Path to a PEM-encoded copy of the issuer certificate. - IssuerCert string - MaxKeySize int - - DNSResolver string - DNSTimeout string - } + Common CommonConfig SubscriberAgreementURL string } +type CAConfig struct { + Profile string + TestMode bool + DBDriver string + DBConnect string + SerialPrefix int + Key KeyConfig + // LifespanOCSP is how long OCSP responses are valid for; It should be longer + // than the minTimeToExpiry field for the OCSP Updater. + LifespanOCSP string + // How long issued certificates are valid for, should match expiry field + // in cfssl config. + Expiry string + // The maximum number of subjectAltNames in a single certificate + MaxNames int + CFSSL cfsslConfig.Config + + // DebugAddr is the address to run the /debug handlers on. + DebugAddr string +} + +// KeyConfig should contain either a File path to a PEM-format private key, +// or a PKCS11Config defining how to load a module for an HSM. +type KeyConfig struct { + File string + PKCS11 PKCS11Config +} + +// PKCS11Config defines how to load a module for an HSM. +type PKCS11Config struct { + Module string + Token string + PIN string + Label string +} + +type CommonConfig struct { + BaseURL string + // Path to a PEM-encoded copy of the issuer certificate. + IssuerCert string + MaxKeySize int + + DNSResolver string + DNSTimeout string + + PolicyDBDriver string + PolicyDBConnect string +} + // TLSConfig reprents certificates and a key for authenticated TLS. type TLSConfig struct { CertFile *string diff --git a/policy/policy-authority.go b/policy/policy-authority.go index 4d2848132..17e3b6098 100644 --- a/policy/policy-authority.go +++ b/policy/policy-authority.go @@ -20,21 +20,26 @@ type PolicyAuthorityImpl struct { db core.PolicyAuthorityDatabase PublicSuffixList map[string]bool // A copy of the DNS root zone - Blacklist map[string]bool // A blacklist of denied names } // NewPolicyAuthorityImpl constructs a Policy Authority. -func NewPolicyAuthorityImpl() *PolicyAuthorityImpl { +func NewPolicyAuthorityImpl(dbDriver, dbName string) (*PolicyAuthorityImpl, error) { logger := blog.GetAuditLogger() logger.Notice("Policy Authority Starting") pa := PolicyAuthorityImpl{log: logger} + // Setup policy db + padb, err := NewPolicyAuthorityDatabaseImpl(dbDriver, dbName) + if err != nil { + return nil, err + } + pa.db = padb + // TODO: Add configurability pa.PublicSuffixList = PublicSuffixList - pa.Blacklist = blacklist - return &pa + return &pa, nil } const maxLabels = 10 diff --git a/policy/policy-authority_test.go b/policy/policy-authority_test.go index 085d86b93..d2c1351a8 100644 --- a/policy/policy-authority_test.go +++ b/policy/policy-authority_test.go @@ -90,7 +90,10 @@ func TestWillingToIssue(t *testing.T) { "www.zombo-.com", } - pa := NewPolicyAuthorityImpl() + pa, _ := NewPolicyAuthorityImpl("sqlite3", ":memory:") + for _, b := range shouldBeBlacklisted { + pa.db.AddRule(b, blacklisted) + } // Test for invalid identifier type identifier := core.AcmeIdentifier{Type: "ip", Value: "example.com"} @@ -140,7 +143,7 @@ func TestWillingToIssue(t *testing.T) { } func TestChallengesFor(t *testing.T) { - pa := NewPolicyAuthorityImpl() + pa, _ := NewPolicyAuthorityImpl("sqlite3", ":memory:") challenges, combinations := pa.ChallengesFor(core.AcmeIdentifier{}) diff --git a/ra/registration-authority.go b/ra/registration-authority.go index 45a23f926..434bf9791 100644 --- a/ra/registration-authority.go +++ b/ra/registration-authority.go @@ -15,6 +15,7 @@ import ( "strings" "time" + "github.com/letsencrypt/boulder/cmd" "github.com/letsencrypt/boulder/core" blog "github.com/letsencrypt/boulder/log" "github.com/letsencrypt/boulder/policy" @@ -37,13 +38,18 @@ type RegistrationAuthorityImpl struct { } // NewRegistrationAuthorityImpl constructs a new RA object. -func NewRegistrationAuthorityImpl() RegistrationAuthorityImpl { +func NewRegistrationAuthorityImpl(commonConfig cmd.CommonConfig) (ra RegistrationAuthorityImpl, err error) { logger := blog.GetAuditLogger() logger.Notice("Registration Authority Starting") - ra := RegistrationAuthorityImpl{log: logger} - ra.PA = policy.NewPolicyAuthorityImpl() - return ra + ra.log = logger + pa, err := policy.NewPolicyAuthorityImpl(commonConfig.PolicyDBDriver, commonConfig.PolicyDBConnect) + if err != nil { + return RegistrationAuthorityImpl{}, err + } + ra.PA = pa + + return ra, nil } var allButLastPathSegment = regexp.MustCompile("^.*/") diff --git a/ra/registration-authority_test.go b/ra/registration-authority_test.go index 1874ed792..51aba24ba 100644 --- a/ra/registration-authority_test.go +++ b/ra/registration-authority_test.go @@ -23,6 +23,7 @@ import ( jose "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/letsencrypt/go-jose" _ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/mattn/go-sqlite3" "github.com/letsencrypt/boulder/ca" + "github.com/letsencrypt/boulder/cmd" "github.com/letsencrypt/boulder/core" "github.com/letsencrypt/boulder/mocks" "github.com/letsencrypt/boulder/policy" @@ -123,6 +124,11 @@ var ( AuthzFinal = core.Authorization{} log = mocks.UseMockLog() + + common = cmd.CommonConfig{ + PolicyDBDriver: "sqlite3", + PolicyDBConnect: ":memory:", + } ) func initAuthorities(t *testing.T) (core.CertificateAuthority, *DummyValidationAuthority, *sa.SQLStorageAuthority, core.RegistrationAuthority) { @@ -167,7 +173,7 @@ func initAuthorities(t *testing.T) (core.CertificateAuthority, *DummyValidationA } signer, _ := local.NewSigner(caKey, caCert, x509.SHA256WithRSA, basicPolicy) ocspSigner, _ := ocsp.NewSigner(caCert, caCert, caKey, time.Hour) - pa := policy.NewPolicyAuthorityImpl() + pa, _ := policy.NewPolicyAuthorityImpl("sqlite3", ":memory:") cadb, _ := mocks.NewMockCertificateAuthorityDatabase() ca := ca.CertificateAuthorityImpl{ Signer: signer, @@ -185,7 +191,7 @@ func initAuthorities(t *testing.T) (core.CertificateAuthority, *DummyValidationA // This registration implicitly gets ID = 1 Registration, _ = sa.NewRegistration(core.Registration{Key: AccountKeyA}) - ra := NewRegistrationAuthorityImpl() + ra, err := NewRegistrationAuthorityImpl(common) ra.SA = sa ra.VA = va ra.CA = &ca diff --git a/test/boulder-config.json b/test/boulder-config.json index b1c89de98..f65749927 100644 --- a/test/boulder-config.json +++ b/test/boulder-config.json @@ -109,8 +109,9 @@ } }, - "monolith": { - "debugAddr": "localhost:8008" + "pa": { + "dbDriver": "sqlite3", + "dbConnect": ":memory:" }, "ra": { diff --git a/wfe/web-front-end_test.go b/wfe/web-front-end_test.go index f43a86e58..866b94723 100644 --- a/wfe/web-front-end_test.go +++ b/wfe/web-front-end_test.go @@ -27,6 +27,7 @@ import ( "time" "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd" + "github.com/letsencrypt/boulder/cmd" jose "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/letsencrypt/go-jose" "github.com/letsencrypt/boulder/core" @@ -512,7 +513,11 @@ func TestIssueCertificate(t *testing.T) { mockLog := wfe.log.SyslogWriter.(*mocks.MockSyslogWriter) // TODO: Use a mock RA so we can test various conditions of authorized, not authorized, etc. - ra := ra.NewRegistrationAuthorityImpl() + common := cmd.CommonConfig{ + PolicyDBDriver: "sqlite3", + PolicyDBConnect: ":memory:", + } + ra, _ := ra.NewRegistrationAuthorityImpl(common) ra.SA = &MockSA{} ra.CA = &MockCA{} wfe.SA = &MockSA{}