AWS CLI Script to add security groups - bash

I've a script that I'm using to run authorize-security-group-ingress AWS CLI command.
IP = 10.10.10.10
CIDR = 32
Variable = sudo aws ec2 authorize-security-group-ingress --group-id sg-xxxxxx --ip-permissions FromPort=10,ToPort=23,IpProtocol=tcp,IpRanges='[{CidrIp=$((IP / 32))}]'
$Variable
But I get an error CIDR block $((IP / 32)) is malformed. I tried changing the $((IP / 32)) block to $IP/32 , ($(IP) / $(CIDR)) but I still seem to get the same error. Can someone tell me what I'm doing wrong? The main issue is converting to a valid IP CIDR.

You could do as Siddarth mentioned. Or, fix your query. The issue with your code is that you are using a single-quote (') instead of double-quotes (") for IpRanges. As per this SO question, Single quotes won't interpolate anything, but double quotes will.
Once you replace it, your script will fail again because $((...)) is an arithmetic expansion. Remove the (()) in your script and it should work fine.
Final solution:
aws ec2 authorize-security-group-ingress --group-id sg-xxxxxx --ip-permissions FromPort=10,ToPort=23,IpProtocol=tcp,IpRanges="[{CidrIp=$IP/$CIDR}]"

Have you tried it like this
'[{"IpProtocol":"tcp","IpRanges": [{"CidrIp": "10.10.10.10/32"}]}]'
Replacing your line of code with this worked for me.

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'

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.

AWS EC2 and AMI tags with spaces using CLI

I try to create an instance using CLI, first like described in the doc (https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/run-instances.html, Example 4):
aws ec2 run-instances ... --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=val}]' 'ResourceType=volume,Tags=[{Key=Name,Value=val}]'
and it works well. The problem starts when I try to move whole tag-specifications in a separate bash variable, I need it because in fact there are many tags and they are built during the script run. So I do, but first use :
tags="--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=val}]' 'ResourceType=volume,Tags=[{Key=Name,Value=val}]'"
aws ec2 run-instances ... $tags
and it fails:
Error parsing parameter '--tag-specifications': Expected: '=', received: ''' for input:
'ResourceType=instance,Tags=[{Key=Name,Value=val}]'
^
If I remove single quotes then it works:
tags="--tag-specifications ResourceType=instance,Tags=[{Key=Name,Value=val_no_spaces}] ResourceType=volume,Tags=[{Key=Name,Value=val_no_spaces}]" # just works.
Despite it works, it's not good to me because if the values have spaces it stops working again:
tags="--tag-specifications ResourceType=instance,Tags=[{Key=Name,Value=val with spaces}] ResourceType=volume,Tags=[{Key=Name,Value=val with spaces}]"
Error parsing parameter '--tag-specifications': Expected: ',', received: 'EOF' for input:
ResourceType=instance,Tags=[{Key=Name,Value=val
^
I tried to wrap val into \", \' - neither works to me.
The same behavior is if you run very similar command aws ec2 create-image.
So, how can I add tags with spaces in the value and having them in a separate variable?
I had the same problem with aws cli. I solved it using arrays. In your case I would do the following:
tags=(
--tag-specifications
'ResourceType=instance,Tags=[{Key=Name,Value=val}]'
'ResourceType=volume,Tags=[{Key=Name,Value=val with spaces}]'
)
aws ec2 run-instances ... "${tags[#]}"

How to escape curly bracket in AWS CLI Bash

I'm trying to use AWS CLI Lambda to replace environment variables. However the value I want to replace has a pair of curly braces in it and CLI complaints about json format even when I already put the whole thing in single quote. Here's my command:
aws lambda update-function-configuration --function-name myFunc --environment Variables={URL='http://example.com/api/{0}'}
Here's the error:
Error parsing parameter '--environment': Expected: ',', received: '}' for input:
The funny thing is that if I removed the closing bracket }, it worked:
aws lambda update-function-configuration --function-name myFunc --environment Variables={URL='http://example.com/api/{0'}
Please help!!!
Enclose in double quotes:
Variables="{URL='http://example.com/api/{0}'}"
aws lambda update-function-configuration --function-name myFunc --environment Variables="{URL='http://example.com/api/{0}'}"
An error occurred (ResourceNotFoundException) when calling the
UpdateFunctionConfiguration operation: Function not found:
arn:aws:lambda:us-west-1:1234567890:function:myFunc
aws lambda update-function-configuration --function-name myFunc --environment "Variables={URL='http://example.com/api/{0}'}"
Here is the detailed issue regarding double quotes in aws cli
https://github.com/aws/aws-cli/issues/2638
This worked, my command is different though.
aws apigateway update-resource \
--rest-api-id <rest_api_id> \
--resource-id <resource_id> \
--patch-operations 'op=replace,path=/pathPart,value="{something}"'
The points are:
Single quote to for the whole argument,
Double quote to for the outer curly bracket.

how to use aws public ips with elixir

Have 2 iex shells running on different servers in EC2 but when I try to connect from one to the other I get this error:
Node.connect :them#ip-172-30-<--snip-->
** (ArithmeticError) bad argument in arithmetic expression
:erlang
It looks like elixir doesn't like that the hostname has dashes in it. How can I change the hostname without breaking the routing between the EC2 instances?
Thanks!
The error was caused by atom literal can not contain dash.
You can try :a-b-c and :"a-b-c" in iex.
So you should use Node.connect :"them#ip-172-30-<--snip-->".
Besides, you can use --name NAME instead of --sname NAME to name a node.
sname option makes and assigns a short name with your hostname.
You can name the node with --name like iex --name "them#thisismyhost.

Resources