I'm running into quoting issues with AWS CLI when trying to update description of security group rules.
Can anyone advise how I can rewrite this piece to accommodate a list of IPs?
while read -r line; do
aws ec2 update-security-group-rule-descriptions-ingress \
--group-id sg-123456 \
--region us-east-2 \
--ip-permissions "[{'IpProtocol': 'tcp', 'FromPort': 443, 'ToPort': 443, 'IpRanges': [{'CidrIp': ${line}, 'Description': 'Meaningful description'}]}]"
done < ip_list
Move the single quotes to encompass the whole JSON, then use double quotes for the JSON content, which typically expects double quotes.
--ip-permissions '[{"IpProtocol": "tcp", "FromPort": 443, "ToPort": 443, "IpRanges": [{"CidrIp": ${line}, "Description": "Meaningful description"}]}]'
I ended up having to use this format:
while IFS=, read -r IP CLIENT_DESC
do
aws ec2 authorize-security-group-ingress --region us-east-2 --group-id sg-123456 --ip-permissions IpProtocol=tcp,FromPort=443,ToPort=443,IpRanges="[{CidrIp=${IP},Description=${CLIENT_DESC}}]"
done < server_rules
Related
I am trying to run the following command by reading cidr ips out of a txt file.
aws ec2 authorize-security-group-ingress --group-id $sgid --ip-permissions '[{"IpProtocol": "tcp", "FromPort": 9092, "ToPort": 9092, "IpRanges": [{"CidrIp": '${cidreip}', "Description": "$train us-east-2"}]}]'
When I try this with a single quote around my variable for cidr ip, I get the below error.
Error parsing parameter '--ip-permissions': Invalid JSON: Expecting ',' delimiter: line 1 column 87 (char 86)
Trying it with a double quote around the variable, the command takes it as a literal value. Not a variable.
How do I work around it? I tried escaping. I tried using the following
aws ec2 authorize-security-group-ingress --group-id $sgid --ip-permissions "[{"IpProtocol": "tcp", "FromPort": 9092, "ToPort": 9092, "IpRanges": [{"CidrIp": "$cidreip", "Description": "$train us-east-2"}]}]"
and I get a Error parsing parameter '--ip-permissions': Invalid JSON: error.
Please help. Thanks in advance.
First JSON does not use ', but you need ". Also you have to build your string in chunks:
aws ec2 authorize-security-group-ingress --group-id 33333 --ip-permissions '[{"IpProtocol": "tcp", "FromPort": 9092, "ToPort": 9092, "IpRanges": [{"CidrIp": "'${cidreip}'", "Description": "'${train}' us-east-2"}]}]'
My exposed service on nodePort seems to not allow traffic through it.
So how to add rules to allow traffic for that port range on CLI not on the console?
EC2 Security groups
There is a security group on your screen.
See more about security groups:
EC2 Security Groups
Creating a Security Group
CLI for AWS Security groups
As for CLI for working with AWS Security groups, see this article: Creating, Configuring, and Deleting Security Groups for Amazon EC2 - AWS Command Line Interface
$ aws ec2 create-security-group --group-name my-sg --description "My security group" --vpc-id vpc-1a2b3c4d
{
"GroupId": "sg-903004f8"
}
$ aws ec2 authorize-security-group-ingress --group-id sg-903004f8 --protocol tcp --port 3389 --cidr 203.0.113.0/24
The following command adds another rule to enable SSH to instances in the same security group.
$ aws ec2 authorize-security-group-ingress --group-id sg-903004f8 --protocol tcp --port 22 --cidr 203.0.113.0/24
To view the changes to the security group, run the describe-security-groups command.
$ aws ec2 describe-security-groups --group-ids `sg-903004f8`
O/P is:
{
"SecurityGroups": [
{
"IpPermissionsEgress": [
{
"IpProtocol": "-1",
"IpRanges": [
{
"CidrIp": "0.0.0.0/0"
}
],
"UserIdGroupPairs": []
}
],
"Description": "My security group"
"IpPermissions": [
{
"ToPort": 22,
"IpProtocol": "tcp",
"IpRanges": [
{
"CidrIp": "203.0.113.0/24"
}
]
"UserIdGroupPairs": [],
"FromPort": 22
}
],
"GroupName": "my-sg",
"OwnerId": "123456789012",
"GroupId": "sg-903004f8"
}
]
}
P.S. awless.io - A Mighty CLI for AWS
There is also a bit outdated but still convenient CLI tool:
wallix/awless: A Mighty CLI for AWS
A Mighty CLI for AWS http://awless.io/
Here the Medium post about it
after the VPC is created, how I can grep only 1 VPC-ID from specific VPC by aws ec2 describe-vpcs, so that VPC ID can be passed inside the script for the next step, I know I can see it manually from that command or from AWS console,
for example:
aws ec2 describe-vpcs --vpc-ids |grep VpcId
"VpcId": "vpc-00a0338c2f671a77c",
"VpcId": "vpc-0b3697513d5987516",
"VpcId": "vpc-061e25f5f78877798",
it gives me all of them, or:
aws ec2 describe-vpcs --vpc-ids |grep -i ansible
"Value": "ANSIBLE_VPC",
but I need only to get the VPC-ID for that specific VPC from command.
If you just issued a create-vpc command, then the VPC ID of that VPC would have been returned in response to that command:
Output:
{
"Vpc": {
"CidrBlock": "10.0.0.0/16",
"DhcpOptionsId": "dopt-5EXAMPLE",
"State": "pending",
"VpcId": "vpc-0a60eb65b4EXAMPLE", <-- This is the VPC ID
"OwnerId": "123456789012",
"InstanceTenancy": "default",
"Ipv6CidrBlockAssociationSet": [],
"CidrBlockAssociationSet": [
{
"AssociationId": "vpc-cidr-assoc-07501b79ecEXAMPLE",
"CidrBlock": "10.0.0.0/16",
"CidrBlockState": {
"State": "associated"
}
}
],
"IsDefault": false,
"Tags": []
}
}
Thus, you could create the VPC and store its ID like this:
$ ID=`aws ec2 create-vpc --cidr-block 10.0.0.0/16 --query Vpc.VpcId --output text`
$ echo $ID
vpc-0fb4d08f9d6501e94
If, instead, you are seeking the VPC ID for a VPC given its Name tag, you could use:
$ ID=`aws ec2 describe-vpcs --filter Name=tag:Name,Values=ANSIBLE_VPC --query Vpcs[].VpcId --output text`
$ echo $ID
vpc-0fb4d08f9d6501e94
You can use just the aws cli for this, with filters and query:
aws ec2 describe-vpcs --filters Name=tag:Name,Values=ANSIBLE_VPC --query "Vpcs[].VpcId" --output text"
Or you can use a mix of the --filters command with grep to accomplish your task:
aws ec2 describe-vpcs --filters Name=tag:Name,Values=ANSIBLE_VPC | grep VpcId | grep -oh "vpc-\w*"
Is it possible to revoke all the ingress rules in an AWS security group? Is it possible to revoke all the SSH ingress rules? I'm trying with the cli command below, but it's not working:
aws ec2 revoke-security-group-ingress --group-id GroupID --protocol tcp --port 22
Based on the suggestion of #kuboon, here is a simpler, working version of that script, tested in zsh. The key differences are:
Forcing the first command to return json (which is not always the default) by explicitly using --output json option
Passing that result to parameter --ip-permissions of revoke-security-group-ingress rather than as a fully-formatted command in json (which it is not) that --cli-input-json would require.
groupId="your group-id"
aws ec2 revoke-security-group-ingress --group-id $groupId \
--ip-permissions \
"`aws ec2 describe-security-groups --output json --group-ids $groupId --query "SecurityGroups[0].IpPermissions"`"
I ended up writing a Powershell script that uses the AWS CLI to do that.
The script goes through all the regions, looks for the default security group, and deletes all rules in it.
Here it is:
# get all regions
write-host "Getting all regions.."
$regions = ([string](aws ec2 describe-regions --region eu-west-2) | ConvertFrom-Json).Regions.RegionName
write-host "Got them:"
$regions
write-host "-------------------"
write-host ""
# for all regions
foreach ($region in $regions)
{
write-host "Getting default security groups for $region.."
# get all subnets
$groupIds = ([string](aws ec2 describe-security-groups --filters Name=group-name,Values=default --region $region) | ConvertFrom-Json).SecurityGroups.GroupId
foreach ($groupId in $groupIds)
{
write-host "Got it: $groupId"
write-host "Getting all rules.."
$rules = [string](aws ec2 describe-security-groups --group-id $groupId --query "SecurityGroups[0].IpPermissions" --region $region) | ConvertFrom-Json
foreach ($rule in $rules)
{
$protocol = $rule.IpProtocol
$cidr = $rule.IpRanges.CidrIp
$fromPort = $rule.FromPort
$toPort = $rule.ToPort
$cidrIpv6 = $rule.Ipv6Ranges.CidrIpv6
$sourceGroup = $rule.UserIdGroupPairs.GroupId
$sourceGroupUserId = $rule.UserIdGroupPairs.UserId
if ($protocol -eq "icmpv6") {
$protocol = "icmp"
}
if (($protocol -eq "tcp") -Or ($protocol -eq "udp") -Or ($protocol -eq "icmp"))
{
if ($cidr){
if ($fromPort -eq -1){
write-host "Removing rule from security group using this command:"
write-host "aws ec2 revoke-security-group-ingress --group-id $groupId --protocol $protocol --port "$fromPort" --cidr $cidr --region $region"
aws ec2 revoke-security-group-ingress --group-id $groupId --protocol $protocol --port "$fromPort" --cidr $cidr --region $region
write-host "Done!"
query
}
else {
write-host "Removing rule from security group using this command:"
write-host "aws ec2 revoke-security-group-ingress --group-id $groupId --protocol $protocol --port "$fromPort-$toPort" --cidr $cidr --region $region"
aws ec2 revoke-security-group-ingress --group-id $groupId --protocol $protocol --port "$fromPort-$toPort" --cidr $cidr --region $region
write-host "Done!"
}
}
if ($cidrIpv6){
$json = ('{"IpProtocol": "'+$protocol+'", "FromPort": '+$fromPort+', "ToPort": '+$toPort+', "Ipv6Ranges": [{"CidrIpv6": "'+$cidrIpv6+'"}]}') | ConvertTo-Json
write-host "Removing Ipv6 version of rule from security group using this command:"
write-host "aws ec2 revoke-security-group-ingress --group-id $groupId --ip-permissions $json --region $region"
aws ec2 revoke-security-group-ingress --group-id $groupId --ip-permissions $json --region $region
write-host "Done!"
}
if ($sourceGroup -and $sourceGroupUserId)
{
write-host "Removing SourceGroup rule from security group using this command:"
write-host "aws ec2 revoke-security-group-ingress --group-id $groupId --protocol $protocol --port "$fromPort-$toPort" --cidr $cidr --region $region"
aws ec2 revoke-security-group-ingress --group-id $groupId --protocol $protocol --port "$fromPort-$toPort" --source-group $sourceGroup --group-owner $sourceGroupUserId --region $region
write-host "Done!"
}
}
else
{
if ($cidr){
write-host "Removing rule from security group using this command:"
write-host "aws ec2 revoke-security-group-ingress --group-id $groupId --protocol $protocol --cidr $cidr --region $region"
aws ec2 revoke-security-group-ingress --group-id $groupId --protocol $protocol --cidr $cidr --region $region
write-host "Done!"
}
if ($cidrIpv6){
$json = '{"IpProtocol": "-1", "Ipv6Ranges": [{"CidrIpv6": "'+$cidrIpv6+'"}]}' | ConvertTo-Json
write-host "Removing Ipv6 version of rule from security group using this command:"
write-host "aws ec2 revoke-security-group-ingress --group-id $groupId --ip-permissions $json --region $region"
aws ec2 revoke-security-group-ingress --group-id $groupId --ip-permissions $json --region $region
write-host "Done!"
}
if ($sourceGroup)
{
$json = '{ "IpProtocol": "-1", "UserIdGroupPairs":[{"GroupId":"'+$sourceGroup+'","UserId":"'+$sourceGroupUserId+'"}] }' | ConvertTo-Json
write-host "Removing SourceGroup rule from security group using this command:"
write-host "aws ec2 revoke-security-group-ingress --group-id $groupId --ip-permissions $json --region $region"
aws ec2 revoke-security-group-ingress --group-id $groupId --ip-permissions $json --region $region
write-host "Done!"
}
}
}
}
write-host "-------------------"
write-host ""
}
N.B.
This script cannot delete some rules (custom protocols, Custom ICMP Rule - IPv6), but it works for most rules.
I tested the script on the following set of rules:
This is what is left after running the script:
Hope this helps somebody out there!
It looks like you have to specify each source individually, for example --cidr 0.0.0.0/0 or --source-group sg-12345678.
Get list of rules and revoke all.
groupId="your group-id"
json=`aws ec2 describe-security-groups --group-id $groupId --query "SecurityGroups[0].IpPermissions"`
aws ec2 revoke-security-group-ingress --cli-input-json "{\"GroupId\": \"$groupId\", \"IpPermissions\": $json}"
Just a minor improvement to demonicdaron's script, more than 1 cidr can be returned to the same rule, in this case you just do a foreach() on the $cidr to loop over everyone.
But it works like a charm
How to remove all rules for a given port using the "aws ec2"?
aws ec2 revoke-security-group-ingress --group-name MySecurityGroup --protocol tcp --port 22 **--ALL-IP**
As per the documentation, This commands works on either --cidr or --source-group. so If you have multiple IP addresses then I would say the only option is to run the same command multiple times for the individual IP address (which would take the form of 1.1.1.1/32).
Or,
You can list all the ipadress in cidr format (1.1.1.1/32) in a file (each ip address on a new line) and then run a for loop over it running above command for each iteration. e.g.
for i in `cat ip_address_cidr.txt`; do aws ec2 revoke-security-group-ingress --group-name MySecurityGroup --protocol tcp --port 22 $i; done
I have not tested above command syntax but that should do it so that you can revoke the rules in a single one-liner command.
I think that this is what you are looking for: How to Close All Open SSH Ports in AWS Security Groups
Here a solution for a specific security group-id:
#!/bin/bash
sg = {security group}
# get the cidrs for the ingress rule
rules=$(aws ec2 describe-security-groups --group-ids $sg --output text --query 'SecurityGroups[*].IpPermissions')
# rules will contain something like:
# 22 tcp 22
# IPRANGES 108.42.177.53/32
# IPRANGES 10.0.0.0/16
# 80 tcp 80
# IPRANGES 0.0.0.0/0
# luckily, aws returns all ipranges per port grouped together
# flag for if we are reading ipranges
reading=0
# loop returned lines
while read -r line; do
# split the line up
rulebits=($line)
# check if if we are reading ssh port ipranges
if [ $reading -eq 0 ] ; then
# we are not reading ipranges
# check if '22 tcp 22'
if [ ${rulebits[0]} == "22" ] && [ ${rulebits[1]} == "tcp" ] && [ ${rulebits[2]} == "22" ] ; then
# found it
reading=1
fi
else
# we are reading ipranges
# check if first word is 'IPRANGES'
if [ ${rulebits[0]} == "IPRANGES" ] ; then
# found a cidr for open ssh port
cidr=${rulebits[1]}
echo -n found port 22 open cidr $cidr closing...
# close it
result=$(aws ec2 revoke-security-group-ingress --group-id $sg --protocol tcp --port 22 --cidr $cidr --output text)
if [ "$result" == "true" ] ; then
echo " OK"
else
echo " ERROR"
fi
else
# new port
reading=0
fi
fi
done
revoke-security-group-ingress in version 2 gives us to specify multiple IP CIDRS. See below solution written in PHP which I am trying to clean in multiple region and multiple prots.
To specify multiple rules in a single command use the --ip-permissions option https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/revoke-security-group-ingress.html
$cleanports = [22,5984];
$sgids = [["sgid"=>"sg1","region"=>"us-east-1"],["sgid"=>"sg1","region"=>"us-east-1"]];
foreach($sgids as $sgidDetail){
$iprules = json_decode(shell_exec("/usr/bin/aws ec2 describe-security-groups --group-ids {$sgidDetail['sgid']} --region {$sgidDetail['region']} --query 'SecurityGroups[*].IpPermissions'"), true)[0];
foreach ($iprules as $key => $ips) {
if(!empty($ips['FromPort']) && !empty($ips['ToPort']) && in_array($ips['FromPort'], $cleanports) && in_array($ips['ToPort'], $cleanports)){
echo "\n\n";
echo shell_exec("/usr/bin/aws ec2 revoke-security-group-ingress --group-id {$sgidDetail['sgid']} --region {$sgidDetail['region']} --ip-permissions '".json_encode($ips)."'");
}
}
}