mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-10-29 09:42:25 +00:00
Add directory paths to KV capabilities checks (#24404)
* add getter to metadata model * add changelog and data model fix * add test coverage * add nested create coverage * Update 24404.txt * remove from data model * return to how it was
This commit is contained in:
3
changelog/24404.txt
Normal file
3
changelog/24404.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
```release-note:bug
|
||||
ui: fix issue where kv v2 capabilities checks were not passing in the full secret path if secret was inside a directory.
|
||||
```
|
||||
@@ -95,9 +95,14 @@ export default class KvSecretMetadataModel extends Model {
|
||||
};
|
||||
}
|
||||
|
||||
get permissionsPath() {
|
||||
return this.fullSecretPath || this.path;
|
||||
}
|
||||
|
||||
// permissions needed for the list view where kv/data has not yet been called. Allows us to conditionally show action items in the LinkedBlock popups.
|
||||
@lazyCapabilities(apiPath`${'backend'}/data/${'path'}`, 'backend', 'path') dataPath;
|
||||
@lazyCapabilities(apiPath`${'backend'}/metadata/${'path'}`, 'backend', 'path') metadataPath;
|
||||
@lazyCapabilities(apiPath`${'backend'}/data/${'permissionsPath'}`, 'backend', 'permissionsPath') dataPath;
|
||||
@lazyCapabilities(apiPath`${'backend'}/metadata/${'permissionsPath'}`, 'backend', 'permissionsPath')
|
||||
metadataPath;
|
||||
|
||||
get canDeleteMetadata() {
|
||||
return this.metadataPath.get('canDelete') !== false;
|
||||
|
||||
@@ -95,7 +95,11 @@
|
||||
{{/if}}
|
||||
{{#if metadata.canCreateVersionData}}
|
||||
<li>
|
||||
<LinkTo @route="secret.details.edit" @model={{metadata.fullSecretPath}}>
|
||||
<LinkTo
|
||||
@route="secret.details.edit"
|
||||
@model={{metadata.fullSecretPath}}
|
||||
data-test-popup-create-new-version
|
||||
>
|
||||
Create new version
|
||||
</LinkTo>
|
||||
</li>
|
||||
@@ -106,6 +110,7 @@
|
||||
@isInDropdown={{true}}
|
||||
@onConfirmAction={{fn this.onDelete metadata}}
|
||||
@confirmMessage="This will permanently delete this secret and all its versions."
|
||||
data-test-popup-metadata-delete
|
||||
/>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
@@ -1003,6 +1003,26 @@ module('Acceptance | kv-v2 workflow | secret and version create', function (hook
|
||||
});
|
||||
});
|
||||
|
||||
module('secret-nested-creator persona', function (hooks) {
|
||||
hooks.beforeEach(async function () {
|
||||
const token = await runCmd(
|
||||
tokenWithPolicyCmd('secret-nested-creator', personas.secretNestedCreator(this.backend))
|
||||
);
|
||||
await authPage.login(token);
|
||||
clearRecords(this.store);
|
||||
return;
|
||||
});
|
||||
test('can create a secret from the nested list view (snc)', async function (assert) {
|
||||
assert.expect(1);
|
||||
// go to nested secret directory list view
|
||||
await visit(`/vault/secrets/${this.backend}/kv/list/app/`);
|
||||
// correct popup menu items appear on list view
|
||||
const popupSelector = `${PAGE.list.item('first')} ${PAGE.popup}`;
|
||||
await click(popupSelector);
|
||||
assert.dom(PAGE.list.listMenuCreate).exists('shows the option to create new version');
|
||||
});
|
||||
});
|
||||
|
||||
module('enterprise controlled access persona', function (hooks) {
|
||||
hooks.beforeEach(async function () {
|
||||
this.controlGroup = this.owner.lookup('service:control-group');
|
||||
|
||||
@@ -40,9 +40,11 @@ module('Acceptance | kv-v2 workflow | delete, undelete, destroy', function (hook
|
||||
this.store = this.owner.lookup('service:store');
|
||||
this.backend = `kv-delete-${uuidv4()}`;
|
||||
this.secretPath = 'bad-secret';
|
||||
this.nestedSecretPath = 'app/nested/bad-secret';
|
||||
await authPage.login();
|
||||
await runCmd(mountEngineCmd('kv-v2', this.backend), false);
|
||||
await writeVersionedSecret(this.backend, this.secretPath, 'foo', 'bar', 4);
|
||||
await writeVersionedSecret(this.backend, this.nestedSecretPath, 'foo', 'bar', 1);
|
||||
await writeVersionedSecret(this.backend, 'nuke', 'foo', 'bar', 2);
|
||||
// Delete latest version for testing undelete for users that can't delete
|
||||
await runCmd(deleteLatestCmd(this.backend, 'nuke'));
|
||||
@@ -353,6 +355,33 @@ module('Acceptance | kv-v2 workflow | delete, undelete, destroy', function (hook
|
||||
});
|
||||
});
|
||||
|
||||
module('secret-nested-creator persona', function (hooks) {
|
||||
hooks.beforeEach(async function () {
|
||||
const token = await runCmd(
|
||||
tokenWithPolicyCmd('secret-nested-creator', personas.secretNestedCreator(this.backend))
|
||||
);
|
||||
await authPage.login(token);
|
||||
clearRecords(this.store);
|
||||
return;
|
||||
});
|
||||
test('can delete all secret versions from the nested list view (snc)', async function (assert) {
|
||||
assert.expect(1);
|
||||
// go to nested secret directory list view
|
||||
await visit(`/vault/secrets/${this.backend}/kv/list/app/nested`);
|
||||
// correct popup menu items appear on list view
|
||||
const popupSelector = `${PAGE.list.item('bad-secret')} ${PAGE.popup}`;
|
||||
await click(popupSelector);
|
||||
assert.dom(PAGE.list.listMenuDelete).exists('shows the option to permanently delete');
|
||||
});
|
||||
test('can not delete all secret versions from root list view (snc)', async function (assert) {
|
||||
assert.expect(1);
|
||||
// go to root secret directory list view
|
||||
await visit(`/vault/secrets/${this.backend}/kv/list`);
|
||||
// shows overview card and not list view
|
||||
assert.dom(PAGE.list.overviewCard).exists('renders overview card');
|
||||
});
|
||||
});
|
||||
|
||||
module('secret-creator persona', function (hooks) {
|
||||
hooks.beforeEach(async function () {
|
||||
const token = await runCmd(tokenWithPolicyCmd('secret-creator', personas.secretCreator(this.backend)));
|
||||
|
||||
@@ -58,6 +58,8 @@ export const PAGE = {
|
||||
createSecret: '[data-test-toolbar-create-secret]',
|
||||
item: (secret) => (!secret ? '[data-test-list-item]' : `[data-test-list-item="${secret}"]`),
|
||||
filter: `[data-test-kv-list-filter]`,
|
||||
listMenuDelete: `[data-test-popup-metadata-delete]`,
|
||||
listMenuCreate: `[data-test-popup-create-new-version]`,
|
||||
overviewCard: '[data-test-overview-card-container="View secret"]',
|
||||
overviewInput: '[data-test-view-secret] input',
|
||||
overviewButton: '[data-test-get-secret-detail]',
|
||||
|
||||
@@ -25,6 +25,14 @@ export const dataPolicy = ({ backend, secretPath = '*', capabilities = root }) =
|
||||
`;
|
||||
};
|
||||
|
||||
export const dataNestedPolicy = ({ backend, secretPath = '*', capabilities = root }) => {
|
||||
return `
|
||||
path "${backend}/data/app/${secretPath}" {
|
||||
capabilities = [${format(capabilities)}]
|
||||
}
|
||||
`;
|
||||
};
|
||||
|
||||
export const metadataPolicy = ({ backend, secretPath = '*', capabilities = root }) => {
|
||||
// "delete" capability on this path can destroy all versions
|
||||
return `
|
||||
@@ -34,6 +42,14 @@ export const metadataPolicy = ({ backend, secretPath = '*', capabilities = root
|
||||
`;
|
||||
};
|
||||
|
||||
export const metadataNestedPolicy = ({ backend, secretPath = '*', capabilities = root }) => {
|
||||
return `
|
||||
path "${backend}/metadata/app/${secretPath}" {
|
||||
capabilities = [${format(capabilities)}]
|
||||
}
|
||||
`;
|
||||
};
|
||||
|
||||
export const metadataListPolicy = (backend) => {
|
||||
return `
|
||||
path "${backend}/metadata" {
|
||||
@@ -71,11 +87,13 @@ export const personas = {
|
||||
dataListReader: (backend) =>
|
||||
dataPolicy({ backend, capabilities: ['read', 'delete'] }) + metadataListPolicy(backend),
|
||||
metadataMaintainer: (backend) =>
|
||||
metadataListPolicy(backend) +
|
||||
metadataPolicy({ backend, capabilities: ['create', 'read', 'update', 'list'] }) +
|
||||
deleteVersionsPolicy({ backend }) +
|
||||
undeleteVersionsPolicy({ backend }) +
|
||||
destroyVersionsPolicy({ backend }),
|
||||
secretNestedCreator: (backend) =>
|
||||
dataNestedPolicy({ backend, capabilities: ['create', 'update'] }) +
|
||||
metadataNestedPolicy({ backend, capabilities: ['list', 'delete'] }),
|
||||
secretCreator: (backend) =>
|
||||
dataPolicy({ backend, capabilities: ['create', 'update'] }) +
|
||||
metadataPolicy({ backend, capabilities: ['delete'] }),
|
||||
|
||||
Reference in New Issue
Block a user