Table of Contents
EC2
Listing instances
root@ftphost02:~/.aws# aws ec2 describe-instances --output table --query 'Reservations[].Instances[].Tags[?Key==`Name`].Value' ------------------- |DescribeInstances| +-----------------+ | Node1 | | FTP | +-----------------+ root@ftphost02:~/.aws# aws ec2 describe-instances --output table --query 'Reservations[].Instances[].[join(`,`,Tags[?Key==`Name`].Value),State.Name]' ---------------------------- | DescribeInstances | +--------------+-----------+ | Node1 | running | | FTP | running | +--------------+-----------+ OR (Using pipe syntax) root@ftphost02:~/.aws# aws ec2 describe-instances --output table --query 'Reservations[].Instances[].[Tags[?Key==`Name`] | [0].Value, State.Name]' ---------------------------- | DescribeInstances | +--------------+-----------+ | Node1 | running | | FTP | running | +--------------+-----------+ root@ftphost02:~/.aws# aws ec2 describe-instances --instance-ids i-65b45c6b --output table --query 'Reservations[].Instances[].[join(`,`,Tags[?Key==`Name`].Value),State.Name]' ---------------------------- | DescribeInstances | +--------------+-----------+ | Node1 | running | +--------------+-----------+ root@ftphost02:~/.aws# aws ec2 describe-instances --output table --query 'Reservations[].Instances[].[Tags[?Key==`Name`] | [0].Value, InstanceId]' ------------------------------- | DescribeInstances | +--------------+--------------+ | Node1 | i-65b45c6b | | FTP | i-59891e53 | +--------------+--------------+
Controlling instances
root@ftphost02:~/.aws# aws ec2 start-instances --instance-ids i-65b45c6b { "StartingInstances": [ { "InstanceId": "i-65b45c6b", "CurrentState": { "Code": 0, "Name": "pending" }, "PreviousState": { "Code": 80, "Name": "stopped" } } ] } root@ftphost02:~/.aws# aws ec2 stop-instances --instance-ids i-65b45c6b { "StoppingInstances": [ { "InstanceId": "i-65b45c6b", "CurrentState": { "Code": 64, "Name": "stopping" }, "PreviousState": { "Code": 16, "Name": "running" } } ] }
State codes
0 | pending |
16 | running |
32 | shutting-down |
48 | terminated |
64 | stopping |
80 | stopped |
Filters
Combining two filters can be either AND
or OR
.
AND
Filters are in separate quotes, note space between two quoted blocks:-
–filters “Name=image-id, Values=ami-07cf57ebf50e78466” “Name=tag-key, Values=aws:autoscaling:groupName”
$ aws ec2 describe-instances --filters "Name=image-id, Values=ami-07cf57ebf50e78466" "Name=tag-key, Values=aws:autoscaling:groupName" --query 'Reservations[*].Instances[*].[InstanceId]' --profile nonprod_admin [ [ [ "i-05c83bdad5311253c" ] ], [ [ "i-0dbcfbdea9b501851" ] ] ]
OR
Filters are part of the same quotes:-
–filters “Name=image-id, Values=ami-07cf57ebf50e78466,Name=tag-key, Values=aws:autoscaling:groupName”
$ aws ec2 describe-instances --filters "Name=image-id, Values=ami-07cf57ebf50e78466,Name=tag-key, Values=aws:autoscaling:groupName" --query 'Reservations[*].Instances[*].[InstanceId]' --profile nonprod_admin [ [ [ "i-0983d97f816fdd9ea" ] ], ...edited.... [ [ "i-04d8e1a1de04d6bc6" ] ], [ [ "i-0dbcfbdea9b501851" ] ] ]
Using JMESpath
$ aws ec2 describe-instances --filters "Name=image-id, Values=ami-07cf57ebf50e78466" "Name=tag-key, Values=aws:autoscaling:groupName" --query 'Reservations[*].Instances[*].{ImageId:ImageId,Tags:Tags}' --profile nonprod_admin
$ aws ec2 describe-instances --query 'Reservations[].Instances[].[Tags[?contains(`["Name"]`, Key)].Value, State.Name, Platform][][]' --profile nonprod_admin --out=text
$ aws ec2 describe-instances --filters "Name=image-id, Values=ami-0927c25b5177ff0de" --query 'Reservations[*].Instances[*].[Tags[?(Key==`Name`)].Value, State.Name, Platform]' --profile nonprod_admin --out=table $ aws ec2 describe-instances --profile nonprod_admin | jq --raw-output '.[][].Instances[] | {"InstanceId": .InstanceId, "State": .State.Name, "Name": .Tags[]|select(.Key=="Name").Value, "servicename": .Tags[]|select(.Key=="servicename").Value } | join(", ")'
listOfAMI0lderThanX.py
#!/usr/bin/env python import boto3 import datetime from datetime import date from datetime import datetime profile = 'nonprod_admin' context = 'dummy' session = boto3.session.Session(profile_name=profile) ec2 = session.client('ec2') # ec2 = boto3.client('ec2',region) def getListOfAMI(agearguments, context): Regex = agearguments["Regex"] AGEthreshold = int(agearguments["AGEthreshold"]) AMIlist = [] # get list of all AMI owned by this account, matching the regex AMIResponse = ec2.describe_images(Filters=[{'Name': 'name', 'Values': [Regex]}, ], Owners=['self']) for i in AMIResponse['Images']: AMIname = i['Name'] AMIimageID = i['ImageId'] AMIcreationDate = i['CreationDate'] # convert unicode string to timedate object AMICreationDateTime = datetime.strptime((i['CreationDate']), '%Y-%m-%dT%H:%M:%S.%fZ') # only needs days not time, so use date method, likewise now is just days AMICreationDate = AMICreationDateTime.date() now = date.today() # Get age of ami and convert timedelta to contain only days AMIage = (now - AMICreationDate).days if AMIage >= AGEthreshold: olderThanThreshold = True AMIlist.append(AMIimageID) else: olderThanThreshold = False # print ("AMI", AMIimageID, "Age Threshold ", AGEthreshold, "AMI age ",AMIage, "olderthanthres ", olderThanThreshold) # print (AMIlist) # resultDict = {"OlderThanThreshold":olderThanThreshold, "AMIage":AMIage} return (AMIlist) AMILIST = getListOfAMI({"Regex": "*JS-AMZN2*", "AGEthreshold": "7"}, context) print (AMILIST)
CheckAMIinUse.py
#!/usr/bin/env python import boto3 import sys profile = 'nonprod_admin' session = boto3.session.Session(profile_name=profile) ec2 = session.client('ec2') ASsession = boto3.session.Session(profile_name=profile) ec2as = ASsession.client('autoscaling') # ec2 = boto3.client('ec2') # ec2as = boto3.client('autoscaling') context = '' def checkAMIinUse(AMIimageID, context): try: # print (AMIimageID['ImageID']) # aws ec2 describe-instances --filters "Name=image-id, Values=ami-0e12cbde3e77cbb98" --query 'Reservations[*].Instances[*].[InstanceId]' --profile nonprod_admin EC2InUseResponse = ec2.describe_instances(Filters=[{'Name': 'image-id', 'Values': [AMIimageID['ImageID']]}]) except: return ('Exception! Error with AWS response') # list comprehension, returns list of instances EC2instance_ids = [ i["InstanceId"] for r in EC2InUseResponse["Reservations"] for i in r["Instances"] ] # print ('checkAMIinUse: Instances relying on ',AMIimageID, ' are ', EC2instance_ids) if len(EC2instance_ids) == 0: EC2AMIinUse = False else: EC2AMIinUse = True # print ('checkAMIinUse: Instances ', EC2AMIinUse) # test if ASG relies on AMI # get all ASG and for ech, get the Launch config. # check each LC for the AMI in AMIimageID # this gets all asg but have to match lc passed to function within it. # aws autoscaling describe-auto-scaling-groups --profile nonprod_admin --auto-scaling-group-names "AJS asg1" # print ('checkAMIinUse: ASG Check if AMI is in use by ASG') ASGresponse = ec2as.describe_auto_scaling_groups() ASGresponse1 = ASGresponse['AutoScalingGroups'] ASGAMIinUse = False for i in ASGresponse1: LCGroup = i['LaunchConfigurationName'] LCResponse = GetAllLaunchConf(LCGroup) LC_object = LCResponse['LaunchConfigurations'] for item in LC_object: # print ('Testing for AMIimageID ', AMIimageID, ' in ', item['ImageId']) if item['ImageId'] == AMIimageID: # print('True') ASGAMIinUse = True break if ASGAMIinUse is True: break # print ('checkAMIinUse: ASG Ami InUse:- ', ASGAMIinUse ) if EC2AMIinUse or ASGAMIinUse is True: AMIinUse = True else: AMIinUse = False return (AMIinUse) def GetAllLaunchConf(LCName): # aws autoscaling describe-launch-configurations --launch-configuration-names "AJS launchconf1" --profile nonprod_admin # returns dictionary GLCresponse = ec2as.describe_launch_configurations(LaunchConfigurationNames=[LCName, ], ) return (GLCresponse) try: InUse, EC2instance_ids, ASGAMIinUse = checkAMIinUse({"ImageID": "ami-094ef7a0cbb90a7c1"}, context) except: print ('Exception! Not enough arguments supplied.', sys.exc_info()) print (InUse, EC2instance_ids, ASGAMIinUse)
Get Latest tagged image (AMI)
$ aws ec2 describe-images --filters Name=tag:release,Values=Latest Name=is-public,Values=false --profile nonprod_admin | more { "Images": [ { "Architecture": "x86_64", "CreationDate": "2019-09-01T09:26:52.000Z", "ImageId": "ami-01efb7e3b3f79ecf9", "ImageLocation": "057726927330/JS-AMZN2-AMI-CIS-L2-1567328875", "ImageType": "machine", "Public": false, "OwnerId": "057726927330", "State": "available",
Get Stopped Instances
#!/bin/bash for I in `aws ec2 describe-instances --filters "Name=instance-state-name, Values=stopped" --query 'Reservations[].Instances[].InstanceId' --profile nonprod_admin --out text` do aws ec2 describe-instances --instance-ids ${I} --query 'Reservations[*].Instances[*].[Tags[?(Key==`Name`)].Value, InstanceId,State.Name, Platform]' \ --profile nonprod_admin #--out=table done
Security Groups
$ aws ec2 describe-network-interfaces --filters Name=group-id,Values=sg-0f99adeb1ca8f1892 --profile nonprod_admin { "NetworkInterfaces": [] }
EC2 cli
aws ec2 describe-instances –region us-west-2
aws ec2 describe-instances –region us-west-2 –output table –filters “Name=instance-type,Values=t2.small”
# for region in `aws ec2 describe-regions --output text | \ cut -f3`; do aws ec2 describe-instances --region $region \ --query 'Reservations[].Instances[].[PrivateIpAddress,InstanceId,Tags[?Key==`Name`].Value[]]' \ --output text | sed '$!N;s/\n/ /'; \ done 10.0.6.10 i-30d917bb prod-001 10.0.0.112 i-33cc3902 EC2ContainerService-default 10.0.0.4 i-f1602579 prod-002 10.130.200.188 i-7c31a9f4 Repair 01 ...edited...
EC2 metadata - get public ip address
$ TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 56 100 56 0 0 25282 0 --:--:-- --:--:-- --:--:-- 28000 [ssm-user@ip-10-0-0-251 2048]$ curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/public-ipv4 -w "\n" 52.25.145.1 $
AWS NTP Time
Use 169.254.169.123 with ntp or chrony.
server 169.254.169.123 prefer iburst
Force timesync with chrony
If you get this message:-
$ ./get_repos.sh An error occurred (InvalidSignatureException) when calling the ListRepositories operation: Signature expired: 20231207T141711Z is now earlier than 20231207T152038Z (20231207T153538Z - 15 min.)
your time may be out by more than AWS allows, use this with chrony to force a reset. ntpdate
will force a resync with the ntpd package. You will need to stop the ntpd
daemon first and then restart it after.
root@ubuntu20:~# chronyd -q 'server time.domain.com iburst' 2023-10-26T15:32:22Z chronyd version 3.5 starting (+CMDMON +NTP +REFCLOCK +RTC +PRIVDROP +SCFILTER +SIGND +ASYNCDNS +SECHASH +IPV6 -DEBUG) 2023-10-26T15:32:22Z Initial frequency 5.379 ppm 2023-10-26T15:32:26Z System clock wrong by 1931.782000 seconds (step) 2023-10-26T16:04:38Z chronyd exiting root@ubuntu20:~#
Getting info from within a running instance
The 169.254.169.254 address allows access to metadata about an instance from within THAT instance, eg:-
[root@ip-172-31-21-109 ~]# curl http://169.254.169.254/latest/meta-data/ami-id ami-0f1229ec7823be3db [root@ip-172-31-21-109 ~]# [root@ip-172-31-21-109 ~]# curl http://169.254.169.254/latest/meta-data/public-keys/ 0=AndrewAWS [root@ip-172-31-21-109 ~]# [root@ip-172-31-21-109 ~]# curl http://169.254.169.254/latest/meta-data/network/interfaces/macs/06:b7:e8:98:98:0a/public-hostname/ ec2-34-244-253-26.eu-west-1.compute.amazonaws.com [root@ip-172-31-21-109 ~]#
AWS cli
[ec2-user@ip-10-96-10-231 ~]$ aws ec2 describe-instances --query 'Reservations[].Instances[].[InstanceId,Tags[?Key==`Name`].Value|[0], IamInstanceProfile.Arn]' --output table ----------------------------------------------------------------------------------------------------------------------------------- | DescribeInstances | +---------------------+---------------------------------+-------------------------------------------------------------------------+ | i-0ec2f28f95c0b4396| MadLib API Tier - AutoScaled | arn:aws:iam::399862743030:instance-profile/MadLib-APIrole | | i-0fd0f2f4e072463b0| MadLib Save Tier - AutoScaled | arn:aws:iam::399862743030:instance-profile/MadLib-Saverole | | i-0ac39407f3b79e43b| MadLib API Tier - AutoScaled | arn:aws:iam::399862743030:instance-profile/MadLib-APIrole | | i-0eba4f6906abf1833| MadLib Web Tier - AutoScaled | arn:aws:iam::399862743030:instance-profile/MadLib-AppRole | | i-0b558db478ac2bdbc| CommandHost | arn:aws:iam::399862743030:instance-profile/CommandHostInstanceProfile | | i-09a53d2758f4d749d| MadLib Web Tier - AutoScaled | arn:aws:iam::399862743030:instance-profile/MadLib-AppRole | | i-03804db70790dc0ed| MadLib Save Tier - AutoScaled | arn:aws:iam::399862743030:instance-profile/MadLib-Saverole | +---------------------+---------------------------------+-------------------------------------------------------------------------+ [ec2-user@ip-10-96-10-231 ~]$ [ec2-user@ip-10-96-10-231 ~]$ aws ec2 describe-instances --filter "Name=tag:Name,Values=MadLib Save*" --query 'Reservations[].Instances[].[InstanceId,Tags[?Key==`Name`].Value|[0], IamInstanceProfile.Arn]' --output table ------------------------------------------------------------------------------------------------------------------------ | DescribeInstances | +---------------------+---------------------------------+--------------------------------------------------------------+ | i-0fd0f2f4e072463b0| MadLib Save Tier - AutoScaled | arn:aws:iam::399862743030:instance-profile/MadLib-Saverole | | i-03804db70790dc0ed| MadLib Save Tier - AutoScaled | arn:aws:iam::399862743030:instance-profile/MadLib-Saverole | +---------------------+---------------------------------+--------------------------------------------------------------+ [ec2-user@ip-10-96-10-231 ~]$
[ec2-user@ip-10-96-10-231 ~]$ aws ec2 describe-instances --filter "Name=tag:Name,Values=MadLib Web*" --query 'Reservations[0].Instances[0].IamInstanceProfile.Arn' --output text arn:aws:iam::399862743030:instance-profile/MadLib-AppRole [ec2-user@ip-10-96-10-231 ~]$ [ec2-user@ip-10-96-10-231 ~]$ appROLEARN=$(aws ec2 describe-instances --filter "Name=tag:Name,Values=MadLib Web*" --query 'Reservations[0].Instances[0].IamInstanceProfile.Arn' --output text) [ec2-user@ip-10-96-10-231 ~]$ [ec2-user@ip-10-96-10-231 ~]$ echo ${appROLEARN} arn:aws:iam::399862743030:instance-profile/MadLib-AppRole [ec2-user@ip-10-96-10-231 ~]$ [ec2-user@ip-10-96-10-231 ~]$ aws iam list-instance-profiles --query "InstanceProfiles[?Arn=='$appROLEARN']" [ { "InstanceProfileId": "AIPAJJGZDTBTYGJDSLFVM", "Roles": [ { "AssumeRolePolicyDocument": { "Version": "2008-10-17", "Statement": [ { "Action": "sts:AssumeRole", "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com" } } ] }, "RoleId": "AROAJ7OSABF7346MV6RIY", "CreateDate": "2018-10-09T08:06:50Z", "RoleName": "qls-1577787-84859361afe35637-AppLayerWebSi-AppRole-5CZ1MUJYE8Y4", "Path": "/", "Arn": "arn:aws:iam::399862743030:role/qls-1577787-84859361afe35637-AppLayerWebSi-AppRole-5CZ1MUJYE8Y4" } ], "CreateDate": "2018-10-09T08:07:07Z", "InstanceProfileName": "MadLib-AppRole", "Path": "/", "Arn": "arn:aws:iam::399862743030:instance-profile/MadLib-AppRole" } ] [ec2-user@ip-10-96-10-231 ~]$ [ec2-user@ip-10-96-10-231 ~]$ aws iam list-instance-profiles --query "InstanceProfiles[?Arn=='$appROLEARN'].Roles[0].RoleName" [ "qls-1577787-84859361afe35637-AppLayerWebSi-AppRole-5CZ1MUJYE8Y4" ] [ec2-user@ip-10-96-10-231 ~]$ [ec2-user@ip-10-96-10-231 ~]$ appROLENAME=$(aws iam list-instance-profiles --query "InstanceProfiles[?Arn=='$appROLEARN'].Roles[0].RoleName" --output text) [ec2-user@ip-10-96-10-231 ~]$ aws iam list-role-policies --role-name ${appROLENAME} { "PolicyNames": [ "MabLib-App-Policy" ] } [ec2-user@ip-10-96-10-231 ~]$ appPOLNAME=$(aws iam list-role-policies --role-name ${appROLENAME} --query PolicyNames[] --output text) [ec2-user@ip-10-96-10-231 ~]$ [ec2-user@ip-10-96-10-231 ~]$ aws iam get-role-policy --role-name ${appROLENAME} --policy-name ${appPOLNAME} { "RoleName": "qls-1577787-84859361afe35637-AppLayerWebSi-AppRole-5CZ1MUJYE8Y4", "PolicyDocument": { "Statement": [ { "Action": [ "s3:List*", "s3:Get*" ], "Resource": "*", "Effect": "Allow" } ] }, "PolicyName": "MabLib-App-Policy" } [ec2-user@ip-10-96-10-231 ~]$
[ec2-user@ip-10-96-10-231 ~]$ aws deploy list-applications { "applications": [ "qls-1577787-84859361afe35637-AppLayerWebSite-1P4CE84PXN67F-MadLibsSite-1AG3943MCP2N9", "qls-1577787-84859361afe35637-AppStackAPI-FO024805JDNG-MadLibsAPI-1Q30CGWVEPZDA", "qls-1577787-84859361afe35637-AppStackSave-1O3LTSI3CAKLB-MadLibsSave-XM6SBRZK607M" ] } [ec2-user@ip-10-96-10-231 ~]$ aws deploy list-deployments { "deployments": [ "d-W13R99NVV", "d-Y639UTFVV", "d-EAQ1SUMVV" ] } [ec2-user@ip-10-96-10-231 ~]$ DEPLOYARRAY=$(aws deploy list-deployments --output text) [ec2-user@ip-10-96-10-231 ~]$ IFS=' ' read -r -a DEPLOYID <<< $DEPLOYARRAY [ec2-user@ip-10-96-10-231 ~]$ echo "${DEPLOYID[1]}" d-W13R99NVV [ec2-user@ip-10-96-10-231 ~]$ echo "${DEPLOYID[3]}" d-Y639UTFVV [ec2-user@ip-10-96-10-231 ~]$ echo "${DEPLOYID[5]}" d-EAQ1SUMVV [ec2-user@ip-10-96-10-231 ~]$ [ec2-user@ip-10-96-10-231 ~]$ aws deploy list-deployment-instances --deployment-id ${DEPLOYID[1]} { "instancesList": [ "i-09a53d2758f4d749d", "i-0eba4f6906abf1833" ] } [ec2-user@ip-10-96-10-231 ~]$ aws ec2 describe-instances --filter "Name=tag:Name,Values=MadLib*" --query 'Reservations[].Instances[].[InstanceId, Tags[?Key==`Name`].Value | [0]]' --output table ---------------------------------------------------------- | DescribeInstances | +----------------------+---------------------------------+ | i-0ec2f28f95c0b4396 | MadLib API Tier - AutoScaled | | i-0fd0f2f4e072463b0 | MadLib Save Tier - AutoScaled | | i-0ac39407f3b79e43b | MadLib API Tier - AutoScaled | | i-0eba4f6906abf1833 | MadLib Web Tier - AutoScaled | | i-09a53d2758f4d749d | MadLib Web Tier - AutoScaled | | i-03804db70790dc0ed | MadLib Save Tier - AutoScaled | +----------------------+---------------------------------+ [ec2-user@ip-10-96-10-231 ~]$ [ec2-user@ip-10-96-10-231 ~]$ aws deploy get-deployment --deployment-id ${DEPLOYID[1]} { "deploymentInfo": { "applicationName": "qls-1577787-84859361afe35637-AppLayerWebSite-1P4CE84PXN67F-MadLibsSite-1AG3943MCP2N9", "status": "Succeeded", "deploymentOverview": { "Skipped": 0, "Succeeded": 2, "Failed": 0, "Ready": 0, "InProgress": 0, "Pending": 0 }, "description": "[CFN-DSHWMLJA] Deploying App MadLibs-Site Version-1.0\n", "deploymentConfigName": "MadLibs-Site", "creator": "user", "fileExistsBehavior": "DISALLOW", "deploymentId": "d-W13R99NVV", "deploymentStatusMessages": [], "ignoreApplicationStopFailures": true, "autoRollbackConfiguration": { "enabled": false }, "deploymentStyle": { "deploymentType": "IN_PLACE", "deploymentOption": "WITHOUT_TRAFFIC_CONTROL" }, "updateOutdatedInstancesOnly": false, "instanceTerminationWaitTimeStarted": false, "computePlatform": "Server", "deploymentGroupName": "WebAppDeplyGroup", "createTime": 1539072614.847, "completeTime": 1539072703.42, "revision": { "revisionType": "S3", "s3Location": { "bundleType": "zip", "bucket": "us-east-1-tcprod", "key": "courses/AWS-200-DOP/v2.1.5/lab-1-CLI/scripts/MadLibs-WebSite-Package.zip" } } } } [ec2-user@ip-10-96-10-231 ~]$