diff --git a/builtin/logical/pki/backend_test.go b/builtin/logical/pki/backend_test.go index b5d43ed1c7..484386753f 100644 --- a/builtin/logical/pki/backend_test.go +++ b/builtin/logical/pki/backend_test.go @@ -2438,13 +2438,27 @@ func TestBackend_Root_Idempotency(t *testing.T) { require.NoError(t, err) require.NotNil(t, resp, "expected ca info") + firstMapping := resp.Data["mapping"].(map[string]string) firstImportedKeys := resp.Data["imported_keys"].([]string) firstImportedIssuers := resp.Data["imported_issuers"].([]string) + firstExistingKeys := resp.Data["existing_keys"].([]string) + firstExistingIssuers := resp.Data["existing_issuers"].([]string) require.NotContains(t, firstImportedKeys, keyId1) require.NotContains(t, firstImportedKeys, keyId2) require.NotContains(t, firstImportedIssuers, issuerId1) require.NotContains(t, firstImportedIssuers, issuerId2) + require.Empty(t, firstExistingKeys) + require.Empty(t, firstExistingIssuers) + require.NotEmpty(t, firstMapping) + require.Equal(t, 1, len(firstMapping)) + + var issuerId3 string + var keyId3 string + for i, k := range firstMapping { + issuerId3 = i + keyId3 = k + } // Performing this again should result in no key/issuer ids being imported/generated. resp, err = CBWrite(b, s, "config/ca", map[string]interface{}{ @@ -2452,11 +2466,17 @@ func TestBackend_Root_Idempotency(t *testing.T) { }) require.NoError(t, err) require.NotNil(t, resp, "expected ca info") + secondMapping := resp.Data["mapping"].(map[string]string) secondImportedKeys := resp.Data["imported_keys"] secondImportedIssuers := resp.Data["imported_issuers"] + secondExistingKeys := resp.Data["existing_keys"] + secondExistingIssuers := resp.Data["existing_issuers"] - require.Nil(t, secondImportedKeys) - require.Nil(t, secondImportedIssuers) + require.Empty(t, secondImportedKeys) + require.Empty(t, secondImportedIssuers) + require.Contains(t, secondExistingKeys, keyId3) + require.Contains(t, secondExistingIssuers, issuerId3) + require.Equal(t, 1, len(secondMapping)) resp, err = CBDelete(b, s, "root") require.NoError(t, err) diff --git a/builtin/logical/pki/path_config_ca.go b/builtin/logical/pki/path_config_ca.go index 74fa3099e7..e77386f4b1 100644 --- a/builtin/logical/pki/path_config_ca.go +++ b/builtin/logical/pki/path_config_ca.go @@ -51,6 +51,16 @@ secret key and certificate.`, Description: "Net-new issuers imported as a part of this request", Required: true, }, + "existing_keys": { + Type: framework.TypeCommaStringSlice, + Description: "Existing keys specified as part of the import bundle of this request", + Required: true, + }, + "existing_issuers": { + Type: framework.TypeCommaStringSlice, + Description: "Existing issuers specified as part of the import bundle of this request", + Required: true, + }, }, }}, }, diff --git a/builtin/logical/pki/path_intermediate.go b/builtin/logical/pki/path_intermediate.go index 32b7c3290f..1a685630e6 100644 --- a/builtin/logical/pki/path_intermediate.go +++ b/builtin/logical/pki/path_intermediate.go @@ -68,6 +68,16 @@ appended to the bundle.`, Description: "Net-new issuers imported as a part of this request", Required: true, }, + "existing_keys": { + Type: framework.TypeCommaStringSlice, + Description: "Existing keys specified as part of the import bundle of this request", + Required: true, + }, + "existing_issuers": { + Type: framework.TypeCommaStringSlice, + Description: "Existing issuers specified as part of the import bundle of this request", + Required: true, + }, }, }}, }, diff --git a/builtin/logical/pki/path_manage_issuers.go b/builtin/logical/pki/path_manage_issuers.go index 285c254f29..0a4a4bc8cb 100644 --- a/builtin/logical/pki/path_manage_issuers.go +++ b/builtin/logical/pki/path_manage_issuers.go @@ -243,6 +243,16 @@ secret-key (optional) and certificates.`, Description: "Net-new issuers imported as a part of this request", Required: true, }, + "existing_keys": { + Type: framework.TypeCommaStringSlice, + Description: "Existing keys specified as part of the import bundle of this request", + Required: true, + }, + "existing_issuers": { + Type: framework.TypeCommaStringSlice, + Description: "Existing issuers specified as part of the import bundle of this request", + Required: true, + }, }, }}, }, @@ -308,6 +318,8 @@ func (b *backend) pathImportIssuers(ctx context.Context, req *logical.Request, d var createdKeys []string var createdIssuers []string + var existingKeys []string + var existingIssuers []string issuerKeyMap := make(map[string]string) // Rather than using certutil.ParsePEMBundle (which restricts the @@ -364,6 +376,8 @@ func (b *backend) pathImportIssuers(ctx context.Context, req *logical.Request, d if !existing { createdKeys = append(createdKeys, key.ID.String()) + } else { + existingKeys = append(existingKeys, key.ID.String()) } } @@ -376,6 +390,8 @@ func (b *backend) pathImportIssuers(ctx context.Context, req *logical.Request, d issuerKeyMap[cert.ID.String()] = cert.KeyID.String() if !existing { createdIssuers = append(createdIssuers, cert.ID.String()) + } else { + existingIssuers = append(existingIssuers, cert.ID.String()) } } @@ -384,6 +400,8 @@ func (b *backend) pathImportIssuers(ctx context.Context, req *logical.Request, d "mapping": issuerKeyMap, "imported_keys": createdKeys, "imported_issuers": createdIssuers, + "existing_keys": existingKeys, + "existing_issuers": existingIssuers, }, } diff --git a/changelog/20441.txt b/changelog/20441.txt new file mode 100644 index 0000000000..628784883f --- /dev/null +++ b/changelog/20441.txt @@ -0,0 +1,3 @@ +```release-note:improvement +secrets/pki: Allow determining existing issuers and keys on import. +``` diff --git a/website/content/api-docs/secret/pki.mdx b/website/content/api-docs/secret/pki.mdx index 088168b34e..129ef5541d 100644 --- a/website/content/api-docs/secret/pki.mdx +++ b/website/content/api-docs/secret/pki.mdx @@ -2042,7 +2042,10 @@ issuer or key entry; duplicates (including with existing keys) will be ignored. The response will indicate what issuers and keys were created as part of this request (in the `imported_issuers` and `imported_keys`), along with a `mapping` field, indicating which keys belong to which issuers (including from already -imported entries present in the same bundle). +imported entries present in the same bundle). In Vault 1.14.0, the response +also contains an `existing_issuers` and `existing_keys` fields, which specifies +the issuer and key IDs of any entries in the bundle that already +existed within this mount. | Method | Path | Allows private keys | Request Parameter | | :----- | :----------------------------- | :------------------ | :---------------- | @@ -2109,7 +2112,9 @@ JSON-formatted, with newlines replaced with `\n`, like so: "imported_keys": ["97be2525-717a-e2f7-88da-0a20e11aad88"], "mapping": { "1ae8ce9d-2f70-0761-a465-8c9840a247a2": "97be2525-717a-e2f7-88da-0a20e11aad88" - } + }, + "existing_issuers": [], + "existing_keys": [] } } ```