mirror of https://github.com/status-im/consul.git
ui: Create auth-method show page with General Info Tab (#9845)
* Update list items to be linkable to auth-methods show * Add general, namespace, and binding sub-routes * Remove namespace and binding tabs to be done separately * Update auth-method byId endpoint * Style the show auth-method kubernetes type * Finish Kubernetes auth-method type styling * OIDC and JWT auth-method styling * Create consul-auth-method-view component * Add navigation test for auth-methods * Create Certificate component
This commit is contained in:
parent
6872c33881
commit
f9e8b26af6
|
@ -0,0 +1,14 @@
|
||||||
|
<div class="certificate">
|
||||||
|
<CopyButton @value={{@item}} @name={{@name}} />
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class={{concat "visibility" (if this.show " hide" " show")}}
|
||||||
|
{{on "click" this.setVisibility}}
|
||||||
|
>
|
||||||
|
</button>
|
||||||
|
{{#if this.show}}
|
||||||
|
<div class="key">{{@item}}</div>
|
||||||
|
{{else}}
|
||||||
|
<hr />
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
|
@ -0,0 +1,14 @@
|
||||||
|
import Component from '@glimmer/component';
|
||||||
|
import { tracked } from '@glimmer/tracking';
|
||||||
|
import { action } from '@ember/object';
|
||||||
|
|
||||||
|
export default class Certificate extends Component {
|
||||||
|
// =attributes
|
||||||
|
@tracked show = false;
|
||||||
|
|
||||||
|
// =actions
|
||||||
|
@action
|
||||||
|
setVisibility() {
|
||||||
|
this.show = !this.show;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
.certificate {
|
||||||
|
display: flex;
|
||||||
|
button.visibility {
|
||||||
|
height: fit-content;
|
||||||
|
padding-top: 4px;
|
||||||
|
margin-right: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
button.hide::before {
|
||||||
|
@extend %with-visibility-hide-icon, %as-pseudo;
|
||||||
|
}
|
||||||
|
button.show::before {
|
||||||
|
@extend %with-visibility-show-icon, %as-pseudo;
|
||||||
|
}
|
||||||
|
div.key {
|
||||||
|
background-color: var(--gray-050);
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
}
|
||||||
|
hr {
|
||||||
|
border: 3px dashed var(--gray-300);
|
||||||
|
background-color: $white;
|
||||||
|
width: 150px;
|
||||||
|
margin: auto;
|
||||||
|
margin-top: 9px;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,74 @@
|
||||||
.consul-auth-method-list ul {
|
.consul-consul-auth-method-view-list ul {
|
||||||
.consul-auth-method-type {
|
|
||||||
@extend %pill-200, %frame-gray-600;
|
|
||||||
}
|
|
||||||
.locality::before {
|
.locality::before {
|
||||||
@extend %with-public-default-mask, %as-pseudo;
|
@extend %with-public-default-mask, %as-pseudo;
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.consul-auth-method-view {
|
||||||
|
margin-bottom: 32px;
|
||||||
|
> hr {
|
||||||
|
background-color: var(--gray-200);
|
||||||
|
}
|
||||||
|
section {
|
||||||
|
@extend %p1;
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
overflow-y: auto;
|
||||||
|
h2 {
|
||||||
|
@extend %h200;
|
||||||
|
padding-bottom: 12px;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
thead td {
|
||||||
|
color: var(--gray-500);
|
||||||
|
font-weight: $typo-weight-semibold;
|
||||||
|
font-size: $typo-size-700;
|
||||||
|
}
|
||||||
|
tbody td {
|
||||||
|
font-size: $typo-size-600;
|
||||||
|
color: $black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dl,
|
||||||
|
section dl {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
> dt:last-of-type,
|
||||||
|
> dd:last-of-type {
|
||||||
|
border-bottom: 1px solid var(--gray-300) !important;
|
||||||
|
}
|
||||||
|
dt, dd {
|
||||||
|
padding: 12px 0;
|
||||||
|
margin: 0;
|
||||||
|
border-top: 1px solid var(--gray-300) !important;
|
||||||
|
color: $black !important;
|
||||||
|
}
|
||||||
|
dt {
|
||||||
|
width: 20%;
|
||||||
|
font-weight: $typo-weight-bold;
|
||||||
|
}
|
||||||
|
dd {
|
||||||
|
margin-left: auto;
|
||||||
|
width: 80%;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
dd > ul li {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
dd > ul li:not(:last-of-type) {
|
||||||
|
padding-bottom: 12px;
|
||||||
|
}
|
||||||
|
dd .copy-button button {
|
||||||
|
padding: 0 !important;
|
||||||
|
margin: 0 4px 0 0 !important;
|
||||||
|
}
|
||||||
|
dd .copy-button button::before {
|
||||||
|
background-color: $black;
|
||||||
|
}
|
||||||
|
dt.check + dd {
|
||||||
|
padding-top: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
<ListCollection
|
<ListCollection
|
||||||
class="consul-auth-method-list"
|
class="consul-auth-method-list"
|
||||||
@items={{@items}}
|
@items={{@items}}
|
||||||
as |item|>
|
as |item|
|
||||||
|
>
|
||||||
<BlockSlot @name="header">
|
<BlockSlot @name="header">
|
||||||
{{#if (not-eq item.DisplayName '')}}
|
{{#if (not-eq item.DisplayName '')}}
|
||||||
<p data-test-auth-method>{{item.DisplayName}}</p>
|
<a data-test-auth-method href={{href-to "dc.acls.auth-methods.show" item.Name}}>
|
||||||
|
{{item.DisplayName}}
|
||||||
|
</a>
|
||||||
{{else}}
|
{{else}}
|
||||||
<p data-test-auth-method>{{item.Name}}</p>
|
<a data-test-auth-method href={{href-to "dc.acls.auth-methods.show" item.Name}}>
|
||||||
|
{{item.Name}}
|
||||||
|
</a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="details">
|
<BlockSlot @name="details">
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
export default (collection, text) => () => {
|
export default (collection, clickable, text) => () => {
|
||||||
return collection('.consul-auth-method-list [data-test-list-row]', {
|
return collection('.consul-auth-method-list [data-test-list-row]', {
|
||||||
|
authMethod: clickable('a'),
|
||||||
name: text('[data-test-auth-method]'),
|
name: text('[data-test-auth-method]'),
|
||||||
displayName: text('[data-test-display-name]'),
|
displayName: text('[data-test-display-name]'),
|
||||||
type: text('[data-test-type]'),
|
type: text('[data-test-type]'),
|
||||||
|
|
|
@ -0,0 +1,217 @@
|
||||||
|
<div class="consul-auth-method-view">
|
||||||
|
{{#if (eq @item.Type 'kubernetes')}}
|
||||||
|
<dl>
|
||||||
|
<dt>{{t 'models.auth-method.Type'}}</dt>
|
||||||
|
<dd><Consul::AuthMethod::Type @item={{@item}} /></dd>
|
||||||
|
|
||||||
|
{{#each (array "MaxTokenTTL" "TokenLocality" "DisplayName" "Description") as |value|}}
|
||||||
|
{{#if (get @item value)}}
|
||||||
|
<dt>{{t (concat "models.auth-method." value)}}</dt>
|
||||||
|
<dd>{{get @item value}}</dd>
|
||||||
|
{{/if}}
|
||||||
|
{{/each}}
|
||||||
|
{{#if @item.Config.Host}}
|
||||||
|
<dt>{{t 'models.auth-method.Config.Host'}}</dt>
|
||||||
|
<dd>
|
||||||
|
<CopyButton @value={{@item.Config.Host}} @name={{t 'models.auth-method.Config.Host'}}/>
|
||||||
|
<span>{{@item.Config.Host}}</span>
|
||||||
|
</dd>
|
||||||
|
{{/if}}
|
||||||
|
{{#if @item.Config.CACert}}
|
||||||
|
<dt>{{t 'models.auth-method.Config.CACert'}}</dt>
|
||||||
|
<dd>
|
||||||
|
<Certificate @item={{@item.Config.CACert}} @name={{t 'models.auth-method.Config.CACert'}} />
|
||||||
|
</dd>
|
||||||
|
{{/if}}
|
||||||
|
{{#if @item.Config.ServiceAccountJWT}}
|
||||||
|
<dt>{{t 'models.auth-method.Config.ServiceAccountJWT'}}</dt>
|
||||||
|
<dd>
|
||||||
|
<CopyButton @value={{@item.Config.ServiceAccountJWT}} @name={{t 'models.auth-method.Config.ServiceAccountJWT'}} />
|
||||||
|
<span>
|
||||||
|
{{@item.Config.ServiceAccountJWT}}
|
||||||
|
</span>
|
||||||
|
</dd>
|
||||||
|
{{/if}}
|
||||||
|
</dl>
|
||||||
|
{{else}}
|
||||||
|
<section class="meta">
|
||||||
|
<dl>
|
||||||
|
<dt>Type</dt>
|
||||||
|
<dd><Consul::AuthMethod::Type @item={{@item}} /></dd>
|
||||||
|
|
||||||
|
{{#each (array "MaxTokenTTL" "TokenLocality" "DisplayName" "Description") as |value|}}
|
||||||
|
{{#if (get @item value)}}
|
||||||
|
<dt>{{t (concat "models.auth-method." value)}}</dt>
|
||||||
|
<dd>{{get @item value}}</dd>
|
||||||
|
{{/if}}
|
||||||
|
{{/each}}
|
||||||
|
|
||||||
|
{{#if (eq @item.Type 'jwt')}}
|
||||||
|
{{#if @item.Config.JWKSURL}}
|
||||||
|
<dt>{{t 'models.auth-method.Config.JWKSURL'}}</dt>
|
||||||
|
<dd>
|
||||||
|
<CopyButton @value={{@item.Config.JWKSURL}} @name={{t 'models.auth-method.Config.JWKSURL'}} />
|
||||||
|
<span>{{@item.Config.JWKSURL}}</span>
|
||||||
|
</dd>
|
||||||
|
<dt>{{t 'models.auth-method.Config.JWKSCACert'}}</dt>
|
||||||
|
<dd>
|
||||||
|
<Certificate @item={{@item.Config.JWKSCACert}} @name={{t 'models.auth-method.Config.JWKSCACert'}} />
|
||||||
|
</dd>
|
||||||
|
{{/if}}
|
||||||
|
{{#if @item.Config.JWTValidationPubKeys}}
|
||||||
|
<dt>{{t 'models.auth-method.Config.JWTValidationPubKeys'}}</dt>
|
||||||
|
<dd>
|
||||||
|
<Certificate @item={{@item.Config.JWTValidationPubKeys}} @name={{t 'models.auth-method.Config.JWTValidationPubKeys'}} />
|
||||||
|
</dd>
|
||||||
|
{{/if}}
|
||||||
|
{{#if @item.Config.OIDCDiscoveryURL}}
|
||||||
|
<dt>{{t 'models.auth-method.Config.OIDCDiscoveryURL'}}</dt>
|
||||||
|
<dd>
|
||||||
|
<CopyButton @value={{@item.Config.OIDCDiscoveryURL}} @name={{t 'models.auth-method.Config.OIDCDiscoveryURL'}} />
|
||||||
|
<span>{{@item.Config.OIDCDiscoveryURL}}</span>
|
||||||
|
</dd>
|
||||||
|
{{/if}}
|
||||||
|
{{#if @item.Config.JWTSupportedAlgs}}
|
||||||
|
<dt>{{t 'models.auth-method.Config.JWTSupportedAlgs'}}</dt>
|
||||||
|
<dd>{{join ', ' @item.Config.JWTSupportedAlgs}}</dd>
|
||||||
|
{{/if}}
|
||||||
|
{{#if @item.Config.BoundAudiences}}
|
||||||
|
<dt>{{t 'models.auth-method.Config.BoundAudiences'}}</dt>
|
||||||
|
<dd>
|
||||||
|
<ul>
|
||||||
|
{{#each @item.Config.BoundAudiences as |bond|}}
|
||||||
|
<li>
|
||||||
|
<span>{{bond}}</span>
|
||||||
|
</li>
|
||||||
|
{{/each}}
|
||||||
|
</ul>
|
||||||
|
</dd>
|
||||||
|
{{/if}}
|
||||||
|
{{#each (array "BoundIssuer" "ExpirationLeeway" "NotBeforeLeeway" "ClockSkewLeeway") as |value|}}
|
||||||
|
{{#if (get @item.Config value)}}
|
||||||
|
<dt>{{t (concat "models.auth-method.Config." value)}}</dt>
|
||||||
|
<dd>{{get @item.Config value}}</dd>
|
||||||
|
{{/if}}
|
||||||
|
{{/each}}
|
||||||
|
{{else if (eq @item.Type 'oidc')}}
|
||||||
|
{{#if @item.Config.OIDCDiscoveryURL}}
|
||||||
|
<dt>{{t 'models.auth-method.Config.OIDCDiscoveryURL'}}</dt>
|
||||||
|
<dd>
|
||||||
|
<CopyButton @value={{@item.Config.OIDCDiscoveryURL}} @name={{t 'models.auth-method.Config.OIDCDiscoveryURL'}} />
|
||||||
|
<span>{{@item.Config.OIDCDiscoveryURL}}</span>
|
||||||
|
</dd>
|
||||||
|
{{/if}}
|
||||||
|
{{#if @item.Config.OIDCDiscoveryCACert}}
|
||||||
|
<dt>{{t 'models.auth-method.Config.OIDCDiscoveryCACert'}}</dt>
|
||||||
|
<dd>
|
||||||
|
<Certificate @item={{@item.Config.OIDCDiscoveryCACert}} @name={{t 'models.auth-method.Config.OIDCDiscoveryCACert'}} />
|
||||||
|
</dd>
|
||||||
|
{{/if}}
|
||||||
|
{{#if @item.Config.OIDCClientID}}
|
||||||
|
<dt>{{t 'models.auth-method.Config.OIDCClientID'}}</dt>
|
||||||
|
<dd>{{@item.Config.OIDCClientID}}</dd>
|
||||||
|
{{/if}}
|
||||||
|
{{#if @item.Config.OIDCClientSecret}}
|
||||||
|
<dt>{{t 'models.auth-method.Config.OIDCClientSecret'}}</dt>
|
||||||
|
<dd>{{@item.Config.OIDCClientSecret}}</dd>
|
||||||
|
{{/if}}
|
||||||
|
{{#if @item.Config.AllowedRedirectURIs}}
|
||||||
|
<dt>{{t 'models.auth-method.Config.AllowedRedirectURIs'}}</dt>
|
||||||
|
<dd>
|
||||||
|
<ul>
|
||||||
|
{{#each @item.Config.AllowedRedirectURIs as |uri|}}
|
||||||
|
<li>
|
||||||
|
<CopyButton @value={{uri}} @name="Redirect URI" />
|
||||||
|
<span>{{uri}}</span>
|
||||||
|
</li>
|
||||||
|
{{/each}}
|
||||||
|
</ul>
|
||||||
|
</dd>
|
||||||
|
{{/if}}
|
||||||
|
{{#if @item.Config.BoundAudiences}}
|
||||||
|
<dt>{{t 'models.auth-method.Config.BoundAudiences'}}</dt>
|
||||||
|
<dd>
|
||||||
|
<ul>
|
||||||
|
{{#each @item.Config.BoundAudiences as |bond|}}
|
||||||
|
<li>
|
||||||
|
<span>{{bond}}</span>
|
||||||
|
</li>
|
||||||
|
{{/each}}
|
||||||
|
</ul>
|
||||||
|
</dd>
|
||||||
|
{{/if}}
|
||||||
|
{{#if @item.Config.OIDCScopes}}
|
||||||
|
<dt>{{t 'models.auth-method.Config.OIDCScopes'}}</dt>
|
||||||
|
<dd>
|
||||||
|
<ul>
|
||||||
|
{{#each @item.Config.OIDCScopes as |scope|}}
|
||||||
|
<li>
|
||||||
|
<span>{{scope}}</span>
|
||||||
|
</li>
|
||||||
|
{{/each}}
|
||||||
|
</ul>
|
||||||
|
</dd>
|
||||||
|
{{/if}}
|
||||||
|
{{#if @item.Config.JWTSupportedAlgs}}
|
||||||
|
<dt>{{t 'models.auth-method.Config.JWTSupportedAlgs'}}</dt>
|
||||||
|
<dd>{{join ', ' @item.Config.JWTSupportedAlgs}}</dd>
|
||||||
|
{{/if}}
|
||||||
|
{{#if @item.Config.VerboseOIDCLogging}}
|
||||||
|
<dt class="check">{{t 'models.auth-method.Config.VerboseOIDCLogging'}}</dt>
|
||||||
|
<dd><input type="checkbox" disabled="disabled" checked={{@item.Config.VerboseOIDCLogging}}></dd>
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
</dl>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
{{#if @item.Config.ClaimMappings}}
|
||||||
|
<section class="claim-mappings">
|
||||||
|
<h2>Claim Mappings</h2>
|
||||||
|
<p>Use this if the claim you are capturing is singular. When mapped, the values can be any of a number, string, or boolean and will all be stringified when returned.</p>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td>Key</td>
|
||||||
|
<td>Value</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{#each (entries @item.Config.ClaimMappings) as |entry|}}
|
||||||
|
<tr>
|
||||||
|
<td>{{get entry 0}}</td>
|
||||||
|
<td>{{get entry 1}}</td>
|
||||||
|
</tr>
|
||||||
|
{{/each}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</section>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
{{#if @item.Config.ListClaimMappings}}
|
||||||
|
<section class="list-claim-mappings">
|
||||||
|
<h2>List Claim Mappings</h2>
|
||||||
|
<p>Use this if the claim you are capturing is list-like (such as groups). When mapped, the values can be any of a number, string, or boolean and will all be stringified when returned.</p>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td>Key</td>
|
||||||
|
<td>Value</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{#each (entries @item.Config.ListClaimMappings) as |entry|}}
|
||||||
|
<tr>
|
||||||
|
<td>{{get entry 0}}</td>
|
||||||
|
<td>{{get entry 1}}</td>
|
||||||
|
</tr>
|
||||||
|
{{/each}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</section>
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
|
@ -192,7 +192,10 @@ export const routes = {
|
||||||
abilities: ['read auth-methods'],
|
abilities: ['read auth-methods'],
|
||||||
},
|
},
|
||||||
show: {
|
show: {
|
||||||
_options: { path: '/show' },
|
_options: { path: '/:id' },
|
||||||
|
'auth-method': {
|
||||||
|
_options: { path: '/auth-method' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { inject as service } from '@ember/service';
|
||||||
|
import SingleRoute from 'consul-ui/routing/single';
|
||||||
|
import { hash } from 'rsvp';
|
||||||
|
|
||||||
|
export default class ShowRoute extends SingleRoute {
|
||||||
|
@service('repository/auth-method') repo;
|
||||||
|
|
||||||
|
model(params) {
|
||||||
|
return super.model(...arguments).then(model => {
|
||||||
|
return hash({
|
||||||
|
...model,
|
||||||
|
...{
|
||||||
|
item: this.repo.findBySlug({
|
||||||
|
id: params.id,
|
||||||
|
dc: this.modelFor('dc').dc.Name,
|
||||||
|
ns: this.modelFor('nspace').nspace.substr(1),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setupController(controller, model) {
|
||||||
|
super.setupController(...arguments);
|
||||||
|
controller.setProperties(model);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
import Route from 'consul-ui/routing/route';
|
||||||
|
|
||||||
|
export default class AuthMethodRoute extends Route {
|
||||||
|
model() {
|
||||||
|
const parent = this.routeName
|
||||||
|
.split('.')
|
||||||
|
.slice(0, -1)
|
||||||
|
.join('.');
|
||||||
|
return this.modelFor(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
setupController(controller, model) {
|
||||||
|
super.setupController(...arguments);
|
||||||
|
controller.setProperties(model);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
import Route from 'consul-ui/routing/route';
|
||||||
|
import to from 'consul-ui/utils/routing/redirect-to';
|
||||||
|
|
||||||
|
export default Route.extend({
|
||||||
|
redirect: to('auth-method'),
|
||||||
|
});
|
|
@ -63,6 +63,7 @@
|
||||||
@import 'consul-ui/components/informed-action';
|
@import 'consul-ui/components/informed-action';
|
||||||
@import 'consul-ui/components/tab-nav';
|
@import 'consul-ui/components/tab-nav';
|
||||||
@import 'consul-ui/components/search-bar';
|
@import 'consul-ui/components/search-bar';
|
||||||
|
@import 'consul-ui/components/certificate';
|
||||||
|
|
||||||
@import 'consul-ui/components/consul/tomography/graph';
|
@import 'consul-ui/components/consul/tomography/graph';
|
||||||
@import 'consul-ui/components/consul/discovery-chain';
|
@import 'consul-ui/components/consul/discovery-chain';
|
||||||
|
|
|
@ -9,7 +9,8 @@
|
||||||
.consul-node-list > ul > li:not(:first-child),
|
.consul-node-list > ul > li:not(:first-child),
|
||||||
.consul-token-list > ul > li:not(:first-child),
|
.consul-token-list > ul > li:not(:first-child),
|
||||||
.consul-policy-list > ul > li:not(:first-child),
|
.consul-policy-list > ul > li:not(:first-child),
|
||||||
.consul-role-list > ul > li:not(:first-child) {
|
.consul-role-list > ul > li:not(:first-child),
|
||||||
|
.consul-auth-method-list > ul > li:not(:first-child) {
|
||||||
@extend %with-composite-row-intent;
|
@extend %with-composite-row-intent;
|
||||||
}
|
}
|
||||||
.consul-lock-session-list ul > li:not(:first-child) {
|
.consul-lock-session-list ul > li:not(:first-child) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
span.policy-service-identity,
|
span.policy-service-identity,
|
||||||
span.policy-node-identity,
|
span.policy-node-identity,
|
||||||
.leader {
|
.leader,
|
||||||
|
.consul-auth-method-type {
|
||||||
@extend %pill-200, %frame-gray-600;
|
@extend %pill-200, %frame-gray-600;
|
||||||
}
|
}
|
||||||
span.policy-service-identity::before,
|
span.policy-service-identity::before,
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
{{#if isAuthorized }}
|
||||||
|
{{page-title item.Name}}
|
||||||
|
{{else}}
|
||||||
|
{{page-title 'Access Controls'}}
|
||||||
|
{{/if}}
|
||||||
|
<AppView
|
||||||
|
@authorized={{isAuthorized}}
|
||||||
|
@enabled={{isEnabled}}
|
||||||
|
>
|
||||||
|
<BlockSlot @name="breadcrumbs">
|
||||||
|
<ol>
|
||||||
|
<li><a data-test-back href={{href-to 'dc.acls.auth-methods'}}>All Auth Methods</a></li>
|
||||||
|
</ol>
|
||||||
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="header">
|
||||||
|
<h1>
|
||||||
|
{{#if isAuthorized }}
|
||||||
|
{{item.Name}}
|
||||||
|
{{else}}
|
||||||
|
Access Controls
|
||||||
|
{{/if}}
|
||||||
|
</h1>
|
||||||
|
<Consul::AuthMethod::Type @item={{item}} />
|
||||||
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="nav">
|
||||||
|
<TabNav @items={{
|
||||||
|
compact
|
||||||
|
(array
|
||||||
|
(hash label="General info" href=(href-to "dc.acls.auth-methods.show.auth-method") selected=(is-href "dc.acls.auth-methods.show.auth-method"))
|
||||||
|
)
|
||||||
|
}}/>
|
||||||
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="content">
|
||||||
|
<Outlet
|
||||||
|
@name={{routeName}}
|
||||||
|
as |o|>
|
||||||
|
{{outlet}}
|
||||||
|
</Outlet>
|
||||||
|
</BlockSlot>
|
||||||
|
</AppView>
|
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
<div class="tab-section">
|
||||||
|
<Consul::AuthMethod::View @item={{item}} />
|
||||||
|
</div>
|
|
@ -1,7 +1,20 @@
|
||||||
${
|
${
|
||||||
[1].map(() => {
|
[1].map(i => {
|
||||||
const type = `${fake.helpers.randomize(['kubernetes', 'jwt', 'oidc'])}`;
|
const type = `${fake.helpers.randomize(['kubernetes', 'jwt', 'oidc'])}`;
|
||||||
const fakeIP = `${fake.internet.ip()}`;
|
let sourceType;
|
||||||
|
|
||||||
|
if (type !== 'kubernetes') {
|
||||||
|
sourceType = `${fake.helpers.randomize(['JWTValidationPubKeys', 'JWKSURL', 'OIDCDiscoveryURL'])}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const claimMappings = {
|
||||||
|
"http://example.com/example-1": `${fake.hacker.noun()}`,
|
||||||
|
"http://example.com/example-2": `${fake.hacker.noun()}`
|
||||||
|
}
|
||||||
|
const listClaimMappings = {
|
||||||
|
"http://example.com/example-1": `${fake.hacker.noun()}`
|
||||||
|
}
|
||||||
|
|
||||||
let config = {};
|
let config = {};
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case 'kubernetes':
|
case 'kubernetes':
|
||||||
|
@ -14,17 +27,45 @@ ${
|
||||||
case 'oidc':
|
case 'oidc':
|
||||||
config = {
|
config = {
|
||||||
OIDCDiscoveryURL: `https://${fake.internet.ip()}:8443`,
|
OIDCDiscoveryURL: `https://${fake.internet.ip()}:8443`,
|
||||||
|
OIDCDiscoveryCACert: `-----BEGIN CERTIFICATE-----${fake.internet.password(1357)}-----END CERTIFICATE-----`,
|
||||||
|
OIDCClientID: `${fake.hacker.noun()}-ID`,
|
||||||
|
OIDCClientSecret: `${fake.hacker.noun()}-secret`,
|
||||||
|
BoundAudiences: ["aud_example_0", "aud_example_1"],
|
||||||
|
OIDCScopes: ["scope_01", "scope_02", "scope_03"],
|
||||||
|
JWTSupportedAlgs: ["RS256", "RS257"],
|
||||||
|
VerboseOIDCLogging: true,
|
||||||
|
AllowedRedirectURIs: ["http://example.com/example-1", "http://example.com/example-2", "http://example.com/example-3"],
|
||||||
|
ClaimMappings: claimMappings,
|
||||||
|
ListClaimMappings: listClaimMappings
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case 'jwt':
|
case 'jwt':
|
||||||
config = {
|
config = {
|
||||||
JWTValidationPubKeys: `-----BEGIN CERTIFICATE-----${fake.internet.password(1357)}-----END CERTIFICATE-----`,
|
JWTSupportedAlgs: ["RS256", "RS257"],
|
||||||
JWKSURL: `https://${fake.internet.ip()}:8443`,
|
BoundAudiences: ["aud_example_0", "aud_example_1"],
|
||||||
OIDCDiscoveryURL: `https://${fake.internet.ip()}:8443`,
|
BoundIssuer: `${fake.hacker.noun()}-issuer`,
|
||||||
|
ExpirationLeeway: `${fake.random.number({min: 0, max: 60})}`,
|
||||||
|
NotBeforeLeeway: `${fake.random.number({min: 0, max: 60})}`,
|
||||||
|
ClockSkewLeeway: `${fake.random.number({min: 0, max: 60})}`,
|
||||||
|
ClaimMappings: claimMappings,
|
||||||
|
ListClaimMappings: listClaimMappings
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch(sourceType) {
|
||||||
|
case 'JWTValidationPubKeys':
|
||||||
|
config.JWTValidationPubKeys = `-----BEGIN CERTIFICATE-----${fake.internet.password(1357)}-----END CERTIFICATE-----`;
|
||||||
|
break;
|
||||||
|
case 'JWKSURL':
|
||||||
|
config.JWKSURL = `https://${fake.internet.ip()}:8443`;
|
||||||
|
config.JWKSCACert = `-----BEGIN CERTIFICATE-----${fake.internet.password(1357)}-----END CERTIFICATE-----`;
|
||||||
|
break;
|
||||||
|
case 'OIDCDiscoveryURL':
|
||||||
|
config.OIDCDiscoveryURL = `https://${fake.internet.ip()}:8443`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return `{
|
return `{
|
||||||
"Name": "${location.pathname.get(3)}",
|
"Name": "${location.pathname.get(3)}",
|
||||||
"Namespace": "${
|
"Namespace": "${
|
||||||
|
|
|
@ -17,7 +17,11 @@
|
||||||
${typeof location.search.ns !== 'undefined' ? `
|
${typeof location.search.ns !== 'undefined' ? `
|
||||||
"Namespace": "${location.search.ns}",
|
"Namespace": "${location.search.ns}",
|
||||||
` : ``}
|
` : ``}
|
||||||
|
${env('CONSUL_NSPACES_ENABLE', false) ? `
|
||||||
"Type": "${fake.helpers.randomize(['kubernetes', 'jwt', 'oidc'])}",
|
"Type": "${fake.helpers.randomize(['kubernetes', 'jwt', 'oidc'])}",
|
||||||
|
` : `
|
||||||
|
"Type": "${fake.helpers.randomize(['kubernetes', 'jwt'])}",
|
||||||
|
`}
|
||||||
"Description": "${fake.lorem.sentence()}",
|
"Description": "${fake.lorem.sentence()}",
|
||||||
${i%2 ? `
|
${i%2 ? `
|
||||||
"DisplayName": "${fake.hacker.noun()}-${i}",
|
"DisplayName": "${fake.hacker.noun()}-${i}",
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
@setupApplicationTest
|
||||||
|
Feature: dc / acls / auth-methods / navigation
|
||||||
|
Scenario: Clicking a auth-method in the listing and back again
|
||||||
|
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
|
||||||
|
And the title should be "Auth Methods - Consul"
|
||||||
|
Then I see 3 authMethod models
|
||||||
|
When I click authMethod on the authMethods
|
||||||
|
And I click "[data-test-back]"
|
||||||
|
Then the url should be /dc-1/acls/auth-methods
|
||||||
|
|
|
@ -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);
|
||||||
|
});
|
||||||
|
}
|
|
@ -93,7 +93,7 @@ const emptyState = emptyStateFactory(isPresent);
|
||||||
|
|
||||||
const consulHealthCheckList = consulHealthCheckListFactory(collection, text);
|
const consulHealthCheckList = consulHealthCheckListFactory(collection, text);
|
||||||
const consulUpstreamInstanceList = consulUpstreamInstanceListFactory(collection, text);
|
const consulUpstreamInstanceList = consulUpstreamInstanceListFactory(collection, text);
|
||||||
const consulAuthMethodList = consulAuthMethodListFactory(collection, text);
|
const consulAuthMethodList = consulAuthMethodListFactory(collection, clickable, text);
|
||||||
const consulIntentionList = consulIntentionListFactory(
|
const consulIntentionList = consulIntentionListFactory(
|
||||||
collection,
|
collection,
|
||||||
clickable,
|
clickable,
|
||||||
|
|
|
@ -180,3 +180,35 @@ components:
|
||||||
asc: Ascending
|
asc: Ascending
|
||||||
desc: Descending
|
desc: Descending
|
||||||
|
|
||||||
|
models:
|
||||||
|
auth-method:
|
||||||
|
Description: Description
|
||||||
|
DisplayName: Display name
|
||||||
|
TokenLocality: Token locality
|
||||||
|
Type: Type
|
||||||
|
MaxTokenTTL: Maximum token TTL
|
||||||
|
Config:
|
||||||
|
Host: Host
|
||||||
|
CACert: CA Cert
|
||||||
|
ServiceAccountJWT: Service account JSON Web Token
|
||||||
|
JWKSURL: JWKS URL
|
||||||
|
JWKSCACert: JWKS CA Cert
|
||||||
|
JWTValidationPubKeys: JWT validation pub keys
|
||||||
|
OIDCDiscoveryURL: Discovery URL
|
||||||
|
JWTSupportedAlgs: JWT supported algorithms
|
||||||
|
BoundAudiences: Bound audiences
|
||||||
|
BoundIssuer: Bound issuer
|
||||||
|
ExpirationLeeway: Expiration leeway
|
||||||
|
NotBeforeLeeway: Not before leeway
|
||||||
|
ClockSkewLeeway: Clock skew leeway
|
||||||
|
OIDCDiscoveryCACert: OIDC discovery CA cert
|
||||||
|
OIDCClientID: Client ID
|
||||||
|
OIDCClientSecret: Client secret
|
||||||
|
AllowedRedirectURIs: Allowed redirect URIs
|
||||||
|
OIDCScopes: OIDC scopes
|
||||||
|
VerboseOIDCLogging: Verbose OIDC logging
|
||||||
|
ClaimMappings: Claim Mappings
|
||||||
|
ListClaimMappings: List Claim Mappings
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue