We have a requirement that access to an AWS environment is enabled on demand, and said access disabled afterwards. In each case (up / down), this means we will do two things:
- Enable access- Turn on the Bastion instance
- Modify the Security Groups of the EC2 instances, so a SG allowing RDP access is added to the list of associated SGs.
 
- Disable access- Turn off the Bastion
- Modify the SGs of the EC2 instances, to remove the SG that grants RDP access.
 
The script is pretty straight forwards, but there is not much error handling / logging going on.
The script is designed to run either from local machine or in AWS lambda, without modification (providing environment variables, credentials/permissions setup correctly).
import boto3, os 
region = os.environ['PFregion'] 
security_group_id = os.environ['PFSG'] 
bastion_iid = os.environ['PFbastion_iid'] 
aws_profile = 'profile_name'
def lambda_handler(event, context):
    if (__name__ == "__main__"):
        print 'using ENV creds'     
        session = boto3.Session(profile_name=aws_profile)
        ec2_client = session.client('ec2', region_name=region)      
        ec2_resx = session.resource('ec2', region_name=region)
    else:
        ec2_client = boto3.client('ec2', region_name=region)
        ec2_resx = boto3.resource('ec2', region_name=region)
    all_instances = ec2_resx.instances.filter()
    if (event['up'].lower() == 'true'):
    # Start the Bastion 
        print 'inside up'
        ec2_client.start_instances(
            InstanceIds = [bastion_iid,],
            AdditionalInfo = 'Called from Lambda function to Up access',
            #DryRun = event['dry_run'], 
        )
        # Modify the SGs accordingly 
        for instance in all_instances:
            all_sg_ids = [sg['GroupId'] for sg in instance.security_groups]
            if security_group_id not in all_sg_ids:
                print 'SG not assigned currently'
                all_sg_ids.append(security_group_id)
                instance.modify_attribute(Groups=all_sg_ids)
    else:
        # Stop the Bastion 
        print 'inside down'
        ec2_client.stop_instances(
            InstanceIds = [bastion_iid,],           
            #DryRun = bool(event['dry_run']), 
        )
        # Remove the SG rules
        for instance in all_instances:
            all_sg_ids = [sg['GroupId'] for sg in instance.security_groups]
            if security_group_id in all_sg_ids:
                print 'SG IS assigned currently'
                all_sg_ids.remove(security_group_id)
                instance.modify_attribute(Groups=all_sg_ids)
if __name__ == '__main__':
    event = { "up" : "true", "desc" : "this is a description field", "dry_run" : "false" }
    #print event
    lambda_handler(event, None)

