-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(containers): create ecr-repos Terraform module (#25)
- Loading branch information
Showing
7 changed files
with
300 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
module "ecr_repos" { | ||
source = "../../../../modules/aws/containers/ecr-repos" | ||
|
||
repositories = { | ||
example = {} | ||
another-example = { | ||
image_tag_mutability = "IMMUTABLE" | ||
external_account_ids_with_read_access = ["586861619874"] | ||
external_account_ids_with_write_access = ["586861619874"] | ||
external_account_ids_with_lambda_access = ["586861619874"] | ||
tags = { | ||
Hello = "World" | ||
} | ||
} | ||
} | ||
|
||
tags_all = { | ||
Hi = "There" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
output "ecr_repo_arns" { | ||
description = "A map of repository name to its ECR ARN." | ||
value = module.ecr_repos.ecr_repo_arns | ||
} | ||
|
||
output "ecr_repo_urls" { | ||
description = "A map of repository name to its URL." | ||
value = module.ecr_repos.ecr_repo_urls | ||
} | ||
|
||
output "ecr_read_policy_actions" { | ||
description = "A list of IAM policy actions necessary for ECR read access." | ||
value = module.ecr_repos.ecr_read_policy_actions | ||
} | ||
|
||
output "ecr_write_policy_actions" { | ||
description = "A list of IAM policy actions necessary for ECR write access." | ||
value = module.ecr_repos.ecr_write_policy_actions | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
data "aws_caller_identity" "current" {} | ||
data "aws_region" "current" {} | ||
data "aws_partition" "current" {} | ||
|
||
locals { | ||
# Construct the configuration of ECR repositories that combine the raw user input with the configured defaults. | ||
repositories_with_defaults = { | ||
for repo_name, user_config in var.repositories : | ||
repo_name => { | ||
external_account_ids_with_read_access = lookup(user_config, "external_account_ids_with_read_access", var.default_external_account_ids_with_read_access) | ||
external_account_ids_with_write_access = lookup(user_config, "external_account_ids_with_write_access", var.default_external_account_ids_with_write_access) | ||
external_account_ids_with_lambda_access = lookup(user_config, "external_account_ids_with_lambda_access", var.default_external_account_ids_with_lambda_access) | ||
enable_automatic_image_scanning = lookup(user_config, "enable_automatic_image_scanning", var.default_automatic_image_scanning) | ||
encryption_config = lookup(user_config, "encryption_config", var.default_encryption_config) | ||
image_tag_mutability = lookup(user_config, "image_tag_mutability", var.default_image_tag_mutability) | ||
lifecycle_policy_rules = lookup(user_config, "lifecycle_policy_rules", var.default_lifecycle_policy_rules) | ||
tags = merge( | ||
lookup(user_config, "tags", {}), | ||
var.tags_all, | ||
) | ||
} | ||
} | ||
|
||
repositories_with_lifecycle_rules = { | ||
for repo_name, repo in local.repositories_with_defaults : | ||
repo_name => repo if length(repo.lifecycle_policy_rules) > 0 | ||
} | ||
repositories_with_external_access = { | ||
for repo_name, repo in local.repositories_with_defaults : | ||
repo_name => repo | ||
if( | ||
length(repo.external_account_ids_with_read_access) > 0 | ||
|| length(repo.external_account_ids_with_write_access) > 0 | ||
|| length(repo.external_account_ids_with_lambda_access) > 0 | ||
) | ||
} | ||
|
||
# The list of IAM policy actions for write access | ||
iam_write_access_policies = [ | ||
"ecr:GetAuthorizationToken", | ||
"ecr:BatchCheckLayerAvailability", | ||
"ecr:GetDownloadUrlForLayer", | ||
"ecr:GetRepositoryPolicy", | ||
"ecr:DescribeRepositories", | ||
"ecr:ListImages", | ||
"ecr:DescribeImages", | ||
"ecr:BatchGetImage", | ||
"ecr:InitiateLayerUpload", | ||
"ecr:UploadLayerPart", | ||
"ecr:CompleteLayerUpload", | ||
"ecr:PutImage", | ||
] | ||
|
||
# The list of IAM policy actions for read access | ||
iam_read_access_policies = [ | ||
"ecr:GetDownloadUrlForLayer", | ||
"ecr:BatchGetImage", | ||
"ecr:BatchCheckLayerAvailability", | ||
"ecr:ListImages", | ||
] | ||
} | ||
|
||
resource "aws_ecr_repository" "repos" { | ||
for_each = local.repositories_with_defaults | ||
|
||
name = each.key | ||
image_tag_mutability = each.value.image_tag_mutability | ||
tags = each.value.tags | ||
|
||
image_scanning_configuration { | ||
scan_on_push = each.value.enable_automatic_image_scanning | ||
} | ||
|
||
dynamic "encryption_configuration" { | ||
for_each = each.value.encryption_config != null ? ["once"] : [] | ||
content { | ||
encryption_type = each.value.encryption_config.encryption_type | ||
kms_key = each.value.encryption_config.kms_key | ||
} | ||
} | ||
} | ||
|
||
resource "aws_ecr_lifecycle_policy" "this" { | ||
for_each = local.repositories_with_lifecycle_rules | ||
repository = aws_ecr_repository.repos[each.key].name | ||
policy = jsonencode(each.value.lifecycle_policy_rules) | ||
} | ||
|
||
resource "aws_ecr_replication_configuration" "this" { | ||
count = length(var.replication_regions) > 0 ? 1 : 0 | ||
replication_configuration { | ||
rule { | ||
|
||
dynamic "destination" { | ||
for_each = var.replication_regions | ||
content { | ||
region = destination.value | ||
registry_id = data.aws_caller_identity.current.account_id | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
output "ecr_repo_arns" { | ||
description = "A map of repository name to its ECR ARN." | ||
value = { for repo_name, repo in aws_ecr_repository.repos : repo_name => repo.arn } | ||
} | ||
|
||
output "ecr_repo_urls" { | ||
description = "A map of repository name to its URL." | ||
value = { for repo_name, repo in aws_ecr_repository.repos : repo_name => repo.repository_url } | ||
} | ||
|
||
output "ecr_read_policy_actions" { | ||
description = "A list of IAM policy actions necessary for ECR read access." | ||
value = local.iam_read_access_policies | ||
} | ||
|
||
output "ecr_write_policy_actions" { | ||
description = "A list of IAM policy actions necessary for ECR write access." | ||
value = local.iam_write_access_policies | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
resource "aws_ecr_repository_policy" "external_account_access" { | ||
for_each = local.repositories_with_external_access | ||
repository = aws_ecr_repository.repos[each.key].name | ||
policy = data.aws_iam_policy_document.external_account_access[each.key].json | ||
} | ||
|
||
data "aws_iam_policy_document" "external_account_access" { | ||
for_each = local.repositories_with_external_access | ||
|
||
dynamic "statement" { | ||
for_each = length(each.value.external_account_ids_with_read_access) > 0 ? ["noop"] : [] | ||
|
||
content { | ||
effect = "Allow" | ||
|
||
principals { | ||
type = "AWS" | ||
identifiers = formatlist("arn:${data.aws_partition.current.partition}:iam::%s:root", each.value.external_account_ids_with_read_access) | ||
} | ||
|
||
actions = local.iam_read_access_policies | ||
} | ||
} | ||
|
||
dynamic "statement" { | ||
for_each = length(each.value.external_account_ids_with_write_access) > 0 ? ["noop"] : [] | ||
|
||
content { | ||
effect = "Allow" | ||
|
||
principals { | ||
type = "AWS" | ||
identifiers = formatlist("arn:${data.aws_partition.current.partition}:iam::%s:root", each.value.external_account_ids_with_write_access) | ||
} | ||
|
||
actions = local.iam_write_access_policies | ||
} | ||
} | ||
|
||
dynamic "statement" { | ||
for_each = each.value.external_account_ids_with_lambda_access | ||
|
||
content { | ||
effect = "Allow" | ||
|
||
principals { | ||
type = "Service" | ||
identifiers = ["lambda.amazonaws.com"] | ||
} | ||
|
||
condition { | ||
test = "StringLike" | ||
variable = "aws:sourceARN" | ||
|
||
# Allow lambda function access in any of the regions that the ECR repo is created for each account. | ||
values = [ | ||
for region in concat([data.aws_region.current.name], var.replication_regions) : | ||
"arn:${data.aws_partition.current.partition}:lambda:${region}:${statement.value}:function:*" | ||
] | ||
} | ||
|
||
actions = local.iam_read_access_policies | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
variable "repositories" { | ||
description = "A map of repo names to configurations for that repository." | ||
type = any | ||
} | ||
|
||
variable "default_external_account_ids_with_read_access" { | ||
description = "The default list of AWS account IDs for external AWS accounts that should be able to pull images from these ECR repos. Can be overridden on a per repo basis by the external_account_ids_with_read_access property in the repositories map." | ||
type = list(string) | ||
default = [] | ||
} | ||
|
||
variable "default_external_account_ids_with_write_access" { | ||
description = "The default list of AWS account IDs for external AWS accounts that should be able to pull and push images to these ECR repos. Can be overridden on a per repo basis by the external_account_ids_with_write_access property in the repositories map." | ||
type = list(string) | ||
default = [] | ||
} | ||
|
||
variable "default_external_account_ids_with_lambda_access" { | ||
description = "The default list of AWS account IDs for external AWS accounts that should be able to create Lambda functions based on container images in these ECR repos. Can be overridden on a per repo basis by the external_account_ids_with_lambda_access property in the repositories map." | ||
type = list(string) | ||
default = [] | ||
} | ||
|
||
variable "default_automatic_image_scanning" { | ||
description = "Whether or not to enable image scanning on all the repos. Can be overridden on a per repo basis by the enable_automatic_image_scanning property in the repositories map." | ||
type = bool | ||
default = true | ||
} | ||
|
||
variable "default_encryption_config" { | ||
description = "The default encryption configuration to apply to the created ECR repository. When null, the images in the ECR repo will not be encrypted at rest. Can be overridden on a per repo basis by the encryption_config property in the repositories map." | ||
type = object({ | ||
encryption_type = string | ||
kms_key = string | ||
}) | ||
default = { | ||
encryption_type = "AES256" | ||
kms_key = null | ||
} | ||
} | ||
|
||
variable "default_image_tag_mutability" { | ||
description = "The tag mutability setting for all the repos. Must be one of: MUTABLE or IMMUTABLE. Can be overridden on a per repo basis by the image_tag_mutability property in the repositories map." | ||
type = string | ||
default = "MUTABLE" | ||
} | ||
|
||
variable "tags_all" { | ||
description = "A map of tags (where the key and value correspond to tag keys and values) that should be assigned to all ECR repositories." | ||
type = map(string) | ||
default = {} | ||
} | ||
|
||
variable "default_lifecycle_policy_rules" { | ||
description = "Add lifecycle policy to ECR repo." | ||
type = any | ||
default = [] | ||
} | ||
|
||
variable "replication_regions" { | ||
description = "List of regions (e.g., us-east-1) to replicate the ECR repository to." | ||
type = list(string) | ||
default = [] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
terraform { | ||
required_version = ">=1.3" | ||
|
||
required_providers { | ||
aws = { | ||
source = "hashicorp/aws" | ||
version = ">=4.0" | ||
} | ||
} | ||
} |