diff --git a/ui/app/adapters/secret-engine.js b/ui/app/adapters/secret-engine.js index f8230f7e6532..c19b68b3fb17 100644 --- a/ui/app/adapters/secret-engine.js +++ b/ui/app/adapters/secret-engine.js @@ -117,14 +117,12 @@ export default ApplicationAdapter.extend({ } }, - // ARG Todo moving to own adapter/model/serializer saveAWSRoot(store, type, snapshot) { const { data } = snapshot.adapterOptions; const path = encodePath(snapshot.id); return this.ajax(`/v1/${path}/config/root`, 'POST', { data }); }, - // ARG Todo moving to own adapter/model/serializer saveAWSLease(store, type, snapshot) { const { data } = snapshot.adapterOptions; const path = encodePath(snapshot.id); diff --git a/ui/app/components/secret-engine/configurable-secret-engine-details.js b/ui/app/components/secret-engine/configurable-secret-engine-details.js deleted file mode 100644 index 81b7bf2ed43b..000000000000 --- a/ui/app/components/secret-engine/configurable-secret-engine-details.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: BUSL-1.1 - */ - -import { service } from '@ember/service'; -import Component from '@glimmer/component'; -import errorMessage from 'vault/utils/error-message'; -import { tracked } from '@glimmer/tracking'; -// ARG TODO add documentation -export default class ConfigurableSecretEngineDetails extends Component { - @service store; - @tracked configModel = null; - @tracked configError = null; - - constructor() { - super(...arguments); - const { model } = this.args; - // Currently two secret engines that return configuration data and that can be configured by the user on the ui: aws, and ssh. - if (model.type === 'aws') { - this.fetchAwsRootConfig(model.id); - } - if (model.type === 'ssh') { - this.fetchSshCaConfig(model.id); - } - } - - async fetchAwsRootConfig(backend) { - try { - this.configModel = await this.store.queryRecord('aws/root-config', { backend }); - } catch (e) { - this.configError = errorMessage(e); - } - } - - async fetchSshCaConfig(backend) { - try { - this.configModel = await this.store.queryRecord('ssh/ca-config', { backend }); - } catch (e) { - this.configError = errorMessage(e); - } - } - - get typeDisplay() { - // TODO will eventually handle GCP and Azure. - // Did not use capitalize helper because some are all caps and some only title case. - const { type } = this.args.model; - switch (type) { - case 'aws': - return 'AWS'; - case 'ssh': - return 'SSH'; - default: - return type; - } - } -} diff --git a/ui/app/components/secret-engine/configurable-secret-engine-details.ts b/ui/app/components/secret-engine/configurable-secret-engine-details.ts new file mode 100644 index 000000000000..c990ae763f5b --- /dev/null +++ b/ui/app/components/secret-engine/configurable-secret-engine-details.ts @@ -0,0 +1,89 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { service } from '@ember/service'; +import Component from '@glimmer/component'; +import errorMessage from 'vault/utils/error-message'; +import { tracked } from '@glimmer/tracking'; + +import type Store from '@ember-data/store'; +import type SecretEngineModel from 'vault/models/secret-engine'; +import type AdapterError from 'ember-data/adapter'; // eslint-disable-line ember/use-ember-data-rfc-395-imports + +/** + * @module ConfigurableSecretEngineDetails + * The `ConfigurableSecretEngineDetails` is used by configurable secret engines to show either a prompt, error + * or configuration details depending on the response from the engines specific config endpoint (ex: aws -> aws/root-config vs ssh: ssh/ca-config). + * + * @example ```js + * ``` + * + * @param {object} model - The secret-engine model to be configured. + * + */ + +interface Args { + model: SecretEngineModel; +} + +export default class ConfigurableSecretEngineDetails extends Component { + @service declare readonly store: Store; + @tracked configModel = null; + @tracked configError: string | null = null; + + constructor(owner: unknown, args: Args) { + super(owner, args); + const { model } = this.args; + // Currently two secret engines that return configuration data and that can be configured by the user on the ui: aws, and ssh. + if (model.type === 'aws') { + this.fetchAwsRootConfig(model.id); + } + if (model.type === 'ssh') { + this.fetchSshCaConfig(model.id); + } + } + + async fetchAwsRootConfig(backend: string) { + try { + this.configModel = await this.store.queryRecord('aws/root-config', { backend }); + } catch (e: AdapterError) { + // if it's a 404 then the user has not configured the backend yet and we want to show the prompt instead + if (e.httpStatus !== 404) { + this.configError = errorMessage(e); + } + return; + } + } + + async fetchSshCaConfig(backend: string) { + try { + this.configModel = await this.store.queryRecord('ssh/ca-config', { backend }); + } catch (e: AdapterError) { + // Unfortunately, SSH Api will return a 400 Bad request when GET /v1/ssh/ca-config is called. + // Unlike the AWS Api, the SSH Api does not return a 404 not found but always an error. + // Thus to show a prompt instead of an error when first configuring the backend, we need to catch the error, + // and transform it into a semi-prompt. This way, in case there is a true error we show it, but we also don't immediately show an error after mounting the engine. + if (e.httpStatus !== 404) { + // if it's a 404 then the user has not configured the backend yet and we want to show the prompt instead + this.configError = `${backend} has not been configured yet. Please configure it to use this feature. ${e.message}`; + } + return; + } + } + + get typeDisplay() { + // Will eventually handle GCP and Azure. + // Did not use capitalize helper because some are all caps and some only title case. + const { type } = this.args.model; + switch (type) { + case 'aws': + return 'AWS'; + case 'ssh': + return 'SSH'; + default: + return type; + } + } +} diff --git a/ui/app/templates/vault/cluster/secrets/backend/configuration.hbs b/ui/app/templates/vault/cluster/secrets/backend/configuration.hbs index 33bf815f3284..24522608108d 100644 --- a/ui/app/templates/vault/cluster/secrets/backend/configuration.hbs +++ b/ui/app/templates/vault/cluster/secrets/backend/configuration.hbs @@ -15,7 +15,7 @@ /> {{#if this.isConfigurable}} - {{! only relevant to SSH and AWS, eventually Azure and GCP }} + {{! only configurable secret engines are SSH and AWS. Eventually we will add Azure and GCP }} - + diff --git a/ui/types/vault/models/secret-engine.d.ts b/ui/types/vault/models/secret-engine.d.ts index cce4d0d6be95..635542df2f4d 100644 --- a/ui/types/vault/models/secret-engine.d.ts +++ b/ui/types/vault/models/secret-engine.d.ts @@ -9,6 +9,7 @@ import type { ModelValidations, FormField, FormFieldGroups } from 'vault/app-typ import type MountConfigModel from 'vault/models/mount-config'; export default class SecretEngineModel extends Model { + id: string; path: string; type: string; description: string;