Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions src/lib/engage/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
68 changes: 67 additions & 1 deletion src/lib/engage/utils/agents/flows/awsAgents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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<BundleType> => {
Expand Down Expand Up @@ -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;
Expand Down
92 changes: 88 additions & 4 deletions src/lib/engage/utils/agents/flows/awsSaasAgents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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;
}
}

Expand All @@ -47,6 +52,9 @@ class SaasAWSAgentValues extends SaasAgentValues {
accessLogARN: string;
fullTransactionLogging: boolean;
stageTagName: string;
agentCoreGatewayMode: boolean;
agentCore: AWSAgentCoreConfig;
cognito: AWSCognitoConfig[];

constructor() {
super();
Expand All @@ -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({
Expand All @@ -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<BundleType> => {
Expand Down Expand Up @@ -155,6 +172,69 @@ const askForAWSCredentials = async (agentValues: SaasAWSAgentValues, log: (text:
return agentValues;
};

const askForAgentCoreGatewayMode = async (agentValues: SaasAWSAgentValues, log: (text: string) => void = () => {}): Promise<SaasAWSAgentValues> => {
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<SaasAgentValues> => {
installConfig.log('\nCONNECTION TO AMAZON API GATEWAY:');
installConfig.log(
Expand All @@ -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({
Expand Down Expand Up @@ -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');
Expand Down
19 changes: 19 additions & 0 deletions src/lib/engage/utils/agents/templates/awsTemplates.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import {
AWSAgentCoreConfig,
AWSCognitoConfig,
CentralAgentConfig,
CloudFormationConfig,
TraceabilityConfig,
Expand All @@ -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**' : '';
Expand All @@ -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 = () => {
Expand Down Expand Up @@ -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}}
Expand Down
2 changes: 2 additions & 0 deletions src/lib/engage/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading
Loading