Fix some inconsistencies around the CA provider code

pull/4275/head
Kyle Havlovitz 7 years ago committed by Mitchell Hashimoto
parent 1b197d934a
commit edcfdb37af
No known key found for this signature in database
GPG Key ID: 744E147AA52F5B0A

@ -1,7 +1,6 @@
package connect
import (
"bytes"
"crypto"
"crypto/ecdsa"
"crypto/rsa"
@ -28,21 +27,21 @@ func ParseCert(pemValue string) (*x509.Certificate, error) {
return x509.ParseCertificate(block.Bytes)
}
// ParseCertFingerprint parses the x509 certificate from a PEM-encoded value
// and returns the SHA-1 fingerprint.
func ParseCertFingerprint(pemValue string) (string, error) {
// CalculateCertFingerprint parses the x509 certificate from a PEM-encoded value
// and calculates the SHA-1 fingerprint.
func CalculateCertFingerprint(pemValue string) (string, error) {
// The _ result below is not an error but the remaining PEM bytes.
block, _ := pem.Decode([]byte(pemValue))
if block == nil {
return "", fmt.Errorf("no PEM-encoded data found")
}
hash := sha1.Sum(block.Bytes)
hexified := make([][]byte, len(hash))
for i, data := range hash {
hexified[i] = []byte(fmt.Sprintf("%02X", data))
if block.Type != "CERTIFICATE" {
return "", fmt.Errorf("first PEM-block should be CERTIFICATE type")
}
return string(bytes.Join(hexified, []byte(":"))), nil
hash := sha1.Sum(block.Bytes)
return HexString(hash[:]), nil
}
// ParseSigner parses a crypto.Signer from a PEM-encoded key. The private key

@ -98,7 +98,7 @@ func (s *ConnectCA) ConfigurationSet(
return err
}
id, err := connect.ParseCertFingerprint(newRootPEM)
id, err := connect.CalculateCertFingerprint(newRootPEM)
if err != nil {
return fmt.Errorf("error parsing root fingerprint: %v", err)
}

@ -222,7 +222,7 @@ func (c *ConsulCAProvider) Sign(csr *x509.CertificateRequest) (string, error) {
// Cert template for generation
sn := &big.Int{}
sn.SetUint64(providerState.LeafIndex + 1)
sn.SetUint64(providerState.SerialIndex + 1)
template := x509.Certificate{
SerialNumber: sn,
Subject: pkix.Name{CommonName: serviceId.Service},
@ -240,6 +240,7 @@ func (c *ConsulCAProvider) Sign(csr *x509.CertificateRequest) (string, error) {
x509.ExtKeyUsageClientAuth,
x509.ExtKeyUsageServerAuth,
},
// todo(kyhavlov): add a way to set the cert lifetime here from the CA config
NotAfter: time.Now().Add(3 * 24 * time.Hour),
NotBefore: time.Now(),
AuthorityKeyId: keyId,
@ -258,20 +259,7 @@ func (c *ConsulCAProvider) Sign(csr *x509.CertificateRequest) (string, error) {
return "", fmt.Errorf("error encoding private key: %s", err)
}
// Increment the leaf cert index
newState := *providerState
newState.LeafIndex += 1
args := &structs.CARequest{
Op: structs.CAOpSetProviderState,
ProviderState: &newState,
}
resp, err := c.srv.raftApply(structs.ConnectCARequestType, args)
if err != nil {
return "", err
}
if respErr, ok := resp.(error); ok {
return "", respErr
}
c.incrementSerialIndex(providerState)
// Set the response
return buf.String(), nil
@ -306,10 +294,9 @@ func (c *ConsulCAProvider) CrossSignCA(cert *x509.Certificate) (string, error) {
// Create the cross-signing template from the existing root CA
serialNum := &big.Int{}
serialNum.SetUint64(providerState.LeafIndex + 1)
serialNum.SetUint64(providerState.SerialIndex + 1)
template := *cert
template.SerialNumber = serialNum
template.Subject = rootCA.Subject
template.SignatureAlgorithm = rootCA.SignatureAlgorithm
template.SubjectKeyId = keyId
template.AuthorityKeyId = keyId
@ -326,9 +313,30 @@ func (c *ConsulCAProvider) CrossSignCA(cert *x509.Certificate) (string, error) {
return "", fmt.Errorf("error encoding private key: %s", err)
}
c.incrementSerialIndex(providerState)
return buf.String(), nil
}
// incrementSerialIndex increments the cert serial number index in the provider state
func (c *ConsulCAProvider) incrementSerialIndex(providerState *structs.CAConsulProviderState) error {
newState := *providerState
newState.SerialIndex += 1
args := &structs.CARequest{
Op: structs.CAOpSetProviderState,
ProviderState: &newState,
}
resp, err := c.srv.raftApply(structs.ConnectCARequestType, args)
if err != nil {
return err
}
if respErr, ok := resp.(error); ok {
return respErr
}
return nil
}
// generatePrivateKey returns a new private key
func generatePrivateKey() (string, error) {
var pk *ecdsa.PrivateKey

@ -426,7 +426,7 @@ func (s *Server) initializeCA() error {
return fmt.Errorf("error getting root cert: %v", err)
}
id, err := connect.ParseCertFingerprint(rootPEM)
id, err := connect.CalculateCertFingerprint(rootPEM)
if err != nil {
return fmt.Errorf("error parsing root fingerprint: %v", err)
}

@ -168,10 +168,10 @@ type ConsulCAProviderConfig struct {
// CAConsulProviderState is used to track the built-in Consul CA provider's state.
type CAConsulProviderState struct {
ID string
PrivateKey string
RootCert string
LeafIndex uint64
ID string
PrivateKey string
RootCert string
SerialIndex uint64
RaftIndex
}

Loading…
Cancel
Save