Delete old AMI’s by filtering with tags using boto3 and Lambda

Hello,

When you are building custom AMI’s in AWS account you will need to manage them by deleting the old AMI’s and keep only few latest images. For this you can use the below python code in Lambda function. I took the below code as reference from here and modified it to delete the AMI’s by filtering the images which has only specified tags.

Filtering the images with tags is important as different teams/projects will be having their images and it avoids accidental deletion of the wrong images.

Note: Before executing this code make sure your AMI’s are tagged.

    Code explanantion:

* First import libraries datetime, boto3 and time.
* Next get the ec2 connection session using boto3.
* Assign a variable older_days and pass the value as days (all images which are older than specified days from the present date will be filtered)

* Invoke the main function lambda_handler and then
* Invoke the function get_ami_list by passing older_days as a parameter

* Function get_ami_list uses ec2 descirbe_images to get all the images details which has specified ownerid as the owner
* Next it will invoke the function get_delete_date, calculates and finds out the date which is 5 days past from the present date
* Next the images will be filtered according to the specified tag value and if the image is older then 5 days.
* Then images are further filtered if older than 5 days and deregistered by invoking function delete_ami

from datetime import datetime, timedelta, timezone
import boto3
import time

client.ec2 = boto3.client('ec2', region_name='us-east-1')

#Here all images which are older than 5 days from the present date will be filtered
older_days = 5

def lambda_handler(event, context):
    get_ami_list(older_days)

def get_ami_list(older_days):
    amiNames = client.ec2.describe_images(Owners=['123456789123'])
    print(amiNames)
    today_date = datetime.now().strftime('%d-%m-%Y')
    print("Today's date is " + today_date)
    deldate1 = get_delete_date(older_days)
    print("AMI images which are older than " + str(deldate1) + " will be deregistered")
    for image in amiNames['Images']:
        taginfo = image['Tags']
        for tagName in taginfo:
			#Filter only the images having tag value as Proj1AMI
            if (tagName['Value'] == 'Proj1AMI'):
                ami_creation = image['CreationDate']
                imageID = image['ImageId']
                print("=================================================")
                print("Image id is " + imageID)
                print("Creation date for above image is " + ami_creation)
                if (str(ami_creation) < str(get_delete_date(older_days))):
                    print("This AMI is older than " + str(older_days) + " days")
                    delete_ami(imageID)

def get_delete_date(older_days):
	delete_time = datetime.now(tz=timezone.utc) - timedelta(days=older_days)
	return delete_time;

def delete_ami(imageID):
	print("Deregistering Image ID: " + imageID)
	client.ec2.deregister_image(ImageId=imageID)
Advertisements

Update SSM parameter store on another AWS account using AssumeRole

Hi,

In this post we are going to update the SSM parameter store in 2nd AWS account with the details from 1st AWS account. For this we will create a AWS Lambda function with python code. The python code will assume the role from another account and uses the temporarily generated STS credentials to connect and update the SSM parameter on the 2nd AWS account.

Create a Lambda function by selecting Python 2.7 and add the below code into it


#!/usr/bin/python

import boto3
import time

ssmparam = boto3.client('ssm')

account_id = '112211221122'
account_role = 'AssumeRole-SSM'
region_Name = 'us-east-1'

AmiId = 'ami-119c8dc1172b9c8e'

def lambda_handler(event, context):
    print("Assuming role for account: " + account_id)
    credentials = assume_role(account_id,account_role)

	#Call the function to update the SSM parameter with value
    updateSSM_otherAccount(credentials,region_Name,account_id)

def assume_role(account_id, account_role):
    sts_client = boto3.client('sts')
    role_arn = 'arn:aws:iam::' + account_id + ':role/' + account_role
    print (role_arn)

    '''Call the assume_role method of the STSConnection object and pass the role
    ARN and a role session name'''

    assuming_role = True
    assumedRoleObject = sts_client.assume_role(RoleArn=role_arn,RoleSessionName="NewAccountRole")
    print (assumedRoleObject['Credentials'])

    '''From the response that contains the assumed role, get the temporary
    credentials that can be used to make subsequent API calls'''
    return assumedRoleObject['Credentials']
    
def updateSSM_otherAccount(creds, region_Name, account_id):
    client1 = boto3.client('ssm',region_name=region_Name,aws_access_key_id=creds['AccessKeyId'],aws_secret_access_key=creds['SecretAccessKey'],aws_session_token=creds['SessionToken'])

    ssmparam_update = client1.put_parameter(Name='DevAMI',
            Description='the latest ami id of Dev env',
            Value=AmiId, Type='String', Overwrite=True)

Steps to configure AssumeRole

Note: Make sure to modify the account id’s in the below json policy

1. Add the inline policy to role attached to the lambda in 1st AWS account (556655665566)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "123",
            "Effect": "Allow",
            "Action": [
                "sts:AssumeRole"
            ],
            "Resource": [
                "arn:aws:iam::112211221122:role/AssumeRole-SSM"
            ]
        }
    ]
}

2. Create a role in 2nd AWS account (AssumeRole-SSM) (112211221122), edit the trust relationship and add below policy.
Attach EC2 full permissions to this role so that we will get access to SSM parameter store

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "sts:AssumeRole"
            ],
            "Resource": "arn:aws:iam::556655665566:role/lambda-ec2-role"
        }
    ]
}

How to upload and run Nodejs package using AWS Lambda

Hey guys.. If you have tried using Nodejs code to run in AWS Lambda you know how painful it is to package the node modules with needed libraries to make it work in Lambda function. Yes it is difficult in begining but once you start exploring and understanding it becomes so much interesting as what all you can achieve using nodejs.

Here I will using nodejs UUID module to generate a unique id which can be used in application or in database. The AWS documentation tells that “You can create a deployment package yourself or write your code directly in the Lambda console, in which case the console creates the deployment package for you and uploads it, creating your Lambda function.” but there is no step-by-step instructions and screenshots to show how to do it. And also you won’t get much information in other blogs as I have tried exploring and ended up without proper steps. So, I like to show you here how to do.

The best way is to install nodejs and test the code on your local linux or windows environment and then package and upload the zip file to Lambda function.

Install nodejs using this command (the OS is RedHat)


curl --silent --location https://rpm.nodesource.com/setup_6.x | sudo bash -
sudo yum -y install nodejs

You can verify the installation by checking the node version (node -v) and npm version (npm -v)

 

Install the UUID module using below command


npm install uuid

 

You will get node_modules directory under /home/ec2-user

Navigate to directory /home/ec2-user/node_modules/uuid

and zip the all the files under this
zip -r TestnpmLambda1.zip *

Go to AWS Lambda and create a function
Select nodejs

1

2

Upload the zip file to Lambda function

Next copy the below code to the “edit code inline”


exports.handler = (event, context, callback) => {
var uuid = require('uuid');
console.log(uuid.v4());
};

Next save and test the function by creating a event

3

Then you should see new random UniqueID generated every time when you test this function.