SSH with AWS Lambda
AWS Lambda is the base service of the AWS serverless offering, briefly talking it is a managed container service in which we just care about the code. Lately, it has been used a lot to make automation of all kinds thanks to its low cost and easy implementation.
A not very common, but very useful use for lambda is to execute commands through SSH, we can send commands to our EC2 instances and do some automation of boring and repetitive processes, for example, you can get information about the machines and their processes, install Cloudwatch or SSM agent, etc., etc. Here the imagination is the limit.
In this article, I will try to explain what is required to make a Lambda implementation with Python 2.7 to SSH our instances using the Paramiko library. Paramiko is a library for SSHv2 implementation.
We will start by creating a Lambda Layer containing the Paramiko library.
To create it we will need a Linux environment, in my case, I will use an instance of Amazon Linux 2, we use Amazon Linux 2 because it already has the SSM agent installed, and we can execute the commands we need by connecting through Session Manager.
So first we have to create an instance of any size, I suggest using a t2.micro to avoid costs and give it a role that allows us to connect via Session Manager.
Once inside we execute the following
#We move to our user directory
cd#Install “python-devel” “openssl-devel” and “libffi-devel”
sudo yum install python-devel openssl-devel libffi-devel#install pip
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
sudo python get-pip.py#Install virtualenv
sudo pip install virtualenv#We create a new folder called test and move to it
mkdir test
cd test#We create an environment called python
virtualenv python#We move towards the environment
cd python#Activate the new environment
source bin/activate#Initialize pip
pip install#Move to the lib/python2.7/site-packages/folder
cd lib/python2.7/site-packages/#We proceed to install paramiko and other dependencies
#IMPORTANT Don’t use sudo here and put the full command
pip install paramiko -t.
Once this is done we verify that we have the paramiko, cryptography and .libs_cffi_backend packages
If we do not have these files it means that something went wrong in the installation and that it will give us errors if we upload it as a layer, if we have them, then everything is according to the plan.
Once this is done we move to our test directory and proceed to zip the python directory
cd test
zip -r9 ./paramikolayer.zip .#Once our zip file is obtained, we upload it to s3
aws s3 cp paramikolayer.zip s3://yourbucket/paramikolayer.zip
Then we go to our AWS console, then Lambda -> Layers -> Create a new layer
We have to the name the layer and then select compatibility with python 2.7. Importantly we have to upload our zip folder from s3, if we upload it as .zip it could give problems.
Once created we have to move to Lambda -> Functions
Select create new function
Give it the name you want, select Python 2.7 as runtime, and assign it a role that contains all the permissions to access EC2.
Once created click on Layers.
Click on Add a Layer
Select our layer and version and click Add.
Important once the layer is added click Save.
Now import paramiko to the code.
Run and done!
If it does not throw any error, it means the installation of paramiko in the layer was successful.
Now you can proceed to create a client with paramiko and throw commands to some instance, you can use the following code to obtain information about which operating is inside an instance.
import paramikoimport jsonimport boto3def lambda_handler(event, context):s3_client = boto3.client('s3')#Download the pem key from a s3 buckets3_client.download_file ('bucketname', 'yourkey.pem', '/tmp/keyname.pem')pem_key = paramiko.RSAKey.from_private_key_file("/tmp/keyname.pem")#Creating a new clientssh_client = paramiko.SSHClient()ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())#Put the address of the server to which you want to connecthost = "172.0.0.0"print("Starting connection to:" + host)#Start the connection, in username type the name of the user with whom you want to login#In this case as I am using an Amazon Linux AMI the user is ec2-userssh_client.connect (hostname = host, username = "ec2-user", pkey = pem_key)#Commands to display the OS information fileso_info_commands = ["cat /etc/os-release"]for command in so_info_commands:print "Executing Command: {}".format(command)stdin , stdout, stderr = ssh_client.exec_command(command)response = stdout.readlines()for idx, item in enumerate(response):print("Output "+str(idx+1)+": "+item)return{'message' : "Script execution completed. See Cloudwatch logs for complete output"}
So this is all, with this you can now generate future automation of all kinds.
Clap if you find this article useful! :)
Follow me:
LinkedIn https://www.linkedin.com/in/bertin-cano/