This commit is contained in:
263
lambda_function_addtag.py
Normal file
263
lambda_function_addtag.py
Normal file
@@ -0,0 +1,263 @@
|
||||
import boto3
|
||||
import re
|
||||
|
||||
def get_tag(tags, key):
|
||||
for tag in tags:
|
||||
if tag['Key'] == key:
|
||||
return tag['Value']
|
||||
return None
|
||||
|
||||
def add_output(output, resource_type, resource_id, tenant_value, status, **kwargs):
|
||||
entry = {
|
||||
"ResourceType": resource_type,
|
||||
"ResourceId": resource_id,
|
||||
"Tenant": tenant_value,
|
||||
"Status": status
|
||||
}
|
||||
entry.update(kwargs)
|
||||
output.append(entry)
|
||||
|
||||
def lambda_handler(event, context):
|
||||
ec2 = boto3.client('ec2')
|
||||
kms = boto3.client('kms', region_name='us-east-1')
|
||||
route53 = boto3.client('route53')
|
||||
output = []
|
||||
|
||||
# 1. AMIs
|
||||
images = ec2.describe_images(Owners=['self'])['Images']
|
||||
for image in images:
|
||||
already_tagged = any(tag['Key'] == 'Tenant' for tag in image.get('Tags', []))
|
||||
name = image.get('Name', '')
|
||||
desc = image.get('Description', '')
|
||||
match = re.search(r'i-[0-9a-f]+', name) or re.search(r'i-[0-9a-f]+', desc)
|
||||
instance_id = match.group(0) if match else None
|
||||
tenant = None
|
||||
|
||||
if instance_id:
|
||||
try:
|
||||
reservations = ec2.describe_instances(InstanceIds=[instance_id])['Reservations']
|
||||
if reservations and reservations[0]['Instances']:
|
||||
tags = reservations[0]['Instances'][0].get('Tags', [])
|
||||
tenant = get_tag(tags, 'Tenant')
|
||||
except Exception as e:
|
||||
add_output(output, "AMI", image['ImageId'], tenant or "TagNotExists", f"InstanceDescribeError: {str(e)}", SourceID=instance_id)
|
||||
continue
|
||||
|
||||
if already_tagged:
|
||||
add_output(output, "AMI", image['ImageId'], tenant or "TagNotExists", "AlreadyTagged", SourceID=instance_id)
|
||||
continue
|
||||
|
||||
if not instance_id:
|
||||
add_output(output, "AMI", image['ImageId'], "TagNotExists", "NoInstanceIdInName")
|
||||
continue
|
||||
|
||||
if tenant:
|
||||
try:
|
||||
ec2.create_tags(Resources=[image['ImageId']], Tags=[{'Key': 'Tenant', 'Value': tenant}])
|
||||
add_output(output, "AMI", image['ImageId'], tenant, "TagAdded", SourceID=instance_id)
|
||||
except Exception as e:
|
||||
add_output(output, "AMI", image['ImageId'], tenant, f"TagError: {str(e)}", SourceID=instance_id)
|
||||
else:
|
||||
add_output(output, "AMI", image['ImageId'], "TagNotExists", "NoTenantTagOnInstance", SourceID=instance_id)
|
||||
|
||||
# 2. Volumes EBS
|
||||
volumes = ec2.describe_volumes()['Volumes']
|
||||
for vol in volumes:
|
||||
already_tagged = any(tag['Key'] == 'Tenant' for tag in vol.get('Tags', []))
|
||||
attachments = vol.get('Attachments', [])
|
||||
instance_id = attachments[0]['InstanceId'] if attachments and attachments[0].get('InstanceId') else None
|
||||
tenant = None
|
||||
|
||||
# Try to get Tenant tag from AMI if attached to an instance with an AMI
|
||||
if instance_id:
|
||||
# Try to get AMI from instance
|
||||
try:
|
||||
reservations = ec2.describe_instances(InstanceIds=[instance_id])['Reservations']
|
||||
if reservations and reservations[0]['Instances']:
|
||||
instance = reservations[0]['Instances'][0]
|
||||
ami_id = instance.get('ImageId')
|
||||
if ami_id:
|
||||
# Get the Tenant tag from the AMI if it exists
|
||||
images = ec2.describe_images(ImageIds=[ami_id])['Images']
|
||||
if images:
|
||||
tenant = get_tag(images[0].get('Tags', []), 'Tenant')
|
||||
# Fallback: get Tenant tag from instance itself if AMI doesn't have it
|
||||
if not tenant:
|
||||
tenant = get_tag(instance.get('Tags', []), 'Tenant')
|
||||
except Exception as e:
|
||||
add_output(output, "Volume", vol['VolumeId'], tenant or "TagNotExists", f"InstanceDescribeError: {str(e)}", SourceID=instance_id)
|
||||
continue
|
||||
|
||||
if already_tagged:
|
||||
add_output(output, "Volume", vol['VolumeId'], tenant or "TagNotExists", "AlreadyTagged", SourceID=instance_id)
|
||||
continue
|
||||
|
||||
if not instance_id:
|
||||
add_output(output, "Volume", vol['VolumeId'], "TagNotExists", "NoInstanceAttachment")
|
||||
continue
|
||||
|
||||
if tenant:
|
||||
try:
|
||||
ec2.create_tags(Resources=[vol['VolumeId']], Tags=[{'Key': 'Tenant', 'Value': tenant}])
|
||||
add_output(output, "Volume", vol['VolumeId'], tenant, "TagAdded", SourceID=instance_id)
|
||||
except Exception as e:
|
||||
add_output(output, "Volume", vol['VolumeId'], tenant, f"TagError: {str(e)}", SourceID=instance_id)
|
||||
else:
|
||||
add_output(output, "Volume", vol['VolumeId'], "TagNotExists", "NoTenantTagOnInstanceOrAMI", SourceID=instance_id)
|
||||
|
||||
# 3. Snapshots EBS
|
||||
snapshots = ec2.describe_snapshots(OwnerIds=['self'])['Snapshots']
|
||||
for snap in snapshots:
|
||||
already_tagged = any(tag['Key'] == 'Tenant' for tag in snap.get('Tags', []))
|
||||
volume_id = snap.get('VolumeId')
|
||||
tenant = None
|
||||
|
||||
if volume_id:
|
||||
try:
|
||||
volumes = ec2.describe_volumes(VolumeIds=[volume_id])['Volumes']
|
||||
if volumes:
|
||||
tenant = get_tag(volumes[0].get('Tags', []), 'Tenant')
|
||||
except Exception as e:
|
||||
if 'InvalidVolume.NotFound' in str(e):
|
||||
add_output(output, "Snapshot", snap['SnapshotId'], tenant or "TagNotExists", "NoVolumeIDFound", SourceID=volume_id)
|
||||
else:
|
||||
add_output(output, "Snapshot", snap['SnapshotId'], tenant or "TagNotExists", f"VolumeDescribeError: {str(e)}", SourceID=volume_id)
|
||||
continue
|
||||
|
||||
if already_tagged:
|
||||
add_output(output, "Snapshot", snap['SnapshotId'], tenant or "TagNotExists", "AlreadyTagged", SourceID=volume_id)
|
||||
continue
|
||||
|
||||
if not volume_id:
|
||||
add_output(output, "Snapshot", snap['SnapshotId'], "TagNotExists", "NoVolumeId")
|
||||
continue
|
||||
|
||||
if tenant:
|
||||
try:
|
||||
ec2.create_tags(Resources=[snap['SnapshotId']], Tags=[{'Key': 'Tenant', 'Value': tenant}])
|
||||
add_output(output, "Snapshot", snap['SnapshotId'], tenant, "TagAdded", SourceID=volume_id)
|
||||
except Exception as e:
|
||||
add_output(output, "Snapshot", snap['SnapshotId'], tenant, f"TagError: {str(e)}", SourceID=volume_id)
|
||||
else:
|
||||
add_output(output, "Snapshot", snap['SnapshotId'], "TagNotExists", "NoTenantTagOnVolume", SourceID=volume_id)
|
||||
|
||||
# 4. Network Interfaces (ENIs)
|
||||
enis = ec2.describe_network_interfaces()['NetworkInterfaces']
|
||||
for eni in enis:
|
||||
already_tagged = any(tag['Key'] == 'Tenant' for tag in eni.get('TagSet', []))
|
||||
attachment = eni.get('Attachment', {})
|
||||
instance_id = attachment.get('InstanceId')
|
||||
tenant = None
|
||||
|
||||
if instance_id:
|
||||
try:
|
||||
reservations = ec2.describe_instances(InstanceIds=[instance_id])['Reservations']
|
||||
if reservations and reservations[0]['Instances']:
|
||||
tags = reservations[0]['Instances'][0].get('Tags', [])
|
||||
tenant = get_tag(tags, 'Tenant')
|
||||
except Exception as e:
|
||||
add_output(output, "NetworkInterface", eni['NetworkInterfaceId'], tenant or "TagNotExists", f"InstanceDescribeError: {str(e)}", SourceID=instance_id)
|
||||
continue
|
||||
|
||||
if already_tagged:
|
||||
add_output(output, "NetworkInterface", eni['NetworkInterfaceId'], tenant or "TagNotExists", "AlreadyTagged", SourceID=instance_id)
|
||||
continue
|
||||
|
||||
if not instance_id:
|
||||
add_output(output, "NetworkInterface", eni['NetworkInterfaceId'], "TagNotExists", "NoInstanceAttachment")
|
||||
continue
|
||||
|
||||
if tenant:
|
||||
try:
|
||||
ec2.create_tags(Resources=[eni['NetworkInterfaceId']], Tags=[{'Key': 'Tenant', 'Value': tenant}])
|
||||
add_output(output, "NetworkInterface", eni['NetworkInterfaceId'], tenant, "TagAdded", SourceID=instance_id)
|
||||
except Exception as e:
|
||||
add_output(output, "NetworkInterface", eni['NetworkInterfaceId'], tenant, f"TagError: {str(e)}", SourceID=instance_id)
|
||||
else:
|
||||
add_output(output, "NetworkInterface", eni['NetworkInterfaceId'], "TagNotExists", "NoTenantTagOnInstance", SourceID=instance_id)
|
||||
|
||||
# 5. Elastic IPs (EIPs)
|
||||
addresses = ec2.describe_addresses()['Addresses']
|
||||
for addr in addresses:
|
||||
allocation_id = addr.get('AllocationId')
|
||||
instance_id = addr.get('InstanceId')
|
||||
tags = addr.get('Tags', [])
|
||||
already_tagged = any(tag['Key'] == 'Tenant' for tag in tags)
|
||||
tenant = None
|
||||
|
||||
if instance_id:
|
||||
try:
|
||||
reservations = ec2.describe_instances(InstanceIds=[instance_id])['Reservations']
|
||||
if reservations and reservations[0]['Instances']:
|
||||
instance_tags = reservations[0]['Instances'][0].get('Tags', [])
|
||||
tenant = get_tag(instance_tags, 'Tenant')
|
||||
except Exception as e:
|
||||
add_output(output, "EIP", allocation_id, tenant or "TagNotExists", f"InstanceDescribeError: {str(e)}", SourceID=instance_id)
|
||||
continue
|
||||
|
||||
if already_tagged:
|
||||
add_output(output, "EIP", allocation_id, tenant or "TagNotExists", "AlreadyTagged", SourceID=instance_id)
|
||||
continue
|
||||
|
||||
if not instance_id:
|
||||
add_output(output, "EIP", allocation_id, "TagNotExists", "NoInstanceAttachment")
|
||||
continue
|
||||
|
||||
if tenant:
|
||||
try:
|
||||
ec2.create_tags(Resources=[allocation_id], Tags=[{'Key': 'Tenant', 'Value': tenant}])
|
||||
add_output(output, "EIP", allocation_id, tenant, "TagAdded", SourceID=instance_id)
|
||||
except Exception as e:
|
||||
add_output(output, "EIP", allocation_id, tenant, f"TagError: {str(e)}", SourceID=instance_id)
|
||||
else:
|
||||
add_output(output, "EIP", allocation_id, "TagNotExists", "NoTenantTagOnInstance", SourceID=instance_id)
|
||||
|
||||
# 6. KMS: Tag customer-managed keys with alias name as Tenant (us-east-1)
|
||||
paginator = kms.get_paginator('list_aliases')
|
||||
for page in paginator.paginate():
|
||||
for alias in page['Aliases']:
|
||||
alias_name = alias.get('AliasName', '')
|
||||
key_id = alias.get('TargetKeyId')
|
||||
if alias_name.startswith('alias/aws/') or not key_id:
|
||||
continue
|
||||
# FIX: Remove 'alias/' prefix for the tag value
|
||||
tenant_value = alias_name[len('alias/'):] if alias_name.startswith('alias/') else alias_name
|
||||
try:
|
||||
tags_resp = kms.list_resource_tags(KeyId=key_id)
|
||||
existing_tenant = next((t['TagValue'] for t in tags_resp.get('Tags', []) if t['TagKey'] == 'Tenant'), None)
|
||||
if existing_tenant == tenant_value:
|
||||
add_output(output, "KMS", key_id, tenant_value, "AlreadyTagged")
|
||||
continue
|
||||
kms.tag_resource(
|
||||
KeyId=key_id,
|
||||
Tags=[{'TagKey': 'Tenant', 'TagValue': tenant_value}]
|
||||
)
|
||||
add_output(output, "KMS", key_id, tenant_value, "TagAdded")
|
||||
except Exception as e:
|
||||
add_output(output, "KMS", key_id, tenant_value, f"TagError: {str(e)}")
|
||||
|
||||
# 7. Route 53: Tag hosted zones with description as Tenant (only if needed)
|
||||
hosted_zones = route53.list_hosted_zones()['HostedZones']
|
||||
for zone in hosted_zones:
|
||||
zone_id = zone['Id'].split('/')[-1]
|
||||
description = zone.get('Config', {}).get('Comment', '')
|
||||
tenant_value = description
|
||||
if description:
|
||||
try:
|
||||
tags_resp = route53.list_tags_for_resource(ResourceType='hostedzone', ResourceId=zone_id)
|
||||
existing_tenant = next((t['Value'] for t in tags_resp.get('ResourceTagSet', {}).get('Tags', []) if t['Key'] == 'Tenant'), None)
|
||||
if existing_tenant == tenant_value:
|
||||
add_output(output, "Route53HostedZone", zone_id, tenant_value, "AlreadyTagged")
|
||||
continue
|
||||
route53.change_tags_for_resource(
|
||||
ResourceType='hostedzone',
|
||||
ResourceId=zone_id,
|
||||
AddTags=[{'Key': 'Tenant', 'Value': tenant_value}]
|
||||
)
|
||||
add_output(output, "Route53HostedZone", zone_id, tenant_value, "TagAdded")
|
||||
except Exception as e:
|
||||
add_output(output, "Route53HostedZone", zone_id, tenant_value, f"TagError: {str(e)}")
|
||||
else:
|
||||
add_output(output, "Route53HostedZone", zone_id, "", "NoDescriptionNoTag")
|
||||
|
||||
return output
|
||||
Reference in New Issue
Block a user