From 1639f7faf857a4a94cf6862642ddfa621330355c Mon Sep 17 00:00:00 2001 From: Matthew Irish Date: Mon, 23 Apr 2018 08:54:15 -0500 Subject: [PATCH 01/10] remove unused response-wrapping route and controller --- ui/app/controllers/vault/cluster/response-wrapping.js | 9 --------- ui/app/router.js | 1 - 2 files changed, 10 deletions(-) delete mode 100644 ui/app/controllers/vault/cluster/response-wrapping.js diff --git a/ui/app/controllers/vault/cluster/response-wrapping.js b/ui/app/controllers/vault/cluster/response-wrapping.js deleted file mode 100644 index 612c01b887c8..000000000000 --- a/ui/app/controllers/vault/cluster/response-wrapping.js +++ /dev/null @@ -1,9 +0,0 @@ -import Ember from 'ember'; - -export default Ember.Controller.extend({ - queryParams: { - selectedAction: 'action', - }, - - selectedAction: 'wrap', -}); diff --git a/ui/app/router.js b/ui/app/router.js index f3c65df00ecf..ecb289b57511 100644 --- a/ui/app/router.js +++ b/ui/app/router.js @@ -116,7 +116,6 @@ Router.map(function() { }); }); - this.route('response-wrapping'); this.route('not-found', { path: '/*path' }); }); this.route('not-found', { path: '/*path' }); From 330c72e7935dc4b3bd71b36d32a22d634c94d46e Mon Sep 17 00:00:00 2001 From: Matthew Irish Date: Mon, 23 Apr 2018 08:57:52 -0500 Subject: [PATCH 02/10] move to using the internal mounts endpoint for the secrets list and individual engine lookup --- ui/app/adapters/secret-engine.js | 31 ++++---------- ui/app/routes/vault/cluster/secrets.js | 6 +-- .../routes/vault/cluster/secrets/backend.js | 28 +++++++++---- .../vault/cluster/secrets/backend/list.js | 42 +++++++++---------- .../routes/vault/cluster/secrets/backends.js | 7 ++++ ui/app/serializers/secret-engine.js | 8 +++- 6 files changed, 63 insertions(+), 59 deletions(-) create mode 100644 ui/app/routes/vault/cluster/secrets/backends.js diff --git a/ui/app/adapters/secret-engine.js b/ui/app/adapters/secret-engine.js index 4c483f990189..882b59900f80 100644 --- a/ui/app/adapters/secret-engine.js +++ b/ui/app/adapters/secret-engine.js @@ -1,6 +1,5 @@ import Ember from 'ember'; import ApplicationAdapter from './application'; -import DS from 'ember-data'; export default ApplicationAdapter.extend({ url(path) { @@ -8,30 +7,16 @@ export default ApplicationAdapter.extend({ return path ? url + '/' + path : url; }, - pathForType(type) { - let path; - switch (type) { - case 'cluster': - path = 'clusters'; - break; - case 'secret-engine': - path = 'mounts'; - break; - default: - path = Ember.String.pluralize(type); - break; - } - return path; + pathForType() { + return 'mounts'; }, - query() { - return this.ajax(this.url(), 'GET').catch(e => { - if (e instanceof DS.AdapterError) { - Ember.set(e, 'policyPath', 'sys/mounts'); - } - - throw e; - }); + query(store, type, query) { + let url = `/${this.urlPrefix()}/internal/ui/mounts`; + if (query.path) { + url = `/${this.urlPrefix()}/internal/ui/mount/${query.path}`; + } + return this.ajax(url, 'GET'); }, createRecord(store, type, snapshot) { diff --git a/ui/app/routes/vault/cluster/secrets.js b/ui/app/routes/vault/cluster/secrets.js index d86c74eadb24..faca1fd5f307 100644 --- a/ui/app/routes/vault/cluster/secrets.js +++ b/ui/app/routes/vault/cluster/secrets.js @@ -1,8 +1,4 @@ import Ember from 'ember'; import ClusterRoute from 'vault/mixins/cluster-route'; -export default Ember.Route.extend(ClusterRoute, { - model() { - return this.store.query('secret-engine', {}); - }, -}); +export default Ember.Route.extend(ClusterRoute); diff --git a/ui/app/routes/vault/cluster/secrets/backend.js b/ui/app/routes/vault/cluster/secrets/backend.js index 2cdd61554a5f..71c10ee90293 100644 --- a/ui/app/routes/vault/cluster/secrets/backend.js +++ b/ui/app/routes/vault/cluster/secrets/backend.js @@ -2,19 +2,31 @@ import Ember from 'ember'; const { inject } = Ember; export default Ember.Route.extend({ flashMessages: inject.service(), - beforeModel(transition) { - const target = transition.targetName; - const { backend } = this.paramsFor(this.routeName); - const backendModel = this.store.peekRecord('secret-engine', backend); - const type = backendModel && backendModel.get('type'); - if (type === 'kv' && backendModel.get('options.version') === 2) { + model(params) { + let { backend } = params; + return this.store + .query('secret-engine', { + path: backend, + }) + .then(model => { + if (model) { + return model.get('firstObject'); + } + }); + }, + + afterModel(model, transition) { + let target = transition.targetName; + let path = model && model.get('path'); + let type = model && model.get('type'); + if (type === 'kv' && model.get('options.version') === 2) { this.get('flashMessages').stickyInfo( - `"${backend}" is a newer version of the KV backend. The Vault UI does not currently support the additional versioning features. All actions taken through the UI in this engine will operate on the most recent version of a secret.` + `"${path}" is a newer version of the KV backend. The Vault UI does not currently support the additional versioning features. All actions taken through the UI in this engine will operate on the most recent version of a secret.` ); } if (target === this.routeName) { - return this.replaceWith('vault.cluster.secrets.backend.list-root', backend); + return this.replaceWith('vault.cluster.secrets.backend.list-root', path); } }, }); diff --git a/ui/app/routes/vault/cluster/secrets/backend/list.js b/ui/app/routes/vault/cluster/secrets/backend/list.js index 6c7520159a44..d3ebd7851ba2 100644 --- a/ui/app/routes/vault/cluster/secrets/backend/list.js +++ b/ui/app/routes/vault/cluster/secrets/backend/list.js @@ -45,29 +45,29 @@ export default Ember.Route.extend({ model(params) { const secret = params.secret ? params.secret : ''; const { backend } = this.paramsFor('vault.cluster.secrets.backend'); - const backends = this.modelFor('vault.cluster.secrets').mapBy('id'); + const backendModel = this.modelFor('vault.cluster.secrets.backend'); return Ember.RSVP.hash({ secret, secrets: this.store - .lazyPaginatedQuery(this.getModelType(backend, params.tab), { - id: secret, - backend, - responsePath: 'data.keys', - page: params.page, - pageFilter: params.pageFilter, - size: 100, - }) - .then(model => { - this.set('has404', false); - return model; - }) - .catch(err => { - if (backends.includes(backend) && err.httpStatus === 404 && secret === '') { - return []; - } else { - throw err; - } - }), + .lazyPaginatedQuery(this.getModelType(backend, params.tab), { + id: secret, + backend, + responsePath: 'data.keys', + page: params.page, + pageFilter: params.pageFilter, + size: 100, + }) + .then(model => { + this.set('has404', false); + return model; + }) + .catch(err => { + if (backendModel && err.httpStatus === 404 && secret === '') { + return []; + } else { + throw err; + } + }) }); }, @@ -138,11 +138,9 @@ export default Ember.Route.extend({ error(error, transition) { const { secret } = this.paramsFor(this.routeName); const { backend } = this.paramsFor('vault.cluster.secrets.backend'); - const backends = this.modelFor('vault.cluster.secrets').mapBy('id'); Ember.set(error, 'secret', secret); Ember.set(error, 'isRoot', true); - Ember.set(error, 'hasBackend', backends.includes(backend)); Ember.set(error, 'backend', backend); const hasModel = this.controllerFor(this.routeName).get('hasModel'); // only swallow the error if we have a previous model diff --git a/ui/app/routes/vault/cluster/secrets/backends.js b/ui/app/routes/vault/cluster/secrets/backends.js new file mode 100644 index 000000000000..ceb3edd5b818 --- /dev/null +++ b/ui/app/routes/vault/cluster/secrets/backends.js @@ -0,0 +1,7 @@ +import Ember from 'ember'; + +export default Ember.Route.extend({ + model() { + return this.store.query('secret-engine', {}); + }, +}); diff --git a/ui/app/serializers/secret-engine.js b/ui/app/serializers/secret-engine.js index c14495549892..94bcac46cd49 100644 --- a/ui/app/serializers/secret-engine.js +++ b/ui/app/serializers/secret-engine.js @@ -38,7 +38,13 @@ export default DS.RESTSerializer.extend({ } else if (isQueryRecord) { backends = this.normalizeBackend(null, payload); } else { - backends = Object.keys(payload.data).map(id => this.normalizeBackend(id, payload[id])); + if (payload.data.secret) { + backends = Object.keys(payload.data.secret).map(id => + this.normalizeBackend(id, payload.data.secret[id]) + ); + } else { + backends = [this.normalizeBackend(payload.data.path, payload.data)]; + } } const transformedPayload = { [primaryModelClass.modelName]: backends }; From 1f21f5597b43cefc9b8eb5009549b3af1e8458cb Mon Sep 17 00:00:00 2001 From: Matthew Irish Date: Mon, 23 Apr 2018 08:58:25 -0500 Subject: [PATCH 03/10] remove errors about sys/mounts access because we don't need it anymore :tada: --- ui/app/templates/vault/cluster/error.hbs | 11 ----------- .../templates/vault/cluster/secrets/backend/error.hbs | 8 ++++---- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/ui/app/templates/vault/cluster/error.hbs b/ui/app/templates/vault/cluster/error.hbs index 6bc05baf39f1..13bda69a5174 100644 --- a/ui/app/templates/vault/cluster/error.hbs +++ b/ui/app/templates/vault/cluster/error.hbs @@ -26,17 +26,6 @@

Make sure the policy for the path {{model.policyPath}} includes capabilities = ['update'].

- {{else if (and - (eq model.httpStatus 403) - (eq model.policyPath 'sys/mounts') - ) - }} -

- Your auth token does not have access to {{model.policyPath}}. This is necessary in order to browse secret backends. -

-

- Make sure the policy for the path {{model.policyPath}} has capabilities = ['list', 'read']. -

{{else}} {{#if model.message}}

{{model.message}}

diff --git a/ui/app/templates/vault/cluster/secrets/backend/error.hbs b/ui/app/templates/vault/cluster/secrets/backend/error.hbs index 5a44976b6b03..5662dedf0a91 100644 --- a/ui/app/templates/vault/cluster/secrets/backend/error.hbs +++ b/ui/app/templates/vault/cluster/secrets/backend/error.hbs @@ -2,7 +2,7 @@