in lambda/source/bastion/bastionpostscriptlambda.py [0:0]
def setup_bastion(event, context, stack_name):
try:
print("Fetching Instance_ID by searching for tag Name:EKSBastion")
BastionInstanceID = ''
ec2 = boto3.resource('ec2')
# Get information for all running instances
running_instances = ec2.instances.filter(Filters=[{
'Name': 'instance-state-name',
'Values': ['running']}])
ec2info = defaultdict()
for instance in running_instances:
for tag in instance.tags:
if 'Name' in tag['Key']:
name = tag['Value']
if 'EKSBastion' in tag['Value']:
BastionInstanceID = instance.instance_id
print("BastionInstanceID :" + BastionInstanceID)
print("Creating ssm parameter bastionID")
ssm_client = boto3.client('ssm')
# create a ssm parameter
response = ssm_client.put_parameter(
Name='bastionID',
Description='InstanceID of the bastion host to manage EKS',
Value=BastionInstanceID,
Type='String',
Overwrite=True,
Tier='Standard'
)
### Get Instance Profile from BastionInstanceID
instance = ec2.Instance(BastionInstanceID)
print("EKS bastion instance profile metadata")
print(instance)
print(instance.iam_instance_profile)
bastion_instance_profile_arn = instance.iam_instance_profile['Arn']
print("EKS bastion instance profile ARN")
print(bastion_instance_profile_arn)
bastion_instance_profile_name = bastion_instance_profile_arn.split("instance-profile/")[len(bastion_instance_profile_arn.split("instance-profile/"))-1]
print("bastion_instance_profile_name")
print(bastion_instance_profile_name)
iam = boto3.resource('iam')
instance_profile = iam.InstanceProfile(bastion_instance_profile_name)
print("List of instance profile role attributes")
print(instance_profile.roles_attribute)
print("first element of the list")
print(instance_profile.roles_attribute[0]['RoleName'])
eks_bastion_role = instance_profile.roles_attribute[0]['RoleName']
##
## Appending Bastion IAM Role to KMS key##
kms_policy_arns = []
print("ARN for Bastion IAM Role")
print(instance_profile.roles_attribute[0]['Arn'])
kms_policy_arns.append(instance_profile.roles_attribute[0]['Arn'])
iam = boto3.client('iam')
policy_arn = os.environ['CustomBastionPolicyARN']
response = iam.attach_role_policy (
RoleName=eks_bastion_role,
PolicyArn=policy_arn
)
### Done with Instance Profile
responseBody['Status']=SUCCESS
json_responseBody = json.dumps(responseBody)
print("Completed assigning Role stack response success:\n" + json_responseBody)
#send(event, context, SUCCESS, outputData)
## Added for Mongo ##
print("Creating a ingres Rule for MongoDB security group to allow traffic from EKS \n")
ec2_client = boto3.client('ec2')
describe_security_groups_response = ec2_client.describe_security_groups(
Filters=[
{
'Name': 'tag-key',
'Values': [
'aws:cloudformation:logical-id',
]
},
],
MaxResults=123
)
# Create KMS Keys and attach the IAM policy with required ARNs
sts = boto3.client('sts')
identity = sts.get_caller_identity()
# Inputs
rds_role_name = event['ResourceProperties']['InstanceProfileRoleName']
# role arns that need kms access
rds_role_arn = 'arn:aws:iam::' + identity['Account'] + ':role/' + rds_role_name
cfn_user_arn = identity['Arn']
root_arn = 'arn:aws:iam::' + identity['Account'] + ':root'
kms_policy_arns.append(rds_role_arn)
kms_policy_arns.append(cfn_user_arn)
kms_policy_arns.append(root_arn)
print('user identity: ' + json.dumps(identity))
kms_policy = {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Enable IAM User Permissions for KMS Key",
"Effect": "Allow",
"Principal": {
"AWS": kms_policy_arns
},
"Action": "kms:*",
"Resource": "*"
}
]
}
client_kms = boto3.client('kms')
response = client_kms.create_key(
Description='KMS key to decyrpt the QuickStart credentials',
KeyUsage='ENCRYPT_DECRYPT',
Origin='AWS_KMS',
Policy=json.dumps(kms_policy)
)
print ('Created KMS Key with ARN: ' + response['KeyMetadata']['Arn']);
print ('Created KMS Key with KeyID : ' + response['KeyMetadata']['KeyId']);
kmskeyid = response['KeyMetadata']['KeyId']
# You need to have user type on the password as the parameter in CFN and then pass the password to Lambda using ResourceProperties
# More help @ https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources.html
# You can pass value as event data from cfn and then get it from event object e.g. event['ResourceProperties']['Password']
rds_password = event['ResourceProperties']['RDSPassword']
print("Creating ssm parameter RDS Password")
ssm_client = boto3.client('ssm')
# create a ssm parameter
response = ssm_client.put_parameter(
Name='SSDBAdminPassword',
Description='Password of the RDS DB Server Admin',
Value=rds_password,
KeyId=kmskeyid,
Type='SecureString',
Overwrite=True,
Tier='Standard'
)
# You need to have user type on the password as the parameter in CFN and then pass the password to Lambda using ResourceProperties
# More help @ https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources.html
# You can pass value as event data from cfn and then get it from event object e.g. event['ResourceProperties']['Password']
mongo_password = event['ResourceProperties']['MongoDBPassword']
print("Creating ssm parameter Mongo Password")
ssm_client = boto3.client('ssm')
# create a ssm parameter
response = ssm_client.put_parameter(
Name='MongoDBAdminPassword',
Description='Password of the Mongo DB Server Admin',
Value=mongo_password,
KeyId=kmskeyid,
Type='SecureString',
Overwrite=True,
Tier='Standard'
)
print("Finished creating ssm parameters for Mongo and RDS Password")
security_group_id = ''
for security_group in describe_security_groups_response['SecurityGroups']:
if security_group['Tags']:
for tag_pair in security_group['Tags']:
print('tag_pair[Value]: ' + tag_pair['Value'])
if 'MongoDBServerSecurityGroup' in tag_pair['Value']:
security_group_id = security_group['GroupId']
eks_source_security_group_id = os.environ['EKSSourceSecGroupId']
bastion_source_security_group_id = os.environ['BastionSecurityGroupID']
print("\n EKS Source Security Group from enviroment variable: " + eks_source_security_group_id)
print("\n Bastion Source Security Group from environment variable: " + bastion_source_security_group_id)
print("\n MongoDB Security Group that contains the ingress rule: " + security_group_id)
response = ec2_client.authorize_security_group_ingress(
GroupId=security_group_id,
IpPermissions=[
{
'FromPort': 27017,
'IpProtocol': 'TCP',
'UserIdGroupPairs': [
{
'GroupId': eks_source_security_group_id,
},
],
'ToPort': 27030,
},
],
)
response = ec2_client.authorize_security_group_ingress(
GroupId=security_group_id,
IpPermissions=[
{
'FromPort': 27017,
'IpProtocol': 'TCP',
'UserIdGroupPairs': [
{
'GroupId': bastion_source_security_group_id,
},
],
'ToPort': 27030,
},
],
)
print("Mongodb Security group" + security_group_id + "has been updated by adding ingress from security groups" + eks_source_security_group_id + " and " + bastion_source_security_group_id)
print("Completed setting up the bastion.")
###
return json_responseBody
except Exception as e:
print("Failed to set up the resources required by bastion instance to run scripts. Error: " + str(e))