Bedrock Haiku now classifies marketing/promotional emails as MARKETING and they are filtered out before saving or alerting. This replaces Gmail label-based filtering for more accurate classification. Also: enable Fargate listener (desiredCount=1), update README for CDK, update Notion AWS Architecture Map and Slack Apps Inventory.
125 lines
4.1 KiB
TypeScript
125 lines
4.1 KiB
TypeScript
import { Construct } from 'constructs';
|
|
import * as cdk from 'aws-cdk-lib';
|
|
import * as ec2 from 'aws-cdk-lib/aws-ec2';
|
|
import * as ecs from 'aws-cdk-lib/aws-ecs';
|
|
import * as ecr from 'aws-cdk-lib/aws-ecr';
|
|
import * as logs from 'aws-cdk-lib/aws-logs';
|
|
import * as iam from 'aws-cdk-lib/aws-iam';
|
|
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
|
|
import * as path from 'path';
|
|
|
|
export interface SocketModeProps {
|
|
table: dynamodb.ITable;
|
|
}
|
|
|
|
export class SocketModeConstruct extends Construct {
|
|
constructor(scope: Construct, id: string, props: SocketModeProps) {
|
|
super(scope, id);
|
|
|
|
const account = cdk.Stack.of(this).account;
|
|
const region = cdk.Stack.of(this).region;
|
|
|
|
// ── VPC ────────────────────────────────────────────────────
|
|
|
|
const vpc = new ec2.Vpc(this, 'Vpc', {
|
|
vpcName: 'exec-aide',
|
|
ipAddresses: ec2.IpAddresses.cidr('10.30.0.0/16'),
|
|
maxAzs: 1,
|
|
natGateways: 0,
|
|
subnetConfiguration: [
|
|
{
|
|
cidrMask: 24,
|
|
name: 'exec-aide-listener',
|
|
subnetType: ec2.SubnetType.PUBLIC,
|
|
},
|
|
],
|
|
});
|
|
|
|
const sg = new ec2.SecurityGroup(this, 'ListenerSG', {
|
|
vpc,
|
|
description: 'exec-aide listener - outbound only',
|
|
allowAllOutbound: true,
|
|
});
|
|
|
|
// ── ECR ────────────────────────────────────────────────────
|
|
|
|
new ecr.Repository(this, 'ListenerRepo', {
|
|
repositoryName: 'exec-aide-listener',
|
|
imageScanOnPush: true,
|
|
lifecycleRules: [
|
|
{
|
|
maxImageCount: 5,
|
|
description: 'Keep last 5 images',
|
|
},
|
|
],
|
|
removalPolicy: cdk.RemovalPolicy.RETAIN,
|
|
});
|
|
|
|
// ── ECS Cluster + Task Definition ──────────────────────────
|
|
|
|
const cluster = new ecs.Cluster(this, 'Cluster', {
|
|
clusterName: 'exec-aide',
|
|
vpc,
|
|
});
|
|
|
|
const taskDef = new ecs.FargateTaskDefinition(this, 'TaskDef', {
|
|
family: 'exec-aide-listener',
|
|
cpu: 256,
|
|
memoryLimitMiB: 512,
|
|
runtimePlatform: {
|
|
cpuArchitecture: ecs.CpuArchitecture.ARM64,
|
|
operatingSystemFamily: ecs.OperatingSystemFamily.LINUX,
|
|
},
|
|
});
|
|
|
|
taskDef.addContainer('listener', {
|
|
image: ecs.ContainerImage.fromAsset(
|
|
path.join(__dirname, '../../listener'),
|
|
),
|
|
essential: true,
|
|
environment: {
|
|
TABLE_NAME: props.table.tableName,
|
|
SECRET_SLACK: 'exec-aide/slack-credentials',
|
|
SSM_PREFIX: '/exec-aide',
|
|
},
|
|
logging: ecs.LogDrivers.awsLogs({
|
|
streamPrefix: 'listener',
|
|
logGroup: new logs.LogGroup(this, 'ListenerLogGroup', {
|
|
logGroupName: '/ecs/exec-aide-listener',
|
|
retention: logs.RetentionDays.TWO_MONTHS,
|
|
}),
|
|
}),
|
|
});
|
|
|
|
// ── Task role IAM ──────────────────────────────────────────
|
|
|
|
props.table.grantReadWriteData(taskDef.taskRole);
|
|
|
|
taskDef.taskRole.addToPrincipalPolicy(new iam.PolicyStatement({
|
|
actions: ['secretsmanager:GetSecretValue'],
|
|
resources: [
|
|
`arn:aws:secretsmanager:${region}:${account}:secret:exec-aide/slack-credentials-*`,
|
|
],
|
|
}));
|
|
|
|
taskDef.taskRole.addToPrincipalPolicy(new iam.PolicyStatement({
|
|
actions: ['ssm:GetParametersByPath', 'ssm:GetParameter'],
|
|
resources: [
|
|
`arn:aws:ssm:${region}:${account}:parameter/exec-aide`,
|
|
`arn:aws:ssm:${region}:${account}:parameter/exec-aide/*`,
|
|
],
|
|
}));
|
|
|
|
// ── Fargate Service ────────────────────────────────────────
|
|
|
|
new ecs.FargateService(this, 'Service', {
|
|
serviceName: 'exec-aide-listener',
|
|
cluster,
|
|
taskDefinition: taskDef,
|
|
desiredCount: 1,
|
|
assignPublicIp: true,
|
|
securityGroups: [sg],
|
|
vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC },
|
|
});
|
|
}
|
|
}
|