Skip to content

feat(aws): add Hero host-config SOPS identity - #52

Merged
xnoto merged 2 commits into
mainfrom
feat/hero-host-config-sops-kms
Sep 5, 2026
Merged

feat(aws): add Hero host-config SOPS identity#52
xnoto merged 2 commits into
mainfrom
feat/hero-host-config-sops-kms

Conversation

@xnoto

@xnoto xnoto commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Creates a dedicated AWS KMS recipient and a main-only GitHub OIDC decrypt role for hero-host-config. This is the least-privilege prerequisite for that repository's future SOPS-encrypted Cloudflared configuration, credential material, and Ansible management key.

No S3 bucket or Secrets Manager secret is added: the intended secret source is Git-native SOPS ciphertext, encrypted with this dedicated KMS key. The existing shared SOPS role and key are unchanged.

Fixes #

None — owner-authorized Hero host-management bootstrap work.

Type of change

  • Bug fix
  • Feature / enhancement
  • Documentation
  • Infrastructure (OpenTofu root or module)
  • GitOps desired state (manifests, kustomize, charts, SOPS/KSOPS secrets)
  • Container image
  • CI / reusable workflow
  • Refactor / cleanup
  • Breaking change

Validation

  • Required pull-request checks pass — opentofu / test and opentofu / plan succeeded.
  • Generated or centrally distributed files were regenerated by their owning automation, not hand-edited — the repository-owned pre-commit automation regenerated README.md after adding the OpenTofu resources and outputs.

No local OpenTofu init, plan, apply, import, state, or secret-decryption operation was run or claimed.

Impact and rollout

Producer: tfroot-aws will own the dedicated KMS key, alias, and OIDC role.

Consumers: after a successful environment-gated apply, hero-host-config may use the KMS key as its SOPS recipient, and only its main GitHub Actions workflow may assume the new role to decrypt that repository's SOPS data. tfroot-github and tfroot-cloudflare remain separate producers for the future dedicated WARP enrollment credentials.

Delivery stages: authored and CI-validated on this branch. Merge, environment-gated apply, KMS/role creation, encrypted-secret migration, WARP enrollment, host bootstrap, and Node Exporter deployment remain incomplete.

Rollback: before apply, close or revert this PR. After apply, do not blindly remove the key: it has prevent_destroy and a 30-day deletion window. Make an explicit retention and ciphertext-migration decision first.

Safety and secrets

  • Contains no plaintext secrets, decrypted SOPS values, state files, kubeconfigs, tokens, or private endpoints.
  • No local OpenTofu init/plan/apply/destroy/import/state operations were run or claimed — plans come from pull-request checks.
  • Breaking or irreversible effects are described above with rollback notes.

AI-assisted change: an OpenCode agent materially prepared this branch and pull request. Review the OIDC trust subject, main-only decrypt boundary, key-retention settings, generated README update, and absence of an unnecessary S3 or Secrets Manager backend before merge.

@xnoto
xnoto requested a review from a team as a code owner September 5, 2026 17:29
@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

OpenTofu Test

OpenTofu test passed.

View the workflow run.

View run output
Terraform validate.......................................................Passed
Terraform validate with tflint...........................................Passed
Checkov..................................................................Passed
Terraform fmt............................................................Passed
Terraform docs...........................................................Passed
Detect hardcoded secrets.................................................Passed
check for case conflicts.................................................Passed
check for merge conflicts................................................Passed
check for broken symlinks............................(no files to check)Skipped
check vcs permalinks.....................................................Passed
detect destroyed symlinks................................................Passed
detect private key.......................................................Passed
fix end of files.........................................................Passed
mixed line ending........................................................Passed
trim trailing whitespace.................................................Passed
don't commit to branch..................................................Skipped
check for added large files..............................................Passed

@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

OpenTofu Plan

OpenTofu plan passed.

View the workflow run.

View run output
OpenTofu will perform the following actions:

[REDACTED: potentially sensitive plan output]
[REDACTED: potentially sensitive plan output]
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRoleWithWebIdentity"
                      + Condition = {
                          + StringEquals = {
[REDACTED: potentially sensitive plan output]
[REDACTED: potentially sensitive plan output]
                            }
                        }
                      + Effect    = "Allow"
                      + Principal = {
[REDACTED: potentially sensitive plan output]
                        }
                    },
                ]
              + 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
[REDACTED: potentially sensitive plan output]
      + name_prefix           = (known after apply)
      + path                  = "/"
      + tags                  = {
          + "ManagedBy" = "Terraform"
[REDACTED: potentially sensitive plan output]
        }
      + tags_all              = {
          + "ManagedBy" = "Terraform"
[REDACTED: potentially sensitive plan output]
        }
      + unique_id             = (known after apply)

      + inline_policy (known after apply)
    }

[REDACTED: potentially sensitive plan output]
[REDACTED: potentially sensitive plan output]
      + id          = (known after apply)
[REDACTED: potentially sensitive plan output]
      + name_prefix = (known after apply)
      + policy      = (known after apply)
      + role        = (known after apply)
    }

[REDACTED: potentially sensitive plan output]
[REDACTED: potentially sensitive plan output]
      + arn            = (known after apply)
      + id             = (known after apply)
[REDACTED: potentially sensitive plan output]
      + name_prefix    = (known after apply)
      + region         = "us-west-2"
      + target_key_arn = (known after apply)
      + target_key_id  = (known after apply)
    }

[REDACTED: potentially sensitive plan output]
[REDACTED: potentially sensitive plan output]
      + arn                                = (known after apply)
      + bypass_policy_lockout_safety_check = false
      + customer_master_key_spec           = "SYMMETRIC_DEFAULT"
      + deletion_window_in_days            = 30
[REDACTED: potentially sensitive plan output]
      + enable_key_rotation                = true
      + id                                 = (known after apply)
      + is_enabled                         = true
      + key_id                             = (known after apply)
      + key_usage                          = "ENCRYPT_DECRYPT"
      + multi_region                       = (known after apply)
      + policy                             = (known after apply)
      + region                             = "us-west-2"
      + rotation_period_in_days            = (known after apply)
      + tags                               = {
          + "ManagedBy" = "Terraform"
[REDACTED: potentially sensitive plan output]
        }
      + tags_all                           = {
          + "ManagedBy" = "Terraform"
[REDACTED: potentially sensitive plan output]
        }
    }

Plan: 4 to add, 0 to change, 0 to destroy.
OpenTofu will perform the following actions:

[REDACTED: potentially sensitive plan output]
[REDACTED: potentially sensitive plan output]
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRoleWithWebIdentity"
                      + Condition = {
                          + StringEquals = {
[REDACTED: potentially sensitive plan output]
[REDACTED: potentially sensitive plan output]
                            }
                        }
                      + Effect    = "Allow"
                      + Principal = {
[REDACTED: potentially sensitive plan output]
                        }
                    },
                ]
              + 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
[REDACTED: potentially sensitive plan output]
      + name_prefix           = (known after apply)
      + path                  = "/"
      + tags                  = {
          + "ManagedBy" = "Terraform"
[REDACTED: potentially sensitive plan output]
        }
      + tags_all              = {
          + "ManagedBy" = "Terraform"
[REDACTED: potentially sensitive plan output]
        }
      + unique_id             = (known after apply)

      + inline_policy (known after apply)
    }

[REDACTED: potentially sensitive plan output]
[REDACTED: potentially sensitive plan output]
      + id          = (known after apply)
[REDACTED: potentially sensitive plan output]
      + name_prefix = (known after apply)
      + policy      = (known after apply)
      + role        = (known after apply)
    }

[REDACTED: potentially sensitive plan output]
[REDACTED: potentially sensitive plan output]
      + arn            = (known after apply)
      + id             = (known after apply)
[REDACTED: potentially sensitive plan output]
      + name_prefix    = (known after apply)
      + region         = "us-west-2"
      + target_key_arn = (known after apply)
      + target_key_id  = (known after apply)
    }

[REDACTED: potentially sensitive plan output]
[REDACTED: potentially sensitive plan output]
      + arn                                = (known after apply)
      + bypass_policy_lockout_safety_check = false
      + customer_master_key_spec           = "SYMMETRIC_DEFAULT"
      + deletion_window_in_days            = 30
[REDACTED: potentially sensitive plan output]
      + enable_key_rotation                = true
      + id                                 = (known after apply)
      + is_enabled                         = true
      + key_id                             = (known after apply)
      + key_usage                          = "ENCRYPT_DECRYPT"
      + multi_region                       = (known after apply)
      + policy                             = (known after apply)
      + region                             = "us-west-2"
      + rotation_period_in_days            = (known after apply)
      + tags                               = {
          + "ManagedBy" = "Terraform"
[REDACTED: potentially sensitive plan output]
        }
      + tags_all                           = {
          + "ManagedBy" = "Terraform"
[REDACTED: potentially sensitive plan output]
        }
    }

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

@xnoto
xnoto merged commit 4e65af3 into main Sep 5, 2026
3 checks passed
@xnoto
xnoto deleted the feat/hero-host-config-sops-kms branch September 5, 2026 17:36
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