Skip to content

chore: use KMS-only SOPS encryption and stop age key publishing#10

Merged
xnoto merged 4 commits into
mainfrom
chore/add-sops-kms-recipient
Jun 19, 2026
Merged

chore: use KMS-only SOPS encryption and stop age key publishing#10
xnoto merged 4 commits into
mainfrom
chore/add-sops-kms-recipient

Conversation

@xnoto

@xnoto xnoto commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add the Make IT Work Cloud SOPS AWS KMS key as the SOPS recipient
  • remove the age recipient from .sops.yaml
  • re-key secrets/secrets.yaml so SOPS metadata is KMS-only
  • grant the caller workflow id-token: write for the shared workflow's GitHub OIDC role assumption
  • stop publishing SOPS_AGE_KEY as a GitHub Actions secret to tfroot repositories
  • remove the encrypted sops_age_key value from this repo's SOPS secrets file

Dependency / rollout

  • Requires makeitworkcloud/tfroot-aws#6 and makeitworkcloud/shared-workflows#7, both now merged/applied.
  • Applying this PR will remove managed SOPS_AGE_KEY GitHub Actions secrets from the tfroot repositories.

Validation

  • AWS_PROFILE=makeitwork sops decrypt --output /dev/null secrets/secrets.yaml
  • verified SOPS metadata has kms=1 and age=0
  • verified no remaining SOPS_AGE_KEY / sops_age_key references
  • PCT_TFPATH=$(command -v tofu) pre-commit run --all-files

@xnoto xnoto self-assigned this Jun 19, 2026
@xnoto xnoto changed the title chore: add SOPS KMS recipient chore: add SOPS KMS recipient and remove age key publishing Jun 19, 2026
@xnoto xnoto changed the title chore: add SOPS KMS recipient and remove age key publishing chore: use KMS-only SOPS encryption and stop age key publishing Jun 19, 2026
@github-actions

Copy link
Copy Markdown

OpenTofu Plan

OpenTofu will perform the following actions:

  # github_actions_secret.secrets["tfroot-aws_SOPS_AGE_KEY"] will be destroyed
  # (because key ["tfroot-aws_SOPS_AGE_KEY"] is not in for_each map)
  - resource "github_actions_secret" "secrets" {
      - created_at        = "2025-12-20 20:49:17 +0000 UTC" -> null
      - destroy_on_drift  = false -> null
      - id                = "tfroot-aws:SOPS_AGE_KEY" -> null
      - key_id            = "3380204578043523366" -> null
      - plaintext_value   = (sensitive value) -> null
      - remote_updated_at = "2026-02-19 17:31:39 +0000 UTC" -> null
      - repository        = "tfroot-aws" -> null
      - repository_id     = 1120266217 -> null
      - secret_name       = "SOPS_AGE_KEY" -> null
      - updated_at        = "2026-02-19 17:31:39 +0000 UTC" -> null
    }

  # github_actions_secret.secrets["tfroot-cloudflare_SOPS_AGE_KEY"] will be destroyed
  # (because key ["tfroot-cloudflare_SOPS_AGE_KEY"] is not in for_each map)
  - resource "github_actions_secret" "secrets" {
      - created_at        = "2025-12-20 20:49:47 +0000 UTC" -> null
      - destroy_on_drift  = false -> null
      - id                = "tfroot-cloudflare:SOPS_AGE_KEY" -> null
      - key_id            = "3380204578043523366" -> null
      - plaintext_value   = (sensitive value) -> null
      - remote_updated_at = "2026-02-19 17:31:57 +0000 UTC" -> null
      - repository        = "tfroot-cloudflare" -> null
      - repository_id     = 1120266256 -> null
      - secret_name       = "SOPS_AGE_KEY" -> null
      - updated_at        = "2026-02-19 17:31:57 +0000 UTC" -> null
    }

  # github_actions_secret.secrets["tfroot-github_SOPS_AGE_KEY"] will be destroyed
  # (because key ["tfroot-github_SOPS_AGE_KEY"] is not in for_each map)
  - resource "github_actions_secret" "secrets" {
      - created_at        = "2025-12-20 20:50:13 +0000 UTC" -> null
      - destroy_on_drift  = false -> null
      - id                = "tfroot-github:SOPS_AGE_KEY" -> null
      - key_id            = "3380204578043523366" -> null
      - plaintext_value   = (sensitive value) -> null
      - remote_updated_at = "2026-02-19 17:31:45 +0000 UTC" -> null
      - repository        = "tfroot-github" -> null
      - repository_id     = 1120266290 -> null
      - secret_name       = "SOPS_AGE_KEY" -> null
      - updated_at        = "2026-02-19 17:31:45 +0000 UTC" -> null
    }

  # github_actions_secret.secrets["tfroot-libvirt_SOPS_AGE_KEY"] will be destroyed
  # (because key ["tfroot-libvirt_SOPS_AGE_KEY"] is not in for_each map)
  - resource "github_actions_secret" "secrets" {
      - created_at        = "2025-12-20 20:50:09 +0000 UTC" -> null
      - destroy_on_drift  = false -> null
      - id                = "tfroot-libvirt:SOPS_AGE_KEY" -> null
      - key_id            = "3380204578043523366" -> null
      - plaintext_value   = (sensitive value) -> null
      - remote_updated_at = "2026-02-19 17:32:09 +0000 UTC" -> null
      - repository        = "tfroot-libvirt" -> null
      - repository_id     = 1120266280 -> null
      - secret_name       = "SOPS_AGE_KEY" -> null
      - updated_at        = "2026-02-19 17:32:09 +0000 UTC" -> null
    }

  # github_branch_protection.protections[".github"] will be updated in-place
  ~ resource "github_branch_protection" "protections" {
        id                              = "BPR_kwDOPDNmL84EC8t_"
        # (10 unchanged attributes hidden)

      ~ required_pull_request_reviews {
          ~ dismissal_restrictions          = [
              + "makeitworkcloud/admins",
            ]
          ~ pull_request_bypassers          = [
              + "makeitworkcloud/admins",
            ]
            # (5 unchanged attributes hidden)
        }

      ~ restrict_pushes {
          ~ push_allowances  = [
              + "makeitworkcloud/admins",
            ]
            # (1 unchanged attribute hidden)
        }

        # (1 unchanged block hidden)
    }

  # github_branch_protection.protections["cflan"] will be updated in-place
  ~ resource "github_branch_protection" "protections" {
        id                              = "BPR_kwDOOulWjM4EPi_e"
        # (10 unchanged attributes hidden)

      ~ required_pull_request_reviews {
          ~ dismissal_restrictions          = [
              + "makeitworkcloud/admins",
            ]
          ~ pull_request_bypassers          = [
              + "makeitworkcloud/admins",
            ]
            # (5 unchanged attributes hidden)
        }

      ~ restrict_pushes {
          ~ push_allowances  = [
              + "makeitworkcloud/admins",
            ]
            # (1 unchanged attribute hidden)
        }

        # (1 unchanged block hidden)
    }

  # github_branch_protection.protections["images"] will be updated in-place
  ~ resource "github_branch_protection" "protections" {
        id                              = "BPR_kwDOQsexys4EPi_f"
        # (10 unchanged attributes hidden)

      ~ required_pull_request_reviews {
          ~ dismissal_restrictions          = [
              + "makeitworkcloud/admins",
            ]
          ~ pull_request_bypassers          = [
              + "makeitworkcloud/admins",
            ]
            # (5 unchanged attributes hidden)
        }

      ~ restrict_pushes {
          ~ push_allowances  = [
              + "makeitworkcloud/admins",
            ]
            # (1 unchanged attribute hidden)
        }

        # (1 unchanged block hidden)
    }

  # github_branch_protection.protections["kustomize-cluster"] will be updated in-place
  ~ resource "github_branch_protection" "protections" {
        id                              = "BPR_kwDOQsxTyc4EPi_g"
        # (10 unchanged attributes hidden)

      ~ required_pull_request_reviews {
          ~ dismissal_restrictions          = [
              + "makeitworkcloud/admins",
            ]
          ~ pull_request_bypassers          = [
              + "makeitworkcloud/admins",
            ]
            # (5 unchanged attributes hidden)
        }

      ~ restrict_pushes {
          ~ push_allowances  = [
              + "makeitworkcloud/admins",
            ]
            # (1 unchanged attribute hidden)
        }

        # (1 unchanged block hidden)
    }

  # github_branch_protection.protections["shared-workflows"] will be updated in-place
  ~ resource "github_branch_protection" "protections" {
        id                              = "BPR_kwDOQsfaHs4EPi_h"
        # (10 unchanged attributes hidden)

      ~ required_pull_request_reviews {
          ~ dismissal_restrictions          = [
              + "makeitworkcloud/admins",
            ]
          ~ pull_request_bypassers          = [
              + "makeitworkcloud/admins",
            ]
            # (5 unchanged attributes hidden)
        }

      ~ restrict_pushes {
          ~ push_allowances  = [
              + "makeitworkcloud/admins",
            ]
            # (1 unchanged attribute hidden)
        }

        # (1 unchanged block hidden)
    }

  # github_branch_protection.protections["terraform-libvirt-domain"] will be updated in-place
  ~ resource "github_branch_protection" "protections" {
        id                              = "BPR_kwDOQsXn984EPi_i"
        # (10 unchanged attributes hidden)

      ~ required_pull_request_reviews {
          ~ dismissal_restrictions          = [
              + "makeitworkcloud/admins",
            ]
          ~ pull_request_bypassers          = [
              + "makeitworkcloud/admins",
            ]
            # (5 unchanged attributes hidden)
        }

      ~ restrict_pushes {
          ~ push_allowances  = [
              + "makeitworkcloud/admins",
            ]
            # (1 unchanged attribute hidden)
        }

        # (1 unchanged block hidden)
    }

  # github_branch_protection.protections["tfroot-aws"] will be updated in-place
  ~ resource "github_branch_protection" "protections" {
        id                              = "BPR_kwDOQsXn6c4EPi_j"
        # (10 unchanged attributes hidden)

      ~ required_pull_request_reviews {
          ~ dismissal_restrictions          = [
              + "makeitworkcloud/admins",
            ]
          ~ pull_request_bypassers          = [
              + "makeitworkcloud/admins",
            ]
            # (5 unchanged attributes hidden)
        }

      ~ restrict_pushes {
          ~ push_allowances  = [
              + "makeitworkcloud/admins",
            ]
            # (1 unchanged attribute hidden)
        }

        # (1 unchanged block hidden)
    }

  # github_branch_protection.protections["tfroot-cloudflare"] will be updated in-place
  ~ resource "github_branch_protection" "protections" {
        id                              = "BPR_kwDOQsXoEM4EPi_k"
        # (10 unchanged attributes hidden)

      ~ required_pull_request_reviews {
          ~ dismissal_restrictions          = [
              + "makeitworkcloud/admins",
            ]
          ~ pull_request_bypassers          = [
              + "makeitworkcloud/admins",
            ]
            # (5 unchanged attributes hidden)
        }

      ~ restrict_pushes {
          ~ push_allowances  = [
              + "makeitworkcloud/admins",
            ]
            # (1 unchanged attribute hidden)
        }

        # (1 unchanged block hidden)
    }

  # github_branch_protection.protections["tfroot-github"] will be updated in-place
  ~ resource "github_branch_protection" "protections" {
        id                              = "BPR_kwDOQsXoMs4EPi_l"
        # (10 unchanged attributes hidden)

      ~ required_pull_request_reviews {
          ~ dismissal_restrictions          = [
              + "makeitworkcloud/admins",
            ]
          ~ pull_request_bypassers          = [
              + "makeitworkcloud/admins",
            ]
            # (5 unchanged attributes hidden)
        }

      ~ restrict_pushes {
          ~ push_allowances  = [
              + "makeitworkcloud/admins",
            ]
            # (1 unchanged attribute hidden)
        }

        # (1 unchanged block hidden)
    }

  # github_branch_protection.protections["tfroot-libvirt"] will be updated in-place
  ~ resource "github_branch_protection" "protections" {
        id                              = "BPR_kwDOQsXoKM4EPi_n"
        # (10 unchanged attributes hidden)

      ~ required_pull_request_reviews {
          ~ dismissal_restrictions          = [
              + "makeitworkcloud/admins",
            ]
          ~ pull_request_bypassers          = [
              + "makeitworkcloud/admins",
            ]
            # (5 unchanged attributes hidden)
        }

      ~ restrict_pushes {
          ~ push_allowances  = [
              + "makeitworkcloud/admins",
            ]
            # (1 unchanged attribute hidden)
        }

        # (1 unchanged block hidden)
    }

  # github_branch_protection.protections["www"] will be updated in-place
  ~ resource "github_branch_protection" "protections" {
        id                              = "BPR_kwDOOuKZAc4EPi_o"
        # (10 unchanged attributes hidden)

      ~ required_pull_request_reviews {
          ~ dismissal_restrictions          = [
              + "makeitworkcloud/admins",
            ]
          ~ pull_request_bypassers          = [
              + "makeitworkcloud/admins",
            ]
            # (5 unchanged attributes hidden)
        }

      ~ restrict_pushes {
          ~ push_allowances  = [
              + "makeitworkcloud/admins",
            ]
            # (1 unchanged attribute hidden)
        }

        # (1 unchanged block hidden)
    }

Plan: 0 to add, 11 to change, 4 to destroy.

@xnoto xnoto merged commit dee8d07 into main Jun 19, 2026
3 checks passed
@xnoto xnoto deleted the chore/add-sops-kms-recipient branch June 19, 2026 04:20
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