mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-01 19:17:58 +00:00
Remove dynamic keys from SSH Secrets Engine (#18874)
* Remove dynamic keys from SSH Secrets Engine This removes the functionality of Vault creating keys and adding them to the authorized keys file on hosts. This functionality has been deprecated since Vault version 0.7.2. The preferred alternative is to use the SSH CA method, which also allows key generation but places limits on TTL and doesn't require Vault reach out to provision each key on the specified host, making it much more secure. Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com> * Remove dynamic ssh references from documentation Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com> * Add changelog entry Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com> * Remove dynamic key secret type entirely Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com> * Clarify changelog language Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com> * Add removal notice to the website Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com> --------- Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
This commit is contained in:
@@ -26,17 +26,15 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
testIP = "127.0.0.1"
|
||||
testUserName = "vaultssh"
|
||||
testMultiUserName = "vaultssh,otherssh"
|
||||
testAdminUser = "vaultssh"
|
||||
testCaKeyType = "ca"
|
||||
testOTPKeyType = "otp"
|
||||
testDynamicKeyType = "dynamic"
|
||||
testCIDRList = "127.0.0.1/32"
|
||||
testAtRoleName = "test@RoleName"
|
||||
testDynamicRoleName = "testDynamicRoleName"
|
||||
testOTPRoleName = "testOTPRoleName"
|
||||
testIP = "127.0.0.1"
|
||||
testUserName = "vaultssh"
|
||||
testMultiUserName = "vaultssh,otherssh"
|
||||
testAdminUser = "vaultssh"
|
||||
testCaKeyType = "ca"
|
||||
testOTPKeyType = "otp"
|
||||
testCIDRList = "127.0.0.1/32"
|
||||
testAtRoleName = "test@RoleName"
|
||||
testOTPRoleName = "testOTPRoleName"
|
||||
// testKeyName is the name of the entry that will be written to SSHMOUNTPOINT/ssh/keys
|
||||
testKeyName = "testKeyName"
|
||||
// testSharedPrivateKey is the value of the entry that will be written to SSHMOUNTPOINT/ssh/keys
|
||||
@@ -537,36 +535,22 @@ func TestSSHBackend_Lookup(t *testing.T) {
|
||||
"default_user": testUserName,
|
||||
"cidr_list": testCIDRList,
|
||||
}
|
||||
testDynamicRoleData := map[string]interface{}{
|
||||
"key_type": testDynamicKeyType,
|
||||
"key": testKeyName,
|
||||
"admin_user": testAdminUser,
|
||||
"default_user": testAdminUser,
|
||||
"cidr_list": testCIDRList,
|
||||
}
|
||||
data := map[string]interface{}{
|
||||
"ip": testIP,
|
||||
}
|
||||
resp1 := []string(nil)
|
||||
resp2 := []string{testOTPRoleName}
|
||||
resp3 := []string{testDynamicRoleName, testOTPRoleName}
|
||||
resp4 := []string{testDynamicRoleName}
|
||||
resp5 := []string{testAtRoleName}
|
||||
resp3 := []string{testAtRoleName}
|
||||
logicaltest.Test(t, logicaltest.TestCase{
|
||||
LogicalFactory: newTestingFactory(t),
|
||||
Steps: []logicaltest.TestStep{
|
||||
testLookupRead(t, data, resp1),
|
||||
testRoleWrite(t, testOTPRoleName, testOTPRoleData),
|
||||
testLookupRead(t, data, resp2),
|
||||
testNamedKeysWrite(t, testKeyName, testSharedPrivateKey),
|
||||
testRoleWrite(t, testDynamicRoleName, testDynamicRoleData),
|
||||
testLookupRead(t, data, resp3),
|
||||
testRoleDelete(t, testOTPRoleName),
|
||||
testLookupRead(t, data, resp4),
|
||||
testRoleDelete(t, testDynamicRoleName),
|
||||
testLookupRead(t, data, resp1),
|
||||
testRoleWrite(t, testAtRoleName, testDynamicRoleData),
|
||||
testLookupRead(t, data, resp5),
|
||||
testRoleWrite(t, testAtRoleName, testOTPRoleData),
|
||||
testLookupRead(t, data, resp3),
|
||||
testRoleDelete(t, testAtRoleName),
|
||||
testLookupRead(t, data, resp1),
|
||||
},
|
||||
@@ -615,39 +599,6 @@ func TestSSHBackend_RoleList(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestSSHBackend_DynamicKeyCreate(t *testing.T) {
|
||||
cleanup, sshAddress := prepareTestContainer(t, "", "")
|
||||
defer cleanup()
|
||||
|
||||
host, port, err := net.SplitHostPort(sshAddress)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testDynamicRoleData := map[string]interface{}{
|
||||
"key_type": testDynamicKeyType,
|
||||
"key": testKeyName,
|
||||
"admin_user": testAdminUser,
|
||||
"default_user": testAdminUser,
|
||||
"cidr_list": host + "/32",
|
||||
"port": port,
|
||||
}
|
||||
data := map[string]interface{}{
|
||||
"username": testUserName,
|
||||
"ip": host,
|
||||
}
|
||||
logicaltest.Test(t, logicaltest.TestCase{
|
||||
LogicalFactory: newTestingFactory(t),
|
||||
Steps: []logicaltest.TestStep{
|
||||
testNamedKeysWrite(t, testKeyName, testSharedPrivateKey),
|
||||
testRoleWrite(t, testDynamicRoleName, testDynamicRoleData),
|
||||
testCredsWrite(t, testDynamicRoleName, data, false, sshAddress),
|
||||
testRoleWrite(t, testAtRoleName, testDynamicRoleData),
|
||||
testCredsWrite(t, testAtRoleName, data, false, sshAddress),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestSSHBackend_OTPRoleCrud(t *testing.T) {
|
||||
testOTPRoleData := map[string]interface{}{
|
||||
"key_type": testOTPKeyType,
|
||||
@@ -675,50 +626,6 @@ func TestSSHBackend_OTPRoleCrud(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestSSHBackend_DynamicRoleCrud(t *testing.T) {
|
||||
testDynamicRoleData := map[string]interface{}{
|
||||
"key_type": testDynamicKeyType,
|
||||
"key": testKeyName,
|
||||
"admin_user": testAdminUser,
|
||||
"default_user": testAdminUser,
|
||||
"cidr_list": testCIDRList,
|
||||
}
|
||||
respDynamicRoleData := map[string]interface{}{
|
||||
"cidr_list": testCIDRList,
|
||||
"port": 22,
|
||||
"install_script": DefaultPublicKeyInstallScript,
|
||||
"key_bits": 1024,
|
||||
"key": testKeyName,
|
||||
"admin_user": testUserName,
|
||||
"default_user": testUserName,
|
||||
"key_type": testDynamicKeyType,
|
||||
}
|
||||
logicaltest.Test(t, logicaltest.TestCase{
|
||||
LogicalFactory: newTestingFactory(t),
|
||||
Steps: []logicaltest.TestStep{
|
||||
testNamedKeysWrite(t, testKeyName, testSharedPrivateKey),
|
||||
testRoleWrite(t, testDynamicRoleName, testDynamicRoleData),
|
||||
testRoleRead(t, testDynamicRoleName, respDynamicRoleData),
|
||||
testRoleDelete(t, testDynamicRoleName),
|
||||
testRoleRead(t, testDynamicRoleName, nil),
|
||||
testRoleWrite(t, testAtRoleName, testDynamicRoleData),
|
||||
testRoleRead(t, testAtRoleName, respDynamicRoleData),
|
||||
testRoleDelete(t, testAtRoleName),
|
||||
testRoleRead(t, testAtRoleName, nil),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestSSHBackend_NamedKeysCrud(t *testing.T) {
|
||||
logicaltest.Test(t, logicaltest.TestCase{
|
||||
LogicalFactory: newTestingFactory(t),
|
||||
Steps: []logicaltest.TestStep{
|
||||
testNamedKeysWrite(t, testKeyName, testSharedPrivateKey),
|
||||
testNamedKeysDelete(t),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestSSHBackend_OTPCreate(t *testing.T) {
|
||||
cleanup, sshAddress := prepareTestContainer(t, "", "")
|
||||
defer func() {
|
||||
@@ -772,24 +679,14 @@ func TestSSHBackend_ConfigZeroAddressCRUD(t *testing.T) {
|
||||
"default_user": testUserName,
|
||||
"cidr_list": testCIDRList,
|
||||
}
|
||||
testDynamicRoleData := map[string]interface{}{
|
||||
"key_type": testDynamicKeyType,
|
||||
"key": testKeyName,
|
||||
"admin_user": testAdminUser,
|
||||
"default_user": testAdminUser,
|
||||
"cidr_list": testCIDRList,
|
||||
}
|
||||
req1 := map[string]interface{}{
|
||||
"roles": testOTPRoleName,
|
||||
}
|
||||
resp1 := map[string]interface{}{
|
||||
"roles": []string{testOTPRoleName},
|
||||
}
|
||||
req2 := map[string]interface{}{
|
||||
"roles": fmt.Sprintf("%s,%s", testOTPRoleName, testDynamicRoleName),
|
||||
}
|
||||
resp2 := map[string]interface{}{
|
||||
"roles": []string{testOTPRoleName, testDynamicRoleName},
|
||||
"roles": []string{testOTPRoleName},
|
||||
}
|
||||
resp3 := map[string]interface{}{
|
||||
"roles": []string{},
|
||||
@@ -801,11 +698,7 @@ func TestSSHBackend_ConfigZeroAddressCRUD(t *testing.T) {
|
||||
testRoleWrite(t, testOTPRoleName, testOTPRoleData),
|
||||
testConfigZeroAddressWrite(t, req1),
|
||||
testConfigZeroAddressRead(t, resp1),
|
||||
testNamedKeysWrite(t, testKeyName, testSharedPrivateKey),
|
||||
testRoleWrite(t, testDynamicRoleName, testDynamicRoleData),
|
||||
testConfigZeroAddressWrite(t, req2),
|
||||
testConfigZeroAddressRead(t, resp2),
|
||||
testRoleDelete(t, testDynamicRoleName),
|
||||
testConfigZeroAddressRead(t, resp1),
|
||||
testRoleDelete(t, testOTPRoleName),
|
||||
testConfigZeroAddressRead(t, resp3),
|
||||
@@ -839,43 +732,6 @@ func TestSSHBackend_CredsForZeroAddressRoles_otp(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestSSHBackend_CredsForZeroAddressRoles_dynamic(t *testing.T) {
|
||||
cleanup, sshAddress := prepareTestContainer(t, "", "")
|
||||
defer cleanup()
|
||||
|
||||
host, port, err := net.SplitHostPort(sshAddress)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
dynamicRoleData := map[string]interface{}{
|
||||
"key_type": testDynamicKeyType,
|
||||
"key": testKeyName,
|
||||
"admin_user": testAdminUser,
|
||||
"default_user": testAdminUser,
|
||||
"port": port,
|
||||
}
|
||||
data := map[string]interface{}{
|
||||
"username": testUserName,
|
||||
"ip": host,
|
||||
}
|
||||
req2 := map[string]interface{}{
|
||||
"roles": testDynamicRoleName,
|
||||
}
|
||||
logicaltest.Test(t, logicaltest.TestCase{
|
||||
LogicalFactory: newTestingFactory(t),
|
||||
Steps: []logicaltest.TestStep{
|
||||
testNamedKeysWrite(t, testKeyName, testSharedPrivateKey),
|
||||
testRoleWrite(t, testDynamicRoleName, dynamicRoleData),
|
||||
testCredsWrite(t, testDynamicRoleName, data, true, sshAddress),
|
||||
testConfigZeroAddressWrite(t, req2),
|
||||
testCredsWrite(t, testDynamicRoleName, data, false, sshAddress),
|
||||
testConfigZeroAddressDelete(t),
|
||||
testCredsWrite(t, testDynamicRoleName, data, true, sshAddress),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestSSHBackend_CA(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
@@ -2414,23 +2270,6 @@ func testVerifyWrite(t *testing.T, data map[string]interface{}, expected map[str
|
||||
}
|
||||
}
|
||||
|
||||
func testNamedKeysWrite(t *testing.T, name, key string) logicaltest.TestStep {
|
||||
return logicaltest.TestStep{
|
||||
Operation: logical.UpdateOperation,
|
||||
Path: fmt.Sprintf("keys/%s", name),
|
||||
Data: map[string]interface{}{
|
||||
"key": key,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func testNamedKeysDelete(t *testing.T) logicaltest.TestStep {
|
||||
return logicaltest.TestStep{
|
||||
Operation: logical.DeleteOperation,
|
||||
Path: fmt.Sprintf("keys/%s", testKeyName),
|
||||
}
|
||||
}
|
||||
|
||||
func testLookupRead(t *testing.T, data map[string]interface{}, expected []string) logicaltest.TestStep {
|
||||
return logicaltest.TestStep{
|
||||
Operation: logical.UpdateOperation,
|
||||
@@ -2495,10 +2334,6 @@ func testRoleRead(t *testing.T, roleName string, expected map[string]interface{}
|
||||
if d.KeyType != expected["key_type"] || d.DefaultUser != expected["default_user"] || d.CIDRList != expected["cidr_list"] {
|
||||
return fmt.Errorf("data mismatch. bad: %#v", resp)
|
||||
}
|
||||
case "dynamic":
|
||||
if d.AdminUser != expected["admin_user"] || d.CIDRList != expected["cidr_list"] || d.KeyName != expected["key"] || d.KeyType != expected["key_type"] {
|
||||
return fmt.Errorf("data mismatch. bad: %#v", resp)
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unknown key type. bad: %#v", resp)
|
||||
}
|
||||
@@ -2539,7 +2374,7 @@ func testCredsWrite(t *testing.T, roleName string, data map[string]interface{},
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if roleName == testDynamicRoleName || roleName == testAtRoleName {
|
||||
if roleName == testAtRoleName {
|
||||
var d struct {
|
||||
Key string `mapstructure:"key"`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user