Esempio n. 1
0
    def test_document():
        """Verify correct deployment and use of document."""

        ssm_doc = ssm_testing.SSMTester(ssm_client=ssm_client,
                                        doc_filename=os.path.join(
                                            DOC_DIR, 'Documents',
                                            'aws-DeleteCloudFormation.json'),
                                        doc_name=SSM_DOC_NAME,
                                        doc_type='Automation')

        test_cf_stack = ssm_testing.CFNTester(
            cfn_client=cfn_client,
            template_filename=os.path.join(DOC_DIR, 'Tests',
                                           'CloudFormationTemplates',
                                           'TwoInstances.yml'),
            stack_name=INSTANCE_CFN_STACK_NAME)

        automation_role = ssm_doc.get_automation_role(sts_client, iam_client,
                                                      SERVICE_ROLE_NAME)

        LOGGER.info('Starting instances for testing')
        stack = test_cf_stack.create_stack([{
            'ParameterKey': 'AMI',
            'ParameterValue': AMI_ID
        }, {
            'ParameterKey': 'INSTANCETYPE',
            'ParameterValue': INSTANCE_TYPE
        }])

        try:
            LOGGER.info('Creating automation document')
            assert ssm_doc.create_document() == 'Active', ('Document not '
                                                           'created '
                                                           'successfully')

            execution = ssm_doc.execute_automation(
                params={
                    'StackNameOrId': [INSTANCE_CFN_STACK_NAME],
                    'AutomationAssumeRole': [automation_role]
                })

            LOGGER.info(
                'Verifying automation executions have concluded successfully')

            assert ssm_doc.automation_execution_status(
                ssm_client,
                execution) == 'Success', 'Stack not deleted correctly'

            LOGGER.info('Verifying stack is deleted')
            # deleted stacks require the Stack ID, not the name, as the param to describe_stacks
            stack_desc = cfn_client.describe_stacks(StackName=stack['StackId'])
            stack_status = stack_desc['Stacks'][0]['StackStatus']
            assert stack_status == 'DELETE_COMPLETE', \
                'Stack deletion failed with status: ' + stack_status

        finally:
            ssm_doc.destroy()
    def test_update_document(self):
        cfn_client = boto3.client('cloudformation', region_name=REGION)
        ssm_client = boto3.client('ssm', region_name=REGION)

        ssm_doc = ssm_testing.SSMTester(ssm_client=ssm_client,
                                        doc_filename=os.path.join(
                                            DOC_DIR,
                                            'Documents/aws-DeleteImage.json'),
                                        doc_name=SSM_DOC_NAME,
                                        doc_type='Automation')

        test_cf_stack = ssm_testing.CFNTester(
            cfn_client=cfn_client,
            template_filename=os.path.abspath(
                os.path.join(
                    DOC_DIR,
                    "Tests/CloudFormationTemplates/TestTemplate.yml")),
            stack_name=TEST_CFN_STACK_NAME)

        LOGGER.info('Creating Test Stack')
        LOGGER.info('AMI:' + LINUX_AMI_ID)
        LOGGER.info('Instance Type:' + LINUX_INSTANCE_TYPE)
        test_cf_stack.create_stack([{
            'ParameterKey': 'AMI',
            'ParameterValue': LINUX_AMI_ID
        }, {
            'ParameterKey': 'INSTANCETYPE',
            'ParameterValue': LINUX_INSTANCE_TYPE
        }, {
            'ParameterKey':
            'UserARN',
            'ParameterValue':
            sts_client.get_caller_identity().get('Arn')
        }])
        LOGGER.info('Test Stack has been created')

        # Verify role exists
        role_arn = test_cf_stack.stack_outputs['AutomationAssumeRoleARN']
        verify_role_created(role_arn)

        # Create Amazon Machine Image (AMI) of the Amazon EC2 Instance
        instance_id = test_cf_stack.stack_outputs['InstanceId']
        imageName = instance_id
        ec2client = boto3.client('ec2')
        ec2_resource = boto3.resource('ec2')

        instance = ec2_resource.Instance(instance_id)

        image = instance.create_image(Name=imageName)

        # Test Amazon Machine Image (AMI) and associated Snapshot exist
        describeImage = ec2client.describe_images(
            Filters=[{
                'Name': 'name',
                'Values': [imageName],
            }])
        ImageId = describeImage['Images'][0]['ImageId']

        waiter = ec2client.get_waiter('image_available')
        waiter.wait(ImageIds=[ImageId])

        imageData = ec2_resource.Image(ImageId)
        SnapshotId = imageData.block_device_mappings[0]['Ebs']['SnapshotId']

        waiter = ec2client.get_waiter('snapshot_completed')
        waiter.wait(SnapshotIds=[SnapshotId])

        time.sleep(60)

        try:
            LOGGER.info("Creating automation document")
            self.assertEqual(ssm_doc.create_document(), 'Active')

            instance_id = test_cf_stack.stack_outputs['InstanceId']

            execution = ssm_doc.execute_automation(params={
                'ImageId': [ImageId],
                'AutomationAssumeRole': [role_arn]
            })
            self.assertEqual(
                ssm_doc.automation_execution_status(ssm_client, execution,
                                                    False), 'Success')

            LOGGER.info('Delete Amazon Machine Image has been initiated')

            ec2_resource = boto3.resource('ec2')
            ec2client = boto3.client('ec2')
            instance = ec2_resource.Instance(instance_id)

            # Test Amazon Machine Image exist
            image_response = ec2client.describe_images(Filters=[
                {
                    'Name': 'image-id',
                    'Values': [
                        ImageId,
                    ]
                },
            ])

            images = image_response['Images']
            self.assertEqual(len(images), 0)

            # Test Amazon Machine Snapshot associated to Amazon Machine Image exist
            snapshot_response = ec2client.describe_snapshots(
                Filters=[{
                    'Name': 'snapshot-id',
                    'Values': [SnapshotId]
                }])
        finally:
            try:
                ssm_doc.destroy()
            except Exception:
                pass

            test_cf_stack.delete_stack()
    def test_update_document(self):
        cfn_client = boto3.client('cloudformation', region_name=REGION)
        ssm_client = boto3.client('ssm', region_name=REGION)

        ssm_doc = ssm_testing.SSMTester(
            ssm_client=ssm_client,
            doc_filename=os.path.join(DOC_DIR, 'Output/aws-StopRDSInstance.json'),
            doc_name=SSM_DOC_NAME,
            doc_type='Automation'
        )

        test_cf_stack = ssm_testing.CFNTester(
            cfn_client=cfn_client,
            template_filename=os.path.abspath(os.path.join(
                DOC_DIR,
                "Tests/CloudFormationTemplates/TestTemplate.yml")),
            stack_name=TEST_CFN_STACK_NAME
        )

        LOGGER.info('Creating Test Stack')
        test_cf_stack.create_stack([
            {
                'ParameterKey': 'UserARN',
                'ParameterValue': sts_client.get_caller_identity().get('Arn')
            }
        ])
        LOGGER.info('Test Stack has been created')

        # Verify role exists
        role_arn = test_cf_stack.stack_outputs['AutomationAssumeRoleARN']
        verify_role_created(role_arn)

        LOGGER.info("Creating automation document")
        self.assertEqual(ssm_doc.create_document(), 'Active')

        db_instance_id = test_cf_stack.stack_outputs['DBInstanceId']

        try:
            execution = ssm_doc.execute_automation(
                params={'DBInstanceIdentifier': [db_instance_id],
                        'DBSnapshotIdentifier': ['{db-instance-id}-stopped'],
                        'OverwriteExistingSnapshot': ["True"],
                        'StoppedInstanceTags': [
                            'Key=StopExecutionId,Value={execution-id};'
                            'Key=StopSnapshot,Value={db-snapshot-id};'
                            'Key=StopDateTime,Value={iso-date};'
                            'Key=StopDate,Value={iso-date};'
                            'Key=StopTime,Value={iso-time}'],
                        'SnapshotTags': [
                            'Key=StopExecutionId,Value={execution-id};'
                            'Key=StopDBInstanceId,Value={db-instance-id};'
                            'Key=StopDateTime,Value={iso-date};'
                            'Key=StopDate,Value={iso-date};'
                            'Key=StopTime,Value={iso-time}']
                        })

            self.assertEqual(ssm_doc.automation_execution_status(ssm_client, execution, False), 'Success')

            self.assertTrue(DocumentTest.verify_database_stopped(db_instance_id))
            LOGGER.info("Instance {} was stopped".format(db_instance_id))

            snapshot_id = "{}-stopped".format(db_instance_id)
            self.assertTrue(DocumentTest.verify_snapshot_exists(snapshot_id))

            account = sts_client.get_caller_identity().get("Account")
            db_arn = "arn:aws:rds:{}:{}:db:{}".format(REGION, account, db_instance_id)

            self.assertTrue(self.verify_tags_are_set(db_arn, [
                "StopExecutionId",
                "StopSnapshot",
                "StopDateTime",
                "StopDate",
                "StopTime"]))

            LOGGER.info("All expected tags are set for stopped instance")

            snapshot_arn = "arn:aws:rds:{}:{}:snapshot:{}-stopped".format(REGION, account, db_instance_id)
            self.assertTrue(self.verify_tags_are_set(snapshot_arn, [
                "StopExecutionId",
                "StopDBInstanceId",
                "StopDateTime",
                "StopDate",
                "StopTime"]))

            LOGGER.info("All expected tags are set created snapshot")

            DocumentTest.delete_snapshot(snapshot_id)

        finally:
            try:
                ssm_doc.destroy()
            except Exception:
                pass

            test_cf_stack.delete_stack()
Esempio n. 4
0
    def test_update_document(self):
        cfn_client = boto3.client('cloudformation', region_name=REGION)
        ssm_client = boto3.client('ssm', region_name=REGION)

        ssm_doc = ssm_testing.SSMTester(ssm_client=ssm_client,
                                        doc_filename=os.path.join(
                                            DOC_DIR,
                                            'Output/aws-CopySnapshot.json'),
                                        doc_name=SSM_DOC_NAME,
                                        doc_type='Automation')

        LOGGER.info("Creating automation document")
        self.assertEqual(ssm_doc.create_document(), 'Active')

        test_cf_stack = ssm_testing.CFNTester(
            cfn_client=cfn_client,
            template_filename=os.path.abspath(
                os.path.join(
                    DOC_DIR,
                    "Tests/CloudFormationTemplates/TestTemplate.yml")),
            stack_name=TEST_CFN_STACK_NAME)

        LOGGER.info('Creating Test Stack')
        test_cf_stack.create_stack([{
            'ParameterKey':
            'UserARN',
            'ParameterValue':
            sts_client.get_caller_identity().get('Arn')
        }])
        LOGGER.info('Test Stack has been created')

        # Verify role exists
        role_arn = test_cf_stack.stack_outputs['AutomationAssumeRoleARN']
        verify_role_created(role_arn)

        # Now create the snapshot
        LOGGER.info('Creating test snapshot')
        volume_id = test_cf_stack.stack_outputs['VolumeId']
        snapshot = create_snapshot(volume_id)

        try:
            description = "Copied from " + snapshot.snapshot_id
            execution = ssm_doc.execute_automation(
                params={
                    'SnapshotId': [snapshot.snapshot_id],
                    'SourceRegion': [REGION],
                    'Description': [description],
                    'AutomationAssumeRole': [role_arn]
                })
            self.assertEqual(
                ssm_doc.automation_execution_status(ssm_client, execution,
                                                    False), 'Success')

            LOGGER.info('Now verifying the copied snapshot')
            response = ssm_client.get_automation_execution(
                AutomationExecutionId=execution)
            str_payload = response['AutomationExecution']['Outputs'][
                'copySnapshot.Payload'][0]
            payload = json.loads(str_payload)
            new_snapshot_id = payload['SnapshotId']

            snapshot_response = ec2_client.describe_snapshots(
                SnapshotIds=[new_snapshot_id])

            # Test instance exists in volume
            self.assertEqual(len(snapshot_response['Snapshots']), 1)

            LOGGER.info('new snapshot is verified, now cleaning up')
            delete_snapshot(new_snapshot_id)

        finally:
            try:
                ssm_doc.destroy()
            except Exception:
                pass

            delete_snapshot(snapshot.snapshot_id)
            test_cf_stack.delete_stack()
    def test_update_document(self):
        LOGGER.info("TESTING Automation Document DISABLE Case")
        cfn_client = boto3.client('cloudformation', region_name=REGION)
        ssm_client = boto3.client('ssm', region_name=REGION)

        ssm_doc = ssm_testing.SSMTester(
            ssm_client=ssm_client,
            doc_filename=os.path.join(
                DOC_DIR, 'Output/aws-ConfigureCloudWatchOnEC2Instance.json'),
            doc_name=SSM_DOC_NAME,
            doc_type='Automation')

        test_cf_stack = ssm_testing.CFNTester(
            cfn_client=cfn_client,
            template_filename=os.path.join(
                DOC_DIR, 'Tests/CloudFormationTemplates/TestTemplate.yml'),
            stack_name=TEST_CFN_STACK_NAME)

        LOGGER.info('Creating Test Stack')
        test_cf_stack.create_stack([{
            'ParameterKey':
            'UserARN',
            'ParameterValue':
            sts_client.get_caller_identity().get('Arn')
        }, {
            'ParameterKey': 'AMI',
            'ParameterValue': AMIID
        }, {
            'ParameterKey': 'INSTANCETYPE',
            'ParameterValue': INSTANCETYPE
        }])
        LOGGER.info('Test Stack has been created')
        LOGGER.info(test_cf_stack)
        # Verify role exists
        role_arn = test_cf_stack.stack_outputs['AutomationAssumeRoleARN']
        verify_role_created(role_arn)

        LOGGER.info('Creating automation document')
        self.assertEqual(ssm_doc.create_document(), 'Active')

        ec2_instance_id = test_cf_stack.stack_outputs['InstanceId']
        LOGGER.info('EC-2 instance spun up, id = ' + ec2_instance_id)

        try:
            LOGGER.info('Running the Automation-Document now!')

            execution = ssm_doc.execute_automation(
                params={
                    'InstanceId': [ec2_instance_id],
                    'status': [MONITOR_STATE],
                    'AutomationAssumeRole': [role_arn]
                })
            self.assertEqual(
                ssm_doc.automation_execution_status(ssm_client, execution,
                                                    False), 'Success')
            LOGGER.info('Automation-Execution was successful!')

            end_state = verify_monitorstate_changed(ec2_instance_id)
            LOGGER.info('test subject host Monitoring state is ' + end_state)

            self.assertEqual(
                end_state, REQUIRED_ENDSTATE,
                "The EC-2 instance monitoring failed to change to disabled")
            LOGGER.info('End of Disable Case Test')
        finally:
            try:
                ssm_doc.destroy()
            except Exception:
                pass

            test_cf_stack.delete_stack()
    def test_linux_document_with_custom_vpc(self):
        custom_vpc = create_custom_vpc()
        custom_subnet = create_custom_security_group(custom_vpc["VpcId"])

        self.assertIsNotNone(custom_vpc["VpcId"])

        ssm_doc = None
        try:
            cleanup(custom_vpc["VpcId"])

            ssm_doc = ssm_testing.SSMTester(
                ssm_client=ssm_client,
                doc_filename=os.path.join(
                    DOC_DIR,
                    'Output',
                    'aws-CreateManagedLinuxInstance.json'),
                doc_name=SSM_DOC_NAME,
                doc_type='Automation'
            )

            automation_role = ssm_doc.get_automation_role(
                boto3.client('sts', region_name=REGION),
                boto3.client('iam', region_name=REGION),
                SERVICE_ROLE_NAME
            )

            ec2_client.create_key_pair(
                KeyName=KEY_PAIR_NAME
            )

            self.assertEqual(ssm_doc.create_document(), 'Active')

            execution = ssm_doc.execute_automation(
                params={
                    'AmiId': [LINUX_AMI_ID],
                    'VpcId': [custom_vpc["VpcId"]],
                    'SubnetId': [custom_subnet.id],
                    'KeyPairName': [KEY_PAIR_NAME],
                    'AutomationAssumeRole': [automation_role],
                    'InstanceType': [INSTANCE_TYPE],
                    'StackName': [CFN_STACK_NAME],
                    'RemoteAccessCidr': ["10.0.0.0/24"],
                    'RoleName': [PROFILE_NAME],
                    'GroupName': [GROUP_NAME]})

            result = ssm_doc.automation_execution_status(ssm_client, execution)
            self.assertEqual(result, "Success")

            instances = ec2_client.describe_instances(
                Filters=[
                    {'Name': 'tag:aws:cloudformation:stack-name', 'Values': [CFN_STACK_NAME]},
                    {'Name': 'instance-state-name', 'Values': ["running"]}
                ])
            running_instances = []
            for reservation in instances["Reservations"]:
                for instance in reservation["Instances"]:
                    print instance
                    running_instances.append(instance["InstanceId"])

                    self.assertEqual(instance["VpcId"], custom_vpc["VpcId"])
                    self.assertEqual(instance["KeyName"], KEY_PAIR_NAME)
                    self.assertGreater(len(instance["SecurityGroups"]), 0)
                    self.assertEqual(instance["SecurityGroups"][0]["GroupName"], GROUP_NAME)
                    self.assertEqual(instance["InstanceType"], INSTANCE_TYPE)
                    self.assertTrue(instance["IamInstanceProfile"]["Arn"].endswith(PROFILE_NAME))
                    self.assertEqual(instance["State"]["Name"], "running")

            ssm_info = ssm_client.describe_instance_information(
                InstanceInformationFilterList=[{
                    'key': 'InstanceIds',
                    'valueSet': running_instances
                }]
            )
            print ssm_info
        finally:
            cleanup(custom_vpc["VpcId"])
            if ssm_doc is not None:
                ssm_doc.destroy()
Esempio n. 7
0
    def test_document():
        """Verify correct deployment and use of document."""

        ssm_doc = ssm_testing.SSMTester(
            ssm_client=ssm_client,
            doc_filename=os.path.join(
                DOC_DIR, 'Documents',
                'aws-DeleteCloudFormationWithApproval.json'),
            doc_name=SSM_DOC_NAME,
            doc_type='Automation')

        test_cf_stack = ssm_testing.CFNTester(
            cfn_client=cfn_client,
            template_filename=os.path.join(DOC_DIR, 'Tests',
                                           'CloudFormationTemplates',
                                           'TwoInstances.yml'),
            stack_name=INSTANCE_CFN_STACK_NAME)

        automation_role = ssm_doc.get_automation_role(sts_client, iam_client,
                                                      SERVICE_ROLE_NAME)

        LOGGER.info('Starting instances for testing')
        stack = test_cf_stack.create_stack([{
            'ParameterKey': 'AMI',
            'ParameterValue': AMI_ID
        }, {
            'ParameterKey': 'INSTANCETYPE',
            'ParameterValue': INSTANCE_TYPE
        }])

        try:
            LOGGER.info('Creating automation document')
            assert ssm_doc.create_document(
            ) == 'Active', 'Document not created successfully'

            user_arn = sts_client.get_caller_identity()['Arn']
            sns_topic_arn = test_cf_stack.stack_outputs['SNSTopicArn']

            LOGGER.info("User ARN for approval: " + user_arn)
            LOGGER.info("SNS Topic ARN for approval: " + sns_topic_arn)

            execution = ssm_doc.execute_automation(
                params={
                    'StackNameOrId': [INSTANCE_CFN_STACK_NAME],
                    'AutomationAssumeRole': [automation_role],
                    'Approvers': [user_arn],
                    'SNSTopicArn': [sns_topic_arn]
                })

            # since this automation requires approval to continue, the correct status at this point should be 'Waiting'
            assert ssm_doc.automation_execution_status(ssm_client, execution, False) == 'Waiting', \
                'Automation not waiting for approval'

            LOGGER.info('Approving continuation of execution')
            ssm_client.send_automation_signal(AutomationExecutionId=execution,
                                              SignalType='Approve')

            LOGGER.info(
                'Verifying automation executions have concluded successfully')

            assert ssm_doc.automation_execution_status(
                ssm_client,
                execution) == 'Success', 'Stack not deleted correctly'

            LOGGER.info('Verifying stack is deleted')
            # deleted stacks require the Stack ID, not the name, as the param to describe_stacks
            stack_desc = cfn_client.describe_stacks(StackName=stack['StackId'])
            stack_status = stack_desc['Stacks'][0]['StackStatus']
            assert stack_desc['Stacks'][0]['StackStatus'] == 'DELETE_COMPLETE', \
                'Stack deletion failed with status: ' + stack_status

        finally:
            ssm_doc.destroy()
    def test_update_document(self):
        cfn_client = boto3.client('cloudformation', region_name=REGION)
        ssm_client = boto3.client('ssm', region_name=REGION)

        ssm_doc = ssm_testing.SSMTester(ssm_client=ssm_client,
                                        doc_filename=os.path.join(
                                            DOC_DIR,
                                            'Output/aws-StopRdsInstance.json'),
                                        doc_name=SSM_DOC_NAME,
                                        doc_type='Automation')

        test_cf_stack = ssm_testing.CFNTester(
            cfn_client=cfn_client,
            template_filename=os.path.join(
                DOC_DIR, 'Tests/CloudFormationTemplates/TestTemplate.yml'),
            stack_name=TEST_CFN_STACK_NAME)

        LOGGER.info('Creating Test Stack')
        test_cf_stack.create_stack([{
            'ParameterKey':
            'UserARN',
            'ParameterValue':
            sts_client.get_caller_identity().get('Arn')
        }, {
            'ParameterKey': 'DBInstanceClass',
            'ParameterValue': TEST_DB_CLASS
        }, {
            'ParameterKey': 'AllocatedStorage',
            'ParameterValue': TEST_DB_ALLOCATED_STORAGE
        }, {
            'ParameterKey': 'Engine',
            'ParameterValue': TEST_DB_ENGINE
        }, {
            'ParameterKey': 'MasterUsername',
            'ParameterValue': TEST_DB_MASTER_USERNAME
        }, {
            'ParameterKey':
            'MasterUserPassword',
            'ParameterValue':
            TEST_DB_MASTER_USER_PASSWORD
        }])
        LOGGER.info('Test Stack has been created')

        # Verify role exists
        role_arn = test_cf_stack.stack_outputs['AutomationAssumeRoleARN']
        verify_role_created(role_arn)

        # Start an Rds instance for us to stop
        LOGGER.info('Creating automation document')
        self.assertEqual(ssm_doc.create_document(), 'Active')

        db_instance_id = test_cf_stack.stack_outputs['InstanceId']
        LOGGER.info("Test Case DB Instance ID:" + db_instance_id)

        rds_client.stop_db_instance(DBInstanceIdentifier=db_instance_id)
        # ...waiting for the stop to complete, then proceeding. We're procedurally stopping the DB so that we can prove
        # the Automation Under Test won't implode under legit edge cases (like a logical noop case)
        verify_db_stopped(db_instance_id)

        try:
            LOGGER.info('Executing SSM automation document to stop instances')
            # Stop the Rds instance
            execution = ssm_doc.execute_automation(params={
                'InstanceId': [db_instance_id],
                'AutomationAssumeRole': [role_arn]
            })
            self.assertEqual(
                ssm_doc.automation_execution_status(ssm_client, execution,
                                                    False), 'Success')

            # Now obtain evidence to prove the Rds instance has stopped
            db_state = rds_client.describe_db_instances(
                DBInstanceIdentifier=db_instance_id)
            self.assertEqual(db_state['DBInstances'][0]['DBInstanceStatus'],
                             "stopped")

            LOGGER.info('Verified the DB instance is stopped')
        finally:
            try:
                ssm_doc.destroy()
            except Exception:
                pass

            test_cf_stack.delete_stack()
Esempio n. 9
0
    def test_update_document(self):
        cfn_client = boto3.client('cloudformation', region_name=REGION)
        ssm_client = boto3.client('ssm', region_name=REGION)

        ssm_doc = ssm_testing.SSMTester(ssm_client=ssm_client,
                                        doc_filename=os.path.join(
                                            DOC_DIR,
                                            'Output/aws-DetachEBSVolume.json'),
                                        doc_name=SSM_DOC_NAME,
                                        doc_type='Automation')

        test_cf_stack = ssm_testing.CFNTester(
            cfn_client=cfn_client,
            template_filename=os.path.abspath(
                os.path.join(
                    DOC_DIR,
                    "Tests/CloudFormationTemplates/TestTemplate.yml")),
            stack_name=TEST_CFN_STACK_NAME)

        LOGGER.info('Creating Test Stack')
        test_cf_stack.create_stack([{
            'ParameterKey': 'AMI',
            'ParameterValue': LINUX_AMI_ID
        }, {
            'ParameterKey': 'INSTANCETYPE',
            'ParameterValue': LINUX_INSTANCE_TYPE
        }, {
            'ParameterKey': 'DEVICE',
            'ParameterValue': DEVICE_NAME
        }, {
            'ParameterKey':
            'UserARN',
            'ParameterValue':
            sts_client.get_caller_identity().get('Arn')
        }])
        LOGGER.info('Test Stack has been created')

        # Verify role exists
        role_arn = test_cf_stack.stack_outputs['AutomationAssumeRoleARN']
        verify_role_created(role_arn)

        # Verify instance started
        instance_id = test_cf_stack.stack_outputs['InstanceId']
        verify_instance_started(instance_id)

        LOGGER.info('Mounting Volume')
        # print instance_id
        mount_response = mount_volume(ssm_client, instance_id, DEVICE_NAME)
        # print(mount_response)
        self.assertEqual(mount_response['Status'], 'Success')
        try:
            LOGGER.info("Creating automation document")
            self.assertEqual(ssm_doc.create_document(), 'Active')

            volume_id = test_cf_stack.stack_outputs['VolumeId']

            execution = ssm_doc.execute_automation(params={
                'VolumeId': [volume_id],
                'AutomationAssumeRole': [role_arn]
            })
            self.assertEqual(
                ssm_doc.automation_execution_status(ssm_client, execution,
                                                    False), 'Failed')

            LOGGER.info('Volume is still attached, now verifying')

            ec2 = boto3.resource('ec2')
            volume = ec2.Volume(volume_id)

            # Test instance exists in volume
            self.assertEqual(len(volume.attachments), 1)

            LOGGER.info('Unmounting volume...')
            unmount_volume(ssm_client, instance_id, DEVICE_NAME)
            time.sleep(10)

            volume.reload()
            LOGGER.info('Verifying is detached')
            self.assertEqual(len(volume.attachments), 0)
            LOGGER.info('Test Successful')
        finally:
            try:
                ssm_doc.destroy()
            except Exception:
                pass

            try:
                unmount_volume(ssm_client, instance_id, DEVICE_NAME)
            except Exception:
                pass

            test_cf_stack.delete_stack()
Esempio n. 10
0
    def test_update_document(self):

        ssm_doc = ssm_testing.SSMTester(
            ssm_client=ssm_client,
            doc_filename=os.path.join(DOC_DIR,
                                      'Output/aws-RebootRdsInstance.json'),
            doc_name=SSM_DOC_NAME,
            doc_type='Automation')

        LOGGER.info("Declaring Test Stack")
        test_cf_stack = ssm_testing.CFNTester(
            cfn_client=cfn_client,
            template_filename=os.path.join(
                DOC_DIR, 'Tests/CloudFormationTemplates/TestTemplate.yml'),
            stack_name=TEST_CFN_STACK_NAME)
        LOGGER.info('Creating Test Stack')
        test_cf_stack.create_stack([{
            'ParameterKey':
            'UserARN',
            'ParameterValue':
            sts_client.get_caller_identity().get('Arn')
        }, {
            'ParameterKey': 'DBInstanceClass',
            'ParameterValue': TEST_DB_CLASS
        }, {
            'ParameterKey': 'AllocatedStorage',
            'ParameterValue': TEST_DB_ALLOCATED_STORAGE
        }, {
            'ParameterKey': 'Engine',
            'ParameterValue': TEST_DB_ENGINE
        }, {
            'ParameterKey': 'MasterUsername',
            'ParameterValue': TEST_DB_MASTER_USERNAME
        }, {
            'ParameterKey':
            'MasterUserPassword',
            'ParameterValue':
            TEST_DB_MASTER_USER_PASSWORD
        }])
        LOGGER.info('Test Stack has been created')

        # Verify role exists
        role_arn = test_cf_stack.stack_outputs['AutomationAssumeRoleARN']
        verify_role_created(role_arn)

        # Start an Rds instance for us to test
        LOGGER.info('Creating automation document')
        self.assertEqual(ssm_doc.create_document(), 'Active')

        instance_id = test_cf_stack.stack_outputs['InstanceId']
        LOGGER.info('DB instance featured in this test run has id ' +
                    instance_id)
        db_state = rds_client.describe_db_instances(
            DBInstanceIdentifier=instance_id)
        LOGGER.info('It current state is ' +
                    db_state['DBInstances'][0]['DBInstanceStatus'])

        try:
            LOGGER.info('Commencing automation execution')
            execution = ssm_doc.execute_automation(params={
                'InstanceId': [instance_id],
                'AutomationAssumeRole': [role_arn]
            })
            LOGGER.info('automation execution-id ' + execution)
            exec_fail = 'Automation execution did NOT end successfully'
            self.assertEqual(
                ssm_doc.automation_execution_status(ssm_client, execution,
                                                    False), 'Success',
                exec_fail)

            db_state = rds_client.describe_db_instances(
                DBInstanceIdentifier=instance_id)
            self.assertEqual(db_state['DBInstances'][0]['DBInstanceStatus'],
                             "available")
            LOGGER.info('Verified the DB instance is available')
        finally:
            try:
                LOGGER.info('Destroying automation document')
                ssm_doc.destroy()
            except Exception:
                pass

            LOGGER.info('Standing down Test Stack')
            test_cf_stack.delete_stack()
            LOGGER.info('Test cleanup completed')
    def test_update_document(self):
        cfn_client = boto3.client('cloudformation', region_name=REGION)
        ssm_client = boto3.client('ssm', region_name=REGION)

        ssm_doc = ssm_testing.SSMTester(
            ssm_client=ssm_client,
            doc_filename=os.path.join(
                DOC_DIR, 'Output/aws-UpdateCloudFormationTemplate.json'),
            doc_name=SSM_DOC_NAME,
            doc_type='Automation')

        test_cf_stack = ssm_testing.CFNTester(
            cfn_client=cfn_client,
            template_filename=os.path.abspath(
                os.path.join(
                    DOC_DIR,
                    "Tests/CloudFormationTemplates/TestTemplate.yml")),
            stack_name=TEST_CFN_STACK_NAME)
        test_cf_stack.create_stack([])

        try:
            user_arn = sts_client.get_caller_identity().get('Arn')

            cleanup_role()
            admin_role = create_role(user_arn)["Role"]["Arn"]
            cleanup_bucket()

            LOGGER.info("Creating automation document")
            self.assertEqual(ssm_doc.create_document(), 'Active')

            role_info = iam_client.get_role_policy(
                RoleName=test_cf_stack.stack_outputs["RoleName"],
                PolicyName='test-policy-name')
            self.assertEqual(
                len(role_info["PolicyDocument"]["Statement"]["Action"]), 1)

            LOGGER.info("Creating test S3 bucket")
            s3_client.create_bucket(
                Bucket=TEST_S3_BUCKET,
                CreateBucketConfiguration={"LocationConstraint": "us-west-2"})
            s3_client.upload_file(
                os.path.abspath(
                    os.path.join(
                        DOC_DIR,
                        "Tests/CloudFormationTemplates/TestUpdateTemplate.yml")
                ), TEST_S3_BUCKET, 'TestUpdateTemplate.yml')

            update_template = "http://s3-us-west-2.amazonaws.com/{}/TestUpdateTemplate.yml".format(
                TEST_S3_BUCKET)

            execution = ssm_doc.execute_automation(
                params={
                    'StackNameOrId': [TEST_CFN_STACK_NAME],
                    'TemplateUrl': [update_template],
                    'LambdaAssumeRole': [admin_role],
                    'AutomationAssumeRole': [admin_role]
                })

            result = ssm_doc.automation_execution_status(ssm_client, execution)

            while test_cf_stack.is_stack_in_status(
                    'CREATE_IN_PROGRESS') is True:
                LOGGER.info(
                    'Waiting 5 seconds before checking again for document update'
                )
                time.sleep(5)

            self.assertEqual(result, "Success")

            role_info = iam_client.get_role_policy(
                RoleName=test_cf_stack.stack_outputs["RoleName"],
                PolicyName='test-policy-name')
            self.assertEqual(
                len(role_info["PolicyDocument"]["Statement"]["Action"]), 3)

        finally:
            try:
                ssm_doc.destroy()
            except Exception:
                pass

            test_cf_stack.delete_stack()

            cleanup_bucket()
            cleanup_role()
Esempio n. 12
0
    def test_exit_standby_document(self):
        user_arn = boto3.client('sts', region_name=REGION).get_caller_identity().get('Arn')
        with create_admin_role(iam_client, sts_client, PREFIX + "exit-standby-test", user_arn) as admin_role:
            admin_role_arn = admin_role["Role"]["Arn"]

            available_subnets = vpcUtil.find_default_subnets()

            # ensure the account being used has a default VPC.
            assert len(available_subnets) > 0, "No default subnet available for testing"

            ssm_doc = ssm_testing.SSMTester(
                ssm_client=ssm_client,
                doc_filename=os.path.join(
                    DOC_DIR,
                    'Output/aws-ASGExitStandby.json'),
                doc_name=EXIT_STANDBY_SSM_DOC_NAME,
                doc_type='Automation'
            )

            test_cf_stack = ssm_testing.CFNTester(
                cfn_client=cfn_client,
                template_filename=os.path.abspath(os.path.join(
                    DOC_DIR,
                    'Tests/CloudFormationTemplates/ASG.yml')),
                stack_name=EXIT_STANDBY_CFN_STACK_NAME
            )

            LOGGER.info('Creating AutoScaling Group for testing')
            stack_param = {
                'AMI': AMI_ID,
                'Subnets': available_subnets[0].id,
                'InstanceType': INSTANCE_TYPE
            }
            test_cf_stack.create_stack([
                {'ParameterKey': key, 'ParameterValue': value} for key, value in stack_param.iteritems()])

            asg_name = test_cf_stack.stack_outputs["ASGName"]

            LOGGER.info("Waiting for an instance to become ready...")
            working_instance = asg_wait_for_running_instance(
                asg_name=asg_name,
                number_of_instance=1,
                max_wait_sec=1800)[0]

            LOGGER.info("Setting instance to enter standby mode")
            as_client.enter_standby(
                InstanceIds=[working_instance],
                AutoScalingGroupName=asg_name,
                ShouldDecrementDesiredCapacity=True)

            # poll the instance until it reaches the standby state
            asg_wait_for_instance_in_state(working_instance, 'Standby')

            try:

                LOGGER.info("Creating automation document")
                assert ssm_doc.create_document() == 'Active', 'Document not created successfully'

                LOGGER.info(
                    "Executing SSM automation document to remove instance from standby mode on {}".format(working_instance))
                execution = ssm_doc.execute_automation(
                    params={'LambdaRoleArn': [admin_role_arn],
                            'InstanceId': [working_instance],
                            'AutomationAssumeRole': [admin_role_arn]})

                # Collect asg instance lifecycle change.

                asg_status_changes = []
                asg_status_ignores = ["Pending"]

                # Status callback to collect any necessary data
                def status_callback(_):
                    collect_asg_status_change(asg_name, working_instance, asg_status_ignores, asg_status_changes)

                # Wait for SSM to finish while collecting value change (callback).
                result = ssm_doc.automation_execution_status(ssm_client, execution, status_callback=status_callback)

                # Verify instance status change.
                LOGGER.info("ASG status change sequence: " + str(asg_status_changes))
                expected_status_change_sequence = [
                    "Standby",
                    "InService"
                ]
                is_status_change_expected = asg_status_changes == expected_status_change_sequence
                assert is_status_change_expected, 'ASG instant lifecycle did not match expected.'

                LOGGER.info('Verifying automation executions have concluded successfully')
                assert result == 'Success', 'Document did not complete'

            finally:
                test_cf_stack.delete_stack()
                ssm_doc.destroy()
    def test_update_document(self):
        cfn_client = boto3.client('cloudformation', region_name=REGION)
        ssm_client = boto3.client('ssm', region_name=REGION)

        ssm_doc = ssm_testing.SSMTester(
            ssm_client=ssm_client,
            doc_filename=os.path.join(DOC_DIR,
                                      'Output/aws-StartRdsInstance.json'),
            doc_name=SSM_DOC_NAME,
            doc_type='Automation')

        test_cf_stack = ssm_testing.CFNTester(
            cfn_client=cfn_client,
            template_filename=os.path.join(
                DOC_DIR, 'Tests/CloudFormationTemplates/TestTemplate.yml'),
            stack_name=TEST_CFN_STACK_NAME)

        LOGGER.info('Creating Test Stack')
        test_cf_stack.create_stack([{
            'ParameterKey':
            'UserARN',
            'ParameterValue':
            sts_client.get_caller_identity().get('Arn')
        }, {
            'ParameterKey': 'DBInstanceClass',
            'ParameterValue': TEST_DB_CLASS
        }, {
            'ParameterKey': 'AllocatedStorage',
            'ParameterValue': TEST_DB_ALLOCATED_STORAGE
        }, {
            'ParameterKey': 'Engine',
            'ParameterValue': TEST_DB_ENGINE
        }, {
            'ParameterKey': 'MasterUsername',
            'ParameterValue': TEST_DB_MASTER_USERNAME
        }, {
            'ParameterKey':
            'MasterUserPassword',
            'ParameterValue':
            TEST_DB_MASTER_USER_PASSWORD
        }])
        LOGGER.info('Test Stack has been created')

        # Verify role exists
        role_arn = test_cf_stack.stack_outputs['AutomationAssumeRoleARN']
        verify_role_created(role_arn)

        # Start an Rds instance for us to test
        LOGGER.info('Creating automation document')
        self.assertEqual(ssm_doc.create_document(), 'Active')

        db_instance_id = test_cf_stack.stack_outputs['InstanceId']

        # This case verifies the impl-under-test is resilient in the face of required INACTION
        # Make sure the furnished RDS instance is in running
        verify_db_started(db_instance_id)

        try:
            LOGGER.info('Executing SSM automation document to stop instances')
            # Stop the Rds instance
            execution = ssm_doc.execute_automation(params={
                'InstanceId': [db_instance_id],
                'AutomationAssumeRole': [role_arn]
            })
            self.assertEqual(
                ssm_doc.automation_execution_status(ssm_client, execution,
                                                    False), 'Success')

            db_state = rds_client.describe_db_instances(
                DBInstanceIdentifier=db_instance_id)
            self.assertEqual(db_state['DBInstances'][0]['DBInstanceStatus'],
                             "available")

            LOGGER.info('Verified the DB instance is stopped')
        finally:
            try:
                ssm_doc.destroy()
            except Exception:
                pass

            test_cf_stack.delete_stack()
    def execute(self, ami, document, custom_prefix):
        default_vpc = util.find_default_vpc(ec2_client)
        self.assertIsNotNone(default_vpc["VpcId"])
        user_arn = boto3.client(
            'sts', region_name=REGION).get_caller_identity().get('Arn')

        ssm_doc = None
        with util.sns_topic(APPROVAL_TOPIC, sns_client) as sns_topic, \
                util.admin_role(iam_client, sts_client, custom_prefix + LAMBDA_ROLE, user_arn) as admin_role:
            sns_topic_arn = sns_topic["TopicArn"]
            admin_role_arn = admin_role["Role"]["Arn"]

            try:
                cleanup(default_vpc["VpcId"])

                ssm_doc = ssm_testing.SSMTester(ssm_client=ssm_client,
                                                doc_filename=os.path.join(
                                                    DOC_DIR, 'Output',
                                                    document),
                                                doc_name=SSM_DOC_NAME,
                                                doc_type='Automation')

                ec2_client.create_key_pair(KeyName=KEY_PAIR_NAME)

                self.assertEqual(ssm_doc.create_document(), 'Active')

                execution = ssm_doc.execute_automation(
                    params={
                        'AmiId': [ami],
                        'KeyPairName': [KEY_PAIR_NAME],
                        'AutomationAssumeRole': [admin_role_arn],
                        'InstanceType': [INSTANCE_TYPE],
                        'StackName': [CFN_STACK_NAME],
                        'RemoteAccessCidr': ["10.0.0.0/24"],
                        'Approvers': [user_arn],
                        'SNSTopicArn': [sns_topic_arn],
                        'RoleName': [PROFILE_NAME],
                        'GroupName': [GROUP_NAME]
                    })
                self.assertEqual(
                    ssm_doc.automation_execution_status(
                        ssm_client, execution, False), 'Waiting')

                LOGGER.info('Approving continuation of execution')
                ssm_client.send_automation_signal(
                    AutomationExecutionId=execution, SignalType='Approve')

                result = ssm_doc.automation_execution_status(
                    ssm_client, execution)

                self.assertEqual(result, "Success")

                instances = ec2_client.describe_instances(
                    Filters=[{
                        'Name': 'tag:aws:cloudformation:stack-name',
                        'Values': [CFN_STACK_NAME]
                    }, {
                        'Name': 'instance-state-name',
                        'Values': ["running"]
                    }])
                running_instances = []
                for reservation in instances["Reservations"]:
                    for instance in reservation["Instances"]:
                        print instance
                        running_instances.append(instance["InstanceId"])

                        self.assertEqual(instance["VpcId"],
                                         default_vpc["VpcId"])
                        self.assertEqual(instance["KeyName"], KEY_PAIR_NAME)
                        self.assertGreater(len(instance["SecurityGroups"]), 0)
                        self.assertEqual(
                            instance["SecurityGroups"][0]["GroupName"],
                            GROUP_NAME)
                        self.assertEqual(instance["InstanceType"],
                                         INSTANCE_TYPE)
                        self.assertTrue(instance["IamInstanceProfile"]
                                        ["Arn"].endswith(PROFILE_NAME))
                        self.assertEqual(instance["State"]["Name"], "running")

                ssm_info = ssm_client.describe_instance_information(
                    InstanceInformationFilterList=[{
                        'key':
                        'InstanceIds',
                        'valueSet':
                        running_instances
                    }])
                print ssm_info

            finally:
                cleanup(default_vpc["VpcId"])
                if ssm_doc is not None:
                    ssm_doc.destroy()
Esempio n. 15
0
    def testdocument():
        """Verify correct deployment and use of document."""
        cfn_client = boto3.client('cloudformation', region_name=REGION)
        ec2_client = boto3.client('ec2', region_name=REGION)
        ssm_client = boto3.client('ssm', region_name=REGION)

        ssm_doc = ssm_testing.SSMTester(
            ssm_client=ssm_client,
            doc_filename=os.path.join(DOC_DIR,
                                      'Documents',
                                      'aws-RestartEC2Instance.json'),
            doc_name=SSM_DOC_NAME,
            doc_type='Automation'
        )

        test_cf_stack = ssm_testing.CFNTester(
            cfn_client=cfn_client,
            template_filename=os.path.join(DOC_DIR,
                                           'Tests',
                                           'CloudFormationTemplates',
                                           'TwoInstances.yml'),
            stack_name=INSTANCE_CFN_STACKNAME
        )

        automation_role = ssm_doc.get_automation_role(
            boto3.client('sts', region_name=REGION),
            boto3.client('iam', region_name=REGION),
            SERVICE_ROLE_NAME
        )

        LOGGER.info('Starting instances for testing')
        test_cf_stack.create_stack([
            {
                'ParameterKey': 'AMI',
                'ParameterValue': AMIID
            },
            {
                'ParameterKey': 'INSTANCETYPE',
                'ParameterValue': INSTANCE_TYPE
            }
        ])
        try:
            LOGGER.info('Creating automation document')
            assert ssm_doc.create_document() == 'Active', ('Document not '
                                                           'created '
                                                           'successfully')

            LOGGER.info('Running automation to restart multiple instances '
                        '(using defined role)')
            instances_1_2 = [test_cf_stack.stack_outputs['Instance0Id'],
                             test_cf_stack.stack_outputs['Instance1Id']]
            execution = ssm_doc.execute_automation(
                params={'InstanceId': instances_1_2,
                        'AutomationAssumeRole': [automation_role]})

            LOGGER.info('Verifying automation executions have concluded successfully')

            assert ssm_doc.automation_execution_status(
                ssm_client,
                execution
            ) == 'Success', 'Instances not restarted successfully'

            LOGGER.info('Verifying all instances are running')
            describe_res = ec2_client.describe_instance_status(
                InstanceIds=instances_1_2,
                IncludeAllInstances=True
            )
            assert all(d['InstanceState']['Name'] == 'running' for d in describe_res['InstanceStatuses']) is True, (  # noqa pylint: disable=line-too-long
                'Instances not started')

        finally:
            test_cf_stack.delete_stack()
            ssm_doc.destroy()
Esempio n. 16
0
    def test_document():
        cfn_client = boto3.client('cloudformation', region_name=REGION)
        ssm_client = boto3.client('ssm', region_name=REGION)

        available_subnets = vpcUtil.find_default_subnets()

        # ensure the account being used has a default VPC.
        assert len(available_subnets) > 0, "No default subnet available for testing"

        ssm_doc = ssm_testing.SSMTester(
            ssm_client=ssm_client,
            doc_filename=os.path.join(
                DOC_DIR,
                'Documents/aws-PatchWindowsInASG.json'),
            doc_name=SSM_DOC_NAME,
            doc_type='Automation'
        )

        test_cf_stack = ssm_testing.CFNTester(
            cfn_client=cfn_client,
            template_filename=os.path.abspath(os.path.join(
                DOC_DIR,
                'Tests/CloudFormationTemplates/ASG.yml')),
            stack_name=CFN_STACK_NAME
        )

        automation_role = ssm_doc.get_automation_role(
            boto3.client('sts', region_name=REGION),
            boto3.client('iam', region_name=REGION),
            SERVICE_ROLE_NAME
        )

        LOGGER.info('Creating AutoScaling Group for testing')
        stack_param = {
            'AMI': AMI_ID,
            'Subnets': available_subnets[0].id,
            'InstanceType': INSTANCE_TYPE
        }
        test_cf_stack.create_stack([
            {'ParameterKey': key, 'ParameterValue': value} for key, value in stack_param.iteritems()])

        try:
            asg_name = test_cf_stack.stack_outputs["ASGName"]

            LOGGER.info("Creating automation document")
            assert ssm_doc.create_document() == 'Active', 'Document not created successfully'

            LOGGER.info("Waiting for an instance to become ready...")
            working_instance = asg_wait_for_running_instance(asg_name, 1)[0]

            LOGGER.info("Checking for AutoPatchInstanceInASG tag on instance.")
            check_tag_exist(working_instance, 'AutoPatchInstanceInASG', False)

            LOGGER.info("Executing SSM automation document to update instance on {}".format(working_instance))
            execution = ssm_doc.execute_automation(
                params={'InstanceId': [working_instance],
                        'AutomationAssumeRole': [automation_role]})

            # Collect tag change and asg instance lifecycle change.
            tag_changes = [None]
            asg_status_changes = []
            asg_status_ignores = ["EnteringStandby", "Pending"]

            # Status callback to collect any necessary data
            def status_callback(_):
                collect_tag_change(working_instance, "AutoPatchInstanceInASG", tag_changes),
                collect_asg_status_change(asg_name, working_instance, asg_status_ignores, asg_status_changes)

            # Wait for SSM to finish while collecting value change (callback).
            result = ssm_doc.automation_execution_status(ssm_client, execution, status_callback=status_callback)

            # Verify tag change.
            LOGGER.info(tag_changes)
            expected_tag_change = [
                None,
                "InProgress",
                "Completed"
            ]
            assert tag_changes == expected_tag_change, 'Tag did not follow sequence.'

            # Verify instance status change.
            LOGGER.info(asg_status_changes)
            expected_status_change_sequence = [
                "InService",
                "Standby",
                "InService"
            ]
            is_status_change_expected = asg_status_changes == expected_status_change_sequence
            assert is_status_change_expected, 'ASG instant lifecycle did not match expected.'

            LOGGER.info('Verifying automation executions have concluded successfully')
            assert result == 'Success', 'Document did not complete'

        finally:
            test_cf_stack.delete_stack()
            ssm_doc.destroy()
Esempio n. 17
0
    def test_update_document(self):
        cfn_client = boto3.client('cloudformation', region_name=REGION)
        ssm_client = boto3.client('ssm', region_name=REGION)

        ssm_doc = ssm_testing.SSMTester(
            ssm_client=ssm_client,
            doc_filename=os.path.join(
                DOC_DIR, 'Documents/npark-encryptrootvolume.json'),
            doc_name=SSM_DOC_NAME,
            doc_type='Automation')

        test_cf_stack = ssm_testing.CFNTester(
            cfn_client=cfn_client,
            template_filename=os.path.abspath(
                os.path.join(
                    DOC_DIR,
                    "Tests/CloudFormationTemplates/TestTemplate.yml")),
            stack_name=TEST_CFN_STACK_NAME)

        LOGGER.info('Creating Test Stack')
        LOGGER.info('AMI:' + LINUX_AMI_ID)
        LOGGER.info('Instance Type:' + LINUX_INSTANCE_TYPE)
        test_cf_stack.create_stack([{
            'ParameterKey': 'AMI',
            'ParameterValue': LINUX_AMI_ID
        }, {
            'ParameterKey': 'INSTANCETYPE',
            'ParameterValue': LINUX_INSTANCE_TYPE
        }, {
            'ParameterKey':
            'UserARN',
            'ParameterValue':
            sts_client.get_caller_identity().get('Arn')
        }])
        LOGGER.info('Test Stack has been created')

        # Verify role exists
        role_arn = test_cf_stack.stack_outputs['AutomationAssumeRoleARN']
        verify_role_created(role_arn)
        try:
            LOGGER.info("Creating automation document")
            self.assertEqual(ssm_doc.create_document(), 'Active')

            instance_id = test_cf_stack.stack_outputs['InstanceId']
            kms_key_id = test_cf_stack.stack_outputs['KmsKeyId']

            execution = ssm_doc.execute_automation(
                params={
                    'instanceId': [instance_id],
                    'kmsKeyId': [kms_key_id],
                    'automationAssumeRole': [role_arn]
                })
            self.assertEqual(
                ssm_doc.automation_execution_status(ssm_client, execution,
                                                    False), 'Success')

            LOGGER.info('Encryption of root volume has been completed')

            response = ssm_doc.automation_execution_status(
                ssm_client, execution)
            if response == 'Success':
                response = ec2_client.describe_instances(
                    InstanceIds=[instance_id], DryRun=False)
                rootdevicename = response['Reservations'][0]['Instances'][0][
                    'RootDeviceName']

                response = ec2_client.describe_volumes(Filters=[
                    {
                        'Name': 'attachment.instance-id',
                        'Values': [instance_id],
                    },
                    {
                        'Name': 'attachment.device',
                        'Values': [rootdevicename],
                    },
                ],
                                                       DryRun=False)
                is_encrypted = response['Volumes'][0]['Encrypted']
                self.assertEqual(is_encrypted, True)
                if is_encrypted:
                    LOGGER.info("All Tests Successful, will clean up now")
                else:
                    LOGGER.info(
                        "FAIL: root volume is NOT encrypted, will clean up now"
                    )

        finally:
            try:
                ssm_doc.destroy()
            except Exception:
                pass

            test_cf_stack.delete_stack()
    def test_update_document(self):
        cfn_client = boto3.client('cloudformation', region_name=REGION)
        ssm_client = boto3.client('ssm', region_name=REGION)

        test_cf_stack = ssm_testing.CFNTester(
            cfn_client=cfn_client,
            template_filename=os.path.abspath(os.path.join(
                DOC_DIR,
                "Tests/CloudFormationTemplates/TestNotAssociated.yml")),
            stack_name=TEST_CFN_STACK_NAME
        )

        LOGGER.info('Creating Test Stack')
        test_cf_stack.create_stack([
            {
                'ParameterKey': 'AMI',
                'ParameterValue': LINUX_AMI_ID
            },
            {
                'ParameterKey': 'INSTANCETYPE',
                'ParameterValue': LINUX_INSTANCE_TYPE
            },
            {
                'ParameterKey': 'UserARN',
                'ParameterValue': sts_client.get_caller_identity().get('Arn')
            }
        ])
        LOGGER.info('Test Stack has been created')

        # Verify role exists
        role_arn = test_cf_stack.stack_outputs['AutomationAssumeRoleARN']
        verify_role_created(role_arn)

        # Crete the lambda
        ssm_doc = ssm_testing.SSMTester(
            ssm_client=ssm_client,
            doc_filename=os.path.join(DOC_DIR,
                                      'Output/aws-AttachIAMToInstance.json'),
            doc_name=SSM_DOC_NAME,
            doc_type='Automation'
        )

        LOGGER.info("Creating automation document")
        self.assertEqual(ssm_doc.create_document(), 'Active')

        try:
            instance_id = test_cf_stack.stack_outputs['InstanceId']
            role_name = test_cf_stack.stack_outputs['AutomationAssumeRoleName']

            execution = ssm_doc.execute_automation(
                params={'InstanceId': [instance_id],
                        'RoleName': [role_name],
                        'AutomationAssumeRole': [role_arn]})
            self.assertEqual(ssm_doc.automation_execution_status(ssm_client, execution, False), 'Success')

            LOGGER.info('automation executed successfully')
            response = ssm_client.get_automation_execution(AutomationExecutionId=execution)
            str_payload = response['AutomationExecution']['Outputs']['attachIAMToInstance.Payload'][0]
            payload = json.loads(str_payload)
            association_id = payload['AssociationId']
            profile_name = payload['InstanceProfileName']

            self.assertEqual(role_name, payload['RoleName'])

            LOGGER.info('Verify that the instance has a profile')
            profile_instance_response = ec2_client.describe_iam_instance_profile_associations(Filters=[{
                'Name': 'instance-id',
                'Values': [instance_id]
            }])
            self.assertEqual(len(profile_instance_response['IamInstanceProfileAssociations']), 1)
            iam_instance_profile_association = profile_instance_response['IamInstanceProfileAssociations'][0]
            self.assertEqual(len(profile_instance_response['IamInstanceProfileAssociations']), 1)
            self.assertEqual(iam_instance_profile_association['AssociationId'], association_id)
            self.assertEqual(iam_instance_profile_association['InstanceId'], instance_id)

            LOGGER.info('Verify that the instance profile has the role')
            instance_profile_response = iam_client.get_instance_profile(
                InstanceProfileName=profile_name
            )
            self.assertEqual(instance_profile_response['InstanceProfile']['InstanceProfileName'], profile_name)

            role_count = 0
            for role in instance_profile_response['InstanceProfile']['Roles']:
                if role['RoleName'] == role_name:
                    role_count += 1

            self.assertEqual(role_count, 1)

            LOGGER.info('Tests successful. Cleaning up')
            remove_role_from_instance_profile(profile_name, role_name)
            delete_instance_profile(profile_name)
            disassociate_iam_instance_profile(association_id)

            LOGGER.info('Clean up successful')
        finally:
            try:
                ssm_doc.destroy()
            except Exception:
                pass

            test_cf_stack.delete_stack()
Esempio n. 19
0
    def test_update_document(self):
        cfn_client = boto3.client('cloudformation', region_name=REGION)
        ssm_client = boto3.client('ssm', region_name=REGION)

        ssm_doc = ssm_testing.SSMTester(
            ssm_client=ssm_client,
            doc_filename=os.path.join(DOC_DIR,
                                      'Output/aws-AttachEBSVolume.json'),
            doc_name=SSM_DOC_NAME,
            doc_type='Automation'
        )

        test_cf_stack = ssm_testing.CFNTester(
            cfn_client=cfn_client,
            template_filename=os.path.abspath(os.path.join(
                DOC_DIR,
                "Tests/CloudFormationTemplates/TestTemplate.yml")),
            stack_name=TEST_CFN_STACK_NAME
        )

        LOGGER.info('Creating Test Stack')
        test_cf_stack.create_stack([
            {
                'ParameterKey': 'AMI',
                'ParameterValue': LINUX_AMI_ID
            },
            {
                'ParameterKey': 'INSTANCETYPE',
                'ParameterValue': LINUX_INSTANCE_TYPE
            },
            {
                'ParameterKey': 'UserARN',
                'ParameterValue': sts_client.get_caller_identity().get('Arn')
            }
        ])
        LOGGER.info('Test Stack has been created')

        # Verify role exists
        role_arn = test_cf_stack.stack_outputs['AutomationAssumeRoleARN']
        verify_role_created(role_arn)

        try:
            LOGGER.info("Creating automation document")
            self.assertEqual(ssm_doc.create_document(), 'Active')

            device = 'xvdh'
            instance_id = test_cf_stack.stack_outputs['InstanceId']
            volume_id = test_cf_stack.stack_outputs['VolumeId']

            execution = ssm_doc.execute_automation(
                params={'Device': [device],
                        'InstanceId': [instance_id],
                        'VolumeId': [volume_id],
                        'AutomationAssumeRole': [role_arn]})
            self.assertEqual(ssm_doc.automation_execution_status(ssm_client, execution, False), 'Success')

            LOGGER.info('Volume is attached, now verifying')

            ec2 = boto3.resource('ec2')
            volume = ec2.Volume(volume_id)

            # Test instance exists in volume
            self.assertGreater(len(volume.attachments), 0)
            self.assertEqual(volume.attachments[0]['InstanceId'], instance_id)

            volume.detach_from_instance()
        finally:
            try:
                ssm_doc.destroy()
            except Exception:
                pass

            test_cf_stack.delete_stack()
Esempio n. 20
0
    def test_update_document(self):
        cfn_client = boto3.client('cloudformation', region_name=REGION)
        ssm_client = boto3.client('ssm', region_name=REGION)

        ssm_doc = ssm_testing.SSMTester(ssm_client=ssm_client,
                                        doc_filename=os.path.join(
                                            DOC_DIR,
                                            'Output/aws-ResizeInstance.json'),
                                        doc_name=SSM_DOC_NAME,
                                        doc_type='Automation')

        test_cf_stack = ssm_testing.CFNTester(
            cfn_client=cfn_client,
            template_filename=os.path.abspath(
                os.path.join(
                    DOC_DIR,
                    "Tests/CloudFormationTemplates/TestTemplate.yml")),
            stack_name=TEST_CFN_STACK_NAME)

        LOGGER.info('Creating Test Stack')
        LOGGER.info('AMI:' + LINUX_AMI_ID)
        LOGGER.info('Instance Type:' + LINUX_INSTANCE_TYPE)
        test_cf_stack.create_stack([{
            'ParameterKey': 'AMI',
            'ParameterValue': LINUX_AMI_ID
        }, {
            'ParameterKey': 'INSTANCETYPE',
            'ParameterValue': LINUX_INSTANCE_TYPE
        }, {
            'ParameterKey':
            'UserARN',
            'ParameterValue':
            sts_client.get_caller_identity().get('Arn')
        }])
        LOGGER.info('Test Stack has been created')

        # Verify role exists
        role_arn = test_cf_stack.stack_outputs['AutomationAssumeRoleARN']
        verify_role_created(role_arn)
        try:
            LOGGER.info("Creating automation document")
            self.assertEqual(ssm_doc.create_document(), 'Active')

            instance_id = test_cf_stack.stack_outputs['InstanceId']

            execution = ssm_doc.execute_automation(
                params={
                    'InstanceId': [instance_id],
                    'InstanceType': [NEW_INSTANCE_TYPE],
                    'AutomationAssumeRole': [role_arn]
                })
            self.assertEqual(
                ssm_doc.automation_execution_status(ssm_client, execution,
                                                    False), 'Success')

            LOGGER.info('Instance has changed, Verifying instance')

            ec2 = boto3.resource('ec2')
            instance = ec2.Instance(instance_id)

            LOGGER.info("Current instance Type:" + instance.instance_type)

            # Test instance exists in volume
            self.assertEqual(instance.instance_type, NEW_INSTANCE_TYPE)
            self.assertEqual(instance.state.get('Code'), 16)
            LOGGER.info("All Tests Successful, will clean up now")
        finally:
            try:
                ssm_doc.destroy()
            except Exception:
                pass

            test_cf_stack.delete_stack()
Esempio n. 21
0
    def test_document():
        """Verify correct deployment and use of document."""
        cfn_client = boto3.client('cloudformation', region_name=REGION)
        ec2_client = boto3.client('ec2', region_name=REGION)
        ssm_client = boto3.client('ssm', region_name=REGION)

        ssm_doc = ssm_testing.SSMTester(
            ssm_client=ssm_client,
            doc_filename=os.path.join(DOC_DIR,
                                      'Documents',
                                      'aws-TerminateEC2InstanceWithApproval.json'),
            doc_name=SSM_DOC_NAME,
            doc_type='Automation'
        )

        test_cf_stack = ssm_testing.CFNTester(
            cfn_client=cfn_client,
            template_filename=os.path.join(DOC_DIR,
                                           'Tests',
                                           'CloudFormationTemplates',
                                           'TwoInstances.yml'),
            stack_name=INSTANCE_CFN_STACK_NAME
        )

        automation_role = ssm_doc.get_automation_role(
            boto3.client('sts', region_name=REGION),
            boto3.client('iam', region_name=REGION),
            SERVICE_ROLE_NAME
        )

        LOGGER.info('Starting 2 instances for testing')
        test_cf_stack.create_stack([
            {
                'ParameterKey': 'AMI',
                'ParameterValue': AMIID
            },
            {
                'ParameterKey': 'INSTANCETYPE',
                'ParameterValue': INSTANCE_TYPE
            }
        ])
        try:
            LOGGER.info('Creating automation document')
            assert ssm_doc.create_document() == 'Active', ('Document not '
                                                           'created '
                                                           'successfully')

            LOGGER.info('Running automation to terminate multiple instances '
                        '(using defined role)')
            instances_1_2 = [test_cf_stack.stack_outputs['Instance0Id'],
                             test_cf_stack.stack_outputs['Instance1Id']]

            LOGGER.info('Verifying all instances are running')
            describe_res = ec2_client.describe_instance_status(
                InstanceIds=instances_1_2,
                IncludeAllInstances=True
            )
            assert all(d['InstanceState']['Name'] == 'running' for d in describe_res['InstanceStatuses']) is True, (  # noqa pylint: disable=line-too-long
                'Instances not started')

            LOGGER.info("Executing SSM automation document to terminate instances")

            user_arn = boto3.client('sts', region_name=REGION).get_caller_identity().get('Arn')
            sns_topic_arn = test_cf_stack.stack_outputs['SNSTopicArn']

            LOGGER.info("User ARN for approval: " + user_arn)
            LOGGER.info("SNS Topic ARN for approval: " + sns_topic_arn)

            execution = ssm_doc.execute_automation(
                params={'InstanceId': instances_1_2,
                        'AutomationAssumeRole': [automation_role],
                        'Approvers': [user_arn],
                        'SNSTopicArn': [sns_topic_arn]})

            # since this automation requires approval to continue, the correct status at this point should be 'Waiting'
            assert ssm_doc.automation_execution_status(ssm_client, execution, False) == 'Waiting', \
                'Automation not waiting for approval'

            LOGGER.info('Approving continuation of execution')
            ssm_client.send_automation_signal(
                AutomationExecutionId=execution,
                SignalType='Approve'
            )

            LOGGER.info('Verifying automation executions have concluded '
                        'successfully')
            assert ssm_doc.automation_execution_status(
                ssm_client,
                execution
            ) == 'Success', 'Instance not terminated correctly'

            LOGGER.info('Ensuring instances have terminated')
            describe_res = ec2_client.describe_instance_status(
                InstanceIds=instances_1_2,
                IncludeAllInstances=True
            )
            assert all(d['InstanceState']['Name'] == 'terminated' for d in describe_res['InstanceStatuses']) is True

        finally:
            test_cf_stack.delete_stack()
            ssm_doc.destroy()
Esempio n. 22
0
    def test_enter_standby_document(self):

        available_subnets = vpcUtil.find_default_subnets()

        # ensure the account being used has a default VPC.
        assert len(
            available_subnets) > 0, "No default subnet available for testing"

        ssm_doc = ssm_testing.SSMTester(
            ssm_client=ssm_client,
            doc_filename=os.path.join(
                DOC_DIR, 'Documents/aws-ASGEnterStandbyWithApproval.json'),
            doc_name=ENTER_STANDBY_SSM_DOC_NAME,
            doc_type='Automation')

        test_cf_stack = ssm_testing.CFNTester(
            cfn_client=cfn_client,
            template_filename=os.path.abspath(
                os.path.join(DOC_DIR,
                             'Tests/CloudFormationTemplates/ASG.yml')),
            stack_name=ENTER_STANDBY_CFN_STACK_NAME)

        automation_role = ssm_doc.get_automation_role(sts_client, iam_client,
                                                      SERVICE_ROLE_NAME)

        LOGGER.info('Creating AutoScaling Group for testing')
        stack_param = {
            'AMI': AMI_ID,
            'Subnets': available_subnets[0].id,
            'InstanceType': INSTANCE_TYPE
        }
        test_cf_stack.create_stack([{
            'ParameterKey': key,
            'ParameterValue': value
        } for key, value in stack_param.iteritems()])

        asg_name = test_cf_stack.stack_outputs["ASGName"]

        LOGGER.info("Waiting for an instance to become ready...")
        working_instance = asg_wait_for_running_instance(asg_name=asg_name,
                                                         number_of_instance=1,
                                                         max_wait_sec=300)[0]

        try:

            LOGGER.info("Creating automation document")
            assert ssm_doc.create_document(
            ) == 'Active', 'Document not created successfully'

            user_arn = sts_client.get_caller_identity().get('Arn')
            sns_topic_arn = test_cf_stack.stack_outputs['SNSTopicArn']

            LOGGER.info("User ARN for approval: " + user_arn)
            LOGGER.info("SNS Topic ARN for approval: " + sns_topic_arn)

            LOGGER.info(
                "Executing SSM automation document to set instance to standby mode on {}"
                .format(working_instance))
            execution = ssm_doc.execute_automation(
                params={
                    'InstanceId': [working_instance],
                    'LambdaRoleArn': [automation_role],
                    'AutomationAssumeRole': [automation_role],
                    'Approvers': [user_arn],
                    'SNSTopicArn': [sns_topic_arn]
                })

            # Send approval signal

            # Since this automation requires approval to continue, the correct status at this point should be 'Waiting'
            assert ssm_doc.automation_execution_status(ssm_client, execution, False) == 'Waiting', \
                'Automation not waiting for approval'

            LOGGER.info('Approving continuation of execution')
            ssm_client.send_automation_signal(AutomationExecutionId=execution,
                                              SignalType='Approve')

            # Collect asg instance lifecycle change.

            asg_status_changes = []
            asg_status_ignores = ["EnteringStandby", "Pending"]

            # Status callback to collect any necessary data
            def status_callback(_):
                collect_asg_status_change(asg_name, working_instance,
                                          asg_status_ignores,
                                          asg_status_changes)

            # Wait for SSM to finish while collecting value change (callback).
            result = ssm_doc.automation_execution_status(
                ssm_client, execution, status_callback=status_callback)

            # Verify instance status change.
            LOGGER.info("ASG status change sequence: " +
                        str(asg_status_changes))
            expected_status_change_sequence = ["InService", "Standby"]
            is_status_change_expected = asg_status_changes == expected_status_change_sequence
            assert is_status_change_expected, 'ASG instant lifecycle did not match expected.'

            LOGGER.info(
                'Verifying automation executions have concluded successfully')
            assert result == 'Success', 'Document did not complete'

        finally:
            try:
                LOGGER.info(
                    'Taking instance out of standby (required for CF stack teardown)'
                )
                as_client.exit_standby(InstanceIds=[working_instance],
                                       AutoScalingGroupName=asg_name)

            finally:
                test_cf_stack.delete_stack()
                ssm_doc.destroy()
Esempio n. 23
0
    def test_update_document(self):
        cfn_client = boto3.client('cloudformation', region_name=REGION)
        ssm_client = boto3.client('ssm', region_name=REGION)

        ssm_doc = ssm_testing.SSMTester(ssm_client=ssm_client,
                                        doc_filename=os.path.join(
                                            DOC_DIR,
                                            'Output/aws-DeleteSnapshot.json'),
                                        doc_name=SSM_DOC_NAME,
                                        doc_type='Automation')

        test_cf_stack = ssm_testing.CFNTester(
            cfn_client=cfn_client,
            template_filename=os.path.abspath(
                os.path.join(
                    DOC_DIR,
                    "Tests/CloudFormationTemplates/TestTemplate.yml")),
            stack_name=TEST_CFN_STACK_NAME)

        LOGGER.info('Creating Test Stack')
        test_cf_stack.create_stack([{
            'ParameterKey':
            'UserARN',
            'ParameterValue':
            sts_client.get_caller_identity().get('Arn')
        }])
        LOGGER.info('Test Stack has been created')

        # Verify role exists
        role_arn = test_cf_stack.stack_outputs['AutomationAssumeRoleARN']
        verify_role_created(role_arn)

        LOGGER.info("Creating automation document")
        self.assertEqual(ssm_doc.create_document(), 'Active')

        volume_id = test_cf_stack.stack_outputs['VolumeId']

        # Now create the snapshot
        snapshot = self.create_snapshot(volume_id)

        try:
            execution = ssm_doc.execute_automation(
                params={
                    'SnapshotId': [snapshot.snapshot_id],
                    'AutomationAssumeRole': [role_arn]
                })
            self.assertEqual(
                ssm_doc.automation_execution_status(ssm_client, execution,
                                                    False), 'Success')

            LOGGER.info('Snapshot is deleted: ' + volume_id)

            snapshot_response = ec2_client.describe_snapshots(
                Filters=[{
                    'Name': 'volume-id',
                    'Values': [volume_id]
                }])

            # Test instance exists in volume
            snapshots = snapshot_response['Snapshots']

            self.assertEqual(len(snapshots), 0)

            LOGGER.info('Verified snapshot is deleted')
        finally:
            try:
                ssm_doc.destroy()
            except Exception:
                pass

            self.delete_snapshot(snapshot.snapshot_id)

            test_cf_stack.delete_stack()
    def test_update_document(self):
        cfn_client = boto3.client('cloudformation', region_name=REGION)
        ssm_client = boto3.client('ssm', region_name=REGION)

        ssm_doc = ssm_testing.SSMTester(ssm_client=ssm_client,
                                        doc_filename=os.path.join(
                                            DOC_DIR,
                                            'Documents/aws-CreateImage.json'),
                                        doc_name=SSM_DOC_NAME,
                                        doc_type='Automation')

        test_cf_stack = ssm_testing.CFNTester(
            cfn_client=cfn_client,
            template_filename=os.path.abspath(
                os.path.join(
                    DOC_DIR,
                    "Tests/CloudFormationTemplates/TestTemplate.yml")),
            stack_name=TEST_CFN_STACK_NAME)

        LOGGER.info('Creating Test Stack')
        LOGGER.info('AMI:' + LINUX_AMI_ID)
        LOGGER.info('Instance Type:' + LINUX_INSTANCE_TYPE)
        test_cf_stack.create_stack([{
            'ParameterKey': 'AMI',
            'ParameterValue': LINUX_AMI_ID
        }, {
            'ParameterKey': 'INSTANCETYPE',
            'ParameterValue': LINUX_INSTANCE_TYPE
        }, {
            'ParameterKey':
            'UserARN',
            'ParameterValue':
            sts_client.get_caller_identity().get('Arn')
        }])
        LOGGER.info('Test Stack has been created')

        # Verify role exists
        role_arn = test_cf_stack.stack_outputs['AutomationAssumeRoleARN']
        verify_role_created(role_arn)
        try:
            LOGGER.info("Creating automation document")
            self.assertEqual(ssm_doc.create_document(), 'Active')

            instance_id = test_cf_stack.stack_outputs['InstanceId']

            execution = ssm_doc.execute_automation(params={
                'InstanceId': [instance_id],
                'AutomationAssumeRole': [role_arn]
            })
            self.assertEqual(
                ssm_doc.automation_execution_status(ssm_client, execution,
                                                    False), 'Success')

            LOGGER.info('Create a new Amazon Machine Image has been initiated')

            ec2_resource = boto3.resource('ec2')
            ec2client = boto3.client('ec2')
            instance = ec2_resource.Instance(instance_id)

            imageName = instance_id + '_' + execution
            describeImage = ec2client.describe_images(
                Filters=[{
                    'Name': 'name',
                    'Values': [imageName],
                }])
            ImageId = describeImage['Images'][0]['ImageId']

            # Test Amazon Machine Image exists
            waiter = ec2client.get_waiter('image_available')
            waiter.wait(ImageIds=[ImageId])
            LOGGER.info("All Tests Successful, will clean up now")

            #Get SnapshotId from Amazon Machine Image
            imageData = ec2_resource.Image(ImageId)
            SnapshotId = imageData.block_device_mappings[0]['Ebs'][
                'SnapshotId']
            LOGGER.info(
                "Got the SnapshotId from the Amazon Machine Image for the clean up process."
            )
        finally:
            try:
                ssm_doc.destroy()
                ec2client.deregister_image(ImageId=ImageId)
                ec2client.delete_snapshot(SnapshotId=SnapshotId)
            except Exception:
                pass

            test_cf_stack.delete_stack()