Get a count of active AWS network interfaces - amazon-web-services

I need to get a count of the number of 'active' network interfaces in my region.
I can use the query below to list out the active interfaces, however I am uncertain on how to get a 'count' of the active interfaces and not just a json payload as the output.
I can run this cli command to get the list of all attached interfaces.
aws ec2 describe-network-interfaces --filters "Name=group-name,Values=Redis" "Name=attachment.status,Values=attached"
However I'm not sure how to get a count of interfaces that are attached, i tried the query below but I'm not getting the desired output to just get a count.
aws ec2 describe-network-interfaces --filters "Name=group-name,Values=Redis" "Name=attachment.status,Values=attached" --query 'NetworkInterfaces[*][Attachment.Status,Attachment.Status.Count]'
The output comes out like below.
[
[
"attached",
null
],
[
"attached",
null
],
[
"attached",
null
],
[
"attached",
null
]
]
What I'd like to see if something like below.
[
[
type: "attached",
Count: "x"
]
]

It seems that you want to count the number of Elastic Network Interfaces (ENIs) in the region to know when you are approaching the limit.
The limits page in the EC2 management console doesn't seem to state that the ENI count is only for attached images, so you should probably count the total number of ENIs.
This could be done with:
aws ec2 describe-network-interfaces --query 'length(NetworkInterfaces)'
If you only wish to count count ENIs that are attached, use:
aws ec2 describe-network-interfaces --filters Name=attachment.status,Values=attached --query 'length(NetworkInterfaces)'

Related

AWS CLI --output text on a single line of first and second level json

I am trying to get a list of certificates (let's say 100) from AWS Certificates Manager with their Domain Name, Expiry Data, Validation Status and Validation Method with the aws cli command aws acm describe-certificate.
I tried nesting filtering and --ouput text but the output is on two lines. I guess the reason is that ValidationStatus and ValidationMethod are second level in the json ouput after Certificate/DomainValidationOptions.
How would it be possible to get the text ouput in a single line?
Like
foo.bar.com 2022-06-18T23:59:59+00:00 FAILED DNS
https://awscli.amazonaws.com/v2/documentation/api/latest/reference/acm/describe-certificate.html
This is the --output text
$ aws acm describe-certificate --certificate-arn arn:aws:acm:region:aws-account_id:certificate/xxxx --query Certificate.[DomainName,NotAfter,DomainValidationOptions[].[ValidationStatus,ValidationMethod]] --output text
foo.bar.com 2022-06-18T23:59:59+00:00
FAILED DNS
This is the --output json (default output)
aws acm describe-certificate --certificate-arn arn:aws:acm:region:aws-account_id:certificate/xxxx --query Certificate.[DomainName,NotAfter,DomainValidationOptions[].[ValidationStatus,ValidationMethod]]
[
"foo.bar.com",
2022-06-18T23:59:59+00:00,
[
[
"FAILED",
"DNS"
]
]
]
A way to achieve this is to flatten the array you are receiving from the AWS command, with the help of the JMESPath flatten operator — [] — in your query.
Having a query like this:
Certificate.[
DomainName,
NotAfter,
DomainValidationOptions[].[ValidationStatus, ValidationMethod]
][][]
Would give you, with one domain the JSON output
[
"www.example.com",
"2022-06-18T23:59:59+00:00",
"FAILED",
"DNS"
]
And end up on one line.
Now mind that, if you have more than one item in the DomainValidationOptions array, they will, then, all output on the same line, because you'll have one array with everything.
Example for two domains:
[
"www.example.com",
"2022-06-18T23:59:59+00:00",
"FAILED",
"DNS",
"FAILED",
"DNS"
]
See the DNS and ValidationStatus and ValidationMethod repeating for the two domains there?
What you might want to do, is to query the DomainName from the DomainValidationOptions, at least:
Certificate.[
NotAfter,
DomainValidationOptions[].[DomainName, ValidationStatus, ValidationMethod]
][][]
Which would still be on one line, but will get you the domain related to the validation:
[
"2022-06-18T23:59:59+00:00",
"www.example.com",
"FAILED",
"DNS",
"www.example.net",
"FAILED",
"DNS"
]
Some progress was made using John's suggestion.
By using "InUseBy[0]" and not only "InUseBy", I managed to output the "InUseBy" on the first line; otherwise it would be on the second line.
Also using "DomainValidationOptions[0].ValidationStatus" instead of "DomainValidationOptions.ValidationStatus" outputs this on the 2nd line instead of 3rd.
Still, I would like
"RenewalSummary.[RenewalStatus,DomainValidationOptions[0].ValidationStatus]"
to be output on the first line too. I noticed RenewalSummary is an object ,{}, not an array, [].
"RenewalSummary": {
"RenewalStatus": "PENDING_VALIDATION",
"DomainValidationOptions": [
{
"DomainName": "foo.bar.com",
"ValidationDomain": "foo.bar.com",
"ValidationStatus": "PENDING_VALIDATION",
"ResourceRecord": {
"Name": "_9d77eed0XXX66.foo.bar.com.",
"Type": "CNAME",
"Value": "_a5XXXX3.tgztlnjmjp.acm-validations.aws."
},
"ValidationMethod": "DNS"
}
],
"UpdatedAt": "2022-06-24T11:16:34.617000+00:00"
},
aws acm describe-certificate --certificate-arn arn:aws:acm:region:aws-account_id:certificate/xxxx --query Certificate.[DomainName,Issuer,Status,FailureReason,NotAfter,InUseBy[0],RenewalSummary.[RenewalStatus,DomainValidationOptions[0].ValidationStatus]] --output text
This is how the output looks now:
foo.bar.com Amazon ISSUED None 2022-06-18T23:59:59+00:00 arn:aws:elasticloadbalancing:eu-west-1:aws_account_id:loadbalancer/app/alb_foo_bar/XXX
PENDING_VALIDATION PENDING_VALIDATION

Find and remove outdated AMIs in AWS

I need to remove a list of outdated Ami's in AWS. But first I require to verifying are there any place still using those Ami's. Is there an efficient way to find it out.
First, you need to define "Outdated AMIs", it can be the creation date or something else. But here is the script that will list Instance ID along with AMI details that used by particular instance in particular region. By default it will look into default region.
#Get list of EC2 instance
echo "Getting EC2"
EC2_LIST=$(aws ec2 describe-instances --query 'Reservations[].Instances[].{InstanceId:InstanceId}' --output text | tr '\n' ' ')
#Get list of AMI used by ec2
echo "Getting AMI"
LIST_AMI_ID=$(aws ec2 describe-instances --query 'Reservations[].Instances[].{ImageId:ImageId,InstanceId:InstanceId}' --output text | tr '\n' ' ')
EC2_LIST_ARRAY=($EC2_LIST)
LIST_AMI_ID_ARRAY=($LIST_AMI_ID)
for index in ${!LIST_AMI_ID_ARRAY[*]}; do
echo "Get details for AMI ${LIST_AMI_ID_ARRAY[$index]}"
#Get details of AMI
AMI_DETAILS=$(aws ec2 describe-images --image-ids ${LIST_AMI_ID_ARRAY[$index]} --query 'Images[].{CreationDate:CreationDate,Tags:Tags[]}')
echo "Instance having ID ${EC2_LIST_ARRAY[$index]} using AMI ID ${LIST_AMI_ID_ARRAY[$index]} Details: $AMI_DETAILS"
done
output
Get details for AMI ami-0219162cf838b3455
Instance having ID i-0ceb0dfa197fd7455 using AMI ID ami-0219162cf838b3455 Details: [
{
"CreationDate": "2019-10-22T05:17:46.000Z",
"Tags": [
{
"Key": "Base_AMI_Name",
"Value": "ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-20191021"
},
{
"Key": "OS_Version",
"Value": "Ubuntu"
},
{
"Key": "Release",
"Value": "Latest"
},
{
"Key": "Name",
"Value": "postgres"
},
{
"Key": "Scope",
"Value": "database"
}
]
}
]
aws-cli-cheatsheet
For what it's worth, I built a small tool for this purpose as well -- a bit of JavaScript wrapped around AWS API calls.
This basically tries to find all the AMIs in use in your account and looks at both AMIs by their age and also the newly introduced deprecated flag:
https://github.com/geoffreywiseman/oldamis
https://www.codiform.com/blog/oldamis/
It's pretty simplistic currently, but I'm willing to entertain feature requests. ;)

How to output multiple elements via AWS query?

I trying to output in a column format three keys from 'rds'. If I start with this statement:
aws rds describe-db-instances --region us-east-1 --query 'DBInstances[*].[DBInstanceIdentifier, PubliclyAccessible, VpcSecurityGroupId]' --output text
...I get:
DBId true none
However, if I include another element to pull the security group:
aws rds describe-db-instances --region us-east-1 --query 'DBInstances[*].VpcSecurityGroups[*].[DBInstanceIdentifier, PubliclyAccessible, VpcSecurityGroupId]' --output text
...I get:
none none sg-id
I am not quite sure why my first two columns now become none and the sg-id is presented.
The difference is VpcSecurityGroups[*]:
'DBInstances[*].[DBInstanceIdentifier, PubliclyAccessible, VpcSecurityGroupId]'
vs
'DBInstances[*].VpcSecurityGroups[*].[DBInstanceIdentifier, PubliclyAccessible, VpcSecurityGroupId]'
In the second one, you are receiving none because DBInstanceIdentifier and PubliclyAccessible are not attributes of VpcSecurityGroups.
Here's a portion of an output to show the hierarchy:
{
"DBInstances": [
{
"PubliclyAccessible": false,
"VpcSecurityGroups": [
{
"Status": "active",
"VpcSecurityGroupId": "sg-1203dc23"
}
],
"DBInstanceIdentifier": "mydbinstance-1"
}
]
}
Try this instead:
'DBInstances[*].[DBInstanceIdentifier, PubliclyAccessible, VpcSecurityGroups[*].VpcSecurityGroupId]'
It won't look very pretty if there are multiple security groups, since it is a one-to-many relationship.

How to get all security groups through AWS CLI of an EC2 to show in a table

I am trying to show all instances along with attached security groups, block device name and their deleteontermination status. I need to show this data in table format but I am continuously getting the below error.
Kindly help me to understand what I am missing here.
PR-MacBook-Pro:~ pr$ aws ec2 describe-instances --output table --query 'Reservations[*].Instances[*].[InstanceId,SecurityGroups[].GroupName,Placement.AvailabilityZone,BlockDeviceMappings[].DeviceName, BlockDeviceMappings[].Ebs.DeleteOnTermination]'
Row should have 1 elements, instead it has 2
PR-MacBook-Pro:~ pr$
I came across this while searching in google.
After I did a bit of research I found that you have to use | join(`, `, #)
So the command will be
aws ec2 describe-instances --output table --query 'Reservations[*].Instances[*].[InstanceId,SecurityGroups[].GroupName | join(`, `, #),Placement.AvailabilityZone,BlockDeviceMappings[].DeviceName | join(`, `, #), BlockDeviceMappings[].Ebs.DeleteOnTermination | join(`, `, to_array(to_string(#)))]'
modify your command as below to make it work
aws ec2 describe-instances --output table --region "us-east-1" --query 'Reservations[*].Instances[*].[InstanceId,SecurityGroups[].GroupName |[0],Placement.AvailabilityZone,BlockDeviceMappings[].DeviceName |[0], BlockDeviceMappings[].Ebs.DeleteOnTermination|[0] ]'
the response was in the format of
[
[
"i-xxxxxxxx",
[
"xxxxxx"
],
"us-east-1a",
[
"/dev/xvda"
],
[
true
]
]
]
so you need parse the array element using | [0]

How to filter results from AWS CLI command

How can I filter the following so just results with IP starting with 10.* are returned?
aws ec2 describe-instances --filters "Name=tag-value,Values=mytagavalue" --query 'Reservations[*].Instances[*].{InstanceId:InstanceId,PrivateDnsName:PrivateDnsName,State:State.Name, IP:NetworkInterfaces[0].PrivateIpAddress}'
[
[
{
"InstanceId": "i-12345bnmsdfod",
"PrivateDnsName": "ip-10-34-24-4.my.there.com",
"State": "running",
"IP": "10.10.10.4"
}
],
[
{
"InstanceId": "i-12345bnmsdfop",
"PrivateDnsName": "",
"State": "terminated",
"IP": null
}
],
Option 1) Via Filters
Use the network-interface.addresses.private-ip-address filter to select values matching only "10.*", which will match addresses starting with "10.".
--filters "Name=network-interface.addresses.private-ip-address,Values=10.*"
Simply include a space between different filters to delimit them.
Full Example
aws ec2 describe-instances --filters "Name=tag-value,Values=mytagavalue" "Name=network-interface.addresses.private-ip-address,Values=10.*" --query 'Reservations[*].Instances[*].{InstanceId:InstanceId,PrivateDnsName:PrivateDnsName,State:State.Name, IP:NetworkInterfaces[0].PrivateIpAddress}'
Option 2) Via Query
Use the JMESPath starts_with() function to perform a partial string comparison of "10." against each network interface's private IP address.
Step By Step
First, select all instances:
Reservations[].Instances[]
Then pipe to filter for only instances containing network interfaces that have a private ip address starting with "10.":
| [? NetworkInterfaces [? starts_with(PrivateIpAddress, '10.')]]
Then select the fields just like you did before. This has not changed. (Note that you may want to select for all network interfaces instead of just the first.)
.{InstanceId:InstanceId,PrivateDnsName:PrivateDnsName,State:State.Name, IP:NetworkInterfaces[0].PrivateIpAddress}"
Full Example
aws ec2 describe-instances --filters "Name=tag-value,Values=mytagavalue" --query "Reservations[].Instances[] | [? NetworkInterfaces [? starts_with(PrivateIpAddress, '10.')]].{InstanceId:InstanceId,PrivateDnsName:PrivateDnsName,State:State.Name, IP:NetworkInterfaces[0].PrivateIpAddress}"
Further Reading
JMESPath Documentation - starts_with()
AWS Documentation - Controlling Command Output from the AWS Command Line Interface
AWS Documentation - Listing and Filtering Using the CLI and API