agent/consul: key the public key of the CSR, verify in test
This commit is contained in:
parent
9a8653f45e
commit
1928c07d0c
|
@ -190,7 +190,8 @@ func TestLeaf(t testing.T, service string, root *structs.CARoot) string {
|
||||||
// TestCSR returns a CSR to sign the given service.
|
// TestCSR returns a CSR to sign the given service.
|
||||||
func TestCSR(t testing.T, id SpiffeID) string {
|
func TestCSR(t testing.T, id SpiffeID) string {
|
||||||
template := &x509.CertificateRequest{
|
template := &x509.CertificateRequest{
|
||||||
URIs: []*url.URL{id.URI()},
|
URIs: []*url.URL{id.URI()},
|
||||||
|
SignatureAlgorithm: x509.ECDSAWithSHA256,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the private key we'll use
|
// Create the private key we'll use
|
||||||
|
|
|
@ -71,7 +71,7 @@ func (s *ConnectCA) Roots(
|
||||||
// isn't right, we're not using enough of the CSR fields, etc.
|
// isn't right, we're not using enough of the CSR fields, etc.
|
||||||
func (s *ConnectCA) Sign(
|
func (s *ConnectCA) Sign(
|
||||||
args *structs.CASignRequest,
|
args *structs.CASignRequest,
|
||||||
reply *structs.IndexedCARoots) error {
|
reply *structs.IssuedCert) error {
|
||||||
// Parse the CSR
|
// Parse the CSR
|
||||||
csr, err := connect.ParseCSR(args.CSR)
|
csr, err := connect.ParseCSR(args.CSR)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -132,14 +132,17 @@ func (s *ConnectCA) Sign(
|
||||||
SerialNumber: sn,
|
SerialNumber: sn,
|
||||||
Subject: pkix.Name{CommonName: serviceId.Service},
|
Subject: pkix.Name{CommonName: serviceId.Service},
|
||||||
URIs: csr.URIs,
|
URIs: csr.URIs,
|
||||||
SignatureAlgorithm: x509.ECDSAWithSHA256,
|
Signature: csr.Signature,
|
||||||
|
SignatureAlgorithm: csr.SignatureAlgorithm,
|
||||||
|
PublicKeyAlgorithm: csr.PublicKeyAlgorithm,
|
||||||
|
PublicKey: csr.PublicKey,
|
||||||
BasicConstraintsValid: true,
|
BasicConstraintsValid: true,
|
||||||
KeyUsage: x509.KeyUsageDataEncipherment | x509.KeyUsageKeyAgreement,
|
KeyUsage: x509.KeyUsageDataEncipherment | x509.KeyUsageKeyAgreement,
|
||||||
ExtKeyUsage: []x509.ExtKeyUsage{
|
ExtKeyUsage: []x509.ExtKeyUsage{
|
||||||
x509.ExtKeyUsageClientAuth,
|
x509.ExtKeyUsageClientAuth,
|
||||||
x509.ExtKeyUsageServerAuth,
|
x509.ExtKeyUsageServerAuth,
|
||||||
},
|
},
|
||||||
NotAfter: time.Now().Add(10 * 365 * 24 * time.Hour),
|
NotAfter: time.Now().Add(3 * 24 * time.Hour),
|
||||||
NotBefore: time.Now(),
|
NotBefore: time.Now(),
|
||||||
AuthorityKeyId: keyId,
|
AuthorityKeyId: keyId,
|
||||||
SubjectKeyId: keyId,
|
SubjectKeyId: keyId,
|
||||||
|
@ -157,5 +160,11 @@ func (s *ConnectCA) Sign(
|
||||||
return fmt.Errorf("error encoding private key: %s", err)
|
return fmt.Errorf("error encoding private key: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the response
|
||||||
|
*reply = structs.IssuedCert{
|
||||||
|
SerialNumber: template.SerialNumber,
|
||||||
|
Cert: buf.String(),
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package consul
|
package consul
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/x509"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -30,13 +31,24 @@ func TestConnectCASign(t *testing.T) {
|
||||||
|
|
||||||
// Insert a CA
|
// Insert a CA
|
||||||
state := s1.fsm.State()
|
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
|
// Generate a CSR and request signing
|
||||||
args := &structs.CASignRequest{
|
args := &structs.CASignRequest{
|
||||||
Datacenter: "dc01",
|
Datacenter: "dc01",
|
||||||
CSR: connect.TestCSR(t, connect.TestSpiffeIDService(t, "web")),
|
CSR: connect.TestCSR(t, connect.TestSpiffeIDService(t, "web")),
|
||||||
}
|
}
|
||||||
var reply interface{}
|
var reply structs.IssuedCert
|
||||||
assert.Nil(msgpackrpc.CallWithCodec(codec, "ConnectCA.Sign", args, &reply))
|
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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
package structs
|
package structs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
// IndexedCARoots is the list of currently trusted CA Roots.
|
// IndexedCARoots is the list of currently trusted CA Roots.
|
||||||
type IndexedCARoots struct {
|
type IndexedCARoots struct {
|
||||||
// ActiveRootID is the ID of a root in Roots that is the active CA root.
|
// 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 {
|
func (q *CASignRequest) RequestDatacenter() string {
|
||||||
return q.Datacenter
|
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"`
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue