section-3.tf 19 KB

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