def setUp(self) -> None: self.owner = Address.from_string(f"cx{'0'*40}") db = Mock(spec=IconScoreDatabase) db.configure_mock(address=f"cx{'0'*40}") IconScoreContextUtil.get_owner = Mock(return_value=self.owner) self.governance = Governance(db)
def setup_method(self): """ Initialise Test Suite """ self.mock_template = { 'Resources': { 'Bucket': { 'Type': 'AWS::S3::Bucket', 'Properties': { 'BucketName': 'test-bucket-name' } } } } self.mock_governance = Gov()
def deploy_governed_template_handler(event, context): """ Lambda handler to handles the deployment of governed CloudFormation Templates Args: event (dict): event details from request context (dict): context of the lambda function Returns: response (dict): response built from handler """ payload = event['Payload'] env = event['Env'] cf_builder = CF_BUILDER() s3_cf = S3_CF(payload=payload) s3_cf.set_template() resource = s3_cf.get_template() if 'Description' in event: cf_builder.set_description(event['Description']) cf_builder.set_resources(resource_type='S3Bucket', resource=resource) template = cf_builder.get_template() governance = Governance() governance.set_template(template=template) governance.get_resources() governance.validate() template = governance.get_template() if s3_cf.get_bucketname()['ResponseCode'] == 200: stackname = 's3-{}'.format(s3_cf.get_bucketname()['Message']) create_cloudformation(stack=stackname, template=template, region=env['region']) response = {} response['Test'] = 'Deploy Governance Lambda Handler' response['Template'] = template response['Env'] = env return response
def validate_governed_payload_handler(event, context): """ Lambda handler to validate a payload, construct a CloudFormation template and apply governance checks Args: event (dict): event details from request context (dict): context of the lambda function Returns: response (dict): response built from handler """ payload = event['Payload'] env = event['Env'] cf_builder = CF_BUILDER() s3_cf = S3_CF(payload=payload) s3_cf.set_template() resource = s3_cf.get_template() if 'Description' in event: cf_builder.set_description(event['Description']) cf_builder.set_resources(resource_type='S3Bucket', resource=resource) template = cf_builder.get_template() governance = Governance() governance.set_template(template=template) governance.get_resources() governance.validate() template = governance.get_template() response = {} response['Test'] = 'Validation Governance Lambda Handler' response['Template'] = template response['Env'] = env return response
class TestUnitGovernance(unittest.TestCase): @patch_several(PATCHER_ARRAY_DB, PATCHER_DICT_DB, PATCHER_VAR_DB, PATCHER_NP_ARRAY_DB, PATCHER_NP_DICT_DB) def setUp(self) -> None: self.owner = Address.from_string(f"cx{'0'*40}") db = Mock(spec=IconScoreDatabase) db.configure_mock(address=f"cx{'0'*40}") IconScoreContextUtil.get_owner = Mock(return_value=self.owner) self.governance = Governance(db) @patch_several(PATCHER_VALIDATE_TEXT_PROPOSAL, PATCHER_VALIDATE_REVISION_PROPOSAL, PATCHER_VALIDATE_MALICIOUS_SCORE_PROPOSAL, PATCHER_VALIDATE_PREP_DISQUALIFICATION_PROPOSAL, PATCHER_VALIDATE_STEP_PRICE_PROPOSAL, PATCHER_VALIDATE_IREP_PROPOSAL) def test_validate_network_proposal(self): for invalid_vote_type in (6, 7, -1, 1000): tmp_value = {} self.assertFalse( self.governance._validate_network_proposal( invalid_vote_type, tmp_value)) value_of_type_0 = {"value": "text"} value_of_type_1 = {"code": hex(0), "name": "1.1.0"} value_of_type_2 = {"address": str(create_address()), "type": hex(0)} value_of_type_3 = {"address": str(create_address())} value_of_type_4 = {"value": hex(0)} value_of_type_5 = {"value": hex(0)} return_value = self.governance._validate_network_proposal( 0, value_of_type_0) assert self.governance._validate_text_proposal.called and return_value return_value = self.governance._validate_network_proposal( 1, value_of_type_1) assert self.governance._validate_revision_proposal.called and return_value return_value = self.governance._validate_network_proposal( 2, value_of_type_2) assert self.governance._validate_malicious_score_proposal.called and return_value return_value = self.governance._validate_network_proposal( 3, value_of_type_3) assert self.governance._validate_prep_disqualification_proposal.called and return_value return_value = self.governance._validate_network_proposal( 4, value_of_type_4) assert self.governance._validate_step_price_proposal.called and return_value return_value = self.governance._validate_network_proposal( 5, value_of_type_5) assert self.governance._validate_irep_proposal.called and return_value def test_validate_text_proposal(self): value_of_type_0 = {"value": "text"} assert self.governance._validate_text_proposal(value_of_type_0) def test_validate_revision_proposal(self): value_of_type_1 = {"code": hex(0), "name": "1.1.0"} assert self.governance._validate_revision_proposal(value_of_type_1) @patch('governance.governance.Address.is_contract', return_value=True) def test_validate_malicious_score_proposal(self, is_contract): value_of_type_2 = { "address": str(create_address(AddressPrefix.CONTRACT)), "type": hex(0) } assert self.governance._validate_malicious_score_proposal( value_of_type_2) def test_validate_prep_disqualification_proposal(self): main_prep = [ Prep(create_address(), 0) for _ in range(COUNT_OF_MAIN_PREPS) ] sub_prep = [ Prep(create_address(), 0) for _ in range(COUNT_OF_MAIN_PREPS, 100) ] with patch('governance.governance.get_main_prep_info', return_value=(main_prep, None)): with patch('governance.governance.get_sub_prep_info', return_value=(sub_prep, None)): value_of_type_3 = {"address": str(main_prep[0].address)} assert self.governance._validate_prep_disqualification_proposal( value_of_type_3) value_of_type_3 = {"address": str(sub_prep[0].address)} assert self.governance._validate_prep_disqualification_proposal( value_of_type_3) value_of_type_3 = {"address": str(create_address())} assert not self.governance._validate_prep_disqualification_proposal( value_of_type_3) @patch('governance.governance.Governance.get_icon_network_value', return_value=STEP_PRICE) def test_validate_step_price_proposal(self, get_icon_network_value): TestCase = namedtuple("TestCase", "step_price, result") tests = [ TestCase(STEP_PRICE + 1, True), TestCase(STEP_PRICE - 1, True), TestCase(STEP_PRICE * 125 // 100, True), TestCase(STEP_PRICE * 126 // 100, False), TestCase(STEP_PRICE * 75 // 100, True), TestCase(STEP_PRICE * 74 // 100, False), ] for test in tests: value_of_type_4 = {"value": hex(test.step_price)} assert test.result == self.governance._validate_step_price_proposal( value_of_type_4) value_of_type_4 = {"value": str(test.step_price)} assert test.result == self.governance._validate_step_price_proposal( value_of_type_4) @patch('governance.governance.Governance.validate_irep', return_value=True) def test_validate_irep_proposal(self, validate_irep): value_of_type_5 = {"value": hex(10)} assert self.governance._validate_irep_proposal(value_of_type_5)
class TestGovernance: """ Test Suite for the Governance Class """ def setup_method(self): """ Initialise Test Suite """ self.mock_template = { 'Resources': { 'Bucket': { 'Type': 'AWS::S3::Bucket', 'Properties': { 'BucketName': 'test-bucket-name' } } } } self.mock_governance = Gov() def test_template_empty_if_not_set(self): """ Test Success: Template is empty if not set """ sut = self.mock_governance.get_template() assert sut == {} def test_resources_empty_if_not_set(self): """ Test Success: Resources is empty if not set """ test_template = {} expected = {} self.mock_governance.set_template(template=test_template) sut = self.mock_governance.get_resources() assert sut == expected def test_resources_empty_if_type_not_valid(self): """ Test Failure: Resources is empty if type is not valid """ test_template = { 'Resources': { 'Bucket': { 'Type': 'AWS::IAM::Role', 'Properties': { 'RoleName': 'test-iam-role' } } } } expected = {} self.mock_governance.set_template(template=test_template) sut = self.mock_governance.get_resources() assert sut == expected def test_set_get_template(self): """ Test Success: Set and get template """ self.mock_governance.set_template(template=self.mock_template) sut = self.mock_governance.get_template() assert sut == self.mock_template def test_set_get_template_sets_resources(self): """ Test Success: Setting template sets resources correctly """ expected_resources = { 'AWS::S3::Bucket': { 'BucketName': 'test-bucket-name' } } self.mock_governance.set_template(template=self.mock_template) sut = self.mock_governance.get_resources() assert sut == expected_resources def test_validate_does_not_change_template_with_invalid_type(self): """ Test Failure: Validate does not change original template if type is invalid """ expected_template = { 'Resources': { 'Bucket': { 'Type': 'AWS::IAM::Role', 'Properties': { 'RoleName': 'test-iam-role' } } } } self.mock_governance.set_template(template=expected_template) self.mock_governance.validate() sut = self.mock_governance.get_template() assert sut == expected_template def test_validate_does_change_template_with_valid_type(self): """ Test Success: Validate changes original template if type valid """ expected_template = { 'Resources': { 'Bucket': { 'Type': 'AWS::S3::Bucket', 'Properties': { 'BucketName': 'test-bucket-name' } } } } self.mock_governance.set_template(template=self.mock_template) self.mock_governance.get_resources() self.mock_governance.validate() sut = self.mock_governance.get_template() assert sut != expected_template
class TestS3_Gov: """ Test Suite for the S3 Governance Class """ def setup_method(self): """ Initialise Test Suite """ self.mock_template = { 'Resources': { 'Bucket': { 'Type': 'AWS::S3::Bucket', 'Properties': { 'BucketName': 'test-bucket-name' } } } } self.mock_governance = Gov() def test_read_governance_rules(self): """ Test Success: Rules are set from file """ expected_type = 'AWS::S3::Bucket' self.mock_governance.set_template(template=self.mock_template) self.mock_governance.get_resources() resources = self.mock_governance.get_resources() mock_s3_gov = S3_Gov(res_type=expected_type, res_property=resources[expected_type]) rules = mock_s3_gov.get_rules() assert 'BucketEncryption' in rules assert 'VersioningConfiguration' in rules assert 'PublicAccessBlockConfiguration' in rules assert 'AccessControl' in rules def test_bucket_encryption_validates_no_encryption(self): """ Test Success: Validates no encryption and sets mandatory encryption """ test_template = deepcopy(self.mock_template) expected_mandatory = { 'ServerSideEncryptionConfiguration': [{ 'ServerSideEncryptionByDefault': { 'SSEAlgorithm': 'AES256' } }] } self.mock_governance.set_template(template=test_template) self.mock_governance.get_resources() self.mock_governance.validate() sut = test_template['Resources']['Bucket']['Properties'][ 'BucketEncryption'] assert sut == expected_mandatory assert test_template != self.mock_template def test_bucket_encryption_validates_incorrect_encryption(self): """ Test Failure: Validates incorrect encryption and sets mandatory encryption """ test_template = deepcopy(self.mock_template) properties = test_template['Resources']['Bucket']['Properties'] properties['BucketEncryption'] = { 'ServerSideEncryptionConfiguration': [{ 'ServerSideEncryptionByDefault': { 'Test': 'test' } }] } expected_mandatory = { 'ServerSideEncryptionConfiguration': [{ 'ServerSideEncryptionByDefault': { 'SSEAlgorithm': 'AES256' } }] } self.mock_governance.set_template(template=test_template) self.mock_governance.get_resources() self.mock_governance.validate() sut = test_template['Resources']['Bucket']['Properties'][ 'BucketEncryption'] assert sut == expected_mandatory def test_bucket_encryption_validates_bucket_encryption_mandatory(self): """ Test Success: Validates mandatory encryption """ test_template = deepcopy(self.mock_template) properties = test_template['Resources']['Bucket']['Properties'] properties['BucketEncryption'] = { 'ServerSideEncryptionConfiguration': [{ 'ServerSideEncryptionByDefault': { 'SSEAlgorithm': 'AES256' } }] } expected_mandatory = { 'ServerSideEncryptionConfiguration': [{ 'ServerSideEncryptionByDefault': { 'SSEAlgorithm': 'AES256' } }] } self.mock_governance.set_template(template=test_template) self.mock_governance.get_resources() self.mock_governance.validate() sut = test_template['Resources']['Bucket']['Properties'][ 'BucketEncryption'] assert sut == expected_mandatory def test_bucket_encryption_validates_bucket_encrpytion_accepted(self): """ Test Success: Validates accepted encryption """ test_template = deepcopy(self.mock_template) properties = test_template['Resources']['Bucket']['Properties'] properties['BucketEncryption'] = { 'ServerSideEncryptionConfiguration': [{ 'ServerSideEncryptionByDefault': { 'SSEAlgorithm': 'aws:kms', 'KMSMasterKeyID': '13056591-9cca-457d-84d0-d262c4c370f0' } }] } expected_accepted = { 'ServerSideEncryptionConfiguration': [{ 'ServerSideEncryptionByDefault': { 'SSEAlgorithm': 'aws:kms', 'KMSMasterKeyID': '13056591-9cca-457d-84d0-d262c4c370f0' } }] } self.mock_governance.set_template(template=test_template) self.mock_governance.get_resources() self.mock_governance.validate() sut = test_template['Resources']['Bucket']['Properties'][ 'BucketEncryption'] assert sut == expected_accepted def test_version_configuration_validates_no_versioning(self): """ Test Success: Validates no versioning and sets mandatory """ test_template = deepcopy(self.mock_template) expected_mandatory = {'Status': 'Enabled'} self.mock_governance.set_template(template=test_template) self.mock_governance.get_resources() self.mock_governance.validate() sut = test_template['Resources']['Bucket']['Properties'][ 'VersioningConfiguration'] assert sut == expected_mandatory assert test_template != self.mock_template def test_version_configuration_validates_diasabled_versioning(self): """ Test Success: Validates disabled versioning and sets mandatory """ test_template = deepcopy(self.mock_template) properties = test_template['Resources']['Bucket']['Properties'] properties['VersioningConfiguration'] = {'Status': 'Suspended'} expected_mandatory = {'Status': 'Enabled'} self.mock_governance.set_template(template=test_template) self.mock_governance.get_resources() self.mock_governance.validate() sut = test_template['Resources']['Bucket']['Properties'][ 'VersioningConfiguration'] assert sut == expected_mandatory def test_version_configuration_validates_enabled_versioning(self): """ Test Success: Validates enabled versioning and sets mandatory """ test_template = deepcopy(self.mock_template) properties = test_template['Resources']['Bucket']['Properties'] properties['VersioningConfiguration'] = {'Status': 'Enabled'} expected_mandatory = {'Status': 'Enabled'} self.mock_governance.set_template(template=test_template) self.mock_governance.get_resources() self.mock_governance.validate() sut = test_template['Resources']['Bucket']['Properties'][ 'VersioningConfiguration'] assert sut == expected_mandatory def test_public_access_validates_no_public_access_config(self): """ Test Success: Validates no public access config and sets mandatory public access """ test_template = deepcopy(self.mock_template) expected_mandatory = { 'BlockPublicAcls': True, 'BlockPublicPolicy': True, 'IgnorePublicAcls': True, 'RestrictPublicBuckets': True } self.mock_governance.set_template(template=test_template) self.mock_governance.get_resources() self.mock_governance.validate() sut = test_template['Resources']['Bucket']['Properties'][ 'PublicAccessBlockConfiguration'] assert sut == expected_mandatory assert test_template != self.mock_template def test_public_access_validates_incorrect_public_access_config(self): """ Test Success: Validates incorrect public access config and sets mandatory public access """ test_template = deepcopy(self.mock_template) properties = test_template['Resources']['Bucket']['Properties'] properties['PublicAccessBlockConfiguration'] = {'Test': 'test'} expected_mandatory = { 'BlockPublicAcls': True, 'BlockPublicPolicy': True, 'IgnorePublicAcls': True, 'RestrictPublicBuckets': True } self.mock_governance.set_template(template=test_template) self.mock_governance.get_resources() self.mock_governance.validate() sut = test_template['Resources']['Bucket']['Properties'][ 'PublicAccessBlockConfiguration'] assert sut == expected_mandatory def test_public_access_validates_mandatory_public_access_config(self): """ Test Success: Validates mandatory public access config """ test_template = deepcopy(self.mock_template) properties = test_template['Resources']['Bucket']['Properties'] properties['PublicAccessBlockConfiguration'] = { 'BlockPublicAcls': True, 'BlockPublicPolicy': True, 'IgnorePublicAcls': True, 'RestrictPublicBuckets': True } expected_mandatory = { 'BlockPublicAcls': True, 'BlockPublicPolicy': True, 'IgnorePublicAcls': True, 'RestrictPublicBuckets': True } self.mock_governance.set_template(template=test_template) self.mock_governance.get_resources() self.mock_governance.validate() sut = test_template['Resources']['Bucket']['Properties'][ 'PublicAccessBlockConfiguration'] assert sut == expected_mandatory def test_public_access_validates_accepted_public_access_config(self): """ Test Success: Validates accepted public access config """ test_template = deepcopy(self.mock_template) properties = test_template['Resources']['Bucket']['Properties'] properties['PublicAccessBlockConfiguration'] = { 'BlockPublicAcls': True, 'BlockPublicPolicy': False, 'IgnorePublicAcls': True, 'RestrictPublicBuckets': False } expected_accepted = { 'BlockPublicAcls': True, 'BlockPublicPolicy': False, 'IgnorePublicAcls': True, 'RestrictPublicBuckets': False } self.mock_governance.set_template(template=test_template) self.mock_governance.get_resources() self.mock_governance.validate() sut = test_template['Resources']['Bucket']['Properties'][ 'PublicAccessBlockConfiguration'] assert sut == expected_accepted def test_access_control_validates_no_access_control(self): """ Test Success: Validates no access control and sets mandatory """ test_template = deepcopy(self.mock_template) expected_mandatory = 'BucketOwnerFullControl' self.mock_governance.set_template(template=test_template) self.mock_governance.get_resources() self.mock_governance.validate() sut = test_template['Resources']['Bucket']['Properties'][ 'AccessControl'] assert sut == expected_mandatory assert test_template != self.mock_template def test_access_control_validates_incorrect_access_control(self): """ Test Success: Validates incorrect access control and sets mandatory """ test_template = deepcopy(self.mock_template) properties = test_template['Resources']['Bucket']['Properties'] properties['AccessControl'] = 'test' expected_mandatory = 'BucketOwnerFullControl' self.mock_governance.set_template(template=test_template) self.mock_governance.get_resources() self.mock_governance.validate() sut = test_template['Resources']['Bucket']['Properties'][ 'AccessControl'] assert sut == expected_mandatory def test_access_control_validates_mandatory_access_control(self): """ Test Success: Validates mandatory access control """ test_template = deepcopy(self.mock_template) properties = test_template['Resources']['Bucket']['Properties'] properties['AccessControl'] = ' BucketOwnerFullControl' expected_mandatory = 'BucketOwnerFullControl' self.mock_governance.set_template(template=test_template) self.mock_governance.get_resources() self.mock_governance.validate() sut = test_template['Resources']['Bucket']['Properties'][ 'AccessControl'] assert sut == expected_mandatory def test_access_control_validates_accepted_access_control(self): """ Test Success: Validates accepted access control """ test_template = deepcopy(self.mock_template) properties = test_template['Resources']['Bucket']['Properties'] properties['AccessControl'] = 'Private' expected_accepted = 'Private' self.mock_governance.set_template(template=test_template) self.mock_governance.get_resources() self.mock_governance.validate() sut = test_template['Resources']['Bucket']['Properties'][ 'AccessControl'] assert sut == expected_accepted