cds-snc / url-shortener

An API written in Python that shortens URLs
MIT License
4 stars 1 forks source link

release: infrastructure v1.0.3 #311

Closed patheard closed 1 year ago

patheard commented 1 year ago

Summary

Related

github-actions[bot] commented 1 year ago

Production: network

✅   Terraform Init: success ✅   Terraform Validate: success ✅   Terraform Format: success ✅   Terraform Plan: success ✅   Conftest: success

⚠️   Warning: resources will be destroyed by this change!

Plan: 0 to add, 0 to change, 5 to destroy
Show summary | CHANGE | NAME | |--------|--------------------------------------------------------------------------------------------------------| | delete | `module.url_shortener_vpc.aws_cloudwatch_log_group.flow_logs[0]` | | | `module.url_shortener_vpc.aws_flow_log.flow_logs[0]` | | | `module.url_shortener_vpc.aws_iam_policy.vpc_metrics_flow_logs_write_policy[0]` | | | `module.url_shortener_vpc.aws_iam_role.flow_logs[0]` | | | `module.url_shortener_vpc.aws_iam_role_policy_attachment.vpc_metrics_flow_logs_write_policy_attach[0]` |
Show plan ```terraform Resource actions are indicated with the following symbols: - destroy Terraform will perform the following actions: # module.url_shortener_vpc.aws_cloudwatch_log_group.flow_logs[0] will be destroyed # (because index [0] is out of range for count) - resource "aws_cloudwatch_log_group" "flow_logs" { - arn = "arn:aws:logs:ca-central-1:806721586252:log-group:url-shortener_flow_logs" -> null - id = "url-shortener_flow_logs" -> null - name = "url-shortener_flow_logs" -> null - retention_in_days = 30 -> null - skip_destroy = false -> null - tags = { - "CostCentre" = "url-shortener-production" - "Terraform" = "true" } -> null - tags_all = { - "CostCentre" = "url-shortener-production" - "Terraform" = "true" } -> null } # module.url_shortener_vpc.aws_flow_log.flow_logs[0] will be destroyed # (because index [0] is out of range for count) - resource "aws_flow_log" "flow_logs" { - arn = "arn:aws:ec2:ca-central-1:806721586252:vpc-flow-log/fl-01f1bd66349f15df2" -> null - iam_role_arn = "arn:aws:iam::806721586252:role/url-shortener_flow_logs" -> null - id = "fl-01f1bd66349f15df2" -> null - log_destination = "arn:aws:logs:ca-central-1:806721586252:log-group:url-shortener_flow_logs" -> null - log_destination_type = "cloud-watch-logs" -> null - log_format = "${version} ${account-id} ${interface-id} ${srcaddr} ${dstaddr} ${srcport} ${dstport} ${protocol} ${packets} ${bytes} ${start} ${end} ${action} ${log-status}" -> null - log_group_name = "url-shortener_flow_logs" -> null - max_aggregation_interval = 600 -> null - tags = { - "CostCentre" = "url-shortener-production" - "Terraform" = "true" } -> null - tags_all = { - "CostCentre" = "url-shortener-production" - "Terraform" = "true" } -> null - traffic_type = "ALL" -> null - vpc_id = "vpc-0009bdb7c0677ef88" -> null } # module.url_shortener_vpc.aws_iam_policy.vpc_metrics_flow_logs_write_policy[0] will be destroyed # (because index [0] is out of range for count) - resource "aws_iam_policy" "vpc_metrics_flow_logs_write_policy" { - arn = "arn:aws:iam::806721586252:policy/VpcMetricsFlowLogsWrite" -> null - description = "IAM policy for writing flow logs in CloudWatch" -> null - id = "arn:aws:iam::806721586252:policy/VpcMetricsFlowLogsWrite" -> null - name = "VpcMetricsFlowLogsWrite" -> null - path = "/" -> null - policy = jsonencode( { - Statement = [ - { - Action = [ - "logs:PutLogEvents", - "logs:DescribeLogStreams", - "logs:DescribeLogGroups", - "logs:CreateLogStream", ] - Effect = "Allow" - Resource = [ - "arn:aws:logs:ca-central-1:806721586252:log-group:url-shortener_flow_logs:log-stream:*", - "arn:aws:logs:ca-central-1:806721586252:log-group:url-shortener_flow_logs", ] - Sid = "" }, ] - Version = "2012-10-17" } ) -> null - policy_id = "ANPA3XVC2QRGAA2IML7ZG" -> null - tags = { - "CostCentre" = "url-shortener-production" - "Terraform" = "true" } -> null - tags_all = { - "CostCentre" = "url-shortener-production" - "Terraform" = "true" } -> null } # module.url_shortener_vpc.aws_iam_role.flow_logs[0] will be destroyed # (because index [0] is out of range for count) - resource "aws_iam_role" "flow_logs" { - arn = "arn:aws:iam::806721586252:role/url-shortener_flow_logs" -> null - assume_role_policy = jsonencode( { - Statement = [ - { - Action = "sts:AssumeRole" - Effect = "Allow" - Principal = { - Service = "vpc-flow-logs.amazonaws.com" } - Sid = "" }, ] - Version = "2012-10-17" } ) -> null - create_date = "2023-04-25T19:50:21Z" -> null - force_detach_policies = false -> null - id = "url-shortener_flow_logs" -> null - managed_policy_arns = [ - "arn:aws:iam::806721586252:policy/VpcMetricsFlowLogsWrite", ] -> null - max_session_duration = 3600 -> null - name = "url-shortener_flow_logs" -> null - path = "/" -> null - tags = { - "CostCentre" = "url-shortener-production" - "Terraform" = "true" } -> null - tags_all = { - "CostCentre" = "url-shortener-production" - "Terraform" = "true" } -> null - unique_id = "AROA3XVC2QRGKBBPPRVGF" -> null } # module.url_shortener_vpc.aws_iam_role_policy_attachment.vpc_metrics_flow_logs_write_policy_attach[0] will be destroyed # (because index [0] is out of range for count) - resource "aws_iam_role_policy_attachment" "vpc_metrics_flow_logs_write_policy_attach" { - id = "url-shortener_flow_logs-20230425195022577300000001" -> null - policy_arn = "arn:aws:iam::806721586252:policy/VpcMetricsFlowLogsWrite" -> null - role = "url-shortener_flow_logs" -> null } Plan: 0 to add, 0 to change, 5 to destroy. ───────────────────────────────────────────────────────────────────────────── Saved the plan to: plan.tfplan To perform exactly these actions, run the following command to apply: terraform apply "plan.tfplan" Releasing state lock. This may take a few moments... ```
Show Conftest results ```sh WARN - plan.json - main - Missing Common Tags: ["aws_security_group.api"] WARN - plan.json - main - Missing Common Tags: ["aws_vpc_endpoint.dynamodb"] WARN - plan.json - main - Missing Common Tags: ["aws_vpc_endpoint.logs"] WARN - plan.json - main - Missing Common Tags: ["aws_vpc_endpoint.s3"] 21 tests, 17 passed, 4 warnings, 0 failures, 0 exceptions ```
github-actions[bot] commented 1 year ago

Production: backup_plan

✅   Terraform Init: success ✅   Terraform Validate: success ✅   Terraform Format: success ✅   Terraform Plan: success ✅   Conftest: success

Plan: 5 to add, 0 to change, 0 to destroy
Show summary | CHANGE | NAME | |--------|------------------------------------------| | add | `aws_backup_plan.backup_plan_default` | | | `aws_backup_selection.selection_default` | | | `aws_backup_vault.vault` | | | `aws_backup_vault_policy.vault_policy` | | | `aws_iam_role.role_backup` |
Show plan ```terraform Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # aws_backup_plan.backup_plan_default will be created + resource "aws_backup_plan" "backup_plan_default" { + arn = (known after apply) + id = (known after apply) + name = "backup_plan_default" + tags = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + tags_all = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + version = (known after apply) + rule { + completion_window = 180 + enable_continuous_backup = false + rule_name = "backup_rule_default" + schedule = "cron(0 12 * * ? *)" + start_window = 60 + target_vault_name = "vault" + lifecycle { + cold_storage_after = 30 + delete_after = 120 } } } # aws_backup_selection.selection_default will be created + resource "aws_backup_selection" "selection_default" { + iam_role_arn = (known after apply) + id = (known after apply) + name = "backup_selection_default" + not_resources = (known after apply) + plan_id = (known after apply) + resources = [ + "arn:aws:dynamodb:ca-central-1:806721586252:table/url_shortener", ] + condition { + string_equals { + key = (known after apply) + value = (known after apply) } + string_like { + key = (known after apply) + value = (known after apply) } + string_not_equals { + key = (known after apply) + value = (known after apply) } + string_not_like { + key = (known after apply) + value = (known after apply) } } + selection_tag { + key = "backup_plan" + type = "STRINGEQUALS" + value = "default" } } # aws_backup_vault.vault will be created + resource "aws_backup_vault" "vault" { + arn = (known after apply) + force_destroy = false + id = (known after apply) + kms_key_arn = (known after apply) + name = "vault" + recovery_points = (known after apply) + tags = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + tags_all = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } } # aws_backup_vault_policy.vault_policy will be created + resource "aws_backup_vault_policy" "vault_policy" { + backup_vault_arn = (known after apply) + backup_vault_name = "vault" + id = (known after apply) + policy = (known after apply) } # aws_iam_role.role_backup will be created + resource "aws_iam_role" "role_backup" { + arn = (known after apply) + assume_role_policy = jsonencode( { + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "backup.amazonaws.com" } + Sid = "" }, ] + Version = "2012-10-17" } ) + create_date = (known after apply) + force_detach_policies = false + id = (known after apply) + managed_policy_arns = [ + "arn:aws:iam::aws:policy/AWSBackupServiceRolePolicyForS3Backup", + "arn:aws:iam::aws:policy/AWSBackupServiceRolePolicyForS3Restore", + "arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup", + "arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForRestores", ] + max_session_duration = 3600 + name = "aws-backup-service-role-ca-central-1" + name_prefix = (known after apply) + path = "/" + role_last_used = (known after apply) + tags = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + tags_all = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + unique_id = (known after apply) + inline_policy { + name = (known after apply) + policy = (known after apply) } } Plan: 5 to add, 0 to change, 0 to destroy. ───────────────────────────────────────────────────────────────────────────── Saved the plan to: plan.tfplan To perform exactly these actions, run the following command to apply: terraform apply "plan.tfplan" Releasing state lock. This may take a few moments... ```
Show Conftest results ```sh 18 tests, 18 passed, 0 warnings, 0 failures, 0 exceptions ```
github-actions[bot] commented 1 year ago

Production: alarms

✅   Terraform Init: success ✅   Terraform Validate: success ✅   Terraform Format: success ✅   Terraform Plan: success ✅   Conftest: success

Plan: 24 to add, 0 to change, 0 to destroy
Show summary | CHANGE | NAME | |--------|-------------------------------------------------------------------------------------| | add | `aws_cloudwatch_log_metric_filter.url_shortener_api_error` | | | `aws_cloudwatch_log_metric_filter.url_shortener_api_suspicious` | | | `aws_cloudwatch_log_metric_filter.url_shortener_api_warning` | | | `aws_cloudwatch_metric_alarm.cloudfront_ddos` | | | `aws_cloudwatch_metric_alarm.route53_ddos` | | | `aws_cloudwatch_metric_alarm.url_shoretener_api_suspicious` | | | `aws_cloudwatch_metric_alarm.url_shoretener_api_warning` | | | `aws_cloudwatch_metric_alarm.url_shortener_api_error` | | | `aws_cloudwatch_query_definition.api_errors` | | | `aws_cloudwatch_query_definition.api_suspicious` | | | `aws_cloudwatch_query_definition.api_warnings` | | | `aws_shield_protection.cloudfront_api` | | | `aws_shield_protection.route53_hosted_zone` | | | `aws_sns_topic.cloudwatch_warning` | | | `aws_sns_topic.cloudwatch_warning_us_east` | | | `aws_sns_topic_subscription.alert_warning` | | | `aws_sns_topic_subscription.alert_warning_us_east` | | | `module.cloudwatch_alarms_slack.aws_cloudwatch_log_group.notify_slack_lambda` | | | `module.cloudwatch_alarms_slack.aws_iam_policy.notify_slack_lambda` | | | `module.cloudwatch_alarms_slack.aws_iam_role.notify_slack_lambda` | | | `module.cloudwatch_alarms_slack.aws_iam_role_policy_attachment.notify_slack_lambda` | | | `module.cloudwatch_alarms_slack.aws_lambda_function.notify_slack` | | | `module.cloudwatch_alarms_slack.aws_lambda_permission.notify_slack[0]` | | | `module.cloudwatch_alarms_slack.aws_lambda_permission.notify_slack[1]` |
Show plan ```terraform Resource actions are indicated with the following symbols: + create <= read (data resources) Terraform will perform the following actions: # aws_cloudwatch_log_metric_filter.url_shortener_api_error will be created + resource "aws_cloudwatch_log_metric_filter" "url_shortener_api_error" { + id = (known after apply) + log_group_name = "/aws/lambda/url-shortener-api" + name = "ErrorLoggedAPI" + pattern = "?ERROR ?Error ?error ?failed" + metric_transformation { + name = "ErrorLoggedAPI" + namespace = "UrlShortener" + unit = "None" + value = "1" } } # aws_cloudwatch_log_metric_filter.url_shortener_api_suspicious will be created + resource "aws_cloudwatch_log_metric_filter" "url_shortener_api_suspicious" { + id = (known after apply) + log_group_name = "/aws/lambda/url-shortener-api" + name = "Suspicious" + pattern = "SUSPICIOUS" + metric_transformation { + name = "Suspicious" + namespace = "UrlShortener" + unit = "None" + value = "1" } } # aws_cloudwatch_log_metric_filter.url_shortener_api_warning will be created + resource "aws_cloudwatch_log_metric_filter" "url_shortener_api_warning" { + id = (known after apply) + log_group_name = "/aws/lambda/url-shortener-api" + name = "WarningLoggedAPI" + pattern = "?WARNING ?Warning ?warning" + metric_transformation { + name = "WarningLoggedAPI" + namespace = "UrlShortener" + unit = "None" + value = "1" } } # aws_cloudwatch_metric_alarm.cloudfront_ddos will be created + resource "aws_cloudwatch_metric_alarm" "cloudfront_ddos" { + actions_enabled = true + alarm_actions = (known after apply) + alarm_description = "DDoS detection for CloudFront" + alarm_name = "DDoS CloudFront" + arn = (known after apply) + comparison_operator = "GreaterThanThreshold" + dimensions = { + "ResourceArn" = "arn:aws:cloudfront::123456789012:distribution/A2Z6W4OZAEKEKP" } + evaluate_low_sample_count_percentiles = (known after apply) + evaluation_periods = 1 + id = (known after apply) + metric_name = "DDoSDetected" + namespace = "AWS/DDoSProtection" + ok_actions = (known after apply) + period = 60 + statistic = "Sum" + tags_all = (known after apply) + threshold = 0 + treat_missing_data = "notBreaching" } # aws_cloudwatch_metric_alarm.route53_ddos will be created + resource "aws_cloudwatch_metric_alarm" "route53_ddos" { + actions_enabled = true + alarm_actions = (known after apply) + alarm_description = "DDoS detection for Route53" + alarm_name = "DDoS Route53" + arn = (known after apply) + comparison_operator = "GreaterThanThreshold" + dimensions = { + "ResourceArn" = "arn:aws:route53:::hostedzone/Z0129461HK2TKOF3BTTF" } + evaluate_low_sample_count_percentiles = (known after apply) + evaluation_periods = 1 + id = (known after apply) + metric_name = "DDoSDetected" + namespace = "AWS/DDoSProtection" + ok_actions = (known after apply) + period = 60 + statistic = "Sum" + tags_all = (known after apply) + threshold = 0 + treat_missing_data = "notBreaching" } # aws_cloudwatch_metric_alarm.url_shoretener_api_suspicious will be created + resource "aws_cloudwatch_metric_alarm" "url_shoretener_api_suspicious" { + actions_enabled = true + alarm_actions = (known after apply) + alarm_description = "Suspicious activity by users of the URL Shortener API lambda function over 5 minutes" + alarm_name = "URL Shortener API Suspicious" + arn = (known after apply) + comparison_operator = "GreaterThanOrEqualToThreshold" + evaluate_low_sample_count_percentiles = (known after apply) + evaluation_periods = 1 + id = (known after apply) + metric_name = "Suspicious" + namespace = "UrlShortener" + ok_actions = (known after apply) + period = 300 + statistic = "Sum" + tags_all = (known after apply) + threshold = 5 + treat_missing_data = "notBreaching" } # aws_cloudwatch_metric_alarm.url_shoretener_api_warning will be created + resource "aws_cloudwatch_metric_alarm" "url_shoretener_api_warning" { + actions_enabled = true + alarm_actions = (known after apply) + alarm_description = "Warnings logged by the URL Shortener API lambda function" + alarm_name = "URL Shortener API Warnings" + arn = (known after apply) + comparison_operator = "GreaterThanOrEqualToThreshold" + evaluate_low_sample_count_percentiles = (known after apply) + evaluation_periods = 1 + id = (known after apply) + metric_name = "WarningLoggedAPI" + namespace = "UrlShortener" + ok_actions = (known after apply) + period = 60 + statistic = "Sum" + tags_all = (known after apply) + threshold = 10 + treat_missing_data = "notBreaching" } # aws_cloudwatch_metric_alarm.url_shortener_api_error will be created + resource "aws_cloudwatch_metric_alarm" "url_shortener_api_error" { + actions_enabled = true + alarm_actions = (known after apply) + alarm_description = "Errors logged by the URL Shortener API lambda function" + alarm_name = "URL Shortener API Errors" + arn = (known after apply) + comparison_operator = "GreaterThanOrEqualToThreshold" + evaluate_low_sample_count_percentiles = (known after apply) + evaluation_periods = 1 + id = (known after apply) + metric_name = "ErrorLoggedAPI" + namespace = "UrlShortener" + ok_actions = (known after apply) + period = 60 + statistic = "Sum" + tags_all = (known after apply) + threshold = 1 + treat_missing_data = "notBreaching" } # aws_cloudwatch_query_definition.api_errors will be created + resource "aws_cloudwatch_query_definition" "api_errors" { + id = (known after apply) + log_group_names = [ + "/aws/lambda/url-shortener-api", ] + name = "Errors API" + query_definition_id = (known after apply) + query_string = <<-EOT fields @timestamp, @message, @logStream | filter @message like /(?i)ERROR|FAILED/ | sort @timestamp desc | limit 20 EOT } # aws_cloudwatch_query_definition.api_suspicious will be created + resource "aws_cloudwatch_query_definition" "api_suspicious" { + id = (known after apply) + log_group_names = [ + "/aws/lambda/url-shortener-api", ] + name = "Suspicious activity API" + query_definition_id = (known after apply) + query_string = <<-EOT fields @timestamp, @message, @logStream | filter @message like /SUSPICIOUS/ | sort @timestamp desc | limit 20 EOT } # aws_cloudwatch_query_definition.api_warnings will be created + resource "aws_cloudwatch_query_definition" "api_warnings" { + id = (known after apply) + log_group_names = [ + "/aws/lambda/url-shortener-api", ] + name = "Warnings API" + query_definition_id = (known after apply) + query_string = <<-EOT fields @timestamp, @message, @logStream | filter @message like /WARNING/ | sort @timestamp desc | limit 20 EOT } # aws_shield_protection.cloudfront_api will be created + resource "aws_shield_protection" "cloudfront_api" { + arn = (known after apply) + id = (known after apply) + name = "CloudFrontAPI" + resource_arn = "arn:aws:cloudfront::123456789012:distribution/A2Z6W4OZAEKEKP" + tags = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + tags_all = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } } # aws_shield_protection.route53_hosted_zone will be created + resource "aws_shield_protection" "route53_hosted_zone" { + arn = (known after apply) + id = (known after apply) + name = "Route53HostedZone" + resource_arn = "arn:aws:route53:::hostedzone/Z0129461HK2TKOF3BTTF" + tags = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + tags_all = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } } # aws_sns_topic.cloudwatch_warning will be created + resource "aws_sns_topic" "cloudwatch_warning" { + arn = (known after apply) + content_based_deduplication = false + fifo_topic = false + id = (known after apply) + name = "cloudwatch-alarms-warning" + name_prefix = (known after apply) + owner = (known after apply) + policy = (known after apply) + signature_version = (known after apply) + tags = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + tags_all = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + tracing_config = (known after apply) } # aws_sns_topic.cloudwatch_warning_us_east will be created + resource "aws_sns_topic" "cloudwatch_warning_us_east" { + arn = (known after apply) + content_based_deduplication = false + fifo_topic = false + id = (known after apply) + name = "cloudwatch-alarms-warning" + name_prefix = (known after apply) + owner = (known after apply) + policy = (known after apply) + signature_version = (known after apply) + tags = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + tags_all = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + tracing_config = (known after apply) } # aws_sns_topic_subscription.alert_warning will be created + resource "aws_sns_topic_subscription" "alert_warning" { + arn = (known after apply) + confirmation_timeout_in_minutes = 1 + confirmation_was_authenticated = (known after apply) + endpoint = (known after apply) + endpoint_auto_confirms = false + filter_policy_scope = (known after apply) + id = (known after apply) + owner_id = (known after apply) + pending_confirmation = (known after apply) + protocol = "lambda" + raw_message_delivery = false + topic_arn = (known after apply) } # aws_sns_topic_subscription.alert_warning_us_east will be created + resource "aws_sns_topic_subscription" "alert_warning_us_east" { + arn = (known after apply) + confirmation_timeout_in_minutes = 1 + confirmation_was_authenticated = (known after apply) + endpoint = (known after apply) + endpoint_auto_confirms = false + filter_policy_scope = (known after apply) + id = (known after apply) + owner_id = (known after apply) + pending_confirmation = (known after apply) + protocol = "lambda" + raw_message_delivery = false + topic_arn = (known after apply) } # module.cloudwatch_alarms_slack.data.aws_iam_policy_document.notify_slack_lambda will be read during apply # (config refers to values not yet known) <= data "aws_iam_policy_document" "notify_slack_lambda" { + id = (known after apply) + json = (known after apply) + statement { + actions = [ + "logs:CreateLogStream", + "logs:PutLogEvents", ] + effect = "Allow" + resources = [ + (known after apply), ] } } # module.cloudwatch_alarms_slack.aws_cloudwatch_log_group.notify_slack_lambda will be created + resource "aws_cloudwatch_log_group" "notify_slack_lambda" { + arn = (known after apply) + id = (known after apply) + name = "/aws/lambda/url-shortener-cloudwatch-alarms-slack" + name_prefix = (known after apply) + retention_in_days = 14 + skip_destroy = false + tags = { + "CostCentre" = "url-shortener-production" } + tags_all = { + "CostCentre" = "url-shortener-production" } } # module.cloudwatch_alarms_slack.aws_iam_policy.notify_slack_lambda will be created + resource "aws_iam_policy" "notify_slack_lambda" { + arn = (known after apply) + id = (known after apply) + name = "NotifySlackLambda-url-shortener-cloudwatch-alarms-slack" + name_prefix = (known after apply) + path = "/" + policy = (known after apply) + policy_id = (known after apply) + tags_all = (known after apply) } # module.cloudwatch_alarms_slack.aws_iam_role.notify_slack_lambda will be created + resource "aws_iam_role" "notify_slack_lambda" { + arn = (known after apply) + assume_role_policy = jsonencode( { + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "lambda.amazonaws.com" } + Sid = "" }, ] + Version = "2012-10-17" } ) + create_date = (known after apply) + force_detach_policies = false + id = (known after apply) + managed_policy_arns = (known after apply) + max_session_duration = 3600 + name = "NotifySlackLambda-url-shortener-cloudwatch-alarms-slack" + name_prefix = (known after apply) + path = "/" + role_last_used = (known after apply) + tags_all = (known after apply) + unique_id = (known after apply) + inline_policy { + name = (known after apply) + policy = (known after apply) } } # module.cloudwatch_alarms_slack.aws_iam_role_policy_attachment.notify_slack_lambda will be created + resource "aws_iam_role_policy_attachment" "notify_slack_lambda" { + id = (known after apply) + policy_arn = (known after apply) + role = "NotifySlackLambda-url-shortener-cloudwatch-alarms-slack" } # module.cloudwatch_alarms_slack.aws_lambda_function.notify_slack will be created + resource "aws_lambda_function" "notify_slack" { + architectures = (known after apply) + arn = (known after apply) + description = "Lambda function to post CloudWatch alarm notifications to a Slack channel." + filename = "/tmp/notify_slack.py.zip" + function_name = "url-shortener-cloudwatch-alarms-slack" + handler = "notify_slack.lambda_handler" + id = (known after apply) + invoke_arn = (known after apply) + last_modified = (known after apply) + memory_size = 128 + package_type = "Zip" + publish = false + qualified_arn = (known after apply) + qualified_invoke_arn = (known after apply) + reserved_concurrent_executions = -1 + role = (known after apply) + runtime = "python3.8" + signing_job_arn = (known after apply) + signing_profile_version_arn = (known after apply) + skip_destroy = false + source_code_hash = "iC0Ta5b8fs9u6i/c3LA3/Tk8BUHfS6Jgq4NF8At0CBo=" + source_code_size = (known after apply) + tags = { + "CostCentre" = "url-shortener-production" } + tags_all = { + "CostCentre" = "url-shortener-production" } + timeout = 30 + version = (known after apply) + environment { + variables = { + "LOG_EVENTS" = "True" + "PROJECT_NAME" = "url-shortener" + "SLACK_WEBHOOK_URL" = (sensitive value) } } + ephemeral_storage { + size = (known after apply) } + tracing_config { + mode = (known after apply) } } # module.cloudwatch_alarms_slack.aws_lambda_permission.notify_slack[0] will be created + resource "aws_lambda_permission" "notify_slack" { + action = "lambda:InvokeFunction" + function_name = "url-shortener-cloudwatch-alarms-slack" + id = (known after apply) + principal = "sns.amazonaws.com" + source_arn = (known after apply) + statement_id = "AllowExecutionFromSNS-url-shortener-cloudwatch-alarms-slack-0" + statement_id_prefix = (known after apply) } # module.cloudwatch_alarms_slack.aws_lambda_permission.notify_slack[1] will be created + resource "aws_lambda_permission" "notify_slack" { + action = "lambda:InvokeFunction" + function_name = "url-shortener-cloudwatch-alarms-slack" + id = (known after apply) + principal = "sns.amazonaws.com" + source_arn = (known after apply) + statement_id = "AllowExecutionFromSNS-url-shortener-cloudwatch-alarms-slack-1" + statement_id_prefix = (known after apply) } Plan: 24 to add, 0 to change, 0 to destroy. ───────────────────────────────────────────────────────────────────────────── Saved the plan to: plan.tfplan To perform exactly these actions, run the following command to apply: terraform apply "plan.tfplan" Releasing state lock. This may take a few moments... ```
Show Conftest results ```sh WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.cloudfront_ddos"] WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.route53_ddos"] WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.url_shoretener_api_suspicious"] WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.url_shoretener_api_warning"] WARN - plan.json - main - Missing Common Tags: ["aws_cloudwatch_metric_alarm.url_shortener_api_error"] WARN - plan.json - main - Missing Common Tags: ["module.cloudwatch_alarms_slack.aws_cloudwatch_log_group.notify_slack_lambda"] WARN - plan.json - main - Missing Common Tags: ["module.cloudwatch_alarms_slack.aws_iam_policy.notify_slack_lambda"] WARN - plan.json - main - Missing Common Tags: ["module.cloudwatch_alarms_slack.aws_iam_role.notify_slack_lambda"] WARN - plan.json - main - Missing Common Tags: ["module.cloudwatch_alarms_slack.aws_lambda_function.notify_slack"] WARN - plan.json - main - Cloudwatch log metric pattern is invalid: ["aws_cloudwatch_log_metric_filter.url_shortener_api_error"] WARN - plan.json - main - Cloudwatch log metric pattern is invalid: ["aws_cloudwatch_log_metric_filter.url_shortener_api_warning"] 27 tests, 16 passed, 11 warnings, 0 failures, 0 exceptions ```
github-actions[bot] commented 1 year ago

Production: conformance_pack

✅   Terraform Init: success ✅   Terraform Validate: success ✅   Terraform Format: success ✅   Terraform Plan: success ✅   Conftest: success

Plan: 5 to add, 0 to change, 0 to destroy
Show summary | CHANGE | NAME | |--------|----------------------------------------------------------------------------| | add | `module.conformance_pack.aws_config_conformance_pack.cds_conformance_pack` | | | `module.conformance_pack.aws_s3_object.conformace_pack_yaml` | | | `module.conformance_pack.module.s3.aws_s3_bucket.this` | | | `module.conformance_pack.module.s3.aws_s3_bucket_public_access_block.this` | | | `module.conformance_pack.random_uuid.bucket_suffix` |

✂   Warning: plan has been truncated! See the full plan in the logs.

Show plan ```terraform Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # module.conformance_pack.aws_config_conformance_pack.cds_conformance_pack will be created + resource "aws_config_conformance_pack" "cds_conformance_pack" { + arn = (known after apply) + id = (known after apply) + name = "CDS-Conformance-Pack" + template_s3_uri = (known after apply) + input_parameter { + parameter_name = "AccessKeysRotatedParamMaxAccessKeyAge" + parameter_value = "90" } + input_parameter { + parameter_name = "CloudwatchAlarmActionCheckParamAlarmActionRequired" + parameter_value = "true" } + input_parameter { + parameter_name = "CloudwatchAlarmActionCheckParamInsufficientDataActionRequired" + parameter_value = "false" } + input_parameter { + parameter_name = "CloudwatchAlarmActionCheckParamOkActionRequired" + parameter_value = "false" } + input_parameter { + parameter_name = "ElbPredefinedSecurityPolicySslCheckParamPredefinedPolicyName" + parameter_value = "TLS-1-2-2017-01" } + input_parameter { + parameter_name = "IamCustomerPolicyBlockedKmsActionsParamBlockedActionsPatterns" + parameter_value = "kms:*, kms:Decrypt, kms:ReEncrypt*" } + input_parameter { + parameter_name = "IamInlinePolicyBlockedKmsActionsParamBlockedActionsPatterns" + parameter_value = "kms:*, kms:Decrypt, kms:ReEncrypt*" } + input_parameter { + parameter_name = "IamPasswordPolicyParamMaxPasswordAge" + parameter_value = "90" } + input_parameter { + parameter_name = "IamPasswordPolicyParamMinimumPasswordLength" + parameter_value = "14" } + input_parameter { + parameter_name = "IamPasswordPolicyParamPasswordReusePrevention" + parameter_value = "24" } + input_parameter { + parameter_name = "IamPasswordPolicyParamRequireLowercaseCharacters" + parameter_value = "true" } + input_parameter { + parameter_name = "IamPasswordPolicyParamRequireNumbers" + parameter_value = "true" } + input_parameter { + parameter_name = "IamPasswordPolicyParamRequireSymbols" + parameter_value = "true" } + input_parameter { + parameter_name = "IamPasswordPolicyParamRequireUppercaseCharacters" + parameter_value = "true" } + input_parameter { + parameter_name = "IamUserUnusedCredentialsCheckParamMaxCredentialUsageAge" + parameter_value = "90" } + input_parameter { + parameter_name = "InternetGatewayAuthorizedVpcOnlyParamAuthorizedVpcIds" + parameter_value = "vpc-0009bdb7c0677ef88" } + input_parameter { + parameter_name = "RedshiftClusterConfigurationCheckParamClusterDbEncrypted" + parameter_value = "true" } + input_parameter { + parameter_name = "RedshiftClusterConfigurationCheckParamLoggingEnabled" + parameter_value = "true" } + input_parameter { + parameter_name = "RedshiftClusterMaintenancesettingsCheckParamAllowVersionUpgrade" + parameter_value = "true" } + input_parameter { + parameter_name = "RestrictedIncomingTrafficParamBlockedPort1" + parameter_value = "20" } + input_parameter { + parameter_name = "RestrictedIncomingTrafficParamBlockedPort2" + parameter_value = "21" } + input_parameter { + parameter_name = "RestrictedIncomingTrafficParamBlockedPort3" + parameter_value = "3389" } + input_parameter { + parameter_name = "RestrictedIncomingTrafficParamBlockedPort4" + parameter_value = "3306" } + input_parameter { + parameter_name = "RestrictedIncomingTrafficParamBlockedPort5" + parameter_value = "4333" } + input_parameter { + parameter_name = "VpcSgOpenOnlyToAuthorizedPortsParamAuthorizedTcpPorts" + parameter_value = "443" } } # module.conformance_pack.aws_s3_object.conformace_pack_yaml will be created + resource "aws_s3_object" "conformace_pack_yaml" { + acl = "private" + bucket = (known after apply) + bucket_key_enabled = (known after apply) + content = <<-EOT "Conditions": "accessKeysRotatedParamMaxAccessKeyAge": "Fn::Not": - "Fn::Equals": - "" - "Ref": "AccessKeysRotatedParamMaxAccessKeyAge" "cloudwatchAlarmActionCheckParamAlarmActionRequired": "Fn::Not": - "Fn::Equals": - "" - "Ref": "CloudwatchAlarmActionCheckParamAlarmActionRequired" "cloudwatchAlarmActionCheckParamInsufficientDataActionRequired": "Fn::Not": - "Fn::Equals": - "" - "Ref": "CloudwatchAlarmActionCheckParamInsufficientDataActionRequired" "cloudwatchAlarmActionCheckParamOkActionRequired": "Fn::Not": - "Fn::Equals": - "" - "Ref": "CloudwatchAlarmActionCheckParamOkActionRequired" "elbPredefinedSecurityPolicySslCheckParamPredefinedPolicyName": "Fn::Not": - "Fn::Equals": - "" - "Ref": "ElbPredefinedSecurityPolicySslCheckParamPredefinedPolicyName" "iamCustomerPolicyBlockedKmsActionsParamBlockedActionsPatterns": "Fn::Not": - "Fn::Equals": - "" - "Ref": "IamCustomerPolicyBlockedKmsActionsParamBlockedActionsPatterns" "iamInlinePolicyBlockedKmsActionsParamBlockedActionsPatterns": "Fn::Not": - "Fn::Equals": - "" - "Ref": "IamInlinePolicyBlockedKmsActionsParamBlockedActionsPatterns" "iamPasswordPolicyParamMaxPasswordAge": "Fn::Not": - "Fn::Equals": - "" - "Ref": "IamPasswordPolicyParamMaxPasswordAge" "iamPasswordPolicyParamMinimumPasswordLength": "Fn::Not": - "Fn::Equals": - "" - "Ref": "IamPasswordPolicyParamMinimumPasswordLength" "iamPasswordPolicyParamPasswordReusePrevention": "Fn::Not": - "Fn::Equals": - "" - "Ref": "IamPasswordPolicyParamPasswordReusePrevention" "iamPasswordPolicyParamRequireLowercaseCharacters": "Fn::Not": - "Fn::Equals": - "" - "Ref": "IamPasswordPolicyParamRequireLowercaseCharacters" "iamPasswordPolicyParamRequireNumbers": "Fn::Not": - "Fn::Equals": - "" - "Ref": "IamPasswordPolicyParamRequireNumbers" "iamPasswordPolicyParamRequireSymbols": "Fn::Not": - "Fn::Equals": - "" - "Ref": "IamPasswordPolicyParamRequireSymbols" "iamPasswordPolicyParamRequireUppercaseCharacters": "Fn::Not": - "Fn::Equals": - "" - "Ref": "IamPasswordPolicyParamRequireUppercaseCharacters" "iamUserUnusedCredentialsCheckParamMaxCredentialUsageAge": "Fn::Not": - "Fn::Equals": - "" - "Ref": "IamUserUnusedCredentialsCheckParamMaxCredentialUsageAge" "internetGatewayAuthorizedVpcOnlyParamAuthorizedVpcIds": "Fn::Not": - "Fn::Equals": - "" - "Ref": "InternetGatewayAuthorizedVpcOnlyParamAuthorizedVpcIds" "redshiftClusterConfigurationCheckParamClusterDbEncrypted": "Fn::Not": - "Fn::Equals": - "" - "Ref": "RedshiftClusterConfigurationCheckParamClusterDbEncrypted" "redshiftClusterConfigurationCheckParamLoggingEnabled": "Fn::Not": - "Fn::Equals": - "" - "Ref": "RedshiftClusterConfigurationCheckParamLoggingEnabled" "redshiftClusterMaintenancesettingsCheckParamAllowVersionUpgrade": "Fn::Not": - "Fn::Equals": - "" - "Ref": "RedshiftClusterMaintenancesettingsCheckParamAllowVersionUpgrade" "restrictedIncomingTrafficParamBlockedPort1": "Fn::Not": - "Fn::Equals": - "" - "Ref": "RestrictedIncomingTrafficParamBlockedPort1" "restrictedIncomingTrafficParamBlockedPort2": "Fn::Not": - "Fn::Equals": - "" - "Ref": "RestrictedIncomingTrafficParamBlockedPort2" "restrictedIncomingTrafficParamBlockedPort3": "Fn::Not": - "Fn::Equals": - "" - "Ref": "RestrictedIncomingTrafficParamBlockedPort3" "restrictedIncomingTrafficParamBlockedPort4": "Fn::Not": - "Fn::Equals": - "" - "Ref": "RestrictedIncomingTrafficParamBlockedPort4" "restrictedIncomingTrafficParamBlockedPort5": "Fn::Not": - "Fn::Equals": - "" - "Ref": "RestrictedIncomingTrafficParamBlockedPort5" "vpcSgOpenOnlyToAuthorizedPortsParamAuthorizedTcpPorts": "Fn::Not": - "Fn::Equals": - "" - "Ref": "VpcSgOpenOnlyToAuthorizedPortsParamAuthorizedTcpPorts" "Parameters": "AccessKeysRotatedParamMaxAccessKeyAge": "Default": "90" "Type": "String" "CloudwatchAlarmActionCheckParamAlarmActionRequired": "Default": "true" "Type": "String" "CloudwatchAlarmActionCheckParamInsufficientDataActionRequired": "Default": "true" "Type": "String" "CloudwatchAlarmActionCheckParamOkActionRequired": "Default": "false" "Type": "String" "ElbPredefinedSecurityPolicySslCheckParamPredefinedPolicyName": "Default": "TLS-1-2-2017-01" "Type": "String" "IamCustomerPolicyBlockedKmsActionsParamBlockedActionsPatterns": "Default": "kms:*, kms:Decrypt, kms:ReEncrypt*" "Type": "String" "IamInlinePolicyBlockedKmsActionsParamBlockedActionsPatterns": "Default": "kms:*, kms:Decrypt, kms:ReEncrypt*" "Type": "String" "IamPasswordPolicyParamMaxPasswordAge": "Default": "90" "Type": "String" "IamPasswordPolicyParamMinimumPasswordLength": "Default": "14" "Type": "String" "IamPasswordPolicyParamPasswordReusePrevention": "Default": "24" "Type": "String" "IamPasswordPolicyParamRequireLowercaseCharacters": "Default": "true" "Type": "String" "IamPasswordPolicyParamRequireNumbers": "Default": "true" "Type": "String" "IamPasswordPolicyParamRequireSymbols": "Default": "true" "Type": "String" "IamPasswordPolicyParamRequireUppercaseCharacters": "Default": "true" "Type": "String" "IamUserUnusedCredentialsCheckParamMaxCredentialUsageAge": "Default": "90" "Type": "String" "InternetGatewayAuthorizedVpcOnlyParamAuthorizedVpcIds": "Default": "here add Comma-separated list of the authorized VPC IDs" "Type": "String" "RedshiftClusterConfigurationCheckParamClusterDbEncrypted": "Default": "true" "Type": "String" "RedshiftClusterConfigurationCheckParamLoggingEnabled": "Default": "true" "Type": "String" "RedshiftClusterMaintenancesettingsCheckParamAllowVersionUpgrade": "Default": "true" "Type": "String" "RestrictedIncomingTrafficParamBlockedPort1": "Default": "20" "Type": "String" "RestrictedIncomingTrafficParamBlockedPort2": "Default": "21" "Type": "String" "RestrictedIncomingTrafficParamBlockedPort3": "Default": "3389" "Type": "String" "RestrictedIncomingTrafficParamBlockedPort4": "Default": "3306" "Type": "String" "RestrictedIncomingTrafficParamBlockedPort5": "Default": "4333" "Type": "String" "VpcSgOpenOnlyToAuthorizedPortsParamAuthorizedTcpPorts": "Default": "443" "Type": "String" "Resources": "AccessKeysRotated": "Properties": "ConfigRuleName": "access-keys-rotated" "InputParameters": "maxAccessKeyAge": "Fn::If": - "accessKeysRotatedParamMaxAccessKeyAge" - "Ref": "AccessKeysRotatedParamMaxAccessKeyAge" - "Ref": "AWS::NoValue" "Source": "Owner": "AWS" "SourceIdentifier": "ACCESS_KEYS_ROTATED" "Type": "AWS::Config::ConfigRule" "AlbHttpToHttpsRedirectionCheck": "Properties": "ConfigRuleName": "alb-http-to-https-redirection-check" "Source": "Owner": "AWS" "SourceIdentifier": "ALB_HTTP_TO_HTTPS_REDIRECTION_CHECK" "Type": "AWS::Config::ConfigRule" "AlbWafEnabled": "Properties": "ConfigRuleName": "alb-waf-enabled" "Scope": "ComplianceResourceTypes": - "AWS::ElasticLoadBalancingV2::LoadBalancer" "Source": "Owner": "AWS" "SourceIdentifier": "ALB_WAF_ENABLED" "Type": "AWS::Config::ConfigRule" "ApiGwExecutionLoggingEnabled": "Properties": "ConfigRuleName": "api-gw-execution-logging-enabled" "Scope": "ComplianceResourceTypes": - "AWS::ApiGateway::Stage" - "AWS::ApiGatewayV2::Stage" "Source": "Owner": "AWS" "SourceIdentifier": "API_GW_EXECUTION_LOGGING_ENABLED" "Type": "AWS::Config::ConfigRule" "ApiGwSslEnabled": "Properties": "ConfigRuleName": "api-gw-ssl-enabled" "Scope": "ComplianceResourceTypes": - "AWS::ApiGateway::Stage" "Source": "Owner": "AWS" "SourceIdentifier": "API_GW_SSL_ENABLED" "Type": "AWS::Config::ConfigRule" "ApiGwXrayEnabled": "Properties": "ConfigRuleName": "api-gw-xray-enabled" "Scope": "ComplianceResourceTypes": - "AWS::ApiGateway::Stage" "Source": "Owner": "AWS" "SourceIdentifier": "API_GW_XRAY_ENABLED" "Type": "AWS::Config::ConfigRule" "AuroraResourcesProtectedByBackupPlan": "Properties": "ConfigRuleName": "aurora-resources-protected-by-backup-plan" "Scope": "ComplianceResourceTypes": - "AWS::RDS::DBCluster" "Source": "Owner": "AWS" "SourceIdentifier": "AURORA_RESOURCES_PROTECTED_BY_BACKUP_PLAN" "Type": "AWS::Config::ConfigRule" "AutoscalingGroupElbHealthcheckRequired": "Properties": "ConfigRuleName": "autoscaling-group-elb-healthcheck-required" "Scope": "ComplianceResourceTypes": - "AWS::AutoScaling::AutoScalingGroup" "Source": "Owner": "AWS" "SourceIdentifier": "AUTOSCALING_GROUP_ELB_HEALTHCHECK_REQUIRED" "Type": "AWS::Config::ConfigRule" "BackupPlanMinFrequencyAndMinRetentionCheck": "Properties": "ConfigRuleName": "backup-plan-min-frequency-and-min-retention-check" "Scope": "ComplianceResourceTypes": - "AWS::Backup::BackupPlan" "Source": "Owner": "AWS" "SourceIdentifier": "BACKUP_PLAN_MIN_FREQUENCY_AND_MIN_RETENTION_CHECK" "Type": "AWS::Config::ConfigRule" "BackupRecoveryPointEncrypted": "Properties": "ConfigRuleName": "backup-recovery-point-encrypted" "Scope": "ComplianceResourceTypes": - "AWS::Backup::RecoveryPoint" "Source": "Owner": "AWS" "SourceIdentifier": "BACKUP_RECOVERY_POINT_ENCRYPTED" "Type": "AWS::Config::ConfigRule" "BackupRecoveryPointManualDeletionDisabled": "Properties": "ConfigRuleName": "backup-recovery-point-manual-deletion-disabled" "Scope": "ComplianceResourceTypes": - "AWS::Backup::BackupVault" "Source": "Owner": "AWS" "SourceIdentifier": "BACKUP_RECOVERY_POINT_MANUAL_DELETION_DISABLED" "Type": "AWS::Config::ConfigRule" "BackupRecoveryPointMinimumRetentionCheck": "Properties": "ConfigRuleName": "backup-recovery-point-minimum-retention-check" "Scope": "ComplianceResourceTypes": - "AWS::Backup::RecoveryPoint" "Source": "Owner": "AWS" "SourceIdentifier": "BACKUP_RECOVERY_POINT_MINIMUM_RETENTION_CHECK" "Type": "AWS::Config::ConfigRule" "BeanstalkEnhancedHealthReportingEnabled": "Properties": "ConfigRuleName": "beanstalk-enhanced-health-reporting-enabled" "Scope": "ComplianceResourceTypes": - "AWS::ElasticBeanstalk::Environment" "Source": "Owner": "AWS" "SourceIdentifier": "BEANSTALK_ENHANCED_HEALTH_REPORTING_ENABLED" "Type": "AWS::Config::ConfigRule" "CloudTrailEnabled": "Properties": "ConfigRuleName": "cloudtrail-enabled" "Source": "Owner": "AWS" "SourceIdentifier": "CLOUD_TRAIL_ENABLED" "Type": "AWS::Config::ConfigRule" "CloudTrailLogFileValidationEnabled": "Properties": "ConfigRuleName": "cloud-trail-log-file-validation-enabled" "Source": "Owner": "AWS" "SourceIdentifier": "CLOUD_TRAIL_LOG_FILE_VALIDATION_ENABLED" "Type": "AWS::Config::ConfigRule" "CloudtrailS3DataeventsEnabled": "Properties": "ConfigRuleName": "cloudtrail-s3-dataevents-enabled" "Source": "Owner": "AWS" "SourceIdentifier": "CLOUDTRAIL_S3_DATAEVENTS_ENABLED" "Type": "AWS::Config::ConfigRule" "CloudwatchAlarmActionCheck": "Properties": "ConfigRuleName": "cloudwatch-alarm-action-check" "InputParameters": "alarmActionRequired": "Fn::If": - "cloudwatchAlarmActionCheckParamAlarmActionRequired" - "Ref": "CloudwatchAlarmActionCheckParamAlarmActionRequired" - "Ref": "AWS::NoValue" "insufficientDataActionRequired": "Fn::If": - "cloudwatchAlarmActionCheckParamInsufficientDataActionRequired" - "Ref": "CloudwatchAlarmActionCheckParamInsufficientDataActionRequired" - "Ref": "AWS::NoValue" "okActionRequired": "Fn::If": - "cloudwatchAlarmActionCheckParamOkActionRequired" - "Ref": "CloudwatchAlarmActionCheckParamOkActionRequired" - "Ref": "AWS::NoValue" "Scope": "ComplianceResourceTypes": - "AWS::CloudWatch::Alarm" "Source": "Owner": "AWS" "SourceIdentifier": "CLOUDWATCH_ALARM_ACTION_CHECK" "Type": "AWS::Config::ConfigRule" "CmkBackingKeyRotationEnabled": "Properties": "ConfigRuleName": "cmk-backing-key-rotation-enabled" "Source": "Owner": "AWS" "SourceIdentifier": "CMK_BACKING_KEY_ROTATION_ENABLED" "Type": "AWS::Config::ConfigRule" "CwLoggroupRetentionPeriodCheck": "Properties": "ConfigRuleName": "cw-loggroup-retention-period-check" "Source": "Owner": "AWS" "SourceIdentifier": "CW_LOGGROUP_RETENTION_PERIOD_CHECK" "Type": "AWS::Config::ConfigRule" "DbInstanceBackupEnabled": "Properties": "ConfigRuleName": "db-instance-backup-enabled" "Scope": "ComplianceResourceTypes": - "AWS::RDS::DBInstance" "Source": "Owner": "AWS" "SourceIdentifier": "DB_INSTANCE_BACKUP_ENABLED" "Type": "AWS::Config::ConfigRule" "DmsReplicationNotPublic": "Properties": "ConfigRuleName": "dms-replication-not-public" "Scope": "ComplianceResourceTypes": [] "Source": "Owner": "AWS" "SourceIdentifier": "DMS_REPLICATION_NOT_PUBLIC" "Type": "AWS::Config::ConfigRule" "DynamodbAutoscalingEnabled": "Properties": "ConfigRuleName": "dynamodb-autoscaling-enabled" "Scope": "ComplianceResourceTypes": - "AWS::DynamoDB::Table" "Source": "Owner": "AWS" "SourceIdentifier": "DYNAMODB_AUTOSCALING_ENABLED" "Type": "AWS::Config::ConfigRule" "DynamodbPitrEnabled": "Properties": "ConfigRuleName": "dynamodb-pitr-enabled" "Scope": "ComplianceResourceTypes": - "AWS::DynamoDB::Table" "Source": "Owner": "AWS" "SourceIdentifier": "DYNAMODB_PITR_ENABLED" "Type": "AWS::Config::ConfigRule" "DynamodbResourcesProtectedByBackupPlan": "Properties": "ConfigRuleName": "dynamodb-resources-protected-by-backup-plan" "Scope": "ComplianceResourceTypes": - "AWS::DynamoDB::Table" "Source": "Owner": "AWS" "SourceIdentifier": "DYNAMODB_RESOURCES_PROTECTED_BY_BACKUP_PLAN" "Type": "AWS::Config::ConfigRule" "DynamodbThroughputLimitCheck": "Properties": "ConfigRuleName": "dynamodb-throughput-limit-check" "Source": "Owner": "AWS" "SourceIdentifier": "DYNAMODB_THROUGHPUT_LIMIT_CHECK" "Type": "AWS::Config::ConfigRule" "EbsOptimizedInstance": "Properties": "ConfigRuleName": "ebs-optimized-instance" "Scope": "ComplianceResourceTypes": - "AWS::EC2::Instance" "Source": "Owner": "AWS" "SourceIdentifier": "EBS_OPTIMIZED_INSTANCE" "Type": "AWS::Config::ConfigRule" "EbsResourcesProtectedByBackupPlan": "Properties": "ConfigRuleName": "ebs-resources-protected-by-backup-plan" "Scope": "ComplianceResourceTypes": - "AWS::EC2::Volume" "Source": "Owner": "AWS" "SourceIdentifier": "EBS_RESOURCES_PROTECTED_BY_BACKUP_PLAN" "Type": "AWS::Config::ConfigRule" "EbsSnapshotPublicRestorableCheck": "Properties": "ConfigRuleName": "ebs-snapshot-public-restorable-check" "Source": "Owner": "AWS" "SourceIdentifier": "EBS_SNAPSHOT_PUBLIC_RESTORABLE_CHECK" "Type": "AWS::Config::ConfigRule" "Ec2EbsEncryptionByDefault": "Properties": "ConfigRuleName": "ec2-ebs-encryption-by-default" "Source": "Owner": "AWS" "SourceIdentifier": "EC2_EBS_ENCRYPTION_BY_DEFAULT" "Type": "AWS::Config::ConfigRule" "Ec2Imdsv2Check": "Properties": "ConfigRuleName": "ec2-imdsv2-check" "Scope": "ComplianceResourceTypes": - "AWS::EC2::Instance" "Source": "Owner": "AWS" "SourceIdentifier": "EC2_IMDSV2_CHECK" "Type": "AWS::Config::ConfigRule" "Ec2InstanceDetailedMonitoringEnabled": "Properties": "ConfigRuleName": "ec2-instance-detailed-monitoring-enabled" "Scope": "ComplianceResourceTypes": - "AWS::EC2::Instance" "Source": "Owner": "AWS" "SourceIdentifier": "EC2_INSTANCE_DETAILED_MONITORING_ENABLED" "Type": "AWS::Config::ConfigRule" "Ec2InstanceManagedBySsm": "Properties": "ConfigRuleName": "ec2-instance-managed-by-systems-manager" "Scope": "ComplianceResourceTypes": - "AWS::EC2::Instance" - "AWS::SSM::ManagedInstanceInventory" "Source": "Owner": "AWS" "SourceIdentifier": "EC2_INSTANCE_MANAGED_BY_SSM" "Type": "AWS::Config::ConfigRule" "Ec2InstanceNoPublicIp": "Properties": "ConfigRuleName": "ec2-instance-no-public-ip" "Scope": "ComplianceResourceTypes": - "AWS::EC2::Instance" "Source": "Owner": "AWS" "SourceIdentifier": "EC2_INSTANCE_NO_PUBLIC_IP" "Type": "AWS::Config::ConfigRule" "Ec2ManagedinstanceAssociationComplianceStatusCheck": "Properties": "ConfigRuleName": "ec2-managedinstance-association-compliance-status-check" "Scope": "ComplianceResourceTypes": - "AWS::SSM::AssociationCompliance" "Source": "Owner": "AWS" "SourceIdentifier": "EC2_MANAGEDINSTANCE_ASSOCIATION_COMPLIANCE_STATUS_CHECK" "Type": "AWS::Config::ConfigRule" "Ec2ManagedinstancePatchComplianceStatusCheck": "Properties": "ConfigRuleName": "ec2-managedinstance-patch-compliance-status-check" "Scope": "ComplianceResourceTypes": - "AWS::SSM::PatchCompliance" "Source": "Owner": "AWS" "SourceIdentifier": "EC2_MANAGEDINSTANCE_PATCH_COMPLIANCE_STATUS_CHECK" "Type":... ```
Show Conftest results ```sh WARN - plan.json - main - Missing Common Tags: ["module.conformance_pack.aws_s3_object.conformace_pack_yaml"] 18 tests, 17 passed, 1 warning, 0 failures, 0 exceptions ```
github-actions[bot] commented 1 year ago

Production: cloudfront

✅   Terraform Init: success ✅   Terraform Validate: success ✅   Terraform Format: success ✅   Terraform Plan: success ✅   Conftest: success

Plan: 25 to add, 0 to change, 0 to destroy
Show summary | CHANGE | NAME | |--------|----------------------------------------------------------------------------------------------| | add | `aws_acm_certificate.url_shortener_certificate` | | | `aws_acm_certificate_validation.url_shortener_certificate_validation` | | | `aws_cloudfront_distribution.url_shortener_api` | | | `aws_cloudfront_response_headers_policy.security_headers_api` | | | `aws_iam_policy.write_waf_logs` | | | `aws_iam_role.waf_log_role` | | | `aws_iam_role_policy_attachment.write_waf_logs` | | | `aws_kinesis_firehose_delivery_stream.api` | | | `aws_route53_record.url_shortener_A` | | | `aws_route53_record.url_shortener_dns_validation["*.o.alpha.canada.ca"]` | | | `aws_route53_record.url_shortener_dns_validation["o.alpha.canada.ca"]` | | | `aws_wafv2_regex_pattern_set.login_uri_paths` | | | `aws_wafv2_regex_pattern_set.valid_uri_paths` | | | `aws_wafv2_web_acl.api_waf` | | | `aws_wafv2_web_acl_logging_configuration.api` | | | `module.resolver_dns.aws_cloudwatch_log_group.route53_vpc_dns` | | | `module.resolver_dns.aws_cloudwatch_log_resource_policy.route53_vpc_dns` | | | `module.resolver_dns.aws_route53_resolver_firewall_domain_list.allowed[0]` | | | `module.resolver_dns.aws_route53_resolver_firewall_domain_list.blocked[0]` | | | `module.resolver_dns.aws_route53_resolver_firewall_rule.allowed[0]` | | | `module.resolver_dns.aws_route53_resolver_firewall_rule.blocked[0]` | | | `module.resolver_dns.aws_route53_resolver_firewall_rule_group.firewall_rules[0]` | | | `module.resolver_dns.aws_route53_resolver_firewall_rule_group_association.firewall_rules[0]` | | | `module.resolver_dns.aws_route53_resolver_query_log_config.route53_vpc_dns` | | | `module.resolver_dns.aws_route53_resolver_query_log_config_association.route53_vpc_dns` |

✂   Warning: plan has been truncated! See the full plan in the logs.

Show plan ```terraform Resource actions are indicated with the following symbols: + create <= read (data resources) Terraform will perform the following actions: # aws_acm_certificate.url_shortener_certificate will be created + resource "aws_acm_certificate" "url_shortener_certificate" { + arn = (known after apply) + domain_name = "o.alpha.canada.ca" + domain_validation_options = [ + { + domain_name = "*.o.alpha.canada.ca" + resource_record_name = (known after apply) + resource_record_type = (known after apply) + resource_record_value = (known after apply) }, + { + domain_name = "o.alpha.canada.ca" + resource_record_name = (known after apply) + resource_record_type = (known after apply) + resource_record_value = (known after apply) }, ] + id = (known after apply) + key_algorithm = (known after apply) + not_after = (known after apply) + not_before = (known after apply) + pending_renewal = (known after apply) + renewal_eligibility = (known after apply) + renewal_summary = (known after apply) + status = (known after apply) + subject_alternative_names = [ + "*.o.alpha.canada.ca", + "o.alpha.canada.ca", ] + tags = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + tags_all = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + type = (known after apply) + validation_emails = (known after apply) + validation_method = "DNS" + options { + certificate_transparency_logging_preference = (known after apply) } } # aws_acm_certificate_validation.url_shortener_certificate_validation will be created + resource "aws_acm_certificate_validation" "url_shortener_certificate_validation" { + certificate_arn = (known after apply) + id = (known after apply) + validation_record_fqdns = (known after apply) } # aws_cloudfront_distribution.url_shortener_api will be created + resource "aws_cloudfront_distribution" "url_shortener_api" { + aliases = [ + "o.alpha.canada.ca", ] + arn = (known after apply) + caller_reference = (known after apply) + domain_name = (known after apply) + enabled = true + etag = (known after apply) + hosted_zone_id = (known after apply) + http_version = "http2" + id = (known after apply) + in_progress_validation_batches = (known after apply) + is_ipv6_enabled = false + last_modified_time = (known after apply) + price_class = "PriceClass_100" + retain_on_delete = false + status = (known after apply) + tags = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + tags_all = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + trusted_key_groups = (known after apply) + trusted_signers = (known after apply) + wait_for_deployment = true + web_acl_id = (known after apply) + default_cache_behavior { + allowed_methods = [ + "DELETE", + "GET", + "HEAD", + "OPTIONS", + "PATCH", + "POST", + "PUT", ] + cache_policy_id = "4135ea2d-6df8-44a3-9df3-4b5a84be39ad" + cached_methods = [ + "GET", + "HEAD", ] + compress = true + default_ttl = (known after apply) + max_ttl = (known after apply) + min_ttl = 0 + origin_request_policy_id = "b689b0a8-53d0-40ab-baf2-68738e2966ac" + response_headers_policy_id = (known after apply) + target_origin_id = "url-shortener-api" + trusted_key_groups = (known after apply) + trusted_signers = (known after apply) + viewer_protocol_policy = "redirect-to-https" } + ordered_cache_behavior { + allowed_methods = [ + "GET", + "HEAD", ] + cached_methods = [ + "GET", + "HEAD", ] + compress = true + default_ttl = 0 + max_ttl = 0 + min_ttl = 0 + path_pattern = "/healthcheck" + response_headers_policy_id = (known after apply) + target_origin_id = "url-shortener-api" + viewer_protocol_policy = "redirect-to-https" + forwarded_values { + headers = (known after apply) + query_string = false + query_string_cache_keys = (known after apply) + cookies { + forward = "none" } } } + origin { # At least one attribute in this block is (or was) sensitive, # so its contents will not be displayed. } + restrictions { + geo_restriction { + locations = (known after apply) + restriction_type = "none" } } + viewer_certificate { + acm_certificate_arn = (known after apply) + minimum_protocol_version = "TLSv1.2_2021" + ssl_support_method = "sni-only" } } # aws_cloudfront_response_headers_policy.security_headers_api will be created + resource "aws_cloudfront_response_headers_policy" "security_headers_api" { + etag = (known after apply) + id = (known after apply) + name = "url-shortener-security-headers-api" + security_headers_config { + content_security_policy { + content_security_policy = "report-uri https://csp-report-to.security.cdssandbox.xyz/report; default-src 'none'; script-src 'self' 'unsafe-inline' https://unpkg.com/@cdssnc/ https://o.alpha.canada.ca/static/js/ https://kit.fontawesome.com; font-src 'self' https://fonts.googleapis.com https://fonts.gstatic.com https://kit.fontawesome.com https://ka-f.fontawesome.com https://unpkg.com/font-awesome@4.7.0/; connect-src 'self' https://ka-f.fontawesome.com; img-src 'self' https://o.alpha.canada.ca/static/img/ data: w3.org/svg/2000; style-src 'self' 'unsafe-inline' https://o.alpha.canada.ca/static/css/ https://unpkg.com/@cdssnc/ https://unpkg.com/font-awesome/ https://kit.fontawesome.com https://fonts.googleapis.com; frame-ancestors 'self'; form-action 'self';" + override = false } + content_type_options { + override = true } + frame_options { + frame_option = "DENY" + override = true } + referrer_policy { + override = true + referrer_policy = "same-origin" } + strict_transport_security { + access_control_max_age_sec = 31536000 + include_subdomains = true + override = true + preload = true } + xss_protection { + mode_block = true + override = true + protection = true } } } # aws_iam_policy.write_waf_logs will be created + resource "aws_iam_policy" "write_waf_logs" { + arn = (known after apply) + description = "Allow Firehose to write WAF logs to S3" + id = (known after apply) + name = "url-shortener-waf-logs" + name_prefix = (known after apply) + path = "/" + policy = jsonencode( { + Statement = [ + { + Action = "s3:ListBucket" + Effect = "Allow" + Resource = "arn:aws:s3:::cbs-satellite-806721586252" + Sid = "" }, + { + Action = [ + "s3:PutObject*", + "s3:GetObject*", ] + Effect = "Allow" + Resource = "arn:aws:s3:::cbs-satellite-806721586252/waf_acl_logs/*" + Sid = "" }, ] + Version = "2012-10-17" } ) + policy_id = (known after apply) + tags = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + tags_all = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } } # aws_iam_role.waf_log_role will be created + resource "aws_iam_role" "waf_log_role" { + arn = (known after apply) + assume_role_policy = jsonencode( { + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "firehose.amazonaws.com" } + Sid = "" }, ] + Version = "2012-10-17" } ) + create_date = (known after apply) + force_detach_policies = false + id = (known after apply) + managed_policy_arns = (known after apply) + max_session_duration = 3600 + name = "url-shortener-waf-logs" + name_prefix = (known after apply) + path = "/" + role_last_used = (known after apply) + tags = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + tags_all = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + unique_id = (known after apply) + inline_policy { + name = (known after apply) + policy = (known after apply) } } # aws_iam_role_policy_attachment.write_waf_logs will be created + resource "aws_iam_role_policy_attachment" "write_waf_logs" { + id = (known after apply) + policy_arn = (known after apply) + role = "url-shortener-waf-logs" } # aws_kinesis_firehose_delivery_stream.api will be created + resource "aws_kinesis_firehose_delivery_stream" "api" { + arn = (known after apply) + destination = "extended_s3" + destination_id = (known after apply) + id = (known after apply) + name = "aws-waf-logs-url-shortener" + tags = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + tags_all = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + version_id = (known after apply) + extended_s3_configuration { + bucket_arn = "arn:aws:s3:::cbs-satellite-806721586252" + buffer_interval = 300 + buffer_size = 5 + compression_format = "GZIP" + prefix = "waf_acl_logs/AWSLogs/806721586252/" + role_arn = (known after apply) + s3_backup_mode = "Disabled" + cloudwatch_logging_options { + enabled = false } } + server_side_encryption { + enabled = true + key_type = "AWS_OWNED_CMK" } } # aws_route53_record.url_shortener_A will be created + resource "aws_route53_record" "url_shortener_A" { + allow_overwrite = (known after apply) + fqdn = (known after apply) + id = (known after apply) + name = "o.alpha.canada.ca" + type = "A" + zone_id = "Z0129461HK2TKOF3BTTF" + alias { + evaluate_target_health = false + name = (known after apply) + zone_id = (known after apply) } } # aws_route53_record.url_shortener_dns_validation["*.o.alpha.canada.ca"] will be created + resource "aws_route53_record" "url_shortener_dns_validation" { + allow_overwrite = true + fqdn = (known after apply) + id = (known after apply) + name = (known after apply) + records = (known after apply) + ttl = 60 + type = (known after apply) + zone_id = "Z0129461HK2TKOF3BTTF" } # aws_route53_record.url_shortener_dns_validation["o.alpha.canada.ca"] will be created + resource "aws_route53_record" "url_shortener_dns_validation" { + allow_overwrite = true + fqdn = (known after apply) + id = (known after apply) + name = (known after apply) + records = (known after apply) + ttl = 60 + type = (known after apply) + zone_id = "Z0129461HK2TKOF3BTTF" } # aws_wafv2_regex_pattern_set.login_uri_paths will be created + resource "aws_wafv2_regex_pattern_set" "login_uri_paths" { + arn = (known after apply) + description = "Regex to match the login paths of the API" + id = (known after apply) + lock_token = (known after apply) + name = "login-uri-paths" + scope = "CLOUDFRONT" + tags = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + tags_all = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + regular_expression { + regex_string = "^/en/(login|magic-link)/?$" } + regular_expression { + regex_string = "^/fr/(connexion|lien-magique)/?$" } } # aws_wafv2_regex_pattern_set.valid_uri_paths will be created + resource "aws_wafv2_regex_pattern_set" "valid_uri_paths" { + arn = (known after apply) + description = "Regex to match the valid paths of hte API" + id = (known after apply) + lock_token = (known after apply) + name = "valid-api-paths" + scope = "CLOUDFRONT" + tags = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + tags_all = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + regular_expression { + regex_string = "^/(version|healthcheck|openapi.json|.well-known/security.txt)$" } + regular_expression { + regex_string = "^/?(en|fr)?/?$" } + regular_expression { + regex_string = "^/[0-9A-Za-z]{8}/?$" } + regular_expression { + regex_string = "^/en/(login|logout|contact|magic-link)/?$" } + regular_expression { + regex_string = "^/fr/(connexion|deconnexion|contact|lien-magique)/?$" } + regular_expression { + regex_string = "^/lang/(en|fr)/?$" } + regular_expression { + regex_string = "^/static/(css|js|img)/[^/]+$" } + regular_expression { + regex_string = "^/v1/?$" } } # aws_wafv2_web_acl.api_waf will be created + resource "aws_wafv2_web_acl" "api_waf" { + arn = (known after apply) + capacity = (known after apply) + description = "WAF for URL shortener API" + id = (known after apply) + lock_token = (known after apply) + name = "url-shortener-waf" + scope = "CLOUDFRONT" + tags = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + tags_all = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + custom_response_body { + content = jsonencode( { + detail = { + error = "Request blocked." + status = "ERROR" } } ) + content_type = "APPLICATION_JSON" + key = "json_request_blocked_error_response" } + custom_response_body { + content = jsonencode( { + detail = { + error = "Too many requests." + status = "ERROR" } } ) + content_type = "APPLICATION_JSON" + key = "json_request_rate_limited_error_response" } + default_action { + allow { } } + rule { + name = "APIInvalidPath" + priority = 5 + action { + block { + custom_response { + custom_response_body_key = "json_request_blocked_error_response" + response_code = 403 } } } + statement { + not_statement { + statement { + regex_pattern_set_reference_statement { + arn = (known after apply) + field_to_match { + uri_path {} } + text_transformation { + priority = 1 + type = "COMPRESS_WHITE_SPACE" } + text_transformation { + priority = 2 + type = "LOWERCASE" } } } } } + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "APIInvalidPaths" + sampled_requests_enabled = true } } + rule { + name = "APIRateLimit" + priority = 20 + action { + block { + custom_response { + custom_response_body_key = "json_request_rate_limited_error_response" + response_code = 429 } } } + statement { + rate_based_statement { + aggregate_key_type = "IP" + limit = 2000 } } + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "APIRateLimit" + sampled_requests_enabled = true } } + rule { + name = "LoginAPIRateLimit" + priority = 25 + action { + block { + custom_response { + custom_response_body_key = "json_request_rate_limited_error_response" + response_code = 429 } } } + statement { + rate_based_statement { + aggregate_key_type = "IP" + limit = 100 + scope_down_statement { + regex_pattern_set_reference_statement { + arn = (known after apply) + field_to_match { + uri_path {} } + text_transformation { + priority = 1 + type = "COMPRESS_WHITE_SPACE" } + text_transformation { + priority = 2 + type = "LOWERCASE" } } } } } + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "LoginAPIRateLimit" + sampled_requests_enabled = true } } + rule { + name = "AWSManagedRulesAmazonIpReputationList" + priority = 10 + override_action { + none {} } + statement { + managed_rule_group_statement { + name = "AWSManagedRulesAmazonIpReputationList" + vendor_name = "AWS" } } + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "AWSManagedRulesAmazonIpReputationList" + sampled_requests_enabled = true } } + rule { + name = "AWSManagedRulesCommonRuleSet" + priority = 30 + override_action { + none {} } + statement { + managed_rule_group_statement { + name = "AWSManagedRulesCommonRuleSet" + vendor_name = "AWS" } } + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "AWSManagedRulesCommonRuleSet" + sampled_requests_enabled = true } } + rule { + name = "AWSManagedRulesKnownBadInputsRuleSet" + priority = 40 + override_action { + none {} } + statement { + managed_rule_group_statement { + name = "AWSManagedRulesKnownBadInputsRuleSet" + vendor_name = "AWS" } } + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "AWSManagedRulesKnownBadInputsRuleSet" + sampled_requests_enabled = true } } + rule { + name = "AWSManagedRulesLinuxRuleSet" + priority = 50 + override_action { + none {} } + statement { + managed_rule_group_statement { + name = "AWSManagedRulesLinuxRuleSet" + vendor_name = "AWS" } } + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "AWSManagedRulesLinuxRuleSet" + sampled_requests_enabled = true } } + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "api" + sampled_requests_enabled = false } } # aws_wafv2_web_acl_logging_configuration.api will be created + resource "aws_wafv2_web_acl_logging_configuration" "api" { + id = (known after apply) + log_destination_configs = (known after apply) + resource_arn = (known after apply) } # module.resolver_dns.data.aws_iam_policy_document.route53_resolver_logging_policy will be read during apply # (config refers to values not yet known) <= data "aws_iam_policy_document" "route53_resolver_logging_policy" { + id = (known after apply) + json = (known after apply) + statement { + actions = [ + "logs:CreateLogStream", + "logs:PutLogEvents", ] + resources = [ + (known after apply), ] + principals { + identifiers = [ + "route53.amazonaws.com", ] + type = "Service" } } } # module.resolver_dns.aws_cloudwatch_log_group.route53_vpc_dns will be created + resource "aws_cloudwatch_log_group" "route53_vpc_dns" { + arn = (known after apply) + id = (known after apply) + name = "/aws/route53/vpc-0009bdb7c0677ef88" + name_prefix = (known after apply) + retention_in_days = 30 + skip_destroy = false + tags = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + tags_all = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } } # module.resolver_dns.aws_cloudwatch_log_resource_policy.route53_vpc_dns will be created + resource "aws_cloudwatch_log_resource_policy" "route53_vpc_dns" { + id = (known after apply) + policy_document = (known after apply) + policy_name = "route53_resolver_logging_policy" } # module.resolver_dns.aws_route53_resolver_firewall_domain_list.allowed[0] will be created + resource "aws_route53_resolver_firewall_domain_list" "allowed" { + arn = (known after apply) + domains = [ + "*.akamaiedge.net.", + "*.amazonaws.com.", + "*.canada.ca.", + "*.edgekey.net.", + "*.gc.ca.", + "*.gg.ca.", + "canada.ca.", + "gg.ca.", ] + id = (known after apply) + name = "AllowedDomains" + tags = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + tags_all = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } } # module.resolver_dns.aws_route53_resolver_firewall_domain_list.blocked[0] will be created + resource "aws_route53_resolver_firewall_domain_list" "blocked" { + arn = (known after apply) + domains = [ + "*.", ] + id = (known after apply) + name = "BlockedDomains" + tags = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + tags_all = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } } # module.resolver_dns.aws_route53_resolver_firewall_rule.allowed[0] will be created + resource "aws_route53_resolver_firewall_rule" "allowed" { + action = "ALLOW" + firewall_domain_list_id = (known after apply) + firewall_rule_group_id = (known after apply) + id = (known after apply) + name = "AllowedDomains" + priority = 100 } # module.resolver_dns.aws_route53_resolver_firewall_rule.blocked[0] will be created + resource "aws_route53_resolver_firewall_rule" "blocked" { + action = "BLOCK" + block_response = "NODATA" + firewall_domain_list_id = (known after apply) + firewall_rule_group_id = (known after apply) + id = (known after apply) + name = "BlockedDomains" + priority = 200 } # module.resolver_dns.aws_route53_resolver_firewall_rule_group.firewall_rules[0] will be created + resource "aws_route53_resolver_firewall_rule_group" "firewall_rules" { + arn = (known after apply) + id = (known after apply) + name = "FirewallRules" + owner_id = (known after apply) + share_status = (known after apply) + tags = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } + tags_all = { + "CostCentre" = "url-shortener-production" + "Terraform" = "true" } } # module.resolver_dns.aws_route53_resolver_firewall_rule_group_association.firewall_rules[0] will be created + resource "aws_route53_resolver_firewall_rule_group_association" "firewall_rules" { + arn = (known after apply) + firewall_rule_group_id = (known after apply) + id = (known after apply) + mutation_protection = (known after apply) + name = "FirewallRules" + priority = 101 + tags_all = (known after apply) + vpc_id ... ```
Show Conftest results ```sh WARN - plan.json - main - Missing Common Tags: ["module.resolver_dns.aws_route53_resolver_firewall_rule_group_association.firewall_rules[0]"] WARN - plan.json - main - Missing Common Tags: ["module.resolver_dns.aws_route53_resolver_query_log_config.route53_vpc_dns"] 19 tests, 17 passed, 2 warnings, 0 failures, 0 exceptions ```
github-actions[bot] commented 1 year ago

Production: api

✅   Terraform Init: success ✅   Terraform Validate: success ✅   Terraform Format: success ✅   Terraform Plan: success ✅   Conftest: success

Plan: 3 to add, 0 to change, 0 to destroy
Show summary | CHANGE | NAME | |--------|-----------------------------------------------------------------------------------------------------| | add | `aws_cloudwatch_log_subscription_filter.api_request` | | | `module.sentinel_forwarder.aws_lambda_function.sentinel_forwarder` | | | `module.sentinel_forwarder.aws_lambda_permission.sentinel_forwarder_cloudwatch_log_subscription[0]` |
Show plan ```terraform Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # aws_cloudwatch_log_subscription_filter.api_request will be created + resource "aws_cloudwatch_log_subscription_filter" "api_request" { + destination_arn = (known after apply) + distribution = "Random" + filter_pattern = "?INFO ?WARNING ?ERROR" + id = (known after apply) + log_group_name = "/aws/lambda/url-shortener-api" + name = "API request" + role_arn = (known after apply) } # module.sentinel_forwarder.aws_lambda_function.sentinel_forwarder will be created + resource "aws_lambda_function" "sentinel_forwarder" { + architectures = (known after apply) + arn = (known after apply) + description = "Lambda function to forward AWS logs to Azure Sentinel" + filename = "/tmp/sentinel_forwarder.py.zip" + function_name = "sentinel-cloudwatch-forwarder" + handler = "sentinel_forwarder.lambda_handler" + id = (known after apply) + invoke_arn = (known after apply) + last_modified = (known after apply) + layers = [ + "arn:aws:lambda:ca-central-1:283582579564:layer:aws-sentinel-connector-layer:58", ] + memory_size = 128 + package_type = "Zip" + publish = false + qualified_arn = (known after apply) + qualified_invoke_arn = (known after apply) + reserved_concurrent_executions = -1 + role = "arn:aws:iam::806721586252:role/SentinelForwarderLambda-sentinel-cloudwatch-forwarder" + runtime = "python3.9" + signing_job_arn = (known after apply) + signing_profile_version_arn = (known after apply) + source_code_hash = "liR4yJNhp6SJtCjkSwnH0xGC0q00Uxebs1Cyqv8JLDw=" + source_code_size = (known after apply) + tags = { + "CostCentre" = "url-shortener-production" } + tags_all = { + "CostCentre" = "url-shortener-production" } + timeout = 30 + version = (known after apply) + environment { + variables = { + "CUSTOMER_ID" = (sensitive value) + "LOG_TYPE" = "ApplicationLog" + "SHARED_KEY" = (sensitive value) } } + ephemeral_storage { + size = (known after apply) } + tracing_config { + mode = "Active" } } # module.sentinel_forwarder.aws_lambda_permission.sentinel_forwarder_cloudwatch_log_subscription[0] will be created + resource "aws_lambda_permission" "sentinel_forwarder_cloudwatch_log_subscription" { + action = "lambda:InvokeFunction" + function_name = "sentinel-cloudwatch-forwarder" + id = (known after apply) + principal = "logs.ca-central-1.amazonaws.com" + source_arn = "arn:aws:logs:ca-central-1:806721586252:log-group:/aws/lambda/url-shortener-api:*" + statement_id = "AllowExecutionFromCloudWatchLogs-sentinel-cloudwatch-forwarder-0" + statement_id_prefix = (known after apply) } Plan: 3 to add, 0 to change, 0 to destroy. ───────────────────────────────────────────────────────────────────────────── Saved the plan to: plan.tfplan To perform exactly these actions, run the following command to apply: terraform apply "plan.tfplan" Releasing state lock. This may take a few moments... ```
Show Conftest results ```sh WARN - plan.json - main - Missing Common Tags: ["module.sentinel_forwarder.aws_cloudwatch_log_group.sentinel_forwarder_lambda"] WARN - plan.json - main - Missing Common Tags: ["module.sentinel_forwarder.aws_iam_policy.sentinel_forwarder_lambda"] WARN - plan.json - main - Missing Common Tags: ["module.sentinel_forwarder.aws_iam_role.sentinel_forwarder_lambda"] WARN - plan.json - main - Missing Common Tags: ["module.sentinel_forwarder.aws_lambda_function.sentinel_forwarder"] 21 tests, 17 passed, 4 warnings, 0 failures, 0 exceptions ```