Open rslotte opened 9 months ago
File structure:
% tree terraform
terraform
├── main.tf
├── my-module
│ ├── module.tf
│ ├── my-data-module
│ │ └── output.tf
│ ├── my-nested-module
│ │ └── sg.tf
│ └── sg.tf
└── terraform.tf
Lets say our terraform module uses a my-module
module
main.tf
module "component" {
source = "./my-module"
}
the my-module
module creates its own security group using the my-data-module
as a data source
my-module/sg.tf
module "data-common" {
source = "./my-data-module"
}
resource "aws_security_group" "example_sg" {
name = "example_sg"
description = "Example security group"
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = module.data-common.cidr_blocks
}
}
also it uses the my-nested-module
to create another security group
my-module/module.tf
module "nested-component" {
source = "./my-nested-module"
}
my-module/my-nested-module/sg.tf
resource "aws_security_group" "example_sg_nested_host" {
name = "example_sg_nested_host"
description = "Example security group nested"
}
resource "aws_security_group" "example_sg_nested_client" {
name = "example_sg_nested_client"
description = "Example security group nested"
}
resource "aws_security_group_rule" "example_sg_nested_host_ingress_client" {
source_security_group_id = aws_security_group.example_sg_nested_client.id
security_group_id = aws_security_group.example_sg_nested_host.id
type = "ingress"
from_port = 443
to_port = 443
protocol = "tcp"
}
resource "aws_security_group_rule" "example_sg_nested_client_egress_host" {
source_security_group_id = aws_security_group.example_sg_nested_host.id
security_group_id = aws_security_group.example_sg_nested_client.id
type = "egress"
from_port = 443
to_port = 443
protocol = "tcp"
}
This setup causes the error described in the issue and a following warning
❗ WARNING (mounting): The reference "module.data-common" in resource aws_security_group.example_sg is ambiguous. It will not be mounted.
If we stop using my-data-module
the issue disappears. After replacing the my-module/sg.tf
file with a following content
my-module/sg.tf
resource "aws_security_group" "example_sg" {
name = "example_sg"
description = "Example security group"
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
it starts working fine again.
By adding a debug log in the if statement here https://github.com/terraform-compliance/cli/blob/e9f37e70f56b461287b1f799ea7711226f429868/terraform_compliance/extensions/terraform.py#L335-L336
like this
if parameter not in self.resources[source_resource]['values']:
self.resources[source_resource]['values'][parameter] = target_resource
defaults = Defaults()
console_write('{} {}: {}'.format(defaults.warning_icon,
defaults.warning_colour('WARNING (test)'),
defaults.info_colour('Injecting string into "{}" parameter... Source resource {}, target resource {} ref type "{}".'
''.format(parameter, source_resource, target_resource, ref_type))))
and another one just before the failing line here https://github.com/terraform-compliance/cli/blob/e9f37e70f56b461287b1f799ea7711226f429868/terraform_compliance/extensions/terraform.py#L325-L326
like this
if ref_type in self.resources[target_resource]['values'] and not isinstance(self.resources[target_resource]['values'][ref_type], list):
defaults = Defaults()
console_write('{} {}: {}'.format(defaults.warning_icon,
defaults.warning_colour('WARNING'),
defaults.info_colour('Source resource {}, target resource {} ref type "{}" is not a list. Parameter: {} '
'The value is: "{}"'.format(source_resource, target_resource, ref_type, parameter, self.resources[target_resource]['values'][ref_type]))))
we can see that the failing run logs following warnings
❗ WARNING (mounting): The reference "module.data-common" in resource module.component.aws_security_group.example_sg is ambiguous. It will not be mounted. ❗ WARNING (test): Injecting string into "ingress" parameter... Source resource module.component.module.nested-component.aws_security_group.example_sg_nested_client, target resource module.component.aws_security_group.example_sg ref type "aws_security_group". ❗ WARNING (test): Injecting string into "ingress" parameter... Source resource module.component.module.nested-component.aws_security_group.example_sg_nested_host, target resource module.component.aws_security_group.example_sg ref type "aws_security_group". ❗ WARNING (test): Injecting string into "ingress" parameter... Source resource module.component.module.nested-component.aws_security_group_rule.example_sg_nested_client_egress_host, target resource module.component.aws_security_group.example_sg ref type "aws_security_group_rule". ❗ WARNING (test): Injecting string into "ingress" parameter... Source resource module.component.module.nested-component.aws_security_group_rule.example_sg_nested_host_ingress_client, target resource module.component.aws_security_group.example_sg ref type "aws_security_group_rule". ❗ WARNING (test): Injecting string into "security_group_id" parameter... Source resource module.component.module.nested-component.aws_security_group_rule.example_sg_nested_client_egress_host, target resource module.component.module.nested-component.aws_security_group.example_sg_nested_client ref type "egress". ❗ WARNING (test): Injecting string into "source_security_group_id" parameter... Source resource module.component.module.nested-component.aws_security_group_rule.example_sg_nested_client_egress_host, target resource module.component.module.nested-component.aws_security_group.example_sg_nested_host ref type "egress". ❗ WARNING (test): Injecting string into "security_group_id" parameter... Source resource module.component.module.nested-component.aws_security_group.example_sg_nested_client, target resource module.component.module.nested-component.aws_security_group_rule.example_sg_nested_client_egress_host ref type "aws_security_group". ❗ WARNING (test): Injecting string into "source_security_group_id" parameter... Source resource module.component.module.nested-component.aws_security_group.example_sg_nested_host, target resource module.component.module.nested-component.aws_security_group_rule.example_sg_nested_client_egress_host ref type "aws_security_group". ❗ WARNING: Source resource module.component.module.nested-component.aws_security_group_rule.example_sg_nested_host_ingress_client, target resource module.component.module.nested-component.aws_security_group.example_sg_nested_host ref type "ingress" is not a list. Parameter: security_group_id The value is: "module.component.aws_security_group.example_sg"
where the successful run logs following
❗ WARNING (test): Injecting string into "security_group_id" parameter... Source resource module.component.module.nested-component.aws_security_group_rule.example_sg_nested_client_egress_host, target resource module.component.module.nested-component.aws_security_group.example_sg_nested_client ref type "egress". ❗ WARNING (test): Injecting string into "source_security_group_id" parameter... Source resource module.component.module.nested-component.aws_security_group_rule.example_sg_nested_client_egress_host, target resource module.component.module.nested-component.aws_security_group.example_sg_nested_host ref type "egress". ❗ WARNING (test): Injecting string into "security_group_id" parameter... Source resource module.component.module.nested-component.aws_security_group.example_sg_nested_client, target resource module.component.module.nested-component.aws_security_group_rule.example_sg_nested_client_egress_host ref type "aws_security_group". ❗ WARNING (test): Injecting string into "source_security_group_id" parameter... Source resource module.component.module.nested-component.aws_security_group.example_sg_nested_host, target resource module.component.module.nested-component.aws_security_group_rule.example_sg_nested_client_egress_host ref type "aws_security_group". ❗ WARNING (test): Injecting string into "security_group_id" parameter... Source resource module.component.module.nested-component.aws_security_group_rule.example_sg_nested_host_ingress_client, target resource module.component.module.nested-component.aws_security_group.example_sg_nested_host ref type "ingress". ❗ WARNING (test): Injecting string into "source_security_group_id" parameter... Source resource module.component.module.nested-component.aws_security_group_rule.example_sg_nested_host_ingress_client, target resource module.component.module.nested-component.aws_security_group.example_sg_nested_client ref type "ingress". ❗ WARNING (test): Injecting string into "security_group_id" parameter... Source resource module.component.module.nested-component.aws_security_group.example_sg_nested_host, target resource module.component.module.nested-component.aws_security_group_rule.example_sg_nested_host_ingress_client ref type "aws_security_group". ❗ WARNING (test): Injecting string into "source_security_group_id" parameter... Source resource module.component.module.nested-component.aws_security_group.example_sg_nested_client, target resource module.component.module.nested-component.aws_security_group_rule.example_sg_nested_host_ingress_client ref type "aws_security_group".
We can quickly tell that when we're using the my-data-module
the ingress
parameter is injected into all resources from my-nested-module
(including security groups) and this is probably what's causing the issue as on the subsequent runs we do not expect string here https://github.com/terraform-compliance/cli/blob/e9f37e70f56b461287b1f799ea7711226f429868/terraform_compliance/extensions/terraform.py#L328
Description
Getting the following error when running tf-compliance after checks:
The same Terraform code works fine in a different environment:
and here it runs the scenarios as expected.
To Reproduce
Is there a secure location I can upload the plan to?
Tested Versions: