-
Notifications
You must be signed in to change notification settings - Fork 4.5k
connect: Enable renewing the intermediate cert in the primary DC #8784
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
2ec94b0
e13f4af
4fc0f6d
01ce9f5
cc901df
876500e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
```release-note:bug | ||
connect: Fixed an issue where the Vault intermediate was not renewed in the primary datacenter. | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,13 @@ import ( | |
// on servers and CA provider. | ||
var ErrRateLimited = errors.New("operation rate limited by CA provider") | ||
|
||
// PrimaryIntermediateProviders is a list of CA providers that make use use of an | ||
// intermediate cert in the primary datacenter as well as the secondary. This is used | ||
// when determining whether to run the intermediate renewal routine in the primary. | ||
var PrimaryIntermediateProviders = map[string]struct{}{ | ||
"vault": {}, | ||
} | ||
Comment on lines
+22
to
+24
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I really like implementing this kind of thing as a method on the type. Then calling code can use an interface to check if the type has the method: if _, ok := provider.(interface{
IntermediateCertInPrimaryDC()
}); ok {
...
} But I think we could easily change that later, so I don't want to hold up this bug fix. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good idea, I overlooked that pattern when thinking about this 👍 |
||
|
||
// ProviderConfig encapsulates all the data Consul passes to `Configure` on a | ||
// new provider instance. The provider must treat this as read-only and make | ||
// copies of any map or slice if it might modify them internally. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,7 @@ import ( | |
"io/ioutil" | ||
"net/http" | ||
"strings" | ||
"time" | ||
|
||
"github.com/hashicorp/consul/agent/connect" | ||
"github.com/hashicorp/consul/agent/structs" | ||
|
@@ -384,6 +385,7 @@ func (v *VaultProvider) GenerateIntermediate() (string, error) { | |
"csr": csr, | ||
"use_csr_values": true, | ||
"format": "pem_bundle", | ||
"ttl": v.config.IntermediateCertTTL.String(), | ||
}) | ||
if err != nil { | ||
return "", err | ||
|
@@ -456,6 +458,7 @@ func (v *VaultProvider) SignIntermediate(csr *x509.CertificateRequest) (string, | |
"use_csr_values": true, | ||
"format": "pem_bundle", | ||
"max_path_length": 0, | ||
"ttl": v.config.IntermediateCertTTL.String(), | ||
}) | ||
if err != nil { | ||
return "", err | ||
|
@@ -475,8 +478,20 @@ func (v *VaultProvider) SignIntermediate(csr *x509.CertificateRequest) (string, | |
// CrossSignCA takes a CA certificate and cross-signs it to form a trust chain | ||
// back to our active root. | ||
func (v *VaultProvider) CrossSignCA(cert *x509.Certificate) (string, error) { | ||
rootPEM, err := v.ActiveRoot() | ||
if err != nil { | ||
return "", err | ||
} | ||
rootCert, err := connect.ParseCert(rootPEM) | ||
if err != nil { | ||
return "", fmt.Errorf("error parsing root cert: %v", err) | ||
} | ||
if rootCert.NotAfter.Before(time.Now()) { | ||
return "", fmt.Errorf("root certificate is expired") | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I assume that means that Vault would happily sign a cert with an expired root CA? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right, it's because the |
||
|
||
var pemBuf bytes.Buffer | ||
err := pem.Encode(&pemBuf, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}) | ||
err = pem.Encode(&pemBuf, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should try and move these tests that require vault into the
agent/connect/ca
ortest/integration
packages at some point. But I don't see any reason to block merging this PR. We can revisit once we have a better idea of how we would like to organize our integration tests.I'm not sure if this extra coverage file will get sent to codecov, I suspect only the
coverage.txt
will get sent, but that's something we can fix in a follow up as well.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It definitely feels strange in
agent/consul
, although it does test internal leader logic. It couldn't go directly inagent/connect/ca
but maybe creating a new subpackage in one of these would be the way to go (likeagent/consul/integration
or something similar, that has tests like this which involve leader functionality and something external like a CA).