UI: Mount PKI options + allowed_managed_keys (#19791)

This commit is contained in:
Chelsea Shaw 2023-04-07 16:05:29 -05:00 committed by GitHub
parent 43912fe0e2
commit bb6964e18e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 109 additions and 15 deletions

3
changelog/19791.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:improvement
ui: add allowed_managed_keys field to secret engine mount options
```

View File

@ -56,6 +56,17 @@ export default class MountBackendForm extends Component {
}
}
typeChangeSideEffect(type) {
if (!this.args.mountType === 'secret') return;
if (type === 'pki') {
// If type PKI, set max lease to ~10years
this.args.mountModel.config.maxLeaseTtl = '3650d';
} else {
// otherwise reset
this.args.mountModel.config.maxLeaseTtl = 0;
}
}
checkModelValidity(model) {
const { isValid, state, invalidFormMessage } = model.validate();
this.modelValidations = state;
@ -158,6 +169,7 @@ export default class MountBackendForm extends Component {
@action
setMountType(value) {
this.args.mountModel.type = value;
this.typeChangeSideEffect(value);
this.checkPathChange(value);
}
}

View File

@ -73,7 +73,14 @@ export function withExpandedAttributes() {
});
const expanded = expandAttributeMeta(rModel, rAttrNames);
expanded.forEach((attr) => {
byKey[`${name}.${attr.name}`] = attr;
byKey[`${name}.${attr.name}`] = {
...attr,
options: {
...attr.options,
// This ensures the correct path is updated in FormField
fieldValue: `${name}.${attr.fieldValue || attr.name}`,
},
};
});
}, this);
this._allByKey = byKey;

View File

@ -87,6 +87,7 @@ const MOUNTABLE_SECRET_ENGINES = [
{
displayName: 'PKI Certificates',
type: 'pki',
// engineRoute: 'pki.overview', // TODO VAULT-13822
category: 'generic',
},
{

View File

@ -63,5 +63,8 @@ export default class MountConfigModel extends Model {
})
tokenType;
@attr() allowedManagedKeys;
@attr({
editType: 'stringArray',
})
allowedManagedKeys;
}

View File

@ -155,6 +155,7 @@ export default class SecretEngineModel extends Model {
fields.push('config.defaultLeaseTtl', 'config.maxLeaseTtl');
}
fields.push(
'config.allowedManagedKeys',
'config.auditNonHmacRequestKeys',
'config.auditNonHmacResponseKeys',
'config.passthroughRequestHeaders',
@ -189,6 +190,7 @@ export default class SecretEngineModel extends Model {
...CORE_OPTIONS,
'config.defaultLeaseTtl',
'config.maxLeaseTtl',
'config.allowedManagedKeys',
...STANDARD_CONFIG,
];
break;
@ -198,21 +200,32 @@ export default class SecretEngineModel extends Model {
...CORE_OPTIONS,
'config.defaultLeaseTtl',
'config.maxLeaseTtl',
'config.allowedManagedKeys',
...STANDARD_CONFIG,
];
break;
case 'database':
// Highlight TTLs in default
defaultFields = ['path', 'config.defaultLeaseTtl', 'config.maxLeaseTtl'];
optionFields = [...CORE_OPTIONS, 'config.allowedManagedKeys', ...STANDARD_CONFIG];
break;
case 'pki':
defaultFields = ['path', 'config.defaultLeaseTtl', 'config.maxLeaseTtl', 'config.allowedManagedKeys'];
optionFields = [...CORE_OPTIONS, ...STANDARD_CONFIG];
break;
case 'keymgmt':
// no ttl options for keymgmt
optionFields = [...CORE_OPTIONS, ...STANDARD_CONFIG];
optionFields = [...CORE_OPTIONS, 'config.allowedManagedKeys', ...STANDARD_CONFIG];
break;
default:
defaultFields = ['path'];
optionFields = [...CORE_OPTIONS, 'config.defaultLeaseTtl', 'config.maxLeaseTtl', ...STANDARD_CONFIG];
optionFields = [
...CORE_OPTIONS,
'config.defaultLeaseTtl',
'config.maxLeaseTtl',
'config.allowedManagedKeys',
...STANDARD_CONFIG,
];
break;
}

View File

@ -29,13 +29,14 @@
<InfoTableRow
@alwaysRender={{not (is-empty-value (get this.model attr.name))}}
@label={{or attr.options.label (to-label attr.name)}}
@value={{stringify (get this.model attr.name)}}
@value={{stringify (get this.model (or attr.options.fieldValue attr.name))}}
/>
{{else}}
<InfoTableRow
@alwaysRender={{and (not (is-empty-value (get this.model attr.name))) (not-eq attr.name "version")}}
@formatTtl={{eq attr.options.editType "ttl"}}
@label={{or attr.options.label (to-label attr.name)}}
@value={{get this.model attr.name}}
@value={{get this.model (or attr.options.fieldValue attr.name)}}
/>
{{/if}}
{{/each}}

View File

@ -32,8 +32,6 @@ module('Acceptance | settings/mount-secret-backend', function (hooks) {
const path = `mount-kv-${this.uid}`;
const defaultTTLHours = 100;
const maxTTLHours = 300;
const defaultTTLSeconds = (defaultTTLHours * 60 * 60).toString();
const maxTTLSeconds = (maxTTLHours * 60 * 60).toString();
await page.visit();
@ -51,15 +49,14 @@ module('Acceptance | settings/mount-secret-backend', function (hooks) {
.maxTTLVal(maxTTLHours)
.submit();
await configPage.visit({ backend: path });
assert.strictEqual(configPage.defaultTTL, `${defaultTTLSeconds}s`, 'shows the proper TTL');
assert.strictEqual(configPage.maxTTL, `${maxTTLSeconds}s`, 'shows the proper max TTL');
assert.strictEqual(configPage.defaultTTL, `${defaultTTLHours}h`, 'shows the proper TTL');
assert.strictEqual(configPage.maxTTL, `${maxTTLHours}h`, 'shows the proper max TTL');
});
test('it sets the ttl when enabled then disabled', async function (assert) {
// always force the new mount to the top of the list
const path = `mount-kv-${this.uid}`;
const maxTTLHours = 300;
const maxTTLSeconds = (maxTTLHours * 60 * 60).toString();
await page.visit();
@ -76,8 +73,33 @@ module('Acceptance | settings/mount-secret-backend', function (hooks) {
.maxTTLVal(maxTTLHours)
.submit();
await configPage.visit({ backend: path });
assert.strictEqual(configPage.defaultTTL, '0', 'shows the proper TTL');
assert.strictEqual(configPage.maxTTL, `${maxTTLSeconds}s`, 'shows the proper max TTL');
assert.strictEqual(configPage.defaultTTL, '0s', 'shows the proper TTL');
assert.strictEqual(configPage.maxTTL, `${maxTTLHours}h`, 'shows the proper max TTL');
});
test('it sets the max ttl after pki chosen, resets after', async function (assert) {
await page.visit();
assert.strictEqual(currentRouteName(), 'vault.cluster.settings.mount-secret-backend');
await page.selectType('pki');
await page.next();
assert.dom('[data-test-input="maxLeaseTtl"]').exists();
assert
.dom('[data-test-input="maxLeaseTtl"] [data-test-ttl-toggle]')
.isChecked('Toggle is checked by default');
assert.dom('[data-test-input="maxLeaseTtl"] [data-test-ttl-value]').hasValue('3650');
assert.dom('[data-test-input="maxLeaseTtl"] [data-test-select="ttl-unit"]').hasValue('d');
// Go back and choose a different type
await page.back();
await page.selectType('database');
await page.next();
assert.dom('[data-test-input="maxLeaseTtl"]').exists('3650');
assert
.dom('[data-test-input="maxLeaseTtl"] [data-test-ttl-toggle]')
.isNotChecked('Toggle is unchecked by default');
await page.enableMaxTtl();
assert.dom('[data-test-input="maxLeaseTtl"] [data-test-ttl-value]').hasValue('');
assert.dom('[data-test-input="maxLeaseTtl"] [data-test-select="ttl-unit"]').hasValue('s');
});
test('it throws error if setting duplicate path name', async function (assert) {

View File

@ -7,6 +7,6 @@ import { create, visitable, text } from 'ember-cli-page-object';
export default create({
visit: visitable('/vault/secrets/:backend/configuration'),
defaultTTL: text('[data-test-row-value="Default Lease TTL"]'),
maxTTL: text('[data-test-row-value="Max Lease TTL"]'),
defaultTTL: text('[data-test-value-div="Default Lease TTL"]'),
maxTTL: text('[data-test-value-div="Max Lease TTL"]'),
});

View File

@ -66,6 +66,7 @@ module('Unit | Model | secret-engine', function (hooks) {
'sealWrap',
'config.defaultLeaseTtl',
'config.maxLeaseTtl',
'config.allowedManagedKeys',
'config.auditNonHmacRequestKeys',
'config.auditNonHmacResponseKeys',
'config.passthroughRequestHeaders',
@ -88,6 +89,7 @@ module('Unit | Model | secret-engine', function (hooks) {
'sealWrap',
'config.defaultLeaseTtl',
'config.maxLeaseTtl',
'config.allowedManagedKeys',
'config.auditNonHmacRequestKeys',
'config.auditNonHmacResponseKeys',
'config.passthroughRequestHeaders',
@ -112,6 +114,7 @@ module('Unit | Model | secret-engine', function (hooks) {
'sealWrap',
'config.defaultLeaseTtl',
'config.maxLeaseTtl',
'config.allowedManagedKeys',
'config.auditNonHmacRequestKeys',
'config.auditNonHmacResponseKeys',
'config.passthroughRequestHeaders',
@ -136,6 +139,7 @@ module('Unit | Model | secret-engine', function (hooks) {
'accessor',
'local',
'sealWrap',
'config.allowedManagedKeys',
'config.auditNonHmacRequestKeys',
'config.auditNonHmacResponseKeys',
'config.passthroughRequestHeaders',
@ -161,6 +165,7 @@ module('Unit | Model | secret-engine', function (hooks) {
'sealWrap',
'config.defaultLeaseTtl',
'config.maxLeaseTtl',
'config.allowedManagedKeys',
'config.auditNonHmacRequestKeys',
'config.auditNonHmacResponseKeys',
'config.passthroughRequestHeaders',
@ -186,6 +191,7 @@ module('Unit | Model | secret-engine', function (hooks) {
'sealWrap',
'config.defaultLeaseTtl',
'config.maxLeaseTtl',
'config.allowedManagedKeys',
'config.auditNonHmacRequestKeys',
'config.auditNonHmacResponseKeys',
'config.passthroughRequestHeaders',
@ -212,6 +218,7 @@ module('Unit | Model | secret-engine', function (hooks) {
'sealWrap',
'config.defaultLeaseTtl',
'config.maxLeaseTtl',
'config.allowedManagedKeys',
'config.auditNonHmacRequestKeys',
'config.auditNonHmacResponseKeys',
'config.passthroughRequestHeaders',
@ -229,6 +236,30 @@ module('Unit | Model | secret-engine', function (hooks) {
assert.deepEqual(model.get('formFieldGroups'), [
{ default: ['path', 'config.defaultLeaseTtl', 'config.maxLeaseTtl'] },
{
'Method Options': [
'description',
'config.listingVisibility',
'local',
'sealWrap',
'config.allowedManagedKeys',
'config.auditNonHmacRequestKeys',
'config.auditNonHmacResponseKeys',
'config.passthroughRequestHeaders',
'config.allowedResponseHeaders',
],
},
]);
});
test('returns correct values for pki', function (assert) {
assert.expect(1);
const model = this.store.createRecord('secret-engine', {
type: 'pki',
});
assert.deepEqual(model.get('formFieldGroups'), [
{ default: ['path', 'config.defaultLeaseTtl', 'config.maxLeaseTtl', 'config.allowedManagedKeys'] },
{
'Method Options': [
'description',
@ -258,6 +289,7 @@ module('Unit | Model | secret-engine', function (hooks) {
'config.listingVisibility',
'local',
'sealWrap',
'config.allowedManagedKeys',
'config.auditNonHmacRequestKeys',
'config.auditNonHmacResponseKeys',
'config.passthroughRequestHeaders',