agent/consul: key the public key of the CSR, verify in test

This commit is contained in:
Mitchell Hashimoto 2018-03-19 21:00:01 -07:00
parent 9a8653f45e
commit 1928c07d0c
No known key found for this signature in database
GPG Key ID: 744E147AA52F5B0A
4 changed files with 42 additions and 6 deletions

View File

@ -190,7 +190,8 @@ func TestLeaf(t testing.T, service string, root *structs.CARoot) string {
// TestCSR returns a CSR to sign the given service.
func TestCSR(t testing.T, id SpiffeID) string {
template := &x509.CertificateRequest{
URIs: []*url.URL{id.URI()},
URIs: []*url.URL{id.URI()},
SignatureAlgorithm: x509.ECDSAWithSHA256,
}
// Create the private key we'll use

View File

@ -71,7 +71,7 @@ func (s *ConnectCA) Roots(
// isn't right, we're not using enough of the CSR fields, etc.
func (s *ConnectCA) Sign(
args *structs.CASignRequest,
reply *structs.IndexedCARoots) error {
reply *structs.IssuedCert) error {
// Parse the CSR
csr, err := connect.ParseCSR(args.CSR)
if err != nil {
@ -132,14 +132,17 @@ func (s *ConnectCA) Sign(
SerialNumber: sn,
Subject: pkix.Name{CommonName: serviceId.Service},
URIs: csr.URIs,
SignatureAlgorithm: x509.ECDSAWithSHA256,
Signature: csr.Signature,
SignatureAlgorithm: csr.SignatureAlgorithm,
PublicKeyAlgorithm: csr.PublicKeyAlgorithm,
PublicKey: csr.PublicKey,
BasicConstraintsValid: true,
KeyUsage: x509.KeyUsageDataEncipherment | x509.KeyUsageKeyAgreement,
ExtKeyUsage: []x509.ExtKeyUsage{
x509.ExtKeyUsageClientAuth,
x509.ExtKeyUsageServerAuth,
},
NotAfter: time.Now().Add(10 * 365 * 24 * time.Hour),
NotAfter: time.Now().Add(3 * 24 * time.Hour),
NotBefore: time.Now(),
AuthorityKeyId: keyId,
SubjectKeyId: keyId,
@ -157,5 +160,11 @@ func (s *ConnectCA) Sign(
return fmt.Errorf("error encoding private key: %s", err)
}
// Set the response
*reply = structs.IssuedCert{
SerialNumber: template.SerialNumber,
Cert: buf.String(),
}
return nil
}

View File

@ -1,6 +1,7 @@
package consul
import (
"crypto/x509"
"os"
"testing"
@ -30,13 +31,24 @@ func TestConnectCASign(t *testing.T) {
// Insert a CA
state := s1.fsm.State()
assert.Nil(state.CARootSet(1, connect.TestCA(t, nil)))
ca := connect.TestCA(t, nil)
assert.Nil(state.CARootSet(1, ca))
// Generate a CSR and request signing
args := &structs.CASignRequest{
Datacenter: "dc01",
CSR: connect.TestCSR(t, connect.TestSpiffeIDService(t, "web")),
}
var reply interface{}
var reply structs.IssuedCert
assert.Nil(msgpackrpc.CallWithCodec(codec, "ConnectCA.Sign", args, &reply))
// Verify that the cert is signed by the CA
roots := x509.NewCertPool()
assert.True(roots.AppendCertsFromPEM([]byte(ca.RootCert)))
leaf, err := connect.ParseCert(reply.Cert)
assert.Nil(err)
_, err = leaf.Verify(x509.VerifyOptions{
Roots: roots,
})
assert.Nil(err)
}

View File

@ -1,5 +1,9 @@
package structs
import (
"math/big"
)
// IndexedCARoots is the list of currently trusted CA Roots.
type IndexedCARoots struct {
// ActiveRootID is the ID of a root in Roots that is the active CA root.
@ -62,3 +66,13 @@ type CASignRequest struct {
func (q *CASignRequest) RequestDatacenter() string {
return q.Datacenter
}
// IssuedCert is a certificate that has been issued by a Connect CA.
type IssuedCert struct {
// SerialNumber is the unique serial number for this certificate.
SerialNumber *big.Int
// Cert is the PEM-encoded certificate. This should not be stored in the
// state store, but is present in the sign API response.
Cert string `json:",omitempty"`
}