diff --git a/addons/api/addon/serializers/host-catalog.js b/addons/api/addon/serializers/host-catalog.js index 2e3163df6..b83a053f3 100644 --- a/addons/api/addon/serializers/host-catalog.js +++ b/addons/api/addon/serializers/host-catalog.js @@ -7,6 +7,7 @@ import ApplicationSerializer from './application'; import { TYPE_HOST_CATALOG_PLUGIN_AWS, TYPE_HOST_CATALOG_PLUGIN_AZURE, + TYPE_CREDENTIAL_DYNAMIC, } from '../models/host-catalog'; // These fields are Azure specific @@ -41,7 +42,7 @@ const AWSfieldsWithCredentialType = { export default class HostCatalogSerializer extends ApplicationSerializer { serialize(snapshot) { - const { compositeType } = snapshot.record; + const { compositeType, credentialType } = snapshot.record; const serialized = super.serialize(...arguments); // This is a hack to remove the worker_filter field from the serialized data if the compositeType is not AWS @@ -50,6 +51,11 @@ export default class HostCatalogSerializer extends ApplicationSerializer { delete serialized.worker_filter; } + // By default, disable credential rotation for dynamic credentials + if (credentialType === TYPE_CREDENTIAL_DYNAMIC) { + serialized.attributes.disable_credential_rotation = true; + } + switch (compositeType) { case 'static': return this.serializeStatic(...arguments); diff --git a/addons/core/translations/resources/en-us.yaml b/addons/core/translations/resources/en-us.yaml index 6b2e80bd5..c09d23d66 100644 --- a/addons/core/translations/resources/en-us.yaml +++ b/addons/core/translations/resources/en-us.yaml @@ -212,6 +212,8 @@ host-catalog: help: static: Provide a list of hosts and host sets with static addresses plugin: Automate discovery of target hosts and services on Azure or AWS + role_arn: The ARN (Amazon Resource Name) used by this instance. + disable_credential_rotation: Credential rotation is automatically disabled when you use dynamic credentials. types: static: Static unknown: Plugin @@ -228,7 +230,7 @@ host-catalog: dynamic-credential: edit: Dynamic Credentials label: Use Assume Role (Dynamic Credentials) - help: Specify an Assume Role used to generate credentials to use with this AWS Host Catalog. + help: Specify a role used to generate credentials to use with this AWS Host Catalog. form: aws_region: label: AWS Region @@ -479,7 +481,7 @@ storage-bucket: help: The base path where session recordings will be stored. role_arn: label: Role ARN - help: The ARN (Assume Role Name) used by this instance that the worker runs on. + help: The ARN (Amazon Resource Name) used by this instance that the worker runs on. role_external_id: label: Role external ID help: Used to provide access to this account if you have this configured. diff --git a/ui/admin/app/components/form/host-catalog/aws/index.hbs b/ui/admin/app/components/form/host-catalog/aws/index.hbs index 4b47803cc..1776cf8d0 100644 --- a/ui/admin/app/components/form/host-catalog/aws/index.hbs +++ b/ui/admin/app/components/form/host-catalog/aws/index.hbs @@ -145,7 +145,12 @@ {{#if @model.isNew}} - + {{t 'resources.host-catalog.types.credential.label'}} @@ -217,7 +222,7 @@ {{t 'resources.storage-bucket.form.role_arn.label'}} - {{t 'resources.storage-bucket.form.role_arn.help'}} + {{t 'resources.host-catalog.help.role_arn'}} {{#if @model.errors.role_arn}} @@ -364,46 +369,64 @@ {{/if}} - - - {{t 'resources.host-catalog.form.worker_filter.label'}} - - - {{t 'resources.host-catalog.form.worker_filter.help'}} - - {{t 'actions.learn-more'}} - - - {{#if @model.errors.worker_filter}} - - {{#each @model.errors.worker_filter as |error|}} - - {{error.message}} - - {{/each}} - - {{/if}} - - - - - {{t 'form.disable_credential_rotation.label'}} - - + {{#if (feature-flag 'dynamic-credentials-worker-filter')}} + + + {{t 'resources.host-catalog.form.worker_filter.label'}} + + + {{t 'resources.host-catalog.form.worker_filter.help'}} + + {{t 'actions.learn-more'}} + + + {{#if @model.errors.worker_filter}} + + {{#each @model.errors.worker_filter as |error|}} + + {{error.message}} + + {{/each}} + + {{/if}} + + {{/if}} + {{#if this.showDynamicCredentials}} + + + {{t 'form.disable_credential_rotation.label'}} + + + {{t 'resources.host-catalog.help.disable_credential_rotation'}} + + + {{else}} + + + {{t 'form.disable_credential_rotation.label'}} + + + {{/if}}   {{#if (can 'save model' @model)}} diff --git a/ui/admin/app/styles/app.scss b/ui/admin/app/styles/app.scss index 68bf9d4b0..e853ccdef 100644 --- a/ui/admin/app/styles/app.scss +++ b/ui/admin/app/styles/app.scss @@ -1073,3 +1073,9 @@ gap: 1.5rem; } } + +.dynamic-credential-selection { + .hds-form-group__control-field { + margin-bottom: 0; + } +} diff --git a/ui/admin/config/features.js b/ui/admin/config/features.js index 84a2d8d13..5c0908787 100644 --- a/ui/admin/config/features.js +++ b/ui/admin/config/features.js @@ -28,6 +28,7 @@ const baseEdition = { 'target-network-address': false, 'vault-worker-filter': false, 'ldap-auth-methods': false, + 'dynamic-credentials-worker-filter': false, }; // Editions maps edition keys to their associated featuresets. const featureEditions = {}; @@ -43,6 +44,7 @@ featureEditions.enterprise = { ...featureEditions.oss, 'target-worker-filters-v2-ingress': true, 'vault-worker-filter': true, + 'dynamic-credentials-worker-filter': true, }; featureEditions.hcp = { ...featureEditions.enterprise, diff --git a/ui/admin/tests/acceptance/host-catalogs/create-test.js b/ui/admin/tests/acceptance/host-catalogs/create-test.js index 584d9c1cc..acbb780ab 100644 --- a/ui/admin/tests/acceptance/host-catalogs/create-test.js +++ b/ui/admin/tests/acceptance/host-catalogs/create-test.js @@ -21,6 +21,7 @@ module('Acceptance | host-catalogs | create', function (hooks) { setupMirage(hooks); setupIndexedDb(hooks); + let featuresService; let getHostCatalogCount; const NAME_INPUT_SELECTOR = '[name="name"]'; @@ -84,6 +85,8 @@ module('Acceptance | host-catalogs | create', function (hooks) { urls.newStaticHostCatalog = `${urls.newHostCatalog}?type=static`; urls.newAWSDynamicHostCatalog = `${urls.newHostCatalog}?type=aws`; urls.newAzureDynamicHostCatalog = `${urls.newHostCatalog}?type=azure`; + featuresService = this.owner.lookup('service:features'); + // Generate resource counter getHostCatalogCount = () => this.server.schema.hostCatalogs.all().models.length; @@ -196,6 +199,17 @@ module('Acceptance | host-catalogs | create', function (hooks) { assert.dom('[data-test-error-message-name]').hasText('Name is required.'); }); + test('users should not see worker filter field in community edition', async function (assert) { + await visit(urls.newAWSDynamicHostCatalog); + assert.dom('[data-test-dynamic-credential-worker-filter]').doesNotExist(); + }); + + test('users should see worker filter field in enterprise edition', async function (assert) { + featuresService.enable('dynamic-credentials-worker-filter'); + await visit(urls.newAWSDynamicHostCatalog); + assert.dom('[data-test-dynamic-credential-worker-filter]').exists(); + }); + test('users cannot directly navigate to new host catalog route without proper authorization', async function (assert) { instances.scopes.project.authorized_collection_actions['host-catalogs'] = instances.scopes.project.authorized_collection_actions[