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
15 changes: 15 additions & 0 deletions src/lib/engage/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,21 @@ 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 enum AgentNames {
AKAMAI_CA = 'akamai-compliance-agent',
AWS_DA = 'aws-apigw-discovery-agent',
Expand Down
45 changes: 45 additions & 0 deletions src/lib/engage/utils/agents/flows/awsAgents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ 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_POOL_IDS: 'Do you want to enter another Cognito User Pool ID for Agent Core Gateway mode?',
COGNITO: 'Enter the List of AWS Cognito user pool IDs 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',
};

export const askBundleType = async (): Promise<BundleType> => {
Expand Down Expand Up @@ -310,6 +316,45 @@ 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 cognitoUserPoolIDs: string[] = [];
let askCognitoUserPools = true;

while (askCognitoUserPools) {
const userPoolId = (await askInput({
msg: AWSPrompts.COGNITO_USER_POOL_ID,
})) as string;

cognitoUserPoolIDs.push(userPoolId);

askCognitoUserPools = await askList({
msg: AWSPrompts.ENTER_MORE_COGNITO_USER_POOL_IDS,
choices: YesNoChoices,
default: YesNo.No,
}) === YesNo.Yes;
}

awsAgentValues.cognitoUserPoolIDs = cognitoUserPoolIDs;
}

// set agent versions
awsAgentValues.cloudFormationConfig.DiscoveryAgentVersion = installConfig.daVersion;
awsAgentValues.cloudFormationConfig.TraceabilityAgentVersion = installConfig.taVersion;
Expand Down
71 changes: 67 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, AWSGatewayMode, 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;
cognitoUserPoolIDs: string[];

constructor(arn: string, enableFullTransactionLogging: boolean, stageTagName: string) {
constructor(arn: string, enableFullTransactionLogging: boolean, stageTagName: string, agentCoreConfig: AWSAgentCoreConfig, cognitoUserPoolIDs: string[]) {
super('AWS');
this.accessLogARN = arn;
this.fullTransactionLogging = enableFullTransactionLogging;
this.stageTagName = stageTagName;
this.agentCore = agentCoreConfig;
this.cognitoUserPoolIDs = cognitoUserPoolIDs;
}
}

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

constructor() {
super();
Expand All @@ -59,8 +67,9 @@ class SaasAWSAgentValues extends SaasAgentValues {
this.accessLogARN = '';
this.fullTransactionLogging = false;
this.stageTagName = '';
this.agentCore = {} as AWSAgentCoreConfig;
this.cognitoUserPoolIDs = [] as string[];
}

override getAccessData(): string {
if (this.authType === AWSAuthType.KEYS) {
return JSON.stringify({
Expand All @@ -87,6 +96,12 @@ 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_POOL_IDS: 'Do you want to enter another Cognito User Pool ID for Agent Core Gateway mode?',
COGNITO: 'Enter the List of AWS Cognito user pool IDs 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',
};

export const askBundleType = async (): Promise<BundleType> => {
Expand Down Expand Up @@ -155,6 +170,50 @@ 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 cognitoUserPoolIDs: string[] = [];
let askCognitoUserPools = true;

while (askCognitoUserPools) {
const userPoolId = (await askInput({
msg: SaasPrompts.COGNITO_USER_POOL_ID,
})) as string;

cognitoUserPoolIDs.push(userPoolId);

askCognitoUserPools = await askList({
msg: SaasPrompts.ENTER_MORE_COGNITO_USER_POOL_IDS,
choices: YesNoChoices,
default: YesNo.No,
}) === YesNo.Yes;
}

agentValues.cognitoUserPoolIDs = cognitoUserPoolIDs;

}

return agentValues;
};

export const gatewayConnectivity = async (installConfig: AgentInstallConfig): Promise<SaasAgentValues> => {
installConfig.log('\nCONNECTION TO AMAZON API GATEWAY:');
installConfig.log(
Expand All @@ -174,6 +233,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 +287,9 @@ export const completeInstall = async (
dataplaneConfig = new AWSDataplaneConfig(
awsAgentValues.accessLogARN,
awsAgentValues.fullTransactionLogging,
awsAgentValues.stageTagName
awsAgentValues.stageTagName,
awsAgentValues.agentCore,
awsAgentValues.cognitoUserPoolIDs
);
} else {
dataplaneConfig = new DataplaneConfig('AWS');
Expand Down
17 changes: 17 additions & 0 deletions src/lib/engage/utils/agents/templates/awsTemplates.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
AWSAgentCoreConfig,
CentralAgentConfig,
CloudFormationConfig,
TraceabilityConfig,
Expand All @@ -19,6 +20,9 @@ export class AWSAgentValues {
centralConfig: CentralAgentConfig;
traceabilityConfig: TraceabilityConfig;
cloudFormationConfig: CloudFormationConfig;
agentCoreGatewayMode: boolean;
agentCore: AWSAgentCoreConfig;
cognitoUserPoolIDs: string[];

constructor(awsDeployment: string) {
this.accessKey = awsDeployment === 'Other' ? '**Insert Access Key**' : '';
Expand All @@ -31,6 +35,9 @@ export class AWSAgentValues {
this.centralConfig = new CentralAgentConfig();
this.traceabilityConfig = new TraceabilityConfig();
this.cloudFormationConfig = new CloudFormationConfig();
this.agentCoreGatewayMode = false;
this.agentCore = new AWSAgentCoreConfig();
this.cognitoUserPoolIDs = [];
}

updateCloudFormationConfig = () => {
Expand Down Expand Up @@ -102,6 +109,16 @@ 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 cognitoUserPoolIDs}}
AWS_COGNITO_USERPOOLID_{{add @index 1}}={{this}}
{{/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