Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🟧 AWS CodeCommit Terraform Module

Secure-by-default AWS CodeCommit Git repository — a private, always-encrypted repository, one guarded trigger configuration fanning out to a notification target (typically SNS), and reusable pull-request approval-rule templates that are automatically associated with the repository, all from a single composite call. Built for the AWS provider v6.x.

Terraform aws module type resources


⚠️ Before you use this module: AWS CodeCommit has been closed to new AWS customers since mid-2024. If your account never used CodeCommit before that cutoff, aws_codecommit_repository creation will very likely fail — this module cannot preflight AWS account eligibility. See 📋 AWS Prerequisites before authoring any call that creates a new repository. Accounts with pre-existing CodeCommit usage can continue creating repositories; this module also fully supports managing pre-existing repositories via terraform import regardless of eligibility — see Example Library #14.


🧩 Overview

  • 🏗️ Provisions an aws_codecommit_repository keystone — always encrypted, always private, never anything else.
  • 🔔 One guarded trigger configuration per repository, rendered as a dynamic "trigger" block over var.triggers inside a single aws_codecommit_trigger resource — the provider allows only one such resource per repository and replaces all triggers (including manually-created ones) whenever it applies.
  • Pull-request approval-rule templates, for_each-managed, each automatically associated with the repository so the template actually takes effect — an unassociated template is a silent no-op, so this module never leaves one dangling.
  • 🔐 Encryption is not optional — the AWS-managed aws/codecommit key by default, or a caller-supplied customer-managed KMS key (CMK) for tighter key-policy control and independent revocability.
  • 🏷️ Universal tagging on the repository (the only one of the four managed resources that accepts tags — verified against the live provider schema); tags_all surfaced as an output.
  • 🧱 Deliberately small and near-foundational: originates its own repository_id / arn / clone URLs and reaches out only for an optional CMK, an optional notification destination, and optional approver principal ARNs — everything else (the SNS topic, the CMK, the IAM principals) is a sibling module's concern.

💡 Why it matters: our change-control posture for source that may touch regulated systems needs a Git repository that is private and encrypted by construction, wired for downstream automation (SNS-fed pipelines), and capable of enforcing a mandatory code-review gate — all without a second module call to make the approval gate actually bite.


❤️ Support this project

If these Terraform modules have been helpful to you or your organization, I'd appreciate your support in any of the following ways:

Whether it's a star, a professional connection, or a coffee, every gesture helps keep these modules actively maintained and continually improving. Thank you for being part of the community!


🗺️ Where this fits in the family

terraform-aws-codecommit is a near-foundation module: it originates its own repository identity and reaches out only for an optional CMK, an optional trigger destination, and optional approver principal ARNs.

flowchart LR
 codecommit["terraform-aws-codecommit"]
 kms["terraform-aws-kms"]
 sns["terraform-aws-sns"]
 iam["terraform-aws-iam-role"]
 vpcep["terraform-aws-vpc-endpoint"]
 codeguru["CodeGuru Reviewer /\nCodeStar associations\n(sibling modules)"]
 cwevents["EventBridge / CloudWatch\nEvents rules (sibling modules)"]

 kms -. "kms_key_id (optional CMK)".-> codecommit
 sns -. "triggers[*].destination_arn".-> codecommit
 iam -. "approval_rule_templates[*].content\n.statements[*].approval_pool_members".-> codecommit

 codecommit -- "arn" --> codeguru
 codecommit -- "arn" --> cwevents
 codecommit -- "repository_name (private access only)" --> vpcep

 style codecommit fill:#FF9900,color:#fff,stroke:#cc7a00,stroke-width:2px
Loading

🧬 What this module builds

flowchart TB
 subgraph CCMOD["terraform-aws-codecommit"]
 repo["aws_codecommit_repository.this\n(keystone)"]

 subgraph TRIG["Trigger configuration (0-1 resource)"]
 trig["aws_codecommit_trigger.this\nguarded for_each, 1 resource max\ndynamic trigger block per var.triggers entry\n(AWS caps 10 triggers/repo)"]
 end

 subgraph APPROVAL["Approval rule templates (for_each)"]
 tmpl["aws_codecommit_approval_rule_template.this\nfor_each var.approval_rule_templates"]
 assoc["aws_codecommit_approval_rule_template_association.this\nfor_each var.approval_rule_templates"]
 end
 end

 repo --> trig
 repo --> assoc
 tmpl --> assoc

 style repo fill:#FF9900,color:#fff,stroke:#cc7a00,stroke-width:2px
Loading
Resource Role Cardinality
aws_codecommit_repository.this Keystone Git repository 1
aws_codecommit_trigger.this Single trigger configuration; one trigger{} block per var.triggers entry 0–1 (present only when var.triggers is non-empty)
aws_codecommit_approval_rule_template.this Pull-request approval-rule template content per approval_rule_templates entry
aws_codecommit_approval_rule_template_association.this Binds each template to aws_codecommit_repository.this per approval_rule_templates entry (1:1 with the template)

✅ Provider / Versions

Requirement Version
Terraform >= 1.12.0
hashicorp/aws >= 6.0, < 7.0

No provider {} block is declared inside the module — the caller's configured provider (region/credentials) is inherited. No region variable — CodeCommit is a regional service with no DR/replication semantics in this module.


🔑 Required IAM Permissions

Least-privilege actions the Terraform identity needs to create, read, update, and delete everything this module manages:

Action Required for Notes
codecommit:CreateRepository Repository creation Fails with a restriction-related error if the account has never used CodeCommit before mid-2024 — see AWS Prerequisites
codecommit:GetRepository Read-back / drift detection
codecommit:UpdateRepositoryDescription description changes
codecommit:UpdateRepositoryName repository_name renames Supported by the API, but treat as force-new in practice — see Architecture Notes
codecommit:UpdateDefaultBranch default_branch changes The named branch must already exist
codecommit:DeleteRepository Repository destroy Irreversible — repository content is not recoverable
codecommit:TagResource, codecommit:UntagResource, codecommit:ListTagsForResource Tagging Repository only — the trigger, approval-rule-template, and association resources expose no tags argument
codecommit:PutRepositoryTriggers, codecommit:GetRepositoryTriggers Trigger configuration PutRepositoryTriggers replaces all triggers on the repository, Terraform-managed or not
codecommit:TestRepositoryTriggers Optional Not called by the provider; useful for a manual, out-of-band test of a destination
codecommit:CreateApprovalRuleTemplate, codecommit:GetApprovalRuleTemplate, codecommit:UpdateApprovalRuleTemplateContent, codecommit:UpdateApprovalRuleTemplateDescription, codecommit:DeleteApprovalRuleTemplate Approval-rule template lifecycle
codecommit:AssociateApprovalRuleTemplateWithRepository, codecommit:DisassociateApprovalRuleTemplateFromRepository, codecommit:ListAssociatedApprovalRuleTemplatesForRepository Binding templates to the repository
kms:DescribeKey, kms:CreateGrant Only when kms_key_id is a customer-managed CMK The CMK's key policy must independently allow both the Terraform principal and the codecommit.amazonaws.com service principal
sns:GetTopicAttributes Optional Plan-time sanity check of a caller-supplied destination_arn; not required by the provider itself

ℹ️ No service-linked role is created or required by any action in this module. There is no iam:PassRole requirement anywhere — no in-scope resource assumes a role.


📋 AWS Prerequisites

⚠️ AWS CodeCommit has been closed to new AWS customers since mid-2024. AWS confirmed that customers who had not already used CodeCommit before that date cannot create new CodeCommit repositories, while existing CodeCommit customers (accounts with pre-existing repositories as of the cutoff) can continue creating new repositories and using the service with no announced end-of-life. This module cannot preflight account eligibility — Terraform has no API for it. Before authoring or running a call that creates a new repository, independently confirm eligibility by:

  1. Checking the AWS Management Console → CodeCommit landing page in the target account for an eligibility banner, or
  2. Attempting aws codecommit create-repository (or a disposable terraform plan/apply) in a sandbox account first, or
  3. Confirming with AWS Support / the account team whether the account has pre-existing CodeCommit usage.

If the target account cannot create repositories, this module is still useful for managing pre-existing repositories — triggers, approval-rule templates, and tags — via terraform import (Example Library #14). Re-checked against the aws-documentation MCP during this authoring session: the indexed userguide corpus does not surface AWS's own announcement text (it lives on the pricing/what's-new pages, not the userguide), which is consistent with — not evidence against — the restriction.

Beyond the account-eligibility gate:

  • No service-linked role is required for CodeCommit resources.
  • Region availability: CodeCommit is available in a defined subset of AWS Regions (e.g. US East N. Virginia/Ohio, US West Oregon/N. California, several EU/Asia Pacific/Middle East/South America Regions, Canada Central, China Beijing/Ningxia, and both AWS GovCloud (US) Regions) — not every Region. Confirm the target Region is supported before relying on provider inheritance; there is no cross-Region replication for a single repository.
  • KMS (optional CMK): if kms_key_id is supplied, the CMK's key policy must grant the codecommit.amazonaws.com service principal and the calling principal kms:GenerateDataKey / kms:Decrypt, or repository operations fail with access-denied errors that surface as CodeCommit errors, not KMS ones.
  • SNS trigger destination: if a trigger targets an SNS topic, that topic's access policy must explicitly allow codecommit.amazonaws.com to sns:Publish — this module does not create or modify the destination or its policy.
  • Quotas (verified against the AWS CodeCommit Limits page; corrects stale figures from an earlier scoping pass — see SCOPE.md Provider gotchas for the full correction):
  • 5,000 repositories per AWS account (soft, account-wide — not per-Region).
  • No cap on total branches per repository; 4,000 is the limit on Git references accepted in a single push, not a repository-wide branch cap.
  • 10 triggers per repository — matches the live provider schema's max_items = 10 on the trigger block.
  • 100 files per commit via console/API/CLI (unlimited via the Git CLI protocol itself, subject to 6 MB file / 20 MB commit-metadata / 2 GB Git-blob ceilings).
  • 1,000 approval rule templates per Region; up to 30 approval rules per pull request (25 of which may come from templates); 3,000-character max template content.
  • IAM Identity Center / SSO users cannot authenticate to CodeCommit with Git credentials the same way IAM users can; federated callers need git-remote-codecommit with temporary credentials or SSH public keys uploaded to IAM users.

📁 Module Structure

terraform-aws-codecommit/
├── providers.tf # terraform{} + required_providers (aws >= 6.0, < 7.0); no provider block
├── variables.tf # repository_name, description, default_branch, kms_key_id, triggers, approval_rule_templates, tags
├── main.tf # aws_codecommit_repository.this + guarded trigger + approval-rule template/association for_each
├── outputs.tf # id + arn, clone URLs, trigger_configuration_id, approval-rule-template maps, tags_all
├── README.md # this file
└── SCOPE.md # in/out-of-scope, IAM, prerequisites, emits, gotchas

⚙️ Quick Start

module "repo" {
  source = "git::https://github.com/microsoftexpert/terraform-aws-codecommit?ref=v1.0.0"

  repository_name = "lending-portal-api"
  description     = "Lending Portal API service source"

  tags = {
    Environment = "prod"
    CostCenter  = "lending"
  }
}

⚠️ Pin the source with ?ref=v1.0.0 — never a branch. Confirm account eligibility (see AWS Prerequisites) before running this against an account that has never used CodeCommit.


🔌 Cross-Module Contract

Consumes

Input Type Source module
kms_key_id (optional) string (KMS key ARN or id) terraform-aws-kms — omit to use the AWS-managed aws/codecommit key
triggers[*].destination_arn (optional) string (ARN) terraform-aws-sns (Phase 2) — SNS topic ARN as the notification target
approval_rule_templates[*].content.statements[*].approval_pool_members (optional) list(string) (IAM ARN or assumed-role ARN pattern) terraform-aws-iam-role — principals eligible to approve pull requests

This is otherwise a near-foundation module — it originates its own repository_id / arn / clone URLs and only reaches out for an optional CMK and optional notification/approval targets.

Emits

Output Description Consumed by
id / repository_id System-generated repository id Reference/audit, import blocks
arn Repository ARN — cross-resource reference type IAM policy Resource elements, approval-rule ApprovalPoolMembers scoping, CodeGuru Reviewer associations
clone_url_http / clone_url_ssh Clone URLs CI/CD checkout steps, developer onboarding, SSH-based CI runners
repository_name The repository's name (also its import key) This module's own trigger/association wiring; downstream naming conventions
default_branch Configured default branch, if set Branch-protection / pipeline configuration
kms_key_id Effective encryption key ARN/id Compliance audit of the effective encryption key
trigger_configuration_id Singular configuration_id of the one trigger configuration; null when no triggers Audit/troubleshooting trigger delivery
approval_rule_template_ids Map of template key → approval_rule_template_id terraform-aws-iam-role cross-references, audit
approval_rule_template_association_ids Map of template key → association id Audit, terraform import key
tags_all All tags incl. provider default_tags Governance/audit

📚 Example Library

1 · Minimal repository
module "repo" {
  source = "git::https://github.com/microsoftexpert/terraform-aws-codecommit?ref=v1.0.0"

  repository_name = "sandbox-repo"
}
2 · Description + default_branch on an existing repository
# default_branch requires the branch to already exist -- do NOT set this on
# the same apply that creates the repository (it will fail; CodeCommit
# repositories start with zero branches). Set it in a follow-up apply after
# a first commit has been pushed, or when importing a pre-existing repo.
module "repo" {
  source = "git::https://github.com/microsoftexpert/terraform-aws-codecommit?ref=v1.0.0"

  repository_name = "lending-portal-api"
  description     = "Lending Portal API service source"
  default_branch  = "main"
}
3 · Customer-managed KMS key
module "kms" {
  source = "git::https://github.com/microsoftexpert/terraform-aws-kms?ref=v1.0.0"
  name   = "codecommit-lending"
}

module "repo" {
  source = "git::https://github.com/microsoftexpert/terraform-aws-codecommit?ref=v1.0.0"

  repository_name = "lending-portal-api"
  kms_key_id      = module.kms.arn # prefer the key ARN over an alias ARN
}

💡 The CMK's key policy must grant codecommit.amazonaws.com (and the Terraform principal) kms:GenerateDataKey / kms:Decrypt, or repository operations fail with access-denied errors that surface as CodeCommit errors, not KMS ones.

4 · Tags — merge with provider default_tags
# Caller's provider block owns default_tags; resource tags win on key conflict.
provider "aws" {
  region = "us-east-1"
  default_tags {
    tags = { Owner = "platform", ManagedBy = "terraform" }
  }
}

module "repo" {
  source = "git::https://github.com/microsoftexpert/terraform-aws-codecommit?ref=v1.0.0"

  repository_name = "tagged-repo"

  tags = {
    Environment = "prod"
    Owner       = "app-team" # overrides default_tags Owner on the repository
  }
}
# module.repo.tags_all => { Owner="app-team", ManagedBy="terraform", Environment="prod" }
5 · Single SNS trigger — all events
module "notify_topic" {
  source = "git::https://github.com/microsoftexpert/terraform-aws-sns?ref=v1.0.0"
  name   = "codecommit-lending-notifications"
  # topic policy must allow codecommit.amazonaws.com to sns:Publish
}

module "repo" {
  source = "git::https://github.com/microsoftexpert/terraform-aws-codecommit?ref=v1.0.0"

  repository_name = "lending-portal-api"

  triggers = {
    all-events = {
      destination_arn = module.notify_topic.arn
      events          = ["all"]
    }
  }
}
6 · Multiple triggers via for_each (branch-scoped + all-events)
module "repo" {
  source = "git::https://github.com/microsoftexpert/terraform-aws-codecommit?ref=v1.0.0"

  repository_name = "lending-portal-api"

  # Every entry below renders as one `trigger {... }` block inside the SAME
  # single aws_codecommit_trigger resource -- never as separate resources.
  triggers = {
    all-events = {
      destination_arn = module.notify_topic.arn
      events          = ["all"]
    }
    main-updates = {
      destination_arn = module.release_topic.arn
      events          = ["updateReference"]
      branches        = ["main"]
      custom_data     = "release-pipeline"
    }
  }
}
7 · Approval rule template + automatic association
module "reviewer_role" {
  source = "git::https://github.com/microsoftexpert/terraform-aws-iam-role?ref=v1.0.0"
  name   = "codecommit-reviewers"
  # trust policy / assume-role setup omitted for brevity
}

module "repo" {
  source = "git::https://github.com/microsoftexpert/terraform-aws-codecommit?ref=v1.0.0"

  repository_name = "lending-portal-api"

  # Creates the template AND associates it with this repository automatically
  # -- an unassociated template would otherwise be a silent no-op.
  approval_rule_templates = {
    two-approvers-main = {
      description = "Require 2 approvals on pull requests targeting main"
      content = {
        destination_references = ["refs/heads/main"]
        statements = [{
          number_of_approvals_needed = 2
          approval_pool_members      = [module.reviewer_role.arn]
        }]
      }
    }
  }
}
8 · Multiple approval rule templates via for_each (main vs release)
module "repo" {
  source = "git::https://github.com/microsoftexpert/terraform-aws-codecommit?ref=v1.0.0"

  repository_name = "lending-portal-api"

  approval_rule_templates = {
    two-approvers-main = {
      content = {
        destination_references = ["refs/heads/main"]
        statements = [{
          number_of_approvals_needed = 2
          approval_pool_members      = [module.reviewer_role.arn]
        }]
      }
    }
    one-approver-release = {
      description = "Lighter gate for release branches"
      content = {
        destination_references = ["refs/heads/release/*"]
        statements = [{
          number_of_approvals_needed = 1
          approval_pool_members      = [module.release_manager_role.arn]
        }]
      }
    }
  }
}
9 · Open approval pool (any contributor may approve)
module "repo" {
  source = "git::https://github.com/microsoftexpert/terraform-aws-codecommit?ref=v1.0.0"

  repository_name = "internal-tools"

  approval_rule_templates = {
    one-approver-any = {
      content = {
        destination_references = ["refs/heads/main"]
        statements = [{
          number_of_approvals_needed = 1
          # approval_pool_members omitted (defaults to []) -- any repository
          # contributor may approve when the pool is left empty.
        }]
      }
    }
  }
}
10 · Secure-by-default note — there is no unencrypted/public opt-out to disable
# Unlike S3 (public-access-block flags) or RDS (publicly_accessible), a
# CodeCommit repository has NO unencrypted mode and NO public-repository
# concept -- there is nothing to disable here. The only encryption "choice"
# is which key encrypts the repository, never whether it is encrypted:
module "repo" {
  source = "git::https://github.com/microsoftexpert/terraform-aws-codecommit?ref=v1.0.0"

  repository_name = "no-opt-out-example"
  # kms_key_id left null -> AWS-managed aws/codecommit key. Encryption is
  # still ON; there is no `storage_encrypted = false` equivalent to flip.
}
11 · for_each pattern across multiple repositories
locals {
  repos = {
    api = { description = "API service source" }
    web = { description = "Web frontend source" }
  }
}

module "repos" {
  source   = "git::https://github.com/microsoftexpert/terraform-aws-codecommit?ref=v1.0.0"
  for_each = local.repos

  repository_name = "lending-${each.key}"
  description     = each.value.description

  tags = { Component = each.key }
}
12 · Import block — repository_name is the import key
import {
  to = module.repo.aws_codecommit_repository.this
  id = "ExistingLendingRepo"
}

module "repo" {
  source = "git::https://github.com/microsoftexpert/terraform-aws-codecommit?ref=v1.0.0"

  repository_name = "ExistingLendingRepo"
  # description / default_branch / kms_key_id should match the live
  # repository's current values to avoid a diff on the first plan.
}
13 · Managing a pre-existing repository only (new-customer-restricted account)
# In an account that cannot CREATE new CodeCommit repositories (see AWS
# Prerequisites), this module is still fully usable for an already-existing
# repository -- import it, then manage its triggers/approval-rule templates.
import {
  to = module.legacy_repo.aws_codecommit_repository.this
  id = "LegacyRepoCreatedBefore2024"
}

module "legacy_repo" {
  source = "git::https://github.com/microsoftexpert/terraform-aws-codecommit?ref=v1.0.0"

  repository_name = "LegacyRepoCreatedBefore2024"

  triggers = {
    all-events = {
      destination_arn = module.notify_topic.arn
      events          = ["all"]
    }
  }
}
14 · Custom trigger data + branch scoping
module "repo" {
  source = "git::https://github.com/microsoftexpert/terraform-aws-codecommit?ref=v1.0.0"

  repository_name = "lending-portal-api"

  triggers = {
    release-branch-only = {
      destination_arn = module.notify_topic.arn
      events          = ["createReference", "updateReference"]
      branches        = ["main", "release"]
      custom_data     = "release-pipeline-v2"
    }
  }
}
15 · End-to-end composition — KMS + SNS + IAM role + CodeCommit (finale)
module "kms" {
  source = "git::https://github.com/microsoftexpert/terraform-aws-kms?ref=v1.0.0"
  name   = "codecommit-lending"
}

module "notify_topic" {
  source = "git::https://github.com/microsoftexpert/terraform-aws-sns?ref=v1.0.0"
  name   = "codecommit-lending-notifications"
  # topic policy must independently allow codecommit.amazonaws.com to sns:Publish
}

module "reviewer_role" {
  source = "git::https://github.com/microsoftexpert/terraform-aws-iam-role?ref=v1.0.0"
  name   = "codecommit-lending-reviewers"
}

module "repo" {
  source = "git::https://github.com/microsoftexpert/terraform-aws-codecommit?ref=v1.0.0"

  repository_name = "lending-portal-api"
  description     = "Lending Portal API service source"
  kms_key_id      = module.kms.arn

  triggers = {
    all-events = {
      destination_arn = module.notify_topic.arn
      events          = ["all"]
    }
  }

  approval_rule_templates = {
    two-approvers-main = {
      description = "Require 2 approvals on pull requests targeting main"
      content = {
        destination_references = ["refs/heads/main"]
        statements = [{
          number_of_approvals_needed = 2
          approval_pool_members      = [module.reviewer_role.arn]
        }]
      }
    }
  }

  tags = { Environment = "prod", App = "lending-portal" }
}

📥 Inputs

ℹ️ High-level grouping:

  • Core: repository_name (required — also the terraform import key)
  • Optional config: description, default_branch (branch must already exist), kms_key_id
  • Triggers: triggersmap(object({ name?, destination_arn, events?, custom_data?, branches? })), rendered as dynamic "trigger" blocks inside one resource; max 10 entries
  • Approval rule templates: approval_rule_templatesmap(object({ description?, content = { version?, destination_references, statements = [{ type?, number_of_approvals_needed, approval_pool_members? }] } })), each auto-associated with the repository
  • Universal: tags

🧾 Outputs

  • Primary: id / repository_id, arn
  • Repository attributes: repository_name, clone_url_http, clone_url_ssh, default_branch, kms_key_id
  • Triggers: trigger_configuration_idconditional, null when var.triggers is empty (singular, not a map — see Architecture Notes)
  • Approval rule templates: approval_rule_template_ids, approval_rule_template_rule_content_sha256, approval_rule_template_association_ids — all maps keyed by the approval_rule_templates map key; empty maps when no templates are defined
  • Tags: tags_all

ℹ️ No outputs are marked sensitive — this module emits no secrets.


🧠 Architecture Notes

  • ARN / ID formats:
  • id / repository_id → an opaque system-generated identifier (UUID-shaped, e.g. f7579e13-b83e-4027-aaef-fedbb2a2fc74).
  • arnarn:aws:codecommit:<region>:<account-id>:<repository_name> — note there is no resource-type segment or slash before the name, unlike most AWS ARNs (confirmed against AWS's own IAM policy examples).
  • trigger_configuration_id → an opaque system-generated identifier for the whole trigger configuration.
  • approval_rule_template_association_ids"<approval_rule_template_name>,<repository_name>" (comma-separated) — also the terraform import id for the association resource.
  • Force-new / immutable fields:
  • repository_name is not marked force-new by the provider (codecommit:UpdateRepositoryName is a real, supported rename operation), but treat it as force-new in practice — clone URLs, IAM policy Resource ARNs, CI/CD wiring, and this module's own trigger/association resources are all keyed on the current name, so a rename breaks external references silently even though the apply itself succeeds.
  • kms_key_id has no explicitly documented force-new/update behavior in the provider schema, and the CodeCommit API does not appear to expose an "update encryption key" operation distinct from creation — treat changing kms_key_id on an existing repository as an untested path; verify in a sandbox before relying on an in-place change.
  • tagstags_alldefault_tags: var.tags flows to aws_codecommit_repository.this only — verified against the live hashicorp/aws v6.53.0 schema, aws_codecommit_trigger, aws_codecommit_approval_rule_template, and aws_codecommit_approval_rule_template_association expose no tags argument at all. tags_all is the provider-computed union of the repository's tags over the provider's default_tags; resource tags win on key conflict. default_tags remains the caller's provider-block concern.
  • The single-trigger-resource constraint: the provider allows only one aws_codecommit_trigger resource per repository, and applying it replaces every trigger on the repository, including ones created manually in the console. This module models every logical trigger as one nested trigger {... } block (via dynamic "trigger") inside that single resource — never as separate resources. The provider's own schema caps that block at max_items = 10, matching AWS's 10-triggers-per-repository quota.
  • default_branch requires the branch to already exist: a brand-new CodeCommit repository starts with zero branches until a first commit is pushed, so default_branch cannot be set in the same apply that creates the repository. Leave it null on initial creation; set it in a follow-up apply once a branch exists.
  • Approval rule templates have no effect until associated: aws_codecommit_approval_rule_template_association is in-scope specifically so var.approval_rule_templates is never a dangling, inert template — every template this module creates is associated with its own repository in the same apply.
  • Destroy ordering: the association must be destroyed (or disassociated) before its template or the repository can be deleted cleanly. Terraform's implicit dependency graph (the association resource references both the template's name and the repository's repository_name) handles this automatically — avoid manual prevent_destroy on only one side of that relationship.
  • No us-east-1 constraint. CodeCommit is a regional service; the module inherits the caller's provider region and declares no region variable.

🧱 Design Principles

CodeCommit repositories have no unencrypted mode and no public-access concept — there genuinely is nothing to disable here, unlike S3's public-access-block flags or RDS's publicly_accessible. The table below states that plainly rather than inventing an opt-out that doesn't exist:

Posture Default Opt-out
Encryption at rest Always encrypted — the AWS-managed aws/codecommit key by default Supply kms_key_id with a CMK for tighter key-policy control — a hardening addition, not a weakening opt-out; there is no unencrypted mode to fall back to
Encryption in transit Always TLS (HTTPS clone) / SSH (key-based clone) Not configurable — no opt-out exists, by design
Access control IAM-policy-only; no anonymous or public read Not configurable — CodeCommit has no public-repository concept
Pull-request approval gate approval_rule_templates defaults to {} (none defined) Caller opts in by supplying one or more templates; change-control guidance recommends at least one for repositories touching regulated workloads
Trigger notification fan-out triggers defaults to {} (none defined) Caller opts in per repository; the module never fabricates a default SNS topic, so there is no default over-broad notification fan-out to secure against

Other principles: the module stays intentionally small — three resource types plus the association resource — with everything else (SNS topics, CMKs, approver IAM principals) deliberately out-of-scope and wired by ARN so the blast radius stays limited to the repository, its triggers, and its approval-rule templates/associations; approval-rule content is built from a structured object via jsonencode, never accepted as a raw JSON string, so drift stays limited to genuine semantic changes.


🚀 Runbook

terraform init -backend=false
terraform validate
terraform fmt -check
terraform plan # requires valid AWS credentials (profile / SSO / OIDC) + a supported region
terraform apply
terraform output

⚠️ plan / apply require valid AWS credentials and a region that supports CodeCommit (see AWS Prerequisites), plus confirmed account eligibility if creating a new repository. Always pin the module source with ?ref=v1.0.0, never a branch.


🧪 Testing

  • terraform init -backend=false && terraform validate — schema + reference integrity.
  • terraform fmt -check — formatting.
  • terraform plan against a sandbox account — confirm the account can actually create a CodeCommit repository before relying on apply in a shared environment.
  • After apply, confirm trigger_configuration_id is non-null when var.triggers is non-empty, and that approval_rule_template_association_ids has one entry per approval_rule_templates key.
  • Destroy test in a throwaway account to validate association → template → repository teardown ordering before relying on it elsewhere.

💬 Example Output

Apply complete! Resources: 3 added, 0 changed, 0 destroyed.

Outputs:

arn = "arn:aws:codecommit:us-east-1:123456789012:lending-portal-api"
id = "f7579e13-b83e-4027-aaef-fedbb2a2fc74"
clone_url_http = "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/lending-portal-api"
clone_url_ssh = "ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/lending-portal-api"
repository_name = "lending-portal-api"
trigger_configuration_id = "a1b2c3d4-...."
approval_rule_template_ids = { "two-approvers-main" = "b2c3d4e5-...." }
approval_rule_template_association_ids = { "two-approvers-main" = "two-approvers-main,lending-portal-api" }
tags_all = { "Environment" = "prod", "App" = "lending-portal" }

🔍 Troubleshooting

  • create-repository fails with an access-denied-shaped error on a first-ever CodeCommit call: this is very likely the mid-2024 new-customer restriction, not a missing IAM action — check the console eligibility banner before broadening IAM permissions further.
  • Tag drift / unexpected tags: caused by default_tags overlap. tags_all merges resource tags over provider default_tags, resource tags winning — if a value differs from what you set, a default_tags entry is colliding. Set the value explicitly in var.tags.
  • Credential-chain failures (NoCredentialProviders / ExpiredToken): no valid credentials resolved. Set AWS_PROFILE, refresh SSO, or confirm OIDC role assumption in CI. The module never takes credentials as variables.
  • Region us-east-1 does not support CodeCommit (or similar) region errors: CodeCommit is not available in every Region — confirm the target Region is on AWS's supported list before wiring provider inheritance.
  • AccessDeniedException mentioning KMS, not CodeCommit, on repository read/write: the CMK's key policy is missing a grant for codecommit.amazonaws.com or the calling principal — this is a KMS key-policy fix, not an IAM-policy fix.
  • Triggers you didn't expect disappear or change: aws_codecommit_trigger replaces all triggers on the repository on every apply, including ones created manually in the console. Bring every intended trigger under var.triggers; do not mix manual console triggers with this module.
  • default_branch fails to set on a brand-new repository: the named branch does not exist yet — CodeCommit repositories start with zero branches. Push a first commit, then set default_branch in a follow-up apply.
  • An approval rule template "does nothing": it was created but never associated. This module always creates the matching association for every approval_rule_templates entry — if you're seeing this with an imported template, confirm the association resource was imported too (Example Library #12/#13).
  • DependencyViolation-shaped errors on destroy: the association must be removed before its template or the repository. Terraform's implicit dependency graph handles this within the module automatically; it only surfaces if something outside Terraform (e.g. a manual console disassociation half-done) left state inconsistent.

🔗 Related Docs

  • Terraform Registry — hashicorp/aws provider: aws_codecommit_repository, aws_codecommit_trigger, aws_codecommit_approval_rule_template, aws_codecommit_approval_rule_template_association
  • AWS — What is AWS CodeCommit? (CodeCommit User Guide)
  • AWS — CodeCommit identity-based policies and examples (IAM permissions reference)
  • AWS — Quotas in AWS CodeCommit (repository/branch/trigger/approval-rule limits)
  • AWS — Regions and Git connection endpoints for AWS CodeCommit (Region availability)
  • terraform-aws-kms, terraform-aws-sns, terraform-aws-iam-role (sibling modules)

🧡 "Infrastructure as Code should be standardized, consistent, and secure."

Releases

Packages

Contributors

Languages