service: esdp-api app: esdp-api-app frameworkVersion: '4' package: patterns: - drizzle/** stages: prod: # Enables observability in the prod stage observability: true # Sepcify parameter values to be used in the prod stage params: es_endpoint: https://insurtechtoolkit.com domain: es.imex.online es_user: Imex2 es_password: Patrick db_name: esdpprod beta: # Enables observability in the prod stage observability: false # Sepcify parameter values to be used in the prod stage params: es_endpoint: https://4284-79073.el-alt.com domain: beta.es.imex.online es_user: Imex2 es_password: Patrick db_name: esdpbeta alpha: # Enables observability in the prod stage observability: false # Sepcify parameter values to be used in the prod stage params: es_endpoint: https://4284-79287.el-alt.com domain: alpha.es.imex.online es_user: Imex2 es_password: Patrick db_name: esdpalpha dev: # Enables observability in the prod stage observability: false # Sepcify parameter values to be used in the prod stage params: es_endpoint: https://4284-79287.el-alt.com domain: dev.es.imex.online es_user: Imex2 es_password: Patrick db_name: esdpdev # params: # dev: # domain: dev.es.imex.online # alpha: # domain: alpha.es.imex.online # beta: # domain: beta.es.imex.online # prod: # domain: es.imex.online provider: name: aws runtime: nodejs22.x region: ca-central-1 domain: ${param:domain} httpApi: # This creates a cheaper, faster "HTTP API" Gateway cors: true # Automatically configures CORS build: esbuild: bundle: true minify: false sourcemap: true exclude: - '@aws-sdk/*' target: node22 platform: node functions: vehicleType: handler: src/handlers/vehicleType.handler events: - httpApi: path: /vehicleType method: post scrub: handler: src/handlers/scrub.handler environment: ES_ENDPOINT: ${param:es_endpoint} ES_USER: ${param:es_user} ES_PASSWORD: ${param:es_password} events: - httpApi: path: /scrub method: post emsupload: handler: src/handlers/emsupload.handler environment: ES_ENDPOINT: ${param:es_endpoint} UPLOAD_BUCKET_NAME: ${self:service}-uploads-${sls:stage} iamRoleStatements: - Effect: Allow Action: - s3:PutObject - s3:PutObjectAcl - s3:GetObject Resource: - arn:aws:s3:::${self:service}-uploads-${sls:stage}/* events: - httpApi: path: /emsupload method: post dbMigrate: handler: src/handlers/dbMigrate.handler timeout: 30 memorySize: 512 vpc: securityGroupIds: - Ref: LambdaSecurityGroup subnetIds: - Ref: PrivateSubnetA - Ref: PrivateSubnetB environment: DB_HOST: Fn::GetAtt: - DbProxy - Endpoint DB_PORT: 5432 DB_NAME: ${param:db_name} DB_SECRET_ARN: Ref: DbSecret iamRoleStatements: - Effect: Allow Action: - secretsmanager:GetSecretValue Resource: - Ref: DbSecret dbPing: handler: src/handlers/dbPing.handler timeout: 15 memorySize: 256 vpc: securityGroupIds: - Ref: LambdaSecurityGroup subnetIds: - Ref: PrivateSubnetA - Ref: PrivateSubnetB environment: DB_HOST: Fn::GetAtt: - DbProxy - Endpoint DB_PORT: 5432 DB_NAME: ${param:db_name} DB_SECRET_ARN: Ref: DbSecret iamRoleStatements: - Effect: Allow Action: - secretsmanager:GetSecretValue Resource: - Ref: DbSecret resources: Resources: EsdpVpc: Type: AWS::EC2::VPC Properties: CidrBlock: 10.0.0.0/16 EnableDnsSupport: true EnableDnsHostnames: true Tags: - Key: Name Value: ${self:service}-${sls:stage}-vpc InternetGateway: Type: AWS::EC2::InternetGateway Properties: Tags: - Key: Name Value: ${self:service}-${sls:stage}-igw VpcGatewayAttachment: Type: AWS::EC2::VPCGatewayAttachment Properties: VpcId: Ref: EsdpVpc InternetGatewayId: Ref: InternetGateway PublicSubnetA: Type: AWS::EC2::Subnet Properties: VpcId: Ref: EsdpVpc AvailabilityZone: Fn::Select: - 0 - Fn::GetAZs: '' CidrBlock: 10.0.0.0/24 MapPublicIpOnLaunch: true Tags: - Key: Name Value: ${self:service}-${sls:stage}-public-a PublicSubnetB: Type: AWS::EC2::Subnet Properties: VpcId: Ref: EsdpVpc AvailabilityZone: Fn::Select: - 1 - Fn::GetAZs: '' CidrBlock: 10.0.1.0/24 MapPublicIpOnLaunch: true Tags: - Key: Name Value: ${self:service}-${sls:stage}-public-b PrivateSubnetA: Type: AWS::EC2::Subnet Properties: VpcId: Ref: EsdpVpc AvailabilityZone: Fn::Select: - 0 - Fn::GetAZs: '' CidrBlock: 10.0.10.0/24 MapPublicIpOnLaunch: false Tags: - Key: Name Value: ${self:service}-${sls:stage}-private-a PrivateSubnetB: Type: AWS::EC2::Subnet Properties: VpcId: Ref: EsdpVpc AvailabilityZone: Fn::Select: - 1 - Fn::GetAZs: '' CidrBlock: 10.0.11.0/24 MapPublicIpOnLaunch: false Tags: - Key: Name Value: ${self:service}-${sls:stage}-private-b PublicRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: Ref: EsdpVpc Tags: - Key: Name Value: ${self:service}-${sls:stage}-public-rt PublicRoute: Type: AWS::EC2::Route DependsOn: VpcGatewayAttachment Properties: RouteTableId: Ref: PublicRouteTable DestinationCidrBlock: 0.0.0.0/0 GatewayId: Ref: InternetGateway PublicSubnetARouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: Ref: PublicSubnetA RouteTableId: Ref: PublicRouteTable PublicSubnetBRouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: Ref: PublicSubnetB RouteTableId: Ref: PublicRouteTable NatEip: Type: AWS::EC2::EIP Properties: Domain: vpc NatGateway: Type: AWS::EC2::NatGateway Properties: AllocationId: Fn::GetAtt: - NatEip - AllocationId SubnetId: Ref: PublicSubnetA Tags: - Key: Name Value: ${self:service}-${sls:stage}-nat PrivateRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: Ref: EsdpVpc Tags: - Key: Name Value: ${self:service}-${sls:stage}-private-rt PrivateRoute: Type: AWS::EC2::Route Properties: RouteTableId: Ref: PrivateRouteTable DestinationCidrBlock: 0.0.0.0/0 NatGatewayId: Ref: NatGateway PrivateSubnetARouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: Ref: PrivateSubnetA RouteTableId: Ref: PrivateRouteTable PrivateSubnetBRouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: Ref: PrivateSubnetB RouteTableId: Ref: PrivateRouteTable LambdaSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: ${self:service}-${sls:stage} Lambda security group VpcId: Ref: EsdpVpc SecurityGroupEgress: - IpProtocol: -1 CidrIp: 0.0.0.0/0 Tags: - Key: Name Value: ${self:service}-${sls:stage}-lambda-sg ProxySecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: ${self:service}-${sls:stage} RDS proxy security group VpcId: Ref: EsdpVpc SecurityGroupIngress: - IpProtocol: tcp FromPort: 5432 ToPort: 5432 SourceSecurityGroupId: Ref: LambdaSecurityGroup - IpProtocol: tcp FromPort: 5432 ToPort: 5432 CidrIp: 70.36.57.88/32 SecurityGroupEgress: - IpProtocol: -1 CidrIp: 0.0.0.0/0 Tags: - Key: Name Value: ${self:service}-${sls:stage}-proxy-sg RdsSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: ${self:service}-${sls:stage} RDS security group VpcId: Ref: EsdpVpc SecurityGroupIngress: - IpProtocol: tcp FromPort: 5432 ToPort: 5432 SourceSecurityGroupId: Ref: ProxySecurityGroup - IpProtocol: tcp FromPort: 5432 ToPort: 5432 CidrIp: 70.36.57.88/32 Tags: - Key: Name Value: ${self:service}-${sls:stage}-rds-sg DbSubnetGroup: Type: AWS::RDS::DBSubnetGroup Properties: DBSubnetGroupDescription: ${self:service}-${sls:stage} DB subnet group SubnetIds: - Ref: PrivateSubnetA - Ref: PrivateSubnetB - Ref: PublicSubnetA - Ref: PublicSubnetB DbSecret: Type: AWS::SecretsManager::Secret Properties: Description: ${self:service}-${sls:stage} RDS master credentials GenerateSecretString: SecretStringTemplate: '{"username":"esdp_admin"}' GenerateStringKey: password PasswordLength: 32 ExcludeCharacters: '"@/\\' DbProxyRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - rds.amazonaws.com Action: - sts:AssumeRole Policies: - PolicyName: ${self:service}-${sls:stage}-db-proxy-secrets PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - secretsmanager:GetSecretValue Resource: - Ref: DbSecret DbProxy: Type: AWS::RDS::DBProxy Properties: DBProxyName: ${self:service}-${sls:stage}-proxy EngineFamily: POSTGRESQL IdleClientTimeout: 1800 RequireTLS: true RoleArn: Fn::GetAtt: - DbProxyRole - Arn VpcSubnetIds: - Ref: PrivateSubnetA - Ref: PrivateSubnetB VpcSecurityGroupIds: - Ref: ProxySecurityGroup Auth: - AuthScheme: SECRETS SecretArn: Ref: DbSecret IAMAuth: DISABLED DbProxyTargetGroup: Type: AWS::RDS::DBProxyTargetGroup Properties: DBProxyName: Ref: DbProxy TargetGroupName: default DBInstanceIdentifiers: - Ref: PostgresDb ConnectionPoolConfigurationInfo: MaxConnectionsPercent: 75 MaxIdleConnectionsPercent: 50 ConnectionBorrowTimeout: 120 PostgresDb: Type: AWS::RDS::DBInstance DeletionPolicy: Snapshot UpdateReplacePolicy: Snapshot Properties: DBInstanceIdentifier: ${self:service}-${sls:stage}-postgres Engine: postgres # EngineVersion intentionally omitted so AWS uses the current default/latest for RDS Postgres. AutoMinorVersionUpgrade: true DBInstanceClass: db.t4g.micro AllocatedStorage: 20 StorageType: gp3 StorageEncrypted: true PubliclyAccessible: true MultiAZ: false DBName: ${param:db_name} BackupRetentionPeriod: 7 CopyTagsToSnapshot: true DeletionProtection: true VPCSecurityGroups: - Ref: RdsSecurityGroup DBSubnetGroupName: Ref: DbSubnetGroup MasterUsername: Fn::Sub: '{{resolve:secretsmanager:${DbSecret}::username}}' MasterUserPassword: Fn::Sub: '{{resolve:secretsmanager:${DbSecret}::password}}' UploadBucket: Type: AWS::S3::Bucket Properties: BucketName: ${self:service}-uploads-${sls:stage} CorsConfiguration: CorsRules: - AllowedOrigins: - '*' AllowedMethods: - PUT - POST AllowedHeaders: - '*' Outputs: DbEndpointAddress: Value: Fn::GetAtt: - PostgresDb - Endpoint.Address DbEndpointPort: Value: Fn::GetAtt: - PostgresDb - Endpoint.Port DbSecretArn: Value: Ref: DbSecret DbProxyEndpoint: Value: Fn::GetAtt: - DbProxy - Endpoint