Skip to content

Commit e0d91bd

Browse files
Merge branch 'dev' into feature/BLAZ-2678
2 parents 46b518f + 3515cec commit e0d91bd

20 files changed

Lines changed: 71590 additions & 12 deletions

slp_tfplan/tests/integration/test_tfplan.py renamed to slp_tfplan/tests/integration/test_tfplan_processor.py

Lines changed: 103 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
11
import random
2-
from typing import List
32

43
import pytest
54
from pytest import mark, param
65

76
import slp_tfplan.tests.resources.test_resource_paths as resources
87
from otm.otm.entity.otm import OTM
98
from sl_util.sl_util.file_utils import get_byte_data
10-
from slp_base import IacFileNotValidError
9+
from slp_base import IacFileNotValidError, MappingFileNotValidError
10+
from slp_base.slp_base.errors import ErrorCode
11+
from slp_base.slp_base.mapping import MAX_SIZE as MAPPING_MAX_SIZE, MIN_SIZE as MAPPING_MIN_SIZE
1112
from slp_base.tests.util.otm import validate_and_compare
1213
from slp_tfplan import TFPlanProcessor
1314
from slp_tfplan.tests.util.builders import create_artificial_file, MIN_FILE_SIZE, MAX_TFPLAN_FILE_SIZE, \
1415
MAX_TFGRAPH_FILE_SIZE
1516

1617
DEFAULT_MAPPING_FILE = get_byte_data(resources.terraform_iriusrisk_tfplan_aws_mapping)
18+
SECONDARY_DEFAULT_MAPPING_FILE = get_byte_data(resources.terraform_plan_default_mapping)
19+
CONFIG_CLIENT_MAPPING_FILE = get_byte_data(resources.terraform_plan_config_client_mapping)
20+
CONFIG_TRUSTZONE_MAPPING_FILE = get_byte_data(resources.terraform_plan_config_trustzone_mapping)
21+
CONFIG_OVERRIDE_DEFAULT = get_byte_data(resources.terraform_plan_config_override_default)
22+
CONFIG_OVERRIDE_CUSTOM = get_byte_data(resources.terraform_plan_config_override_custom)
1723

1824
SAMPLE_VALID_TFPLAN = get_byte_data(resources.tfplan_elb)
1925
SAMPLE_VALID_TFGRAPH = get_byte_data(resources.tfgraph_elb)
@@ -24,6 +30,12 @@
2430
TFPLAN_OFFICIAL = get_byte_data(resources.tfplan_official)
2531
TFGRAPH_OFFICIAL = get_byte_data(resources.tfgraph_official)
2632

33+
TFPLAN_AWS_COMPLETE = get_byte_data(resources.tfplan_aws_complete)
34+
TFGRAPH_AWS_COMPLETE = get_byte_data(resources.tfgraph_aws_complete)
35+
36+
TFPLAN_BASE = get_byte_data(resources.tfplan_base)
37+
TFGRAPH_BASE = get_byte_data(resources.tfgraph_base)
38+
2739
SAMPLE_ID = 'id'
2840
SAMPLE_NAME = 'name'
2941
EXCLUDED_REGEX = r"root\[\'dataflows'\]\[.+?\]\['id'\]"
@@ -57,7 +69,7 @@ def test_tfplan_tfgraph_examples(tfplan: bytes, tfgraph: bytes, expected: str):
5769
param([SAMPLE_VALID_TFPLAN], id='one source'),
5870
param([SAMPLE_VALID_TFPLAN] * random.randint(3, 10), id='more than two sources')
5971
])
60-
def test_wrong_number_of_parameters(sources: List[bytes]):
72+
def test_wrong_number_of_parameters(sources: list[bytes]):
6173
# GIVEN a wrong number of sources
6274

6375
# WHEN TFPlanProcessor::process is invoked
@@ -75,7 +87,7 @@ def test_wrong_number_of_parameters(sources: List[bytes]):
7587
param([SAMPLE_VALID_TFPLAN, create_artificial_file(MIN_FILE_SIZE - 1)], id='tfgraph too small'),
7688
param([SAMPLE_VALID_TFPLAN, create_artificial_file(MAX_TFGRAPH_FILE_SIZE + 1)], id='tfgraph too big')
7789
])
78-
def test_invalid_size(sources: List[bytes]):
90+
def test_invalid_size(sources: list[bytes]):
7991
# GIVEN a tfplan or tfgraph with an invalid size
8092

8193
# WHEN TFPlanProcessor::process is invoked
@@ -87,6 +99,30 @@ def test_invalid_size(sources: List[bytes]):
8799
assert error.value.title == 'Terraform Plan file is not valid'
88100
assert error.value.message == 'Provided iac_file is not valid. Invalid size'
89101

102+
@mark.parametrize('mappings', [
103+
param([create_artificial_file(MAPPING_MIN_SIZE - 1), DEFAULT_MAPPING_FILE], id='mapping file too small'),
104+
param([create_artificial_file(MAPPING_MAX_SIZE + 1), DEFAULT_MAPPING_FILE], id='mapping file too big'),
105+
param([DEFAULT_MAPPING_FILE, create_artificial_file(MAPPING_MIN_SIZE - 1)], id='custom mapping file too small'),
106+
param([DEFAULT_MAPPING_FILE, create_artificial_file(MAPPING_MAX_SIZE + 1)], id='custom mapping file too big')
107+
])
108+
def test_invalid_mapping_size(mappings: list[bytes]):
109+
# GIVEN a valid tfplan and tfgraph
110+
tfplan = get_byte_data(resources.tfplan_official)
111+
tfgraph = get_byte_data(resources.tfgraph_official)
112+
113+
# AND a mapping file with an invalid size ('mappings' arg)
114+
115+
# WHEN TFPlanProcessor::process is invoked
116+
# THEN a MappingFileNotValidError is raised
117+
with pytest.raises(MappingFileNotValidError) as error:
118+
TFPlanProcessor(SAMPLE_ID, SAMPLE_NAME, [tfplan, tfgraph], mappings).process()
119+
120+
# AND the error details are correct
121+
assert ErrorCode.MAPPING_FILE_NOT_VALID == error.value.error_code
122+
assert 'Mapping files are not valid' == error.value.title
123+
assert 'Mapping files are not valid. Invalid size' == error.value.detail
124+
assert 'Mapping files are not valid. Invalid size' == error.value.message
125+
90126
def test_two_tfplan():
91127
# GIVEN two valid TFPLANs
92128
sources = [SAMPLE_VALID_TFPLAN, SAMPLE_VALID_TFPLAN]
@@ -105,7 +141,7 @@ def test_two_tfplan():
105141
param([SAMPLE_VALID_TFPLAN, SAMPLE_INVALID_TFGRAPH], id='invalid tfgraph'),
106142
param([SAMPLE_INVALID_TFPLAN, SAMPLE_INVALID_TFGRAPH], id='both invalid')
107143
])
108-
def test_invalid_sources(sources: List[bytes]):
144+
def test_invalid_sources(sources: list[bytes]):
109145
# GIVEN some invalid tfplan
110146

111147
# WHEN TFPlanProcessor::process is invoked
@@ -150,3 +186,65 @@ def test_singleton_grouped_by_category():
150186
assert components[1].id == 'aws_cloudwatch_log_group.click_logger_firehose_delivery_stream_log_group'
151187
assert components[1].name == 'CloudWatch'
152188
assert components[1].type == 'cloudwatch'
189+
190+
def test_aws_complete_sample():
191+
# GIVEN a valid tfplan and tfgraph
192+
tfplan = TFPLAN_AWS_COMPLETE
193+
tfgraph = TFGRAPH_AWS_COMPLETE
194+
195+
# AND a mapping file with an invalid size ('mappings' arg)
196+
mapping_file = SECONDARY_DEFAULT_MAPPING_FILE
197+
198+
# WHEN TFPlanProcessor::process is invoked
199+
otm = TFPlanProcessor(SAMPLE_ID, SAMPLE_NAME, [tfplan, tfgraph], [mapping_file]).process()
200+
201+
# AND the details are correct
202+
assert len(otm.representations) == 1
203+
assert len(otm.trustzones) == 2
204+
assert len(otm.components) == 15
205+
assert len(otm.dataflows) == 8
206+
207+
def test_configuration_trustzone_no_client():
208+
# GIVEN two valid TFPLANs
209+
tfplan = TFPLAN_BASE
210+
tfgraph = TFGRAPH_BASE
211+
212+
# WHEN TFPlanProcessor::process is invoked
213+
# THEN a MappingFileNotValidError exception is raised
214+
with pytest.raises(MappingFileNotValidError) as error:
215+
TFPlanProcessor(SAMPLE_ID, SAMPLE_NAME, [tfplan, tfgraph], [CONFIG_TRUSTZONE_MAPPING_FILE]).process()
216+
217+
# AND the message says that no multiple tfplan files can be processed at the same time
218+
assert str(error.value.title) == 'Mapping files are not valid'
219+
assert str(error.value.detail) == 'Mapping file does not comply with the schema'
220+
assert str(error.value.message) == "'client' is a required property"
221+
222+
def test_configuration_client_no_trustzone():
223+
# GIVEN two valid TFPLANs
224+
tfplan = TFPLAN_BASE
225+
tfgraph = TFGRAPH_BASE
226+
227+
# WHEN TFPlanProcessor::process is invoked
228+
# THEN a MappingFileNotValidError exception is raised
229+
with pytest.raises(MappingFileNotValidError) as error:
230+
TFPlanProcessor(SAMPLE_ID, SAMPLE_NAME, [tfplan, tfgraph], [CONFIG_CLIENT_MAPPING_FILE]).process()
231+
232+
# AND the message says that no multiple tfplan files can be processed at the same time
233+
assert str(error.value.title) == 'Mapping files are not valid'
234+
assert str(error.value.detail) == 'Mapping file does not comply with the schema'
235+
assert str(error.value.message) == "'trustzone' is a required property"
236+
237+
def test_configuration_mapping_override():
238+
# GIVEN two valid TFPLANs
239+
tfplan = TFPLAN_BASE
240+
tfgraph = TFGRAPH_BASE
241+
242+
# WHEN TFPlanProcessor::process is invoked
243+
otm = TFPlanProcessor(SAMPLE_ID, SAMPLE_NAME, [tfplan, tfgraph],
244+
[CONFIG_OVERRIDE_DEFAULT, CONFIG_OVERRIDE_CUSTOM]).process()
245+
246+
# AND the details are correct
247+
assert len(otm.representations) == 1
248+
assert len(otm.trustzones) == 2
249+
assert len(otm.components) == 15
250+
assert len(otm.dataflows) == 13
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
trustzones:
2+
- type: b61d6911-338d-46a8-9f39-8dcd24abfe91
3+
name: Public Cloud
4+
risk:
5+
trust_rating: 10
6+
$default: true
7+
8+
- type: f0ba7722-39b6-4c81-8290-a30a248bb8d9
9+
name: Internet
10+
risk:
11+
trust_rating: 1
12+
13+
components:
14+
15+
- label: aws_acm_certificate
16+
type: CD-ACM
17+
$singleton: true
18+
19+
- label: aws_cloudwatch_metric_alarm
20+
type: cloudwatch
21+
$singleton: true
22+
23+
- label: aws_dynamodb_table
24+
type: dynamodb
25+
26+
- label: aws_vpc
27+
type: vpc
28+
29+
- label: aws_instance
30+
type: ec2
31+
32+
- label: aws_subnet
33+
type: empty-component
34+
35+
- label: aws_vpc_endpoint
36+
type: empty-component
37+
38+
- label: aws_internet_gateway
39+
type: empty-component
40+
41+
- label: aws_ecs_service
42+
type: elastic-container-service
43+
44+
- label: aws_ecs_task_definition
45+
type: docker-container
46+
47+
- label: ["aws_lb", "aws_elb", "aws_alb"]
48+
type: load-balancer
49+
50+
- label: aws_kms_key
51+
type: kms
52+
$singleton: true
53+
54+
- label: aws_lambda_function
55+
type: aws-lambda-function
56+
57+
- label: aws_cloudwatch_log_group
58+
type: cloudwatch
59+
$singleton: true
60+
61+
- label: ["aws_db_instance", "aws_rds_cluster"]
62+
type: rds
63+
64+
- label: aws_route53_zone
65+
type: route-53
66+
67+
- label: aws_autoscaling_group
68+
type: CD-EC2-AUTO-SCALING
69+
70+
- label: cloudflare_record
71+
type: empty-component
72+
73+
- label: aws_s3_bucket
74+
type: s3
75+
76+
- label: aws_secretsmanager_secret
77+
type: CD-SECRETS-MANAGER
78+
$singleton: true
79+
80+
- label: aws_sqs_queue
81+
type: sqs-simple-queue-service
82+
83+
- label: [ "azurerm_data_share", "azurerm_data_share_account" ]
84+
type: CD-MICROSOFT-AZURE-DATA-SHARE
85+
86+
- label: azurerm_elastic_cloud_elasticsearch
87+
type: CD-MICROSOFT-AZURE-ELASTICSEARCH
88+
89+
- label: ["azurerm_media_services_account", "azurerm_media_services_account_filter"]
90+
type: CD-MICROSOFT-AZURE-MEDIA-SERVICES
91+
92+
- label: {$regex: ^aws_ssm_\w*$}
93+
type: CD-SYSTEMS-MANAGER
94+
$singleton: true
95+
96+
- label: aws_synthetics_canary
97+
type: empty-component
98+
99+
- label: {$regex: ^aws_api_gateway_\w*$}
100+
type: api-gateway
101+
$singleton: true
102+
103+
- label: {$regex: ^aws_athena_\w*$}
104+
type: athena
105+
$singleton: true
106+
107+
- label: {$regex: ^aws_mq_\w*$}
108+
type: CD-MQ
109+
$singleton: true
110+
111+
- label: {$regex: ^aws_cloudfront_\w*$}
112+
type: cf-cloudfront
113+
$singleton: true
114+
115+
- label: aws_cloudtrail
116+
type: cloudtrail
117+
118+
- label: ["aws_cognito_user_pool", "aws_cognito_identity_pool"]
119+
type: cognito
120+
121+
- label: {$regex: ^aws_config_\w*$}
122+
type: CD-CONFIG
123+
$singleton: true
124+
125+
- label: {$regex: ^aws_ecr_\w*$}
126+
type: elastic-container-registry
127+
$singleton: true
128+
129+
- label: aws_eks_cluster
130+
type: elastic-container-kubernetes
131+
132+
- label: {$regex: ^aws_elasticache_\w*$}
133+
type: elasticache
134+
$singleton: true
135+
136+
- label: {$regex: ^aws_guardduty_\w*$}
137+
type: CD-GUARDDUTY
138+
$singleton: true
139+
140+
- label: {$regex: ^aws_inspector_\w*$}
141+
type: CD-INSPECTOR
142+
$singleton: true
143+
144+
- label: {$regex: ^aws_macie2_\w*$}
145+
type: CD-MACIE
146+
$singleton: true
147+
148+
- label: aws_networkfirewall_firewall
149+
type: CD-AWS-NETWORK-FIREWALL
150+
151+
- label: aws_redshift_cluster
152+
type: redshift
153+
154+
- label: {$regex: ^aws_ses_\w*$}
155+
type: CD-SES
156+
$singleton: true
157+
158+
- label: {$regex: ^aws_sns_\w*$}
159+
type: sns
160+
$singleton: true
161+
162+
- label: {$regex: ^aws_sfn_\w*$}
163+
type: step-functions
164+
165+
- label: {$regex: ^aws_waf_\w*$}
166+
type: CD-WAF
167+
$singleton: true
168+
169+
- label: {$regex: ^aws_kinesis_analytics_\w*$}
170+
type: kinesis-data-analytics
171+
$singleton: true
172+
173+
- label: {$regex: ^aws_kinesis_stream\w*$}
174+
type: kinesis-data-analytics
175+
$singleton: true
176+
177+
- label: {$regex: ^aws_kinesis_firehose_\w*$}
178+
type: kinesis-data-firehose
179+
$singleton: true
180+
181+
configuration:
182+
attack_surface:
183+
client: generic-client
184+
trustzone: f0ba7722-39b6-4c81-8290-a30a248bb8d9
185+
186+
# skip:
187+
# - aws_security_group
188+
# - aws_db_subnet_group
189+
# catch_all: empty-component

0 commit comments

Comments
 (0)