22
33from sl_util .sl_util .file_utils import get_byte_data
44from slp_base .slp_base .errors import OTMBuildingError , MappingFileNotValidError , IacFileNotValidError , \
5- LoadingIacFileError
5+ LoadingIacFileError , ErrorCode
6+ from slp_base .slp_base .mapping import MAX_SIZE as MAPPING_MAX_SIZE , MIN_SIZE as MAPPING_MIN_SIZE
67from slp_base .tests .util .otm import validate_and_compare_otm , validate_and_compare
78from slp_cft import CloudformationProcessor
89from slp_cft .tests .resources import test_resource_paths
910from slp_cft .tests .resources .test_resource_paths import expected_orphan_component_is_not_mapped , \
1011 cft_components_with_trustzones_of_same_type_otm , cloudformation_minimal_content_otm
1112from slp_cft .tests .utility import excluded_regex
13+ from sl_util .tests .util .file_utils import generate_temporary_file
14+ from slp_cft .slp_cft .validate .cft_validator import MAX_SIZE as FILE_MAX_SIZE , MIN_SIZE as FILE_MIN_SIZE
1215
1316SAMPLE_ID = 'id'
1417SAMPLE_NAME = 'name'
1720SAMPLE_SINGLE_VALID_CFT_FILE = test_resource_paths .cloudformation_single_file
1821SAMPLE_VALID_MAPPING_FILE_IR = test_resource_paths .cloudformation_mapping_iriusrisk
1922SAMPLE_MAPPING_FILE_WITHOUT_REF = test_resource_paths .cloudformation_mapping_without_ref
23+ SAMPLE_DEFAULT_OLD_MAPPING = test_resource_paths .cloudformation_old_default_mapping
24+ SAMPLE_DEFAULT_NEW_MAPPING = test_resource_paths .cloudformation_new_default_mapping
25+ SAMPLE_MAPPING_WITHOUT_TRUSTZONE_TYPE = test_resource_paths .cloudformation_mapping_valid_without_trustzone_type
26+ SAMPLE_CLOUDFORMATION_MAPPING_ALL_FUNCTIONS = test_resource_paths .cloudformation_mapping_all_functions
2027SAMPLE_NETWORKS_CFT_FILE = test_resource_paths .cloudformation_networks_file
2128SAMPLE_RESOURCES_CFT_FILE = test_resource_paths .cloudformation_resources_file
29+ SAMPLE_RESOURCES_INVALID_CFT_FILE = test_resource_paths .cloudformation_resources_invalid
30+ SAMPLE_REACT_CORS_SPA_STACK = test_resource_paths .cloudformation_react_cors_spa_stack
31+ SAMPLE_CLOUDFORMATION_ALL_FUNCTIONS = test_resource_paths .cloudformation_all_functions
32+ SAMPLE_CLOUDFORMATION_TEST = test_resource_paths .cloudformation_test
2233SAMPLE_REF_DEFAULT_JSON = test_resource_paths .cloudformation_with_ref_function_and_default_property_json
2334SAMPLE_REF_DEFAULT_YAML = test_resource_paths .cloudformation_with_ref_function_and_default_property_yaml
2435SAMPLE_REF_WITHOUT_DEFAULT_JSON = test_resource_paths .cloudformation_with_ref_function_and_without_default_property_json
@@ -486,7 +497,7 @@ def test_invalid_cloudformation_file(self, cloudformation_file):
486497 mapping_file = [get_byte_data (SAMPLE_VALID_MAPPING_FILE )]
487498
488499 # WHEN creating OTM project from IaC file
489- # THEN raises OTMBuildingError
500+ # THEN raises IacFileNotValidError
490501 with pytest .raises (IacFileNotValidError ):
491502 CloudformationProcessor (SAMPLE_ID , SAMPLE_NAME , cloudformation_file , mapping_file ).process ()
492503
@@ -522,7 +533,7 @@ def test_run_empty_multiple_iac_files(self):
522533 # GIVEN a request without any iac_file key
523534 mapping_file = get_byte_data (SAMPLE_VALID_MAPPING_FILE_IR )
524535 # WHEN the method CloudformationProcessor::process is invoked
525- # THEN an RequestValidationError is raised
536+ # THEN an LoadingIacFileError is raised
526537 with pytest .raises (LoadingIacFileError ):
527538 CloudformationProcessor ('multiple-files' , 'multiple-files' , [], mapping_file ).process ()
528539
@@ -541,22 +552,6 @@ def test_security_group_configuration(self, source):
541552 assert len (otm .components ) == 1
542553 assert otm .components [0 ].parent == 'f0ba7722-39b6-4c81-8290-a30a248bb8d9'
543554
544- def test_multiple_stack_plus_s3_ec2 (self ):
545- # GIVEN the file with multiple Subnet AWS::EC2::Instance different configurations
546- cloudformation_file = get_byte_data (test_resource_paths .multiple_stack_plus_s3_ec2 )
547- # AND a valid iac mappings file
548- mapping_file = [get_byte_data (SAMPLE_VALID_MAPPING_FILE )]
549-
550- # WHEN processing
551- otm = CloudformationProcessor (SAMPLE_ID , SAMPLE_NAME , [cloudformation_file ], mapping_file ).process ()
552-
553- assert len (otm .components ) == 9
554- publicSubnet1Id = [component for component in otm .components if component .name == 'PublicSubnet1' ][0 ].id
555- assert publicSubnet1Id
556- ec2WithWrongParent = [component for component in otm .components if
557- component .type == 'ec2' and component .parent != publicSubnet1Id ]
558- assert len (ec2WithWrongParent ) == 0
559-
560555 def test_parsing_cft_json_file_with_ref (self ):
561556 # GIVEN a cloudformation JSON file
562557 cloudformation_file = get_byte_data (SAMPLE_REF_DEFAULT_JSON )
@@ -687,3 +682,130 @@ def test_components_with_trustzones_of_same_type(self):
687682 # THEN the result should be the expected
688683 result , expected = validate_and_compare (otm , cft_components_with_trustzones_of_same_type_otm , None )
689684 assert result == expected
685+
686+ def test_multiple_stack_plus_s3_ec2 (self ):
687+ # GIVEN the file with multiple Subnet AWS::EC2::Instance different configurations
688+ cloudformation_file = get_byte_data (test_resource_paths .multiple_stack_plus_s3_ec2 )
689+ # AND a valid iac mappings file
690+ mapping_file = get_byte_data (SAMPLE_VALID_MAPPING_FILE )
691+
692+ # WHEN processing
693+ otm = CloudformationProcessor (SAMPLE_ID , SAMPLE_NAME , [cloudformation_file ], [mapping_file ]).process ()
694+
695+ assert len (otm .components ) == 9
696+ publicSubnet1Id = [component for component in otm .components if component .name == 'PublicSubnet1' ][0 ].id
697+ assert publicSubnet1Id
698+ ec2WithWrongParent = [component for component in otm .components if
699+ component .type == 'ec2' and component .parent != publicSubnet1Id ]
700+ assert len (ec2WithWrongParent ) == 0
701+
702+ def test_improve_parsing_problems_built_in_functions (self ):
703+ # GIVEN a cloudformation file with built-in functions
704+ cloudformation_file = get_byte_data (SAMPLE_REACT_CORS_SPA_STACK )
705+ # AND a valid iac mappings file
706+ mapping_file = get_byte_data (SAMPLE_DEFAULT_OLD_MAPPING )
707+
708+ # WHEN processing
709+ otm = CloudformationProcessor (SAMPLE_ID , SAMPLE_NAME , [cloudformation_file ], [mapping_file ]).process ()
710+
711+ assert len (otm .trustzones ) == 1
712+ assert len (otm .dataflows ) == 1
713+ assert len (otm .components ) == 4
714+
715+ def test_checking_jmespath_functions (self ):
716+ # GIVEN a cloudformation file with all JMESPath functions
717+ cloudformation_file = get_byte_data (SAMPLE_CLOUDFORMATION_ALL_FUNCTIONS )
718+ # AND a valid iac mappings file
719+ mapping_file = get_byte_data (SAMPLE_CLOUDFORMATION_MAPPING_ALL_FUNCTIONS )
720+
721+ # WHEN processing
722+ otm = CloudformationProcessor (SAMPLE_ID , SAMPLE_NAME , [cloudformation_file ], [mapping_file ]).process ()
723+
724+ assert len (otm .trustzones ) == 1
725+ assert len (otm .dataflows ) == 0
726+ assert len (otm .components ) == 5
727+
728+ def test_not_present_parents (self ):
729+ # GIVEN a cloudformation file with all JMESPath functions
730+ cloudformation_file = get_byte_data (SAMPLE_CLOUDFORMATION_TEST )
731+ # AND a valid iac mappings file
732+ mapping_file = get_byte_data (SAMPLE_DEFAULT_NEW_MAPPING )
733+
734+ # WHEN processing
735+ otm = CloudformationProcessor (SAMPLE_ID , SAMPLE_NAME , [cloudformation_file ], [mapping_file ]).process ()
736+
737+ assert len (otm .trustzones ) == 1
738+ assert len (otm .dataflows ) == 0
739+ assert len (otm .components ) == 4
740+
741+ def test_invalid_resources_mapping_file (self ):
742+ # GIVEN a valid CFT file with altsource resources
743+ cloudformation_file = get_byte_data (SAMPLE_VALID_CFT_FILE )
744+
745+ # AND a invalid format CFT mapping file
746+ mapping_file = get_byte_data (SAMPLE_RESOURCES_INVALID_CFT_FILE )
747+
748+ # WHEN the CFT file is processed
749+ # THEN an MappingFileNotValidError is raised
750+ with pytest .raises (MappingFileNotValidError ) as error :
751+ CloudformationProcessor (SAMPLE_ID , SAMPLE_NAME , [cloudformation_file ], [mapping_file ]).process ()
752+
753+ # AND the error details are correct
754+ assert ErrorCode .MAPPING_FILE_NOT_VALID == error .value .error_code
755+ assert 'Mapping files are not valid' == error .value .title
756+ assert 'Mapping file does not comply with the schema' == error .value .detail
757+ assert "'trustzones' is a required property" == error .value .message
758+
759+ @pytest .mark .parametrize ('cft_file_size' , [FILE_MAX_SIZE + 1 , FILE_MIN_SIZE - 1 ])
760+ def test_min_max_cloudformation_file_sizes (self , cft_file_size ):
761+ # GIVEN a max file size limit and a valid CFT file
762+ max_file_size_allowed_in_bytes = 1024 * 1024
763+ cloudformation_file = generate_temporary_file (cft_file_size , "test_max_size.txt" )
764+
765+ # AND a valid CFT mapping file
766+ mapping_file = get_byte_data (SAMPLE_VALID_MAPPING_FILE )
767+
768+ # WHEN the CFT file is processed
769+ # THEN an IacFileNotValidError is raised
770+ with pytest .raises (IacFileNotValidError ) as error :
771+ CloudformationProcessor (SAMPLE_ID , SAMPLE_NAME , [cloudformation_file ], [mapping_file ]).process ()
772+
773+ # AND the error details are correct
774+ assert ErrorCode .IAC_NOT_VALID == error .value .error_code
775+ assert 'CloudFormation file is not valid' == error .value .title
776+ assert 'Provided iac_file is not valid. Invalid size' == error .value .detail
777+ assert 'Provided iac_file is not valid. Invalid size' == error .value .message
778+
779+ @pytest .mark .parametrize ('mapping_file_size' , [MAPPING_MAX_SIZE + 1 , MAPPING_MIN_SIZE - 1 ])
780+ def test_min_max_mapping_file_sizes (self , mapping_file_size ):
781+ # GIVEN a valid CFT file with altsource resources
782+ cloudformation_file = get_byte_data (SAMPLE_VALID_CFT_FILE )
783+
784+ # AND a invalid size CFT mapping file
785+ mapping_file = generate_temporary_file (mapping_file_size , "test_mapping_sizes.txt" )
786+
787+ # WHEN the CFT file is processed
788+ # THEN an MappingFileNotValidError is raised
789+ with pytest .raises (MappingFileNotValidError ) as error :
790+ CloudformationProcessor (SAMPLE_ID , SAMPLE_NAME , [cloudformation_file ], [mapping_file ]).process ()
791+
792+ # AND the error details are correct
793+ assert ErrorCode .MAPPING_FILE_NOT_VALID == error .value .error_code
794+ assert 'Mapping files are not valid' == error .value .title
795+ assert 'Mapping files are not valid. Invalid size' == error .value .detail
796+ assert 'Mapping files are not valid. Invalid size' == error .value .message
797+
798+ def test_mapping_trustzone_no_type (self ):
799+ # GIVEN a valid CFT file with some resources
800+ cloudformation_file = get_byte_data (test_resource_paths .cloudformation_for_security_group_tests_json )
801+
802+ # AND a valid CFT mapping file
803+ mapping_file = get_byte_data (SAMPLE_MAPPING_WITHOUT_TRUSTZONE_TYPE )
804+
805+ # WHEN the CFT file is processed
806+ otm = CloudformationProcessor (SAMPLE_ID , SAMPLE_NAME , [cloudformation_file ], [mapping_file ]).process ()
807+
808+ # THEN the number of TZs, components and dataflows are right
809+ assert len (otm .trustzones ) == 2
810+ assert len (otm .components ) == 22
811+ assert len (otm .dataflows ) == 22
0 commit comments