def test_get_change_batch(self): patch.stopall() cv = CertificateValidator(self.request, self.response) resource_record = { 'Name': '_x1.certificate-validator.com.', 'Type': 'CNAME', 'Value': '_x2.acm-validations.aws.' } actual = cv.get_change_batch( action='CREATE', resource_record=resource_record ) expected = { 'Changes': [{ 'Action': 'CREATE', 'ResourceRecordSet': { 'Name': '_x1.certificate-validator.com.', 'Type': 'CNAME', 'TTL': 300, 'ResourceRecords': [{ 'Value': '_x2.acm-validations.aws.' }] } }] } self.assertEqual(expected, actual)
def handler(event: dict, context: object) -> dict: """ Handle AWS Lambda function event. :param event: event data :type event: dict :param context: runtime information of the AWS Lambda function :type context: LambdaContext object """ logger.debug('Request: {}'.format(event)) request = Request(**event) response = Response( request_id=request.request_id, stack_id=request.stack_id, logical_resource_id=request.logical_resource_id, physical_resource_id=request.physical_resource_id ) if request.resource_type == 'Custom::Certificate': certificate = Certificate(request, response) certificate.handler() logger.debug('Response: {}'.format(certificate.response.dict())) if request.resource_type == 'Custom::CertificateValidator': certificate_validator = CertificateValidator(request, response) certificate_validator.handler() logger.debug( 'Response: {}'.format(certificate_validator.response.dict()) )
def test_get_domain_validation_options(self): patch.stopall() mock_describe_certificate = patch.object( resources.ACM, 'describe_certificate' ).start() mock_describe_certificate.return_value = { 'Certificate': { 'DomainName': 'certificate-validator.com', 'DomainValidationOptions': [{ 'DomainName': 'certificate-validator.com', 'ResourceRecord': { 'Name': '_x1.certificate-validator.com.', 'Type': 'CNAME', 'Value': '_x2.acm-validations.aws.' } }] } } cv = CertificateValidator(self.request, self.response) actual = cv.get_domain_validation_options( certificate_arn='arn:aws:acm:us-east-1:123:certificate/1337' ) expected = [{ 'DomainName': 'certificate-validator.com', 'ResourceRecord': { 'Name': '_x1.certificate-validator.com.', 'Type': 'CNAME', 'Value': '_x2.acm-validations.aws.' } }] self.assertEqual(expected, actual)
def test_change_resource_record_sets_delete_success(self): self.mock_request.resource_properties = { 'CertificateArn': self.certificate_arn } cv = CertificateValidator(self.mock_request, self.mock_response) cv.change_resource_record_sets(self.certificate_arn, Action.DELETE) self.mock_get_hosted_zone_id.assert_called_with( 'certificate-validator.com' ) self.mock_get_domain_validation_options.assert_called_with( 'arn:aws:acm:us-east-1:123:certificate/1337' ) self.mock_get_change_batch.assert_called_with( 'DELETE', { 'Name': '_x1.certificate-validator.com.', 'Type': 'CNAME', 'Value': '_x2.acm-validations.aws.' } ) self.mock_change_resource_record_sets.assert_called_with( hosted_zone_id='Z23ABC4XYZL05B', change_batch={ 'Changes': { 'ResourceRecordSet': { 'Name': '_x1.certificate-validator.com.', 'Type': 'CNAME', 'TTL': 300, 'ResourceRecords': [{ 'Value': '_x2.acm-validations.aws.' }] } } } ) self.mock_response.set_status.assert_called_with(success=True)
def test_delete(self): mock_change_resource_record_sets = \ patch.object(resources.CertificateValidator, 'change_resource_record_sets').start() cv = CertificateValidator(self.request, self.mock_response) cv.delete() mock_change_resource_record_sets.assert_called_with( 'arn:aws:acm:us-east-1:123:certificate/1', Action.DELETE )
def test_change_resource_record_sets_failed_certificate_arn_is_invalid( self ): cv = CertificateValidator(self.mock_request, self.mock_response) cv.change_resource_record_sets('invalid', Action.CREATE) self.mock_response.set_status.assert_called_with(success=False) self.mock_response.set_reason.assert_called_with( reason='Certificate ARN is invalid.' )
def test_update(self): mock_change_resource_record_sets = \ patch.object(resources.CertificateValidator, 'change_resource_record_sets').start() cv = CertificateValidator(self.request, self.mock_response) cv.update() mock_change_resource_record_sets.assert_has_calls([ call('arn:aws:acm:us-east-1:123:certificate/0', Action.DELETE), call('arn:aws:acm:us-east-1:123:certificate/1', Action.UPSERT) ])
def test_create(self): mock_wait = patch.object(resources.ACM, 'wait').start() mock_change_resource_record_sets = \ patch.object(resources.CertificateValidator, 'change_resource_record_sets').start() cv = CertificateValidator(self.request, self.mock_response) cv.create() self.mock_response.set_physical_resource_id.assert_called_with('1337') mock_change_resource_record_sets.assert_called_with( 'arn:aws:acm:us-east-1:123:certificate/1', Action.UPSERT ) mock_wait.assert_called_once_with( 'arn:aws:acm:us-east-1:123:certificate/1' )
def test_get_hosted_zone_id(self): patch.stopall() mock_list_hosted_zones_by_name = patch.object( resources.Route53, 'list_hosted_zones_by_name' ).start() mock_list_hosted_zones_by_name.return_value = { 'HostedZones': [{ 'Id': '/hostedzone/Z23ABC4XYZL05B', 'Name': 'certificate-validator.com.', }] } cv = CertificateValidator(self.request, self.response) actual = cv.get_hosted_zone_id(domain_name='certificate-validator.com') expected = 'Z23ABC4XYZL05B' self.assertEqual(expected, actual)
def test_change_resource_record_sets_delete_failed_cert_not_found(self): self.mock_request.resource_properties = { 'CertificateArn': self.certificate_arn } self.mock_get_domain_validation_options.side_effect = \ exceptions.ClientError( error_response={'Error': { 'Code': 'ResourceNotFoundException', 'Message': 'Message' }}, operation_name='Operation' ) cv = CertificateValidator(self.mock_request, self.mock_response) cv.change_resource_record_sets(self.certificate_arn, Action.DELETE) self.mock_response.set_status.assert_called_with(success=True) self.mock_response.set_reason.assert_called_with( reason='Certificate not found.' )
def test_change_resource_record_sets_delete_failed(self): self.mock_request.resource_properties = { 'CertificateArn': self.certificate_arn } self.mock_get_domain_validation_options.side_effect = \ exceptions.ClientError( error_response={'Error': { 'Code': 'Code', 'Message': 'Message' }}, operation_name='Operation' ) cv = CertificateValidator(self.mock_request, self.mock_response) cv.change_resource_record_sets(self.certificate_arn, Action.DELETE) self.mock_response.set_status.assert_called_with(success=False) reason = \ 'An error occurred (Code) when calling the Operation operation: ' \ 'Message' self.mock_response.set_reason.assert_called_with(reason=reason)
def test_change_resource_record_sets_delete_failed_rrset_not_found(self): self.mock_request.resource_properties = { 'CertificateArn': self.certificate_arn } message = \ 'Tried to delete resource record set ' \ '[name=\'_x1.certificate-validator.com.\', type=\'CNAME\'] but ' \ 'it was not found' self.mock_get_domain_validation_options.side_effect = \ exceptions.ClientError( error_response={'Error': { 'Code': 'InvalidChangeBatch', 'Message': message }}, operation_name='Operation' ) cv = CertificateValidator(self.mock_request, self.mock_response) cv.change_resource_record_sets(self.certificate_arn, Action.DELETE) self.mock_response.set_status.assert_called_with(success=True) self.mock_response.set_reason.assert_called_with( reason='Resource Record Set not found.' )
def test_init(self): cv = CertificateValidator(self.request, self.response) self.assertEqual(self.request, cv.request) self.assertEqual(self.response, cv.response)