diff --git a/src/lib/engage/types.ts b/src/lib/engage/types.ts index 7d1b888d..af859fd7 100644 --- a/src/lib/engage/types.ts +++ b/src/lib/engage/types.ts @@ -752,6 +752,31 @@ export enum GatewayMode { GatewayOnlyMode = 'Gateway only', } +export enum AWSGatewayMode { + APIGateway = 'api-gateway', + AgentCoreGateway = 'agent-core-gateway', +} + +export class AWSAgentCoreConfig { + logGroupPrefix?: string; + iamAuthEnabled?: boolean; + + constructor(logGroupPrefix?: string, iamAuthEnabled?: boolean) { + this.logGroupPrefix = logGroupPrefix ?? ''; + this.iamAuthEnabled = iamAuthEnabled ?? false; + } +} + +export class AWSCognitoConfig { + userPoolId: string; + region?: string; + + constructor(userPoolId: string, region?: string) { + this.userPoolId = userPoolId; + this.region = region; + } +} + export enum AgentNames { AKAMAI_CA = 'akamai-compliance-agent', AWS_DA = 'aws-apigw-discovery-agent', diff --git a/src/lib/engage/utils/agents/flows/awsAgents.ts b/src/lib/engage/utils/agents/flows/awsAgents.ts index e97ea2fa..0017cfa3 100644 --- a/src/lib/engage/utils/agents/flows/awsAgents.ts +++ b/src/lib/engage/utils/agents/flows/awsAgents.ts @@ -2,7 +2,7 @@ import chalk from 'chalk'; import fs from 'fs'; import logger from '../../../../logger.js'; import { dataService } from '../../../../request.js'; -import { AgentConfigTypes, AgentInstallConfig, AgentNames, AgentTypes, AWSRegions, BasePaths, BundleType, GatewayTypes, InstallationFlowMethods, PublicDockerRepoBaseUrl, PublicRepoUrl, TrueFalse, YesNo, YesNoChoices } from '../../../types.js'; +import { AgentConfigTypes, AgentInstallConfig, AgentNames, AgentTypes, AWSCognitoConfig, AWSRegions, BasePaths, BundleType, GatewayTypes, InstallationFlowMethods, PublicDockerRepoBaseUrl, PublicRepoUrl, TrueFalse, YesNo, YesNoChoices } from '../../../types.js'; import { askInput, askList, validateInputLength, validateRegex } from '../../basic-prompts.js'; import { isWindows, writeTemplates, writeToFile } from '../../utils.js'; import { AWSAgentValues } from '../index.js'; @@ -77,6 +77,14 @@ export const AWSPrompts = { FULL_TRANSACTION_LOGGING: 'Do you want to enable Full Transaction Logging? Please note that CloudWatch costs would increase when Full Transaction Logging is enabled', TA_QUEUE: 'Enter the traceability queue name', VPC_ID: 'Enter the VPC ID to deploy the EC2 instance to. Leave blank to create entire infrastructure', + AGENT_CORE_GATEWAY_MODE: 'Do you want to enable Agent Core Gateway Mode? (If not, the default will be to run the agent in API Gateway mode)', + AGENT_CORE_LOG_GROUP_PREFIX: 'Enter the prefix for the Agent Core Gateway vendored logs', + AGENT_CORE_IAM_AUTH: 'Do you want to enable IAM Authentication for Agent Core Gateway requests?', + ENTER_MORE_COGNITO_USER_POOLS: 'Do you want to enter another Cognito User Pool for Agent Core Gateway mode?', + COGNITO: 'Enter the List of AWS Cognito user pools used for authentication in Agent Core Gateway mode', + COGNITO_USER_POOL_ID: 'Enter the User Pool ID for the Cognito User Pool the Agent Core will use for authentication', + ASK_COGNITO_REGION: 'Do you want to specify a region for the Cognito User Pool? (If not, the agent will use the same region as the gateway)', + COGNITO_REGION: 'Select the AWS region of the Cognito user pool. Defaults to the agent region if omitted', }; export const askBundleType = async (): Promise => { @@ -310,6 +318,64 @@ export const gatewayConnectivity = async (installConfig: AgentInstallConfig): Pr awsAgentValues.fullTransactionLogging = fullTransactionLogging; + awsAgentValues.agentCoreGatewayMode = (await askList({ + msg: AWSPrompts.AGENT_CORE_GATEWAY_MODE, + default: YesNo.No, + choices: YesNoChoices, + })) === YesNo.Yes; + + if (awsAgentValues.agentCoreGatewayMode) { + awsAgentValues.agentCore.logGroupPrefix = (await askInput({ + msg: AWSPrompts.AGENT_CORE_LOG_GROUP_PREFIX, + defaultValue: awsAgentValues.agentCore.logGroupPrefix !== '' ? awsAgentValues.agentCore.logGroupPrefix : undefined, + allowEmptyInput: true, + })) as string; + + awsAgentValues.agentCore.iamAuthEnabled = (await askList({ + msg: AWSPrompts.AGENT_CORE_IAM_AUTH, + default: YesNo.No, + choices: YesNoChoices, + })) === YesNo.Yes; + installConfig.log(chalk.gray(AWSPrompts.COGNITO)); + const cognitoUserPools: AWSCognitoConfig[] = []; + let askCognitoUserPools = true; + + while (askCognitoUserPools) { + const userPoolId = (await askInput({ + msg: AWSPrompts.COGNITO_USER_POOL_ID, + })) as string; + + const askRegion = (await askList({ + msg: AWSPrompts.ASK_COGNITO_REGION, + default: YesNo.No, + choices: YesNoChoices, + })) === YesNo.Yes; + + if (askRegion) { + + const regions = Object.values(AWSRegions).map((str) => ({ name: str, value: str })); + + const region = await askList({ + msg: AWSPrompts.COGNITO_REGION, + choices: regions, + + }); + + cognitoUserPools.push({ userPoolId, region }); + } else { + cognitoUserPools.push({ userPoolId, region: awsAgentValues.region }); + } + + askCognitoUserPools = await askList({ + msg: AWSPrompts.ENTER_MORE_COGNITO_USER_POOLS, + choices: YesNoChoices, + default: YesNo.No, + }) === YesNo.Yes; + } + + awsAgentValues.cognito = cognitoUserPools; + } + // set agent versions awsAgentValues.cloudFormationConfig.DiscoveryAgentVersion = installConfig.daVersion; awsAgentValues.cloudFormationConfig.TraceabilityAgentVersion = installConfig.taVersion; diff --git a/src/lib/engage/utils/agents/flows/awsSaasAgents.ts b/src/lib/engage/utils/agents/flows/awsSaasAgents.ts index f8997e82..74c9fb79 100644 --- a/src/lib/engage/utils/agents/flows/awsSaasAgents.ts +++ b/src/lib/engage/utils/agents/flows/awsSaasAgents.ts @@ -2,7 +2,7 @@ import chalk from 'chalk'; import logger from '../../../../logger.js'; import { ApiServerClient } from '../../../clients-external/apiserverclient.js'; import { DefinitionsManager } from '../../../results/DefinitionsManager.js'; -import { AgentConfigTypes, AgentInstallConfig, AgentNames, AgentTypes, BundleType, GatewayTypes, InstallationFlowMethods, SaaSGatewayTypes, YesNo, YesNoChoices } from '../../../types.js'; +import { AgentConfigTypes, AgentInstallConfig, AgentNames, AgentTypes, AWSAgentCoreConfig, AWSCognitoConfig, AWSGatewayMode, AWSRegions, BundleType, GatewayTypes, InstallationFlowMethods, SaaSGatewayTypes, YesNo, YesNoChoices } from '../../../types.js'; import { askInput, askList, validateInputLength, validateRegex } from '../../basic-prompts.js'; import * as helpers from '../index.js'; import { @@ -23,12 +23,17 @@ class AWSDataplaneConfig extends DataplaneConfig { accessLogARN: string; fullTransactionLogging: boolean; stageTagName: string; + gatewayMode: AWSGatewayMode; + agentCore: AWSAgentCoreConfig; + cognito: AWSCognitoConfig[]; - constructor(arn: string, enableFullTransactionLogging: boolean, stageTagName: string) { + constructor(arn: string, enableFullTransactionLogging: boolean, stageTagName: string, agentCoreConfig: AWSAgentCoreConfig, cognitoConfig: AWSCognitoConfig[]) { super('AWS'); this.accessLogARN = arn; this.fullTransactionLogging = enableFullTransactionLogging; this.stageTagName = stageTagName; + this.agentCore = agentCoreConfig; + this.cognito = cognitoConfig; } } @@ -47,6 +52,9 @@ class SaasAWSAgentValues extends SaasAgentValues { accessLogARN: string; fullTransactionLogging: boolean; stageTagName: string; + agentCoreGatewayMode: boolean; + agentCore: AWSAgentCoreConfig; + cognito: AWSCognitoConfig[]; constructor() { super(); @@ -59,8 +67,9 @@ class SaasAWSAgentValues extends SaasAgentValues { this.accessLogARN = ''; this.fullTransactionLogging = false; this.stageTagName = ''; + this.agentCore = {} as AWSAgentCoreConfig; + this.cognito = [] as AWSCognitoConfig[]; } - override getAccessData(): string { if (this.authType === AWSAuthType.KEYS) { return JSON.stringify({ @@ -87,6 +96,14 @@ const SaasPrompts = { ACCESS_LOG_ARN: 'Enter the ARN for the Access Log that the Discovery will add and the Traceability will use', STAGE_TAG_NAME: 'Enter the name of the tag on AWS API Gateway Stage that holds mapped stage on Amplify Engage', FULL_TRANSACTION_LOGGING: 'Do you want to enable Full Transaction Logging? Please note that CloudWatch costs would increase when Full Transaction Logging is enabled', + AGENT_CORE_GATEWAY_MODE: 'Do you want to enable Agent Core Gateway Mode? (If not, the default will be to run the agent in API Gateway mode)', + AGENT_CORE_LOG_GROUP_PREFIX: 'Enter the prefix for the Agent Core Gateway vendored logs', + AGENT_CORE_IAM_AUTH: 'Do you want to enable IAM Authentication for Agent Core Gateway requests?', + ENTER_MORE_COGNITO_USER_POOLS: 'Do you want to enter another Cognito User Pool for Agent Core Gateway mode?', + COGNITO: 'Enter the List of AWS Cognito user pools used for authentication in Agent Core Gateway mode', + COGNITO_USER_POOL_ID: 'Enter the User Pool ID for the Cognito User Pool the Agent Core will use for authentication', + ASK_COGNITO_REGION: 'Do you want to specify a region for the Cognito User Pool? (If not, the agent will use the same region as the gateway)', + COGNITO_REGION: 'Select the AWS region of the Cognito user pool. Defaults to the agent region if omitted', }; export const askBundleType = async (): Promise => { @@ -155,6 +172,69 @@ const askForAWSCredentials = async (agentValues: SaasAWSAgentValues, log: (text: return agentValues; }; +const askForAgentCoreGatewayMode = async (agentValues: SaasAWSAgentValues, log: (text: string) => void = () => {}): Promise => { + agentValues.agentCoreGatewayMode = (await askList({ + msg: SaasPrompts.AGENT_CORE_GATEWAY_MODE, + default: YesNo.No, + choices: YesNoChoices, + })) === YesNo.Yes; + + if (agentValues.agentCoreGatewayMode) { + agentValues.agentCore.logGroupPrefix = (await askInput({ + msg: SaasPrompts.AGENT_CORE_LOG_GROUP_PREFIX, + defaultValue: agentValues.agentCore.logGroupPrefix !== '' ? agentValues.agentCore.logGroupPrefix : undefined, + allowEmptyInput: true, + })) as string; + + agentValues.agentCore.iamAuthEnabled = (await askList({ + msg: SaasPrompts.AGENT_CORE_IAM_AUTH, + default: YesNo.No, + choices: YesNoChoices, + })) === YesNo.Yes; + log(chalk.gray(SaasPrompts.COGNITO)); + const cognitoUserPools: AWSCognitoConfig[] = []; + let askCognitoUserPools = true; + + while (askCognitoUserPools) { + const userPoolId = (await askInput({ + msg: SaasPrompts.COGNITO_USER_POOL_ID, + })) as string; + + const askRegion = (await askList({ + msg: SaasPrompts.ASK_COGNITO_REGION, + default: YesNo.No, + choices: YesNoChoices, + })) === YesNo.Yes; + + if (askRegion) { + + const regions = Object.values(AWSRegions).map((str) => ({ name: str, value: str })); + + const region = await askList({ + msg: SaasPrompts.COGNITO_REGION, + choices: regions, + + }); + + cognitoUserPools.push({ userPoolId, region }); + } else { + cognitoUserPools.push({ userPoolId, region: agentValues.region }); + } + + askCognitoUserPools = await askList({ + msg: SaasPrompts.ENTER_MORE_COGNITO_USER_POOLS, + choices: YesNoChoices, + default: YesNo.No, + }) === YesNo.Yes; + } + + agentValues.cognito = cognitoUserPools; + + } + + return agentValues; +}; + export const gatewayConnectivity = async (installConfig: AgentInstallConfig): Promise => { installConfig.log('\nCONNECTION TO AMAZON API GATEWAY:'); installConfig.log( @@ -174,6 +254,8 @@ export const gatewayConnectivity = async (installConfig: AgentInstallConfig): Pr validate: validateInputLength(STAGE_TAG_NAME_LENGTH, 'Maximum length of \'stage tag name\' is 127'), })) as string; + agentValues = await askForAgentCoreGatewayMode(awsValues, installConfig.log); + if (installConfig.switches.isTaEnabled) { installConfig.log(chalk.gray('\nThe access log ARN is a cloud watch log group amazon resource name')); awsValues.accessLogARN = (await askInput({ @@ -226,7 +308,9 @@ export const completeInstall = async ( dataplaneConfig = new AWSDataplaneConfig( awsAgentValues.accessLogARN, awsAgentValues.fullTransactionLogging, - awsAgentValues.stageTagName + awsAgentValues.stageTagName, + awsAgentValues.agentCore, + awsAgentValues.cognito ); } else { dataplaneConfig = new DataplaneConfig('AWS'); diff --git a/src/lib/engage/utils/agents/templates/awsTemplates.ts b/src/lib/engage/utils/agents/templates/awsTemplates.ts index 64d48608..8fe52123 100644 --- a/src/lib/engage/utils/agents/templates/awsTemplates.ts +++ b/src/lib/engage/utils/agents/templates/awsTemplates.ts @@ -1,4 +1,6 @@ import { + AWSAgentCoreConfig, + AWSCognitoConfig, CentralAgentConfig, CloudFormationConfig, TraceabilityConfig, @@ -19,6 +21,9 @@ export class AWSAgentValues { centralConfig: CentralAgentConfig; traceabilityConfig: TraceabilityConfig; cloudFormationConfig: CloudFormationConfig; + agentCoreGatewayMode: boolean; + agentCore: AWSAgentCoreConfig; + cognito: AWSCognitoConfig[]; constructor(awsDeployment: string) { this.accessKey = awsDeployment === 'Other' ? '**Insert Access Key**' : ''; @@ -31,6 +36,9 @@ export class AWSAgentValues { this.centralConfig = new CentralAgentConfig(); this.traceabilityConfig = new TraceabilityConfig(); this.cloudFormationConfig = new CloudFormationConfig(); + this.agentCoreGatewayMode = false; + this.agentCore = new AWSAgentCoreConfig(); + this.cognito = []; } updateCloudFormationConfig = () => { @@ -102,6 +110,17 @@ AWS_AUTH_SECRETKEY={{secretKey}} {{/if}} AWS_LOGGROUP={{logGroup}} AWS_STAGETAGNAME={{stageTagName}} +{{#if agentCoreGatewayMode}} +AWS_GATEWAYMODE=agentcore-gateway +AWS_AGENTCORE_LOGGROUPPREFIX={{agentCore.logGroupPrefix}} +AWS_AGENTCORE_IAMAUTHENABLED={{agentCore.iamAuthEnabled}} +{{#each cognito}} +AWS_COGNITO_USERPOOLID_{{add @index 1}}={{this.userPoolId}} +AWS_COGNITO_REGION_{{add @index 1}}={{this.region}} +{{/each}} +{{else}} +AWS_GATEWAYMODE=api-gateway +{{/if}} # Amplify Central configs CENTRAL_AGENTNAME={{centralConfig.daAgentName}} diff --git a/src/lib/engage/utils/utils.ts b/src/lib/engage/utils/utils.ts index 6acc5373..b11b5373 100644 --- a/src/lib/engage/utils/utils.ts +++ b/src/lib/engage/utils/utils.ts @@ -549,6 +549,8 @@ export const writeTemplates = (fileName: string, values: object, templateFunc: ( writeToFile(fileName, data); }; +hbs.registerHelper('add', (a: number, b: number) => a + b); + export const buildTemplate = (templateFunc: () => string, input: object): string => { const template = hbs.compile(templateFunc(), { noEscape: true }); return template(input); diff --git a/test/lib/engage/services/install-service/on-prem/test-aws.onprem.js b/test/lib/engage/services/install-service/on-prem/test-aws.onprem.js index 31572925..a0533fe1 100644 --- a/test/lib/engage/services/install-service/on-prem/test-aws.onprem.js +++ b/test/lib/engage/services/install-service/on-prem/test-aws.onprem.js @@ -94,6 +94,7 @@ describe('AWS on-prem agent flow', () => { flowModule.DeploymentTypes.EC2, 'Yes', 'No', + 'No', 't3.micro', 'Yes', ]; @@ -124,8 +125,9 @@ describe('AWS on-prem agent flow', () => { expect(result.logGroup).to.equal('/aws/apigw/logs'); expect(result.stageTagName).to.equal('stage-tag'); expect(result.fullTransactionLogging).to.equal(false); + expect(result.agentCoreGatewayMode).to.equal(false); expect(td.explain(promptStubs.askInput).callCount).to.equal(12); - expect(td.explain(promptStubs.askList).callCount).to.equal(5); + expect(td.explain(promptStubs.askList).callCount).to.equal(6); }); it('skips VPC-derived prompts when EC2 VPC is empty', async () => { @@ -133,6 +135,7 @@ describe('AWS on-prem agent flow', () => { flowModule.DeploymentTypes.EC2, 'Yes', 'No', + 'No', 't3.micro', ]; td.when(promptStubs.askList(td.matchers.anything())).thenDo(() => askListResponses.shift()); @@ -157,7 +160,7 @@ describe('AWS on-prem agent flow', () => { expect(result.cloudFormationConfig.SecurityGroup).to.equal(''); expect(result.cloudFormationConfig.Subnet).to.equal(''); expect(td.explain(promptStubs.askInput).callCount).to.equal(10); - expect(td.explain(promptStubs.askList).callCount).to.equal(4); + expect(td.explain(promptStubs.askList).callCount).to.equal(5); }); it('collects ECS-only deployment prompts', async () => { @@ -165,6 +168,7 @@ describe('AWS on-prem agent flow', () => { flowModule.DeploymentTypes.ECS_FARGATE, 'Yes', 'No', + 'No', ]; td.when(promptStubs.askList(td.matchers.anything())).thenDo(() => askListResponses.shift()); @@ -190,7 +194,7 @@ describe('AWS on-prem agent flow', () => { expect(result.cloudFormationConfig.EC2KeyName).to.equal(''); expect(logs.some((line) => line.includes('ECS Cluster Name'))).to.equal(true); expect(td.explain(promptStubs.askInput).callCount).to.equal(10); - expect(td.explain(promptStubs.askList).callCount).to.equal(3); + expect(td.explain(promptStubs.askList).callCount).to.equal(4); }); it('collects minimal prompts for OTHER deployment type', async () => { @@ -198,6 +202,7 @@ describe('AWS on-prem agent flow', () => { flowModule.DeploymentTypes.OTHER, 'Yes', 'No', + 'No', ]; td.when(promptStubs.askList(td.matchers.anything())).thenDo(() => askListResponses.shift()); @@ -218,7 +223,82 @@ describe('AWS on-prem agent flow', () => { expect(result.cloudFormationConfig.ECSClusterName).to.equal(''); expect(logs.some((line) => line.includes('AWS Access Key'))).to.equal(true); expect(td.explain(promptStubs.askInput).callCount).to.equal(5); - expect(td.explain(promptStubs.askList).callCount).to.equal(3); + expect(td.explain(promptStubs.askList).callCount).to.equal(4); + }); + + it('enables agent core gateway mode and collects a single cognito pool', async () => { + const askListResponses = [ + flowModule.DeploymentTypes.OTHER, + 'Yes', // APIGWCWRoleSetup + 'No', // fullTransactionLogging + 'Yes', // AGENT_CORE_GATEWAY_MODE + 'Yes', // iamAuthEnabled + 'No', // askRegion? (use agent region) + 'No', // enterMore? + ]; + td.when(promptStubs.askList(td.matchers.anything())).thenDo(() => askListResponses.shift()); + + const askInputResponses = [ + 'agents-bucket', + '/aws/apigw/logs', + 'stage-tag', + '/aws/prefix', + 'us-east-1_123456789', + '/aws/da/logs', + '/aws/ta/logs', + ]; + td.when(promptStubs.askInput(td.matchers.anything())).thenDo(() => askInputResponses.shift()); + + const result = await flowModule.gatewayConnectivity(buildInstallConfig({ isDaEnabled: true, isTaEnabled: true })); + + expect(result.agentCoreGatewayMode).to.equal(true); + expect(result.agentCore.logGroupPrefix).to.equal('/aws/prefix'); + expect(result.agentCore.iamAuthEnabled).to.equal(true); + expect(result.cognito).to.have.length(1); + expect(result.cognito[0].userPoolId).to.equal('us-east-1_123456789'); + expect(result.cognito[0].region).to.equal('us-east-1'); + expect(td.explain(promptStubs.askInput).callCount).to.equal(7); + expect(td.explain(promptStubs.askList).callCount).to.equal(7); + }); + + it('enables agent core gateway mode and collects multiple cognito pools', async () => { + const askListResponses = [ + flowModule.DeploymentTypes.OTHER, + 'Yes', // APIGWCWRoleSetup + 'No', // fullTransactionLogging + 'Yes', // AGENT_CORE_GATEWAY_MODE + 'No', // iamAuthEnabled + 'No', // askRegion? pool 1 + 'Yes', // enterMore? (add another pool) + 'No', // askRegion? pool 2 + 'No', // enterMore? + ]; + td.when(promptStubs.askList(td.matchers.anything())).thenDo(() => askListResponses.shift()); + + const askInputResponses = [ + 'agents-bucket', + '/aws/apigw/logs', + 'stage-tag', + '', + 'us-east-1_111111111', + 'eu-west-1_222222222', + '/aws/da/logs', + '/aws/ta/logs', + ]; + td.when(promptStubs.askInput(td.matchers.anything())).thenDo(() => askInputResponses.shift()); + + const result = await flowModule.gatewayConnectivity(buildInstallConfig({ isDaEnabled: true, isTaEnabled: true })); + + expect(result.agentCoreGatewayMode).to.equal(true); + expect(result.agentCore.logGroupPrefix).to.equal(''); + expect(result.agentCore.iamAuthEnabled).to.equal(false); + expect(result.cognito).to.have.length(2); + expect(result.cognito[0].userPoolId).to.equal('us-east-1_111111111'); + expect(result.cognito[0].region).to.equal('us-east-1'); + expect(result.cognito[1].userPoolId).to.equal('eu-west-1_222222222'); + expect(result.cognito[1].region).to.equal('us-east-1'); + expect(td.explain(promptStubs.askInput).callCount).to.equal(8); + expect(td.explain(promptStubs.askList).callCount).to.equal(9); }); it('stops question flow when AWS region lookup fails', async () => { @@ -354,6 +434,9 @@ function createHelpersStubs() { this.logGroup = ''; this.region = 'us-east-1'; this.stageTagName = ''; + this.agentCoreGatewayMode = false; + this.agentCore = { logGroupPrefix: '', iamAuthEnabled: false }; + this.cognito = []; this.cloudFormationConfig = { APIGWCWRoleSetup: '', APIGWTrafficLogGroupName: '/aws/apigw/logs', @@ -383,6 +466,18 @@ function createHelpersStubs() { return { AWSAgentValues, + AWSCognitoConfig: class AWSCognitoConfig { + constructor(userPoolId, region) { + this.userPoolId = userPoolId; + this.region = region; + } + }, + AWSAgentCoreConfig: class AWSAgentCoreConfig { + constructor(logGroupPrefix, iamAuthEnabled) { + this.logGroupPrefix = logGroupPrefix ?? ''; + this.iamAuthEnabled = iamAuthEnabled ?? false; + } + }, AWSRegexPatterns: { AWS_REGEXP: /.*/, AWS_REGEXP_LOG_GROUP_NAME: /.*/, diff --git a/test/lib/engage/services/install-service/saas/test-aws.saas.js b/test/lib/engage/services/install-service/saas/test-aws.saas.js index 677bcfb9..de00d2ac 100644 --- a/test/lib/engage/services/install-service/saas/test-aws.saas.js +++ b/test/lib/engage/services/install-service/saas/test-aws.saas.js @@ -70,12 +70,13 @@ describe('AWS SaaS agent flow', () => { 'arn:aws:logs:us-east-1:000000000000:log-group:my-group', ]; td.when(promptStubs.askInput(td.matchers.anything())).thenDo(() => askInputResponses.shift()); - const askListResponses = [ 'Assume Role Policy', engageTypes.YesNo.Yes ]; + const askListResponses = [ 'Assume Role Policy', engageTypes.YesNo.No, engageTypes.YesNo.Yes ]; td.when(promptStubs.askList(td.matchers.anything())).thenDo(() => askListResponses.shift()); const result = await flowModule.AWSSaaSInstallMethods.AskGatewayQuestions(buildInstallConfig(engageTypes.GatewayTypes.AWS_GATEWAY, true)); expect(result.authType).to.equal('Assume Role Policy'); expect(result.assumeRole).to.contain('arn:aws:iam'); + expect(result.agentCoreGatewayMode).to.equal(false); expect(result.fullTransactionLogging).to.equal(true); }); @@ -132,6 +133,7 @@ describe('AWS SaaS agent flow', () => { const askListResponses = [ 'Assume Role Policy', + engageTypes.YesNo.No, engageTypes.YesNo.Yes, engageTypes.YesNo.No, engageTypes.YesNo.No, @@ -154,12 +156,45 @@ describe('AWS SaaS agent flow', () => { expect(result.redaction.maskingCharacter).to.equal('***'); }); + it('collects agent core gateway mode with IAM auth enabled and a single cognito pool', async () => { + const askInputResponses = [ + 'arn:aws:iam::000000000000:role/name-of-role', + 'external-id', + 'stage-tag', + '/aws/prefix', + 'us-east-1_123456789', + 'arn:aws:logs:us-east-1:000000000000:log-group:my-group', + ]; + td.when(promptStubs.askInput(td.matchers.anything())).thenDo(() => askInputResponses.shift()); + + const askListResponses = [ + 'Assume Role Policy', + engageTypes.YesNo.Yes, + engageTypes.YesNo.Yes, + engageTypes.YesNo.No, + engageTypes.YesNo.No, + engageTypes.YesNo.No, + ]; + td.when(promptStubs.askList(td.matchers.anything())).thenDo(() => askListResponses.shift()); + + const result = await flowModule.AWSSaaSInstallMethods.AskGatewayQuestions(buildInstallConfig(engageTypes.GatewayTypes.AWS_GATEWAY, true)); + expect(result.agentCoreGatewayMode).to.equal(true); + expect(result.agentCore.logGroupPrefix).to.equal('/aws/prefix'); + expect(result.agentCore.iamAuthEnabled).to.equal(true); + expect(result.cognito).to.have.length(1); + expect(result.cognito[0].userPoolId).to.equal('us-east-1_123456789'); + expect(result.cognito[0].region).to.equal('us-east-1'); + expect(result.fullTransactionLogging).to.equal(false); + }); + it('builds AWS dataplane config when TA enabled', async () => { const installConfig = buildInstallConfig(engageTypes.GatewayTypes.AWS_GATEWAY, true); installConfig.gatewayConfig = { accessLogARN: 'arn:aws:logs:us-east-1:000000000000:log-group:my-group', fullTransactionLogging: true, stageTagName: 'stage-tag', + agentCore: { logGroupPrefix: '/aws/prefix', iamAuthEnabled: true }, + cognito: [ { userPoolId: 'us-east-1_123456789', region: 'us-east-1' } ], redaction: {}, }; @@ -167,6 +202,8 @@ describe('AWS SaaS agent flow', () => { const dataplaneArg = td.explain(saasBaseStubs.createDataplaneResources).calls[0].args[1]; expect(dataplaneArg.type).to.equal('AWS'); expect(dataplaneArg.accessLogARN).to.contain('arn:aws:logs'); + expect(dataplaneArg.agentCore).to.deep.equal({ logGroupPrefix: '/aws/prefix', iamAuthEnabled: true }); + expect(dataplaneArg.cognito).to.deep.equal([ { userPoolId: 'us-east-1_123456789', region: 'us-east-1' } ]); }); it('passes IDP config in completeInstall context', async () => {