196 lines
8.2 KiB
Handlebars
196 lines
8.2 KiB
Handlebars
{{!
|
|
Copyright (c) HashiCorp, Inc.
|
|
SPDX-License-Identifier: MPL-2.0
|
|
}}
|
|
|
|
{{page-title "Authorization"}}
|
|
<section class="section authorization-page">
|
|
{{#if this.isValidatingToken}}
|
|
<LoadingSpinner />
|
|
{{else}}
|
|
<h1 class="title">Authorization and access control</h1>
|
|
|
|
<div class="status-notifications {{if this.canSignIn "is-half"}}">
|
|
|
|
{{#if (eq this.signInStatus "failure")}}
|
|
<div data-test-token-error class="notification is-danger">
|
|
<div class="columns">
|
|
<div class="column">
|
|
<h3 class="title is-4">Token Failed to Authenticate</h3>
|
|
<p>The token secret you have provided does not match an existing token, or has expired.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{{/if}}
|
|
|
|
{{#if (eq this.signInStatus "jwtFailure")}}
|
|
<div data-test-token-error class="notification is-danger">
|
|
<div class="columns">
|
|
<div class="column">
|
|
<h3 class="title is-4">JWT Failed to Authenticate</h3>
|
|
<p>You passed in a JWT, but no JWT auth methods were found</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{{/if}}
|
|
|
|
{{#if this.tokenRecord.isExpired}}
|
|
<div data-test-token-expired class="notification is-danger">
|
|
<div class="columns">
|
|
<div class="column">
|
|
<h3 class="title is-4">Your authentication has expired</h3>
|
|
<p>Expired {{moment-from-now this.tokenRecord.expirationTime interval=1000}} ({{this.tokenRecord.expirationTime}})</p>
|
|
</div>
|
|
<div class="column is-centered is-minimum">
|
|
<button data-test-token-clear class="button" {{action "clearTokenProperties"}} type="button">Sign In Again</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{{else}}
|
|
{{#if (eq this.signInStatus "success")}}
|
|
<div data-test-token-success class="notification is-success">
|
|
<div class="columns">
|
|
<div class="column">
|
|
<h3 class="title is-4">Token Authenticated!</h3>
|
|
<p>Your token is valid and authorized for the following policies.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{{/if}}
|
|
{{/if}}
|
|
|
|
{{#if this.token.tokenNotFound}}
|
|
<div data-test-token-not-found class="notification is-danger">
|
|
<div class="columns">
|
|
<div class="column">
|
|
<h3 class="title is-4">Your token was not found</h3>
|
|
<p>It may have expired, or been entered incorrectly.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{{/if}}
|
|
|
|
{{#if this.SSOFailure}}
|
|
<div data-test-sso-error class="notification is-danger column">
|
|
<div class="columns">
|
|
<div class="column">
|
|
<h3 class="title is-4">Failed to sign in with SSO</h3>
|
|
<p>Your OIDC provider has failed on sign in; please try again or contact your SSO administrator.</p>
|
|
</div>
|
|
<div class="column is-centered is-minimum">
|
|
<button data-test-sso-error-clear class="button" {{action (mut this.state)}} type="button">Clear</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{{/if}}
|
|
</div>
|
|
|
|
<div class="columns">
|
|
{{#if this.canSignIn}}
|
|
<div class="column is-half sign-in-methods">
|
|
{{#if this.nonTokenAuthMethods.length}}
|
|
<h3 class="title is-4">Sign in with SSO</h3>
|
|
<p>Sign in to Nomad using the configured authorization provider. After logging in, the policies and rules for the token will be listed.</p>
|
|
<div class="sso-auth-methods">
|
|
{{#each this.nonTokenAuthMethods as |method|}}
|
|
<button
|
|
data-test-auth-method
|
|
class="button is-primary"
|
|
onclick={{action "redirectToSSO" method}}
|
|
type="button"
|
|
>Sign in with {{method.name}}
|
|
</button>
|
|
{{/each}}
|
|
</div>
|
|
<span class="or-divider"><span>Or</span></span>
|
|
{{/if}}
|
|
|
|
<h3 class="title is-4">Sign in with token</h3>
|
|
<p>Clusters that use Access Control Lists require tokens to perform certain tasks. By providing a token Secret ID{{#if this.hasJWTAuthMethods}} or <a href="https://jwt.io/" target="_blank" rel="noopener noreferrer">JWT</a>{{/if}}, each future request will be authenticated, potentially authorizing read access to additional information.</p>
|
|
<label class="label" for="token-input">Secret ID{{#if this.hasJWTAuthMethods}} or JWT{{/if}}</label>
|
|
<div class="control {{if (and this.currentSecretIsJWT (gt this.JWTAuthMethods.length 1)) "with-jwt-selector"}}">
|
|
<Input
|
|
id="token-input"
|
|
class="input"
|
|
@type="text"
|
|
placeholder="{{if this.hasJWTAuthMethods "36-character token secret or JWT" "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"}}"
|
|
{{autofocus}}
|
|
{{on "input" (action (mut this.secret) value="target.value")}}
|
|
@enter={{this.verifyToken}}
|
|
data-test-token-secret />
|
|
|
|
{{#if this.currentSecretIsJWT}}
|
|
{{did-insert (action this.setCurrentAuthMethod)}}
|
|
{{#if (gt this.JWTAuthMethods.length 1)}}
|
|
<SingleSelectDropdown
|
|
data-test-select-jwt
|
|
@label="Sign-in method"
|
|
@options={{this.JWTAuthMethodOptions}}
|
|
@selection={{this.jwtAuthMethod}}
|
|
@onSelect={{fn (mut this.jwtAuthMethod)}}
|
|
/>
|
|
{{/if}}
|
|
{{/if}}
|
|
</div>
|
|
<p class="help">Sent with every request to determine authorization</p>
|
|
<button disabled={{not this.secret}} data-test-token-submit class="button is-primary" {{action "verifyToken"}} type="button">
|
|
{{#if this.currentSecretIsJWT}}
|
|
Sign in with JWT
|
|
{{else}}
|
|
Sign in with secret
|
|
{{/if}}
|
|
</button>
|
|
</div>
|
|
{{/if}}
|
|
|
|
{{#if this.shouldShowPolicies}}
|
|
<div class="column">
|
|
{{#unless this.tokenRecord.isExpired}}
|
|
<div class="columns">
|
|
<div class="column">
|
|
<h3 data-test-token-name class="title is-4">Token: {{this.tokenRecord.name}}</h3>
|
|
<div>AccessorID: <code>{{this.tokenRecord.accessor}}</code></div>
|
|
<div>SecretID: <code>{{this.tokenRecord.secret}}</code></div>
|
|
{{#if this.tokenRecord.expirationTime}}
|
|
<div data-test-token-expiry>Expires: {{moment-from-now this.tokenRecord.expirationTime interval=1000}} <span data-test-expiration-timestamp>({{this.tokenRecord.expirationTime}})</span></div>
|
|
{{/if}}
|
|
</div>
|
|
<div class="column is-minimum">
|
|
<button data-test-token-clear class="button is-primary" {{action "clearTokenProperties"}} type="button">Sign Out</button>
|
|
</div>
|
|
</div>
|
|
<h3 class="title is-4">Policies</h3>
|
|
{{#if (eq this.tokenRecord.type "management")}}
|
|
<div data-test-token-management-message class="boxed-section">
|
|
<div class="boxed-section-body has-centered-text">
|
|
The management token has all permissions
|
|
</div>
|
|
</div>
|
|
{{else}}
|
|
{{#each this.tokenRecord.policies as |policy|}}
|
|
<div data-test-token-policy class="boxed-section">
|
|
<div data-test-policy-name class="boxed-section-head">
|
|
{{policy.name}}
|
|
</div>
|
|
<div class="boxed-section-body">
|
|
<p data-test-policy-description class="content">
|
|
{{#if policy.description}}
|
|
{{policy.description}}
|
|
{{else}}
|
|
<em>No description</em>
|
|
{{/if}}
|
|
</p>
|
|
<pre><code data-test-policy-rules>{{policy.rules}}</code></pre>
|
|
</div>
|
|
</div>
|
|
{{/each}}
|
|
{{/if}}
|
|
{{/unless}}
|
|
</div>
|
|
{{/if}}
|
|
</div>
|
|
|
|
{{/if}}
|
|
</section>
|
|
|