Skip to content

Commit

Permalink
Merge pull request #1394 from hashicorp/vault-cert-rotation
Browse files Browse the repository at this point in the history
Allow additional time for PKI certificates to valid
  • Loading branch information
jasonodonnell authored Jul 23, 2020
2 parents 6bc149b + d45e644 commit afe1806
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 58 deletions.
30 changes: 5 additions & 25 deletions dependency/vault_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ import (
"strings"
"time"

"crypto/x509"
"encoding/json"
"encoding/pem"

"github.com/hashicorp/vault/api"
)

Expand Down Expand Up @@ -106,22 +103,6 @@ func renewSecret(clients *ClientSet, d renewer) error {
}
}

// durationFrom cert gets the duration of validity from cert data and
// returns that value as an integer number of seconds
func durationFromCert(certData string) int {
block, _ := pem.Decode([]byte(certData))
if block == nil {
return -1
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
log.Printf("[WARN] Unable to parse certificate data: %s", err)
return -1
}

return int(cert.NotAfter.Sub(cert.NotBefore).Seconds())
}

// leaseCheckWait accepts a secret and returns the recommended amount of
// time to sleep.
func leaseCheckWait(s *Secret) time.Duration {
Expand All @@ -132,12 +113,11 @@ func leaseCheckWait(s *Secret) time.Duration {
}

// Handle if this is a certificate with no lease
if certInterface, ok := s.Data["certificate"]; ok && s.LeaseID == "" {
if certData, ok := certInterface.(string); ok {
newDuration := durationFromCert(certData)
if newDuration > 0 {
log.Printf("[DEBUG] Found certificate and set lease duration to %d seconds", newDuration)
base = newDuration
if _, ok := s.Data["certificate"]; ok && s.LeaseID == "" {
if expInterface, ok := s.Data["expiration"]; ok {
if expData, err := expInterface.(json.Number).Int64(); err == nil {
base = int(expData - time.Now().Unix())
log.Printf("[DEBUG] Found certificate and set lease duration to %d seconds", base)
}
}
}
Expand Down
48 changes: 15 additions & 33 deletions dependency/vault_common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ package dependency

import (
"encoding/json"
"strconv"
"testing"

"github.com/stretchr/testify/assert"
"time"
)

func init() {
Expand All @@ -26,7 +26,7 @@ func TestVaultRenewDuration(t *testing.T) {

var data = map[string]interface{}{
"rotation_period": json.Number("60"),
"ttl": json.Number("30"),
"ttl": json.Number("30"),
}

nonRenewableRotated := Secret{LeaseDuration: 100, Data: data}
Expand All @@ -39,7 +39,7 @@ func TestVaultRenewDuration(t *testing.T) {

data = map[string]interface{}{
"rotation_period": json.Number("30"),
"ttl": json.Number("5"),
"ttl": json.Number("5"),
}

nonRenewableRotated = Secret{LeaseDuration: 100, Data: data}
Expand All @@ -49,36 +49,18 @@ func TestVaultRenewDuration(t *testing.T) {
if nonRenewableRotatedDur != 6 {
t.Fatalf("renewable duration is not 6: %f", nonRenewableRotatedDur)
}
}

const testGoodCert = `-----BEGIN CERTIFICATE-----
MIICAjCCAWugAwIBAgIJALDrJbXZKXXnMA0GCSqGSIb3DQEBCwUAMBoxGDAWBgNV
BAMMD2NvbnN1bC10ZW1wbGF0ZTAeFw0xODA1MjUxNTAzNDdaFw0xODA2MDQxNTAz
NDdaMBoxGDAWBgNVBAMMD2NvbnN1bC10ZW1wbGF0ZTCBnzANBgkqhkiG9w0BAQEF
AAOBjQAwgYkCgYEAuT1yS2FvX2bpNvEkrapt4wC68NIfTU9Xx55DC4/Pq1ZkuI8b
tC64x1oiJdM7ABEmT58rofTXoEpeHxcLTpXtJcrfLdgHUkPxNdrBgLWJi0BGI3m6
zLF9KLTwEpFfBBTLgM6HIvTqqBD4itFtI0BDS/mqQKqa33Ai6hX0zPAH6AECAwEA
AaNQME4wHQYDVR0OBBYEFLldqcFQ+RF40xBNgSjdNGBN78yHMB8GA1UdIwQYMBaA
FLldqcFQ+RF40xBNgSjdNGBN78yHMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEL
BQADgYEAUXeDp5pyGhH3RCxdJgjbQ67D5nqTVbTJnetEw1UdMEDQGrgCIUrbsJWm
G4SbKUjKP+4wVUJLZpmv9PwJcN0ZxntNkJBDzTk+KULu4+8cCj6A27bBhmzeOu1y
zZlyse1m1NECY3ryPtkst4U/0wCiKcI4ZW58RrhXgKucB3Y0C0w=
-----END CERTIFICATE-----`

const testBadCert = `-----BEGIN CERTIFICATE-----
THIS IS NOT A VALID CERT
-----END CERTIFICATE-----`

func TestDurationFromCert(t *testing.T) {
t.Parallel()

dur := durationFromCert(testGoodCert)
rawExpiration := time.Now().Unix() + 100
expiration := strconv.FormatInt(rawExpiration, 10)

// 10 days in seconds
assert.Equal(t, 864000, dur)

dur = durationFromCert(testBadCert)
data = map[string]interface{}{
"expiration": json.Number(expiration),
"certificate": "foobar",
}

// Negative duration means an invalid cert
assert.Equal(t, -1, dur)
nonRenewableCert := Secret{LeaseDuration: 100, Data: data}
nonRenewableCertDur := leaseCheckWait(&nonRenewableCert).Seconds()
if nonRenewableCertDur < 85 || nonRenewableCertDur > 95 {
t.Fatalf("non renewable certificate duration is not within 85%% to 95%%: %f", nonRenewableCertDur)
}
}

0 comments on commit afe1806

Please sign in to comment.