Skip to content

Fix Config rule tags and restructure Slack alerts#106

Merged
Alexanderamiri merged 1 commit into
mainfrom
fix/alert-formatting
Mar 26, 2026
Merged

Fix Config rule tags and restructure Slack alerts#106
Alexanderamiri merged 1 commit into
mainfrom
fix/alert-formatting

Conversation

@Alexanderamiri
Copy link
Copy Markdown
Member

Summary

Config rule fix:

  • Changed tag1Key from project to servicedefault_tags sets service, not project. This was causing false-positive untagged resource alerts on every platform resource.

Slack alert restructuring:

  • Service name now in the header (e.g. :package: S3 Created (CI/CD) instead of :package: Resource Created (CI/CD))
  • Resource shown first in the fields grid, action moved lower
  • "triggered by {actor}" removed from source line — actor now in footer
  • Footer enriched with resource tags (team, service, commit, repo, environment) when available from CloudTrail
  • Compliance alert text updated to reference service, team, managed-by

Before:

:package: Resource Created (CI/CD)
Source: javaBin/platform / 22f0f732 / run (triggered by Alexanderamiri)
Action: CreateBucket | Resource: javabin-cur-553637109631 | Created by: javabin-ci-infra | Region: eu-central-1 | Service: S3
AWS Account 553637109631 | eu-central-1 | 2026-03-26T21:51:29Z

After:

:package: S3 Created (CI/CD)
Source: javaBin/platform / 22f0f732 / run
Resource: javabin-cur-553637109631 | Est. Cost: $0.022/GB/mo | Action: CreateBucket | Region: eu-central-1
AWS Account 553637109631 | eu-central-1 | 2026-03-26T21:51:29Z
By: javabin-ci-infra (CI/CD)
team=platform | service=platform | repo=javaBin/platform

Test plan

  • terraform validate passes
  • Deploy via CI, check that new resource alerts have service in header
  • Verify no more false-positive untagged resource alerts for platform resources

- Config rule: check for `service` tag instead of `project` (matches default_tags)
- Slack alerts: service name in header instead of generic "Resource"
- Slack alerts: resource shown first in fields, action moved lower
- Slack alerts: "triggered by" removed from source line, actor moved to footer
- Slack alerts: resource tags (team, service, commit, etc.) shown in footer
- Compliance alert text: updated to reference correct tags
@Alexanderamiri Alexanderamiri requested a review from a team as a code owner March 26, 2026 22:13
@github-actions
Copy link
Copy Markdown

Terraform Plan

🚧 Changes detected — Plan: 5 to add, 3 to change, 0 to destroy.

Plan output
Acquiring state lock. This may take a few moments...

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create
  ~ update in-place

Terraform will perform the following actions:

  # module.cost_analytics.aws_bcmdataexports_export.cur will be created
  + resource "aws_bcmdataexports_export" "cur" {
      + id       = (known after apply)
      + tags_all = {
          + "environment" = "production"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "platform"
        }

      + export {
          + export_arn = (known after apply)
          + name       = "javabin-cur"

          + data_query {
              + query_statement      = "SELECT identity_line_item_id, identity_time_interval, bill_invoice_id, bill_invoicing_entity, bill_billing_entity, bill_bill_type, bill_payer_account_id, bill_billing_period_start_date, bill_billing_period_end_date, line_item_usage_account_id, line_item_line_item_type, line_item_usage_start_date, line_item_usage_end_date, line_item_product_code, line_item_usage_type, line_item_operation, line_item_availability_zone, line_item_resource_id, line_item_usage_amount, line_item_normalization_factor, line_item_normalized_usage_amount, line_item_currency_code, line_item_unblended_rate, line_item_unblended_cost, line_item_blended_rate, line_item_blended_cost, line_item_line_item_description, product_product_name, product_region, pricing_unit, pricing_public_on_demand_cost, pricing_public_on_demand_rate, pricing_term, pricing_offering_class, resource_tags_user_team, resource_tags_user_service, resource_tags_user_environment, resource_tags_user_repo, resource_tags_user_managed_by FROM COST_AND_USAGE_REPORT"
              + table_configurations = {
                  + "COST_AND_USAGE_REPORT" = {
                      + "INCLUDE_MANUAL_DISCOUNT_COMPATIBILITY" = "FALSE"
                      + "INCLUDE_RESOURCES"                     = "TRUE"
                      + "INCLUDE_SPLIT_COST_ALLOCATION_DATA"    = "FALSE"
                      + "TIME_GRANULARITY"                      = "DAILY"
                    }
                }
            }

          + destination_configurations {
              + s3_destination {
                  + s3_bucket = "javabin-cur-553637109631"
                  + s3_prefix = "cur"
                  + s3_region = "eu-central-1"

                  + s3_output_configurations {
                      + compression = "PARQUET"
                      + format      = "PARQUET"
                      + output_type = "CUSTOM"
                      + overwrite   = "OVERWRITE_REPORT"
                    }
                }
            }

          + refresh_cadence {
              + frequency = "SYNCHRONOUS"
            }
        }
    }

  # module.cost_analytics.aws_glue_crawler.cur will be created
  + resource "aws_glue_crawler" "cur" {
      + arn           = (known after apply)
      + configuration = jsonencode(
            {
              + Grouping = {
                  + TableGroupingPolicy = "CombineCompatibleSchemas"
                }
              + Version  = 1
            }
        )
      + database_name = "javabin_cur"
      + id            = (known after apply)
      + name          = "javabin-cur-crawler"
      + role          = (known after apply)
      + schedule      = "cron(0 6 * * ? *)"
      + tags_all      = {
          + "environment" = "production"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "platform"
        }

      + s3_target {
          + path = "s3://javabin-cur-553637109631/cur/"
        }

      + schema_change_policy {
          + delete_behavior = "DELETE_FROM_DATABASE"
          + update_behavior = "UPDATE_IN_DATABASE"
        }
    }

  # module.cost_analytics.aws_iam_role.cur_crawler will be created
  + resource "aws_iam_role" "cur_crawler" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "glue.amazonaws.com"
                        }
                    },
                ]
              + 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                  = "javabin-cur-crawler"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + tags_all              = {
          + "environment" = "production"
          + "managed-by"  = "terraform"
          + "repo"        = "javaBin/platform"
          + "service"     = "platform"
          + "team"        = "platform"
        }
      + unique_id             = (known after apply)
    }

  # module.cost_analytics.aws_iam_role_policy.cur_crawler_s3 will be created
  + resource "aws_iam_role_policy" "cur_crawler_s3" {
      + id          = (known after apply)
      + name        = "javabin-cur-crawler-s3"
      + name_prefix = (known after apply)
      + policy      = jsonencode(
            {
              + Statement = [
                  + {
                      + Action   = [
                          + "s3:GetObject",
                          + "s3:ListBucket",
                        ]
                      + Effect   = "Allow"
                      + Resource = [
                          + "arn:aws:s3:::javabin-cur-553637109631",
                          + "arn:aws:s3:::javabin-cur-553637109631/*",
                        ]
                      + Sid      = "ReadCURData"
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + role        = (known after apply)
    }

  # module.cost_analytics.aws_iam_role_policy_attachment.cur_crawler_glue will be created
  + resource "aws_iam_role_policy_attachment" "cur_crawler_glue" {
      + id         = (known after apply)
      + policy_arn = "arn:aws:iam::aws:policy/service-role/AWSGlueServiceRole"
      + role       = "javabin-cur-crawler"
    }

  # module.lambdas.aws_lambda_function.securityhub_summary will be updated in-place
  ~ resource "aws_lambda_function" "securityhub_summary" {
        id                             = "javabin-securityhub-summary"
      ~ last_modified                  = "2026-03-26T19:54:50.000+0000" -> (known after apply)
      ~ source_code_hash               = "//EAo2qOP1ujBcWSwzIrY7e+x0ayJTBlQZWAO/RzIO4=" -> "hm0y6nagoLKwh8EanEkF13bj4Tx83Yp2R+Kr2xGmvIs="
        tags                           = {}
        # (21 unchanged attributes hidden)

        # (4 unchanged blocks hidden)
    }

  # module.lambdas.aws_lambda_function.slack_alert will be updated in-place
  ~ resource "aws_lambda_function" "slack_alert" {
        id                             = "javabin-slack-alert"
      ~ last_modified                  = "2026-03-26T19:54:56.000+0000" -> (known after apply)
      ~ source_code_hash               = "//EAo2qOP1ujBcWSwzIrY7e+x0ayJTBlQZWAO/RzIO4=" -> "hm0y6nagoLKwh8EanEkF13bj4Tx83Yp2R+Kr2xGmvIs="
        tags                           = {}
        # (21 unchanged attributes hidden)

        # (4 unchanged blocks hidden)
    }

  # module.monitoring.aws_config_config_rule.required_tags will be updated in-place
  ~ resource "aws_config_config_rule" "required_tags" {
        id               = "javabin-required-tags"
      ~ input_parameters = jsonencode(
          ~ {
              ~ tag1Key = "project" -> "service"
                # (2 unchanged attributes hidden)
            }
        )
        name             = "javabin-required-tags"
        tags             = {}
        # (3 unchanged attributes hidden)

        # (2 unchanged blocks hidden)
    }

Plan: 5 to add, 3 to change, 0 to destroy.

─────────────────────────────────────────────────────────────────────────────

Saved the plan to: tfplan

To perform exactly these actions, run the following command to apply:
    terraform apply "tfplan"

LLM Review

Risk: 🟢 LOW

Plan adds cost analytics infrastructure (BCM Data Exports, Glue Crawler) and updates Lambda functions and Config rules with no destructive changes.

  • [routine] Lambda function updates (securityhub_summary, slack_alert) - source code hash changes indicate code updates, standard operational change
  • [routine] Config rule parameter update - tag1Key changed from 'project' to 'service' in required_tags rule, aligns with existing tagging strategy
  • 💰 [cost] New BCM Data Exports resource (aws_bcmdataexports_export) - enables Cost and Usage Report export to S3 with daily granularity, minimal cost impact
  • [routine] New Glue Crawler (aws_glue_crawler) - scheduled daily at 6 AM to catalog CUR data in S3, standard data pipeline component
  • [routine] New IAM role and policy for Glue Crawler - scoped to read-only access on CUR S3 bucket with standard AWSGlueServiceRole attachment

@Alexanderamiri Alexanderamiri merged commit bfa000a into main Mar 26, 2026
3 checks passed
@Alexanderamiri Alexanderamiri deleted the fix/alert-formatting branch March 26, 2026 22:14
Alexanderamiri added a commit that referenced this pull request May 9, 2026
## Summary

**Config rule fix:**
- Changed `tag1Key` from `project` to `service` — `default_tags` sets
`service`, not `project`. This was causing false-positive untagged
resource alerts on every platform resource.

**Slack alert restructuring:**
- Service name now in the header (e.g. `:package: S3 Created (CI/CD)`
instead of `:package: Resource Created (CI/CD)`)
- Resource shown first in the fields grid, action moved lower
- "triggered by {actor}" removed from source line — actor now in footer
- Footer enriched with resource tags (team, service, commit, repo,
environment) when available from CloudTrail
- Compliance alert text updated to reference `service, team, managed-by`

**Before:**
```
:package: Resource Created (CI/CD)
Source: javaBin/platform / 23f03cd / run (triggered by Alexanderamiri)
Action: CreateBucket | Resource: javabin-cur-553637109631 | Created by: javabin-ci-infra | Region: eu-central-1 | Service: S3
AWS Account 553637109631 | eu-central-1 | 2026-03-26T21:51:29Z
```

**After:**
```
:package: S3 Created (CI/CD)
Source: javaBin/platform / 23f03cd / run
Resource: javabin-cur-553637109631 | Est. Cost: $0.022/GB/mo | Action: CreateBucket | Region: eu-central-1
AWS Account 553637109631 | eu-central-1 | 2026-03-26T21:51:29Z
By: javabin-ci-infra (CI/CD)
team=platform | service=platform | repo=javaBin/platform
```

## Test plan

- [ ] `terraform validate` passes
- [ ] Deploy via CI, check that new resource alerts have service in
header
- [ ] Verify no more false-positive untagged resource alerts for
platform resources
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant