cloudwatch_metrics_and_alarms.tf 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. locals {
  2. alarm_namespace = "cis"
  3. }
  4. resource "aws_cloudwatch_log_metric_filter" "unauthorized_api_calls" {
  5. name = "UnauthorizedAPICalls"
  6. pattern = "{ ($.errorCode = \"*UnauthorizedOperation\") || ($.errorCode = \"AccessDenied*\") }"
  7. log_group_name = var.log_group_name
  8. metric_transformation {
  9. name = "UnauthorizedAPICalls"
  10. namespace = local.alarm_namespace
  11. value = "1"
  12. }
  13. depends_on = [ module.cloudtrail-logging ]
  14. }
  15. resource "aws_cloudwatch_metric_alarm" "unauthorized_api_calls" {
  16. alarm_name = "UnauthorizedAPICalls"
  17. comparison_operator = "GreaterThanOrEqualToThreshold"
  18. evaluation_periods = "1"
  19. metric_name = aws_cloudwatch_log_metric_filter.unauthorized_api_calls.id
  20. namespace = local.alarm_namespace
  21. period = "300"
  22. statistic = "Sum"
  23. threshold = "50"
  24. alarm_description = "Monitoring unauthorized API calls will help reveal application errors and may reduce time to detect malicious activity."
  25. alarm_actions = ["arn:${var.aws_partition}:sns:${var.aws_region}:${local.c2_account}:account-alerts"]
  26. insufficient_data_actions = []
  27. depends_on = [ module.cloudtrail-logging ]
  28. }
  29. resource "aws_cloudwatch_log_metric_filter" "no_mfa_console_signin" {
  30. name = "NoMFAConsoleSignin"
  31. pattern = "{ ($.eventName = \"ConsoleLogin\") && ($.additionalEventData.MFAUsed != \"Yes\") }"
  32. log_group_name = var.log_group_name
  33. metric_transformation {
  34. name = "NoMFAConsoleSignin"
  35. namespace = local.alarm_namespace
  36. value = "1"
  37. }
  38. depends_on = [ module.cloudtrail-logging ]
  39. }
  40. resource "aws_cloudwatch_metric_alarm" "no_mfa_console_signin" {
  41. alarm_name = "NoMFAConsoleSignin"
  42. comparison_operator = "GreaterThanOrEqualToThreshold"
  43. evaluation_periods = "1"
  44. metric_name = aws_cloudwatch_log_metric_filter.no_mfa_console_signin.id
  45. namespace = local.alarm_namespace
  46. period = "300"
  47. statistic = "Sum"
  48. threshold = "1"
  49. alarm_description = "Monitoring for single-factor console logins will increase visibility into accounts that are not protected by MFA."
  50. alarm_actions = ["arn:${var.aws_partition}:sns:${var.aws_region}:${local.c2_account}:account-alerts"]
  51. insufficient_data_actions = []
  52. }
  53. resource "aws_cloudwatch_log_metric_filter" "root_usage" {
  54. name = "RootUsage"
  55. pattern = "{ $.userIdentity.type = \"Root\" && $.userIdentity.invokedBy NOT EXISTS && $.eventType != \"AwsServiceEvent\" }"
  56. log_group_name = var.log_group_name
  57. metric_transformation {
  58. name = "RootUsage"
  59. namespace = local.alarm_namespace
  60. value = "1"
  61. }
  62. depends_on = [ module.cloudtrail-logging ]
  63. }
  64. resource "aws_cloudwatch_metric_alarm" "root_usage" {
  65. alarm_name = "RootUsage"
  66. comparison_operator = "GreaterThanOrEqualToThreshold"
  67. evaluation_periods = "1"
  68. metric_name = aws_cloudwatch_log_metric_filter.root_usage.id
  69. namespace = local.alarm_namespace
  70. period = "300"
  71. statistic = "Sum"
  72. threshold = "1"
  73. alarm_description = "Monitoring for root account logins will provide visibility into the use of a fully privileged account and an opportunity to reduce the use of it."
  74. alarm_actions = ["arn:${var.aws_partition}:sns:${var.aws_region}:${local.c2_account}:account-alerts"]
  75. insufficient_data_actions = []
  76. }
  77. resource "aws_cloudwatch_log_metric_filter" "iam_changes" {
  78. name = "IAMChanges"
  79. pattern = "{($.eventName=DeleteGroupPolicy)||($.eventName=DeleteRolePolicy)||($.eventName=DeleteUserPolicy)||($.eventName=PutGroupPolicy)||($.eventName=PutRolePolicy)||($.eventName=PutUserPolicy)||($.eventName=CreatePolicy)||($.eventName=DeletePolicy)||($.eventName=CreatePolicyVersion)||($.eventName=DeletePolicyVersion)||($.eventName=AttachRolePolicy)||($.eventName=DetachRolePolicy)||($.eventName=AttachUserPolicy)||($.eventName=DetachUserPolicy)||($.eventName=AttachGroupPolicy)||($.eventName=DetachGroupPolicy)}"
  80. log_group_name = var.log_group_name
  81. metric_transformation {
  82. name = "IAMChanges"
  83. namespace = local.alarm_namespace
  84. value = "1"
  85. }
  86. depends_on = [ module.cloudtrail-logging ]
  87. }
  88. resource "aws_cloudwatch_metric_alarm" "iam_changes" {
  89. alarm_name = "IAMChanges"
  90. comparison_operator = "GreaterThanOrEqualToThreshold"
  91. evaluation_periods = "1"
  92. metric_name = aws_cloudwatch_log_metric_filter.iam_changes.id
  93. namespace = local.alarm_namespace
  94. period = "300"
  95. statistic = "Sum"
  96. threshold = "1"
  97. alarm_description = "Monitoring changes to IAM policies will help ensure authentication and authorization controls remain intact."
  98. alarm_actions = ["arn:${var.aws_partition}:sns:${var.aws_region}:${local.c2_account}:account-alerts"]
  99. insufficient_data_actions = []
  100. }
  101. resource "aws_cloudwatch_log_metric_filter" "cloudtrail_cfg_changes" {
  102. name = "CloudTrailCfgChanges"
  103. pattern = "{ ($.eventName = CreateTrail) || ($.eventName = UpdateTrail) || ($.eventName = DeleteTrail) || ($.eventName = StartLogging) || ($.eventName = StopLogging) }"
  104. log_group_name = var.log_group_name
  105. metric_transformation {
  106. name = "CloudTrailCfgChanges"
  107. namespace = local.alarm_namespace
  108. value = "1"
  109. }
  110. depends_on = [ module.cloudtrail-logging ]
  111. }
  112. resource "aws_cloudwatch_metric_alarm" "cloudtrail_cfg_changes" {
  113. alarm_name = "CloudTrailCfgChanges"
  114. comparison_operator = "GreaterThanOrEqualToThreshold"
  115. evaluation_periods = "1"
  116. metric_name = aws_cloudwatch_log_metric_filter.cloudtrail_cfg_changes.id
  117. namespace = local.alarm_namespace
  118. period = "300"
  119. statistic = "Sum"
  120. threshold = "1"
  121. alarm_description = "Monitoring changes to CloudTrail's configuration will help ensure sustained visibility to activities performed in the AWS account."
  122. alarm_actions = ["arn:${var.aws_partition}:sns:${var.aws_region}:${local.c2_account}:account-alerts"]
  123. insufficient_data_actions = []
  124. }
  125. resource "aws_cloudwatch_log_metric_filter" "console_signin_failures" {
  126. name = "ConsoleSigninFailures"
  127. pattern = "{ ($.eventName = ConsoleLogin) && ($.errorMessage = \"Failed authentication\") }"
  128. log_group_name = var.log_group_name
  129. metric_transformation {
  130. name = "ConsoleSigninFailures"
  131. namespace = local.alarm_namespace
  132. value = "1"
  133. }
  134. depends_on = [ module.cloudtrail-logging ]
  135. }
  136. resource "aws_cloudwatch_metric_alarm" "console_signin_failures" {
  137. alarm_name = "ConsoleSigninFailures"
  138. comparison_operator = "GreaterThanOrEqualToThreshold"
  139. evaluation_periods = "1"
  140. metric_name = aws_cloudwatch_log_metric_filter.console_signin_failures.id
  141. namespace = local.alarm_namespace
  142. period = "300"
  143. statistic = "Sum"
  144. threshold = "1"
  145. alarm_description = "Monitoring failed console logins may decrease lead time to detect an attempt to brute force a credential, which may provide an indicator, such as source IP, that can be used in other event correlation."
  146. alarm_actions = ["arn:${var.aws_partition}:sns:${var.aws_region}:${local.c2_account}:account-alerts"]
  147. insufficient_data_actions = []
  148. }
  149. resource "aws_cloudwatch_log_metric_filter" "disable_or_delete_cmk" {
  150. name = "DisableOrDeleteCMK"
  151. pattern = "{ ($.eventSource = kms.amazonaws.com) && (($.eventName = DisableKey) || ($.eventName = ScheduleKeyDeletion)) }"
  152. log_group_name = var.log_group_name
  153. metric_transformation {
  154. name = "DisableOrDeleteCMK"
  155. namespace = local.alarm_namespace
  156. value = "1"
  157. }
  158. depends_on = [ module.cloudtrail-logging ]
  159. }
  160. resource "aws_cloudwatch_metric_alarm" "disable_or_delete_cmk" {
  161. alarm_name = "DisableOrDeleteCMK"
  162. comparison_operator = "GreaterThanOrEqualToThreshold"
  163. evaluation_periods = "1"
  164. metric_name = aws_cloudwatch_log_metric_filter.disable_or_delete_cmk.id
  165. namespace = local.alarm_namespace
  166. period = "300"
  167. statistic = "Sum"
  168. threshold = "1"
  169. alarm_description = "Monitoring failed console logins may decrease lead time to detect an attempt to brute force a credential, which may provide an indicator, such as source IP, that can be used in other event correlation."
  170. alarm_actions = ["arn:${var.aws_partition}:sns:${var.aws_region}:${local.c2_account}:account-alerts"]
  171. insufficient_data_actions = []
  172. }
  173. resource "aws_cloudwatch_log_metric_filter" "s3_bucket_policy_changes" {
  174. name = "S3BucketPolicyChanges"
  175. pattern = "{ ($.eventSource = s3.amazonaws.com) && (($.eventName = PutBucketAcl) || ($.eventName = PutBucketPolicy) || ($.eventName = PutBucketCors) || ($.eventName = PutBucketLifecycle) || ($.eventName = PutBucketReplication) || ($.eventName = DeleteBucketPolicy) || ($.eventName = DeleteBucketCors) || ($.eventName = DeleteBucketLifecycle) || ($.eventName = DeleteBucketReplication)) }"
  176. log_group_name = var.log_group_name
  177. metric_transformation {
  178. name = "S3BucketPolicyChanges"
  179. namespace = local.alarm_namespace
  180. value = "1"
  181. }
  182. depends_on = [ module.cloudtrail-logging ]
  183. }
  184. resource "aws_cloudwatch_metric_alarm" "s3_bucket_policy_changes" {
  185. alarm_name = "S3BucketPolicyChanges"
  186. comparison_operator = "GreaterThanOrEqualToThreshold"
  187. evaluation_periods = "1"
  188. metric_name = aws_cloudwatch_log_metric_filter.s3_bucket_policy_changes.id
  189. namespace = local.alarm_namespace
  190. period = "300"
  191. statistic = "Sum"
  192. threshold = "1"
  193. alarm_description = "Monitoring changes to S3 bucket policies may reduce time to detect and correct permissive policies on sensitive S3 buckets."
  194. alarm_actions = ["arn:${var.aws_partition}:sns:${var.aws_region}:${local.c2_account}:account-alerts"]
  195. insufficient_data_actions = []
  196. }
  197. resource "aws_cloudwatch_log_metric_filter" "aws_config_changes" {
  198. name = "AWSConfigChanges"
  199. pattern = "{ ($.eventSource = config.amazonaws.com) && (($.eventName=StopConfigurationRecorder)||($.eventName=DeleteDeliveryChannel)||($.eventName=PutDeliveryChannel)||($.eventName=PutConfigurationRecorder)) }"
  200. log_group_name = var.log_group_name
  201. metric_transformation {
  202. name = "AWSConfigChanges"
  203. namespace = local.alarm_namespace
  204. value = "1"
  205. }
  206. depends_on = [ module.cloudtrail-logging ]
  207. }
  208. resource "aws_cloudwatch_metric_alarm" "aws_config_changes" {
  209. alarm_name = "AWSConfigChanges"
  210. comparison_operator = "GreaterThanOrEqualToThreshold"
  211. evaluation_periods = "1"
  212. metric_name = aws_cloudwatch_log_metric_filter.aws_config_changes.id
  213. namespace = local.alarm_namespace
  214. period = "300"
  215. statistic = "Sum"
  216. threshold = "1"
  217. alarm_description = "Monitoring changes to AWS Config configuration will help ensure sustained visibility of configuration items within the AWS account."
  218. alarm_actions = ["arn:${var.aws_partition}:sns:${var.aws_region}:${local.c2_account}:account-alerts"]
  219. insufficient_data_actions = []
  220. }
  221. resource "aws_cloudwatch_log_metric_filter" "security_group_changes" {
  222. name = "SecurityGroupChanges"
  223. pattern = "{ ($.eventName = AuthorizeSecurityGroupIngress) || ($.eventName = AuthorizeSecurityGroupEgress) || ($.eventName = RevokeSecurityGroupIngress) || ($.eventName = RevokeSecurityGroupEgress) || ($.eventName = CreateSecurityGroup) || ($.eventName = DeleteSecurityGroup)}"
  224. log_group_name = var.log_group_name
  225. metric_transformation {
  226. name = "SecurityGroupChanges"
  227. namespace = local.alarm_namespace
  228. value = "1"
  229. }
  230. depends_on = [ module.cloudtrail-logging ]
  231. }
  232. resource "aws_cloudwatch_metric_alarm" "security_group_changes" {
  233. alarm_name = "SecurityGroupChanges"
  234. comparison_operator = "GreaterThanOrEqualToThreshold"
  235. evaluation_periods = "1"
  236. metric_name = aws_cloudwatch_log_metric_filter.security_group_changes.id
  237. namespace = local.alarm_namespace
  238. period = "300"
  239. statistic = "Sum"
  240. threshold = "1"
  241. alarm_description = "Monitoring changes to security group will help ensure that resources and services are not unintentionally exposed."
  242. alarm_actions = ["arn:${var.aws_partition}:sns:${var.aws_region}:${local.c2_account}:account-alerts"]
  243. insufficient_data_actions = []
  244. }
  245. resource "aws_cloudwatch_log_metric_filter" "nacl_changes" {
  246. name = "NACLChanges"
  247. pattern = "{ ($.eventName = CreateNetworkAcl) || ($.eventName = CreateNetworkAclEntry) || ($.eventName = DeleteNetworkAcl) || ($.eventName = DeleteNetworkAclEntry) || ($.eventName = ReplaceNetworkAclEntry) || ($.eventName = ReplaceNetworkAclAssociation) }"
  248. log_group_name = var.log_group_name
  249. metric_transformation {
  250. name = "NACLChanges"
  251. namespace = local.alarm_namespace
  252. value = "1"
  253. }
  254. depends_on = [ module.cloudtrail-logging ]
  255. }
  256. resource "aws_cloudwatch_metric_alarm" "nacl_changes" {
  257. alarm_name = "NACLChanges"
  258. comparison_operator = "GreaterThanOrEqualToThreshold"
  259. evaluation_periods = "1"
  260. metric_name = aws_cloudwatch_log_metric_filter.nacl_changes.id
  261. namespace = local.alarm_namespace
  262. period = "300"
  263. statistic = "Sum"
  264. threshold = "1"
  265. alarm_description = "Monitoring changes to NACLs will help ensure that AWS resources and services are not unintentionally exposed."
  266. alarm_actions = ["arn:${var.aws_partition}:sns:${var.aws_region}:${local.c2_account}:account-alerts"]
  267. insufficient_data_actions = []
  268. }
  269. resource "aws_cloudwatch_log_metric_filter" "network_gw_changes" {
  270. name = "NetworkGWChanges"
  271. pattern = "{ ($.eventName = CreateCustomerGateway) || ($.eventName = DeleteCustomerGateway) || ($.eventName = AttachInternetGateway) || ($.eventName = CreateInternetGateway) || ($.eventName = DeleteInternetGateway) || ($.eventName = DetachInternetGateway) }"
  272. log_group_name = var.log_group_name
  273. metric_transformation {
  274. name = "NetworkGWChanges"
  275. namespace = local.alarm_namespace
  276. value = "1"
  277. }
  278. depends_on = [ module.cloudtrail-logging ]
  279. }
  280. resource "aws_cloudwatch_metric_alarm" "network_gw_changes" {
  281. alarm_name = "NetworkGWChanges"
  282. comparison_operator = "GreaterThanOrEqualToThreshold"
  283. evaluation_periods = "1"
  284. metric_name = aws_cloudwatch_log_metric_filter.network_gw_changes.id
  285. namespace = local.alarm_namespace
  286. period = "300"
  287. statistic = "Sum"
  288. threshold = "1"
  289. alarm_description = "Monitoring changes to network gateways will help ensure that all ingress/egress traffic traverses the VPC border via a controlled path."
  290. alarm_actions = ["arn:${var.aws_partition}:sns:${var.aws_region}:${local.c2_account}:account-alerts"]
  291. insufficient_data_actions = []
  292. }
  293. resource "aws_cloudwatch_log_metric_filter" "route_table_changes" {
  294. name = "RouteTableChanges"
  295. pattern = "{ ($.eventName = CreateRoute) || ($.eventName = CreateRouteTable) || ($.eventName = ReplaceRoute) || ($.eventName = ReplaceRouteTableAssociation) || ($.eventName = DeleteRouteTable) || ($.eventName = DeleteRoute) || ($.eventName = DisassociateRouteTable) }"
  296. log_group_name = var.log_group_name
  297. metric_transformation {
  298. name = "RouteTableChanges"
  299. namespace = local.alarm_namespace
  300. value = "1"
  301. }
  302. depends_on = [ module.cloudtrail-logging ]
  303. }
  304. resource "aws_cloudwatch_metric_alarm" "route_table_changes" {
  305. alarm_name = "RouteTableChanges"
  306. comparison_operator = "GreaterThanOrEqualToThreshold"
  307. evaluation_periods = "1"
  308. metric_name = aws_cloudwatch_log_metric_filter.route_table_changes.id
  309. namespace = local.alarm_namespace
  310. period = "300"
  311. statistic = "Sum"
  312. threshold = "1"
  313. alarm_description = "Monitoring changes to route tables will help ensure that all VPC traffic flows through an expected path."
  314. alarm_actions = ["arn:${var.aws_partition}:sns:${var.aws_region}:${local.c2_account}:account-alerts"]
  315. insufficient_data_actions = []
  316. }
  317. resource "aws_cloudwatch_log_metric_filter" "vpc_changes" {
  318. name = "VPCChanges"
  319. pattern = "{ ($.eventName = CreateVpc) || ($.eventName = DeleteVpc) || ($.eventName = ModifyVpcAttribute) || ($.eventName = AcceptVpcPeeringConnection) || ($.eventName = CreateVpcPeeringConnection) || ($.eventName = DeleteVpcPeeringConnection) || ($.eventName = RejectVpcPeeringConnection) || ($.eventName = AttachClassicLinkVpc) || ($.eventName = DetachClassicLinkVpc) || ($.eventName = DisableVpcClassicLink) || ($.eventName = EnableVpcClassicLink) }"
  320. log_group_name = var.log_group_name
  321. metric_transformation {
  322. name = "VPCChanges"
  323. namespace = local.alarm_namespace
  324. value = "1"
  325. }
  326. depends_on = [ module.cloudtrail-logging ]
  327. }
  328. resource "aws_cloudwatch_metric_alarm" "vpc_changes" {
  329. alarm_name = "VPCChanges"
  330. comparison_operator = "GreaterThanOrEqualToThreshold"
  331. evaluation_periods = "1"
  332. metric_name = aws_cloudwatch_log_metric_filter.vpc_changes.id
  333. namespace = local.alarm_namespace
  334. period = "300"
  335. statistic = "Sum"
  336. threshold = "1"
  337. alarm_description = "Monitoring changes to VPC will help ensure that all VPC traffic flows through an expected path."
  338. alarm_actions = ["arn:${var.aws_partition}:sns:${var.aws_region}:${local.c2_account}:account-alerts"]
  339. insufficient_data_actions = []
  340. }