From b6e981ec994ca0391e47b53853830b34ea814204 Mon Sep 17 00:00:00 2001 From: Juan Garcia Losada Date: Tue, 16 Aug 2022 16:55:55 +0200 Subject: [PATCH] [OPT-353] Terraform alt_source parsing result in OTM schema validation error --- startleft/iac/mapping/mapper.py | 10 +- .../terraform/aws_altsource_components.tf | 70 --------- tests/unit/iac/mapping/test_mapper.py | 24 ++++ tests/unit/iac/test_iac_to_otm_tf_aws.py | 134 ++++++++++-------- 4 files changed, 109 insertions(+), 129 deletions(-) create mode 100644 tests/unit/iac/mapping/test_mapper.py diff --git a/startleft/iac/mapping/mapper.py b/startleft/iac/mapping/mapper.py index d980ad03..99ebe24d 100644 --- a/startleft/iac/mapping/mapper.py +++ b/startleft/iac/mapping/mapper.py @@ -98,13 +98,19 @@ def get_tags(source_model, source_object, mapping): if mapping is not None: if isinstance(mapping, list): for tag in mapping: - c_tags.append(source_model.search(tag, source=source_object)) + __search_and_add_tag(c_tags, tag, source_model, source_object) else: - c_tags.append(source_model.search(mapping, source=source_object)) + __search_and_add_tag(c_tags, mapping, source_model, source_object) return c_tags +def __search_and_add_tag(c_tags: [], query, source_model, source_object): + tag = source_model.search(query, source=source_object) + if isinstance(tag, str): + c_tags.append(tag) + + def set_optional_parameters_to_resource(resource, mapping_tags, resource_tags, singleton_multiple_name=None, singleton_multiple_tags=None): if mapping_tags is not None and resource_tags is not None and len( diff --git a/tests/resources/terraform/aws_altsource_components.tf b/tests/resources/terraform/aws_altsource_components.tf index 7017648b..1d7a3459 100644 --- a/tests/resources/terraform/aws_altsource_components.tf +++ b/tests/resources/terraform/aws_altsource_components.tf @@ -32,60 +32,10 @@ variable "subnet_cidrs" { default = [] } -resource "aws_subnet" "subnets" { - count = length(local.selected_subnet_cidrs) - vpc_id = data.aws_vpc.selected.id - availability_zone = data.aws_availability_zones.available.names[count.index] - cidr_block = local.selected_subnet_cidrs[count.index] - tags { - Name = "VPC Endpoint" - } -} -resource "aws_security_group" "vpc_endpoint" { - name = "vpc_endpoint" - description = "Allow VPC traffic to communicate with AWS Services" - vpc_id = data.aws_vpc.selected.id - - ingress { - from_port = 443 - to_port = 443 - protocol = "tcp" - cidr_blocks = [var.vpc_id] - } -} -resource "aws_vpc_endpoint" "ec2" { - vpc_id = data.aws_vpc.selected.id - service_name = "com.amazonaws.${var.region}.ec2" - vpc_endpoint_type = "Interface" - subnet_ids = [aws_subnet.subnets.*.id] - - security_group_ids = [ - aws_security_group.vpc_endpoint.id - ] - - private_dns_enabled = true -} -resource "aws_vpc_endpoint" "ec2_messages" { - vpc_id = data.aws_vpc.selected.id - service_name = "com.amazonaws.${var.region}.ec2messages" - vpc_endpoint_type = "Interface" - subnet_ids = [aws_subnet.subnets.*.id] - - security_group_ids = [ - aws_security_group.vpc_endpoint.id - ] - - private_dns_enabled = true -} resource "aws_vpc_endpoint" "ssm" { vpc_id = data.aws_vpc.selected.id service_name = "com.amazonaws.${var.region}.ssm" vpc_endpoint_type = "Interface" - subnet_ids = [aws_subnet.subnets.*.id] - - security_group_ids = [ - aws_security_group.vpc_endpoint.id - ] private_dns_enabled = true } @@ -93,11 +43,6 @@ resource "aws_vpc_endpoint" "ssm_messages" { vpc_id = data.aws_vpc.selected.id service_name = "com.amazonaws.${var.region}.ssmmessages" vpc_endpoint_type = "Interface" - subnet_ids = [aws_subnet.subnets.*.id] - - security_group_ids = [ - aws_security_group.vpc_endpoint.id - ] private_dns_enabled = true } @@ -105,11 +50,6 @@ resource "aws_vpc_endpoint" "ecr" { vpc_id = data.aws_vpc.selected.id service_name = "com.amazonaws.${var.region}.ecr.dkr" vpc_endpoint_type = "Interface" - subnet_ids = [aws_subnet.subnets.*.id] - - security_group_ids = [ - aws_security_group.vpc_endpoint.id - ] private_dns_enabled = true } @@ -117,11 +57,6 @@ resource "aws_vpc_endpoint" "dynamodb" { vpc_id = data.aws_vpc.selected.id service_name = "com.amazonaws.${var.region}.dynamodb" vpc_endpoint_type = "Interface" - subnet_ids = [aws_subnet.subnets.*.id] - - security_group_ids = [ - aws_security_group.vpc_endpoint.id - ] private_dns_enabled = true } @@ -129,11 +64,6 @@ resource "aws_vpc_endpoint" "s3" { vpc_id = data.aws_vpc.selected.id service_name = "com.amazonaws.${var.region}.s3" vpc_endpoint_type = "Interface" - subnet_ids = [aws_subnet.subnets.*.id] - - security_group_ids = [ - aws_security_group.vpc_endpoint.id - ] private_dns_enabled = true } diff --git a/tests/unit/iac/mapping/test_mapper.py b/tests/unit/iac/mapping/test_mapper.py new file mode 100644 index 00000000..4e19927f --- /dev/null +++ b/tests/unit/iac/mapping/test_mapper.py @@ -0,0 +1,24 @@ +from unittest.mock import patch, MagicMock + +from startleft.iac.mapping.mapper import get_tags + + +class TestMapper: + + @patch("startleft.iac.mapping.sourcemodel.SourceModel") + def test_get_tags_with_mapping_str(self, mock_source_model): + mock_source_model.search.return_value = 'value' + c_tags = get_tags(mock_source_model, MagicMock(), MagicMock()) + assert len(c_tags) is 1 + + @patch("startleft.iac.mapping.sourcemodel.SourceModel") + def test_get_tags_with_mapping_list(self, mock_source_model): + mock_source_model.search.return_value = 'value' + c_tags = get_tags(mock_source_model, MagicMock(), [MagicMock(), MagicMock()]) + assert len(c_tags) is 2 + + @patch("startleft.iac.mapping.sourcemodel.SourceModel") + def test_get_tags_with_attribute_not_found(self, mock_source_model): + mock_source_model.search.return_value = [] + c_tags = get_tags(mock_source_model, MagicMock(), MagicMock()) + assert len(c_tags) is 0 diff --git a/tests/unit/iac/test_iac_to_otm_tf_aws.py b/tests/unit/iac/test_iac_to_otm_tf_aws.py index 7ec0177b..e8fc9db1 100644 --- a/tests/unit/iac/test_iac_to_otm_tf_aws.py +++ b/tests/unit/iac/test_iac_to_otm_tf_aws.py @@ -46,25 +46,30 @@ def test_aws_multiple_components(self): assert_otm_component(otm, 0, 'empty-component', 'gw', self.public_cloud_id, ['aws_internet_gateway']) assert_otm_component(otm, 1, 'elastic-container-service', 'mongo', self.public_cloud_id, ['aws_ecs_service']) assert_otm_component(otm, 2, 'docker-container', 'service', self.public_cloud_id, ['aws_ecs_task_definition']) - assert_otm_component(otm, 3, 'docker-container', 'service_task', self.public_cloud_id, ['aws_ecs_task_definition']) + assert_otm_component(otm, 3, 'docker-container', 'service_task', self.public_cloud_id, + ['aws_ecs_task_definition']) assert_otm_component(otm, 4, 'load-balancer', 'lb', None, ['aws_lb']) assert_otm_component(otm, 5, 'load-balancer', 'wu-tang', None, ['aws_elb']) - assert_otm_component(otm, 6, 'aws-lambda-function', 'test_lambda', self.public_cloud_id, ['aws_lambda_function']) + assert_otm_component(otm, 6, 'aws-lambda-function', 'test_lambda', self.public_cloud_id, + ['aws_lambda_function']) assert_otm_component(otm, 7, 'rds', 'mysql', self.public_cloud_id, ['aws_db_instance']) assert_otm_component(otm, 8, 'rds', 'aurora-cluster-demo', self.public_cloud_id, ['aws_rds_cluster']) assert_otm_component(otm, 9, 'route-53', 'route-53-zone-example', self.public_cloud_id, ['aws_route53_zone']) assert_otm_component(otm, 10, 's3', 'foo_s3_bucket', self.public_cloud_id, ['aws_s3_bucket']) - assert_otm_component(otm, 11, 'sqs-simple-queue-service', 'terraform_queue', self.public_cloud_id, ['aws_sqs_queue']) + assert_otm_component(otm, 11, 'sqs-simple-queue-service', 'terraform_queue', self.public_cloud_id, + ['aws_sqs_queue']) assert_otm_component(otm, 12, 'empty-component', 'some-canary', self.public_cloud_id, ['aws_synthetics_canary']) assert_otm_component(otm, 13, 'cloudtrail', 'foobar', self.public_cloud_id, ['aws_cloudtrail']) assert_otm_component(otm, 14, 'cognito', 'pool', self.public_cloud_id, ['aws_cognito_user_pool']) assert_otm_component(otm, 15, 'cognito', 'main', self.public_cloud_id, ['aws_cognito_identity_pool']) - assert_otm_component(otm, 16, 'elastic-container-kubernetes', 'example', self.public_cloud_id, ['aws_eks_cluster']) + assert_otm_component(otm, 16, 'elastic-container-kubernetes', 'example', self.public_cloud_id, + ['aws_eks_cluster']) assert_otm_component(otm, 17, 'CD-AWS-NETWORK-FIREWALL', 'firewall_example', None, ['aws_networkfirewall_firewall']) assert_otm_component(otm, 18, 'redshift', 'tf-redshift-cluster', self.public_cloud_id, ['aws_redshift_cluster']) assert_otm_component(otm, 19, 'step-functions', 'my_sfn_activity', self.public_cloud_id, ['aws_sfn_activity']) - assert_otm_component(otm, 20, 'step-functions', 'my_sfn_state_machine', self.public_cloud_id, ['aws_sfn_state_machine']) + assert_otm_component(otm, 20, 'step-functions', 'my_sfn_state_machine', self.public_cloud_id, + ['aws_sfn_state_machine']) def test_aws_parent_children_components(self): filename = test_resource_paths.terraform_aws_parent_children_components @@ -137,11 +142,12 @@ def test_aws_singleton_components(self, filename: str, break_line: str): 'config_config_rule (aws_config_config_rule)', 'config_configuration_recorder (aws_config_configuration_recorder)' ]) - assert_otm_component(otm, 10, 'elastic-container-registry', 'elastic-container-registry (grouped)', self.public_cloud_id, + assert_otm_component(otm, 10, 'elastic-container-registry', 'elastic-container-registry (grouped)', + self.public_cloud_id, [ - 'ecr_repository (aws_ecr_repository)', - 'ecr_lifecycle_policy (aws_ecr_lifecycle_policy)' - ]) + 'ecr_repository (aws_ecr_repository)', + 'ecr_lifecycle_policy (aws_ecr_lifecycle_policy)' + ]) assert_otm_component(otm, 11, 'elasticache', 'elasticache (grouped)', self.public_cloud_id, [ 'elasticache_user (aws_elasticache_user)', 'elasticache_user_group (aws_elasticache_user_group)' @@ -170,16 +176,18 @@ def test_aws_singleton_components(self, filename: str, break_line: str): 'waf_ipset (aws_waf_ipset)', 'waf_rule (aws_waf_rule)' ]) - assert_otm_component(otm, 18, 'kinesis-data-analytics', 'kinesis-data-analytics (grouped)', self.public_cloud_id, [ - 'kinesis_analytics_application_1 (aws_kinesis_analytics_application)', - 'kinesis_analytics_application_2 (aws_kinesis_analytics_application)', - 'kinesis_stream (aws_kinesis_stream)', - 'kinesis_stream_consumer (aws_kinesis_stream_consumer)' - ]) - assert_otm_component(otm, 19, 'kinesis-data-firehose', 'kinesis-data-firehose (grouped)', self.public_cloud_id, [ - 'kinesis_firehose_delivery_stream_1 (aws_kinesis_firehose_delivery_stream)', - 'kinesis_firehose_delivery_stream_1 (aws_kinesis_firehose_delivery_stream)' - ]) + assert_otm_component(otm, 18, 'kinesis-data-analytics', 'kinesis-data-analytics (grouped)', + self.public_cloud_id, [ + 'kinesis_analytics_application_1 (aws_kinesis_analytics_application)', + 'kinesis_analytics_application_2 (aws_kinesis_analytics_application)', + 'kinesis_stream (aws_kinesis_stream)', + 'kinesis_stream_consumer (aws_kinesis_stream_consumer)' + ]) + assert_otm_component(otm, 19, 'kinesis-data-firehose', 'kinesis-data-firehose (grouped)', self.public_cloud_id, + [ + 'kinesis_firehose_delivery_stream_1 (aws_kinesis_firehose_delivery_stream)', + 'kinesis_firehose_delivery_stream_1 (aws_kinesis_firehose_delivery_stream)' + ]) def test_aws_altsource_components(self): filename = test_resource_paths.terraform_aws_altsource_components @@ -191,33 +199,26 @@ def test_aws_altsource_components(self): assert iac_to_otm.otm otm = iac_to_otm.otm assert len(otm.trustzones) == 1 - assert len(otm.components) == 13 + assert len(otm.components) == 9 assert_otm_component(otm, 0, 'dynamodb', 'DynamoDB from VPCEndpoint', None, ['dynamodb (aws_vpc_endpoint)']) - assert_otm_component(otm, 1, 'empty-component', 'subnets', None, ['aws_subnet']) - assert_otm_component(otm, 2, 'empty-component', 'ec2', None, ['aws_vpc_endpoint']) - assert_otm_component(otm, 3, 'empty-component', 'ec2_messages', None, ['aws_vpc_endpoint']) - assert_otm_component(otm, 4, 'empty-component', 'ssm', None, ['aws_vpc_endpoint']) - assert_otm_component(otm, 5, 'empty-component', 'ssm_messages', None, ['aws_vpc_endpoint']) - assert_otm_component(otm, 6, 'empty-component', 'ecr', None, ['aws_vpc_endpoint']) - assert_otm_component(otm, 7, 'empty-component', 'dynamodb', None, ['aws_vpc_endpoint']) - assert_otm_component(otm, 8, 'empty-component', 's3', None, ['aws_vpc_endpoint']) - assert_otm_component(otm, 9, 's3', 'S3 from VPCEndpoint', None, ['s3 (aws_vpc_endpoint)']) - assert_otm_component(otm, 10, 'generic-client', '0.0.0.0/0', None, - ['Inbound connection source IP']) - assert_otm_component(otm, 11, 'CD-SYSTEMS-MANAGER', 'Systems Manager from VPCEndpoint (grouped)', None, - [ - 'ssm (aws_vpc_endpoint)', - 'ssm_messages (aws_vpc_endpoint)' - ]) - assert_otm_component(otm, 12, 'elastic-container-registry', 'ECR from VPCEndpoint', None, + assert_otm_component(otm, 1, 'empty-component', 'ssm', None, ['aws_vpc_endpoint']) + assert_otm_component(otm, 2, 'empty-component', 'ssm_messages', None, ['aws_vpc_endpoint']) + assert_otm_component(otm, 3, 'empty-component', 'ecr', None, ['aws_vpc_endpoint']) + assert_otm_component(otm, 4, 'empty-component', 'dynamodb', None, ['aws_vpc_endpoint']) + assert_otm_component(otm, 5, 'empty-component', 's3', None, ['aws_vpc_endpoint']) + assert_otm_component(otm, 6, 's3', 'S3 from VPCEndpoint', None, ['s3 (aws_vpc_endpoint)']) + assert_otm_component(otm, 7, 'CD-SYSTEMS-MANAGER', 'Systems Manager from VPCEndpoint (grouped)', None, + ['ssm (aws_vpc_endpoint)', 'ssm_messages (aws_vpc_endpoint)']) + assert_otm_component(otm, 8, 'elastic-container-registry', 'ECR from VPCEndpoint', None, ['ecr (aws_vpc_endpoint)']) def test_aws_security_groups_components(self): filename = test_resource_paths.terraform_aws_security_groups_components iac_data = FileUtils.get_byte_data(filename).decode() mapping_filename = test_resource_paths.default_terraform_aws_mapping - iac_to_otm = IacToOtm('Test case AWS security groups components', 'aws_security_groups_components', IacType.TERRAFORM) + iac_to_otm = IacToOtm('Test case AWS security groups components', 'aws_security_groups_components', + IacType.TERRAFORM) iac_to_otm.run(IacType.TERRAFORM, [FileUtils.get_data(mapping_filename)], [iac_data]) otm = iac_to_otm.otm @@ -243,29 +244,42 @@ def test_aws_security_groups_components(self): assert_otm_component(otm, 10, 'empty-component', 'VPCmonitoring', otm.components[2].id, ['aws_vpc_endpoint']) assert_otm_component(otm, 11, 'elastic-container-service', 'Service', otm.components[1].id, ['aws_ecs_service']) assert_otm_component(otm, 12, 'elastic-container-service', 'Service', otm.components[2].id, ['aws_ecs_service']) - assert_otm_component(otm, 13, 'docker-container', 'ServiceTaskDefinition', otm.components[11].id, ['aws_ecs_task_definition']) - assert_otm_component(otm, 14, 'docker-container', 'ServiceTaskDefinition', otm.components[12].id, ['aws_ecs_task_definition']) + assert_otm_component(otm, 13, 'docker-container', 'ServiceTaskDefinition', otm.components[11].id, + ['aws_ecs_task_definition']) + assert_otm_component(otm, 14, 'docker-container', 'ServiceTaskDefinition', otm.components[12].id, + ['aws_ecs_task_definition']) assert_otm_component(otm, 15, 'load-balancer', 'ServiceLB', otm.components[1].id, ['aws_lb']) assert_otm_component(otm, 16, 'load-balancer', 'ServiceLB', otm.components[2].id, ['aws_lb']) assert_otm_component(otm, 17, 'empty-component', 'Canary', otm.components[3].id, ['aws_synthetics_canary']) assert_otm_component(otm, 18, 'empty-component', 'Canary', otm.components[4].id, ['aws_synthetics_canary']) - assert_otm_component(otm, 19, 'generic-client', '0.0.0.0/0', self.internet_id, ['Outbound connection destination IP']) - assert_otm_component(otm, 20, 'generic-client', '255.255.255.255/32', self.internet_id, ['Outbound connection destination IP']) - assert_otm_component(otm, 21, 'CD-SYSTEMS-MANAGER', 'Systems Manager from VPCEndpoint (grouped)', self.public_cloud_id, + assert_otm_component(otm, 19, 'generic-client', '0.0.0.0/0', self.internet_id, + ['Outbound connection destination IP']) + assert_otm_component(otm, 20, 'generic-client', '255.255.255.255/32', self.internet_id, + ['Outbound connection destination IP']) + assert_otm_component(otm, 21, 'CD-SYSTEMS-MANAGER', 'Systems Manager from VPCEndpoint (grouped)', + self.public_cloud_id, ['VPCssm (aws_vpc_endpoint)', 'VPCssmmessages (aws_vpc_endpoint)']) assert_otm_dataflow(otm, 0, otm.components[0].id, otm.components[5].id, 'VPCssmSecurityGroup -> VPCssm') assert_otm_dataflow(otm, 1, otm.components[5].id, otm.components[19].id, 'VPCssm -> VPCssmSecurityGroup') assert_otm_dataflow(otm, 2, otm.components[0].id, otm.components[6].id, 'VPCssmSecurityGroup -> VPCssm') assert_otm_dataflow(otm, 3, otm.components[6].id, otm.components[19].id, 'VPCssm -> VPCssmSecurityGroup') - assert_otm_dataflow(otm, 4, otm.components[0].id, otm.components[7].id, 'VPCssmmessagesSecurityGroup -> VPCssmmessages') - assert_otm_dataflow(otm, 5, otm.components[7].id, otm.components[19].id, 'VPCssmmessages -> VPCssmmessagesSecurityGroup') - assert_otm_dataflow(otm, 6, otm.components[0].id, otm.components[8].id, 'VPCssmmessagesSecurityGroup -> VPCssmmessages') - assert_otm_dataflow(otm, 7, otm.components[8].id, otm.components[19].id, 'VPCssmmessages -> VPCssmmessagesSecurityGroup') - assert_otm_dataflow(otm, 8, otm.components[0].id, otm.components[9].id, 'VPCmonitoringSecurityGroup -> VPCmonitoring') - assert_otm_dataflow(otm, 9, otm.components[9].id, otm.components[19].id, 'VPCmonitoring -> VPCmonitoringSecurityGroup') - assert_otm_dataflow(otm, 10, otm.components[0].id, otm.components[10].id, 'VPCmonitoringSecurityGroup -> VPCmonitoring') - assert_otm_dataflow(otm, 11, otm.components[10].id, otm.components[19].id, 'VPCmonitoring -> VPCmonitoringSecurityGroup') + assert_otm_dataflow(otm, 4, otm.components[0].id, otm.components[7].id, + 'VPCssmmessagesSecurityGroup -> VPCssmmessages') + assert_otm_dataflow(otm, 5, otm.components[7].id, otm.components[19].id, + 'VPCssmmessages -> VPCssmmessagesSecurityGroup') + assert_otm_dataflow(otm, 6, otm.components[0].id, otm.components[8].id, + 'VPCssmmessagesSecurityGroup -> VPCssmmessages') + assert_otm_dataflow(otm, 7, otm.components[8].id, otm.components[19].id, + 'VPCssmmessages -> VPCssmmessagesSecurityGroup') + assert_otm_dataflow(otm, 8, otm.components[0].id, otm.components[9].id, + 'VPCmonitoringSecurityGroup -> VPCmonitoring') + assert_otm_dataflow(otm, 9, otm.components[9].id, otm.components[19].id, + 'VPCmonitoring -> VPCmonitoringSecurityGroup') + assert_otm_dataflow(otm, 10, otm.components[0].id, otm.components[10].id, + 'VPCmonitoringSecurityGroup -> VPCmonitoring') + assert_otm_dataflow(otm, 11, otm.components[10].id, otm.components[19].id, + 'VPCmonitoring -> VPCmonitoringSecurityGroup') assert_otm_dataflow(otm, 12, otm.components[11].id, otm.components[20].id, 'Service -> OutboundSecurityGroup') assert_otm_dataflow(otm, 13, otm.components[12].id, otm.components[20].id, 'Service -> OutboundSecurityGroup') assert_otm_dataflow(otm, 14, otm.components[15].id, otm.components[11].id, 'ServiceLB -> Service') @@ -294,19 +308,25 @@ def test_aws_dataflows(self): assert_otm_trustzone(otm, 0, self.public_cloud_id, "Public Cloud") assert_otm_component(otm, 0, 'dynamodb', 'basic_dynamodb_table', self.public_cloud_id, ['aws_dynamodb_table']) - assert_otm_component(otm, 1, 'aws-lambda-function', 'basic_lambda', self.public_cloud_id, ['aws_lambda_function']) + assert_otm_component(otm, 1, 'aws-lambda-function', 'basic_lambda', self.public_cloud_id, + ['aws_lambda_function']) assert_otm_component(otm, 2, 's3', 'log_bucket_deprecated', self.public_cloud_id, ['aws_s3_bucket']) assert_otm_component(otm, 3, 's3', 'bucket_deprecated', self.public_cloud_id, ['aws_s3_bucket']) assert_otm_component(otm, 4, 's3', 'log_bucket', self.public_cloud_id, ['aws_s3_bucket']) assert_otm_component(otm, 5, 's3', 'bucket', self.public_cloud_id, ['aws_s3_bucket']) - assert_otm_component(otm, 6, 'sqs-simple-queue-service', 'failure_queue', self.public_cloud_id, ['aws_sqs_queue']) + assert_otm_component(otm, 6, 'sqs-simple-queue-service', 'failure_queue', self.public_cloud_id, + ['aws_sqs_queue']) assert_otm_component(otm, 7, 'cognito', 'user_pool', self.public_cloud_id, ['aws_cognito_user_pool']) assert_otm_component(otm, 8, 'api-gateway', 'api-gateway (grouped)', self.public_cloud_id, ['rest_api (aws_api_gateway_rest_api)', 'api_authorizer (aws_api_gateway_authorizer)']) - assert_otm_dataflow(otm, 0, otm.components[0].id, otm.components[1].id, 'dataflow to Lambda function in basic_dynamodb_event') - assert_otm_dataflow(otm, 1, otm.components[1].id, otm.components[6].id, 'dataflow from Lambda function on Failure basic_dynamodb_event') + assert_otm_dataflow(otm, 0, otm.components[0].id, otm.components[1].id, + 'dataflow to Lambda function in basic_dynamodb_event') + assert_otm_dataflow(otm, 1, otm.components[1].id, otm.components[6].id, + 'dataflow from Lambda function on Failure basic_dynamodb_event') assert_otm_dataflow(otm, 2, otm.components[3].id, otm.components[2].id, 'S3 dataflow from bucket_deprecated') - assert_otm_dataflow(otm, 3, otm.components[5].id, otm.components[4].id, 'S3 dataflow from aws_s3_bucket_logging') - assert_otm_dataflow(otm, 4, otm.components[8].id, otm.components[7].id, 'API gateway data flow from aws_api_gateway_authorizer') + assert_otm_dataflow(otm, 3, otm.components[5].id, otm.components[4].id, + 'S3 dataflow from aws_s3_bucket_logging') + assert_otm_dataflow(otm, 4, otm.components[8].id, otm.components[7].id, + 'API gateway data flow from aws_api_gateway_authorizer')