mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-02 03:27:54 +00:00
* feature(ember-exam): add ember-exam to split ui tests and run them in parallel * update yarn.lock * update package.json scripts * test(oidc): comment out test with race condition in oidc test * chore(test): use 127.0.0.1 in testem config and add uuid to pki mount path * test(kv-workflow): make policy creation unique per-test * chore(test): use --preserve-test-name so flakey test reporting is preserved * yarn test:filter runs ember test instead of exam for easier filtering * fix kv control group tests --------- Co-authored-by: Chelsea Shaw <cshaw@hashicorp.com>
320 lines
13 KiB
JavaScript
320 lines
13 KiB
JavaScript
/**
|
|
* Copyright (c) HashiCorp, Inc.
|
|
* SPDX-License-Identifier: BUSL-1.1
|
|
*/
|
|
|
|
import { module, test } from 'qunit';
|
|
import { v4 as uuidv4 } from 'uuid';
|
|
import { setupApplicationTest } from 'vault/tests/helpers';
|
|
import authPage from 'vault/tests/pages/auth';
|
|
import { deleteEngineCmd, mountEngineCmd, runCmd, tokenWithPolicyCmd } from 'vault/tests/helpers/commands';
|
|
import { personas } from 'vault/tests/helpers/policy-generator/kv';
|
|
import {
|
|
clearRecords,
|
|
deleteVersionCmd,
|
|
destroyVersionCmd,
|
|
writeVersionedSecret,
|
|
} from 'vault/tests/helpers/kv/kv-run-commands';
|
|
|
|
import { PAGE } from 'vault/tests/helpers/kv/kv-selectors';
|
|
import { click, currentRouteName, currentURL, visit, waitUntil } from '@ember/test-helpers';
|
|
import { grantAccess, setupControlGroup } from 'vault/tests/helpers/control-groups';
|
|
|
|
const makeToken = (name, mountPath, policyGenerator) => {
|
|
return tokenWithPolicyCmd(`${name}-${mountPath}`, policyGenerator(mountPath));
|
|
};
|
|
/**
|
|
* This test set is for testing version history & path pages for secret.
|
|
* Letter(s) in parenthesis at the end are shorthand for the persona,
|
|
* for ease of tracking down specific tests failures from CI
|
|
*/
|
|
module('Acceptance | kv-v2 workflow | version history, paths', function (hooks) {
|
|
setupApplicationTest(hooks);
|
|
|
|
hooks.beforeEach(async function () {
|
|
this.store = this.owner.lookup('service:store');
|
|
this.backend = `kv-workflow-${uuidv4()}`;
|
|
this.secretPath = 'app/first-secret';
|
|
this.urlPath = `${this.backend}/kv/${encodeURIComponent(this.secretPath)}`;
|
|
this.navToSecret = async () => {
|
|
return visit(`/vault/secrets/${this.urlPath}/details?version=4`);
|
|
};
|
|
await authPage.login();
|
|
await runCmd(mountEngineCmd('kv-v2', this.backend), false);
|
|
await writeVersionedSecret(this.backend, this.secretPath, 'hello', 'there', 6);
|
|
await runCmd([
|
|
destroyVersionCmd(this.backend, this.secretPath),
|
|
deleteVersionCmd(this.backend, this.secretPath, 2),
|
|
]);
|
|
});
|
|
|
|
hooks.afterEach(async function () {
|
|
await authPage.login();
|
|
return runCmd(deleteEngineCmd(this.backend));
|
|
});
|
|
|
|
module('admin persona', function (hooks) {
|
|
hooks.beforeEach(async function () {
|
|
const token = await runCmd(makeToken('admin', this.backend, personas.admin));
|
|
await authPage.login(token);
|
|
clearRecords(this.store);
|
|
});
|
|
test('can navigate to the version history page (a)', async function (assert) {
|
|
await this.navToSecret();
|
|
await click(PAGE.secretTab('Version History'));
|
|
assert.strictEqual(
|
|
currentURL(),
|
|
`/vault/secrets/${this.urlPath}/metadata/versions`,
|
|
'navigates to version history'
|
|
);
|
|
assert.dom(PAGE.versions.linkedBlock()).exists({ count: 6 });
|
|
|
|
assert.dom(PAGE.versions.linkedBlock(6)).hasTextContaining('Version 6');
|
|
assert.dom(PAGE.versions.icon(6)).hasTextContaining('Current');
|
|
|
|
assert.dom(PAGE.versions.linkedBlock(2)).hasTextContaining('Version 2');
|
|
assert.dom(PAGE.versions.icon(2)).hasTextContaining('Deleted');
|
|
|
|
assert.dom(PAGE.versions.linkedBlock(1)).hasTextContaining('Version 1');
|
|
assert.dom(PAGE.versions.icon(1)).hasText('Destroyed');
|
|
|
|
await click(PAGE.versions.linkedBlock(5));
|
|
assert.strictEqual(
|
|
currentURL(),
|
|
`/vault/secrets/${this.urlPath}/details?version=5`,
|
|
'navigates to detail at specific version'
|
|
);
|
|
});
|
|
test('can navigate to the paths page (a)', async function (assert) {
|
|
await this.navToSecret();
|
|
await click(PAGE.secretTab('Paths'));
|
|
assert.strictEqual(
|
|
currentURL(),
|
|
`/vault/secrets/${this.urlPath}/paths`,
|
|
'navigates to secret paths route'
|
|
);
|
|
assert.dom(PAGE.infoRow).exists({ count: 3 }, 'shows 3 rows of information');
|
|
assert.dom(PAGE.infoRowValue('API path')).hasText(`/v1/${this.backend}/data/${this.secretPath}`);
|
|
assert.dom(PAGE.infoRowValue('CLI path')).hasText(`-mount="${this.backend}" "${this.secretPath}"`);
|
|
assert
|
|
.dom(PAGE.infoRowValue('API path for metadata'))
|
|
.hasText(`/v1/${this.backend}/metadata/${this.secretPath}`);
|
|
});
|
|
});
|
|
|
|
module('data-reader persona', function (hooks) {
|
|
hooks.beforeEach(async function () {
|
|
const token = await runCmd(makeToken('data-reader', this.backend, personas.dataReader));
|
|
await authPage.login(token);
|
|
clearRecords(this.store);
|
|
});
|
|
test('cannot navigate to the version history page (dr)', async function (assert) {
|
|
await this.navToSecret();
|
|
assert.dom(PAGE.secretTab('Version History')).doesNotExist('Does not render Version History tab');
|
|
});
|
|
test('can navigate to the paths page (dr)', async function (assert) {
|
|
await this.navToSecret();
|
|
await click(PAGE.secretTab('Paths'));
|
|
assert.strictEqual(
|
|
currentURL(),
|
|
`/vault/secrets/${this.urlPath}/paths`,
|
|
'navigates to secret paths route'
|
|
);
|
|
assert.dom(PAGE.infoRow).exists({ count: 3 }, 'shows 3 rows of information');
|
|
assert.dom(PAGE.infoRowValue('API path')).hasText(`/v1/${this.backend}/data/${this.secretPath}`);
|
|
assert.dom(PAGE.infoRowValue('CLI path')).hasText(`-mount="${this.backend}" "${this.secretPath}"`);
|
|
assert
|
|
.dom(PAGE.infoRowValue('API path for metadata'))
|
|
.hasText(`/v1/${this.backend}/metadata/${this.secretPath}`);
|
|
});
|
|
});
|
|
|
|
module('data-list-reader persona', function (hooks) {
|
|
hooks.beforeEach(async function () {
|
|
const token = await runCmd(makeToken('data-list-reader', this.backend, personas.dataListReader));
|
|
await authPage.login(token);
|
|
clearRecords(this.store);
|
|
});
|
|
test('cannot navigate to the version history page (dlr)', async function (assert) {
|
|
await this.navToSecret();
|
|
assert.dom(PAGE.secretTab('Version History')).doesNotExist('Does not render Version History tab');
|
|
});
|
|
test('can navigate to the paths page (dlr)', async function (assert) {
|
|
await this.navToSecret();
|
|
await click(PAGE.secretTab('Paths'));
|
|
assert.strictEqual(
|
|
currentURL(),
|
|
`/vault/secrets/${this.urlPath}/paths`,
|
|
'navigates to secret paths route'
|
|
);
|
|
assert.dom(PAGE.infoRow).exists({ count: 3 }, 'shows 3 rows of information');
|
|
assert.dom(PAGE.infoRowValue('API path')).hasText(`/v1/${this.backend}/data/${this.secretPath}`);
|
|
assert.dom(PAGE.infoRowValue('CLI path')).hasText(`-mount="${this.backend}" "${this.secretPath}"`);
|
|
assert
|
|
.dom(PAGE.infoRowValue('API path for metadata'))
|
|
.hasText(`/v1/${this.backend}/metadata/${this.secretPath}`);
|
|
});
|
|
});
|
|
|
|
module('metadata-maintainer persona', function (hooks) {
|
|
hooks.beforeEach(async function () {
|
|
const token = await runCmd(makeToken('metadata-maintainer', this.backend, personas.metadataMaintainer));
|
|
await authPage.login(token);
|
|
clearRecords(this.store);
|
|
});
|
|
test('can navigate to the version history page (mm)', async function (assert) {
|
|
await this.navToSecret();
|
|
await click(PAGE.secretTab('Version History'));
|
|
assert.strictEqual(
|
|
currentURL(),
|
|
`/vault/secrets/${this.urlPath}/metadata/versions`,
|
|
'navigates to version history'
|
|
);
|
|
assert.dom(PAGE.versions.linkedBlock()).exists({ count: 6 });
|
|
|
|
assert.dom(PAGE.versions.linkedBlock(6)).hasTextContaining('Version 6');
|
|
assert.dom(PAGE.versions.icon(6)).hasTextContaining('Current');
|
|
|
|
assert.dom(PAGE.versions.linkedBlock(2)).hasTextContaining('Version 2');
|
|
assert.dom(PAGE.versions.icon(2)).hasTextContaining('Deleted');
|
|
|
|
assert.dom(PAGE.versions.linkedBlock(1)).hasTextContaining('Version 1');
|
|
assert.dom(PAGE.versions.icon(1)).hasText('Destroyed');
|
|
|
|
await click(PAGE.versions.linkedBlock(5));
|
|
assert.strictEqual(
|
|
currentURL(),
|
|
`/vault/secrets/${this.urlPath}/details?version=5`,
|
|
'navigates to detail at specific version'
|
|
);
|
|
});
|
|
test('can navigate to the paths page (mm)', async function (assert) {
|
|
await this.navToSecret();
|
|
await click(PAGE.secretTab('Paths'));
|
|
assert.strictEqual(
|
|
currentURL(),
|
|
`/vault/secrets/${this.urlPath}/paths`,
|
|
'navigates to secret paths route'
|
|
);
|
|
assert.dom(PAGE.infoRow).exists({ count: 3 }, 'shows 3 rows of information');
|
|
assert.dom(PAGE.infoRowValue('API path')).hasText(`/v1/${this.backend}/data/${this.secretPath}`);
|
|
assert.dom(PAGE.infoRowValue('CLI path')).hasText(`-mount="${this.backend}" "${this.secretPath}"`);
|
|
assert
|
|
.dom(PAGE.infoRowValue('API path for metadata'))
|
|
.hasText(`/v1/${this.backend}/metadata/${this.secretPath}`);
|
|
});
|
|
});
|
|
|
|
module('secret-creator persona', function (hooks) {
|
|
hooks.beforeEach(async function () {
|
|
const token = await runCmd(makeToken('secret-creator', this.backend, personas.secretCreator));
|
|
await authPage.login(token);
|
|
clearRecords(this.store);
|
|
});
|
|
test('cannot navigate to the version history page (sc)', async function (assert) {
|
|
await this.navToSecret();
|
|
assert.dom(PAGE.secretTab('Version History')).doesNotExist('Does not render Version History tab');
|
|
});
|
|
test('can navigate to the paths page (sc)', async function (assert) {
|
|
await this.navToSecret();
|
|
await click(PAGE.secretTab('Paths'));
|
|
assert.strictEqual(
|
|
currentURL(),
|
|
`/vault/secrets/${this.urlPath}/paths`,
|
|
'navigates to secret paths route'
|
|
);
|
|
assert.dom(PAGE.infoRow).exists({ count: 3 }, 'shows 3 rows of information');
|
|
assert.dom(PAGE.infoRowValue('API path')).hasText(`/v1/${this.backend}/data/${this.secretPath}`);
|
|
assert.dom(PAGE.infoRowValue('CLI path')).hasText(`-mount="${this.backend}" "${this.secretPath}"`);
|
|
assert
|
|
.dom(PAGE.infoRowValue('API path for metadata'))
|
|
.hasText(`/v1/${this.backend}/metadata/${this.secretPath}`);
|
|
});
|
|
});
|
|
|
|
module('enterprise controlled access persona', function (hooks) {
|
|
hooks.beforeEach(async function () {
|
|
const userPolicy = `
|
|
path "${this.backend}/metadata/*" {
|
|
capabilities = ["create", "read", "update", "delete", "list"]
|
|
control_group = {
|
|
max_ttl = "24h"
|
|
factor "approver" {
|
|
controlled_capabilities = ["read"]
|
|
identity {
|
|
group_names = ["managers"]
|
|
approvals = 1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
path "${this.backend}/*" {
|
|
capabilities = ["list"]
|
|
}
|
|
`;
|
|
const { userToken } = await setupControlGroup({ userPolicy, backend: this.backend });
|
|
this.userToken = userToken;
|
|
await authPage.login(userToken);
|
|
clearRecords(this.store);
|
|
});
|
|
test('can navigate to the version history page (cg)', async function (assert) {
|
|
await this.navToSecret();
|
|
await click(PAGE.secretTab('Version History'));
|
|
assert.ok(
|
|
await waitUntil(() => currentRouteName() === 'vault.cluster.access.control-group-accessor'),
|
|
'redirects to access control group route'
|
|
);
|
|
await grantAccess({
|
|
apiPath: `${this.backend}/metadata/${this.secretPath}`,
|
|
originUrl: `/vault/secrets/${this.urlPath}/details`,
|
|
userToken: this.userToken,
|
|
backend: this.backend,
|
|
});
|
|
assert.strictEqual(
|
|
currentURL(),
|
|
`/vault/secrets/${this.urlPath}/details`,
|
|
'navigates back to secret overview after authorized'
|
|
);
|
|
await click(PAGE.secretTab('Version History'));
|
|
assert.strictEqual(
|
|
currentURL(),
|
|
`/vault/secrets/${this.urlPath}/metadata/versions`,
|
|
'goes to version history page'
|
|
);
|
|
assert.dom(PAGE.versions.linkedBlock()).exists({ count: 6 });
|
|
|
|
assert.dom(PAGE.versions.linkedBlock(6)).hasTextContaining('Version 6');
|
|
assert.dom(PAGE.versions.icon(6)).hasTextContaining('Current');
|
|
|
|
assert.dom(PAGE.versions.linkedBlock(2)).hasTextContaining('Version 2');
|
|
assert.dom(PAGE.versions.icon(2)).hasTextContaining('Deleted');
|
|
|
|
assert.dom(PAGE.versions.linkedBlock(1)).hasTextContaining('Version 1');
|
|
assert.dom(PAGE.versions.icon(1)).hasText('Destroyed');
|
|
|
|
await click(PAGE.versions.linkedBlock(5));
|
|
assert.strictEqual(
|
|
currentURL(),
|
|
`/vault/secrets/${this.urlPath}/details?version=5`,
|
|
'navigates to detail at specific version'
|
|
);
|
|
});
|
|
test('can navigate to the paths page (cg)', async function (assert) {
|
|
await this.navToSecret();
|
|
await click(PAGE.secretTab('Paths'));
|
|
assert.strictEqual(
|
|
currentURL(),
|
|
`/vault/secrets/${this.urlPath}/paths`,
|
|
'navigates to secret paths route'
|
|
);
|
|
assert.dom(PAGE.infoRow).exists({ count: 3 }, 'shows 3 rows of information');
|
|
assert.dom(PAGE.infoRowValue('API path')).hasText(`/v1/${this.backend}/data/${this.secretPath}`);
|
|
assert.dom(PAGE.infoRowValue('CLI path')).hasText(`-mount="${this.backend}" "${this.secretPath}"`);
|
|
assert
|
|
.dom(PAGE.infoRowValue('API path for metadata'))
|
|
.hasText(`/v1/${this.backend}/metadata/${this.secretPath}`);
|
|
});
|
|
});
|
|
});
|