-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support root issuer generation #14975
Changes from 4 commits
3903eab
5f2179f
e301ef4
d2f24d7
58115c0
5d5e0be
ce4769a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4613,6 +4613,213 @@ func TestBackend_Roles_KeySizeRegression(t *testing.T) { | |
t.Log(fmt.Sprintf("Key size regression expanded matrix test scenarios: %d", tested)) | ||
} | ||
|
||
func TestRootWithExistingKey(t *testing.T) { | ||
coreConfig := &vault.CoreConfig{ | ||
LogicalBackends: map[string]logical.Factory{ | ||
"pki": Factory, | ||
}, | ||
} | ||
cluster := vault.NewTestCluster(t, coreConfig, &vault.TestClusterOptions{ | ||
HandlerFunc: vaulthttp.Handler, | ||
}) | ||
cluster.Start() | ||
defer cluster.Cleanup() | ||
|
||
client := cluster.Cores[0].Client | ||
var err error | ||
|
||
mountPKIEndpoint(t, client, "pki-root") | ||
|
||
// Fail requests if type is existing, and we specify the key_type param | ||
ctx := context.Background() | ||
_, err = client.Logical().WriteWithContext(ctx, "pki-root/root/generate/existing", map[string]interface{}{ | ||
"common_name": "root myvault.com", | ||
"key_type": "rsa", | ||
}) | ||
require.Error(t, err) | ||
require.Contains(t, err.Error(), "key_type nor key_bits arguments can be set in this mode") | ||
|
||
// Fail requests if type is existing, and we specify the key_bits param | ||
_, err = client.Logical().WriteWithContext(ctx, "pki-root/root/generate/existing", map[string]interface{}{ | ||
"common_name": "root myvault.com", | ||
"key_bits": "2048", | ||
}) | ||
require.Error(t, err) | ||
require.Contains(t, err.Error(), "key_type nor key_bits arguments can be set in this mode") | ||
|
||
// Fail if the specified key does not exist. | ||
_, err = client.Logical().WriteWithContext(ctx, "pki-root/issuers/generate/root/existing", map[string]interface{}{ | ||
"common_name": "root myvault.com", | ||
"issuer_name": "my-issuer1", | ||
"key_ref": "my-key1", | ||
}) | ||
require.Error(t, err) | ||
require.Contains(t, err.Error(), "unable to find PKI key for reference: my-key1") | ||
|
||
// Fail if the specified key name is default. | ||
_, err = client.Logical().WriteWithContext(ctx, "pki-root/issuers/generate/root/internal", map[string]interface{}{ | ||
"common_name": "root myvault.com", | ||
"issuer_name": "my-issuer1", | ||
"key_name": "Default", | ||
}) | ||
require.Error(t, err) | ||
require.Contains(t, err.Error(), "reserved keyword 'default' can not be used as key name") | ||
|
||
// Fail if the specified issuer name is default. | ||
_, err = client.Logical().WriteWithContext(ctx, "pki-root/issuers/generate/root/internal", map[string]interface{}{ | ||
"common_name": "root myvault.com", | ||
"issuer_name": "DEFAULT", | ||
}) | ||
require.Error(t, err) | ||
require.Contains(t, err.Error(), "reserved keyword 'default' can not be used as issuer name") | ||
|
||
// Create the first CA | ||
resp, err := client.Logical().WriteWithContext(ctx, "pki-root/issuers/generate/root/internal", map[string]interface{}{ | ||
"common_name": "root myvault.com", | ||
"key_type": "rsa", | ||
"issuer_name": "my-issuer1", | ||
}) | ||
require.NoError(t, err) | ||
require.NotNil(t, resp.Data["certificate"]) | ||
myIssuerId1 := resp.Data["issuer_id"] | ||
myKeyId1 := resp.Data["key_id"] | ||
require.NotEmpty(t, myIssuerId1) | ||
require.NotEmpty(t, myKeyId1) | ||
|
||
// Fail if the specified issuer name is re-used. | ||
_, err = client.Logical().WriteWithContext(ctx, "pki-root/issuers/generate/root/internal", map[string]interface{}{ | ||
"common_name": "root myvault.com", | ||
"issuer_name": "my-issuer1", | ||
}) | ||
require.Error(t, err) | ||
require.Contains(t, err.Error(), "issuer name already used") | ||
|
||
// Create the second CA | ||
resp, err = client.Logical().WriteWithContext(ctx, "pki-root/issuers/generate/root/internal", map[string]interface{}{ | ||
"common_name": "root myvault.com", | ||
"key_type": "rsa", | ||
"issuer_name": "my-issuer2", | ||
"key_name": "root-key2", | ||
}) | ||
require.NoError(t, err) | ||
require.NotNil(t, resp.Data["certificate"]) | ||
myIssuerId2 := resp.Data["issuer_id"] | ||
myKeyId2 := resp.Data["key_id"] | ||
require.NotEmpty(t, myIssuerId2) | ||
require.NotEmpty(t, myKeyId2) | ||
|
||
// Fail if the specified key name is re-used. | ||
_, err = client.Logical().WriteWithContext(ctx, "pki-root/issuers/generate/root/internal", map[string]interface{}{ | ||
"common_name": "root myvault.com", | ||
"issuer_name": "my-issuer3", | ||
"key_name": "root-key2", | ||
}) | ||
require.Error(t, err) | ||
require.Contains(t, err.Error(), "key name already used") | ||
|
||
// Create a third CA re-using key from CA 1 | ||
resp, err = client.Logical().WriteWithContext(ctx, "pki-root/issuers/generate/root/existing", map[string]interface{}{ | ||
"common_name": "root myvault.com", | ||
"issuer_name": "my-issuer3", | ||
"key_ref": myKeyId1, | ||
}) | ||
require.NoError(t, err) | ||
require.NotNil(t, resp.Data["certificate"]) | ||
myIssuerId3 := resp.Data["issuer_id"] | ||
myKeyId3 := resp.Data["key_id"] | ||
require.NotEmpty(t, myIssuerId3) | ||
require.NotEmpty(t, myKeyId3) | ||
|
||
require.NotEqual(t, myIssuerId1, myIssuerId2) | ||
require.NotEqual(t, myIssuerId1, myIssuerId3) | ||
require.NotEqual(t, myKeyId1, myKeyId2) | ||
require.Equal(t, myKeyId1, myKeyId3) | ||
|
||
resp, err = client.Logical().ListWithContext(ctx, "pki-root/issuers") | ||
require.NoError(t, err) | ||
require.Equal(t, 3, len(resp.Data["keys"].([]interface{}))) | ||
require.Contains(t, resp.Data["keys"], myIssuerId1) | ||
require.Contains(t, resp.Data["keys"], myIssuerId2) | ||
require.Contains(t, resp.Data["keys"], myIssuerId3) | ||
} | ||
|
||
func TestIntermediateWithExistingKey(t *testing.T) { | ||
coreConfig := &vault.CoreConfig{ | ||
LogicalBackends: map[string]logical.Factory{ | ||
"pki": Factory, | ||
}, | ||
} | ||
cluster := vault.NewTestCluster(t, coreConfig, &vault.TestClusterOptions{ | ||
HandlerFunc: vaulthttp.Handler, | ||
}) | ||
cluster.Start() | ||
defer cluster.Cleanup() | ||
|
||
client := cluster.Cores[0].Client | ||
var err error | ||
|
||
mountPKIEndpoint(t, client, "pki-root") | ||
|
||
// Fail requests if type is existing, and we specify the key_type param | ||
ctx := context.Background() | ||
_, err = client.Logical().WriteWithContext(ctx, "pki-root/intermediate/generate/existing", map[string]interface{}{ | ||
"common_name": "root myvault.com", | ||
"key_type": "rsa", | ||
}) | ||
require.Error(t, err) | ||
require.Contains(t, err.Error(), "key_type nor key_bits arguments can be set in this mode") | ||
|
||
// Fail requests if type is existing, and we specify the key_bits param | ||
_, err = client.Logical().WriteWithContext(ctx, "pki-root/intermediate/generate/existing", map[string]interface{}{ | ||
"common_name": "root myvault.com", | ||
"key_bits": "2048", | ||
}) | ||
require.Error(t, err) | ||
require.Contains(t, err.Error(), "key_type nor key_bits arguments can be set in this mode") | ||
|
||
// Fail if the specified key does not exist. | ||
_, err = client.Logical().WriteWithContext(ctx, "pki-root/issuers/generate/intermediate/existing", map[string]interface{}{ | ||
"common_name": "root myvault.com", | ||
"key_ref": "my-key1", | ||
}) | ||
require.Error(t, err) | ||
require.Contains(t, err.Error(), "unable to find PKI key for reference: my-key1") | ||
|
||
// Create the first intermediate CA | ||
resp, err := client.Logical().WriteWithContext(ctx, "pki-root/issuers/generate/intermediate/internal", map[string]interface{}{ | ||
"common_name": "root myvault.com", | ||
"key_type": "rsa", | ||
}) | ||
require.NoError(t, err) | ||
// csr1 := resp.Data["csr"] | ||
myKeyId1 := resp.Data["key_id"] | ||
require.NotEmpty(t, myKeyId1) | ||
|
||
// Create the second intermediate CA | ||
resp, err = client.Logical().WriteWithContext(ctx, "pki-root/issuers/generate/intermediate/internal", map[string]interface{}{ | ||
"common_name": "root myvault.com", | ||
"key_type": "rsa", | ||
"key_name": "interkey1", | ||
}) | ||
require.NoError(t, err) | ||
// csr2 := resp.Data["csr"] | ||
myKeyId2 := resp.Data["key_id"] | ||
require.NotEmpty(t, myKeyId2) | ||
|
||
// Create a third intermediate CA re-using key from intermediate CA 1 | ||
resp, err = client.Logical().WriteWithContext(ctx, "pki-root/issuers/generate/intermediate/existing", map[string]interface{}{ | ||
"common_name": "root myvault.com", | ||
"key_ref": myKeyId1, | ||
}) | ||
require.NoError(t, err) | ||
// csr3 := resp.Data["csr"] | ||
myKeyId3 := resp.Data["key_id"] | ||
require.NotEmpty(t, myKeyId3) | ||
|
||
require.NotEqual(t, myKeyId1, myKeyId2) | ||
require.Equal(t, myKeyId1, myKeyId3) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. key name reusue? issuer name reuse (for non roots?) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Validating that the new CA we generated re-used a key that we had previous generated. Will add a clearer message on this test. |
||
|
||
var ( | ||
initTest sync.Once | ||
rsaCAKey string | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what happens if we try generating a root credential with a name which is the Issuer's Key ID? (I'm hoping that this would fail)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes that would fail if an end-user were to try to use an existing id for a Name value. Now if they could predict the uuid we would generate in the future though, that would be a bad day...