-
-
+{{#if @model.id}}
+ {{! Model only has ID once form has been submitted and saved }}
+
+
+
+
+ Copy the CSR below for a parent issuer to sign and then import the signed certificate back into this mount.
+ {{#if @model.privateKey}}
+ The
+ private_key
+ is only available once. Make sure you copy and save it now.
+ {{/if}}
+
+ {{#each this.showFields as |fieldName|}}
+ {{#let (find-by "name" fieldName @model.allFields) as |attr|}}
+ {{#let (get @model attr.name) as |value|}}
+
+ {{#if (and attr.options.masked value)}}
+
+ {{else if (eq attr.name "keyId")}}
+
+ {{@model.keyId}}
+
+ {{else}}
+ {{! this block only ever renders privateKey and privateKeyType }}
+ {{or value "internal"}}
+ {{/if}}
+
+ {{/let}}
+ {{/let}}
+ {{/each}}
- {{#if this.alert}}
+
+
+
+{{else}}
+
+{{/if}}
\ No newline at end of file
diff --git a/ui/lib/pki/addon/components/pki-generate-csr.ts b/ui/lib/pki/addon/components/pki-generate-csr.ts
index 736265f0b0..ef8795cbfd 100644
--- a/ui/lib/pki/addon/components/pki-generate-csr.ts
+++ b/ui/lib/pki/addon/components/pki-generate-csr.ts
@@ -12,11 +12,11 @@ import errorMessage from 'vault/utils/error-message';
interface Args {
model: PkiActionModel;
useIssuer: boolean;
- onSave: CallableFunction;
+ onComplete: CallableFunction;
onCancel: CallableFunction;
}
-export default class PkiGenerateIntermediateComponent extends Component {
+export default class PkiGenerateCsrComponent extends Component {
@service declare readonly flashMessages: FlashMessageService;
@tracked modelValidations = null;
@@ -24,6 +24,8 @@ export default class PkiGenerateIntermediateComponent extends Component {
@tracked alert: string | null = null;
formFields;
+ // fields rendered after CSR generation
+ showFields = ['csr', 'keyId', 'privateKey', 'privateKeyType'];
constructor(owner: unknown, args: Args) {
super(owner, args);
@@ -57,13 +59,12 @@ export default class PkiGenerateIntermediateComponent extends Component {
*save(event: Event): Generator> {
event.preventDefault();
try {
- const { model, onSave } = this.args;
+ const { model } = this.args;
const { isValid, state, invalidFormMessage } = model.validate();
if (isValid) {
const useIssuer = yield this.getCapability();
yield model.save({ adapterOptions: { actionType: 'generate-csr', useIssuer } });
this.flashMessages.success('Successfully generated CSR.');
- onSave();
} else {
this.modelValidations = state;
this.alert = invalidFormMessage;
diff --git a/ui/lib/pki/addon/components/pki-sign-intermediate-form.hbs b/ui/lib/pki/addon/components/pki-sign-intermediate-form.hbs
index 2e4c5301b2..6a2581e8d3 100644
--- a/ui/lib/pki/addon/components/pki-sign-intermediate-form.hbs
+++ b/ui/lib/pki/addon/components/pki-sign-intermediate-form.hbs
@@ -11,7 +11,7 @@
{{#each this.showFields as |fieldName|}}
{{#let (find-by "name" fieldName @model.allFields) as |attr|}}
-
+
{{#if (and attr.options.masked (get @model attr.name))}}
{{else if (eq attr.name "serialNumber")}}
diff --git a/ui/lib/pki/addon/templates/issuers/generate-intermediate.hbs b/ui/lib/pki/addon/templates/issuers/generate-intermediate.hbs
index 3a497c4c3d..5b0096268d 100644
--- a/ui/lib/pki/addon/templates/issuers/generate-intermediate.hbs
+++ b/ui/lib/pki/addon/templates/issuers/generate-intermediate.hbs
@@ -12,5 +12,5 @@
\ No newline at end of file
diff --git a/ui/lib/pki/addon/templates/keys/index.hbs b/ui/lib/pki/addon/templates/keys/index.hbs
index e5a4193e81..d956232e9d 100644
--- a/ui/lib/pki/addon/templates/keys/index.hbs
+++ b/ui/lib/pki/addon/templates/keys/index.hbs
@@ -8,7 +8,7 @@
}}
@isEngine={{true}}
/>
-{{#if this.model.hasConfig}}
+{{#if (or this.model.hasConfig this.model.keyModels)}}
assert.ok(true, 'onSave action fires');
-
- await render(hbs``, {
+ await render(hbs``, {
owner: this.engine,
});
@@ -55,6 +54,9 @@ module('Integration | Component | PkiGenerateCsr', function (hooks) {
await fillIn('[data-test-input="type"]', 'exported');
await fillIn('[data-test-input="commonName"]', 'foo');
await click('[data-test-save]');
+
+ const savedRecord = this.store.peekAll('pki/action').firstObject;
+ assert.false(savedRecord.isNew, 'record is saved');
});
test('it should display validation errors', async function (assert) {
@@ -78,4 +80,65 @@ module('Integration | Component | PkiGenerateCsr', function (hooks) {
await click('[data-test-cancel]');
});
+
+ test('it should show generated CSR for type=exported', async function (assert) {
+ assert.expect(6);
+ this.model.id = '1235-someId';
+ this.model.csr = '-----BEGIN CERTIFICATE REQUEST-----...-----END CERTIFICATE REQUEST-----';
+ this.model.keyId = '9179de78-1275-a1cf-ebb0-a4eb2e376636';
+ this.model.privateKey = '-----BEGIN RSA PRIVATE KEY-----...-----END RSA PRIVATE KEY-----';
+ this.model.privateKeyType = 'rsa';
+ this.onComplete = () => assert.ok(true, 'onComplete action fires');
+
+ await render(hbs``, {
+ owner: this.engine,
+ });
+ assert
+ .dom('[data-test-alert-banner="alert"]')
+ .hasText(
+ 'Next steps Copy the CSR below for a parent issuer to sign and then import the signed certificate back into this mount. The private_key is only available once. Make sure you copy and save it now.',
+ 'renders Next steps alert banner'
+ );
+ assert
+ .dom('[data-test-value-div="CSR"] [data-test-masked-input] button')
+ .hasAttribute('data-clipboard-text', this.model.csr, 'it renders copyable csr');
+ assert
+ .dom('[data-test-value-div="Key ID"] button')
+ .hasAttribute('data-clipboard-text', this.model.keyId, 'it renders copyable key_id');
+ assert
+ .dom('[data-test-value-div="Private key"] [data-test-masked-input] button')
+ .hasAttribute('data-clipboard-text', this.model.privateKey, 'it renders copyable private_key');
+ assert
+ .dom('[data-test-value-div="Private key type"]')
+ .hasText(this.model.privateKeyType, 'renders private_key_type');
+ await click('[data-test-done]');
+ });
+
+ test('it should show generated CSR for type=internal', async function (assert) {
+ assert.expect(5);
+ this.model.id = '1235-someId';
+ this.model.csr = '-----BEGIN CERTIFICATE REQUEST-----...-----END CERTIFICATE REQUEST-----';
+ this.model.keyId = '9179de78-1275-a1cf-ebb0-a4eb2e376636';
+ this.onComplete = () => {};
+
+ await render(hbs``, {
+ owner: this.engine,
+ });
+ assert
+ .dom('[data-test-alert-banner="alert"]')
+ .hasText(
+ 'Next steps Copy the CSR below for a parent issuer to sign and then import the signed certificate back into this mount.',
+ 'renders Next steps alert banner'
+ );
+ assert
+ .dom('[data-test-value-div="CSR"] [data-test-masked-input] button')
+ .hasAttribute('data-clipboard-text', this.model.csr, 'it renders copyable csr');
+ assert
+ .dom('[data-test-value-div="Key ID"] button')
+ .hasAttribute('data-clipboard-text', this.model.keyId, 'it renders copyable key_id');
+ assert.dom('[data-test-value-div="Private key"]').hasText('internal', 'does not render private key');
+ assert
+ .dom('[data-test-value-div="Private key type"]')
+ .hasText('internal', 'does not render private key type');
+ });
});
diff --git a/ui/tests/integration/components/pki-generate-root-test.js b/ui/tests/integration/components/pki/pki-generate-root-test.js
similarity index 100%
rename from ui/tests/integration/components/pki-generate-root-test.js
rename to ui/tests/integration/components/pki/pki-generate-root-test.js
diff --git a/ui/tests/integration/components/pki-role-generate-test.js b/ui/tests/integration/components/pki/pki-role-generate-test.js
similarity index 100%
rename from ui/tests/integration/components/pki-role-generate-test.js
rename to ui/tests/integration/components/pki/pki-role-generate-test.js
diff --git a/ui/tests/integration/components/pki-sign-intermediate-form-test.js b/ui/tests/integration/components/pki/pki-sign-intermediate-form-test.js
similarity index 100%
rename from ui/tests/integration/components/pki-sign-intermediate-form-test.js
rename to ui/tests/integration/components/pki/pki-sign-intermediate-form-test.js