Skip to content
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

Backport UI: fix PKI issuer capabilities (#24686) #24706

Merged
merged 1 commit into from
Jan 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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]');
await fillIn('[data-test-component="navigate-input"]', policyLower);

assert
.dom(`[data-test-policy-link="${policyLower}"]`)
Expand All @@ -64,6 +65,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');
}
Loading