Allow cleanup ssh dynamic keys host keys (#18939)

* Add ability to clean up host keys for dynamic keys

This adds a new endpoint, tidy/dynamic-keys that removes any stale host
keys still present on the mount. This does not clean up any pending
dynamic key leases and will not remove these keys from systems with
authorized hosts entries created by Vault.

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Add documentation

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Add changelog entry

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

---------

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
This commit is contained in:
Alexander Scheel
2023-02-01 10:09:16 -05:00
committed by GitHub
parent 207f0475c0
commit e4766aa974
5 changed files with 150 additions and 1 deletions

View File

@@ -23,6 +23,8 @@ import (
vaulthttp "github.com/hashicorp/vault/http"
"github.com/hashicorp/vault/vault"
"github.com/mitchellh/mapstructure"
"github.com/stretchr/testify/require"
)
const (
@@ -2404,3 +2406,59 @@ func testCredsWrite(t *testing.T, roleName string, data map[string]interface{},
},
}
}
func TestBackend_CleanupDynamicHostKeys(t *testing.T) {
config := logical.TestBackendConfig()
config.StorageView = &logical.InmemStorage{}
b, err := Backend(config)
if err != nil {
t.Fatal(err)
}
err = b.Setup(context.Background(), config)
if err != nil {
t.Fatal(err)
}
// Running on a clean mount shouldn't do anything.
cleanRequest := &logical.Request{
Operation: logical.DeleteOperation,
Path: "tidy/dynamic-keys",
Storage: config.StorageView,
}
resp, err := b.HandleRequest(context.Background(), cleanRequest)
require.NoError(t, err)
require.NotNil(t, resp)
require.NotNil(t, resp.Data)
require.NotNil(t, resp.Data["message"])
require.Contains(t, resp.Data["message"], "0 of 0")
// Write a bunch of bogus entries.
for i := 0; i < 15; i++ {
data := map[string]interface{}{
"host": "localhost",
"key": "nothing-to-see-here",
}
entry, err := logical.StorageEntryJSON(fmt.Sprintf("%vexample-%v", keysStoragePrefix, i), &data)
require.NoError(t, err)
err = config.StorageView.Put(context.Background(), entry)
require.NoError(t, err)
}
// Should now have 15
resp, err = b.HandleRequest(context.Background(), cleanRequest)
require.NoError(t, err)
require.NotNil(t, resp)
require.NotNil(t, resp.Data)
require.NotNil(t, resp.Data["message"])
require.Contains(t, resp.Data["message"], "15 of 15")
// Should have none left.
resp, err = b.HandleRequest(context.Background(), cleanRequest)
require.NoError(t, err)
require.NotNil(t, resp)
require.NotNil(t, resp.Data)
require.NotNil(t, resp.Data["message"])
require.Contains(t, resp.Data["message"], "0 of 0")
}