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

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.

Related

AWS CLI: How to use variable to filter EFS

I want to use the value of the DOMAIN_ID variable to filter the EFS to get a FileSystemId. I used the commands below. The first command works and it stores the domain ID. The second one returns an empty list, even though the DOMAIN_ID variable is present.
DOMAIN_ID=$(aws sagemaker list-domains --query 'Domains[0].DomainId')
aws efs describe-file-systems --query 'FileSystems[?CreationToken==`$DOMAIN_ID`].FileSystemId'
Output:
[]
Expected output:
<Some EFS identifier>
This works (escaping backticks) -
aws efs describe-file-systems --query "FileSystems[?CreationToken==\`$DOMAIN_ID\`].FileSystemId"
You can also use describe-domain command instead -
$ DOMAIN_ID=$(aws sagemaker list-domains --query 'Domains[0].DomainId' | tr -d '"')
$ aws sagemaker describe-domain --domain-id $DOMAIN_ID --query 'HomeEfsFileSystemId'

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 --query parameter

I am trying to do a filter using aws query to output 0.0.0.0/0 Ips and find which ports they are coming from however when I do
aws ec2 describe-security-groups --filters Name=ip-permission.cidr,Values='0.0.0.0/0' --query "SecurityGroups[*].{GN:GroupName,Ports: IpPermissions.FromPorts}" --output json
In the Ports column, it outputs None, since it is not finding that filter and when I do
aws ec2 describe-security-groups --filters Name=ip-permission.cidr,Values='0.0.0.0/0' --query "SecurityGroups[*].{GN:GroupName,Ports: IpPermissions}" --output json
I get all the Ip Ranges when I only want 0.0.0.0/0 and which Port that Open Ip is coming from (FromPort and ToPort). And I don't want to do a filter just for a certain Port because I want to see what port each open Ip is coming from.
I am not sure why this is not working since the IpPermissions.ToPort and IpPermissions.FromPort are both a filter of aws security groups.
You need two modification in the query
The key name is FromPort not FromPort
IpPermissions return array not object, so use IpPermissions[].FromPort
aws ec2 describe-security-groups --filters Name=ip-permission.cidr,Values='0.0.0.0/0' \
--query "SecurityGroups[*].{GN:GroupName,Ports: IpPermissions[].FromPort}" --output json

Compare 2 successful results

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.

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

Resources