Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 42 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ AWS ECR Module which creates
- ECR policy

## Usage
### Private Repository
```hcl
module "ecr" {
source = "mattyait/ecr/aws"
Expand All @@ -24,26 +25,60 @@ module "ecr" {
max_tagged_image_count = 50
protected_tags = ["latest"]

tags = {
tags = {
Environment = "demo"
Created_By = "Terraform"
}
}
```

### Public Repository
```
module "public_ecr" {
source = "../"
repository_type = "public"
image_names = [
"test",
"test1",
]

public_repository_catalog_data = [
{
description = "Docker container Description test repo"
about_text = "About Text test"
usage_text = "Usage Text test"
operating_systems = ["Linux"]
architectures = ["x86"]
},
{
description = "Docker container Description test1 repo"
about_text = "About Text test1"
usage_text = "Usage Text test1"
operating_systems = ["Alpine"]
architectures = ["x86"]
}
]

tags = {
Environment = "demo"
Created_By = "Terraform"
}
}
```

<!-- BEGIN_TF_DOCS -->
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >=1.0.3 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | ~> 4.31.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | ~> 5.31.0 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | ~> 4.31.0 |
| <a name="provider_aws"></a> [aws](#provider\_aws) | ~> 5.31.0 |

## Modules

Expand All @@ -56,6 +91,7 @@ No modules.
| [aws_ecr_lifecycle_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_lifecycle_policy) | resource |
| [aws_ecr_repository.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_repository) | resource |
| [aws_ecr_repository_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_repository_policy) | resource |
| [aws_ecrpublic_repository.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecrpublic_repository) | resource |
| [aws_kms_alias.kms_key_alias](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource |
| [aws_kms_key.kms_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource |
| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
Expand All @@ -74,15 +110,17 @@ No modules.
| <a name="input_max_untagged_image_count"></a> [max\_untagged\_image\_count](#input\_max\_untagged\_image\_count) | The maximum number of untagged images that you want to retain in repository. | `number` | `1` | no |
| <a name="input_only_pull_accounts"></a> [only\_pull\_accounts](#input\_only\_pull\_accounts) | AWS accounts which pull only. | `list(string)` | `[]` | no |
| <a name="input_protected_tags"></a> [protected\_tags](#input\_protected\_tags) | Name of image tags prefixes that should not be destroyed. | `list(string)` | <pre>[<br> "latest"<br>]</pre> | no |
| <a name="input_public_repository_catalog_data"></a> [public\_repository\_catalog\_data](#input\_public\_repository\_catalog\_data) | Catalog data configuration for the public repository | `any` | `{}` | no |
| <a name="input_push_and_pull_accounts"></a> [push\_and\_pull\_accounts](#input\_push\_and\_pull\_accounts) | AWS accounts which push and pull. | `list(string)` | `[]` | no |
| <a name="input_repository_type"></a> [repository\_type](#input\_repository\_type) | The type of repository to create(public or private) | `string` | `"private"` | no |
| <a name="input_scan_on_push"></a> [scan\_on\_push](#input\_scan\_on\_push) | Whether images should automatically be scanned on push or not. | `bool` | `false` | no |
| <a name="input_tags"></a> [tags](#input\_tags) | The tags for the resources | `map(any)` | `{}` | no |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_ecr_repository_arn"></a> [ecr\_repository\_arn](#output\_ecr\_repository\_arn) | Full ARN of the repository. |
| <a name="output_ecr_repository_arn"></a> [ecr\_repository\_arn](#output\_ecr\_repository\_arn) | Full ARN of the repository |
| <a name="output_ecr_repository_name"></a> [ecr\_repository\_name](#output\_ecr\_repository\_name) | Name of first repository created |
| <a name="output_ecr_repository_registry_id"></a> [ecr\_repository\_registry\_id](#output\_ecr\_repository\_registry\_id) | The registry ID where the repository was created. |
| <a name="output_ecr_repository_url"></a> [ecr\_repository\_url](#output\_ecr\_repository\_url) | URL of first repository created |
Expand Down
39 changes: 35 additions & 4 deletions example/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,21 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.31.0"
version = "~> 5.31.0"
}
}
}

provider "aws" {
region = "ap-southeast-2"
region = "us-east-1"
}

module "ecr" {
source = "../"

image_names = [
"test",
"test1",
"test_private",
"test1_private",
]
scan_on_push = true
image_tag_mutability = "IMMUTABLE"
Expand Down Expand Up @@ -53,3 +53,34 @@ module "ecr_with_kms" {
Created_By = "Terraform"
}
}

module "public_ecr" {
source = "../"
repository_type = "public"
image_names = [
"test",
"test1",
]

public_repository_catalog_data = [
{
description = "Docker container Description test repo"
about_text = "About Text test"
usage_text = "Usage Text test"
operating_systems = ["Linux"]
architectures = ["x86"]
},
{
description = "Docker container Description test1 repo"
about_text = "About Text test1"
usage_text = "Usage Text test1"
operating_systems = ["Alpine"]
architectures = ["x86"]
}
]

tags = {
Environment = "demo"
Created_By = "Terraform"
}
}
22 changes: 16 additions & 6 deletions example/outputs.tf
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
output "ecr_repository_arn" {
value = module.ecr.ecr_repository_arn
description = "Full ARN of the repository."
output "public_ecr_repository_url_map" {
value = try(module.public_ecr.repository_url_map, null)
description = "Returning the ecr repo url as map"
}

output "ecr_repository_name" {
value = module.ecr.ecr_repository_name
description = "Name of first repository created"
output "public_repository_arn_map" {
value = try(module.public_ecr.repository_arn_map, null)
description = "Returning the ecr repo arn as map"
}

output "private_ecr_repository_url_map" {
value = try(module.ecr.repository_url_map, null)
description = "Returning the ecr repo url as map"
}

output "private_repository_arn_map" {
value = try(module.ecr.repository_arn_map, null)
description = "Returning the ecr repo arn as map"
}
40 changes: 32 additions & 8 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ locals {
kms_key = var.encryption_type == "KMS" && var.kms_key == null ? aws_kms_key.kms_key[0].arn : var.kms_key
}
]
}
locals {
image_names = length(var.image_names) > 0 ? var.image_names : []

create_private_repository = var.repository_type == "private"
create_public_repository = var.repository_type == "public"
}


locals {
untagged_image_rule = [{
rulePriority = length(var.protected_tags) + 1
Expand Down Expand Up @@ -62,19 +64,19 @@ locals {
}

resource "aws_kms_key" "kms_key" {
count = var.encryption_type == "KMS" && var.kms_key == null ? 1 : 0
count = (local.create_private_repository && var.encryption_type == "KMS" && var.kms_key == null) ? 1 : 0
description = "ECR KMS key for ECR"
tags = var.tags
}

resource "aws_kms_alias" "kms_key_alias" {
count = var.encryption_type == "KMS" && var.kms_key == null ? 1 : 0
count = (local.create_private_repository && var.encryption_type == "KMS" && var.kms_key == null) ? 1 : 0
name = "alias/ecrkey"
target_key_id = aws_kms_key.kms_key[0].key_id
}

resource "aws_ecr_repository" "this" {
for_each = toset(local.image_names)
for_each = local.create_private_repository ? toset(local.image_names) : []
name = each.value
image_tag_mutability = var.image_tag_mutability

Expand All @@ -94,7 +96,7 @@ resource "aws_ecr_repository" "this" {
}

resource "aws_ecr_repository_policy" "this" {
for_each = toset(local.image_names)
for_each = local.create_private_repository ? toset(local.image_names) : []
repository = aws_ecr_repository.this[each.value].name
policy = data.aws_iam_policy_document.push_and_pull.json
}
Expand All @@ -118,7 +120,7 @@ data "aws_iam_policy_document" "only_pull" {

# Allows specific accounts to push and pull images
data "aws_iam_policy_document" "push_and_pull" {
source_json = data.aws_iam_policy_document.only_pull.json
source_policy_documents = [data.aws_iam_policy_document.only_pull.json]

statement {
sid = "ElasticContainerRegistryPushAndPull"
Expand All @@ -139,7 +141,7 @@ data "aws_iam_policy_document" "push_and_pull" {
}

resource "aws_ecr_lifecycle_policy" "this" {
for_each = toset(local.image_names)
for_each = local.create_private_repository ? toset(local.image_names) : []
repository = aws_ecr_repository.this[each.value].name
policy = jsonencode({
rules = concat(local.protected_tag_rules, local.untagged_image_rule, local.remove_old_image_rule)
Expand All @@ -149,3 +151,25 @@ resource "aws_ecr_lifecycle_policy" "this" {


data "aws_caller_identity" "current" {}



resource "aws_ecrpublic_repository" "this" {
for_each = local.create_public_repository ? toset(local.image_names) : []

repository_name = each.value

dynamic "catalog_data" {
for_each = length(var.public_repository_catalog_data) > 0 ? [var.public_repository_catalog_data] : []
content {
about_text = try(catalog_data.value[index(local.image_names, each.value)].about_text, null)
architectures = try(catalog_data.value[index(local.image_names, each.value)].architectures, null)
description = try(catalog_data.value[index(local.image_names, each.value)].description, null)
logo_image_blob = try(catalog_data.value[index(local.image_names, each.value)].logo_image_blob, null)
operating_systems = try(catalog_data.value[index(local.image_names, each.value)].operating_systems, null)
usage_text = try(catalog_data.value[index(local.image_names, each.value)].usage_text, null)
}
}

tags = var.tags
}
19 changes: 9 additions & 10 deletions outputs.tf
Original file line number Diff line number Diff line change
@@ -1,36 +1,35 @@

output "ecr_repository_arn" {
value = aws_ecr_repository.this[local.image_names[0]].arn
description = "Full ARN of the repository."
description = "Full ARN of the repository"
value = try(aws_ecr_repository.this[local.image_names[0]].arn, aws_ecrpublic_repository.this[local.image_names[0]].arn, null)
}

output "ecr_repository_name" {
value = aws_ecr_repository.this[local.image_names[0]].name
value = try(aws_ecr_repository.this[local.image_names[0]].name, aws_ecrpublic_repository.this[local.image_names[0]].name, null)
description = "Name of first repository created"
}

output "ecr_repository_registry_id" {
value = aws_ecr_repository.this[local.image_names[0]].registry_id
value = try(aws_ecr_repository.this[local.image_names[0]].registry_id, aws_ecrpublic_repository.this[local.image_names[0]].registry_id, null)
description = "The registry ID where the repository was created."
}

output "ecr_repository_url" {
value = aws_ecr_repository.this[local.image_names[0]].repository_url
value = try(aws_ecr_repository.this[local.image_names[0]].repository_url, aws_ecrpublic_repository.this[local.image_names[0]].repository_url, null)
description = "URL of first repository created"
}

output "repository_url_map" {
value = zipmap(
values(aws_ecr_repository.this)[*].name,
values(aws_ecr_repository.this)[*].repository_url
concat(values(aws_ecr_repository.this)[*].name, values(aws_ecrpublic_repository.this)[*].repository_name),
concat(values(aws_ecr_repository.this)[*].repository_url, values(aws_ecrpublic_repository.this)[*].repository_uri)
)
description = "Map of repository names to repository URLs"
}

output "repository_arn_map" {
value = zipmap(
values(aws_ecr_repository.this)[*].name,
values(aws_ecr_repository.this)[*].arn
concat(values(aws_ecr_repository.this)[*].name, values(aws_ecrpublic_repository.this)[*].repository_name),
concat(values(aws_ecr_repository.this)[*].arn, values(aws_ecrpublic_repository.this)[*].arn)
)
description = "Map of repository names to repository ARNs"
}
12 changes: 12 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
variable "repository_type" {
description = "The type of repository to create(public or private)"
type = string
default = "private"
}

variable "image_names" {
type = list(string)
default = []
Expand Down Expand Up @@ -64,3 +70,9 @@ variable "tags" {
type = map(any)
default = {}
}

variable "public_repository_catalog_data" {
description = "Catalog data configuration for the public repository"
type = any
default = {}
}
2 changes: 1 addition & 1 deletion versions.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.31.0"
version = "~> 5.31.0"
}
}
}