From 0c8e4de5c7116468a971a56baab377e0428266bd Mon Sep 17 00:00:00 2001 From: Vladimir Djurovic Date: Sat, 29 Nov 2025 21:15:29 +0100 Subject: [PATCH 1/3] feat: support for setting principals for default repo policy --- Makefile | 2 +- codeartifact-repo/README.md | 2 +- codeartifact-repo/main.tf | 81 +++++++++++++- codeartifact-repo/outputs.tf | 5 + codeartifact-repo/tests/policies.tftest.hcl | 113 ++++++++++++++++++++ codeartifact-repo/variables.tf | 16 +-- scripts/format.sh | 5 + 7 files changed, 213 insertions(+), 11 deletions(-) create mode 100644 codeartifact-repo/tests/policies.tftest.hcl diff --git a/Makefile b/Makefile index a8c0538..e7ecefd 100644 --- a/Makefile +++ b/Makefile @@ -9,4 +9,4 @@ codeartifact-repo-format: init cd ./codeartifact-repo && ../scripts/format.sh codeartifact-repo-verify: init - cd ./codeartifact-repo && terraform-docs -c ../.terraform-docs.yaml . && ../scripts/verify.sh \ No newline at end of file + cd ./codeartifact-repo && ../scripts/verify.sh \ No newline at end of file diff --git a/codeartifact-repo/README.md b/codeartifact-repo/README.md index ae0918a..7b1bae4 100644 --- a/codeartifact-repo/README.md +++ b/codeartifact-repo/README.md @@ -45,7 +45,7 @@ This module is intended to configure AWS CodeArtifact domains and repositories. | [domain\_policy\_document\_path](#input\_domain\_policy\_document\_path) | Path to IAM policy document applied to Codeartifact domain | `string` | `null` | no | | [encryption\_key\_arn](#input\_encryption\_key\_arn) | ARN of KMS key used for repository encryption. If not specified, and use\_default\_ecnryption\_key is false, creates new KMS key | `string` | `null` | no | | [repo\_region](#input\_repo\_region) | Region in which repository will be managed. If not specified, defaults to region configured for provider | `string` | `null` | no | -| [repositories](#input\_repositories) | List of repositories within Codeartifact domain |
list(object({
repository_name = string
description = optional(string, "")
region = optional(string, null)
domain_owner = optional(string, null)
upstream = optional(string, null)
external_connection = optional(string, null)
policy_document_path = optional(string, null)
}))
| `[]` | no | +| [repositories](#input\_repositories) | List of repositories within Codeartifact domain |
list(object({
repository_name = string
description = optional(string, "")
region = optional(string, null)
domain_owner = optional(string, null)
upstream = optional(string, null)
external_connection = optional(string, null)
policy_document_path = optional(string, null)
default_read_access_principals = optional(list(string), null)
default_write_access_principals = optional(list(string), null)
}))
| `[]` | no | | [tags](#input\_tags) | Tags to be applied to resources | `map(string)` | `{}` | no | | [use\_default\_ecnryption\_key](#input\_use\_default\_ecnryption\_key) | Whether to use default Codeartifact KMS key (defaults to true) | `bool` | `true` | no | diff --git a/codeartifact-repo/main.tf b/codeartifact-repo/main.tf index e788ffd..27daa65 100644 --- a/codeartifact-repo/main.tf +++ b/codeartifact-repo/main.tf @@ -5,6 +5,16 @@ locals { should_create_kms_key = (!var.use_default_ecnryption_key && var.encryption_key_arn == null) ? true : false + + repo_read_access_principals = { + for repo in var.repositories : repo.repository_name => repo.default_read_access_principals + } + repo_write_access_principals = { + for repo in var.repositories : repo.repository_name => repo.default_write_access_principals + } + repo_final_policy_documents = { + for repo in var.repositories : repo.repository_name => data.aws_iam_policy_document.combined_default_policies[repo.repository_name] if length(data.aws_iam_policy_document.combined_default_policies) > 0 && contains(keys(data.aws_iam_policy_document.combined_default_policies),repo.repository_name) + } } resource "aws_codeartifact_domain" "repo_domain" { @@ -47,11 +57,78 @@ resource "aws_codeartifact_repository" "repository" { tags = var.tags } +data "aws_iam_policy_document" "default_readonly_repo_policy" { + for_each = { for k, v in local.repo_read_access_principals : k => v if v != null } + statement { + effect = "Allow" + actions = [ + "codeartifact:GetAuthorizationToken", + "codeartifact:GetRepositoryEndpoint", + "codeartifact:ReadFromRepository", + ] + resources = [aws_codeartifact_repository.repository[each.key].arn] + principals { + type = "*" + identifiers = each.value + } + } + statement { + effect = "Allow" + actions = ["sts:GetServiceBearerToken"] + resources = [aws_codeartifact_repository.repository[each.key].arn] + condition { + variable = "sts:AWSServiceName" + values = ["codeartifact.amazonaws.com"] + test = "StringEquals" + } + } +} + +data "aws_iam_policy_document" "default_write_access_repo_policy" { + for_each = { for k, v in local.repo_write_access_principals : k => v if v != null } + statement { + effect = "Allow" + actions = [ + "codeartifact:GetAuthorizationToken", + "codeartifact:GetRepositoryEndpoint", + "codeartifact:ReadFromRepository", + "codeartifact:PutPackageMetadata", + "codeartifact:PublishPackageVersion" + ] + resources = [aws_codeartifact_repository.repository[each.key].arn] + principals { + type = "*" + identifiers = each.value + } + } + statement { + effect = "Allow" + actions = ["sts:GetServiceBearerToken"] + resources = [aws_codeartifact_repository.repository[each.key].arn] + condition { + variable = "sts:AWSServiceName" + values = ["codeartifact.amazonaws.com"] + test = "StringEquals" + } + } +} + +data "aws_iam_policy_document" "combined_default_policies" { + for_each = { for repo in var.repositories : repo.repository_name => repo if local.repo_read_access_principals[repo.repository_name] != null || local.repo_write_access_principals[repo.repository_name] != null } + + source_policy_documents = compact( + [ + try(data.aws_iam_policy_document.default_readonly_repo_policy[each.key].json, null), + try(data.aws_iam_policy_document.default_write_access_repo_policy[each.key].json, null) + ] + ) +} + resource "aws_codeartifact_repository_permissions_policy" "repo_permissions_policy" { - for_each = { for repo in var.repositories : repo.repository_name => repo if repo.policy_document_path != null } + for_each = { for repo in var.repositories : repo.repository_name => repo } repository = aws_codeartifact_repository.repository[each.key].repository domain = aws_codeartifact_domain.repo_domain.domain - policy_document = file(each.value.policy_document_path) + policy_document = each.value.policy_document_path != null ? file(each.value.policy_document_path) : (contains(keys(local.repo_final_policy_documents), each.key) ? local.repo_final_policy_documents[each.key].json : null) region = var.repo_region != null ? var.repo_region : null domain_owner = each.value.domain_owner != null ? each.value.domain_owner : null } diff --git a/codeartifact-repo/outputs.tf b/codeartifact-repo/outputs.tf index 3d90ab3..c69713d 100644 --- a/codeartifact-repo/outputs.tf +++ b/codeartifact-repo/outputs.tf @@ -15,3 +15,8 @@ output "created_repositories" { description = "A list of names of the created repositories." value = tolist(keys(aws_codeartifact_repository.repository)) } + +output "debug_repo_final_policy" { + description = "DEBUG: Shows the generated repository policies." + value = local.repo_final_policy_documents +} diff --git a/codeartifact-repo/tests/policies.tftest.hcl b/codeartifact-repo/tests/policies.tftest.hcl new file mode 100644 index 0000000..9cda502 --- /dev/null +++ b/codeartifact-repo/tests/policies.tftest.hcl @@ -0,0 +1,113 @@ +// Copyright 2025 Bitshift +// SPDX-License-Identifier: MPL-2.0 + +mock_provider "aws" {} + +run "default_policy_should_be_created_when_principals_specified" { + command = plan + + variables { + domain_name = "test-domain" + repositories = [ + { + repository_name = "repo-with-policies" + default_read_access_principals = ["arn:aws:iam::123456789012:role/ReadRole"] + default_write_access_principals = ["arn:aws:iam::123456789012:role/WriteRole"] + } + ] + } + + assert { + condition = length(data.aws_iam_policy_document.default_readonly_repo_policy) == 1 + error_message = "Default read-only policy document was not created." + } + + assert { + condition = length(data.aws_iam_policy_document.default_write_access_repo_policy) == 1 + error_message = "Default write-access policy document was not created." + } +} + +run "no_default_policy_when_no_principals" { + command = plan + + variables { + domain_name = "test-domain" + repositories = [ + { + repository_name = "repo-without-policies" + } + ] + } + + assert { + condition = length(data.aws_iam_policy_document.default_readonly_repo_policy) == 0 + error_message = "Default read-only policy document was created despite no principals being specified." + } + + assert { + condition = length(data.aws_iam_policy_document.default_write_access_repo_policy) == 0 + error_message = "Default write-access policy document was created despite no principals being specified." + } +} + +run "combined_policy_created_when_either_principal_specified" { + command = plan + + variables { + domain_name = "test-domain" + repositories = [ + { + repository_name = "repo-with-read-policy" + default_read_access_principals = ["arn:aws:iam::123456789012:role/ReadRole"] + }, + { + repository_name = "repo-with-write-policy" + default_write_access_principals = ["arn:aws:iam::123456789012:role/WriteRole"] + } + ] + } + + assert { + condition = length(data.aws_iam_policy_document.combined_default_policies) == 2 + error_message = "Combined default policies were not created correctly when either read or write principals were specified." + } +} + +run "no_combined_policy_when_no_principals" { + command = plan + + variables { + domain_name = "test-domain" + repositories = [ + { + repository_name = "repo-without-policies" + } + ] + } + + assert { + condition = length(data.aws_iam_policy_document.combined_default_policies) == 0 + error_message = "Combined default policy was created despite no principals being specified." + } +} + +run "policy_file_should_override_default_policy" { + command = plan + + variables { + domain_name = "test-domain" + repositories = [ + { + repository_name = "repo-with-policy-file" + policy_document_path = "tests/test-repo-policy.json" + default_read_access_principals = ["arn:aws:iam::123456789012:role/ReadRole"] + } + ] + } + + assert { + condition = length(aws_codeartifact_repository_permissions_policy.repo_permissions_policy) == 1 + error_message = "Repository permissions policy was not created when a policy document path was provided." + } +} \ No newline at end of file diff --git a/codeartifact-repo/variables.tf b/codeartifact-repo/variables.tf index 4a7b6a3..c5a8b1d 100644 --- a/codeartifact-repo/variables.tf +++ b/codeartifact-repo/variables.tf @@ -50,13 +50,15 @@ variable "domain_permissions_policy_revision" { variable "repositories" { type = list(object({ - repository_name = string - description = optional(string, "") - region = optional(string, null) - domain_owner = optional(string, null) - upstream = optional(string, null) - external_connection = optional(string, null) - policy_document_path = optional(string, null) + repository_name = string + description = optional(string, "") + region = optional(string, null) + domain_owner = optional(string, null) + upstream = optional(string, null) + external_connection = optional(string, null) + policy_document_path = optional(string, null) + default_read_access_principals = optional(list(string), null) + default_write_access_principals = optional(list(string), null) })) description = "List of repositories within Codeartifact domain" default = [] diff --git a/scripts/format.sh b/scripts/format.sh index 04d721f..fea120e 100755 --- a/scripts/format.sh +++ b/scripts/format.sh @@ -5,6 +5,7 @@ GOPATH=$(go env GOPATH) echo "Formatting files..." echo "Adding license headers..." +echo "dir: $(pwd)" $GOPATH/bin/addlicense -c 'Bitshift' -y 2025 -l mpl -s=only ./*.tf || exit 1 cd tests && $GOPATH/bin/addlicense -check -c 'Bitshift' -y 2025 -l mpl -s=only ./*.tftest.hcl || exit 1 cd .. @@ -14,3 +15,7 @@ echo "License headers added successfully" echo "Running Terraform format..." terraform fmt || exit 1 echo "Terraform formatting successfull" + +echo "Generating terraform docs..." +terraform-docs -c ../.terraform-docs.yaml . || exit 1 +echo "Terraform docs generated successfully" From c35a3015c665a277f8482edf45a6e7ef63d6e406 Mon Sep 17 00:00:00 2001 From: Vladimir Djurovic Date: Mon, 1 Dec 2025 16:27:51 +0100 Subject: [PATCH 2/3] fix apply errors --- codeartifact-repo/README.md | 2 ++ codeartifact-repo/main.tf | 65 +++++++++++++++++++++++------------- codeartifact-repo/outputs.tf | 11 ++++-- 3 files changed, 51 insertions(+), 27 deletions(-) diff --git a/codeartifact-repo/README.md b/codeartifact-repo/README.md index 7b1bae4..a184d32 100644 --- a/codeartifact-repo/README.md +++ b/codeartifact-repo/README.md @@ -54,8 +54,10 @@ This module is intended to configure AWS CodeArtifact domains and repositories. | Name | Description | |------|-------------| | [created\_repositories](#output\_created\_repositories) | A list of names of the created repositories. | +| [default\_sts\_policies](#output\_default\_sts\_policies) | Created STS policies | | [domain](#output\_domain) | Name of the CodeArtifact domain | | [domain\_owner](#output\_domain\_owner) | Owner account of the CodeArtifact domain | +| [policy\_documents](#output\_policy\_documents) | A map of repository names to their applied policy documents (if any). | ## Examples \ No newline at end of file diff --git a/codeartifact-repo/main.tf b/codeartifact-repo/main.tf index 27daa65..28b8cd2 100644 --- a/codeartifact-repo/main.tf +++ b/codeartifact-repo/main.tf @@ -12,8 +12,15 @@ locals { repo_write_access_principals = { for repo in var.repositories : repo.repository_name => repo.default_write_access_principals } - repo_final_policy_documents = { - for repo in var.repositories : repo.repository_name => data.aws_iam_policy_document.combined_default_policies[repo.repository_name] if length(data.aws_iam_policy_document.combined_default_policies) > 0 && contains(keys(data.aws_iam_policy_document.combined_default_policies),repo.repository_name) + repo_final_policy_documents = data.aws_iam_policy_document.combined_default_policies + repos_with_policy_files = [ + for repo in var.repositories : repo.repository_name if repo.policy_document_path != null + ] + all_sts_principals = { + for repo in var.repositories : repo.repository_name => distinct(concat( + repo.default_read_access_principals != null ? repo.default_read_access_principals : [], + repo.default_write_access_principals != null ? repo.default_write_access_principals : [] + )) } } @@ -62,26 +69,22 @@ data "aws_iam_policy_document" "default_readonly_repo_policy" { statement { effect = "Allow" actions = [ - "codeartifact:GetAuthorizationToken", + "codeartifact:DescribePackageVersion", + "codeartifact:DescribeRepository", + "codeartifact:GetPackageVersionReadme", "codeartifact:GetRepositoryEndpoint", - "codeartifact:ReadFromRepository", + "codeartifact:ListPackageVersionAssets", + "codeartifact:ListPackageVersionDependencies", + "codeartifact:ListPackageVersions", + "codeartifact:ListPackages", + "codeartifact:ReadFromRepository" ] - resources = [aws_codeartifact_repository.repository[each.key].arn] + resources = ["*"] principals { - type = "*" + type = "AWS" identifiers = each.value } } - statement { - effect = "Allow" - actions = ["sts:GetServiceBearerToken"] - resources = [aws_codeartifact_repository.repository[each.key].arn] - condition { - variable = "sts:AWSServiceName" - values = ["codeartifact.amazonaws.com"] - test = "StringEquals" - } - } } data "aws_iam_policy_document" "default_write_access_repo_policy" { @@ -89,22 +92,36 @@ data "aws_iam_policy_document" "default_write_access_repo_policy" { statement { effect = "Allow" actions = [ - "codeartifact:GetAuthorizationToken", + "codeartifact:DescribePackageVersion", + "codeartifact:DescribeRepository", + "codeartifact:GetPackageVersionReadme", "codeartifact:GetRepositoryEndpoint", - "codeartifact:ReadFromRepository", + "codeartifact:ListPackageVersionAssets", + "codeartifact:ListPackageVersionDependencies", + "codeartifact:ListPackageVersions", + "codeartifact:ListPackages", + "codeartifact:PublishPackageVersion", "codeartifact:PutPackageMetadata", - "codeartifact:PublishPackageVersion" + "codeartifact:ReadFromRepository" ] - resources = [aws_codeartifact_repository.repository[each.key].arn] + resources = ["*"] principals { - type = "*" + type = "AWS" identifiers = each.value } } +} + +data "aws_iam_policy_document" "default_sts_policy" { + for_each = local.all_sts_principals statement { effect = "Allow" actions = ["sts:GetServiceBearerToken"] resources = [aws_codeartifact_repository.repository[each.key].arn] + principals { + type = "AWS" + identifiers = each.value + } condition { variable = "sts:AWSServiceName" values = ["codeartifact.amazonaws.com"] @@ -114,7 +131,7 @@ data "aws_iam_policy_document" "default_write_access_repo_policy" { } data "aws_iam_policy_document" "combined_default_policies" { - for_each = { for repo in var.repositories : repo.repository_name => repo if local.repo_read_access_principals[repo.repository_name] != null || local.repo_write_access_principals[repo.repository_name] != null } + for_each = { for repo in var.repositories : repo.repository_name => repo if(local.repo_read_access_principals[repo.repository_name] != null || local.repo_write_access_principals[repo.repository_name] != null) && repo.policy_document_path == null } source_policy_documents = compact( [ @@ -125,10 +142,10 @@ data "aws_iam_policy_document" "combined_default_policies" { } resource "aws_codeartifact_repository_permissions_policy" "repo_permissions_policy" { - for_each = { for repo in var.repositories : repo.repository_name => repo } + for_each = { for repo in var.repositories : repo.repository_name => repo if repo.policy_document_path != null || contains(keys(local.repo_final_policy_documents), repo.repository_name) } repository = aws_codeartifact_repository.repository[each.key].repository domain = aws_codeartifact_domain.repo_domain.domain - policy_document = each.value.policy_document_path != null ? file(each.value.policy_document_path) : (contains(keys(local.repo_final_policy_documents), each.key) ? local.repo_final_policy_documents[each.key].json : null) + policy_document = each.value.policy_document_path != null ? file(each.value.policy_document_path) : local.repo_final_policy_documents[each.key].json region = var.repo_region != null ? var.repo_region : null domain_owner = each.value.domain_owner != null ? each.value.domain_owner : null } diff --git a/codeartifact-repo/outputs.tf b/codeartifact-repo/outputs.tf index c69713d..6c55eaf 100644 --- a/codeartifact-repo/outputs.tf +++ b/codeartifact-repo/outputs.tf @@ -16,7 +16,12 @@ output "created_repositories" { value = tolist(keys(aws_codeartifact_repository.repository)) } -output "debug_repo_final_policy" { - description = "DEBUG: Shows the generated repository policies." - value = local.repo_final_policy_documents +output "policy_documents" { + description = "A map of repository names to their applied policy documents (if any)." + value = { for repo_name, repo_policy in aws_codeartifact_repository_permissions_policy.repo_permissions_policy : repo_name => repo_policy.policy_document } } + +output "default_sts_policies" { + description = "Created STS policies" + value = { for repo_name, sts_policy in data.aws_iam_policy_document.default_sts_policy : repo_name => sts_policy.json } +} \ No newline at end of file From bcf3f7c11fad759f34f110e6c1d80bcb174adca2 Mon Sep 17 00:00:00 2001 From: Vladimir Djurovic Date: Tue, 2 Dec 2025 15:55:33 +0100 Subject: [PATCH 3/3] fix policy check --- codeartifact-repo/main.tf | 29 ++++++++++++--------- codeartifact-repo/tests/policies.tftest.hcl | 26 +++++++++++++++++- 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/codeartifact-repo/main.tf b/codeartifact-repo/main.tf index 28b8cd2..ec9081f 100644 --- a/codeartifact-repo/main.tf +++ b/codeartifact-repo/main.tf @@ -7,15 +7,17 @@ locals { should_create_kms_key = (!var.use_default_ecnryption_key && var.encryption_key_arn == null) ? true : false repo_read_access_principals = { - for repo in var.repositories : repo.repository_name => repo.default_read_access_principals + for repo in var.repositories : repo.repository_name => repo.default_read_access_principals if(repo.default_read_access_principals != null + && length(repo.default_read_access_principals) > 0) } repo_write_access_principals = { - for repo in var.repositories : repo.repository_name => repo.default_write_access_principals + for repo in var.repositories : repo.repository_name => repo.default_write_access_principals if(repo.default_write_access_principals != null + && length(repo.default_write_access_principals) > 0) } repo_final_policy_documents = data.aws_iam_policy_document.combined_default_policies - repos_with_policy_files = [ - for repo in var.repositories : repo.repository_name if repo.policy_document_path != null - ] + # repos_with_policy_files = [ + # for repo in var.repositories : repo.repository_name if repo.policy_document_path != null + # ] all_sts_principals = { for repo in var.repositories : repo.repository_name => distinct(concat( repo.default_read_access_principals != null ? repo.default_read_access_principals : [], @@ -65,7 +67,7 @@ resource "aws_codeartifact_repository" "repository" { } data "aws_iam_policy_document" "default_readonly_repo_policy" { - for_each = { for k, v in local.repo_read_access_principals : k => v if v != null } + for_each = { for k, v in local.repo_read_access_principals : k => v } statement { effect = "Allow" actions = [ @@ -77,9 +79,9 @@ data "aws_iam_policy_document" "default_readonly_repo_policy" { "codeartifact:ListPackageVersionDependencies", "codeartifact:ListPackageVersions", "codeartifact:ListPackages", - "codeartifact:ReadFromRepository" + "codeartifact:ReadFromRepository", ] - resources = ["*"] + resources = [aws_codeartifact_repository.repository[each.key].arn] principals { type = "AWS" identifiers = each.value @@ -88,7 +90,7 @@ data "aws_iam_policy_document" "default_readonly_repo_policy" { } data "aws_iam_policy_document" "default_write_access_repo_policy" { - for_each = { for k, v in local.repo_write_access_principals : k => v if v != null } + for_each = { for k, v in local.repo_write_access_principals : k => v } statement { effect = "Allow" actions = [ @@ -102,9 +104,9 @@ data "aws_iam_policy_document" "default_write_access_repo_policy" { "codeartifact:ListPackages", "codeartifact:PublishPackageVersion", "codeartifact:PutPackageMetadata", - "codeartifact:ReadFromRepository" + "codeartifact:ReadFromRepository", ] - resources = ["*"] + resources = [aws_codeartifact_repository.repository[each.key].arn] principals { type = "AWS" identifiers = each.value @@ -131,12 +133,13 @@ data "aws_iam_policy_document" "default_sts_policy" { } data "aws_iam_policy_document" "combined_default_policies" { - for_each = { for repo in var.repositories : repo.repository_name => repo if(local.repo_read_access_principals[repo.repository_name] != null || local.repo_write_access_principals[repo.repository_name] != null) && repo.policy_document_path == null } + for_each = { for repo in var.repositories : repo.repository_name => repo if contains(keys(local.repo_read_access_principals), repo.repository_name) || contains(keys(local.repo_write_access_principals), repo.repository_name) } source_policy_documents = compact( [ try(data.aws_iam_policy_document.default_readonly_repo_policy[each.key].json, null), - try(data.aws_iam_policy_document.default_write_access_repo_policy[each.key].json, null) + try(data.aws_iam_policy_document.default_write_access_repo_policy[each.key].json, null), + try(data.aws_iam_policy_document.default_sts_policy[each.key].json, null) ] ) } diff --git a/codeartifact-repo/tests/policies.tftest.hcl b/codeartifact-repo/tests/policies.tftest.hcl index 9cda502..f12d8dc 100644 --- a/codeartifact-repo/tests/policies.tftest.hcl +++ b/codeartifact-repo/tests/policies.tftest.hcl @@ -1,7 +1,26 @@ // Copyright 2025 Bitshift // SPDX-License-Identifier: MPL-2.0 -mock_provider "aws" {} +mock_provider "aws" { + override_data { + target = data.aws_iam_policy_document.default_readonly_repo_policy + values = { + json = "{}" + } + } + override_data { + target = data.aws_iam_policy_document.default_write_access_repo_policy + values = { + json = "{}" + } + } + override_data { + target = data.aws_iam_policy_document.combined_default_policies + values = { + json = "{}" + } + } +} run "default_policy_should_be_created_when_principals_specified" { command = plan @@ -26,6 +45,11 @@ run "default_policy_should_be_created_when_principals_specified" { condition = length(data.aws_iam_policy_document.default_write_access_repo_policy) == 1 error_message = "Default write-access policy document was not created." } + + assert { + condition = length(data.aws_iam_policy_document.default_sts_policy) == 1 + error_message = "Default STS policy document was not created." + } } run "no_default_policy_when_no_principals" {