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.
⚠️ 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_repositorycreation 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 viaterraform importregardless of eligibility — see Example Library #14.
- 🏗️ Provisions an
aws_codecommit_repositorykeystone — always encrypted, always private, never anything else. - 🔔 One guarded trigger configuration per repository, rendered as a
dynamic "trigger"block overvar.triggersinside a singleaws_codecommit_triggerresource — 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/codecommitkey 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_allsurfaced 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.
If these Terraform modules have been helpful to you or your organization, I'd appreciate your support in any of the following ways:
- ⭐ Star this repository to help others discover this Terraform module.
- 🤝 Connect with me on LinkedIn: linkedin.com/in/microsoftexpert
- ☕ Buy me a coffee: buymeacoffee.com/microsoftexpert
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!
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
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
| 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) |
| 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.
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:PassRolerequirement anywhere — no in-scope resource assumes a role.
⚠️ 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:
- Checking the AWS Management Console → CodeCommit landing page in the target account for an eligibility banner, or
- Attempting
aws codecommit create-repository(or a disposableterraform plan/apply) in a sandbox account first, or- 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 theaws-documentationMCP 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_idis supplied, the CMK's key policy must grant thecodecommit.amazonaws.comservice principal and the calling principalkms: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.comtosns: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 = 10on thetriggerblock. - 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-codecommitwith temporary credentials or SSH public keys uploaded to IAM users.
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
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.
| 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.
| 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 |
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" }
}ℹ️ High-level grouping:
- Core:
repository_name(required — also theterraform importkey) - Optional config:
description,default_branch(branch must already exist),kms_key_id - Triggers:
triggers—map(object({ name?, destination_arn, events?, custom_data?, branches? })), rendered asdynamic "trigger"blocks inside one resource; max 10 entries - Approval rule templates:
approval_rule_templates—map(object({ description?, content = { version?, destination_references, statements = [{ type?, number_of_approvals_needed, approval_pool_members? }] } })), each auto-associated with the repository - Universal:
tags
- Primary:
id/repository_id,arn - Repository attributes:
repository_name,clone_url_http,clone_url_ssh,default_branch,kms_key_id - Triggers:
trigger_configuration_id— conditional,nullwhenvar.triggersis 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 theapproval_rule_templatesmap key; empty maps when no templates are defined - Tags:
tags_all
ℹ️ No outputs are marked
sensitive— this module emits no secrets.
- ARN / ID formats:
id/repository_id→ an opaque system-generated identifier (UUID-shaped, e.g.f7579e13-b83e-4027-aaef-fedbb2a2fc74).arn→arn: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 theterraform importid for the association resource.- Force-new / immutable fields:
repository_nameis not marked force-new by the provider (codecommit:UpdateRepositoryNameis a real, supported rename operation), but treat it as force-new in practice — clone URLs, IAM policyResourceARNs, 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 theapplyitself succeeds.kms_key_idhas 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 changingkms_key_idon an existing repository as an untested path; verify in a sandbox before relying on an in-place change.tags↔tags_all↔default_tags:var.tagsflows toaws_codecommit_repository.thisonly — verified against the livehashicorp/awsv6.53.0 schema,aws_codecommit_trigger,aws_codecommit_approval_rule_template, andaws_codecommit_approval_rule_template_associationexpose notagsargument at all.tags_allis the provider-computed union of the repository's tags over the provider'sdefault_tags; resource tags win on key conflict.default_tagsremains the caller's provider-block concern.- The single-trigger-resource constraint: the provider allows only one
aws_codecommit_triggerresource 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 nestedtrigger {... }block (viadynamic "trigger") inside that single resource — never as separate resources. The provider's own schema caps that block atmax_items = 10, matching AWS's 10-triggers-per-repository quota. default_branchrequires the branch to already exist: a brand-new CodeCommit repository starts with zero branches until a first commit is pushed, sodefault_branchcannot be set in the sameapplythat creates the repository. Leave itnullon initial creation; set it in a follow-upapplyonce a branch exists.- Approval rule templates have no effect until associated:
aws_codecommit_approval_rule_template_associationis in-scope specifically sovar.approval_rule_templatesis never a dangling, inert template — every template this module creates is associated with its own repository in the sameapply. - 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
nameand the repository'srepository_name) handles this automatically — avoid manualprevent_destroyon only one side of that relationship. - No
us-east-1constraint. CodeCommit is a regional service; the module inherits the caller's provider region and declares noregionvariable.
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.
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/applyrequire 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.
terraform init -backend=false && terraform validate— schema + reference integrity.terraform fmt -check— formatting.terraform planagainst a sandbox account — confirm the account can actually create a CodeCommit repository before relying onapplyin a shared environment.- After
apply, confirmtrigger_configuration_idis non-null whenvar.triggersis non-empty, and thatapproval_rule_template_association_idshas one entry perapproval_rule_templateskey. - Destroy test in a throwaway account to validate association → template → repository teardown ordering before relying on it elsewhere.
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" }
create-repositoryfails 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_tagsoverlap.tags_allmerges resource tags over providerdefault_tags, resource tags winning — if a value differs from what you set, adefault_tagsentry is colliding. Set the value explicitly invar.tags. - Credential-chain failures (
NoCredentialProviders/ExpiredToken): no valid credentials resolved. SetAWS_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.AccessDeniedExceptionmentioning KMS, not CodeCommit, on repository read/write: the CMK's key policy is missing a grant forcodecommit.amazonaws.comor 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_triggerreplaces all triggers on the repository on every apply, including ones created manually in the console. Bring every intended trigger undervar.triggers; do not mix manual console triggers with this module. default_branchfails 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 setdefault_branchin 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_templatesentry — 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.
- Terraform Registry —
hashicorp/awsprovider: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."