mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-05 22:27:03 +02:00
* adding clause for external plugin to tooltip * fixing mouseover event * fix check * pulling object out of list * fix used parameter * adding comments * fix * fixing tests * adding 1 more test * update tooltip func, remove excess params, update tests
231 lines
8.4 KiB
JavaScript
231 lines
8.4 KiB
JavaScript
/**
|
|
* Copyright (c) HashiCorp, Inc.
|
|
* SPDX-License-Identifier: BUSL-1.1
|
|
*/
|
|
|
|
import { click, fillIn, currentRouteName, visit, currentURL } from '@ember/test-helpers';
|
|
import { selectChoose } from 'ember-power-select/test-support';
|
|
import { module, test } from 'qunit';
|
|
import { setupApplicationTest } from 'ember-qunit';
|
|
import { v4 as uuidv4 } from 'uuid';
|
|
|
|
import { GENERAL } from 'vault/tests/helpers/general-selectors';
|
|
import { SECRET_ENGINE_SELECTORS as SES } from 'vault/tests/helpers/secret-engine/secret-engine-selectors';
|
|
import {
|
|
createTokenCmd,
|
|
deleteEngineCmd,
|
|
mountEngineCmd,
|
|
runCmd,
|
|
tokenWithPolicyCmd,
|
|
} from 'vault/tests/helpers/commands';
|
|
import { login, loginNs } from 'vault/tests/helpers/auth/auth-helpers';
|
|
import { MOUNT_BACKEND_FORM } from '../helpers/components/mount-backend-form-selectors';
|
|
import page from 'vault/tests/pages/settings/mount-secret-backend';
|
|
|
|
module('Acceptance | secret-engine list view', function (hooks) {
|
|
setupApplicationTest(hooks);
|
|
|
|
const createSecret = async (path, key, value, enginePath) => {
|
|
await click(SES.createSecretLink);
|
|
await fillIn(SES.secretPath('create'), path);
|
|
await fillIn(SES.secretKey('create'), key);
|
|
await fillIn(GENERAL.inputByAttr(key), value);
|
|
await click(GENERAL.submitButton);
|
|
await click(SES.crumb(enginePath));
|
|
};
|
|
|
|
hooks.beforeEach(function () {
|
|
this.uid = uuidv4();
|
|
return login();
|
|
});
|
|
|
|
// the new API service camelizes response keys, so this tests is to assert that does NOT happen when we re-implement it
|
|
test('it does not camelize the secret mount path', async function (assert) {
|
|
await visit('/vault/secrets');
|
|
await page.enableEngine();
|
|
await click(MOUNT_BACKEND_FORM.mountType('aws'));
|
|
await fillIn(GENERAL.inputByAttr('path'), 'aws_engine');
|
|
await click(GENERAL.submitButton);
|
|
await click(GENERAL.breadcrumbLink('Secrets'));
|
|
assert.strictEqual(
|
|
currentRouteName(),
|
|
'vault.cluster.secrets.backends',
|
|
'breadcrumb navigates to the list page'
|
|
);
|
|
assert.dom(SES.secretsBackendLink('aws_engine')).hasTextContaining('aws_engine/');
|
|
// cleanup
|
|
await runCmd(deleteEngineCmd('aws_engine'));
|
|
});
|
|
|
|
test('after enabling an unsupported engine it takes you to list page', async function (assert) {
|
|
await visit('/vault/secrets');
|
|
await page.enableEngine();
|
|
await click(MOUNT_BACKEND_FORM.mountType('nomad'));
|
|
await click(GENERAL.submitButton);
|
|
|
|
assert.strictEqual(currentRouteName(), 'vault.cluster.secrets.backends', 'navigates to the list page');
|
|
// cleanup
|
|
await runCmd(deleteEngineCmd('nomad'));
|
|
});
|
|
|
|
test('after enabling a supported engine it takes you to mount page, can see configure and clicking breadcrumb takes you back to list page', async function (assert) {
|
|
await visit('/vault/secrets');
|
|
await page.enableEngine();
|
|
await click(MOUNT_BACKEND_FORM.mountType('aws'));
|
|
await click(GENERAL.submitButton);
|
|
|
|
assert.dom(SES.configTab).exists();
|
|
|
|
await click(GENERAL.breadcrumbLink('Secrets'));
|
|
assert.strictEqual(
|
|
currentRouteName(),
|
|
'vault.cluster.secrets.backends',
|
|
'breadcrumb navigates to the list page'
|
|
);
|
|
// cleanup
|
|
await runCmd(deleteEngineCmd('aws'));
|
|
});
|
|
|
|
test('enterprise: cannot view list without permissions inside a namespace', async function (assert) {
|
|
this.namespace = `ns-${this.uid}`;
|
|
const enginePath1 = `kv-t1-${this.uid}`;
|
|
const userDefault = await runCmd(createTokenCmd()); // creates a default user token
|
|
|
|
await runCmd([`write sys/namespaces/${this.namespace} -force`]); // creates a namespace
|
|
await loginNs(this.namespace); //logs into namespace with root token
|
|
await runCmd(mountEngineCmd('kv', enginePath1)); // mounts a kv engine in namespace
|
|
|
|
await loginNs(this.namespace, userDefault); // logs into that same namespace with a default user token
|
|
|
|
await visit(`/vault/secrets?namespace=${this.namespace}`); // nav to specified namespace list
|
|
assert.strictEqual(
|
|
currentURL(),
|
|
`/vault/secrets?namespace=${this.namespace}`,
|
|
'Should be on main secret engines list page within namespace.'
|
|
);
|
|
assert.dom(SES.secretsBackendLink(enginePath1)).doesNotExist(); // without permissions, engine should not show for this user
|
|
|
|
// cleanup namespace
|
|
await login();
|
|
await runCmd(`delete sys/namespaces/${this.namespace}`);
|
|
});
|
|
|
|
test('enterprise: can view list with permissions inside a namespace', async function (assert) {
|
|
this.namespace = `ns-${this.uid}`;
|
|
const enginePath1 = `kv-t2-${this.uid}`;
|
|
const userToken = await runCmd(
|
|
tokenWithPolicyCmd(
|
|
'policy',
|
|
`path "${this.namespace}/sys/*" {
|
|
capabilities = ["create", "read", "update", "delete", "list"]
|
|
}`
|
|
)
|
|
);
|
|
|
|
await runCmd([`write sys/namespaces/${this.namespace} -force`]);
|
|
await loginNs(this.namespace, userToken); // logs into namespace with user token
|
|
await runCmd(mountEngineCmd('kv', enginePath1)); // mount kv engine as user
|
|
|
|
await loginNs(this.namespace); // logs into namespace with root token
|
|
|
|
await visit(`/vault/secrets?namespace=${this.namespace}`); // nav to specified namespace list
|
|
assert.strictEqual(
|
|
currentURL(),
|
|
`/vault/secrets?namespace=${this.namespace}`,
|
|
'Should be on main secret engines list page within namespace.'
|
|
);
|
|
|
|
assert.dom(SES.secretsBackendLink(enginePath1)).exists(); // with permissions, able to see the engine in list
|
|
|
|
// cleanup namespace
|
|
await login();
|
|
await runCmd(`delete sys/namespaces/${this.namespace}`);
|
|
});
|
|
|
|
test('after disabling it stays on the list view', async function (assert) {
|
|
// first mount an engine so we can disable it.
|
|
const enginePath = `alicloud-disable-${this.uid}`;
|
|
await runCmd(mountEngineCmd('alicloud', enginePath));
|
|
await visit('/vault/secrets');
|
|
// to reduce flakiness, searching by engine name first in case there are pagination issues
|
|
await selectChoose(GENERAL.searchSelect.trigger('filter-by-engine-name'), enginePath);
|
|
assert.dom(SES.secretsBackendLink(enginePath)).exists('the alicloud engine is mounted');
|
|
|
|
await click(GENERAL.menuTrigger);
|
|
await click(GENERAL.menuItem('disable-engine'));
|
|
await click(GENERAL.confirmButton);
|
|
assert.strictEqual(
|
|
currentRouteName(),
|
|
'vault.cluster.secrets.backends',
|
|
'redirects to the backends list page'
|
|
);
|
|
});
|
|
|
|
test('it allows navigation to a non-nested secret with pagination', async function (assert) {
|
|
assert.expect(2);
|
|
|
|
const enginePath1 = `kv-v1-${this.uid}`;
|
|
const secretPath = 'secret-9';
|
|
await runCmd(mountEngineCmd('kv', enginePath1));
|
|
|
|
// check kv1
|
|
await visit('/vault/secrets');
|
|
await click(SES.secretsBackendLink(enginePath1));
|
|
for (let i = 0; i <= 15; i++) {
|
|
await createSecret(`secret-${i}`, 'foo', 'bar', enginePath1);
|
|
}
|
|
|
|
// navigate and check that details view is shown from non-nested secrets
|
|
await click(GENERAL.pagination.next);
|
|
assert.strictEqual(
|
|
currentURL(),
|
|
`/vault/secrets/${enginePath1}/list?page=2`,
|
|
'After clicking next page in navigates to the second page.'
|
|
);
|
|
await click(SES.secretLink(secretPath));
|
|
assert.strictEqual(
|
|
currentURL(),
|
|
`/vault/secrets/${enginePath1}/show/${secretPath}`,
|
|
'After clicking a non-nested secret, it navigates to the details view.'
|
|
);
|
|
|
|
// cleanup
|
|
await runCmd(deleteEngineCmd(enginePath1));
|
|
});
|
|
|
|
test('it allows navigation to a nested secret with pagination', async function (assert) {
|
|
assert.expect(2);
|
|
|
|
const enginePath1 = `kv-v1-${this.uid}`;
|
|
const parentPath = 'nested';
|
|
|
|
await runCmd(mountEngineCmd('kv', enginePath1));
|
|
|
|
// check kv1
|
|
await visit('/vault/secrets');
|
|
await click(SES.secretsBackendLink(enginePath1));
|
|
for (let i = 0; i <= 15; i++) {
|
|
await createSecret(`${parentPath}/secret-${i}`, 'foo', 'bar', enginePath1);
|
|
}
|
|
|
|
// navigate and check that the children list view is shown from nested secrets
|
|
await click(SES.secretLink(`${parentPath}/`));
|
|
|
|
assert.strictEqual(
|
|
currentURL(),
|
|
`/vault/secrets/${enginePath1}/list/${parentPath}/`,
|
|
'After clicking a nested secret it navigates to the children list view.'
|
|
);
|
|
|
|
await click(GENERAL.pagination.next);
|
|
assert.strictEqual(
|
|
currentURL(),
|
|
`/vault/secrets/${enginePath1}/list/${parentPath}/?page=2`,
|
|
'After clicking next page it navigates to the second page.'
|
|
);
|
|
|
|
// cleanup
|
|
await runCmd(deleteEngineCmd(enginePath1));
|
|
});
|
|
});
|