From 0e07fc3305d382a15909dfe0d066ff33e8f789db Mon Sep 17 00:00:00 2001 From: prajwalakhuj Date: Wed, 13 Sep 2023 17:29:38 +0530 Subject: [PATCH 1/5] enabled basic alerts and slack integration --- README.md | 57 +++++++++++----- examples/complete/main.tf | 46 +++++++------ lambda/README.md | 60 +++++++++++++++++ lambda/data.tf | 32 +++++++++ lambda/iam.tf | 10 +++ lambda/main.tf | 26 ++++++++ lambda/outputs.tf | 19 ++++++ lambda/sns_slack.py | 51 ++++++++++++++ lambda/sns_slack.zip | Bin 0 -> 3010 bytes lambda/variables.tf | 57 ++++++++++++++++ main.tf | 136 ++++++++++++++++++++++++++++++++++++++ variables.tf | 55 +++++++++++++++ 12 files changed, 513 insertions(+), 36 deletions(-) create mode 100644 lambda/README.md create mode 100644 lambda/data.tf create mode 100644 lambda/iam.tf create mode 100644 lambda/main.tf create mode 100644 lambda/outputs.tf create mode 100644 lambda/sns_slack.py create mode 100644 lambda/sns_slack.zip create mode 100644 lambda/variables.tf diff --git a/README.md b/README.md index 37f3edc..65c03ac 100644 --- a/README.md +++ b/README.md @@ -31,22 +31,28 @@ module "redis" { environment = "production" name = "redis" family = "redis6.x" - vpc_id = "vpc-06eb7eskaf" - subnets = ["subnet-0bfa3eskaf","subnet-0140bskaf"] - node_type = "cache.t3.small" - kms_key_arn = "arn:aws:kms:us-east-2:222222222222:key/kms_key_arn" - num_cache_nodes = 2 - engine_version = "6.x" - multi_az_enabled = false - availability_zones = 2 - automatic_failover_enabled = true - snapshot_retention_limit = 7 - at_rest_encryption_enabled = true - transit_encryption_enabled = false - notification_topic_arn = null - allowed_security_groups = [sg-0132a18skaf] - snapshot_window = "07:00-08:00" - maintenance_window = "sun:09:00-sun:10:00" + vpc_id = "vpc-06eb7eskaf" + subnets = ["subnet-0bfa3eskaf","subnet-0140bskaf"] + node_type = "cache.t3.small" + kms_key_arn = "arn:aws:kms:us-east-2:222222222222:key/kms_key_arn" + num_cache_nodes = 2 + engine_version = "6.x" + multi_az_enabled = false + availability_zones = 2 + automatic_failover_enabled = true + snapshot_retention_limit = 7 + at_rest_encryption_enabled = true + transit_encryption_enabled = false + notification_topic_arn = null + allowed_security_groups = [sg-0132a18skaf] + snapshot_window = "07:00-08:00" + maintenance_window = "sun:09:00-sun:10:00" + cloudwatch_metric_alarms_enabled = true # For enabling basic alerting + alarm_cpu_threshold_percent = 70 + alarm_memory_threshold_bytes = "10000000" # in bytes + slack_username = "john" + slack_channel = "redis-alerts" + slack_webhook_url = "https://hooks.slack.com/services/xxxxxxxxx" } ``` @@ -79,6 +85,7 @@ Security scanning is graciously provided by Prowler. Proowler is the leading ful | Name | Version | |------|---------| +| [archive](#provider\_archive) | n/a | | [aws](#provider\_aws) | >= 4.23 | | [random](#provider\_random) | >= 3.0.0 | @@ -86,30 +93,44 @@ Security scanning is graciously provided by Prowler. Proowler is the leading ful | Name | Source | Version | |------|--------|---------| +| [cw\_sns\_slack](#module\_cw\_sns\_slack) | ./lambda | n/a | | [security\_group\_redis](#module\_security\_group\_redis) | terraform-aws-modules/security-group/aws | 4.13.0 | ## Resources | Name | Type | |------|------| +| [aws_cloudwatch_metric_alarm.cache_cpu](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_metric_alarm) | resource | +| [aws_cloudwatch_metric_alarm.cache_memory](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_metric_alarm) | resource | | [aws_elasticache_parameter_group.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/elasticache_parameter_group) | resource | | [aws_elasticache_replication_group.redis](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/elasticache_replication_group) | resource | | [aws_elasticache_subnet_group.elasticache](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/elasticache_subnet_group) | resource | +| [aws_kms_ciphertext.slack_url](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_ciphertext) | resource | +| [aws_kms_key.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | +| [aws_lambda_permission.sns_lambda_slack_invoke](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource | | [aws_secretsmanager_secret.secret_redis](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) | resource | | [aws_security_group_rule.cidr_ingress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | | [aws_security_group_rule.default_ingress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_sns_topic.slack_topic](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic) | resource | +| [aws_sns_topic_subscription.slack-endpoint](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_subscription) | resource | | [random_password.password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource | +| [archive_file.lambdazip](https://registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/file) | data source | | [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [alarm\_actions](#input\_alarm\_actions) | Alarm action list | `list(string)` | `[]` | no | +| [alarm\_cpu\_threshold\_percent](#input\_alarm\_cpu\_threshold\_percent) | CPU threshold alarm level | `number` | `75` | no | +| [alarm\_memory\_threshold\_bytes](#input\_alarm\_memory\_threshold\_bytes) | Ram threshold alarm level in bytes | `number` | `10000000` | no | | [allowed\_cidr\_blocks](#input\_allowed\_cidr\_blocks) | A list of CIDR blocks which are allowed to access the database | `list(any)` | `[]` | no | | [allowed\_security\_groups](#input\_allowed\_security\_groups) | A list of Security Group ID's to allow access to | `list(any)` | `[]` | no | | [at\_rest\_encryption\_enabled](#input\_at\_rest\_encryption\_enabled) | (Optional) Whether to enable encryption at rest | `bool` | `true` | no | | [automatic\_failover\_enabled](#input\_automatic\_failover\_enabled) | Enable automatic failover | `bool` | `true` | no | | [availability\_zones](#input\_availability\_zones) | The no. of AZs | `string` | `2` | no | +| [cloudwatch\_metric\_alarms\_enabled](#input\_cloudwatch\_metric\_alarms\_enabled) | Boolean flag to enable/disable CloudWatch metrics alarms | `bool` | `false` | no | +| [cw\_sns\_topic\_arn](#input\_cw\_sns\_topic\_arn) | The username to use when sending notifications to Slack. | `string` | `""` | no | | [engine\_log\_destination](#input\_engine\_log\_destination) | The destination for engine logs(eg. Cloudwatch log-group name or kinesis firehose stream name) | `string` | `null` | no | | [engine\_log\_destination\_type](#input\_engine\_log\_destination\_type) | The type of destination for engine logs(eg . cloudwatch-logs or kinesis-firehose) | `string` | `""` | no | | [engine\_log\_format](#input\_engine\_log\_format) | the format for logs eg. json/text | `string` | `"json"` | no | @@ -124,9 +145,13 @@ Security scanning is graciously provided by Prowler. Proowler is the leading ful | [node\_type](#input\_node\_type) | The instance size of the redis cluster | `string` | `"cache.t3.micro"` | no | | [notification\_topic\_arn](#input\_notification\_topic\_arn) | (Optional) ARN of an SNS topic to send ElastiCache notifications | `string` | `null` | no | | [num\_cache\_nodes](#input\_num\_cache\_nodes) | The number of cache nodes | `number` | `1` | no | +| [ok\_actions](#input\_ok\_actions) | The list of actions to execute when this alarm transitions into an OK state from any other state. Each action is specified as an Amazon Resource Number (ARN) | `list(string)` | `[]` | no | | [parameter\_group\_description](#input\_parameter\_group\_description) | Parameter group | `string` | `null` | no | | [port](#input\_port) | The redis port | `number` | `6379` | no | | [recovery\_window\_aws\_secret](#input\_recovery\_window\_aws\_secret) | Number of days that AWS Secrets Manager waits before it can delete the secret. This value can be 0 to force deletion without recovery or range from 7 to 30 days. | `number` | `0` | no | +| [slack\_channel](#input\_slack\_channel) | The Slack channel where notifications will be posted. | `string` | `""` | no | +| [slack\_username](#input\_slack\_username) | The username to use when sending notifications to Slack. | `string` | `""` | no | +| [slack\_webhook\_url](#input\_slack\_webhook\_url) | The Slack Webhook URL where notifications will be sent. | `string` | `""` | no | | [slow\_log\_destination](#input\_slow\_log\_destination) | The destination for slow logs(eg. Cloudwatch log-group name or kinesis firehose stream name.) | `string` | `null` | no | | [slow\_log\_destination\_type](#input\_slow\_log\_destination\_type) | The type of destination for slow logs(eg . cloudwatch-logs or kinesis-firehose) | `string` | `""` | no | | [slow\_log\_format](#input\_slow\_log\_format) | the format for logs eg. json/text | `string` | `"json"` | no | diff --git a/examples/complete/main.tf b/examples/complete/main.tf index 91ce41b..13bdab2 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -1,14 +1,14 @@ locals { name = "redis" - region = "us-east-1" + region = "us-east-2" family = "redis6.x" node_type = "cache.t3.small" - vpc_id = "vpc-06f1a2f3a7" - subnet_ids = ["subnet-0bb128ab", "subnet-0b54928666a"] - kms_key_arn = "arn:aws:kms:us-east-1:2222222222:key/bcfdc1c5-1bbbdb467d90" + vpc_id = "vpc-0220830b5260698db" + subnet_ids = ["subnet-0d4dee4a7ea31a96d", "subnet-07fdc14616382f833"] + kms_key_arn = "" environment = "prod" redis_engine_version = "6.0" - allowed_security_groups = ["sg-0e8dab08e40"] + allowed_security_groups = ["sg-02c3f55874f6e0c64"] additional_tags = { Owner = "Organization_Name" Expires = "Never" @@ -17,19 +17,25 @@ locals { } module "redis" { - source = "squareops/elasticache-redis/aws" - name = local.name - family = local.family - node_type = local.node_type - environment = local.environment - engine_version = local.redis_engine_version - num_cache_nodes = 2 - vpc_id = local.vpc_id - subnets = local.subnet_ids - kms_key_arn = local.kms_key_arn - multi_az_enabled = false - availability_zones = 2 - snapshot_window = "07:00-08:00" - maintenance_window = "sun:09:00-sun:10:00" - allowed_security_groups = local.allowed_security_groups + source = "squareops/elasticache-redis/aws" + name = local.name + family = local.family + node_type = local.node_type + environment = local.environment + engine_version = local.redis_engine_version + num_cache_nodes = 2 + vpc_id = local.vpc_id + subnets = local.subnet_ids + kms_key_arn = local.kms_key_arn + multi_az_enabled = false + availability_zones = 2 + snapshot_window = "07:00-08:00" + maintenance_window = "sun:09:00-sun:10:00" + allowed_security_groups = local.allowed_security_groups + cloudwatch_metric_alarms_enabled = true + alarm_cpu_threshold_percent = 70 + alarm_memory_threshold_bytes = "10000000" # in bytes + slack_username = "" + slack_channel = "" + slack_webhook_url = "" } diff --git a/lambda/README.md b/lambda/README.md new file mode 100644 index 0000000..e880905 --- /dev/null +++ b/lambda/README.md @@ -0,0 +1,60 @@ +## Lambda for SNS +![squareops_avatar] + +[squareops_avatar]: https://squareops.com/wp-content/uploads/2022/12/squareops-logo.png + +### [SquareOps Technologies](https://squareops.com/) Your DevOps Partner for Accelerating cloud journey. +
+ +Here is Lambda that calls the Slack webhook and passes the alarm message as the payload. + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_cloudwatch_log_group.lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | +| [aws_iam_role.lambda_exec_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy.lambda_cwl_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_lambda_function.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | +| [aws_iam_policy_document.lambda_cwl_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.lambda_exec_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [artifact\_file](#input\_artifact\_file) | The path to the function's deployment package within the local filesystem | `string` | `null` | no | +| [cwl\_retention\_days](#input\_cwl\_retention\_days) | The retention time in days for the CloudWatch Logs Stream. | `number` | `30` | no | +| [description](#input\_description) | Description of what the Lambda Function does. | `string` | `null` | no | +| [environment](#input\_environment) | The Lambda environment's configuration settings. | `map(string)` | `{}` | no | +| [handler](#input\_handler) | The function entrypoint in the code. | `string` | `"index.handler"` | no | +| [memory\_size](#input\_memory\_size) | Amount of memory in MB your Lambda Function can use at runtime. | `number` | `128` | no | +| [name](#input\_name) | A unique name for the Lambda Function. | `string` | n/a | yes | +| [runtime](#input\_runtime) | The Runtime used in the Lambda Function. | `string` | n/a | yes | +| [tags](#input\_tags) | A mapping of tags to assign to the module resources. | `map(string)` | `{}` | no | +| [timeout](#input\_timeout) | The amount of time your Lambda Function has to run in seconds. | `number` | `6` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [arn](#output\_arn) | The ARN identifying the Lambda Function. | +| [exec\_role\_id](#output\_exec\_role\_id) | The ID of the Function's IAM Role. | +| [invoke\_arn](#output\_invoke\_arn) | The ARN to be used for invoking Lambda Function from API Gateway. | +| [name](#output\_name) | The name of the Lambda Function. | + + \ No newline at end of file diff --git a/lambda/data.tf b/lambda/data.tf new file mode 100644 index 0000000..679463c --- /dev/null +++ b/lambda/data.tf @@ -0,0 +1,32 @@ +# Lambda Assume Role policy +data "aws_iam_policy_document" "lambda_exec_role_policy" { + statement { + sid = "LambdaExecRolePolicy" + effect = "Allow" + principals { + identifiers = [ + "lambda.amazonaws.com", + ] + type = "Service" + } + actions = [ + "sts:AssumeRole", + ] + } +} + +# Lambda CloudWatch Logs access +data "aws_iam_policy_document" "lambda_cwl_access" { + statement { + sid = "LambdaCreateCloudWatchLogGroup" + effect = "Allow" + actions = [ + "logs:PutLogEvents", + "logs:CreateLogStream", + "logs:CreateLogGroup" + ] + resources = [ + "arn:aws:logs:*:*:log-group:/aws/lambda/*:*:*" + ] + } +} diff --git a/lambda/iam.tf b/lambda/iam.tf new file mode 100644 index 0000000..b6e4760 --- /dev/null +++ b/lambda/iam.tf @@ -0,0 +1,10 @@ +resource "aws_iam_role" "lambda_exec_role" { + name = "${replace(title(var.name), "-", "")}LambdaExecRole" + assume_role_policy = data.aws_iam_policy_document.lambda_exec_role_policy.json +} + +resource "aws_iam_role_policy" "lambda_cwl_policy" { + name = "${replace(title(var.name), "-", "")}LambdaCWLogsPolicy" + role = aws_iam_role.lambda_exec_role.id + policy = data.aws_iam_policy_document.lambda_cwl_access.json +} diff --git a/lambda/main.tf b/lambda/main.tf new file mode 100644 index 0000000..1a845ef --- /dev/null +++ b/lambda/main.tf @@ -0,0 +1,26 @@ +resource "aws_cloudwatch_log_group" "lambda" { + name = "/aws/lambda/${var.name}" + retention_in_days = var.cwl_retention_days + tags = var.tags +} + +resource "aws_lambda_function" "this" { + function_name = var.name + description = var.description + filename = var.artifact_file + source_code_hash = var.artifact_file != null ? filebase64sha256(var.artifact_file) : null + role = aws_iam_role.lambda_exec_role.arn + handler = var.handler + runtime = var.runtime + memory_size = var.memory_size + timeout = var.timeout + + dynamic "environment" { + for_each = (length(var.environment) > 0 ? [1] : []) + content { + variables = var.environment + } + } + + tags = var.tags +} diff --git a/lambda/outputs.tf b/lambda/outputs.tf new file mode 100644 index 0000000..e97e7ec --- /dev/null +++ b/lambda/outputs.tf @@ -0,0 +1,19 @@ +output "name" { + description = "The name of the Lambda Function." + value = aws_lambda_function.this.function_name +} + +output "arn" { + description = "The ARN identifying the Lambda Function." + value = aws_lambda_function.this.arn +} + +output "invoke_arn" { + description = "The ARN to be used for invoking Lambda Function from API Gateway." + value = aws_lambda_function.this.invoke_arn +} + +output "exec_role_id" { + description = "The ID of the Function's IAM Role." + value = aws_iam_role.lambda_exec_role.id +} diff --git a/lambda/sns_slack.py b/lambda/sns_slack.py new file mode 100644 index 0000000..239e101 --- /dev/null +++ b/lambda/sns_slack.py @@ -0,0 +1,51 @@ +import json +import re +import os +import boto3 +import urllib3 + +# Lambda global variables +region = os.environ["AWS_REGION"] # from Lambda default envs +slack_url = os.environ["SLACK_URL"] +slack_channel = os.environ["SLACK_CHANNEL"] +slack_user = os.environ["SLACK_USER"] + + +http = urllib3.PoolManager() +def format_cloudwatch_alarm_message(event): + alarm_data = json.loads(event['Records'][0]['Sns']['Message']) + + alarm_name = alarm_data["AlarmName"] + alarm_description = alarm_data["AlarmDescription"] + new_state = alarm_data["NewStateValue"] + reason = alarm_data["NewStateReason"] + metric_name = alarm_data["Trigger"]["MetricName"] + threshold = alarm_data["Trigger"]["Threshold"] + + message = f"*:exclamation: CloudWatch Alarm Alert :exclamation:*\n\n" + message += f" *Alarm Name:* {alarm_name}\n" + message += f" *Description:* _{alarm_description}_\n" + message += f" *New State:* {new_state}\n" + message += f" *Reason:* _{reason}_\n" + message += f" *Metric Name:* {metric_name}\n" + message += f" *Threshold:* {threshold}\n" + + return message + +def lambda_handler(event, context): + url = slack_url + msg = { + "channel": slack_channel, + "username": slack_user, + "text": format_cloudwatch_alarm_message(event), + "icon_emoji": ":cloudwatch:" + } + + encoded_msg = json.dumps(msg).encode('utf-8') + resp = http.request('POST', url, body=encoded_msg) + + print({ + "message": msg, + "status_code": resp.status, + "response": resp.data + }) \ No newline at end of file diff --git a/lambda/sns_slack.zip b/lambda/sns_slack.zip new file mode 100644 index 0000000000000000000000000000000000000000..c38796dd0c9ecd2f9b104d2f840990c011052257 GIT binary patch literal 3010 zcmaJ@2{@En7@n~WDwU;+2)99&Q8ac!B$6c}%P__|3}czG6GJXjvKz85SCoCdCvL&^FHVQ-t#T5o)$F?D~KL=Kp?)m!0_E5z|01P zM~UI>BBI4HOUg$(yaE~BT#l^qH}I*_Pr=SyzKB29mT%vtC}TDU?a5$Gq0 zUNRd*wrs2&XB}<4NiP!9%;#;X+h69j6>peNPX`g=ma-Klv5hrn869I+63~*1g;Dz@ zs~>H&2W988LORZa+zb^+mdvg==xNkgJcm8HMX5Ezowz^Yw6>yV>;c_ zk8z&8<@cJa=9_)hs!H@+VL`*OolT4@Z@c4bbtmLb2nUECDW*VH8<6nZ8<=!VS54C? zgbUNqW5mr|qij~h8vKNml1E9WrW^0nCF6Pm3XS7}@>Ep#pF)0nC7yiVHTsG~S$Num zx|pvgK_Ci6PYXiN&?Q}<00x0_s6ZgSpAt?75bl6-2KbJTD$}7BKcVIq*oM9mqwyp# znsFdk86H1eUUNBY8TW28Ci5I6(!WkQ2u^l~`^uN(&z6M;d)sHtvtEn5mf5*jHIwO= zAS)+h`S$mn08IaztOcp^h3qZK_tPQwTzY01@wy@>U{NW=?b=&DSU9AVoP-Y!bB=8C zx4IuGvbzy)z*#S9J(%^SC1ox+utuRa2RC9nHyjnWJniMl=MmTWtXrUk{E|2ww1u`p z-2Ns#x}8Rijdiv*QS0eVMgpGx?RR@P*uE9;ssecPbHDck%^Br@1sr#Z?ZJ*+IB{pq z|E|!0sy}foyN53*1;RjOrCkK0`pTdoT#VUybB~SxroMf2cA{0G zuBum-qunC!UA40Yht3%vGQ@P>YtU zKgGox)a1QUBS1@gQ!cTn?vLz(2K^=M7-0^sCL+LDzg1i*Wk2v@PwMPvedUfeyKS*Q zJ|=~Vp6cCrUwtea@rLLmseem(sdIFwZ1K@2%Cq&wAQ|td#DPtX(2VB9^yWQp-yO)r zl+PXh#&BD$PfhX})udWe3z&cjs?Tp3jJsG+ z9Wi-0OO=;}H5V|^>>bf~VuFt35zAwj8J6OC8()qpj~xk__b%RJZwnru5^R1;TY{Wi zj~Je~#XlqdyAo}l%>F=F_+5nfb_rC$j2<&(9 zz`J_jalqaDKG1iq^}-3db-(oKoL^i5LKIomgz`J56<*=qw zj$dwmu^lpyx+R9VH{o(t`~TD98+xh={8Rvi>r= zY`JO)xVwa7gF5)q!kxLYHW>ealT5xs-rf(n>xL$HP!wt@+dfzv8HF z$GpnWt2s98mB%@Eb0zlNiwfn|G8|!Qb(fBZT#yM7u_(eZh3a9%Ec-mVMyRye(W2M* z`M|aU=eBc=+`Arb-^1VjOqoyNFaxJPQ7?EL*Xi~Qg96V^+##G)*i9ccZM&cZ*r*Dmo)tyI1e34!QkP^Xw-yrS{=_bIM0CvCT~%Jz=Q*fYgRj#%9w|}IfqdpAV;;3=9IFe-m zOttYA=s2s9F{wSruh^9~1?If?$XF@)WmW3DHivY|BwD^=*QgPkHoVp(pssW}Y|Vnf z3`0KYkeK~zvUi@D7>@9|>63M5eC5v2)mGX)c3bEaXJ=?1VcMJdVL1^es8s(0@wBP;(P2rA?@qn`n`Aq zA3(JG17JVL@27+(%H08FVQ8;Y@CoIC8v;G=u1-#c#@m{W+iS!=6ky%zKM|vg%ij z(NfiCTypaaAumC@$h)szI&NMk^O@1a~% z@=$>B1M71JnK3e7K9RMmTlBOc+k*l-Suq!Gc22ZB;HMuW+Mb!1zOh!zZ5_OlM0dTb z%D?d|uhecZ33~M+Y|b_VDM1t$^$lO;t=NrYxHi*8G_jJZFi4NY5OvBZyIDo4`HIa@ z$z00!09cUlFYW+VmOvEfX@RL&ss9y)SPtxqodcr~+<;^L zmOejX4tJ{m9^?ST_CK=WN6_JFzTdcA+3IpDAVMFI)-BlIxM|2 Date: Wed, 13 Sep 2023 17:35:31 +0530 Subject: [PATCH 2/5] removed .zip --- lambda/sns_slack.zip | Bin 3010 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 lambda/sns_slack.zip diff --git a/lambda/sns_slack.zip b/lambda/sns_slack.zip deleted file mode 100644 index c38796dd0c9ecd2f9b104d2f840990c011052257..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3010 zcmaJ@2{@En7@n~WDwU;+2)99&Q8ac!B$6c}%P__|3}czG6GJXjvKz85SCoCdCvL&^FHVQ-t#T5o)$F?D~KL=Kp?)m!0_E5z|01P zM~UI>BBI4HOUg$(yaE~BT#l^qH}I*_Pr=SyzKB29mT%vtC}TDU?a5$Gq0 zUNRd*wrs2&XB}<4NiP!9%;#;X+h69j6>peNPX`g=ma-Klv5hrn869I+63~*1g;Dz@ zs~>H&2W988LORZa+zb^+mdvg==xNkgJcm8HMX5Ezowz^Yw6>yV>;c_ zk8z&8<@cJa=9_)hs!H@+VL`*OolT4@Z@c4bbtmLb2nUECDW*VH8<6nZ8<=!VS54C? zgbUNqW5mr|qij~h8vKNml1E9WrW^0nCF6Pm3XS7}@>Ep#pF)0nC7yiVHTsG~S$Num zx|pvgK_Ci6PYXiN&?Q}<00x0_s6ZgSpAt?75bl6-2KbJTD$}7BKcVIq*oM9mqwyp# znsFdk86H1eUUNBY8TW28Ci5I6(!WkQ2u^l~`^uN(&z6M;d)sHtvtEn5mf5*jHIwO= zAS)+h`S$mn08IaztOcp^h3qZK_tPQwTzY01@wy@>U{NW=?b=&DSU9AVoP-Y!bB=8C zx4IuGvbzy)z*#S9J(%^SC1ox+utuRa2RC9nHyjnWJniMl=MmTWtXrUk{E|2ww1u`p z-2Ns#x}8Rijdiv*QS0eVMgpGx?RR@P*uE9;ssecPbHDck%^Br@1sr#Z?ZJ*+IB{pq z|E|!0sy}foyN53*1;RjOrCkK0`pTdoT#VUybB~SxroMf2cA{0G zuBum-qunC!UA40Yht3%vGQ@P>YtU zKgGox)a1QUBS1@gQ!cTn?vLz(2K^=M7-0^sCL+LDzg1i*Wk2v@PwMPvedUfeyKS*Q zJ|=~Vp6cCrUwtea@rLLmseem(sdIFwZ1K@2%Cq&wAQ|td#DPtX(2VB9^yWQp-yO)r zl+PXh#&BD$PfhX})udWe3z&cjs?Tp3jJsG+ z9Wi-0OO=;}H5V|^>>bf~VuFt35zAwj8J6OC8()qpj~xk__b%RJZwnru5^R1;TY{Wi zj~Je~#XlqdyAo}l%>F=F_+5nfb_rC$j2<&(9 zz`J_jalqaDKG1iq^}-3db-(oKoL^i5LKIomgz`J56<*=qw zj$dwmu^lpyx+R9VH{o(t`~TD98+xh={8Rvi>r= zY`JO)xVwa7gF5)q!kxLYHW>ealT5xs-rf(n>xL$HP!wt@+dfzv8HF z$GpnWt2s98mB%@Eb0zlNiwfn|G8|!Qb(fBZT#yM7u_(eZh3a9%Ec-mVMyRye(W2M* z`M|aU=eBc=+`Arb-^1VjOqoyNFaxJPQ7?EL*Xi~Qg96V^+##G)*i9ccZM&cZ*r*Dmo)tyI1e34!QkP^Xw-yrS{=_bIM0CvCT~%Jz=Q*fYgRj#%9w|}IfqdpAV;;3=9IFe-m zOttYA=s2s9F{wSruh^9~1?If?$XF@)WmW3DHivY|BwD^=*QgPkHoVp(pssW}Y|Vnf z3`0KYkeK~zvUi@D7>@9|>63M5eC5v2)mGX)c3bEaXJ=?1VcMJdVL1^es8s(0@wBP;(P2rA?@qn`n`Aq zA3(JG17JVL@27+(%H08FVQ8;Y@CoIC8v;G=u1-#c#@m{W+iS!=6ky%zKM|vg%ij z(NfiCTypaaAumC@$h)szI&NMk^O@1a~% z@=$>B1M71JnK3e7K9RMmTlBOc+k*l-Suq!Gc22ZB;HMuW+Mb!1zOh!zZ5_OlM0dTb z%D?d|uhecZ33~M+Y|b_VDM1t$^$lO;t=NrYxHi*8G_jJZFi4NY5OvBZyIDo4`HIa@ z$z00!09cUlFYW+VmOvEfX@RL&ss9y)SPtxqodcr~+<;^L zmOejX4tJ{m9^?ST_CK=WN6_JFzTdcA+3IpDAVMFI)-BlIxM|2 Date: Thu, 14 Sep 2023 16:26:40 +0530 Subject: [PATCH 3/5] removed the kms encryption over sns topic --- main.tf | 1 - 1 file changed, 1 deletion(-) diff --git a/main.tf b/main.tf index 7443d87..fb9c13c 100644 --- a/main.tf +++ b/main.tf @@ -217,7 +217,6 @@ resource "aws_sns_topic" "slack_topic" { count = var.cloudwatch_metric_alarms_enabled ? 1 : 0 depends_on = [aws_elasticache_replication_group.redis] name = format("%s-%s-%s", var.environment, var.name, "slack-topic") - kms_master_key_id = aws_kms_key.this[0].key_id delivery_policy = < Date: Thu, 14 Sep 2023 16:31:44 +0530 Subject: [PATCH 4/5] code refactoring --- lambda/README.md | 3 +-- lambda/sns_slack.py | 6 +++--- main.tf | 8 ++++---- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/lambda/README.md b/lambda/README.md index e880905..6c252e1 100644 --- a/lambda/README.md +++ b/lambda/README.md @@ -56,5 +56,4 @@ No modules. | [exec\_role\_id](#output\_exec\_role\_id) | The ID of the Function's IAM Role. | | [invoke\_arn](#output\_invoke\_arn) | The ARN to be used for invoking Lambda Function from API Gateway. | | [name](#output\_name) | The name of the Lambda Function. | - - \ No newline at end of file + diff --git a/lambda/sns_slack.py b/lambda/sns_slack.py index 239e101..1351c7e 100644 --- a/lambda/sns_slack.py +++ b/lambda/sns_slack.py @@ -33,7 +33,7 @@ def format_cloudwatch_alarm_message(event): return message def lambda_handler(event, context): - url = slack_url + url = slack_url msg = { "channel": slack_channel, "username": slack_user, @@ -43,9 +43,9 @@ def lambda_handler(event, context): encoded_msg = json.dumps(msg).encode('utf-8') resp = http.request('POST', url, body=encoded_msg) - + print({ "message": msg, "status_code": resp.status, "response": resp.data - }) \ No newline at end of file + }) diff --git a/main.tf b/main.tf index fb9c13c..05ba51f 100644 --- a/main.tf +++ b/main.tf @@ -214,10 +214,10 @@ resource "aws_kms_ciphertext" "slack_url" { } resource "aws_sns_topic" "slack_topic" { - count = var.cloudwatch_metric_alarms_enabled ? 1 : 0 - depends_on = [aws_elasticache_replication_group.redis] - name = format("%s-%s-%s", var.environment, var.name, "slack-topic") - delivery_policy = < Date: Fri, 15 Sep 2023 13:33:40 +0530 Subject: [PATCH 5/5] Removed unwanted variable and added CW alerts description --- README.md | 4 +++- main.tf | 5 ++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 65c03ac..d562225 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,9 @@ Features 7. Logging and Monitoring: Easily configure logging destinations for slow logs and engine logs, allowing you to monitor the performance and troubleshoot any issues efficiently. + 8. CloudWatch Alerts: Set up CloudWatch alarms to monitor the health and performance of your Redis cluster. Integrate these alarms with AWS Simple Notification Service (SNS) to receive real-time alerts. Use AWS Lambda functions to customize your alerting logic, and send notifications to Slack channels for immediate visibility into your Redis cluster's status. + + ## Uses Example ```hcl @@ -41,7 +44,6 @@ module "redis" { availability_zones = 2 automatic_failover_enabled = true snapshot_retention_limit = 7 - at_rest_encryption_enabled = true transit_encryption_enabled = false notification_topic_arn = null allowed_security_groups = [sg-0132a18skaf] diff --git a/main.tf b/main.tf index 05ba51f..547afa3 100644 --- a/main.tf +++ b/main.tf @@ -48,7 +48,6 @@ resource "aws_elasticache_replication_group" "redis" { multi_az_enabled = var.multi_az_enabled kms_key_id = var.kms_key_arn auth_token = var.transit_encryption_enabled ? random_password.password.result : null - at_rest_encryption_enabled = var.at_rest_encryption_enabled transit_encryption_enabled = var.transit_encryption_enabled notification_topic_arn = var.notification_topic_arn maintenance_window = var.maintenance_window @@ -166,7 +165,7 @@ resource "aws_cloudwatch_metric_alarm" "cache_cpu" { } alarm_actions = [aws_sns_topic.slack_topic[0].arn] - ok_actions = var.ok_actions + ok_actions = [aws_sns_topic.slack_topic[0].arn] depends_on = [aws_sns_topic.slack_topic] tags = merge( @@ -193,7 +192,7 @@ resource "aws_cloudwatch_metric_alarm" "cache_memory" { } alarm_actions = [aws_sns_topic.slack_topic[0].arn] - ok_actions = var.ok_actions + ok_actions = [aws_sns_topic.slack_topic[0].arn] depends_on = [aws_sns_topic.slack_topic] tags = merge(