UI/Remove token_type field from token auth method (#12904)

* chane form field to angle bracket syntax

* computes tuneAttrs depending on auth method type

* make all attrs linkable

* delete token_type for token auth methods before save

* adds changelog

* adds copy to unsupported auth methods

* adds doc link to copy

* adds test for linkable auth method list
This commit is contained in:
claire bontempo 2021-10-29 13:00:34 -07:00 committed by GitHub
parent 353e8a312f
commit ab1fd3255b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 126 additions and 125 deletions

3
changelog/12904.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:bug
ui: Removes ability to tune token_type for token auth methods
```

View File

@ -22,6 +22,12 @@ export default AuthConfigComponent.extend({
saveModel: task(function*() {
let data = this.model.config.serialize();
data.description = this.model.description;
// token_type should not be tuneable for the token auth method, default is 'default-service'
if (this.model.type === 'token') {
delete data.token_type;
}
try {
yield this.model.tune(data);
} catch (err) {

View File

@ -1,6 +1,6 @@
import { helper as buildHelper } from '@ember/component/helper';
const MANAGED_AUTH_BACKENDS = ['okta', 'radius', 'ldap', 'cert', 'userpass'];
const MANAGED_AUTH_BACKENDS = ['cert', 'userpass', 'ldap', 'okta', 'radius'];
export function supportedManagedAuthBackends() {
return MANAGED_AUTH_BACKENDS;

View File

@ -49,14 +49,25 @@ let ModelExport = Model.extend(Validations, {
return this.local ? 'local' : 'replicated';
}),
tuneAttrs: computed(function() {
return expandAttributeMeta(this, [
'description',
'config.{listingVisibility,defaultLeaseTtl,maxLeaseTtl,tokenType,auditNonHmacRequestKeys,auditNonHmacResponseKeys,passthroughRequestHeaders}',
]);
tuneAttrs: computed('path', function() {
let { methodType } = this;
let tuneAttrs;
// token_type should not be tuneable for the token auth method
if (methodType === 'token') {
tuneAttrs = [
'description',
'config.{listingVisibility,defaultLeaseTtl,maxLeaseTtl,auditNonHmacRequestKeys,auditNonHmacResponseKeys,passthroughRequestHeaders}',
];
} else {
tuneAttrs = [
'description',
'config.{listingVisibility,defaultLeaseTtl,maxLeaseTtl,tokenType,auditNonHmacRequestKeys,auditNonHmacResponseKeys,passthroughRequestHeaders}',
];
}
return expandAttributeMeta(this, tuneAttrs);
}),
//sys/mounts/auth/[auth-path]/tune.
// sys/mounts/auth/[auth-path]/tune.
tune: memberAction({
path: 'tune',
type: 'post',

View File

@ -3,7 +3,7 @@
<MessageError @model={{model}} @errorMessage={{model.errorMessage}}/>
<NamespaceReminder @mode="save" @noun="Auth Method" />
{{#each model.tuneAttrs as |attr|}}
{{form-field data-test-field attr=attr model=model}}
<FormField data-test-field @attr={{attr}} @model={{model}} />
{{/each}}
</div>
<div class="field is-grouped box is-fullwidth is-bottomless">
@ -16,4 +16,4 @@
Update Options
</button>
</div>
</form>
</form>

View File

@ -17,7 +17,16 @@
</h1>
</p.levelLeft>
</PageHeader>
{{#if (not (contains model.type (supported-managed-auth-backends)))}}
<div class="has-text-grey has-top-bottom-margin" data-test-doc-link>
The Vault UI only supports configuration for this authentication method.
For management, the <DocLink @path="/api/auth">API or CLI</DocLink> should be used.
</div>
{{/if}}
{{section-tabs model "authShow" paths}}
{{#if (eq section "configuration")}}
<Toolbar>
<ToolbarActions>

View File

@ -15,43 +15,45 @@
</Toolbar>
{{#each (sort-by "path" model) as |method|}}
{{#if (contains method.methodType (supported-managed-auth-backends))}}
<LinkedBlock @params={{array
<LinkedBlock @params={{array
"vault.cluster.access.method"
method.id}} class="list-item-row" data-test-auth-backend-link={{method.id}}>
<div class="level is-mobile">
<div class="level-left">
<div>
<ToolTip @horizontalPosition="left" as |T|>
<T.trigger>
<Icon @glyph={{if
(or
(find-by "type" method.methodType (mountable-auth-methods))
(eq method.methodType "token")
)
method.methodType
"auth"
}} @size="l" class="has-text-grey-light" />
</T.trigger>
<T.content @class="tool-tip">
<div class="box">
{{method.methodType}}
</div>
</T.content>
</ToolTip>
<span data-test-path data-test-id={{method.id}} class="has-text-weight-semibold has-text-black">
{{method.path}}
</span>
<br />
<code class="has-text-grey is-size-8">
{{method.accessor}}
</code>
</div>
method.id}} class="list-item-row"
data-test-auth-backend-link={{method.id}}
>
<div class="level is-mobile">
<div class="level-left">
<div>
<ToolTip @horizontalPosition="left" as |T|>
<T.trigger>
<Icon @size="l" class="has-text-grey-light"
@glyph={{if
(or
(find-by "type" method.methodType (mountable-auth-methods))
(eq method.methodType "token")
)
method.methodType
"auth"}}
/>
</T.trigger>
<T.content @class="tool-tip">
<div class="box">
{{method.methodType}}
</div>
</T.content>
</ToolTip>
<span data-test-path data-test-id={{method.id}} class="has-text-weight-semibold has-text-black">
{{method.path}}
</span>
<br />
<code class="has-text-grey is-size-8">
{{method.accessor}}
</code>
</div>
<div class="level-right is-flex is-paddingless is-marginless">
<div class="level-item">
<PopupMenu @name="auth-backend-nav">
<Confirm as |c|>
</div>
<div class="level-right is-flex is-paddingless is-marginless">
<div class="level-item">
<PopupMenu @name="auth-backend-nav">
<Confirm as |c|>
<nav class="menu">
<ul class="menu-list">
<li>
@ -69,88 +71,21 @@
{{#if (and (not-eq method.methodType 'token') method.canDisable)}}
<li class="action">
<c.Message
@id={{method.id}}
@title="Disable method?"
@message="This may affect access to Vault data."
@triggerText="Disable"
@onConfirm={{perform disableMethod method}}>
</c.Message>
<c.Message
@id={{method.id}}
@title="Disable method?"
@message="This may affect access to Vault data."
@triggerText="Disable"
@onConfirm={{perform disableMethod method}}>
</c.Message>
</li>
{{/if}}
</ul>
</nav>
</Confirm>
</PopupMenu>
</div>
</div>
</div>
</LinkedBlock>
{{else}}
<div class="list-item-row" data-test-auth-backend-link={{method.id}}>
<div class="level is-mobile">
<div class="level-left">
<div>
<ToolTip @horizontalPosition="left" as |T|>
<T.trigger>
<Icon @glyph={{if
(or
(find-by "type" method.methodType (mountable-auth-methods))
(eq method.methodType "token")
)
method.methodType
"auth"
}} @size="l" class="has-text-grey-light" />
</T.trigger>
<T.content @class="tool-tip">
<div class="box">
{{method.methodType}}
</div>
</T.content>
</ToolTip>
<span data-test-path data-test-id={{method.id}} class="has-text-weight-semibold has-text-grey">
{{method.path}}
</span>
<br />
<code class="has-text-grey is-size-8">
{{method.accessor}}
</code>
</div>
</div>
<div class="level-right is-flex is-paddingless is-marginless">
<div class="level-item">
<PopupMenu @name="auth-backend-nav">
<Confirm as |c|>
<nav class="menu">
<ul class="menu-list">
<li>
<LinkTo @route="vault.cluster.access.method.section" @models={{array method.id "configuration"}}>
View configuration
</LinkTo>
</li>
{{#if method.canEdit}}
<li>
<LinkTo @route="vault.cluster.settings.auth.configure" @model={{method.id}}>
Edit configuration
</LinkTo>
</li>
{{/if}}
{{#if (and (not-eq method.methodType 'token') method.canDisable)}}
<li class="action">
<c.Message @id={{method.id}} @title="Disable method?"
@message="This may affect access to Vault data." @triggerText="Disable"
@onConfirm={{perform disableMethod method}}>
</c.Message>
</li>
{{/if}}
</ul>
</nav>
</Confirm>
</PopupMenu>
</div>
</Confirm>
</PopupMenu>
</div>
</div>
</div>
{{/if}}
</LinkedBlock>
{{/each}}

View File

@ -2,4 +2,4 @@
{{auth-config-form/options model.model}}
{{else}}
{{auth-config-form/config model.model}}
{{/if}}
{{/if}}

View File

@ -1,11 +1,13 @@
import { click, fillIn, settled, visit, triggerKeyEvent } from '@ember/test-helpers';
import { click, findAll, fillIn, settled, visit, triggerKeyEvent } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import authPage from 'vault/tests/pages/auth';
import logout from 'vault/tests/pages/logout';
import enablePage from 'vault/tests/pages/settings/auth/enable';
import { supportedAuthBackends } from 'vault/helpers/supported-auth-backends';
import { supportedManagedAuthBackends } from 'vault/helpers/supported-managed-auth-backends';
module('Acceptance | userpass secret backend', function(hooks) {
module('Acceptance | auth backend list', function(hooks) {
setupApplicationTest(hooks);
hooks.beforeEach(function() {
@ -16,7 +18,7 @@ module('Acceptance | userpass secret backend', function(hooks) {
return logout.visit();
});
test('userpass backend', async function(assert) {
test('userpass secret backend', async function(assert) {
let n = Math.random();
const path1 = `userpass-${++n}`;
const path2 = `userpass-${++n}`;
@ -73,4 +75,39 @@ module('Acceptance | userpass secret backend', function(hooks) {
.dom('[data-test-list-item-content]')
.hasText(user1, 'first user created shows in current auth list');
});
test('auth methods are linkable and link to correct view', async function(assert) {
await visit('/vault/access');
await settled();
let supportManaged = supportedManagedAuthBackends();
let backends = supportedAuthBackends();
for (let backend of backends) {
let { type } = backend;
if (type !== 'token') {
await enablePage.enable(type, type);
}
await settled();
await visit('/vault/access');
// all auth methods should be linkable
await click(`[data-test-auth-backend-link="${type}"]`);
if (!supportManaged.includes(type)) {
assert.equal(findAll('[data-test-auth-section-tab]').length, 1);
assert
.dom('[data-test-auth-section-tab]')
.hasText('Configuration', `only shows configuration tab for ${type} auth method`);
assert.dom('[data-test-doc-link] .doc-link').exists(`includes doc link for ${type} auth method`);
} else {
// managed auth methods should have more than 1 tab
assert.notEqual(
findAll('[data-test-auth-section-tab]').length,
1,
`has management tabs for ${type} auth method`
);
}
}
});
});