-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Alexander Scheel <[email protected]>
- Loading branch information
Showing
1 changed file
with
160 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
package pki | ||
|
||
import ( | ||
"testing" | ||
"time" | ||
|
||
"github.com/hashicorp/vault/api" | ||
vaulthttp "github.com/hashicorp/vault/http" | ||
"github.com/hashicorp/vault/sdk/logical" | ||
"github.com/hashicorp/vault/vault" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestAutoTidy(t *testing.T) { | ||
t.Parallel() | ||
|
||
// While we'd like to reduce this duration, we need to wait until | ||
// the rollback manager timer ticks. With the new helper, we can | ||
// modify the rollback manager timer period directly, allowing us | ||
// to shorten the total test time significantly. | ||
// | ||
// We set the delta CRL time to ensure it executes prior to the | ||
// main CRL rebuild, and the new CRL doesn't rebuild until after | ||
// we're done. | ||
newPeriod := 1 * time.Second | ||
|
||
// This test requires the periodicFunc to trigger, which requires we stand | ||
// up a full test cluster. | ||
coreConfig := &vault.CoreConfig{ | ||
LogicalBackends: map[string]logical.Factory{ | ||
"pki": Factory, | ||
}, | ||
// See notes below about usage of /sys/raw for reading cluster | ||
// storage without barrier encryption. | ||
EnableRaw: true, | ||
} | ||
oldPeriod := vault.SetRollbackPeriodForTesting(newPeriod) | ||
cluster := vault.NewTestCluster(t, coreConfig, &vault.TestClusterOptions{ | ||
HandlerFunc: vaulthttp.Handler, | ||
}) | ||
cluster.Start() | ||
defer cluster.Cleanup() | ||
client := cluster.Cores[0].Client | ||
vault.SetRollbackPeriodForTesting(oldPeriod) | ||
|
||
// Mount PKI | ||
err := client.Sys().Mount("pki", &api.MountInput{ | ||
Type: "pki", | ||
Config: api.MountConfigInput{ | ||
DefaultLeaseTTL: "10m", | ||
MaxLeaseTTL: "60m", | ||
}, | ||
}) | ||
require.NoError(t, err) | ||
|
||
// Generate root. | ||
resp, err := client.Logical().Write("pki/root/generate/internal", map[string]interface{}{ | ||
"ttl": "40h", | ||
"common_name": "Root X1", | ||
"key_type": "ec", | ||
}) | ||
require.NoError(t, err) | ||
require.NotNil(t, resp) | ||
require.NotEmpty(t, resp.Data) | ||
require.NotEmpty(t, resp.Data["issuer_id"]) | ||
|
||
// Run tidy so status is not empty when we run it later... | ||
_, err = client.Logical().Write("pki/tidy", map[string]interface{}{ | ||
"tidy_revoked_certs": true, | ||
}) | ||
require.NoError(t, err) | ||
|
||
// Setup a testing role. | ||
_, err = client.Logical().Write("pki/roles/local-testing", map[string]interface{}{ | ||
"allow_any_name": true, | ||
"enforce_hostnames": false, | ||
"key_type": "ec", | ||
}) | ||
require.NoError(t, err) | ||
|
||
// Write the auto-tidy config. | ||
_, err = client.Logical().Write("pki/config/auto-tidy", map[string]interface{}{ | ||
"enabled": true, | ||
"interval_duration": "1s", | ||
"tidy_cert_store": true, | ||
"tidy_revoked_certs": true, | ||
"safety_buffer": "1s", | ||
}) | ||
require.NoError(t, err) | ||
|
||
// Issue a cert and revoke it. | ||
resp, err = client.Logical().Write("pki/issue/local-testing", map[string]interface{}{ | ||
"common_name": "example.com", | ||
"ttl": "10s", | ||
}) | ||
require.NoError(t, err) | ||
require.NotNil(t, resp) | ||
require.NotNil(t, resp.Data) | ||
require.NotEmpty(t, resp.Data["serial_number"]) | ||
require.NotEmpty(t, resp.Data["certificate"]) | ||
leafSerial := resp.Data["serial_number"].(string) | ||
leafCert := parseCert(t, resp.Data["certificate"].(string)) | ||
|
||
_, err = client.Logical().Write("pki/revoke", map[string]interface{}{ | ||
"serial_number": leafSerial, | ||
}) | ||
require.NoError(t, err) | ||
|
||
// Cert should still exist. | ||
resp, err = client.Logical().Read("pki/cert/" + leafSerial) | ||
require.NoError(t, err) | ||
require.NotNil(t, resp) | ||
require.NotNil(t, resp.Data) | ||
require.NotEmpty(t, resp.Data["certificate"]) | ||
|
||
// Wait for cert to expire and the safety buffer to elapse. | ||
time.Sleep(leafCert.NotAfter.Sub(time.Now()) + 3*time.Second) | ||
|
||
// Wait for auto-tidy to run afterwards. | ||
var foundTidyRunning string | ||
var foundTidyFinished bool | ||
timeoutChan := time.After(120 * time.Second) | ||
for { | ||
if foundTidyRunning != "" && foundTidyFinished { | ||
break | ||
} | ||
|
||
select { | ||
case <-timeoutChan: | ||
t.Fatalf("expected auto-tidy to run (%v) and finish (%v) before 120 seconds elapsed", foundTidyRunning, foundTidyFinished) | ||
default: | ||
time.Sleep(250 * time.Millisecond) | ||
|
||
resp, err = client.Logical().Read("pki/tidy-status") | ||
require.NoError(t, err) | ||
require.NotNil(t, resp) | ||
require.NotNil(t, resp.Data) | ||
require.NotEmpty(t, resp.Data["state"]) | ||
require.NotEmpty(t, resp.Data["time_started"]) | ||
state := resp.Data["state"].(string) | ||
started := resp.Data["time_started"].(string) | ||
t.Logf("Resp: %v", resp.Data) | ||
|
||
// We want the _next_ tidy run after the cert expires. This | ||
// means if we're currently finished when we hit this the | ||
// first time, we want to wait for the next run. | ||
if foundTidyRunning == "" { | ||
foundTidyRunning = started | ||
} else if foundTidyRunning != started && !foundTidyFinished && state == "Finished" { | ||
foundTidyFinished = true | ||
} | ||
} | ||
} | ||
|
||
// Cert should no longer exist. | ||
resp, err = client.Logical().Read("pki/cert/" + leafSerial) | ||
require.Nil(t, err) | ||
require.Nil(t, resp) | ||
} |