Skip to content

Commit

Permalink
Improve ecr-registry module (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
posquit0 authored May 14, 2024
1 parent f88e4f0 commit ce2df04
Show file tree
Hide file tree
Showing 7 changed files with 289 additions and 191 deletions.
155 changes: 10 additions & 145 deletions modules/ecr-registry/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ locals {
package = "terraform-aws-container"
version = trimspace(file("${path.module}/../../VERSION"))
module = basename(path.module)
name = data.aws_caller_identity.this.id
name = local.account_id
}
module_tags = {
"module.terraform.io/package" = local.metadata.package
Expand All @@ -27,156 +27,21 @@ locals {
# Registry Policy
###################################################

data "aws_iam_policy_document" "replication" {
count = length(try(var.replication_policies, [])) > 0 ? 1 : 0

dynamic "statement" {
for_each = try(var.replication_policies, [])

content {
sid = "ReplicationAccess${statement.value.account_id}"
effect = "Allow"
principals {
type = "AWS"
identifiers = [
"arn:aws:iam::${statement.value.account_id}:root"
]
}
actions = compact([
try(statement.value.allow_create_repository, true) ? "ecr:CreateRepository" : null,
"ecr:ReplicateImage",
])
resources = [
for repository in statement.value.repositories :
"arn:aws:ecr:${local.region}:${local.account_id}:repository/${repository}"
]
}
}
}

data "aws_iam_policy_document" "pull_through_cache" {
count = length(try(var.pull_through_cache_policies, [])) > 0 ? 1 : 0

dynamic "statement" {
for_each = try(var.pull_through_cache_policies, [])

content {
sid = "PullThroughCacheAccess-${statement.key}"
effect = "Allow"
principals {
type = "AWS"
identifiers = try(statement.value.iam_entities, [])
}
actions = compact([
try(statement.value.allow_create_repository, true) ? "ecr:CreateRepository" : null,
"ecr:BatchImportUpstreamImage",
])
resources = [
for repository in statement.value.repositories :
"arn:aws:ecr:${local.region}:${local.account_id}:repository/${repository}"
]
}
}
}

data "aws_iam_policy_document" "this" {
source_policy_documents = concat(
try(data.aws_iam_policy_document.replication[*].json, []),
try(data.aws_iam_policy_document.pull_through_cache[*].json, []),
)
source_policy_documents = compact([
one(data.aws_iam_policy_document.replication[*].json),
one(data.aws_iam_policy_document.pull_through_cache[*].json),
])

override_policy_documents = var.policy != null ? [var.policy] : null
}

resource "aws_ecr_registry_policy" "this" {
count = length(var.replication_policies) > 0 || length(var.pull_through_cache_policies) > 0 || var.policy != null ? 1 : 0
count = anytrue([
length(var.replication_policies) > 0,
length(var.pull_through_cache_policies) > 0,
var.policy != null,
]) ? 1 : 0

policy = data.aws_iam_policy_document.this.json
}


###################################################
# Replication Configurations
###################################################

resource "aws_ecr_replication_configuration" "this" {
count = length(var.replication_destinations) > 0 ? 1 : 0

replication_configuration {
rule {
dynamic "destination" {
for_each = var.replication_destinations

content {
registry_id = destination.value.registry_id
region = destination.value.region
}
}
}
}
}


###################################################
# Pull Through Cache Rule
###################################################

locals {
default_namespaces = {
"quay.io" = "quay"
"public.ecr.aws" = "ecr-public"
}
}

resource "aws_ecr_pull_through_cache_rule" "this" {
for_each = {
for rule in var.pull_through_cache_rules :
try(rule.namespace, local.default_namespaces[rule.upstream_url]) => rule
}

ecr_repository_prefix = each.key
upstream_registry_url = each.value.upstream_url
}


###################################################
# Scanning Configuration
###################################################

resource "aws_ecr_registry_scanning_configuration" "this" {
scan_type = var.scanning_type

dynamic "rule" {
for_each = length(var.scanning_on_push_filters) > 0 ? ["go"] : []

content {
scan_frequency = "SCAN_ON_PUSH"

dynamic "repository_filter" {
for_each = var.scanning_on_push_filters

content {
filter = repository_filter.value
filter_type = "WILDCARD"
}
}
}
}

dynamic "rule" {
for_each = length(var.scanning_continuous_filters) > 0 ? ["go"] : []

content {
scan_frequency = "CONTINUOUS_SCAN"

dynamic "repository_filter" {
for_each = var.scanning_continuous_filters

content {
filter = repository_filter.value
filter_type = "WILDCARD"
}
}
}
}
}
43 changes: 25 additions & 18 deletions modules/ecr-registry/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,40 @@ output "policy" {
value = one(aws_ecr_registry_policy.this[*].policy)
}

output "replication_destinations" {
description = "A list of destinations for ECR registry replication."
value = var.replication_destinations
output "replication_policies" {
description = "A list of replication policies for ECR Registry."
value = var.replication_policies
}

output "replication_rules" {
description = "A list of replication rules for ECR Registry."
value = var.replication_rules
}

output "pull_through_cache_policies" {
description = "A list of Pull Through Cache policies for ECR Registry."
value = var.pull_through_cache_policies
}

output "pull_through_cache_rules" {
description = "A list of Pull Through Cache Rules for ECR registry."
value = [
for id, rule in aws_ecr_pull_through_cache_rule.this : {
id = id
namespace = rule.ecr_repository_prefix
upstream_url = rule.upstream_registry_url
}
]
value = var.pull_through_cache_rules
}

output "scanning_type" {
description = "The scanning type for the registry."
description = "The scanning type to set for the registry."
value = aws_ecr_registry_scanning_configuration.this.scan_type
}

output "scanning_on_push_filters" {
description = "A list of repository filter to scan on push."
value = var.scanning_on_push_filters
output "scanning_rules" {
description = "A list of scanning rules to determine which repository filters are used and at what frequency scanning will occur."
value = var.scanning_rules
}

output "scanning_continuous_filters" {
description = "A list of repository filter to scan continuous."
value = var.scanning_continuous_filters
}
# output "debug" {
# value = {
# pull_through_cache_rules = aws_ecr_pull_through_cache_rule.this
# replication_rules = aws_ecr_replication_configuration.this
# scanning_rules = aws_ecr_registry_scanning_configuration.this
# }
# }
62 changes: 62 additions & 0 deletions modules/ecr-registry/pull-through-cache.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
###################################################
# Pull Through Cache Policy
###################################################

data "aws_iam_policy_document" "pull_through_cache" {
count = length(var.pull_through_cache_policies) > 0 ? 1 : 0

dynamic "statement" {
for_each = var.pull_through_cache_policies
iterator = policy

content {
sid = "PullThroughCacheAccess-${policy.key}"
effect = "Allow"

principals {
type = "AWS"
identifiers = policy.value.iam_entities
}
actions = (policy.value.allow_create_repository
? ["ecr:CreateRepository", "ecr:BatchImportUpstreamImage"]
: ["ecr:BatchImportUpstreamImage"]
)
resources = [
for repository in policy.value.repositories :
"arn:aws:ecr:${local.region}:${local.account_id}:repository/${repository}"
]
}
}
}


###################################################
# Pull Through Cache Rules
###################################################

locals {
default_namespaces = {
"ghcr.io" = "github"
"myregistry.azurecr.io" = "azure"
"public.ecr.aws" = "ecr-public"
"quay.io" = "quay"
"registry-1.docker.io" = "docker-hub"
"registry.gitlab.com" = "gitlab"
"registry.k8s.io" = "kubernetes"
}
}

resource "aws_ecr_pull_through_cache_rule" "this" {
for_each = {
for rule in var.pull_through_cache_rules :
coalesce(rule.namespace, local.default_namespaces[rule.upstream_url]) => rule
}

ecr_repository_prefix = each.key
upstream_registry_url = each.value.upstream_url

credential_arn = (each.value.credential != null
? each.value.credential.secretsmanager_secret
: null
)
}
69 changes: 69 additions & 0 deletions modules/ecr-registry/replication.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
###################################################
# Replication Policy
###################################################

data "aws_iam_policy_document" "replication" {
count = length(var.replication_policies) > 0 ? 1 : 0

dynamic "statement" {
for_each = var.replication_policies
iterator = policy

content {
sid = "ReplicationAccess${policy.value.account}"
effect = "Allow"

principals {
type = "AWS"
identifiers = [
"arn:aws:iam::${policy.value.account}:root"
]
}
actions = (policy.value.allow_create_repository
? ["ecr:CreateRepository", "ecr:ReplicateImage"]
: ["ecr:ReplicateImage"]
)
resources = [
for repository in policy.value.repositories :
"arn:aws:ecr:${local.region}:${local.account_id}:repository/${repository}"
]
}
}
}


###################################################
# Replication Rules
###################################################

resource "aws_ecr_replication_configuration" "this" {
count = length(var.replication_rules) > 0 ? 1 : 0

replication_configuration {
dynamic "rule" {
for_each = var.replication_rules
iterator = rule

content {
dynamic "destination" {
for_each = rule.value.destinations

content {
registry_id = coalesce(destination.value.account, local.account_id)
region = destination.value.region
}
}

dynamic "repository_filter" {
for_each = rule.value.filters
iterator = filter

content {
filter_type = filter.value.type
filter = filter.value.value
}
}
}
}
}
}
25 changes: 25 additions & 0 deletions modules/ecr-registry/scanning.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
###################################################
# Scanning Configuration
###################################################

resource "aws_ecr_registry_scanning_configuration" "this" {
scan_type = var.scanning_type

dynamic "rule" {
for_each = var.scanning_rules

content {
scan_frequency = rule.value.frequency

dynamic "repository_filter" {
for_each = rule.value.filters
iterator = filter

content {
filter_type = filter.value.type
filter = filter.value.value
}
}
}
}
}
Loading

0 comments on commit ce2df04

Please sign in to comment.