From 01e424842e46a1912ebc31e85340f12655046bb5 Mon Sep 17 00:00:00 2001 From: Ayoub Umoru Date: Sun, 1 Dec 2024 17:33:07 +0100 Subject: [PATCH 1/3] feat: improved cost saving - pay per request --- src/components/chatgpt-waf-log-evaluation.ts | 118 +++++++++++-------- 1 file changed, 66 insertions(+), 52 deletions(-) diff --git a/src/components/chatgpt-waf-log-evaluation.ts b/src/components/chatgpt-waf-log-evaluation.ts index 261507c..4398885 100644 --- a/src/components/chatgpt-waf-log-evaluation.ts +++ b/src/components/chatgpt-waf-log-evaluation.ts @@ -1,11 +1,11 @@ -import * as path from 'path'; -import * as cdk from 'aws-cdk-lib'; -import * as dynamodb from 'aws-cdk-lib/aws-dynamodb'; -import { Rule, Schedule } from 'aws-cdk-lib/aws-events'; -import { LambdaFunction } from 'aws-cdk-lib/aws-events-targets'; -import * as iam from 'aws-cdk-lib/aws-iam'; -import * as lambda from 'aws-cdk-lib/aws-lambda'; -import { Construct } from 'constructs'; +import * as path from "path"; +import * as cdk from "aws-cdk-lib"; +import * as dynamodb from "aws-cdk-lib/aws-dynamodb"; +import { Rule, Schedule } from "aws-cdk-lib/aws-events"; +import { LambdaFunction } from "aws-cdk-lib/aws-events-targets"; +import * as iam from "aws-cdk-lib/aws-iam"; +import * as lambda from "aws-cdk-lib/aws-lambda"; +import { Construct } from "constructs"; export interface IChatGPTWafLogEvaluationProps { rule_scope: string; @@ -20,87 +20,101 @@ export class ChatGPTWafLogEvaluation extends Construct { prefix: string; log_group: string; chatgpt_log_check_intervall_minutes: number; - constructor(scope: Construct, id: string, props: IChatGPTWafLogEvaluationProps) { + constructor( + scope: Construct, + id: string, + props: IChatGPTWafLogEvaluationProps + ) { super(scope, id); this.rule_scope = props.rule_scope; - this.prefix = 'alpha'; + this.prefix = "alpha"; this.log_group = props.log_group; - this.chatgpt_log_check_intervall_minutes = props.chatgpt_log_check_intervall_minutes; + this.chatgpt_log_check_intervall_minutes = + props.chatgpt_log_check_intervall_minutes; //Define DynamoDB - const table = new dynamodb.Table(this, 'waf-autoblock-db', { + const table = new dynamodb.Table(this, "waf-autoblock-db", { tableName: `${this.prefix}-waf_ip_protection`, - partitionKey: { name: 'ip', type: dynamodb.AttributeType.STRING }, - sortKey: { name: 'product', type: dynamodb.AttributeType.STRING }, + partitionKey: { name: "ip", type: dynamodb.AttributeType.STRING }, + sortKey: { name: "product", type: dynamodb.AttributeType.STRING }, + billingMode: dynamodb.BillingMode.PAY_PER_REQUEST, }); this.table_name = table.tableName; const waf_log_checker_lambda_role = new iam.Role( this, - 'waf-log-checker-lambda-role', + "waf-log-checker-lambda-role", { - assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'), - description: 'Lambda role that checks WAFv2 logs, talks to ChatGPT and stores results to DynamoDB.', + assumedBy: new iam.ServicePrincipal("lambda.amazonaws.com"), + description: + "Lambda role that checks WAFv2 logs, talks to ChatGPT and stores results to DynamoDB.", managedPolicies: [ cdk.aws_iam.ManagedPolicy.fromAwsManagedPolicyName( - 'service-role/AWSLambdaBasicExecutionRole', + "service-role/AWSLambdaBasicExecutionRole" ), ], - }, + } ); - const chatGPTAPISecret = new cdk.aws_secretsmanager.Secret( this, - 'waf-chatgpt-secret', + "waf-chatgpt-secret", { - description: 'Secret for ChatGPT API', + description: "Secret for ChatGPT API", secretName: `${this.prefix}-chatgpt-api-key`, - }, + } ); waf_log_checker_lambda_role.addToPolicy( new iam.PolicyStatement({ - resources: ['*'], - actions: ['logs:*'], - }), + resources: ["*"], + actions: ["logs:*"], + }) ); if (props.notification_sns_arn) { waf_log_checker_lambda_role.addToPolicy( new iam.PolicyStatement({ resources: [props.notification_sns_arn], - actions: ['sns:Publish'], - }), + actions: ["sns:Publish"], + }) ); } - const waf_log_analysis_lambda = new lambda.Function(this, 'waf-log-check-lambda', { - runtime: lambda.Runtime.PYTHON_3_10, - code: lambda.Code.fromAsset(path.join(__dirname, '..', '..', 'lambda', 'log_analytics.zip')), - handler: 'index.handler', - role: waf_log_checker_lambda_role, - memorySize: 160, - architecture: lambda.Architecture.ARM_64, - //layers: [lambdaLayer], - description: - 'Reads WAFv2 logs, makes ChatGPT evaluations and stores the results DynamoDB.', - environment: { - PRODUCT: 'ChatGPTBadIPs', - DB_NAME: table.tableName, - SCOPE: this.rule_scope, - LOG_GROUP: this.log_group, - SNS_ARN: props.notification_sns_arn, - SECRET_ID: chatGPTAPISecret.secretName, - LAST_LOG_MINUTES: this.chatgpt_log_check_intervall_minutes.toString(), - }, - timeout: cdk.Duration.minutes(6), - }); + const waf_log_analysis_lambda = new lambda.Function( + this, + "waf-log-check-lambda", + { + runtime: lambda.Runtime.PYTHON_3_10, + code: lambda.Code.fromAsset( + path.join(__dirname, "..", "..", "lambda", "log_analytics.zip") + ), + handler: "index.handler", + role: waf_log_checker_lambda_role, + memorySize: 160, + architecture: lambda.Architecture.ARM_64, + //layers: [lambdaLayer], + description: + "Reads WAFv2 logs, makes ChatGPT evaluations and stores the results DynamoDB.", + environment: { + PRODUCT: "ChatGPTBadIPs", + DB_NAME: table.tableName, + SCOPE: this.rule_scope, + LOG_GROUP: this.log_group, + SNS_ARN: props.notification_sns_arn, + SECRET_ID: chatGPTAPISecret.secretName, + LAST_LOG_MINUTES: this.chatgpt_log_check_intervall_minutes.toString(), + }, + timeout: cdk.Duration.minutes(6), + } + ); chatGPTAPISecret.grantRead(waf_log_analysis_lambda); table.grantWriteData(waf_log_analysis_lambda); table.grantReadData(waf_log_analysis_lambda); - new Rule(this, 'waf-chatgpt-analysis-rule', { - description: 'Schedule for the ChatGPT log analysis.', - schedule: Schedule.rate(cdk.Duration.minutes(this.chatgpt_log_check_intervall_minutes)), + new Rule(this, "waf-chatgpt-analysis-rule", { + description: "Schedule for the ChatGPT log analysis.", + schedule: Schedule.rate( + cdk.Duration.minutes(this.chatgpt_log_check_intervall_minutes) + ), targets: [new LambdaFunction(waf_log_analysis_lambda)], }); } From 6be26eebe217b415710f6fc04125e65ed23b175b Mon Sep 17 00:00:00 2001 From: Ayoub Umoru Date: Sun, 1 Dec 2024 17:54:27 +0100 Subject: [PATCH 2/3] fix: fix projen issue --- .projenrc.ts | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/.projenrc.ts b/.projenrc.ts index ff258e0..a34783b 100644 --- a/.projenrc.ts +++ b/.projenrc.ts @@ -1,26 +1,37 @@ -import { awscdk } from 'projen'; +import { awscdk } from "projen"; +project.github?.actions.set( + "actions/upload-artifact", + "actions/upload-artifact@v4.3.6" +); -const PROJECT_NAME = 'cdk-aws-wafv2-geofence-lib'; +const PROJECT_NAME = "cdk-aws-wafv2-geofence-lib"; const PROJECT_DESCRIPTION = - 'The cdk-aws-wafv2-geofence-lib is an AWS CDK construct library that adds a AWS WAFv2 with GeoBlocking and AWS Managed Rules for AppSync, API Gateway or an ALB.'; + "The cdk-aws-wafv2-geofence-lib is an AWS CDK construct library that adds a AWS WAFv2 with GeoBlocking and AWS Managed Rules for AppSync, API Gateway or an ALB."; const project = new awscdk.AwsCdkConstructLibrary({ - author: 'ZeroDotFive', - authorAddress: 'ayoub.umoru@zerodotfive.com', - cdkVersion: '2.127.0', + author: "ZeroDotFive", + authorAddress: "ayoub.umoru@zerodotfive.com", + cdkVersion: "2.127.0", majorVersion: 1, - defaultReleaseBranch: 'main', + defaultReleaseBranch: "main", authorOrganization: true, - jsiiVersion: '~5.3.0', + jsiiVersion: "~5.3.0", name: PROJECT_NAME, projenrcTs: true, - repositoryUrl: 'https://github.com/ZDF-OSS/cdk-aws-wafv2-geofence-lib.git', - homepage: 'https://zerodotfive.com', + repositoryUrl: "https://github.com/ZDF-OSS/cdk-aws-wafv2-geofence-lib.git", + homepage: "https://zerodotfive.com", description: PROJECT_DESCRIPTION, - keywords: ['aws', 'cdk', 'awscdk', 'aws-cdk', 'wafv2', 'aws-waf', 'aws-wafv2', 'geoblock'], - gitignore: [ - 'cdk.out/', + keywords: [ + "aws", + "cdk", + "awscdk", + "aws-cdk", + "wafv2", + "aws-waf", + "aws-wafv2", + "geoblock", ], - bundledDeps: ['openai'], + gitignore: ["cdk.out/"], + bundledDeps: ["openai"], }); project.synth(); From df1c2ed424128ef47a76830057409f1546f5b33b Mon Sep 17 00:00:00 2001 From: Ayoub Umoru Date: Sun, 1 Dec 2024 17:55:56 +0100 Subject: [PATCH 3/3] chroe: misaligned change --- .projenrc.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.projenrc.ts b/.projenrc.ts index a34783b..c9505ea 100644 --- a/.projenrc.ts +++ b/.projenrc.ts @@ -1,8 +1,4 @@ import { awscdk } from "projen"; -project.github?.actions.set( - "actions/upload-artifact", - "actions/upload-artifact@v4.3.6" -); const PROJECT_NAME = "cdk-aws-wafv2-geofence-lib"; const PROJECT_DESCRIPTION = @@ -34,4 +30,10 @@ const project = new awscdk.AwsCdkConstructLibrary({ gitignore: ["cdk.out/"], bundledDeps: ["openai"], }); + +project.github?.actions.set( + "actions/upload-artifact", + "actions/upload-artifact@v4.3.6" +); + project.synth();