mirror of
https://github.com/hashicorp/vault.git
synced 2026-06-08 16:24:51 -04:00
Don't revoke CA certificates with leases.
This commit is contained in:
parent
0aad4e68a7
commit
9de0ea081a
7 changed files with 53 additions and 24 deletions
|
|
@ -489,6 +489,12 @@ func generateURLSteps(t *testing.T, caCert, caKey string, intdata, reqdata map[s
|
|||
"common_name": "Root Cert",
|
||||
"ttl": "180h",
|
||||
},
|
||||
Check: func(resp *logical.Response) error {
|
||||
if resp.Secret != nil && resp.Secret.LeaseID != "" {
|
||||
return fmt.Errorf("root returned with a lease")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
},
|
||||
|
||||
logicaltest.TestStep{
|
||||
|
|
@ -556,6 +562,9 @@ func generateURLSteps(t *testing.T, caCert, caKey string, intdata, reqdata map[s
|
|||
if certString == "" {
|
||||
return fmt.Errorf("no certificate returned")
|
||||
}
|
||||
if resp.Secret != nil && resp.Secret.LeaseID != "" {
|
||||
return fmt.Errorf("signed intermediate returned with a lease")
|
||||
}
|
||||
certBytes, _ := base64.StdEncoding.DecodeString(certString)
|
||||
certs, err := x509.ParseCertificates(certBytes)
|
||||
if err != nil {
|
||||
|
|
@ -596,6 +605,9 @@ func generateURLSteps(t *testing.T, caCert, caKey string, intdata, reqdata map[s
|
|||
if certString == "" {
|
||||
return fmt.Errorf("no certificate returned")
|
||||
}
|
||||
if resp.Secret != nil && resp.Secret.LeaseID != "" {
|
||||
return fmt.Errorf("signed intermediate returned with a lease")
|
||||
}
|
||||
certBytes, _ := base64.StdEncoding.DecodeString(certString)
|
||||
certs, err := x509.ParseCertificates(certBytes)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ type revocationInfo struct {
|
|||
}
|
||||
|
||||
// Revokes a cert, and tries to be smart about error recovery
|
||||
func revokeCert(b *backend, req *logical.Request, serial string) (*logical.Response, error) {
|
||||
func revokeCert(b *backend, req *logical.Request, serial string, fromLease bool) (*logical.Response, error) {
|
||||
// As this backend is self-contained and this function does not hook into
|
||||
// third parties to manage users or resources, if the mount is tainted,
|
||||
// revocation doesn't matter anyways -- the CRL that would be written will
|
||||
|
|
@ -80,6 +80,12 @@ func revokeCert(b *backend, req *logical.Request, serial string) (*logical.Respo
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
// Compatibility: Don't revoke CAs if they had leases. New CAs going
|
||||
// forward aren't issued leases.
|
||||
if cert.IsCA && fromLease {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
revInfo.CertificateBytes = certEntry.Value
|
||||
revInfo.RevocationTime = time.Now().Unix()
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ func (b *backend) pathRevokeWrite(req *logical.Request, data *framework.FieldDat
|
|||
b.revokeStorageLock.Lock()
|
||||
defer b.revokeStorageLock.Unlock()
|
||||
|
||||
return revokeCert(b, req, serial)
|
||||
return revokeCert(b, req, serial, false)
|
||||
}
|
||||
|
||||
func (b *backend) pathRotateCRLRead(req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package pki
|
|||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vault/helper/certutil"
|
||||
"github.com/hashicorp/vault/logical"
|
||||
|
|
@ -97,14 +96,12 @@ func (b *backend) pathCAGenerateRoot(
|
|||
return nil, fmt.Errorf("error converting raw cert bundle to cert bundle: %s", err)
|
||||
}
|
||||
|
||||
resp := b.Secret(SecretCertsType).Response(
|
||||
map[string]interface{}{
|
||||
resp := &logical.Response{
|
||||
Data: map[string]interface{}{
|
||||
"expiration": int64(parsedBundle.Certificate.NotAfter.Unix()),
|
||||
"serial_number": cb.SerialNumber,
|
||||
},
|
||||
map[string]interface{}{
|
||||
"serial_number": cb.SerialNumber,
|
||||
})
|
||||
}
|
||||
|
||||
switch format {
|
||||
case "pem":
|
||||
|
|
@ -135,8 +132,6 @@ func (b *backend) pathCAGenerateRoot(
|
|||
}
|
||||
}
|
||||
|
||||
resp.Secret.TTL = parsedBundle.Certificate.NotAfter.Sub(time.Now())
|
||||
|
||||
// Store it as the CA bundle
|
||||
entry, err := logical.StorageEntryJSON("config/ca_bundle", cb)
|
||||
if err != nil {
|
||||
|
|
@ -237,14 +232,12 @@ func (b *backend) pathCASignIntermediate(
|
|||
return nil, fmt.Errorf("Error converting raw cert bundle to cert bundle: %s", err)
|
||||
}
|
||||
|
||||
resp := b.Secret(SecretCertsType).Response(
|
||||
map[string]interface{}{
|
||||
resp := &logical.Response{
|
||||
Data: map[string]interface{}{
|
||||
"expiration": int64(parsedBundle.Certificate.NotAfter.Unix()),
|
||||
"serial_number": cb.SerialNumber,
|
||||
},
|
||||
map[string]interface{}{
|
||||
"serial_number": cb.SerialNumber,
|
||||
})
|
||||
}
|
||||
|
||||
switch format {
|
||||
case "pem":
|
||||
|
|
@ -260,8 +253,6 @@ func (b *backend) pathCASignIntermediate(
|
|||
resp.Data["issuing_ca"] = base64.StdEncoding.EncodeToString(parsedBundle.IssuingCABytes)
|
||||
}
|
||||
|
||||
resp.Secret.TTL = parsedBundle.Certificate.NotAfter.Sub(time.Now())
|
||||
|
||||
err = req.Storage.Put(&logical.StorageEntry{
|
||||
Key: "certs/" + cb.SerialNumber,
|
||||
Value: parsedBundle.CertificateBytes,
|
||||
|
|
|
|||
|
|
@ -51,5 +51,5 @@ func (b *backend) secretCredsRevoke(
|
|||
b.revokeStorageLock.Lock()
|
||||
defer b.revokeStorageLock.Unlock()
|
||||
|
||||
return revokeCert(b, req, serial)
|
||||
return revokeCert(b, req, serial, true)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,19 @@ certificate storage, or both. In addition, you can specify a safety buffer
|
|||
(defaulting to 72 hours) to ensure that any time discrepancies between your
|
||||
hosts is accounted for.
|
||||
|
||||
## PKI Backend Does Not Issue Leases for CA Certificates
|
||||
|
||||
When a token expires, it revokes all leases associated with it. This means that
|
||||
long-lived CA certs need correspondingly long-lived tokens, something that is
|
||||
easy to forget, resulting in an unintended revocation of the CA certificate
|
||||
when the token expires. To prevent this, root and intermediate CA certs no
|
||||
longer have associated leases. To revoke these certificates, use the
|
||||
`pki/revoke` endpoint.
|
||||
|
||||
CA certificates that have already been issued and acquired leases will report
|
||||
to the lease manager that revocation was successful, but will not actually be
|
||||
revoked and placed onto the CRL.
|
||||
|
||||
## Cert Authentication Backend Performs Client Checking During Renewals
|
||||
|
||||
The `cert` backend now performs a variant of channel binding at renewal time
|
||||
|
|
|
|||
|
|
@ -127,6 +127,15 @@ enforced. Software that can handle SHA256 signatures should also be able to
|
|||
handle 2048-bit keys, and 1024-bit keys are considered unsafe and are
|
||||
disallowed in the Internet PKI.
|
||||
|
||||
### Token Lifetimes and Revocation
|
||||
|
||||
When a token expires, it revokes all leases associated with it. This means that
|
||||
long-lived CA certs need correspondingly long-lived tokens, something that is
|
||||
easy to forget. Starting with 0.6, root and intermediate CA certs no longer
|
||||
have associated leases, to prevent unintended revocation when not using a token
|
||||
with a long enough lifetime. To revoke these certificates, use the `pki/revoke`
|
||||
endpoint.
|
||||
|
||||
## Quick Start
|
||||
|
||||
#### Mount the backend
|
||||
|
|
@ -166,8 +175,6 @@ Now, we generate our root certificate:
|
|||
```text
|
||||
$ vault write pki/root/generate/internal common_name=myvault.com ttl=87600h
|
||||
Key Value
|
||||
lease_id pki/root/generate/internal/aa959dd4-467e-e5ff-642b-371add518b40
|
||||
lease_duration 315359999
|
||||
certificate -----BEGIN CERTIFICATE-----
|
||||
MIIDvTCCAqWgAwIBAgIUAsza+fvOw+Xh9ifYQ0gNN0ruuWcwDQYJKoZIhvcNAQEL
|
||||
BQAwFjEUMBIGA1UEAxMLbXl2YXVsdC5jb20wHhcNMTUxMTE5MTYwNDU5WhcNMjUx
|
||||
|
|
@ -1308,8 +1315,8 @@ subpath for interactive help output.
|
|||
|
||||
```javascript
|
||||
{
|
||||
"lease_id": "pki/root/generate/internal/aa959dd4-467e-e5ff-642b-371add518b40",
|
||||
"lease_duration": 315359999,
|
||||
"lease_id": "",
|
||||
"lease_duration": 0,
|
||||
"renewable": false,
|
||||
"data": {
|
||||
"certificate": "-----BEGIN CERTIFICATE-----\nMIIDzDCCAragAwIBAgIUOd0ukLcjH43TfTHFG9qE0FtlMVgwCwYJKoZIhvcNAQEL\n...\numkqeYeO30g1uYvDuWLXVA==\n-----END CERTIFICATE-----\n",
|
||||
|
|
@ -1418,9 +1425,9 @@ subpath for interactive help output.
|
|||
|
||||
```javascript
|
||||
{
|
||||
"lease_id": "pki/root/sign-intermediate/bc23e3c6-8dcd-48c6-f3af-dd2db7f815c2",
|
||||
"lease_id": "",
|
||||
"renewable": false,
|
||||
"lease_duration": 21600,
|
||||
"lease_duration": 0,
|
||||
"data": {
|
||||
"certificate": "-----BEGIN CERTIFICATE-----\nMIIDzDCCAragAwIBAgIUOd0ukLcjH43TfTHFG9qE0FtlMVgwCwYJKoZIhvcNAQEL\n...\numkqeYeO30g1uYvDuWLXVA==\n-----END CERTIFICATE-----\n",
|
||||
"issuing_ca": "-----BEGIN CERTIFICATE-----\nMIIDUTCCAjmgAwIBAgIJAKM+z4MSfw2mMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNV\n...\nG/7g4koczXLoUM3OQXd5Aq2cs4SS1vODrYmgbioFsQ3eDHd1fg==\n-----END CERTIFICATE-----\n",
|
||||
|
|
|
|||
Loading…
Reference in a new issue