From 17e23c8dc1484b08a59ae12343d85bff40500f04 Mon Sep 17 00:00:00 2001 From: hmalphettes Date: Wed, 3 Jun 2020 17:17:01 +0800 Subject: [PATCH] #6435 UI Obfuscated password input --- ui/app/components/secret-edit.js | 26 +++++++---- .../vault/cluster/secrets/backend/create.js | 4 ++ .../vault/cluster/secrets/backend/edit.js | 4 ++ .../vault/cluster/secrets/backend/show.js | 4 ++ ui/app/models/auth-config/aws/client.js | 8 +++- ui/app/models/auth-config/azure.js | 2 + ui/app/models/auth-config/jwt.js | 1 + ui/app/models/auth-config/kubernetes.js | 1 + .../cluster/secrets/backend/secret-edit.js | 3 ++ ui/app/styles/app.scss | 10 +++++ ui/app/styles/components/masked-input.scss | 6 +++ .../components/auth-config-form/config.hbs | 2 +- ui/app/templates/components/secret-edit.hbs | 12 ++++- .../templates/partials/secret-form-create.hbs | 5 ++- .../templates/partials/secret-form-edit.hbs | 1 + .../secrets/backend/secret-edit-layout.hbs | 2 + ui/config/environment.js | 1 + .../templates/components/masked-input.hbs | 41 +++++++++++------- ui/public/fonts/ObfuscatedPasswordFont.woff | Bin 0 -> 5680 bytes ui/public/fonts/ObfuscatedPasswordFont.woff2 | Bin 0 -> 3044 bytes vault/ui.go | 2 +- 21 files changed, 105 insertions(+), 30 deletions(-) create mode 100644 ui/public/fonts/ObfuscatedPasswordFont.woff create mode 100644 ui/public/fonts/ObfuscatedPasswordFont.woff2 diff --git a/ui/app/components/secret-edit.js b/ui/app/components/secret-edit.js index 96d224497d0b3..7391448bc6b5e 100644 --- a/ui/app/components/secret-edit.js +++ b/ui/app/components/secret-edit.js @@ -1,14 +1,14 @@ -import { isBlank, isNone } from '@ember/utils'; -import { inject as service } from '@ember/service'; import Component from '@ember/component'; import { computed, set } from '@ember/object'; import { alias, or } from '@ember/object/computed'; +import { inject as service } from '@ember/service'; +import { isBlank, isNone } from '@ember/utils'; import { task, waitForEvent } from 'ember-concurrency'; -import FocusOnInsertMixin from 'vault/mixins/focus-on-insert'; -import WithNavToNearestAncestor from 'vault/mixins/with-nav-to-nearest-ancestor'; import keys from 'vault/lib/keycodes'; import KVObject from 'vault/lib/kv-object'; import { maybeQueryRecord } from 'vault/macros/maybe-query-record'; +import FocusOnInsertMixin from 'vault/mixins/focus-on-insert'; +import WithNavToNearestAncestor from 'vault/mixins/with-nav-to-nearest-ancestor'; const LIST_ROUTE = 'vault.cluster.secrets.backend.list'; const LIST_ROOT_ROUTE = 'vault.cluster.secrets.backend.list-root'; @@ -19,6 +19,7 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, { router: service(), store: service(), flashMessages: service(), + classNameBindings: ['showObfuscatedInputMode:obfuscated-input'], // a key model key: null, @@ -41,13 +42,16 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, { onDataChange() {}, onRefresh() {}, onToggleAdvancedEdit() {}, + onToggleObfuscatedInput() {}, // did user request advanced mode preferAdvancedEdit: false, + preferObfuscatedInput: false, // use a named action here so we don't have to pass one in // this will bubble to the route toggleAdvancedEdit: 'toggleAdvancedEdit', + toggleObfuscatedInput: 'toggleObfuscatedInput', error: null, codemirrorString: null, @@ -164,12 +168,15 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, { if (this.isV2 && this.modelForData.failedServerRead) { return true; } - // if the model couldn't be read from the server - if (!this.isV2 && this.model.failedServerRead) { - return true; - } return false; }), + showObfuscatedInputMode: computed('preferObfuscatedInput', 'lastChange', function() { + return this.preferObfuscatedInput; + }), + + showObfuscatedInputMode: computed('preferObfuscatedInput', 'lastChange', function() { + return this.preferObfuscatedInput; + }), transitionToRoute() { return this.router.transitionTo(...arguments); @@ -346,6 +353,9 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, { toggleAdvanced(bool) { this.onToggleAdvancedEdit(bool); }, + toggleObfuscated(bool) { + this.onToggleObfuscatedInput(bool); + }, codemirrorUpdated(val, codemirror) { this.set('error', null); diff --git a/ui/app/controllers/vault/cluster/secrets/backend/create.js b/ui/app/controllers/vault/cluster/secrets/backend/create.js index abf822816ed30..c8abbd6791859 100644 --- a/ui/app/controllers/vault/cluster/secrets/backend/create.js +++ b/ui/app/controllers/vault/cluster/secrets/backend/create.js @@ -15,5 +15,9 @@ export default Controller.extend(BackendCrumbMixin, { this.set('preferAdvancedEdit', bool); this.get('backendController').set('preferAdvancedEdit', bool); }, + toggleObfuscatedInput(bool) { + this.set('preferObfuscatedInput', bool); + this.get('backendController').set('preferObfuscatedInput', bool); + }, }, }); diff --git a/ui/app/controllers/vault/cluster/secrets/backend/edit.js b/ui/app/controllers/vault/cluster/secrets/backend/edit.js index b3acca861301b..a9d461b2bdf1c 100644 --- a/ui/app/controllers/vault/cluster/secrets/backend/edit.js +++ b/ui/app/controllers/vault/cluster/secrets/backend/edit.js @@ -19,5 +19,9 @@ export default Controller.extend(BackendCrumbMixin, { this.set('preferAdvancedEdit', bool); this.get('backendController').set('preferAdvancedEdit', bool); }, + toggleObfuscatedInput(bool) { + this.set('preferObfuscatedInput', bool); + this.get('backendController').set('preferObfuscatedInput', bool); + }, }, }); diff --git a/ui/app/controllers/vault/cluster/secrets/backend/show.js b/ui/app/controllers/vault/cluster/secrets/backend/show.js index 26c00b359fdba..8617154853711 100644 --- a/ui/app/controllers/vault/cluster/secrets/backend/show.js +++ b/ui/app/controllers/vault/cluster/secrets/backend/show.js @@ -21,5 +21,9 @@ export default Controller.extend(BackendCrumbMixin, { this.set('preferAdvancedEdit', bool); this.get('backendController').set('preferAdvancedEdit', bool); }, + toggleObfuscatedInput(bool) { + this.set('preferObfuscated', bool); + this.get('backendController').set('preferObfuscated', bool); + }, }, }); diff --git a/ui/app/models/auth-config/aws/client.js b/ui/app/models/auth-config/aws/client.js index 7568371f5a129..6cda67c9396d0 100644 --- a/ui/app/models/auth-config/aws/client.js +++ b/ui/app/models/auth-config/aws/client.js @@ -6,8 +6,12 @@ import fieldToAttrs from 'vault/utils/field-to-attrs'; const { attr } = DS; export default AuthConfig.extend({ - secretKey: attr('string'), - accessKey: attr('string'), + secretKey: attr('string', { + sensitive: true, + }), + accessKey: attr('string', { + sensitive: true, + }), endpoint: attr('string', { label: 'EC2 Endpoint', }), diff --git a/ui/app/models/auth-config/azure.js b/ui/app/models/auth-config/azure.js index 6ef8a3f507f09..e420f66f18871 100644 --- a/ui/app/models/auth-config/azure.js +++ b/ui/app/models/auth-config/azure.js @@ -19,9 +19,11 @@ export default AuthConfig.extend({ label: 'Client ID', helpText: 'The client ID for credentials to query the Azure APIs. Currently read permissions to query compute resources are required.', + sensitive: true, }), clientSecret: attr('string', { helpText: 'The client secret for credentials to query the Azure APIs', + sensitive: true, }), googleCertsEndpoint: attr('string'), diff --git a/ui/app/models/auth-config/jwt.js b/ui/app/models/auth-config/jwt.js index 91b68b54ff14c..9dc9d17dc91a9 100644 --- a/ui/app/models/auth-config/jwt.js +++ b/ui/app/models/auth-config/jwt.js @@ -20,6 +20,7 @@ export default AuthConfig.extend({ oidcClientSecret: attr('string', { label: 'OIDC client secret', + sensitive: true, }), oidcDiscoveryCaPem: attr('string', { label: 'OIDC discovery CA PEM', diff --git a/ui/app/models/auth-config/kubernetes.js b/ui/app/models/auth-config/kubernetes.js index 8eb0b0913e4a2..3041c0d3281a0 100644 --- a/ui/app/models/auth-config/kubernetes.js +++ b/ui/app/models/auth-config/kubernetes.js @@ -22,6 +22,7 @@ export default AuthConfig.extend({ tokenReviewerJwt: attr('string', { helpText: 'A service account JWT used to access the TokenReview API to validate other JWTs during login. If not set the JWT used for login will be used to access the API', + sensitive: true, }), pemKeys: attr({ diff --git a/ui/app/routes/vault/cluster/secrets/backend/secret-edit.js b/ui/app/routes/vault/cluster/secrets/backend/secret-edit.js index c79e90972de11..82b1b7fe5f646 100644 --- a/ui/app/routes/vault/cluster/secrets/backend/secret-edit.js +++ b/ui/app/routes/vault/cluster/secrets/backend/secret-edit.js @@ -231,6 +231,8 @@ export default Route.extend(UnloadModelRoute, { let backend = this.enginePathParam(); const preferAdvancedEdit = this.controllerFor('vault.cluster.secrets.backend').get('preferAdvancedEdit') || false; + const preferObfuscatedInput = + this.controllerFor('vault.cluster.secrets.backend').get('preferObfuscatedInput') || false; const backendType = this.backendType(); model.secret.setProperties({ backend }); controller.setProperties({ @@ -244,6 +246,7 @@ export default Route.extend(UnloadModelRoute, { .replace('-root', ''), backend, preferAdvancedEdit, + preferObfuscatedInput, backendType, }); }, diff --git a/ui/app/styles/app.scss b/ui/app/styles/app.scss index 7f8fbdb710249..9c8fe851aceed 100644 --- a/ui/app/styles/app.scss +++ b/ui/app/styles/app.scss @@ -1,3 +1,13 @@ @import 'ember-basic-dropdown'; @import 'ember-power-select'; @import './core'; + +@mixin font-face($name) { + @font-face { + font-family: $name; + src: url("/ui/fonts/#{$name}.woff2") format("woff2"), + url("/ui/fonts/#{$name}.woff") format("woff"); + } +} + +@include font-face('ObfuscatedPasswordFont'); \ No newline at end of file diff --git a/ui/app/styles/components/masked-input.scss b/ui/app/styles/components/masked-input.scss index 124f2a1640e17..3c4e964f8b4ea 100644 --- a/ui/app/styles/components/masked-input.scss +++ b/ui/app/styles/components/masked-input.scss @@ -24,6 +24,12 @@ line-height: 2.5; } +.obfuscated-input .masked-input .input { + font-size: 9px; + font-family: ObfuscatedPasswordFont; + line-height: 2.5; +} + .masked-input.display-only .masked-value { order: 1; } diff --git a/ui/app/templates/components/auth-config-form/config.hbs b/ui/app/templates/components/auth-config-form/config.hbs index a03f76f13e4ae..188d6ee74cea5 100644 --- a/ui/app/templates/components/auth-config-form/config.hbs +++ b/ui/app/templates/components/auth-config-form/config.hbs @@ -1,5 +1,5 @@
-
+
{{message-error model=model}} {{#if model.attrs}} diff --git a/ui/app/templates/components/secret-edit.hbs b/ui/app/templates/components/secret-edit.hbs index 9719fb03342cf..5fbf3f6a22378 100644 --- a/ui/app/templates/components/secret-edit.hbs +++ b/ui/app/templates/components/secret-edit.hbs @@ -26,6 +26,16 @@ {{#unless (and (eq mode 'show') isWriteWithoutRead)}} + + Obfuscated Input + -{{partial partialName}} +{{partial partialName}} \ No newline at end of file diff --git a/ui/app/templates/partials/secret-form-create.hbs b/ui/app/templates/partials/secret-form-create.hbs index 3470343406dfc..6bdca7182a088 100644 --- a/ui/app/templates/partials/secret-form-create.hbs +++ b/ui/app/templates/partials/secret-form-create.hbs @@ -1,10 +1,10 @@ - +

- {{input + {{input autocomplete="off" spellcheck="false" data-test-secret-path="true" @@ -21,6 +21,7 @@

- {{#if displayOnly}} -
{{displayValue}}
+
+ {{#if displayOnly}} +
{{displayValue}}
{{else}} -