|
|
|
@ -45,7 +45,7 @@ type ConsulProvider struct {
|
|
|
|
|
|
|
|
|
|
type ConsulProviderStateDelegate interface { |
|
|
|
|
State() *state.Store |
|
|
|
|
ApplyCARequest(*structs.CARequest) error |
|
|
|
|
ApplyCARequest(*structs.CARequest) (interface{}, error) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Configure sets up the provider using the given configuration.
|
|
|
|
@ -91,7 +91,7 @@ func (c *ConsulProvider) Configure(cfg ProviderConfig) error {
|
|
|
|
|
Op: structs.CAOpSetProviderState, |
|
|
|
|
ProviderState: &newState, |
|
|
|
|
} |
|
|
|
|
if err := c.Delegate.ApplyCARequest(createReq); err != nil { |
|
|
|
|
if _, err := c.Delegate.ApplyCARequest(createReq); err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -99,7 +99,7 @@ func (c *ConsulProvider) Configure(cfg ProviderConfig) error {
|
|
|
|
|
Op: structs.CAOpDeleteProviderState, |
|
|
|
|
ProviderState: providerState, |
|
|
|
|
} |
|
|
|
|
if err := c.Delegate.ApplyCARequest(deleteReq); err != nil { |
|
|
|
|
if _, err := c.Delegate.ApplyCARequest(deleteReq); err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -115,7 +115,7 @@ func (c *ConsulProvider) Configure(cfg ProviderConfig) error {
|
|
|
|
|
Op: structs.CAOpSetProviderState, |
|
|
|
|
ProviderState: &newState, |
|
|
|
|
} |
|
|
|
|
if err := c.Delegate.ApplyCARequest(args); err != nil { |
|
|
|
|
if _, err := c.Delegate.ApplyCARequest(args); err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -147,7 +147,7 @@ func (c *ConsulProvider) ActiveRoot() (string, error) {
|
|
|
|
|
// GenerateRoot initializes a new root certificate and private key
|
|
|
|
|
// if needed.
|
|
|
|
|
func (c *ConsulProvider) GenerateRoot() error { |
|
|
|
|
idx, providerState, err := c.getState() |
|
|
|
|
_, providerState, err := c.getState() |
|
|
|
|
if err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
@ -173,7 +173,12 @@ func (c *ConsulProvider) GenerateRoot() error {
|
|
|
|
|
|
|
|
|
|
// Generate the root CA if necessary
|
|
|
|
|
if c.config.RootCert == "" { |
|
|
|
|
ca, err := c.generateCA(newState.PrivateKey, idx+1) |
|
|
|
|
nextSerial, err := c.incrementAndGetNextSerialNumber() |
|
|
|
|
if err != nil { |
|
|
|
|
return fmt.Errorf("error computing next serial number: %v", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ca, err := c.generateCA(newState.PrivateKey, nextSerial) |
|
|
|
|
if err != nil { |
|
|
|
|
return fmt.Errorf("error generating CA: %v", err) |
|
|
|
|
} |
|
|
|
@ -187,7 +192,7 @@ func (c *ConsulProvider) GenerateRoot() error {
|
|
|
|
|
Op: structs.CAOpSetProviderState, |
|
|
|
|
ProviderState: &newState, |
|
|
|
|
} |
|
|
|
|
if err := c.Delegate.ApplyCARequest(args); err != nil { |
|
|
|
|
if _, err := c.Delegate.ApplyCARequest(args); err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -231,7 +236,7 @@ func (c *ConsulProvider) GenerateIntermediateCSR() (string, error) {
|
|
|
|
|
Op: structs.CAOpSetProviderState, |
|
|
|
|
ProviderState: &newState, |
|
|
|
|
} |
|
|
|
|
if err := c.Delegate.ApplyCARequest(args); err != nil { |
|
|
|
|
if _, err := c.Delegate.ApplyCARequest(args); err != nil { |
|
|
|
|
return "", err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -267,7 +272,7 @@ func (c *ConsulProvider) SetIntermediate(intermediatePEM, rootPEM string) error
|
|
|
|
|
Op: structs.CAOpSetProviderState, |
|
|
|
|
ProviderState: &newState, |
|
|
|
|
} |
|
|
|
|
if err := c.Delegate.ApplyCARequest(args); err != nil { |
|
|
|
|
if _, err := c.Delegate.ApplyCARequest(args); err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -301,7 +306,7 @@ func (c *ConsulProvider) Cleanup() error {
|
|
|
|
|
Op: structs.CAOpDeleteProviderState, |
|
|
|
|
ProviderState: &structs.CAConsulProviderState{ID: c.id}, |
|
|
|
|
} |
|
|
|
|
if err := c.Delegate.ApplyCARequest(args); err != nil { |
|
|
|
|
if _, err := c.Delegate.ApplyCARequest(args); err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -317,7 +322,7 @@ func (c *ConsulProvider) Sign(csr *x509.CertificateRequest) (string, error) {
|
|
|
|
|
defer c.Unlock() |
|
|
|
|
|
|
|
|
|
// Get the provider state
|
|
|
|
|
idx, providerState, err := c.getState() |
|
|
|
|
_, providerState, err := c.getState() |
|
|
|
|
if err != nil { |
|
|
|
|
return "", err |
|
|
|
|
} |
|
|
|
@ -362,9 +367,14 @@ func (c *ConsulProvider) Sign(csr *x509.CertificateRequest) (string, error) {
|
|
|
|
|
return "", fmt.Errorf("error parsing CA cert: %s", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
nextSerial, err := c.incrementAndGetNextSerialNumber() |
|
|
|
|
if err != nil { |
|
|
|
|
return "", fmt.Errorf("error computing next serial number: %v", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Cert template for generation
|
|
|
|
|
sn := &big.Int{} |
|
|
|
|
sn.SetUint64(idx + 1) |
|
|
|
|
sn.SetUint64(nextSerial) |
|
|
|
|
// Sign the certificate valid from 1 minute in the past, this helps it be
|
|
|
|
|
// accepted right away even when nodes are not in close time sync across the
|
|
|
|
|
// cluster. A minute is more than enough for typical DC clock drift.
|
|
|
|
@ -407,11 +417,6 @@ func (c *ConsulProvider) Sign(csr *x509.CertificateRequest) (string, error) {
|
|
|
|
|
return "", fmt.Errorf("error encoding certificate: %s", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
err = c.incrementProviderIndex(providerState) |
|
|
|
|
if err != nil { |
|
|
|
|
return "", err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Set the response
|
|
|
|
|
return buf.String(), nil |
|
|
|
|
} |
|
|
|
@ -421,7 +426,7 @@ func (c *ConsulProvider) Sign(csr *x509.CertificateRequest) (string, error) {
|
|
|
|
|
// are met. It should return a signed CA certificate with a path length constraint
|
|
|
|
|
// of 0 to ensure that the certificate cannot be used to generate further CA certs.
|
|
|
|
|
func (c *ConsulProvider) SignIntermediate(csr *x509.CertificateRequest) (string, error) { |
|
|
|
|
idx, providerState, err := c.getState() |
|
|
|
|
_, providerState, err := c.getState() |
|
|
|
|
if err != nil { |
|
|
|
|
return "", err |
|
|
|
|
} |
|
|
|
@ -447,9 +452,14 @@ func (c *ConsulProvider) SignIntermediate(csr *x509.CertificateRequest) (string,
|
|
|
|
|
return "", fmt.Errorf("error parsing CA cert: %s", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
nextSerial, err := c.incrementAndGetNextSerialNumber() |
|
|
|
|
if err != nil { |
|
|
|
|
return "", fmt.Errorf("error computing next serial number: %v", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Cert template for generation
|
|
|
|
|
sn := &big.Int{} |
|
|
|
|
sn.SetUint64(idx + 1) |
|
|
|
|
sn.SetUint64(nextSerial) |
|
|
|
|
// Sign the certificate valid from 1 minute in the past, this helps it be
|
|
|
|
|
// accepted right away even when nodes are not in close time sync across the
|
|
|
|
|
// cluster. A minute is more than enough for typical DC clock drift.
|
|
|
|
@ -485,11 +495,6 @@ func (c *ConsulProvider) SignIntermediate(csr *x509.CertificateRequest) (string,
|
|
|
|
|
return "", fmt.Errorf("error encoding certificate: %s", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
err = c.incrementProviderIndex(providerState) |
|
|
|
|
if err != nil { |
|
|
|
|
return "", err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Set the response
|
|
|
|
|
return buf.String(), nil |
|
|
|
|
} |
|
|
|
@ -504,7 +509,7 @@ func (c *ConsulProvider) CrossSignCA(cert *x509.Certificate) (string, error) {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Get the provider state
|
|
|
|
|
idx, providerState, err := c.getState() |
|
|
|
|
_, providerState, err := c.getState() |
|
|
|
|
if err != nil { |
|
|
|
|
return "", err |
|
|
|
|
} |
|
|
|
@ -524,9 +529,14 @@ func (c *ConsulProvider) CrossSignCA(cert *x509.Certificate) (string, error) {
|
|
|
|
|
return "", err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
nextSerial, err := c.incrementAndGetNextSerialNumber() |
|
|
|
|
if err != nil { |
|
|
|
|
return "", fmt.Errorf("error computing next serial number: %v", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Create the cross-signing template from the existing root CA
|
|
|
|
|
serialNum := &big.Int{} |
|
|
|
|
serialNum.SetUint64(idx + 1) |
|
|
|
|
serialNum.SetUint64(nextSerial) |
|
|
|
|
template := *cert |
|
|
|
|
template.SerialNumber = serialNum |
|
|
|
|
template.SignatureAlgorithm = rootCA.SignatureAlgorithm |
|
|
|
@ -555,11 +565,6 @@ func (c *ConsulProvider) CrossSignCA(cert *x509.Certificate) (string, error) {
|
|
|
|
|
return "", fmt.Errorf("error encoding private key: %s", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
err = c.incrementProviderIndex(providerState) |
|
|
|
|
if err != nil { |
|
|
|
|
return "", err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return buf.String(), nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -584,19 +589,17 @@ func (c *ConsulProvider) getState() (uint64, *structs.CAConsulProviderState, err
|
|
|
|
|
return idx, providerState, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// incrementProviderIndex does a write to increment the provider state store table index
|
|
|
|
|
// used for serial numbers when generating certificates.
|
|
|
|
|
func (c *ConsulProvider) incrementProviderIndex(providerState *structs.CAConsulProviderState) error { |
|
|
|
|
newState := *providerState |
|
|
|
|
func (c *ConsulProvider) incrementAndGetNextSerialNumber() (uint64, error) { |
|
|
|
|
args := &structs.CARequest{ |
|
|
|
|
Op: structs.CAOpSetProviderState, |
|
|
|
|
ProviderState: &newState, |
|
|
|
|
Op: structs.CAOpIncrementProviderSerialNumber, |
|
|
|
|
} |
|
|
|
|
if err := c.Delegate.ApplyCARequest(args); err != nil { |
|
|
|
|
return err |
|
|
|
|
|
|
|
|
|
raw, err := c.Delegate.ApplyCARequest(args) |
|
|
|
|
if err != nil { |
|
|
|
|
return 0, err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return nil |
|
|
|
|
return raw.(uint64), nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// generateCA makes a new root CA using the current private key
|
|
|
|
|