Skip to content
Merged
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
2 changes: 1 addition & 1 deletion src/commands/engage/install/agents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { installAgents } from '../../../lib/engage/services/install-service.js';
import { highlight } from '../../../lib/logger.js';

export class EngageInstallAgentsCommand extends Command {
static override summary = 'Amplify API Gateway / Apigee X Gateway / Amazon API Gateway / Azure API Gateway / Azure EventHub / Backstage / GitLab / Istio / Kafka /'
static override summary = 'Amplify API Gateway / Apigee X Gateway / AWS / Azure API Gateway / Azure EventHub / Backstage / GitLab / Istio / Kafka /'
+ ' Graylog / IBM API Connect / SwaggerHub / Software AG WebMethods / Traceable / SAP API Portal / Sensedia / WSO2';

static override aliases = [ 'central:install:agents' ];
Expand Down
2 changes: 1 addition & 1 deletion src/lib/engage/services/create-service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import chalk from 'chalk';
import { ApiServerClient } from '../clients-external/apiserverclient.js';
import { DefinitionsManager } from '../results/DefinitionsManager.js';
import { AgentResourceCreateResult, AgentResourceKind, AgentTypes, ApiServerClientSingleResult, ApiServerVersions, BundleType, CreateCommandParams, CreateCommandResult, CreateEnvironmentCommandParams, DataPlaneNames, EngageCommandParams, GenericResource } from '../types.js';
import { AgentResourceCreateResult, AgentResourceKind, AgentTypes, ApiServerClientSingleResult, BundleType, CreateCommandParams, CreateCommandResult, CreateEnvironmentCommandParams, DataPlaneNames, EngageCommandParams, GenericResource } from '../types.js';
import { getLatestServedAPIVersion, loadAndVerifySpecs, verifyFile } from '../utils/utils.js';
import { askInput, askList } from '../utils/basic-prompts.js';
import { askAgentName, askEnvironmentName } from '../utils/agents/inputs.js';
Expand Down
23 changes: 21 additions & 2 deletions src/lib/engage/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,25 @@ export enum GatewayMode {
GatewayOnlyMode = 'Gateway only',
}

export enum AWSGatewayMode {
APIGateway = 'api-gateway',
AgentCoreGateway = 'agent-core-gateway',
}

export class AWSAgentCoreConfig {
logGroupPrefix?: string;
iamAuthEnabled?: boolean;
cloudTrailEnabled?: boolean;
cloudTrailBucket?: string;

constructor(logGroupPrefix?: string, iamAuthEnabled?: boolean, cloudTrailEnabled?: boolean, cloudTrailBucket?: string) {
this.logGroupPrefix = logGroupPrefix ?? '';
this.iamAuthEnabled = iamAuthEnabled ?? false;
this.cloudTrailEnabled = cloudTrailEnabled ?? false;
this.cloudTrailBucket = cloudTrailBucket ?? '';
}
}

export enum AgentNames {
AKAMAI_CA = 'akamai-compliance-agent',
AWS_DA = 'aws-apigw-discovery-agent',
Expand Down Expand Up @@ -787,7 +806,7 @@ export enum GatewayTypes {
AKAMAI = 'Akamai',
EDGE_GATEWAY = 'Amplify API Gateway',
APIGEEX_GATEWAY = 'Apigee X Gateway',
AWS_GATEWAY = 'Amazon API Gateway',
AWS_GATEWAY = 'AWS',
AZURE_GATEWAY = 'Azure API Gateway',
AZURE_EVENTHUB = 'Azure EventHub',
GITLAB = 'GitLab',
Expand All @@ -806,7 +825,7 @@ export enum GatewayTypes {

export enum SaaSGatewayTypes {
AKAMAI = 'Akamai',
AWS_GATEWAY = 'Amazon API Gateway',
AWS_GATEWAY = 'AWS',
APIGEEX_GATEWAY = 'Apigee X Gateway',
GITHUB = 'GitHub',
SWAGGERHUB = 'SwaggerHub',
Expand Down
170 changes: 110 additions & 60 deletions src/lib/engage/utils/agents/flows/awsAgents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export const AWSPrompts = {
PUBLIC_IP: 'Assign a Public IP Address to this, only change if your VPC has a NAT Gateway',
SECURITY_GROUP: 'Enter the Security Group for the EC2 Instance of ECS Container',
SETUP_APIGW_CW:
'The Amazon API Gateway service requires a role to write usage logs to Cloud Watch. Do you want to configure that?',
'The AWS API Gateway service requires a role to write usage logs to Cloud Watch. Do you want to configure that?',
SSH_LOCATION: 'Enter the IP address range that can be used to SSH to the EC2 instances',
SSM_PRIVATE: 'Enter the name of the SSM Parameter holding the Private Key',
SSM_PUBLIC: 'Enter the name of the SSM Parameter holding the Public Key',
Expand All @@ -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 AgentCore 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 AgentCore Gateway vendored logs',
AGENT_CORE_IAM_AUTH: 'Do you want to enable IAM Authentication for AgentCore Gateway requests?',
ENTER_MORE_COGNITO_USER_POOL_IDS: 'Do you want to enter another Cognito User Pool ID for AgentCore Gateway mode?',
COGNITO: 'Enter the List of AWS Cognito user pool IDs used for authentication in AgentCore Gateway mode',
COGNITO_USER_POOL_ID: 'Enter the User Pool ID for the Cognito User Pool the AgentCore will use for authentication',
AGENTCORE_CLOUDTRAILENABLED: 'Do you want to enable CloudTrail-based consumer attribution for Cognito gateway?',
AGENTCORE_CLOUDTRAILBUCKET: 'Enter the name of the S3 bucket that stores the CloudTrail data-event logs'
};

export const askBundleType = async (): Promise<BundleType> => {
Expand Down Expand Up @@ -241,7 +249,7 @@ async function configureECSDeployment(awsAgentValues: helpers.AWSAgentValues): P
}

export const gatewayConnectivity = async (installConfig: AgentInstallConfig): Promise<AWSAgentValues> => {
installConfig.log('\nCONNECTION TO AMAZON API GATEWAY:');
installConfig.log('\nCONNECTION TO AWS:');
installConfig.log(
chalk.gray(
'You need credentials for executing the AWS CLI commands.\n'
Expand Down Expand Up @@ -276,69 +284,111 @@ export const gatewayConnectivity = async (installConfig: AgentInstallConfig): Pr
// AWS Region
awsAgentValues.region = await helpers.askAWSRegion();

// S3 bucket
awsAgentValues.cloudFormationConfig.AgentResourcesBucket = (await askInput({
msg: AWSPrompts.S3_BUCKET,
validate: validateRegex(helpers.AWSRegexPatterns.AWS_REGEXP, InvalidMsg.S3_BUCKET),
})) as string;

// APIGWCWRoleSetup
awsAgentValues.cloudFormationConfig.APIGWCWRoleSetup = await askToCreateRoleSetup();

// APIGWTrafficLogGroupName
const apiGWTrafficLogGroupName = (await askInput({
msg: AWSPrompts.APIGW_LOG_GROUP,
defaultValue: awsAgentValues.cloudFormationConfig.APIGWTrafficLogGroupName,
validate: validateRegex(helpers.AWSRegexPatterns.AWS_REGEXP_LOG_GROUP_NAME, InvalidMsg.LOG_GROUP),
})) as string;
awsAgentValues.logGroup = apiGWTrafficLogGroupName;
awsAgentValues.cloudFormationConfig.APIGWTrafficLogGroupName = apiGWTrafficLogGroupName;

// StageTagName
const stageTagName = (await askInput({
msg: AWSPrompts.STAGE_TAG_NAME,
validate: validateInputLength(STAGE_TAG_NAME_LENGTH, 'Maximum length of \'stage tag name\' is 127'),
})) as string;
awsAgentValues.stageTagName = stageTagName;

// FullTransactionLogging
const fullTransactionLogging = ((await askList({
msg: AWSPrompts.FULL_TRANSACTION_LOGGING,
choices: YesNoChoices,
// Determine gateway mode early to skip irrelevant API GW prompts
awsAgentValues.agentCoreGatewayMode = (await askList({
msg: AWSPrompts.AGENT_CORE_GATEWAY_MODE,
default: YesNo.No,
})) === YesNo.Yes);

awsAgentValues.fullTransactionLogging = fullTransactionLogging;

// set agent versions
awsAgentValues.cloudFormationConfig.DiscoveryAgentVersion = installConfig.daVersion;
awsAgentValues.cloudFormationConfig.TraceabilityAgentVersion = installConfig.taVersion;
choices: YesNoChoices,
})) === YesNo.Yes;

if (awsAgentValues.agentCoreGatewayMode) {
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;
}

// Configure appropriate Gateway type
switch (awsAgentValues.cloudFormationConfig.DeploymentType) {
case DeploymentTypes.ECS_FARGATE: {
awsAgentValues = await configureECSDeployment(awsAgentValues);
break;
awsAgentValues.cognitoUserPoolIDs = cognitoUserPoolIDs;
if (installConfig.switches.isTaEnabled) {
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.cloudTrailEnabled = (await askList({
msg: AWSPrompts.AGENTCORE_CLOUDTRAILENABLED,
default: YesNo.No,
choices: YesNoChoices,
})) === YesNo.Yes;

awsAgentValues.agentCore.cloudTrailBucket = (await askInput({
msg: AWSPrompts.AGENTCORE_CLOUDTRAILBUCKET,
defaultValue: awsAgentValues.agentCore.cloudTrailBucket !== '' ? awsAgentValues.agentCore.cloudTrailBucket : undefined,
allowEmptyInput: false,
})) as string;
}
case DeploymentTypes.EC2: {
awsAgentValues = await configureEC2Deployment(awsAgentValues, installConfig.log);
break;
} else {
// API Gateway mode — collect all API GW-specific configuration
awsAgentValues.cloudFormationConfig.AgentResourcesBucket = (await askInput({
msg: AWSPrompts.S3_BUCKET,
validate: validateRegex(helpers.AWSRegexPatterns.AWS_REGEXP, InvalidMsg.S3_BUCKET),
})) as string;

awsAgentValues.cloudFormationConfig.APIGWCWRoleSetup = await askToCreateRoleSetup();

const apiGWTrafficLogGroupName = (await askInput({
msg: AWSPrompts.APIGW_LOG_GROUP,
defaultValue: awsAgentValues.cloudFormationConfig.APIGWTrafficLogGroupName,
validate: validateRegex(helpers.AWSRegexPatterns.AWS_REGEXP_LOG_GROUP_NAME, InvalidMsg.LOG_GROUP),
})) as string;
awsAgentValues.logGroup = apiGWTrafficLogGroupName;
awsAgentValues.cloudFormationConfig.APIGWTrafficLogGroupName = apiGWTrafficLogGroupName;

awsAgentValues.stageTagName = (await askInput({
msg: AWSPrompts.STAGE_TAG_NAME,
validate: validateInputLength(STAGE_TAG_NAME_LENGTH, 'Maximum length of \'stage tag name\' is 127'),
})) as string;

awsAgentValues.fullTransactionLogging = ((await askList({
msg: AWSPrompts.FULL_TRANSACTION_LOGGING,
choices: YesNoChoices,
default: YesNo.No,
})) === YesNo.Yes);

awsAgentValues.cloudFormationConfig.DiscoveryAgentVersion = installConfig.daVersion;
awsAgentValues.cloudFormationConfig.TraceabilityAgentVersion = installConfig.taVersion;

switch (awsAgentValues.cloudFormationConfig.DeploymentType) {
case DeploymentTypes.ECS_FARGATE: {
awsAgentValues = await configureECSDeployment(awsAgentValues);
break;
}
case DeploymentTypes.EC2: {
awsAgentValues = await configureEC2Deployment(awsAgentValues, installConfig.log);
break;
}
}
}

// DiscoveryAgentLogGroupName
awsAgentValues.cloudFormationConfig.DiscoveryAgentLogGroupName = (await askInput({
msg: AWSPrompts.DA_LOG_GROUP,
defaultValue: awsAgentValues.cloudFormationConfig.DiscoveryAgentLogGroupName,
validate: validateRegex(helpers.AWSRegexPatterns.AWS_REGEXP_LOG_GROUP_NAME, InvalidMsg.LOG_GROUP),
})) as string;

// TraceabilityAgentLogGroupName
awsAgentValues.cloudFormationConfig.TraceabilityAgentLogGroupName = (await askInput({
msg: AWSPrompts.TA_LOG_GROUP,
defaultValue: awsAgentValues.cloudFormationConfig.TraceabilityAgentLogGroupName,
validate: validateRegex(helpers.AWSRegexPatterns.AWS_REGEXP_LOG_GROUP_NAME, InvalidMsg.LOG_GROUP),
})) as string;
awsAgentValues.cloudFormationConfig.DiscoveryAgentLogGroupName = (await askInput({
msg: AWSPrompts.DA_LOG_GROUP,
defaultValue: awsAgentValues.cloudFormationConfig.DiscoveryAgentLogGroupName,
validate: validateRegex(helpers.AWSRegexPatterns.AWS_REGEXP_LOG_GROUP_NAME, InvalidMsg.LOG_GROUP),
})) as string;

awsAgentValues.cloudFormationConfig.TraceabilityAgentLogGroupName = (await askInput({
msg: AWSPrompts.TA_LOG_GROUP,
defaultValue: awsAgentValues.cloudFormationConfig.TraceabilityAgentLogGroupName,
validate: validateRegex(helpers.AWSRegexPatterns.AWS_REGEXP_LOG_GROUP_NAME, InvalidMsg.LOG_GROUP),
})) as string;
}

return awsAgentValues;
};
Expand Down
Loading
Loading