mirror of https://github.com/hashicorp/consul
Fix some inconsistencies around the CA provider code
parent
1b197d934a
commit
edcfdb37af
|
@ -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…
Reference in New Issue