Skip to content

Commit

Permalink
UI: fix PKI issuer capabilities (#24686)
Browse files Browse the repository at this point in the history
  • Loading branch information
hashishaw authored Jan 5, 2024
1 parent 8caaa13 commit d5af065
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 50 deletions.
3 changes: 3 additions & 0 deletions changelog/24686.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
ui: fix incorrectly calculated capabilities on PKI issuer endpoints
```
13 changes: 7 additions & 6 deletions ui/app/models/pki/issuer.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,14 @@ export default class PkiIssuerModel extends Model {
@attr importedKeys;
@attr mapping;

@lazyCapabilities(apiPath`${'backend'}/issuer/${'issuerId'}`) issuerPath;
@lazyCapabilities(apiPath`${'backend'}/root/rotate/exported`) rotateExported;
@lazyCapabilities(apiPath`${'backend'}/root/rotate/internal`) rotateInternal;
@lazyCapabilities(apiPath`${'backend'}/root/rotate/existing`) rotateExisting;
@lazyCapabilities(apiPath`${'backend'}/issuer/${'issuerId'}`, 'backend', 'issuerId') issuerPath;
@lazyCapabilities(apiPath`${'backend'}/root/rotate/exported`, 'backend') rotateExported;
@lazyCapabilities(apiPath`${'backend'}/root/rotate/internal`, 'backend') rotateInternal;
@lazyCapabilities(apiPath`${'backend'}/root/rotate/existing`, 'backend') rotateExisting;
@lazyCapabilities(apiPath`${'backend'}/root`, 'backend') deletePath;
@lazyCapabilities(apiPath`${'backend'}/intermediate/cross-sign`) crossSignPath;
@lazyCapabilities(apiPath`${'backend'}/issuer/${'issuerId'}/sign-intermediate`) signIntermediate;
@lazyCapabilities(apiPath`${'backend'}/intermediate/cross-sign`, 'backend') crossSignPath;
@lazyCapabilities(apiPath`${'backend'}/issuer/${'issuerId'}/sign-intermediate`, 'backend', 'issuerId')
signIntermediate;
get canRotateIssuer() {
return (
this.rotateExported.get('canUpdate') !== false ||
Expand Down
109 changes: 66 additions & 43 deletions ui/tests/acceptance/pki/pki-engine-workflow-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import enablePage from 'vault/tests/pages/settings/mount-secret-backend';
import { click, currentURL, fillIn, find, isSettled, visit } from '@ember/test-helpers';
import { SELECTORS } from 'vault/tests/helpers/pki/workflow';
import { adminPolicy, readerPolicy, updatePolicy } from 'vault/tests/helpers/policy-generator/pki';
import { tokenWithPolicy, runCommands } from 'vault/tests/helpers/pki/pki-run-commands';
import { tokenWithPolicy, runCommands, clearRecords } from 'vault/tests/helpers/pki/pki-run-commands';
import { unsupportedPem } from 'vault/tests/helpers/pki/values';

/**
Expand All @@ -25,12 +25,14 @@ module('Acceptance | pki workflow', function (hooks) {
setupApplicationTest(hooks);

hooks.beforeEach(async function () {
this.store = this.owner.lookup('service:store');
await authPage.login();
// Setup PKI engine
const mountPath = `pki-workflow-${uuidv4()}`;
await enablePage.enable('pki', mountPath);
this.mountPath = mountPath;
await logout.visit();
clearRecords(this.store);
});

hooks.afterEach(async function () {
Expand All @@ -40,40 +42,50 @@ module('Acceptance | pki workflow', function (hooks) {
await runCommands([`delete sys/mounts/${this.mountPath}`]);
});

test('empty state messages are correct when PKI not configured', async function (assert) {
assert.expect(21);
const assertEmptyState = (assert, resource) => {
assert.strictEqual(currentURL(), `/vault/secrets/${this.mountPath}/pki/${resource}`);
assert
.dom(SELECTORS.emptyStateTitle)
.hasText(
'PKI not configured',
`${resource} index renders correct empty state title when PKI not configured`
);
assert.dom(SELECTORS.emptyStateLink).hasText('Configure PKI');
assert
.dom(SELECTORS.emptyStateMessage)
.hasText(
`This PKI mount hasn't yet been configured with a certificate issuer.`,
`${resource} index empty state message correct when PKI not configured`
);
};
await authPage.login(this.pkiAdminToken);
await visit(`/vault/secrets/${this.mountPath}/pki/overview`);
assert.strictEqual(currentURL(), `/vault/secrets/${this.mountPath}/pki/overview`);

await click(SELECTORS.rolesTab);
assertEmptyState(assert, 'roles');

await click(SELECTORS.issuersTab);
assertEmptyState(assert, 'issuers');

await click(SELECTORS.certsTab);
assertEmptyState(assert, 'certificates');
await click(SELECTORS.keysTab);
assertEmptyState(assert, 'keys');
await click(SELECTORS.tidyTab);
assertEmptyState(assert, 'tidy');
module('not configured', function (hooks) {
hooks.beforeEach(async function () {
await authPage.login();
const pki_admin_policy = adminPolicy(this.mountPath, 'roles');
this.pkiAdminToken = await tokenWithPolicy(`pki-admin-${this.mountPath}`, pki_admin_policy);
await logout.visit();
clearRecords(this.store);
});

test('empty state messages are correct when PKI not configured', async function (assert) {
assert.expect(21);
const assertEmptyState = (assert, resource) => {
assert.strictEqual(currentURL(), `/vault/secrets/${this.mountPath}/pki/${resource}`);
assert
.dom(SELECTORS.emptyStateTitle)
.hasText(
'PKI not configured',
`${resource} index renders correct empty state title when PKI not configured`
);
assert.dom(SELECTORS.emptyStateLink).hasText('Configure PKI');
assert
.dom(SELECTORS.emptyStateMessage)
.hasText(
`This PKI mount hasn't yet been configured with a certificate issuer.`,
`${resource} index empty state message correct when PKI not configured`
);
};
await authPage.login(this.pkiAdminToken);
await visit(`/vault/secrets/${this.mountPath}/pki/overview`);
assert.strictEqual(currentURL(), `/vault/secrets/${this.mountPath}/pki/overview`);

await click(SELECTORS.rolesTab);
assertEmptyState(assert, 'roles');

await click(SELECTORS.issuersTab);
assertEmptyState(assert, 'issuers');

await click(SELECTORS.certsTab);
assertEmptyState(assert, 'certificates');
await click(SELECTORS.keysTab);
assertEmptyState(assert, 'keys');
await click(SELECTORS.tidyTab);
assertEmptyState(assert, 'tidy');
});
});

module('roles', function (hooks) {
Expand All @@ -91,10 +103,11 @@ module('Acceptance | pki workflow', function (hooks) {
const pki_admin_policy = adminPolicy(this.mountPath, 'roles');
const pki_reader_policy = readerPolicy(this.mountPath, 'roles');
const pki_editor_policy = updatePolicy(this.mountPath, 'roles');
this.pkiRoleReader = await tokenWithPolicy('pki-reader', pki_reader_policy);
this.pkiRoleEditor = await tokenWithPolicy('pki-editor', pki_editor_policy);
this.pkiAdminToken = await tokenWithPolicy('pki-admin', pki_admin_policy);
this.pkiRoleReader = await tokenWithPolicy(`pki-reader-${this.mountPath}`, pki_reader_policy);
this.pkiRoleEditor = await tokenWithPolicy(`pki-editor-${this.mountPath}`, pki_editor_policy);
this.pkiAdminToken = await tokenWithPolicy(`pki-admin-${this.mountPath}`, pki_admin_policy);
await logout.visit();
clearRecords(this.store);
});

test('shows correct items if user has all permissions', async function (assert) {
Expand Down Expand Up @@ -222,10 +235,11 @@ module('Acceptance | pki workflow', function (hooks) {
const pki_admin_policy = adminPolicy(this.mountPath);
const pki_reader_policy = readerPolicy(this.mountPath, 'keys', true);
const pki_editor_policy = updatePolicy(this.mountPath, 'keys');
this.pkiKeyReader = await tokenWithPolicy('pki-reader', pki_reader_policy);
this.pkiKeyEditor = await tokenWithPolicy('pki-editor', pki_editor_policy);
this.pkiAdminToken = await tokenWithPolicy('pki-admin', pki_admin_policy);
this.pkiKeyReader = await tokenWithPolicy(`pki-reader-${this.mountPath}`, pki_reader_policy);
this.pkiKeyEditor = await tokenWithPolicy(`pki-editor-${this.mountPath}`, pki_editor_policy);
this.pkiAdminToken = await tokenWithPolicy(`pki-admin-${this.mountPath}`, pki_admin_policy);
await logout.visit();
clearRecords(this.store);
});

test('shows correct items if user has all permissions', async function (assert) {
Expand Down Expand Up @@ -339,11 +353,14 @@ module('Acceptance | pki workflow', function (hooks) {
module('issuers', function (hooks) {
hooks.beforeEach(async function () {
await authPage.login();
const pki_admin_policy = adminPolicy(this.mountPath);
this.pkiAdminToken = await tokenWithPolicy(`pki-admin-${this.mountPath}`, pki_admin_policy);
// Configure engine with a default issuer
await runCommands([
`write ${this.mountPath}/root/generate/internal common_name="Hashicorp Test" name="Hashicorp Test"`,
]);
await logout.visit();
clearRecords(this.store);
});
test('lists the correct issuer metadata info', async function (assert) {
assert.expect(6);
Expand Down Expand Up @@ -373,7 +390,10 @@ module('Acceptance | pki workflow', function (hooks) {
capabilities = ["deny"]
}
`;
this.token = await tokenWithPolicy('pki-issuer-denied-policy', pki_issuer_denied_policy);
this.token = await tokenWithPolicy(
`pki-issuer-denied-policy-${this.mountPath}`,
pki_issuer_denied_policy
);
await logout.visit();
await authPage.login(this.token);
await visit(`/vault/secrets/${this.mountPath}/pki/overview`);
Expand Down Expand Up @@ -487,7 +507,10 @@ module('Acceptance | pki workflow', function (hooks) {
${adminPolicy(this.mountPath)}
${readerPolicy(this.mountPath, 'config/cluster')}
`;
this.mixedConfigCapabilities = await tokenWithPolicy('pki-reader', mixed_config_policy);
this.mixedConfigCapabilities = await tokenWithPolicy(
`pki-reader-${this.mountPath}`,
mixed_config_policy
);
await logout.visit();
});

Expand Down
4 changes: 3 additions & 1 deletion ui/tests/acceptance/pki/pki-overview-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ import logout from 'vault/tests/pages/logout';
import enablePage from 'vault/tests/pages/settings/mount-secret-backend';
import { click, currentURL, currentRouteName, visit } from '@ember/test-helpers';
import { SELECTORS } from 'vault/tests/helpers/pki/overview';
import { tokenWithPolicy, runCommands } from 'vault/tests/helpers/pki/pki-run-commands';
import { tokenWithPolicy, runCommands, clearRecords } from 'vault/tests/helpers/pki/pki-run-commands';

module('Acceptance | pki overview', function (hooks) {
setupApplicationTest(hooks);

hooks.beforeEach(async function () {
this.store = this.owner.lookup('service:store');
await authPage.login();
// Setup PKI engine
const mountPath = `pki`;
Expand All @@ -42,6 +43,7 @@ module('Acceptance | pki overview', function (hooks) {
this.pkiIssuersList = await tokenWithPolicy('pki-issuers-list', pki_issuers_list_policy);
this.pkiAdminToken = await tokenWithPolicy('pki-admin', pki_admin_policy);
await logout.visit();
clearRecords(this.store);
});

hooks.afterEach(async function () {
Expand Down
2 changes: 2 additions & 0 deletions ui/tests/acceptance/policies-acl-old-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ module('Acceptance | policies (old)', function (hooks) {
assert.dom('[data-test-policy-name]').hasText(policyLower, 'displays the policy name on the show page');
assert.dom('[data-test-flash-message].is-info').doesNotExist('no flash message is displayed on save');
await click('[data-test-policy-list-link] a');
await fillIn('[data-test-component="navigate-input"]', policyLower);
assert
.dom(`[data-test-policy-link="${policyLower}"]`)
.exists({ count: 1 }, 'new policy shown in the list');
Expand All @@ -63,6 +64,7 @@ module('Acceptance | policies (old)', function (hooks) {
`/vault/policies/acl`,
'navigates to policy list on successful deletion'
);
await fillIn('[data-test-component="navigate-input"]', policyLower);
assert
.dom(`[data-test-policy-item="${policyLower}"]`)
.doesNotExist('deleted policy is not shown in the list');
Expand Down
18 changes: 18 additions & 0 deletions ui/tests/helpers/pki/pki-run-commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,21 @@ export const runCommands = async function (commands) {
throw error;
}
};

// Clears pki-related data and capabilities so that admin
// capabilities from setup don't rollover
export function clearRecords(store) {
store.unloadAll('pki/action');
store.unloadAll('pki/issuer');
store.unloadAll('pki/key');
store.unloadAll('pki/role');
store.unloadAll('pki/sign-intermediate');
store.unloadAll('pki/tidy');
store.unloadAll('pki/config/urls');
store.unloadAll('pki/config/crl');
store.unloadAll('pki/config/cluster');
store.unloadAll('pki/config/acme');
store.unloadAll('pki/certificate/generate');
store.unloadAll('pki/certificate/sign');
store.unloadAll('capabilities');
}

0 comments on commit d5af065

Please sign in to comment.