diff --git a/ui/packages/consul-ui/app/adapters/auth-method.js b/ui/packages/consul-ui/app/adapters/auth-method.js
new file mode 100644
index 0000000000..fdfee01cea
--- /dev/null
+++ b/ui/packages/consul-ui/app/adapters/auth-method.js
@@ -0,0 +1,28 @@
+import Adapter from './application';
+
+export default class AuthMethodAdapter extends Adapter {
+ requestForQuery(request, { dc, ns, index, id }) {
+ return request`
+ GET /v1/acl/auth-methods?${{ dc }}
+
+ ${{
+ ...this.formatNspace(ns),
+ index,
+ }}
+ `;
+ }
+
+ requestForQueryRecord(request, { dc, ns, index, id }) {
+ if (typeof id === 'undefined') {
+ throw new Error('You must specify an id');
+ }
+ return request`
+ GET /v1/acl/auth-method/${id}?${{ dc }}
+
+ ${{
+ ...this.formatNspace(ns),
+ index,
+ }}
+ `;
+ }
+}
diff --git a/ui/packages/consul-ui/app/components/consul/auth-method/index.scss b/ui/packages/consul-ui/app/components/consul/auth-method/index.scss
new file mode 100644
index 0000000000..3aef2415ff
--- /dev/null
+++ b/ui/packages/consul-ui/app/components/consul/auth-method/index.scss
@@ -0,0 +1,9 @@
+.consul-auth-method-list ul {
+ .consul-auth-method-type {
+ @extend %pill-200, %frame-gray-600;
+ }
+ .locality::before {
+ @extend %with-public-default-mask, %as-pseudo;
+ margin-right: 4px;
+ }
+}
\ No newline at end of file
diff --git a/ui/packages/consul-ui/app/components/consul/auth-method/list/index.hbs b/ui/packages/consul-ui/app/components/consul/auth-method/list/index.hbs
new file mode 100644
index 0000000000..4b0223f1f5
--- /dev/null
+++ b/ui/packages/consul-ui/app/components/consul/auth-method/list/index.hbs
@@ -0,0 +1,31 @@
+
+
+ {{#if (not-eq item.DisplayName '')}}
+ {{item.DisplayName}}
+ {{else}}
+ {{item.Name}}
+ {{/if}}
+
+
+
+ {{#if (not-eq item.DisplayName '')}}
+ {{item.Name}}
+ {{/if}}
+ {{#if (eq item.TokenLocality 'global')}}
+ creates global tokens
+ {{/if}}
+ {{#if item.MaxTokenTTL}}
+
+
+
+ Maximum Time to Live: the maximum life of any token created by this auth method
+
+
+ {{item.MaxTokenTTL}}
+
+ {{/if}}
+
+
diff --git a/ui/packages/consul-ui/app/components/consul/auth-method/list/pageobject.js b/ui/packages/consul-ui/app/components/consul/auth-method/list/pageobject.js
new file mode 100644
index 0000000000..870bb9a889
--- /dev/null
+++ b/ui/packages/consul-ui/app/components/consul/auth-method/list/pageobject.js
@@ -0,0 +1,7 @@
+export default (collection, text) => () => {
+ return collection('.consul-auth-method-list [data-test-list-row]', {
+ name: text('[data-test-auth-method]'),
+ displayName: text('[data-test-display-name]'),
+ type: text('[data-test-type]'),
+ });
+};
diff --git a/ui/packages/consul-ui/app/components/consul/auth-method/search-bar/index.hbs b/ui/packages/consul-ui/app/components/consul/auth-method/search-bar/index.hbs
new file mode 100644
index 0000000000..2e7e5313fa
--- /dev/null
+++ b/ui/packages/consul-ui/app/components/consul/auth-method/search-bar/index.hbs
@@ -0,0 +1,148 @@
+
+ <:status as |search|>
+
+{{#let
+
+ (t (concat "components.consul.auth-method.search-bar." search.status.key ".name")
+ default=(array
+ (concat "common.search." search.status.key)
+ (concat "common.consul." search.status.key)
+ )
+ )
+
+ (t (concat "components.consul.auth-method.search-bar." search.status.key ".options." search.status.value)
+ default=(array
+ (concat "common.search." search.status.value)
+ (concat "common.consul." search.status.value)
+ (concat "common.brand." search.status.value)
+ )
+ )
+
+as |key value|}}
+
+
+ {{key}}
+ {{value}}
+
+
+{{/let}}
+
+
+ <:search as |search|>
+
+
+
+
+ {{t "common.search.searchproperty"}}
+
+
+
+ {{#let components.Optgroup components.Option as |Optgroup Option|}}
+ {{#each @filter.searchproperty.default as |prop|}}
+
+ {{t (concat "common.consul." (lowercase prop))}}
+
+ {{/each}}
+ {{/let}}
+
+
+
+
+ <:filter as |search|>
+
+
+
+ {{t "components.consul.auth-method.search-bar.kind.name"}}
+
+
+
+ {{#let components.Optgroup components.Option as |Optgroup Option|}}
+ Kubernetes
+ JWT
+ {{#if (env 'CONSUL_SSO_ENABLED')}}
+ OIDC
+ {{/if}}
+ {{/let}}
+
+
+
+
+
+ {{t "components.consul.auth-method.search-bar.locality.name"}}
+
+
+
+ {{#let components.Optgroup components.Option as |Optgroup Option|}}
+ {{#each (array "local" "global") as |option|}}
+
+ {{t (concat "components.consul.auth-method.search-bar.locality.options." option)}}
+
+ {{/each}}
+ {{/let}}
+
+
+
+ <:sort as |search|>
+
+
+
+ {{#let (from-entries (array
+ (array "MethodName:asc" (t "common.sort.alpha.asc"))
+ (array "MethodName:desc" (t "common.sort.alpha.desc"))
+ (array "MaxTokenTTL:desc" (t "common.sort.duration.asc"))
+ (array "MaxTokenTTL:asc" (t "common.sort.duration.desc"))
+ ))
+ as |selectable|
+ }}
+ {{get selectable @sort.value}}
+ {{/let}}
+
+
+
+ {{#let components.Optgroup components.Option as |Optgroup Option|}}
+
+ {{t "common.sort.alpha.asc"}}
+ {{t "common.sort.alpha.desc"}}
+
+
+ {{t "common.sort.duration.asc"}}
+ {{t "common.sort.duration.desc"}}
+
+ {{/let}}
+
+
+
+
diff --git a/ui/packages/consul-ui/app/components/consul/auth-method/type/index.hbs b/ui/packages/consul-ui/app/components/consul/auth-method/type/index.hbs
new file mode 100644
index 0000000000..6aadacc3ca
--- /dev/null
+++ b/ui/packages/consul-ui/app/components/consul/auth-method/type/index.hbs
@@ -0,0 +1,3 @@
+
+ {{t (concat "common.brand." @item.Type)}}
+
diff --git a/ui/packages/consul-ui/app/components/hashicorp-consul/index.hbs b/ui/packages/consul-ui/app/components/hashicorp-consul/index.hbs
index 83b097c39c..bac2214fed 100644
--- a/ui/packages/consul-ui/app/components/hashicorp-consul/index.hbs
+++ b/ui/packages/consul-ui/app/components/hashicorp-consul/index.hbs
@@ -126,6 +126,9 @@
Roles
+
+ Auth Methods
+
{{/if}}
diff --git a/ui/packages/consul-ui/app/filter/predicates/auth-method.js b/ui/packages/consul-ui/app/filter/predicates/auth-method.js
new file mode 100644
index 0000000000..796cd23c6d
--- /dev/null
+++ b/ui/packages/consul-ui/app/filter/predicates/auth-method.js
@@ -0,0 +1,11 @@
+export default {
+ kind: {
+ kubernetes: (item, value) => item.Type === value,
+ jwt: (item, value) => item.Type === value,
+ oidc: (item, value) => item.Type === value,
+ },
+ source: {
+ local: (item, value) => item.TokenLocality === value,
+ global: (item, value) => item.TokenLocality === value,
+ },
+};
diff --git a/ui/packages/consul-ui/app/instance-initializers/nspace.js b/ui/packages/consul-ui/app/instance-initializers/nspace.js
index 8bd6938413..0285415ae7 100644
--- a/ui/packages/consul-ui/app/instance-initializers/nspace.js
+++ b/ui/packages/consul-ui/app/instance-initializers/nspace.js
@@ -99,7 +99,10 @@ export function initialize(container) {
register(container, index, indexed);
}
}
- register(container, route, item);
+
+ if (typeof route !== 'undefined') {
+ register(container, route, item);
+ }
});
}
}
diff --git a/ui/packages/consul-ui/app/models/auth-method.js b/ui/packages/consul-ui/app/models/auth-method.js
new file mode 100644
index 0000000000..a2aaf6c792
--- /dev/null
+++ b/ui/packages/consul-ui/app/models/auth-method.js
@@ -0,0 +1,24 @@
+import Model, { attr } from '@ember-data/model';
+import { or } from '@ember/object/computed';
+
+export const PRIMARY_KEY = 'uid';
+export const SLUG_KEY = 'Name';
+
+export default class AuthMethod extends Model {
+ @attr('string') uid;
+ @attr('string') Name;
+
+ @attr('string') Datacenter;
+ @attr('string') Namespace;
+ @attr('string', { defaultValue: () => '' }) Description;
+ @attr('string', { defaultValue: () => '' }) DisplayName;
+ @attr('string', { defaultValue: () => 'local' }) TokenLocality;
+ @attr('string') Type;
+ @or('DisplayName', 'Name') MethodName;
+ @attr() Config;
+ @attr('string') MaxTokenTTL;
+ @attr('number') CreateIndex;
+ @attr('number') ModifyIndex;
+ @attr() Datacenters; // string[]
+ @attr() meta; // {}
+}
diff --git a/ui/packages/consul-ui/app/router.js b/ui/packages/consul-ui/app/router.js
index a85c772475..f931be9631 100644
--- a/ui/packages/consul-ui/app/router.js
+++ b/ui/packages/consul-ui/app/router.js
@@ -149,6 +149,12 @@ export const routes = {
_options: { path: '/create' },
},
},
+ 'auth-methods': {
+ _options: { path: '/auth-methods' },
+ show: {
+ _options: { path: '/show' },
+ },
+ },
},
},
// Shows a datacenter picker. If you only have one
diff --git a/ui/packages/consul-ui/app/routes/dc/acls/auth-methods/index.js b/ui/packages/consul-ui/app/routes/dc/acls/auth-methods/index.js
new file mode 100644
index 0000000000..f45d92397b
--- /dev/null
+++ b/ui/packages/consul-ui/app/routes/dc/acls/auth-methods/index.js
@@ -0,0 +1,38 @@
+import { inject as service } from '@ember/service';
+import Route from 'consul-ui/routing/route';
+import { hash } from 'rsvp';
+
+export default class IndexRoute extends Route {
+ @service('repository/auth-method') repo;
+
+ queryParams = {
+ sortBy: 'sort',
+ source: 'source',
+ kind: 'kind',
+ searchproperty: {
+ as: 'searchproperty',
+ empty: [['Name', 'DisplayName']],
+ },
+ search: {
+ as: 'filter',
+ replace: true,
+ },
+ };
+
+ model(params) {
+ return hash({
+ ...this.repo.status({
+ items: this.repo.findAllByDatacenter(
+ this.modelFor('dc').dc.Name,
+ this.modelFor('nspace').nspace.substr(1)
+ ),
+ }),
+ searchProperties: this.queryParams.searchproperty.empty[0],
+ });
+ }
+
+ setupController(controller, model) {
+ super.setupController(...arguments);
+ controller.setProperties(model);
+ }
+}
diff --git a/ui/packages/consul-ui/app/search/predicates/auth-method.js b/ui/packages/consul-ui/app/search/predicates/auth-method.js
new file mode 100644
index 0000000000..15a6cf3514
--- /dev/null
+++ b/ui/packages/consul-ui/app/search/predicates/auth-method.js
@@ -0,0 +1,4 @@
+export default {
+ Name: item => item.Name,
+ DisplayName: item => item.DisplayName,
+};
diff --git a/ui/packages/consul-ui/app/serializers/auth-method.js b/ui/packages/consul-ui/app/serializers/auth-method.js
new file mode 100644
index 0000000000..435382c684
--- /dev/null
+++ b/ui/packages/consul-ui/app/serializers/auth-method.js
@@ -0,0 +1,7 @@
+import Serializer from './application';
+import { PRIMARY_KEY, SLUG_KEY } from 'consul-ui/models/auth-method';
+
+export default class AuthMethodSerializer extends Serializer {
+ primaryKey = PRIMARY_KEY;
+ slugKey = SLUG_KEY;
+}
diff --git a/ui/packages/consul-ui/app/services/filter.js b/ui/packages/consul-ui/app/services/filter.js
index 89b2cf8692..7a521f9e16 100644
--- a/ui/packages/consul-ui/app/services/filter.js
+++ b/ui/packages/consul-ui/app/services/filter.js
@@ -10,12 +10,14 @@ import kv from 'consul-ui/filter/predicates/kv';
import intention from 'consul-ui/filter/predicates/intention';
import token from 'consul-ui/filter/predicates/token';
import policy from 'consul-ui/filter/predicates/policy';
+import authMethod from 'consul-ui/filter/predicates/auth-method';
const predicates = {
acl: andOr(acl),
service: andOr(service),
['service-instance']: andOr(serviceInstance),
['health-check']: andOr(healthCheck),
+ ['auth-method']: andOr(authMethod),
node: andOr(node),
kv: andOr(kv),
intention: andOr(intention),
diff --git a/ui/packages/consul-ui/app/services/repository/auth-method.js b/ui/packages/consul-ui/app/services/repository/auth-method.js
new file mode 100644
index 0000000000..818b3ecacb
--- /dev/null
+++ b/ui/packages/consul-ui/app/services/repository/auth-method.js
@@ -0,0 +1,26 @@
+import RepositoryService from 'consul-ui/services/repository';
+import statusFactory from 'consul-ui/utils/acls-status';
+import isValidServerErrorFactory from 'consul-ui/utils/http/acl/is-valid-server-error';
+import { PRIMARY_KEY, SLUG_KEY } from 'consul-ui/models/auth-method';
+
+const isValidServerError = isValidServerErrorFactory();
+const status = statusFactory(isValidServerError, Promise);
+const MODEL_NAME = 'auth-method';
+
+export default class AuthMethodService extends RepositoryService {
+ getModelName() {
+ return MODEL_NAME;
+ }
+
+ getPrimaryKey() {
+ return PRIMARY_KEY;
+ }
+
+ getSlugKey() {
+ return SLUG_KEY;
+ }
+
+ status(obj) {
+ return status(obj);
+ }
+}
diff --git a/ui/packages/consul-ui/app/services/search.js b/ui/packages/consul-ui/app/services/search.js
index 086bd43266..dce0d897a6 100644
--- a/ui/packages/consul-ui/app/services/search.js
+++ b/ui/packages/consul-ui/app/services/search.js
@@ -13,6 +13,7 @@ import kv from 'consul-ui/search/predicates/kv';
import token from 'consul-ui/search/predicates/token';
import role from 'consul-ui/search/predicates/role';
import policy from 'consul-ui/search/predicates/policy';
+import authMethod from 'consul-ui/search/predicates/auth-method';
import nspace from 'consul-ui/search/predicates/nspace';
const predicates = {
@@ -21,6 +22,7 @@ const predicates = {
['service-instance']: serviceInstance,
['upstream-instance']: upstreamInstance,
['health-check']: healthCheck,
+ ['auth-method']: authMethod,
node: node,
kv: kv,
acl: acl,
diff --git a/ui/packages/consul-ui/app/services/sort.js b/ui/packages/consul-ui/app/services/sort.js
index dd63993900..44ff5aac7b 100644
--- a/ui/packages/consul-ui/app/services/sort.js
+++ b/ui/packages/consul-ui/app/services/sort.js
@@ -9,6 +9,7 @@ import intention from 'consul-ui/sort/comparators/intention';
import token from 'consul-ui/sort/comparators/token';
import role from 'consul-ui/sort/comparators/role';
import policy from 'consul-ui/sort/comparators/policy';
+import authMethod from 'consul-ui/sort/comparators/auth-method';
import nspace from 'consul-ui/sort/comparators/nspace';
import node from 'consul-ui/sort/comparators/node';
@@ -32,6 +33,7 @@ const comparators = {
['service-instance']: serviceInstance(options),
['upstream-instance']: upstreamInstance(options),
['health-check']: healthCheck(options),
+ ['auth-method']: authMethod(options),
acl: acl(options),
kv: kv(options),
intention: intention(options),
diff --git a/ui/packages/consul-ui/app/sort/comparators/auth-method.js b/ui/packages/consul-ui/app/sort/comparators/auth-method.js
new file mode 100644
index 0000000000..fafacd3fff
--- /dev/null
+++ b/ui/packages/consul-ui/app/sort/comparators/auth-method.js
@@ -0,0 +1,3 @@
+export default ({ properties }) => (key = 'MethodName:asc') => {
+ return properties(['MethodName', 'MaxTokenTTL'])(key);
+};
diff --git a/ui/packages/consul-ui/app/styles/base/icons/base-variables.scss b/ui/packages/consul-ui/app/styles/base/icons/base-variables.scss
index 35f6f25261..2dd1a649e7 100644
--- a/ui/packages/consul-ui/app/styles/base/icons/base-variables.scss
+++ b/ui/packages/consul-ui/app/styles/base/icons/base-variables.scss
@@ -77,6 +77,7 @@ $history-svg: url('data:image/svg+xml;charset=UTF-8, ');
$info-circle-fill-svg: url('data:image/svg+xml;charset=UTF-8, ');
$info-circle-outline-svg: url('data:image/svg+xml;charset=UTF-8, ');
+$jwt-logo-svg: url('data:image/svg+xml;charset=UTF-8, ');
$key-svg: url('data:image/svg+xml;charset=UTF-8, ');
$kubernetes-logo-color-svg: url('data:image/svg+xml;charset=UTF-8, ');
$layers-svg: url('data:image/svg+xml;charset=UTF-8, ');
@@ -128,6 +129,7 @@ $nomad-logo-color-svg: url('data:image/svg+xml;charset=UTF-8, ');
$notification-fill-svg: url('data:image/svg+xml;charset=UTF-8, ');
$notification-outline-svg: url('data:image/svg+xml;charset=UTF-8, ');
+$oidc-logo-svg: url('data:image/svg+xml;charset=UTF-8, ');
$outline-svg: url('data:image/svg+xml;charset=UTF-8, ');
$page-outline-svg: url('data:image/svg+xml;charset=UTF-8, ');
$partner-svg: url('data:image/svg+xml;charset=UTF-8, ');
diff --git a/ui/packages/consul-ui/app/styles/base/icons/icon-placeholders.scss b/ui/packages/consul-ui/app/styles/base/icons/icon-placeholders.scss
index a497982733..15e4366d12 100644
--- a/ui/packages/consul-ui/app/styles/base/icons/icon-placeholders.scss
+++ b/ui/packages/consul-ui/app/styles/base/icons/icon-placeholders.scss
@@ -778,6 +778,16 @@
mask-image: $info-circle-outline-svg;
}
+%with-jwt-logo-icon {
+ @extend %with-icon;
+ background-image: $jwt-logo-svg;
+}
+%with-jwt-logo-mask {
+ @extend %with-mask;
+ -webkit-mask-image: $jwt-logo-svg;
+ mask-image: $jwt-logo-svg;
+}
+
%with-key-icon {
@extend %with-icon;
background-image: $key-svg;
@@ -1316,6 +1326,16 @@
mask-image: $notification-outline-svg;
}
+%with-oidc-logo-icon {
+ @extend %with-icon;
+ background-image: $oidc-logo-svg;
+}
+%with-oidc-logo-mask {
+ @extend %with-mask;
+ -webkit-mask-image: $oidc-logo-svg;
+ mask-image: $oidc-logo-svg;
+}
+
%with-outline-icon {
@extend %with-icon;
background-image: $outline-svg;
diff --git a/ui/packages/consul-ui/app/styles/components.scss b/ui/packages/consul-ui/app/styles/components.scss
index 1a22481b48..51765dab26 100644
--- a/ui/packages/consul-ui/app/styles/components.scss
+++ b/ui/packages/consul-ui/app/styles/components.scss
@@ -74,6 +74,7 @@
@import 'consul-ui/components/consul/kind';
@import 'consul-ui/components/consul/intention';
@import 'consul-ui/components/consul/lock-session/form';
+@import 'consul-ui/components/consul/auth-method';
@import 'consul-ui/components/role-selector';
@import 'consul-ui/components/topology-metrics';
diff --git a/ui/packages/consul-ui/app/styles/components/pill.scss b/ui/packages/consul-ui/app/styles/components/pill.scss
index 038a7e93e9..236eac8daf 100644
--- a/ui/packages/consul-ui/app/styles/components/pill.scss
+++ b/ui/packages/consul-ui/app/styles/components/pill.scss
@@ -33,3 +33,9 @@ span.policy-service-identity::before {
%pill.leader::before {
@extend %with-star-outline-mask, %as-pseudo;
}
+%pill.jwt::before {
+ @extend %with-jwt-logo-icon, %as-pseudo;
+}
+%pill.oidc::before {
+ @extend %with-oidc-logo-icon, %as-pseudo;
+}
diff --git a/ui/packages/consul-ui/app/styles/components/popover-select.scss b/ui/packages/consul-ui/app/styles/components/popover-select.scss
index 6cad84b09c..6f7653da83 100644
--- a/ui/packages/consul-ui/app/styles/components/popover-select.scss
+++ b/ui/packages/consul-ui/app/styles/components/popover-select.scss
@@ -49,6 +49,12 @@
%popover-select .kubernetes button::before {
@extend %with-logo-kubernetes-color-icon, %as-pseudo;
}
+%popover-select .jwt button::before {
+ @extend %with-jwt-logo-icon, %as-pseudo;
+}
+%popover-select .oidc button::before {
+ @extend %with-oidc-logo-icon, %as-pseudo;
+}
%popover-select .consul button::before {
@extend %with-logo-consul-color-icon, %as-pseudo;
}
diff --git a/ui/packages/consul-ui/app/templates/dc/acls/auth-methods/index.hbs b/ui/packages/consul-ui/app/templates/dc/acls/auth-methods/index.hbs
new file mode 100644
index 0000000000..95f507c8e1
--- /dev/null
+++ b/ui/packages/consul-ui/app/templates/dc/acls/auth-methods/index.hbs
@@ -0,0 +1,102 @@
+{{#if isAuthorized }}
+ {{page-title 'Auth Methods'}}
+{{else}}
+ {{page-title 'Access Controls'}}
+{{/if}}
+
+{{#let
+
+ (hash
+ value=(or sortBy "MethodName:asc")
+ change=(action (mut sortBy) value="target.selected")
+ )
+
+ (hash
+ kind=(hash
+ value=(if kind (split kind ',') undefined)
+ change=(action (mut kind) value="target.selectedItems")
+ )
+ source=(hash
+ value=(if source (split source ',') undefined)
+ change=(action (mut source) value="target.selectedItems")
+ )
+ searchproperty=(hash
+ value=(if (not-eq searchproperty undefined)
+ (split searchproperty ',')
+ searchProperties
+ )
+ change=(action (mut searchproperty) value="target.selectedItems")
+ default=searchProperties
+ )
+ )
+
+ items
+
+as |sort filters items|}}
+
+
+
+
+
+ Access Controls
+
+
+
+ {{#if (gt items.length 0)}}
+
+ {{/if}}
+
+
+
+
+
+
+
+
+
+
+ {{#if (gt items.length 0)}}
+ No auth methods found
+ {{else}}
+ Welcome to Auth Methods
+ {{/if}}
+
+
+
+
+ {{#if (gt items.length 0)}}
+ No auth methods where found matching that search, or you may not have access to view the auth methods you are searching for.
+ {{else}}
+ There don't seem to be any auth methods, or you may not have access to view auth methods yet.
+ {{/if}}
+
+
+
+
+ Documentation on auth methods
+
+
+ Read the API Docs
+
+
+
+
+
+
+
+{{/let}}
+
diff --git a/ui/packages/consul-ui/app/templates/dc/acls/roles/index.hbs b/ui/packages/consul-ui/app/templates/dc/acls/roles/index.hbs
index aee311bdd3..af50974f1a 100644
--- a/ui/packages/consul-ui/app/templates/dc/acls/roles/index.hbs
+++ b/ui/packages/consul-ui/app/templates/dc/acls/roles/index.hbs
@@ -97,7 +97,7 @@ as |sort filters items|}}
Documentation on roles
- Read the guide
+ Read the API Docs
diff --git a/ui/packages/consul-ui/mock-api/v1/acl/auth-method/_ b/ui/packages/consul-ui/mock-api/v1/acl/auth-method/_
new file mode 100644
index 0000000000..2cd545e4e3
--- /dev/null
+++ b/ui/packages/consul-ui/mock-api/v1/acl/auth-method/_
@@ -0,0 +1,44 @@
+${
+ [1].map(() => {
+ const type = `${fake.helpers.randomize(['kubernetes', 'jwt', 'oidc'])}`;
+ const fakeIP = `${fake.internet.ip()}`;
+ let config = {};
+ switch(type) {
+ case 'kubernetes':
+ config = {
+ Host: `https://${fake.internet.ip()}:8443`,
+ CACert: `-----BEGIN CERTIFICATE-----${fake.internet.password(1357)}-----END CERTIFICATE-----`,
+ ServiceAccountJWT: `eyJhbGciOiJ${fake.internet.password(25)}.eyJ${fake.internet.password(61)}.${fake.internet.password(32)}`
+ };
+ break;
+ case 'oidc':
+ config = {
+ OIDCDiscoveryURL: `https://${fake.internet.ip()}:8443`,
+ };
+ break;
+ case 'jwt':
+ config = {
+ JWTValidationPubKeys: `-----BEGIN CERTIFICATE-----${fake.internet.password(1357)}-----END CERTIFICATE-----`,
+ JWKSURL: `https://${fake.internet.ip()}:8443`,
+ OIDCDiscoveryURL: `https://${fake.internet.ip()}:8443`,
+ };
+ break;
+ }
+
+ return `{
+ "Name": "${location.pathname.get(3)}",
+ "Namespace": "${
+ typeof location.search.ns !== 'undefined' ? location.search.ns :
+ typeof http.body.Namespace !== 'undefined' ? http.body.Namespace : 'default'
+ }",
+ "Type": "${type}",
+ "Description": "${fake.lorem.sentence()}",
+ "DisplayName": "${fake.hacker.noun()}",
+ "MaxTokenTTL": "${fake.random.number({min: 0, max: 60})}m${fake.random.number({min: 0, max: 60})}s",
+ "TokenLocality": "${fake.helpers.randomize(['local', 'global', ''])}",
+ "Config": ${JSON.stringify(config)},
+ "CreateIndex": ${fake.random.number()},
+ "ModifyIndex": 10
+ }`
+ })
+}
diff --git a/ui/packages/consul-ui/mock-api/v1/acl/auth-methods b/ui/packages/consul-ui/mock-api/v1/acl/auth-methods
new file mode 100644
index 0000000000..d5697e5a05
--- /dev/null
+++ b/ui/packages/consul-ui/mock-api/v1/acl/auth-methods
@@ -0,0 +1,42 @@
+[
+ ${
+ range(
+ env(
+ 'CONSUL_AUTH_METHOD_COUNT',
+ Math.floor(
+ (
+ Math.random() * env('CONSUL_AUTH_METHOD_MAX', 10)
+ ) + parseInt(env('CONSUL_AUTH_METHOD_MIN', 1))
+ )
+ )
+ ).map(
+ function(item, i) {
+ return `
+ {
+ "Name": "${fake.hacker.noun()}-${i}",
+${typeof location.search.ns !== 'undefined' ? `
+ "Namespace": "${location.search.ns}",
+` : ``}
+ "Type": "${fake.helpers.randomize(['kubernetes', 'jwt', 'oidc'])}",
+ "Description": "${fake.lorem.sentence()}",
+${i%2 ? `
+ "DisplayName": "${fake.hacker.noun()}-${i}",
+` : `
+ "DisplayName": "",
+`}
+${i%2 ? `
+ "MaxTokenTTL": "${fake.random.number({min: 0, max: 60})}m${fake.random.number({min: 0, max: 60})}s",
+` : `
+`}
+${i%2 ? `
+ "TokenLocality": "${fake.helpers.randomize(['local', 'global', ''])}",
+` : `
+`}
+ "CreateIndex": ${fake.random.number()},
+ "ModifyIndex": 10
+ }
+ `
+ }
+ )
+ }
+]
diff --git a/ui/packages/consul-ui/tests/acceptance/dc/acls/auth-methods/index.feature b/ui/packages/consul-ui/tests/acceptance/dc/acls/auth-methods/index.feature
new file mode 100644
index 0000000000..68da2e61f7
--- /dev/null
+++ b/ui/packages/consul-ui/tests/acceptance/dc/acls/auth-methods/index.feature
@@ -0,0 +1,48 @@
+@setupApplicationTest
+Feature: dc / acls / auth-methods / index: ACL Auth Methods List
+
+ Scenario:
+ Given 1 datacenter model with the value "dc-1"
+ And 3 authMethod models
+ When I visit the authMethods page for yaml
+ ---
+ dc: dc-1
+ ---
+ Then the url should be /dc-1/acls/auth-methods
+ Then I see 3 authMethod models
+ And the title should be "Auth Methods - Consul"
+ Scenario: Searching the Auth Methods
+ Given 1 datacenter model with the value "dc-1"
+ And 3 authMethod models from yaml
+ ---
+ - Name: kube
+ DisplayName: minikube
+ - Name: agent
+ DisplayName: ''
+ - Name: node
+ DisplayName: mininode
+ ---
+ When I visit the authMethods page for yaml
+ ---
+ dc: dc-1
+ ---
+ Then the url should be /dc-1/acls/auth-methods
+ Then I see 3 authMethod models
+ Then I fill in with yaml
+ ---
+ s: kube
+ ---
+ And I see 1 authMethod model
+ And I see 1 authMethod model with the name "minikube"
+ Then I fill in with yaml
+ ---
+ s: agent
+ ---
+ And I see 1 authMethod model
+ And I see 1 authMethod model with the name "agent"
+ Then I fill in with yaml
+ ---
+ s: ode
+ ---
+ And I see 1 authMethod model
+ And I see 1 authMethod model with the name "mininode"
diff --git a/ui/packages/consul-ui/tests/acceptance/dc/acls/auth-methods/sorting.feature b/ui/packages/consul-ui/tests/acceptance/dc/acls/auth-methods/sorting.feature
new file mode 100644
index 0000000000..11cd0e4d89
--- /dev/null
+++ b/ui/packages/consul-ui/tests/acceptance/dc/acls/auth-methods/sorting.feature
@@ -0,0 +1,39 @@
+@setupApplicationTest
+Feature: dc / acls / auth-methods / sorting
+ Scenario: Sorting Auth Methods
+ Given 1 datacenter model with the value "dc-1"
+ And 4 authMethod models from yaml
+ ---
+ - Name: "system-A"
+ DisplayName: ''
+ - Name: "system-D"
+ DisplayName: ''
+ - Name: "system-C"
+ DisplayName: ''
+ - Name: "system-B"
+ DisplayName: ''
+ ---
+ When I visit the authMethods page for yaml
+ ---
+ dc: dc-1
+ ---
+ Then the url should be /dc-1/acls/auth-methods
+ Then I see 4 authMethod models
+ When I click selected on the sort
+ When I click options.1.button on the sort
+ Then I see name on the authMethods vertically like yaml
+ ---
+ - "system-D"
+ - "system-C"
+ - "system-B"
+ - "system-A"
+ ---
+ When I click selected on the sort
+ When I click options.0.button on the sort
+ Then I see name on the authMethods vertically like yaml
+ ---
+ - "system-A"
+ - "system-B"
+ - "system-C"
+ - "system-D"
+ ---
diff --git a/ui/packages/consul-ui/tests/acceptance/steps/dc/acls/auth-methods/index-steps.js b/ui/packages/consul-ui/tests/acceptance/steps/dc/acls/auth-methods/index-steps.js
new file mode 100644
index 0000000000..3231912b98
--- /dev/null
+++ b/ui/packages/consul-ui/tests/acceptance/steps/dc/acls/auth-methods/index-steps.js
@@ -0,0 +1,10 @@
+import steps from '../../../steps';
+
+// step definitions that are shared between features should be moved to the
+// tests/acceptance/steps/steps.js file
+
+export default function(assert) {
+ return steps(assert).then('I should find a file', function() {
+ assert.ok(true, this.step);
+ });
+}
diff --git a/ui/packages/consul-ui/tests/acceptance/steps/dc/acls/auth-methods/sorting-steps.js b/ui/packages/consul-ui/tests/acceptance/steps/dc/acls/auth-methods/sorting-steps.js
new file mode 100644
index 0000000000..3231912b98
--- /dev/null
+++ b/ui/packages/consul-ui/tests/acceptance/steps/dc/acls/auth-methods/sorting-steps.js
@@ -0,0 +1,10 @@
+import steps from '../../../steps';
+
+// step definitions that are shared between features should be moved to the
+// tests/acceptance/steps/steps.js file
+
+export default function(assert) {
+ return steps(assert).then('I should find a file', function() {
+ assert.ok(true, this.step);
+ });
+}
diff --git a/ui/packages/consul-ui/tests/helpers/set-cookies.js b/ui/packages/consul-ui/tests/helpers/set-cookies.js
index 53ff9872c8..772b8fe439 100644
--- a/ui/packages/consul-ui/tests/helpers/set-cookies.js
+++ b/ui/packages/consul-ui/tests/helpers/set-cookies.js
@@ -42,6 +42,10 @@ export default function(type, value) {
key = 'CONSUL_TOKEN_COUNT';
obj['CONSUL_ACLS_ENABLE'] = 1;
break;
+ case 'authMethod':
+ key = 'CONSUL_AUTH_METHOD_COUNT';
+ obj['CONSUL_ACLS_ENABLE'] = 1;
+ break;
case 'nspace':
key = 'CONSUL_NSPACE_COUNT';
break;
diff --git a/ui/packages/consul-ui/tests/helpers/type-to-url.js b/ui/packages/consul-ui/tests/helpers/type-to-url.js
index 905480bee7..aa45c3fb31 100644
--- a/ui/packages/consul-ui/tests/helpers/type-to-url.js
+++ b/ui/packages/consul-ui/tests/helpers/type-to-url.js
@@ -35,6 +35,9 @@ export default function(type) {
case 'token':
requests = ['/v1/acl/tokens', '/v1/acl/token/'];
break;
+ case 'authMethod':
+ requests = ['/v1/acl/auth-methods', '/v1/acl/auth-method/'];
+ break;
case 'nspace':
requests = ['/v1/namespaces', '/v1/namespace/'];
break;
diff --git a/ui/packages/consul-ui/tests/integration/adapters/auth-method-test.js b/ui/packages/consul-ui/tests/integration/adapters/auth-method-test.js
new file mode 100644
index 0000000000..8c41801ac2
--- /dev/null
+++ b/ui/packages/consul-ui/tests/integration/adapters/auth-method-test.js
@@ -0,0 +1,50 @@
+import { module, test } from 'qunit';
+import { setupTest } from 'ember-qunit';
+import getNspaceRunner from 'consul-ui/tests/helpers/get-nspace-runner';
+
+const nspaceRunner = getNspaceRunner('auth-method');
+module('Integration | Adapter | auth-method', function(hooks) {
+ setupTest(hooks);
+ const dc = 'dc-1';
+ const id = 'slug';
+ test('requestForQueryRecord returns the correct url/method', function(assert) {
+ const adapter = this.owner.lookup('adapter:auth-method');
+ const client = this.owner.lookup('service:client/http');
+ const expected = `GET /v1/acl/auth-method/${id}?dc=${dc}`;
+ const actual = adapter.requestForQueryRecord(client.requestParams.bind(client), {
+ dc: dc,
+ id: id,
+ });
+ assert.equal(`${actual.method} ${actual.url}`, expected);
+ });
+ test("requestForQueryRecord throws if you don't specify an id", function(assert) {
+ const adapter = this.owner.lookup('adapter:auth-method');
+ const client = this.owner.lookup('service:client/http');
+ assert.throws(function() {
+ adapter.requestForQueryRecord(client.url, {
+ dc: dc,
+ });
+ });
+ });
+ test('requestForQueryRecord returns the correct body', function(assert) {
+ return nspaceRunner(
+ (adapter, serializer, client) => {
+ return adapter.requestForQueryRecord(client.body, {
+ id: id,
+ dc: dc,
+ ns: 'team-1',
+ index: 1,
+ });
+ },
+ {
+ index: 1,
+ ns: 'team-1',
+ },
+ {
+ index: 1,
+ },
+ this,
+ assert
+ );
+ });
+});
diff --git a/ui/packages/consul-ui/tests/integration/serializers/auth-method-test.js b/ui/packages/consul-ui/tests/integration/serializers/auth-method-test.js
new file mode 100644
index 0000000000..002f662f19
--- /dev/null
+++ b/ui/packages/consul-ui/tests/integration/serializers/auth-method-test.js
@@ -0,0 +1,75 @@
+import { module, test, skip } from 'qunit';
+import { setupTest } from 'ember-qunit';
+import { get } from 'consul-ui/tests/helpers/api';
+import {
+ HEADERS_SYMBOL as META,
+ HEADERS_DATACENTER as DC,
+ HEADERS_NAMESPACE as NSPACE,
+} from 'consul-ui/utils/http/consul';
+module('Integration | Serializer | auth-method', function(hooks) {
+ setupTest(hooks);
+ const dc = 'dc-1';
+ const id = 'auth-method-name';
+ const undefinedNspace = 'default';
+ [undefinedNspace, 'team-1', undefined].forEach(nspace => {
+ test(`respondForQuery returns the correct data for list endpoint when nspace is ${nspace}`, function(assert) {
+ const serializer = this.owner.lookup('serializer:auth-method');
+ const request = {
+ url: `/v1/acl/auth-methods?dc=${dc}${typeof nspace !== 'undefined' ? `&ns=${nspace}` : ``}`,
+ };
+ return get(request.url).then(function(payload) {
+ const expected = payload.map(item =>
+ Object.assign({}, item, {
+ Datacenter: dc,
+ Namespace: item.Namespace || undefinedNspace,
+ uid: `["${item.Namespace || undefinedNspace}","${dc}","${item.Name}"]`,
+ })
+ );
+ const actual = serializer.respondForQuery(
+ function(cb) {
+ const headers = {};
+ const body = payload;
+ return cb(headers, body);
+ },
+ {
+ dc: dc,
+ ns: nspace,
+ }
+ );
+ assert.deepEqual(actual, expected);
+ });
+ });
+ skip(`respondForQueryRecord returns the correct data for item endpoint when nspace is ${nspace}`, function(assert) {
+ const serializer = this.owner.lookup('serializer:auth-method');
+ const request = {
+ url: `/v1/acl/auth-method/${id}?dc=${dc}${
+ typeof nspace !== 'undefined' ? `&ns=${nspace}` : ``
+ }`,
+ };
+ return get(request.url).then(function(payload) {
+ const expected = Object.assign({}, payload, {
+ Datacenter: dc,
+ [META]: {
+ [DC.toLowerCase()]: dc,
+ [NSPACE.toLowerCase()]: payload.Namespace || undefinedNspace,
+ },
+ Namespace: payload.Namespace || undefinedNspace,
+ uid: `["${payload.Namespace || undefinedNspace}","${dc}","${id}"]`,
+ });
+ const actual = serializer.respondForQueryRecord(
+ function(cb) {
+ const headers = {};
+ const body = payload;
+ return cb(headers, body);
+ },
+ {
+ dc: dc,
+ ns: nspace,
+ id: id,
+ }
+ );
+ assert.deepEqual(actual, expected);
+ });
+ });
+ });
+});
diff --git a/ui/packages/consul-ui/tests/integration/services/repository/auth-method-test.js b/ui/packages/consul-ui/tests/integration/services/repository/auth-method-test.js
new file mode 100644
index 0000000000..2d489be3a6
--- /dev/null
+++ b/ui/packages/consul-ui/tests/integration/services/repository/auth-method-test.js
@@ -0,0 +1,82 @@
+import { moduleFor, test } from 'ember-qunit';
+import repo from 'consul-ui/tests/helpers/repo';
+import { skip } from 'qunit';
+
+const NAME = 'auth-method';
+moduleFor(`service:repository/${NAME}`, `Integration | Service | ${NAME}`, {
+ // Specify the other units that are required for this test.
+ integration: true,
+});
+const dc = 'dc-1';
+const id = 'auth-method-name';
+const undefinedNspace = 'default';
+[undefinedNspace, 'team-1', undefined].forEach(nspace => {
+ test(`findAllByDatacenter returns the correct data for list endpoint when nspace is ${nspace}`, function(assert) {
+ return repo(
+ 'auth-method',
+ 'findAllByDatacenter',
+ this.subject(),
+ function retrieveStub(stub) {
+ return stub(
+ `/v1/acl/auth-methods?dc=${dc}${typeof nspace !== 'undefined' ? `&ns=${nspace}` : ``}`,
+ {
+ CONSUL_AUTH_METHOD_COUNT: '3',
+ }
+ );
+ },
+ function performTest(service) {
+ return service.findAllByDatacenter(dc, nspace || undefinedNspace);
+ },
+ function performAssertion(actual, expected) {
+ assert.deepEqual(
+ actual,
+ expected(function(payload) {
+ return payload.map(function(item) {
+ return Object.assign({}, item, {
+ Datacenter: dc,
+ Namespace: item.Namespace || undefinedNspace,
+ uid: `["${item.Namespace || undefinedNspace}","${dc}","${item.Name}"]`,
+ });
+ });
+ })
+ );
+ }
+ );
+ });
+ skip(`findBySlug returns the correct data for item endpoint when the nspace is ${nspace}`, function(assert) {
+ return repo(
+ 'AuthMethod',
+ 'findBySlug',
+ this.subject(),
+ function retrieveStub(stub) {
+ return stub(
+ `/v1/acl/auth-method/${id}?dc=${dc}${
+ typeof nspace !== 'undefined' ? `&ns=${nspace}` : ``
+ }`
+ );
+ },
+ function performTest(service) {
+ return service.findBySlug(id, dc, nspace || undefinedNspace);
+ },
+ function performAssertion(actual, expected) {
+ assert.deepEqual(
+ actual,
+ expected(function(payload) {
+ const item = payload;
+ return Object.assign({}, item, {
+ Datacenter: dc,
+ Namespace: item.Namespace || undefinedNspace,
+ uid: `["${item.Namespace || undefinedNspace}","${dc}","${item.Name}"]`,
+ meta: {
+ cacheControl: undefined,
+ cursor: undefined,
+ dc: dc,
+ nspace: item.Namespace || undefinedNspace,
+ },
+ });
+ })
+ );
+ }
+ );
+ });
+});
diff --git a/ui/packages/consul-ui/tests/pages.js b/ui/packages/consul-ui/tests/pages.js
index 3512763071..26d7f00ce7 100644
--- a/ui/packages/consul-ui/tests/pages.js
+++ b/ui/packages/consul-ui/tests/pages.js
@@ -42,6 +42,7 @@ import consulUpstreamInstanceListFactory from 'consul-ui/components/consul/upstr
import consulTokenListFactory from 'consul-ui/components/consul/token/list/pageobject';
import consulRoleListFactory from 'consul-ui/components/consul/role/list/pageobject';
import consulPolicyListFactory from 'consul-ui/components/consul/policy/list/pageobject';
+import consulAuthMethodListFactory from 'consul-ui/components/consul/auth-method/list/pageobject';
import consulIntentionListFactory from 'consul-ui/components/consul/intention/list/pageobject';
import consulNspaceListFactory from 'consul-ui/components/consul/nspace/list/pageobject';
import consulKvListFactory from 'consul-ui/components/consul/kv/list/pageobject';
@@ -65,6 +66,7 @@ import roles from 'consul-ui/tests/pages/dc/acls/roles/index';
import role from 'consul-ui/tests/pages/dc/acls/roles/edit';
import tokens from 'consul-ui/tests/pages/dc/acls/tokens/index';
import token from 'consul-ui/tests/pages/dc/acls/tokens/edit';
+import authMethods from 'consul-ui/tests/pages/dc/acls/auth-methods/index';
import intentions from 'consul-ui/tests/pages/dc/intentions/index';
import intention from 'consul-ui/tests/pages/dc/intentions/edit';
import nspaces from 'consul-ui/tests/pages/dc/nspaces/index';
@@ -90,6 +92,7 @@ const emptyState = emptyStateFactory(isPresent);
const consulHealthCheckList = consulHealthCheckListFactory(collection, text);
const consulUpstreamInstanceList = consulUpstreamInstanceListFactory(collection, text);
+const consulAuthMethodList = consulAuthMethodListFactory(collection, text);
const consulIntentionList = consulIntentionListFactory(
collection,
clickable,
@@ -191,6 +194,7 @@ export default {
token: create(
token(visitable, submitable, deletable, cancelable, clickable, policySelector, roleSelector)
),
+ authMethods: create(authMethods(visitable, creatable, consulAuthMethodList, popoverSelect)),
intentions: create(
intentions(visitable, creatable, clickable, consulIntentionList, popoverSelect)
),
diff --git a/ui/packages/consul-ui/tests/pages/dc/acls/auth-methods/index.js b/ui/packages/consul-ui/tests/pages/dc/acls/auth-methods/index.js
new file mode 100644
index 0000000000..030736cdcb
--- /dev/null
+++ b/ui/packages/consul-ui/tests/pages/dc/acls/auth-methods/index.js
@@ -0,0 +1,7 @@
+export default function(visitable, creatable, authMethods, popoverSelect) {
+ return creatable({
+ visit: visitable('/:dc/acls/auth-methods'),
+ authMethods: authMethods(),
+ sort: popoverSelect('[data-test-sort-control]'),
+ });
+}
diff --git a/ui/packages/consul-ui/tests/unit/adapters/auth-method-test.js b/ui/packages/consul-ui/tests/unit/adapters/auth-method-test.js
new file mode 100644
index 0000000000..9b1e31a6c9
--- /dev/null
+++ b/ui/packages/consul-ui/tests/unit/adapters/auth-method-test.js
@@ -0,0 +1,12 @@
+import { module, test } from 'qunit';
+import { setupTest } from 'ember-qunit';
+
+module('Unit | Adapter | auth-method', function(hooks) {
+ setupTest(hooks);
+
+ // Replace this with your real tests.
+ test('it exists', function(assert) {
+ let adapter = this.owner.lookup('adapter:auth-method');
+ assert.ok(adapter);
+ });
+});
diff --git a/ui/packages/consul-ui/tests/unit/models/auth-method-test.js b/ui/packages/consul-ui/tests/unit/models/auth-method-test.js
new file mode 100644
index 0000000000..ae7107e0b3
--- /dev/null
+++ b/ui/packages/consul-ui/tests/unit/models/auth-method-test.js
@@ -0,0 +1,14 @@
+import { module, test } from 'qunit';
+import { setupTest } from 'ember-qunit';
+import { run } from '@ember/runloop';
+
+module('Unit | Model | auth-method', function(hooks) {
+ setupTest(hooks);
+
+ // Replace this with your real tests.
+ test('it exists', function(assert) {
+ let store = this.owner.lookup('service:store');
+ let model = run(() => store.createRecord('auth-method', {}));
+ assert.ok(model);
+ });
+});
diff --git a/ui/packages/consul-ui/tests/unit/serializers/auth-method-test.js b/ui/packages/consul-ui/tests/unit/serializers/auth-method-test.js
new file mode 100644
index 0000000000..d1bacfa207
--- /dev/null
+++ b/ui/packages/consul-ui/tests/unit/serializers/auth-method-test.js
@@ -0,0 +1,23 @@
+import { module, test } from 'qunit';
+import { setupTest } from 'ember-qunit';
+
+module('Unit | Serializer | auth-method', function(hooks) {
+ setupTest(hooks);
+
+ // Replace this with your real tests.
+ test('it exists', function(assert) {
+ let store = this.owner.lookup('service:store');
+ let serializer = store.serializerFor('auth-method');
+
+ assert.ok(serializer);
+ });
+
+ test('it serializes records', function(assert) {
+ let store = this.owner.lookup('service:store');
+ let record = store.createRecord('auth-method', {});
+
+ let serializedRecord = record.serialize();
+
+ assert.ok(serializedRecord);
+ });
+});
diff --git a/ui/packages/consul-ui/tests/unit/services/repository/auth-method-test.js b/ui/packages/consul-ui/tests/unit/services/repository/auth-method-test.js
new file mode 100644
index 0000000000..5290bfb18f
--- /dev/null
+++ b/ui/packages/consul-ui/tests/unit/services/repository/auth-method-test.js
@@ -0,0 +1,12 @@
+import { module, test } from 'qunit';
+import { setupTest } from 'ember-qunit';
+
+module('Unit | Service | auth-method', function(hooks) {
+ setupTest(hooks);
+
+ // Replace this with your real tests.
+ test('it exists', function(assert) {
+ let service = this.owner.lookup('service:repository/auth-method');
+ assert.ok(service);
+ });
+});
diff --git a/ui/packages/consul-ui/translations/en-us.yaml b/ui/packages/consul-ui/translations/en-us.yaml
index db329791f9..21491358c4 100644
--- a/ui/packages/consul-ui/translations/en-us.yaml
+++ b/ui/packages/consul-ui/translations/en-us.yaml
@@ -6,11 +6,14 @@ common:
vault: Vault
aws: AWS
kubernetes: Kubernetes
+ jwt: JWT
+ oidc: OIDC
ui:
remove: Remove {item}
filtered-by: Filtered by {item}
name: Name
creation: Creation
+ maxttl: Max TTL
consul:
name: Name
passing: Passing
@@ -35,6 +38,7 @@ common:
localbindport: Local Bind Port
destinationname: Destination Name
sourcename: Source Name
+ displayname: Display Name
search:
search: Search
searchproperty: Search Across
@@ -52,6 +56,9 @@ common:
age:
asc: Oldest to Newest
desc: Newest to Oldest
+ duration:
+ asc: Longest to shortest
+ desc: Shortest to longest
status:
asc: Unhealthy to Healthy
desc: Healthy to Unhealthy
@@ -127,6 +134,15 @@ components:
options:
global-management: Global Management
standard: Standard
+ auth-method:
+ search-bar:
+ kind:
+ name: Type
+ locality:
+ name: Source
+ options:
+ local: Creates local tokens
+ global: Creates global tokens
kv:
search-bar:
kind: