Skip to content

Commit c13ef40

Browse files
committed
Feat: dynamic filter regex
1 parent 2dc8e74 commit c13ef40

File tree

5 files changed

+44
-7
lines changed

5 files changed

+44
-7
lines changed

README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
An AWS Lambda function that is designed to filter logs to remove sensitive data, mask any sensitive information, and then post the resulting data to a separate log group.
2+
3+
4+
## Provision the Lambda using Terraform
5+
```
6+
module "log-filter-mask" {
7+
source = "github.com/mhd999/aws-lambda-log-filter-mask?ref=v0.0.3"
8+
9+
source_log_group = "/aws/appsync/apis/abc"
10+
destination_log_group = "aws/sensitive/data"
11+
sensitive_words = "password|\"password\"|new_password|\"new_password\""
12+
placeholder = "*****"
13+
filter_pattern = "?password ?new_password"
14+
}
15+
```
16+
## Environment variables
17+
18+
| Variable | Description | Example |
19+
| --------------------- | ------------|---------------------------------------------|
20+
| DESTINATION_LOG_GROUP | Name of AWS cloudwatch destination log group | aws/sensitive/data
21+
| SOURCE_LOG_GROUP | Name of AWS cloudwatch source log group | aws/appsync/apis/abc
22+
| SENSITIVE_WORDS | The sensitive words in logs to mask | password|"password"|new_password|"new_password"
23+
| PLACEHOLDER | The value to replace the value of the senstive words with | "*****"

handler.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18451,9 +18451,10 @@ const zlib_1 = __webpack_require__(796);
1845118451
const crypto_1 = __webpack_require__(113);
1845218452
const client_cloudwatch_logs_1 = __webpack_require__(316);
1845318453
exports.handler = async (event) => {
18454-
const placeholder = process.env.PLAEHOLDER || "*****";
18454+
const placeholder = process.env.PLACEHOLDER || "*****";
1845518455
const destinationLogGroupName = process.env.DESTINATION_LOG_GROUP;
1845618456
const sourceLogGroupName = process.env.SOURCE_LOG_GROUP;
18457+
const sensitiveWords = process.env.SENSITIVE_WORDS;
1845718458
const payload = await Buffer.from(event.awslogs.data, 'base64');
1845818459
function getLogRecord() {
1845918460
return new Promise(function (resolve, reject) {
@@ -18476,7 +18477,7 @@ exports.handler = async (event) => {
1847618477
return new Promise(function (resolve, reject) {
1847718478
const logs = logEvents.map(logEvent => {
1847818479
const logMessage = logEvent.message;
18479-
const pattern = /("password"|password|new_password|"new_password")\s*:\s*"([^"]*)/g;
18480+
let pattern = new RegExp(`(${sensitiveWords})\s*:\s*"([^"]*)`, 'g');
1848018481
const maskedMessage = logMessage?.replace(pattern, (match, key, value) => {
1848118482
return `"${key}":"${placeholder}"`;
1848218483
});

main.tf

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ variable "aws_region" {
33
}
44
variable "source_log_group" {}
55
variable "destination_log_group" {}
6+
variable "sensitive_words" {}
7+
variable "placeholder" {}
68
variable "filter_pattern" {
79
default = ""
810
}
@@ -27,6 +29,14 @@ resource "aws_cloudwatch_log_group" "destination_log_group" {
2729
retention_in_days = 60
2830
}
2931

32+
resource "random_string" "lambda_postfix_generator" {
33+
length = 16
34+
upper = true
35+
lower = true
36+
numeric = true
37+
special = false
38+
}
39+
3040
resource "aws_lambda_function" "filter_and_mask_logs" {
3141
filename = "filter-and-mask-logs.zip"
3242
function_name = "filter-and-mask-logs"
@@ -39,6 +49,8 @@ resource "aws_lambda_function" "filter_and_mask_logs" {
3949
SOURCE_LOG_GROUP = data.aws_cloudwatch_log_group.source_log_group.name
4050
# FILTER_PATTERN = "password"
4151
DESTINATION_LOG_GROUP = aws_cloudwatch_log_group.destination_log_group.name
52+
SENSITIVE_WORDS = var.sensitive_words
53+
PLACEHOLDER = var.placeholder
4254
}
4355
}
4456

src/index.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import { CloudWatchLogsClient, PutLogEventsCommand, CreateLogStreamCommand, Dele
44
import { MetadataBearer } from "@aws-sdk/types";
55

66
exports.handler = async (event) => {
7-
const placeholder = process.env.PLAEHOLDER || "*****";
7+
const placeholder = process.env.PLACEHOLDER || "*****";
88
const destinationLogGroupName = process.env.DESTINATION_LOG_GROUP;
99
const sourceLogGroupName = process.env.SOURCE_LOG_GROUP;
10-
// TODO: get sensitive phrases from env var
10+
const sensitiveWords = process.env.SENSITIVE_WORDS;
1111

1212
const payload = await Buffer.from(event.awslogs.data, 'base64');
1313

@@ -42,7 +42,7 @@ exports.handler = async (event) => {
4242
return new Promise(function (resolve, reject) {
4343
const logs = logEvents.map(logEvent => {
4444
const logMessage = logEvent.message;
45-
const pattern = /("password"|password|new_password|"new_password")\s*:\s*"([^"]*)/g;
45+
let pattern = new RegExp(`(${sensitiveWords})\s*:\s*"([^"]*)`, 'g');
4646

4747
const maskedMessage = logMessage?.replace(pattern, (match, key, value) => {
4848
return `"${key}":"${placeholder}"`;
@@ -60,7 +60,6 @@ exports.handler = async (event) => {
6060
}
6161

6262
const maskedLogEvents: InputLogEvent[] = await maskEvent();
63-
6463
const logStreamName = randomBytes(20).toString('hex');
6564

6665
// create log stream

template.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,6 @@ Resources:
1313
Environment:
1414
Variables:
1515
DESTINATION_LOG_GROUP:
16-
SOURCE_LOG_GROUP:
16+
SOURCE_LOG_GROUP:
17+
SENSITIVE_WORDS:
18+
PLACEHOLDER:

0 commit comments

Comments
 (0)