Compare 2 successful results - bash

This results instances listed with ELB:
aws elb describe-load-balancers --load-balancer-name XXXXXXX --region us-east-1 | jq -r '.LoadBalancerDescriptions[].Instances[].InstanceId'
I need some help in writing a script, which checks for new aws instances attached to the ELB.
- Need to compare the present result and previous results, which helps us to get the new instance info.

Related

Create EC2 instance and get public IP when available

I have a monotonous work of creating an ec2 instance from an AMI and then ssh into it and run a crypto bot to get a sub domain SSL certificates for it and then run some frontend and backend onto it.
I would like to automate this...
I am able to create the EC2 instance
aws ec2 run-instances --image-id ami-0bef9cfcxxxxxx --count 1 --instance-type t2.medium --key-name MyKey --security-group-ids SG-1 --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=SubDomain}]'
but how do I wait till the instance is UP and get the public IP for the next steps?
Any suggestions would help,
Thanks!
Assuming you know the target instance id, you can query your instance and get the current state, instanceId, name (assuming you tagged them with a name) and public IP via something like:
aws ec2 describe-instances \
--instance-ids YOUR_TARGET_INSTANCE_ID \
--query "Reservations[*].Instances[*].[State.Name, InstanceId, Tags[?Key==\`Name\`]|[0].Value, PublicIpAddress]" \
--output text
You could run this query in a loop until the status comes back as running and then capture the public ip address:
while :
do
output=$(aws ec2 describe-instances \
--instance-ids YOUR_TARGET_INSTANCE_ID \
--query "Reservations[*].Instances[*].[State.Name, InstanceId, \
Tags[?Key==\`Name\`]|[0].Value, PublicIpAddress]" \
--output text)
if [[ "${output}" == running* ]] ; then
cut -d $'\t' -f4- <<<"${output}"
break
fi
done
Note:
The aws ec2 queries are all using the default AWS profile. You can specify a different profile via --profile your_target_profile_name if needed.
If you do not know your target instance id, you can remove the --instance-id portion of the aws ec2 query and list all of your instances (in your default region). You could choose the required instance id from that list.

AWS CLI - Create script to add my IP to security group

I'm trying to create a script to add my IP adress to AWS VPC security groups somthing like
> aws ec2 modify-security-group-rules --group-id GROUPID\
> --security-group-rules SecurityGroupRuleId= RULEID\
SecurityGroupRule={IpProtocol:'tcp',FromPort:433,ToPort:433,CidrIpv4:'MYIP'}
But I keep getting different errors like -
IpProtocol:tcp, type: <class 'str'>, valid types: <class 'dict'>
Can anyone please help figure out the correct syntax for this?
UPDATE:
I tried a new syntax that seems to work better
SecurityGroupRule={{IpProtocol=tcp},{FromPort=433},{ToPort=433},{CidrIpv4='IP'}}
But now I get a different error from AWS -
Invalid value for portRange. Must specify both from and to ports with TCP/UDP.
UPDATE: For reference - Here's the workaround I used- (based on John Rotenstein answer)
Instead of modifying the rule I create a new one each time and save the rule ID so I can delete it next time I run the script
IP=`curl -s http://whatismyip.akamai.com/`
aws ec2 revoke-security-group-ingress \
--group-id GROUP_ID \
--security-group-rule-ids $(cat ruleid_1.txt)
aws ec2 authorize-security-group-ingress --group-id GROUP_ID\
--ip-permissions "IpProtocol"="tcp","FromPort"=433,"ToPort"=443,"IpRanges"="[{CidrIp=$IP/32,Description=Shalev}]"|jq '.SecurityGroupRules[0].SecurityGroupRuleId' -r > ruleid_1.txt
Place value of parameter --security-group-rules inside quotes.
Both of the following seem to work for me (on Amazon Linux 2) -
Using double quotes for complete value, with description in single quotes-
aws ec2 modify-security-group-rules --group-id sg-xxx
--security-group-rules "SecurityGroupRuleId=sgr-xxx,SecurityGroupRule={Description='SSH
Test1',CidrIpv4=x.x.x.x/32,IpProtocol=tcp,FromPort=22,ToPort=22}"
Using single quotes for complete value, with description in double quotes-
aws ec2 modify-security-group-rules --group-id sg-xxx
--security-group-rules 'SecurityGroupRuleId=sgr-xxx,SecurityGroupRule={Description="SSH
Test2",CidrIpv4=x.x.x.x/32,IpProtocol=tcp,FromPort=22,ToPort=22}'
For reference - Here's the workaround I used- (based on John Rotenstein answer) Instead of modifying the rule I create a new one each time and save the rule ID so I can delete it next time I run the script
IP=`curl -s http://whatismyip.akamai.com/`
aws ec2 revoke-security-group-ingress \
--group-id GROUP_ID \
--security-group-rule-ids $(cat ruleid_1.txt)
aws ec2 authorize-security-group-ingress --group-id GROUP_ID\
--ip-permissions "IpProtocol"="tcp","FromPort"=433,"ToPort"=443,"IpRanges"="[{CidrIp=$IP/32,Description=Shalev}]"|jq '.SecurityGroupRules[0].SecurityGroupRuleId' -r > ruleid_1.txt
Here is a way to use the aws CLI to change a rule.
Requires "ec2:ModifySecurityGroupRules" permission.
aws ec2 describe-security-group-rules help
aws ec2 modify-security-group-rules --group-id sg--???????
--security-group-rules SecurityGroupRuleId=sgr---???????,SecurityGroupRule={IpProtocol=tcp,FromPort=22,ToPort=22,CidrIpv4=IP/32,Description="Regra
Alterada"}
Here's a script I use to add my current IP address to a Security Group:
IP=`curl -s http://whatismyip.akamai.com/`
aws ec2 authorize-security-group-ingress --group-name XXX --protocol tcp --port 22 --cidr $IP/32 --output text
It uses Akamai to retrieve my public IP address and then adds it to the desired Security Group.
Note that there is a limit to the number of rules in a Security Group, so eventually you will need to remove unused entries.
Use a variable for SecurityGroupRule.
Like:
IP=`curl -s http://whatismyip.akamai.com/`
security_group_rules={CidrIpv4=$IP/32,IpProtocol=tcp,FromPort=443,ToPort=443}
aws ec2 modify-security-group-rules \
--group-id sg-123 \
--security-group-rules SecurityGroupRuleId=sgr-123,SecurityGroupRule=$security_group_rules
It worked for me perfectly.
PS: This is my first answer here.

How can I get the the ID of an AWS security group if I know the name?

I'm using the AWS CLI and I want to get the ID of security group whose name I know (kingkajou_sg). How can I do it?
When I ask it to list all the security groups, it does so happily:
$ aws ec2 describe-security-groups | wc -l
430
When I grep through this information, I see that the SG in question is listed:
$ aws ec2 describe-security-groups | grep -i kingkajou_sg
"GroupName": "kingkajou_sg",
However, when I try to get the information about only that security group, it won't let me. Why?
$ aws ec2 describe-security-groups --group-names kingkajou_sg
An error occurred (InvalidGroup.NotFound) when calling the
DescribeSecurityGroups operation: The security group 'kingkajou_sg' does not exist in default VPC 'vpc-XXXXXXXX'
Can someone please provide me the one line command that I can use to extract the Security group's ID given its name? You can assume that the command will be run from within an EC2 which is in the same VPC as the Security group.
From the API Documentation:
--group-names (list)
[EC2-Classic and default VPC only] One or more security group names. You can specify either the security group name or the security group ID. For security groups in a nondefault VPC, use the group-name filter to describe security groups by name.
If you are using a non-default VPC, use the Filter
aws ec2 describe-security-groups --filter Name=vpc-id,Values=<my-vpc-id> Name=group-name,Values=kingkajou_sg --query 'SecurityGroups[*].[GroupId]' --output text
If it's in a VPC and you know the name & region and vpc id, you can try it like below:
aws ec2 describe-security-groups --region eu-west-1 --filter Name=vpc-id,Values=vpc-xxxxx Name=group-name,Values=<your sg name> --query 'SecurityGroups[*].[GroupId]' --output text
You just need to add --query 'SecurityGroups[*].[GroupId]' option with aws cli command.
aws ec2 describe-security-groups --group-names kingkajou_sg --query 'SecurityGroups[*].[GroupId]' --output text
To get the IDs of all security groups with a name matching exactly a specified string (default in this example) without specifying a VPC ID, use the following:
aws ec2 describe-security-groups --filter Name=group-name,Values=default --output json | jq -r .SecurityGroups[].GroupId
Note: this works for security groups even if they are not in the default VPC.
Small shell script to list security with search string as a variable. and we can tag the security groups.
https://ideasofpraveen.blogspot.com/2022/09/aws-cli-get-security-group-id-with-name.html.
If you want boto3 script to integrate with lambda for automations .
https://ideasofpraveen.blogspot.com/2022/09/aws-cli-get-security-group-id-with-name_15.html

How do I Copy the same AMI to multiple regions simultaneously?

I am trying to find a way to perform a simultaneously copy of a AMI to all other regions.
I have search near and far but beside seeing on a blog post that it can be done, I haven't found a way using aws cli ...
https://aws.amazon.com/blogs/aws/ec2-ami-copy-between-regions/
Currently I have written a bash script to do so, but I would like to find a better, easier way to do so
I have 8 AMI's that need to be passed to all regions.
using an array-
declare -a DEST=('us-east-1' ...2....3)
aws copy-image --source-region $SRC --region ${DESTx[#]} --source-ami-id $ami
Do you guys have any other suggestion?
Thanks.
you can make a single line bash, specially useful if in future there are new regions:
aws ec2 describe-regions
--output text |\
cut -f 3 | \
xargs -I {} aws copy-image
--source-region $SRC
--region {}
--source-ami-id $ami
basically it goes like this:
aws ec2 describe-regions --output text returns the list of all available regions for ec2, its a 3 columns table ("REGIONS", endpoint, region-name)
cut -f 3 takes the 3rd column of the previous table (read as list)
keep the current region from previous argument (xargs) into {} so you can send it to the region parameter of the copy-image command

aws ec2 cli + jq exclude results

I'm writing a bash script that needs to get the private ips of all instances where describe-instances does not return platform=>windows, and store them in an array $ips
This script works so far (just getting the private ips)
ips=$(aws ec2 describe-instances --region $r --filters "Name=tag:Name,Values=*$c*" | jq '.Reservations[].Instances[].NetworkInterfaces[].PrivateIpAddress')
but what I can't figure out is how to exclude windows servers (or, conversely, only include non-windows servers)
Here's what I've tried
--filters "Name=tag:Name,Values=*$c*" "Name=platform,Values="
--filters "Name=tag:Name,Values=*$c*" "Name=platform,Values=null"
--filters "Name=tag:Name,Values=*$c*" "Name=platform,Values=NULL"
I've also tried doing it on the jq side of the pipe, but my attempts were ridiculous and I will not publish them here. I did find out you cannot do more than two filters on that side (unless I messed that up too)
Any ideas?
I don't use AWS so I don't have much to go on but based off of the describe-instances reference, I think this filter should work.
.Reservations[].Instances |
map(select(.Platform != "Windows") | .NetworkInterfaces[].PrivateIpAddress)

Resources