Use remote signer in CA testing

This commit is contained in:
Richard Barnes 2015-03-17 11:29:01 -04:00
parent b5d67c733a
commit 34da176328
1 changed files with 186 additions and 47 deletions

View File

@ -7,10 +7,16 @@ package ca
import (
"crypto/x509"
"encoding/asn1"
"encoding/hex"
"encoding/pem"
"net/http"
"testing"
"time"
apisign "github.com/cloudflare/cfssl/api/sign"
"github.com/cloudflare/cfssl/auth"
"github.com/cloudflare/cfssl/config"
"github.com/cloudflare/cfssl/signer/local"
_ "github.com/mattn/go-sqlite3"
@ -108,24 +114,109 @@ var CA_CERT_PEM = "-----BEGIN CERTIFICATE-----\n" +
// * Random public key
// * CN = example.com
// * DNSNames = example.com, www.example.com
var CSR_HEX = "308202953082017d0201003016311430120603" +
"550403130b6578616d706c652e636f6d30820122300d06092a864886f70d0101010500038201" +
"0f003082010a0282010100baaf16e891828470cad87b849a73356f65e20ad3699fd5583a7200" +
"e924512d9eeb1dbe16441ad7bd804fa2e5726a06f0af5279012fe6354a5677259f5591984aa9" +
"99b8ea3ea10fbd5ecfa30e5f563b41c419374decfc98ea62c611046ad011c326470a2426f46d" +
"be6cc44fae3b247e19710810585f9f3ad7f64b2f305aebb72e2829866f89b20b03a300b7ff5f" +
"4e6204f41420d9fa731252692cee8e616636723abe8a7053fd86e2673190fa8b618ada5bc735" +
"ba57a145af86904a8f55a288d4d6ba9e501530f23f197f5b623443193fc92b7f87d6abbf740d" +
"9fc92800c7e0e1484d5eec6ffae1007c139c1ec19d67e749743fe8d8396fe190cfbcf2f90e05" +
"230203010001a03a303806092a864886f70d01090e312b302930270603551d110420301e820b" +
"6578616d706c652e636f6d820f7777772e6578616d706c652e636f6d300d06092a864886f70d" +
"01010b05000382010100514c622dc866b31c86777a26e9b2911618ce5b188591f08007b42772" +
"3497b733676a7d493c434fc819b8089869442fd299aa99ff7f7b9df881843727f0c8b89ca62a" +
"f8a12b38c963e9210148c4e1c0fc964aef2605f88ed777e6497d2e43e9a9713835d1ae96260c" +
"ca826c34c7ae52c77f5d8468643ee1936eadf04e1ebf8bbbb68b0ec7d0ef694432451292e4a3" +
"1989fd8339c07e01e04b6dd3834872b828d3f5b2b4dadda0596396e15fbdf446998066a74873" +
"2baf53f3f7ebb849e83cf734753c35ab454d1b62e1741a6514c5c575c0c805b4d668fcf71746" +
"ef32017613a52d6b807e2977f4fbc0a88b2e263347c4d9e35435333cf4f8288be53df41228ec"
var CN_AND_SAN_CSR_HEX = "308202a130820189020100301a311830160603550403130f6e6f742d6578" +
"616d706c652e636f6d30820122300d06092a864886f70d01010105000382" +
"010f003082010a0282010100e56ccbe37003c150202e6f543f9eb1d0e590" +
"76ac7f1f62654fa82fe131a23c66bd53a2f62ff7852015c84a394e36836d" +
"2018eba278e0740c85c4c6102787400c2ef069b4a72e6eb8ad8d1da5d76b" +
"f3e70dafc126578ed28cf40030e7fe5b5307ef630254726c639561b5445d" +
"372847bdb02576aa3622a688158c6af09d3938dbeba4d670cec4325be73a" +
"fa52a0a04dcba2f335f1e85020704db94ca125dce70b3209294c6c46ed4b" +
"48b95d8d51ae2d2fd227116023a48ca7381e35fd302ad2999df625a4b5ee" +
"82a0d0fefa88ac6a62b01674de75637ef83328202cda9930947d932000b0" +
"e53b82e099ab60fec9c8b6d4eccdee508b6ebca7e6ca3f752046c8350203" +
"010001a042304006092a864886f70d01090e31333031302f0603551d1104" +
"283026820f6e6f742d6578616d706c652e636f6d82137777772e6e6f742d" +
"6578616d706c652e636f6d300d06092a864886f70d01010b050003820101" +
"008c4bf2ab4dfd28d768697eecc5be889a6275287c7dd24f9232ffad5675" +
"de708c9cc911545d0e84f61b6584c5e237915bbf231d6518e7e228be2e65" +
"b4d50bd9729ce9e6aee00482e014de4edd4b9a4f9a7777b8943ef3512dbf" +
"940ac561c25b34ded9db1074136b978a65943ab1259608fb8109e008eac6" +
"23d7b29b2f1fad3a8e358aa070ead688016d9efed6da43412b136903de07" +
"137462d3f9203a344d84d7eb336999004e7e9972d5176001e2792f206e6c" +
"7c70b86d312459f21751d29ea53b41f9d02a229f9d7615b2a7ac83e849d0" +
"d0d9f8a08f8d7ba23295e77c95bc060c9227bfec0afb8c898e33c89903d7" +
"bbde4cf059dcc3e6c4ae4eef207c499d62"
// CSR generated by Go:
// * Random public key
// * CN = not-example.com
// * DNSNames = [none]
var NO_SAN_CSR_HEX = "3082025f30820147020100301a311830160603550403130f6e6f742d6578" +
"616d706c652e636f6d30820122300d06092a864886f70d01010105000382" +
"010f003082010a0282010100aa6e56ff24906f93b855e7871dc8411a3cf7" +
"678d9563627e8ca37ab17dfe814ef7f828d6aa92b717f0da9df56990b953" +
"989d5afc3f2dddacd2b504b89782b49e55a04a64a4370d8ab1b2688f2596" +
"98132e5ce536f812ef5eb13824a922bbb89e30d6f2cace77462b9e65264a" +
"32320a7b348f9903b16640bc8c1c5f1208c6b456fd85bfa96ee9b7642c68" +
"3ab05b142d249525a730b230b39f2ba8d6f253263b5c3948b1a3d8a3467f" +
"7cfcdd1fdd6bff7828fda12784fd277be8c680fcdf2cc4676acff5df759f" +
"f4bc712ee1a560157233cbf6bb4bcb91dd1c5d2824b42f4913e4715c1ba4" +
"001fde0d90c274bfa81a79e4a0d00a7ddcbfdd8de4183b497487a20d0203" +
"010001a000300d06092a864886f70d01010b050003820101000ead204cfd" +
"45d307dd49de6937d7e2d8abf17490a49a8cee5250ef7799ef53229f8cfc" +
"735b9f65d789f898945f3d5536a09932e241050bd5473c47a4ac2493707f" +
"1142bf9a06d047384ad463463acb3744d435b4cff8c8b0f9673e8700e13b" +
"6bc99a486823fa85f7707e1bb8430e62541715ab6cb3fae3efb8356042a5" +
"c9f493dd08eff690570cce65cffc4fe354aa40957dc16a37a833aa968f62" +
"693d5059d53f6a96a159195d3fb7b558d462de63d945d4e3680d2b1f2c98" +
"33c3bfd92a9235de3d345a431ee5a675e0e18308bd2729413acd84432da4" +
"2410e1b87ae70227dd9a98e49ee6aeea9eaff67f968691918201e94697f2" +
"da010d6f939cea40c26038"
// CSR generated by Go:
// * Random public key
// * C = US
// * CN = [none]
// * DNSNames = not-example.com
var NO_CN_CSR_HEX = "3082027f30820167020100300d310b300906035504061302555330820122" +
"300d06092a864886f70d01010105000382010f003082010a0282010100d8" +
"b3c11610ce17614f6d78de3f079db430e479c38978da8cd625b7c70dd445" +
"57fd99b9831693e6b9b09fb7c74a82058a1f1a4e1e087f04f93aa73bc35a" +
"688440205a6f5fd56ff478c5554b14c3b2a1a0b5eed1aef7189ad848e117" +
"04b1eb6c29b47ada40a5719a38ce2f2869896bf5405c2bafd4c7dfb99c0e" +
"9f26f80145e16b73bbacf67aedcd3b7ce57bb5b67cf692aec7956d23c236" +
"2336c2408b65469630dccca3ca006f28e36ca8c95dda84b6586f29c8de63" +
"661c09b58253e386a74707394cbba4de165f2745a65b717b9fd4b8b84c09" +
"85583b5c17d3e88bbf71c88eeeccb5d552d61cde7835ec83d6ec9b41114a" +
"0583f8eeae8a536cb3ca5786c22ab30203010001a02d302b06092a864886" +
"f70d01090e311e301c301a0603551d1104133011820f6e6f742d6578616d" +
"706c652e636f6d300d06092a864886f70d01010b05000382010100430239" +
"8db6b64b94d93399db32335232967ca6a748048483db8cb2b387871f758c" +
"6f7bf1593624b142127847cd2a511897bbadd8ad038468fb309fa2161031" +
"949b9ba24931b0d363ad2f8dae56a4c908ba748d41c664aa129dcb1a6f88" +
"0b90502cd244d9abd8dd5e78f763730660655a350f1c25af95cf1f89dda9" +
"076f4e6b84b6da9a98ed87f538624e4338fa0ff1a404e763dd6800694a21" +
"d28595927606308aefa1ac7e8f5600b05e33c0a7b25d3a9f5032c7c25264" +
"026c039733b179315254af4f25e90a1d00facd69313b36fdc66a5818fb49" +
"a0d90e0745d66a82d337289c9968b3ec4a4826c530c758cacecc18e06366" +
"dd8962c451c3ce22c2aed33726"
// CSR generated by Go:
// * Random public key
// * C = US
// * CN = [none]
// * DNSNames = [none]
var NO_NAME_CSR_HEX = "308202523082013a020100300d310b300906035504061302555330820122" +
"300d06092a864886f70d01010105000382010f003082010a0282010100bc" +
"fae49f68f02c42500b2faf251628ee19e8ef048a35fef311c9c419c80606" +
"ab37340ad6e25cf4cc63c0283994b4ba705d86950ad5298094e0b9684647" +
"8d67abc695741317b4ff8da9fd33120342559cfdaf9109ac403f0d0bf9ff" +
"54dd79fa2256b218a9bdb17c608167c7fcad4cf839733c7eab9589fe6137" +
"e99bb24c24b7eb74e19f51ffee4ea62c4ab756f099ff5197c5032f60edff" +
"36022b8a99d35aeb706854fa9a31ea8a362a2251f08b93023b32e1df771a" +
"970f08a30ced656950b8ef71600d65d6995a0b92903b179c05a76f702a08" +
"0b41402c308d8ab57f14b5516b89fe317e38e13d7adad7f7025743610881" +
"9fb60268f0773b08b62ac8c8c84f2d0203010001a000300d06092a864886" +
"f70d01010b050003820101001eda9ce8253e8b933348851acd38ab63cd64" +
"f833d7ffc711f1b6e6a37a7deb7ad44b5589d90533ed61dfd48cab2775e2" +
"a19c41f5cb69faa9dde856606822a3bf798381836214154c17bc037f23ad" +
"67c84d876855c0aea871dc55bd14b2cd267e49b734bc7a38c29c334611bf" +
"ec7efdc56a1512e25fd12ca99a5809b1b6a808caf6a8baefff7fb2bda454" +
"5c226849674900ce7a1f90287ab31be80a4e2b6d64765b9d973628e60299" +
"6423edd74e7a58005bd520d4173f0c30d935de530477480d7725d9758f9a" +
"58c004d9e1e55af59ea517dfbd2bccca58216d8130b9f77c90328b2aa54b" +
"1778a629b584f2bc059489a236131de9b444adca90218c31a499a485"
func TestIssueCertificate(t *testing.T) {
// Decode pre-generated values
@ -135,44 +226,92 @@ func TestIssueCertificate(t *testing.T) {
caCertPEM, _ := pem.Decode([]byte(CA_CERT_PEM))
caCert, _ := x509.ParseCertificate(caCertPEM.Bytes)
csrDER, _ := hex.DecodeString(CSR_HEX)
csr, _ := x509.ParseCertificateRequest(csrDER)
// Uncomment to create a CFSSL local signer
// Create a CFSSL local signer
signer, _ := local.NewSigner(caKey, caCert, x509.SHA256WithRSA, nil)
// CFSSL config
hostPort := "localhost:9000"
authKey := "79999d86250c367a2b517a1ae7d409c1"
profileName := "ee"
// Create an SA
sa, err := sa.NewSQLStorageAuthority("sqlite3", ":memory:")
test.AssertNotError(t, err, "Failed to create SA")
sa.InitTables()
// Create an online CFSSL instance
// This is designed to mimic what LE plans to do
authHandler, err := auth.New(authKey, nil)
test.AssertNotError(t, err, "Failed to create authentication handler")
policy := &config.Signing{
Profiles: map[string]*config.SigningProfile{
profileName: &config.SigningProfile{
Usage: []string{"server auth"},
CA: false,
IssuerURL: []string{"http://not-example.com/issuer-url"},
OCSP: "http://not-example.com/ocsp",
CRL: "http://not-example.com/crl",
Policies: []asn1.ObjectIdentifier{
asn1.ObjectIdentifier{2, 23, 140, 1, 2, 1},
},
Expiry: 8760 * time.Hour,
Backdate: time.Hour,
Provider: authHandler,
},
},
Default: &config.SigningProfile{
Expiry: time.Hour,
},
}
signer, err := local.NewSigner(caKey, caCert, x509.SHA256WithRSA, policy)
test.AssertNotError(t, err, "Failed to create signer")
signHandler, err := apisign.NewAuthHandlerFromSigner(signer)
test.AssertNotError(t, err, "Failed to create signing API endpoint")
http.Handle("/api/v1/cfssl/authsign", signHandler)
// This goroutine should get killed when main() return
go (func() { http.ListenAndServe(hostPort, nil) })()
// Create a CA
// Uncomment to test with a remote signer
ca, err := NewCertificateAuthorityImpl(hostPort, authKey, profileName)
test.AssertNotError(t, err, "Failed to create CA")
ca.SA = sa
/*
// Uncomment to test with a remote signer
ca, err := NewCertificateAuthorityImpl("localhost:9000", "79999d86250c367a2b517a1ae7d409c1", "ee")
test.AssertNotError(t, err, "Failed to create CA")
ca.SA = sa
// Uncomment to test with a local signer
signer, _ := local.NewSigner(caKey, caCert, x509.SHA256WithRSA, nil)
ca := CertificateAuthorityImpl{
Signer: signer,
SA: sa,
}
*/
ca := CertificateAuthorityImpl{
Signer: signer,
SA: sa,
csrs := []string{CN_AND_SAN_CSR_HEX, NO_SAN_CSR_HEX, NO_CN_CSR_HEX}
for _, csrHEX := range csrs {
csrDER, _ := hex.DecodeString(csrHEX)
csr, _ := x509.ParseCertificateRequest(csrDER)
// Sign CSR
certObj, err := ca.IssueCertificate(*csr)
test.AssertNotError(t, err, "Failed to sign certificate")
// Verify cert contents
cert, err := x509.ParseCertificate(certObj.DER)
test.AssertNotError(t, err, "Certificate failed to parse")
test.AssertEquals(t, cert.Subject.CommonName, "not-example.com")
if len(cert.DNSNames) == 0 || cert.DNSNames[0] != "not-example.com" {
// NB: This does not check for www.not-example.com in the 'both' case
t.Errorf("Improper list of domain names %v", cert.DNSNames)
}
if len(cert.Subject.Country) > 0 {
t.Errorf("Subject contained unauthorized values")
}
// Verify that the cert got stored in the DB
_, err = sa.GetCertificate(certObj.ID)
test.AssertNotError(t, err, "Certificate not found in database")
}
// Sign CSR
certObj, err := ca.IssueCertificate(*csr)
test.AssertNotError(t, err, "Failed to sign certificate")
// Verify cert contents
cert, err := x509.ParseCertificate(certObj.DER)
test.AssertNotError(t, err, "Certificate failed to parse")
test.AssertEquals(t, cert.Subject.CommonName, "example.com")
if len(cert.DNSNames) != 2 || cert.DNSNames[0] != "example.com" || cert.DNSNames[1] != "www.example.com" {
t.Errorf("Improper list of domain names %v", cert.DNSNames)
}
// Verify that the cert got stored in the DB
_, err = sa.GetCertificate(certObj.ID)
test.AssertNotError(t, err, "Certificate not found in database")
}