UI: refactor to use pki/action model for importing a pem bundle (#19425)
* rename component test file * rename component * rename file again.. * rename component file and remove import from issuer adapter * rename hbs file * update to new component name, use pki/action * update test selectors * update tests * update workflow test * add useIssuer to adapter options
This commit is contained in:
parent
87c9649515
commit
a22bb9bfcc
|
@ -26,16 +26,6 @@ export default class PkiIssuerAdapter extends ApplicationAdapter {
|
|||
}
|
||||
}
|
||||
|
||||
createRecord(store, type, snapshot) {
|
||||
let url = this.urlForQuery(this._getBackend(snapshot));
|
||||
if (snapshot.adapterOptions.import) {
|
||||
url = `${url}/import/bundle`;
|
||||
}
|
||||
return this.ajax(url, 'POST', { data: this.serialize(snapshot) }).then((resp) => {
|
||||
return resp;
|
||||
});
|
||||
}
|
||||
|
||||
updateRecord(store, type, snapshot) {
|
||||
const { issuerId } = snapshot.record;
|
||||
const backend = this._getBackend(snapshot);
|
||||
|
|
|
@ -28,6 +28,10 @@ export default class PkiActionModel extends Model {
|
|||
|
||||
/* actionType import */
|
||||
@attr('string') pemBundle;
|
||||
// readonly attrs returned after importing
|
||||
@attr importedIssuers;
|
||||
@attr importedKeys;
|
||||
@attr mapping;
|
||||
|
||||
/* actionType generate-root */
|
||||
@attr('string', {
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
</div>
|
||||
{{/unless}}
|
||||
{{#if (eq @config.actionType "import")}}
|
||||
<PkiCaCertificateImport
|
||||
<PkiImportPemBundle
|
||||
@model={{@config}}
|
||||
@onCancel={{transition-to "vault.cluster.secrets.backend.pki.overview"}}
|
||||
@onSave={{transition-to "vault.cluster.secrets.backend.pki.issuers"}}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<label class="title has-padding-top is-5">
|
||||
Certificate parameters
|
||||
</label>
|
||||
<form {{on "submit" (perform this.submitForm)}} data-test-pki-ca-cert-import-form>
|
||||
<form {{on "submit" (perform this.submitForm)}} data-test-pki-import-pem-bundle-form>
|
||||
<MessageError @errorMessage={{this.errorBanner}} class="has-top-margin-s" />
|
||||
<div class="box is-sideless is-fullwidth is-marginless has-top-padding-l">
|
||||
<TextFile @onChange={{this.onFileUploaded}} @label="PEM Bundle" />
|
||||
|
@ -17,7 +17,7 @@
|
|||
type="submit"
|
||||
class="button is-primary {{if this.submitForm.isRunning 'is-loading'}}"
|
||||
disabled={{this.submitForm.isRunning}}
|
||||
data-test-pki-ca-cert-import
|
||||
data-test-pki-import-pem-bundle
|
||||
>
|
||||
Import issuer
|
||||
</button>
|
|
@ -6,17 +6,16 @@ import { task } from 'ember-concurrency';
|
|||
import { tracked } from '@glimmer/tracking';
|
||||
import { waitFor } from '@ember/test-waiters';
|
||||
import errorMessage from 'vault/utils/error-message';
|
||||
import PkiIssuerModel from 'vault/models/pki/issuer';
|
||||
import PkiActionModel from 'vault/models/pki/action';
|
||||
|
||||
/**
|
||||
* @module PkiCaCertificateImport
|
||||
* PkiCaCertificateImport components are used to import PKI CA certificates and keys via pem_bundle.
|
||||
* @module PkiImportPemBundle
|
||||
* PkiImportPemBundle components are used to import PKI CA certificates and keys via pem_bundle.
|
||||
* https://github.com/hashicorp/vault/blob/main/website/content/api-docs/secret/pki.mdx#import-ca-certificates-and-keys
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* <PkiCaCertificateImport @model={{this.model}} />
|
||||
* <PkiImportPemBundle @model={{this.model}} />
|
||||
* ```
|
||||
*
|
||||
* @param {Object} model - certificate model from route
|
||||
|
@ -24,14 +23,18 @@ import PkiActionModel from 'vault/models/pki/action';
|
|||
* @callback onSubmit - Callback triggered on submit success.
|
||||
*/
|
||||
|
||||
interface AdapterOptions {
|
||||
actionType: string;
|
||||
useIssuer: boolean | undefined;
|
||||
}
|
||||
interface Args {
|
||||
onSave: CallableFunction;
|
||||
onCancel: CallableFunction;
|
||||
model: PkiIssuerModel | PkiActionModel;
|
||||
adapterOptions: object | undefined;
|
||||
model: PkiActionModel;
|
||||
adapterOptions: AdapterOptions;
|
||||
}
|
||||
|
||||
export default class PkiCaCertificateImport extends Component<Args> {
|
||||
export default class PkiImportPemBundle extends Component<Args> {
|
||||
@service declare readonly flashMessages: FlashMessageService;
|
||||
|
||||
@tracked errorBanner = '';
|
||||
|
@ -42,7 +45,7 @@ export default class PkiCaCertificateImport extends Component<Args> {
|
|||
event.preventDefault();
|
||||
try {
|
||||
yield this.args.model.save({ adapterOptions: this.args.adapterOptions });
|
||||
this.flashMessages.success('Successfully imported certificate.');
|
||||
this.flashMessages.success('Successfully imported data.');
|
||||
this.args.onSave();
|
||||
} catch (error) {
|
||||
this.errorBanner = errorMessage(error);
|
|
@ -195,8 +195,8 @@ export default class PkiIssuerCrossSign extends Component {
|
|||
// the newly issued intermediate CA, so that they can do recovery
|
||||
// as they'd like.
|
||||
const issuerId = await this.store
|
||||
.createRecord('pki/issuer', { pemBundle: signedCaChain })
|
||||
.save({ adapterOptions: { import: true, mount: intMount } })
|
||||
.createRecord('pki/action', { pemBundle: signedCaChain })
|
||||
.save({ adapterOptions: { actionType: 'import', mount: intMount, useIssuer: true } })
|
||||
.then((importedIssuer) => {
|
||||
return Object.keys(importedIssuer.mapping).find(
|
||||
// matching key is the issuer_id
|
||||
|
|
|
@ -7,7 +7,7 @@ export default class PkiIssuersImportRoute extends PkiIssuersIndexRoute {
|
|||
@service store;
|
||||
|
||||
model() {
|
||||
return this.store.createRecord('pki/issuer');
|
||||
return this.store.createRecord('pki/action');
|
||||
}
|
||||
|
||||
setupController(controller, resolvedModel) {
|
||||
|
|
|
@ -8,10 +8,9 @@
|
|||
</h1>
|
||||
</p.levelLeft>
|
||||
</PageHeader>
|
||||
|
||||
<PkiCaCertificateImport
|
||||
<PkiImportPemBundle
|
||||
@model={{this.model}}
|
||||
@onCancel={{transition-to "vault.cluster.secrets.backend.pki.issuers.index"}}
|
||||
@onSave={{transition-to "vault.cluster.secrets.backend.pki.issuers.index"}}
|
||||
@adapterOptions={{hash import=true}}
|
||||
@adapterOptions={{hash actionType="import" useIssuer=true}}
|
||||
/>
|
|
@ -163,18 +163,18 @@ module('Acceptance | pki engine route cleanup test', function (hooks) {
|
|||
await visit(`/vault/secrets/${this.mountPath}/pki/overview`);
|
||||
await click(SELECTORS.issuersTab);
|
||||
issuers = this.store.peekAll('pki/issuer');
|
||||
assert.strictEqual(issuers.length, 0, 'No issuers exist yet');
|
||||
assert.strictEqual(issuers.length, 0, 'No issuer models exist yet');
|
||||
await click(SELECTORS.importIssuerLink);
|
||||
issuers = this.store.peekAll('pki/issuer');
|
||||
assert.strictEqual(issuers.length, 1, 'Issuer model created');
|
||||
issuers = this.store.peekAll('pki/action');
|
||||
assert.strictEqual(issuers.length, 1, 'Action model created');
|
||||
const issuer = issuers.objectAt(0);
|
||||
assert.true(issuer.hasDirtyAttributes, 'Issuer has dirty attrs');
|
||||
assert.true(issuer.isNew, 'Issuer is new');
|
||||
assert.true(issuer.hasDirtyAttributes, 'Action has dirty attrs');
|
||||
assert.true(issuer.isNew, 'Action is new');
|
||||
// Exit
|
||||
await click('[data-test-pki-ca-cert-cancel]');
|
||||
assert.strictEqual(currentURL(), `/vault/secrets/${this.mountPath}/pki/issuers`);
|
||||
issuers = this.store.peekAll('pki/issuer');
|
||||
assert.strictEqual(issuers.length, 0, 'Issuer is removed from store');
|
||||
issuers = this.store.peekAll('pki/action');
|
||||
assert.strictEqual(issuers.length, 0, 'Action is removed from store');
|
||||
});
|
||||
test('import issuer exit via breadcrumb', async function (assert) {
|
||||
let issuers;
|
||||
|
@ -184,15 +184,15 @@ module('Acceptance | pki engine route cleanup test', function (hooks) {
|
|||
issuers = this.store.peekAll('pki/issuer');
|
||||
assert.strictEqual(issuers.length, 0, 'No issuers exist yet');
|
||||
await click(SELECTORS.importIssuerLink);
|
||||
issuers = this.store.peekAll('pki/issuer');
|
||||
assert.strictEqual(issuers.length, 1, 'Issuer model created');
|
||||
issuers = this.store.peekAll('pki/action');
|
||||
assert.strictEqual(issuers.length, 1, 'Action model created');
|
||||
const issuer = issuers.objectAt(0);
|
||||
assert.true(issuer.hasDirtyAttributes, 'Issuer has dirty attrs');
|
||||
assert.true(issuer.isNew, 'Issuer is new');
|
||||
assert.true(issuer.hasDirtyAttributes, 'Action model has dirty attrs');
|
||||
assert.true(issuer.isNew, 'Action model is new');
|
||||
// Exit
|
||||
await click(SELECTORS.overviewBreadcrumb);
|
||||
assert.strictEqual(currentURL(), `/vault/secrets/${this.mountPath}/pki/overview`);
|
||||
issuers = this.store.peekAll('pki/issuer');
|
||||
issuers = this.store.peekAll('pki/action');
|
||||
assert.strictEqual(issuers.length, 0, 'Issuer is removed from store');
|
||||
});
|
||||
test('generate root exit via cancel', async function (assert) {
|
||||
|
|
|
@ -94,7 +94,7 @@ module('Acceptance | pki workflow', function (hooks) {
|
|||
assert.dom(SELECTORS.configuration.emptyState).doesNotExist();
|
||||
await click('[data-test-text-toggle]');
|
||||
await fillIn('[data-test-text-file-textarea]', this.pemBundle);
|
||||
await click('[data-test-pki-ca-cert-import]');
|
||||
await click('[data-test-pki-import-pem-bundle]');
|
||||
assert.strictEqual(
|
||||
currentURL(),
|
||||
`/vault/secrets/${this.mountPath}/pki/issuers`,
|
||||
|
|
|
@ -9,7 +9,7 @@ export const SELECTORS = {
|
|||
// pki-generate-root
|
||||
...GENERATE_ROOT,
|
||||
// pki-ca-cert-import
|
||||
importForm: '[data-test-pki-ca-cert-import-form]',
|
||||
importForm: '[data-test-pki-import-pem-bundle-form]',
|
||||
// generate-intermediate
|
||||
csrDetails: '[data-test-generate-csr-result]',
|
||||
};
|
||||
|
|
|
@ -6,14 +6,14 @@ import { setupEngine } from 'ember-engines/test-support';
|
|||
import { setupMirage } from 'ember-cli-mirage/test-support';
|
||||
import { issuerPemBundle } from 'vault/tests/helpers/pki/values';
|
||||
|
||||
module('Integration | Component | pki issuer import', function (hooks) {
|
||||
module('Integration | Component | PkiImportPemBundle', function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
setupMirage(hooks);
|
||||
setupEngine(hooks, 'pki'); // https://github.com/ember-engines/ember-engines/pull/653
|
||||
|
||||
hooks.beforeEach(function () {
|
||||
this.store = this.owner.lookup('service:store');
|
||||
this.model = this.store.createRecord('pki/issuer');
|
||||
this.model = this.store.createRecord('pki/action');
|
||||
this.backend = 'pki-test';
|
||||
this.secretMountPath = this.owner.lookup('service:secret-mount-path');
|
||||
this.secretMountPath.currentPath = this.backend;
|
||||
|
@ -24,7 +24,7 @@ module('Integration | Component | pki issuer import', function (hooks) {
|
|||
assert.expect(3);
|
||||
await render(
|
||||
hbs`
|
||||
<PkiCaCertificateImport
|
||||
<PkiImportPemBundle
|
||||
@model={{this.model}}
|
||||
@onCancel={{this.onCancel}}
|
||||
@onSave={{this.onSave}}
|
||||
|
@ -33,7 +33,7 @@ module('Integration | Component | pki issuer import', function (hooks) {
|
|||
{ owner: this.engine }
|
||||
);
|
||||
|
||||
assert.dom('[data-test-pki-ca-cert-import-form]').exists('renders form');
|
||||
assert.dom('[data-test-pki-import-pem-bundle-form]').exists('renders form');
|
||||
assert.dom('[data-test-component="text-file"]').exists('renders text file input');
|
||||
await click('[data-test-text-toggle]');
|
||||
await fillIn('[data-test-text-file-textarea]', this.pemBundle);
|
||||
|
@ -41,7 +41,7 @@ module('Integration | Component | pki issuer import', function (hooks) {
|
|||
});
|
||||
|
||||
test('it sends correct payload to import endpoint', async function (assert) {
|
||||
assert.expect(3);
|
||||
assert.expect(4);
|
||||
this.server.post(`/${this.backend}/issuers/import/bundle`, (schema, req) => {
|
||||
assert.ok(true, 'Request made to the correct endpoint to import issuer');
|
||||
const request = JSON.parse(req.requestBody);
|
||||
|
@ -59,11 +59,11 @@ module('Integration | Component | pki issuer import', function (hooks) {
|
|||
|
||||
await render(
|
||||
hbs`
|
||||
<PkiCaCertificateImport
|
||||
<PkiImportPemBundle
|
||||
@model={{this.model}}
|
||||
@onCancel={{this.onCancel}}
|
||||
@onSave={{this.onSave}}
|
||||
@adapterOptions={{hash import=true}}
|
||||
@adapterOptions={{hash actionType="import" useIssuer=true}}
|
||||
/>
|
||||
`,
|
||||
{ owner: this.engine }
|
||||
|
@ -72,7 +72,42 @@ module('Integration | Component | pki issuer import', function (hooks) {
|
|||
await click('[data-test-text-toggle]');
|
||||
await fillIn('[data-test-text-file-textarea]', this.pemBundle);
|
||||
assert.strictEqual(this.model.pemBundle, this.pemBundle);
|
||||
await click('[data-test-pki-ca-cert-import]');
|
||||
await click('[data-test-pki-import-pem-bundle]');
|
||||
});
|
||||
|
||||
test('it hits correct endpoint when userIssuer=false', async function (assert) {
|
||||
assert.expect(4);
|
||||
this.server.post(`${this.backend}/config/ca`, (schema, req) => {
|
||||
assert.ok(true, 'Request made to the correct endpoint to import issuer');
|
||||
const request = JSON.parse(req.requestBody);
|
||||
assert.propEqual(
|
||||
request,
|
||||
{
|
||||
pem_bundle: `${this.pemBundle}`,
|
||||
},
|
||||
'sends params in correct type'
|
||||
);
|
||||
return {};
|
||||
});
|
||||
|
||||
this.onSave = () => assert.ok(true, 'onSave callback fires on save success');
|
||||
|
||||
await render(
|
||||
hbs`
|
||||
<PkiImportPemBundle
|
||||
@model={{this.model}}
|
||||
@onCancel={{this.onCancel}}
|
||||
@onSave={{this.onSave}}
|
||||
@adapterOptions={{hash actionType="import" useIssuer=false}}
|
||||
/>
|
||||
`,
|
||||
{ owner: this.engine }
|
||||
);
|
||||
|
||||
await click('[data-test-text-toggle]');
|
||||
await fillIn('[data-test-text-file-textarea]', this.pemBundle);
|
||||
assert.strictEqual(this.model.pemBundle, this.pemBundle);
|
||||
await click('[data-test-pki-import-pem-bundle]');
|
||||
});
|
||||
|
||||
test('it should unload record on cancel', async function (assert) {
|
||||
|
@ -80,7 +115,7 @@ module('Integration | Component | pki issuer import', function (hooks) {
|
|||
this.onCancel = () => assert.ok(true, 'onCancel callback fires');
|
||||
await render(
|
||||
hbs`
|
||||
<PkiCaCertificateImport
|
||||
<PkiImportPemBundle
|
||||
@model={{this.model}}
|
||||
@onCancel={{this.onCancel}}
|
||||
@onSave={{this.onSave}}
|
|
@ -225,4 +225,26 @@ module('Unit | Adapter | pki/action', function (hooks) {
|
|||
.save(adapterOptions);
|
||||
});
|
||||
});
|
||||
|
||||
module('actionType sign-intermediate', function () {
|
||||
test('it overrides backend when adapter options specify a mount', async function (assert) {
|
||||
assert.expect(1);
|
||||
const mount = 'foo';
|
||||
const issuerRef = 'ref';
|
||||
const adapterOptions = {
|
||||
adapterOptions: { actionType: 'sign-intermediate', mount, issuerRef },
|
||||
};
|
||||
|
||||
this.server.post(`${mount}/issuer/${issuerRef}/sign-intermediate`, () => {
|
||||
assert.ok(true, 'request made to correct mount');
|
||||
return {};
|
||||
});
|
||||
|
||||
await this.store
|
||||
.createRecord('pki/action', {
|
||||
csr: '---BEGIN REQUEST---',
|
||||
})
|
||||
.save(adapterOptions);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue