AWS EC2 un-assign or remove a security group using API - amazon-web-services

For a AWS EC2 Instance, Is it possible to unassign or remove a security group from a instance using the cmd line. It is easy to do via the UI, but I can't seem to do it easily via the API. I am restricted to using AWS cli version 1 for now. https://docs.aws.amazon.com/cli/latest/reference/ec2/index.html
I have looked at using the modify instance attribute but it seems like a really round about way to unassign a security group from a instance. I have to reassign all other groups except for the security group I do not want assigned
aws ec2 modify-instance-attribute --instance-id [Instance ID] --groups [groups]
Deleting the security group, will not work as it is assigned to a instance.
aws ec2 delete-security-group --group-id [grou id]
I get the correct error
<br>
An error occurred (DependencyViolation) when calling the DeleteSecurityGroup operation
Is there a easier way to remove or unassign a security group from a instance other than using the modify-instance-attribute using the cmd line?

Related

How do I assign a new security group to an EC2 instance without removing the currently attached security groups using AWS CLI?

The AWS CLI command to attach a security group to running EC2 instance is as below.
aws ec2 modify-instance-attribute --instance-id i-12345 --groups sg-12345 sg-67890
But the above command will remove the currently attached security groups and attach the new one.
I have a use case where there are 100+ servers and I have to attach a new security group to all those servers without detaching the current security groups.
How can I achieve this using the AWS CLI?
The --groups does a complete replacement based on the arguments passed & there's no way to bypass this behaviour so you'll need to implement the logic of getting the existing security groups (SGs), appending the new SG on & then passing that as an input to --groups.
Confirmed by aws ec2 modify-instance-attribute documentation:
--groups (list)
[EC2-VPC] Replaces the security groups of the instance with the specified security groups. You must specify at least one security group, even if it’s just the default security group for the VPC. You must specify the security group ID, not the security group name.
(string)
This command should store all of the security groups for an instance with ID i-12345 in $securitygroups:
securitygroups=$(aws ec2 describe-instances --instance-ids i-12345 --query "Reservations[].Instances[].SecurityGroups[].GroupId[]" --output text)
The output of echo $securitygroups will look something similar to this:
sg-074bb9206bd7edaf2 sg-07cd92995b937cbd2 sg-05414d9cef32901be
Given that your new security group ID is sg-67890, execute the below command to append the new SG ID onto the list of security groups that we want to set (the space is important & needed):
securitygroups+=" sg-67890"
The output of echo $securitygroups should now have the new SG ID appended:
sg-074bb9206bd7edaf2 sg-07cd92995b937cbd2 sg-05414d9cef32901be sg-67890
Finally, pass $securitygroups to the --groups option of aws ec2 modify-instance-attribute.
This variable will contain the existing assigned SG IDs as well as the new SG ID to be assigned so it'll be an assigning the new SG without unassigning any current SGs:
aws ec2 modify-instance-attribute --instance-id i-067a3aae02b8239e6 --groups $securitygroups
Put this in a loop for however many instances you have, problem solved.

AWS Security Groups Rules- add or delete

I have been asked to automate addition or deletion of rules in AWS Security Groups. Before I perform the action, I need to validate if the requested rules (taken as parameter) exists in the security groups or not, only if the rule exists we need to add or delete the rule.
I am trying to use below which will list all the ingress rules of the Security Group and delete it:
aws ec2 describe-security-groups --group-ids sg-XX --query SecurityGroups[].IpPermissions[]
aws ec2 revoke-security-group-ingress --group-id sg-XX --ip-permissions "`aws ec2 describe-security-groups --group-ids sg-XX --query SecurityGroups[].IpPermissions[]`"
But I need to just validate if the rule exists or not, if it exists I don't have to perform any activity, if it doesn't exists then I need to add the rule to the existing security group.

How to set "Name" of security group (AWS EC2)

Creating an EC2 security group through the console allows you to set a "group name" and it automatically provides a "group id".
However the "name" is always blank, unless the security group was generated automatically by elastic beanstalk or another resource.
Is there any way to set this name in the console, otherwise how is it done in the CLI?
You can either edit the name directly in the console or attach a Name tag to your security group.
Using AWS CLI:
aws ec2 create-tags --resources <sg_id> --tags Key=Name,Value=Test-Sg

Quick way to get AWS Account number from the AWS CLI tools?

Looking for a quick way to pull my account number, I had originally thought of using aws iam get-account-authorization-details --max-items 1 but there are several issues with doing it this way. Is there a way to do this that might not cross account origins?
You can get the account number from the Secure Token Service subcommand get-caller-identity using the following:
aws sts get-caller-identity --query Account --output text
From my related answer for the AWS PowerShell CLI, your Account ID is a part of the Arn of resources that you create... and those that are automatically created for you. Some resources will also list you as an OwnerId.
The Default Security Group is automatically created for you in each region's default VPC as a reserved security group. From the documentation:
You can't delete a default security group. If you try to delete the EC2-Classic default security group, you'll get the following error: Client.InvalidGroup.Reserved: The security group 'default' is reserved. If you try to delete a VPC default security group, you'll get the following error: Client.CannotDelete: the specified group: "sg-51530134" name: "default" cannot be deleted by a user.
This makes it a reliable candidate for retrieving our account Id, as long as you are in EC2 classic or have a default VPC (*see edge cases if you don't).
Example:
aws ec2 describe-security-groups \
--group-names 'Default' \
--query 'SecurityGroups[0].OwnerId' \
--output text
This uses --query to filter the output down to the "owner ID" for the first result from this request, and then uses --output to output your account ID as plaintext:
123456781234
Edge cases:
(Thanks #kenchew) Note that if you've deleted your default VPC in a given region, this security group no longer exists and you should use one of these alternative solutions:
query STS get-caller-identity, per #Taras
use the first security group returned, per #Phillip
Further reading:
AWS EC2 Documentation: Default Security Groups
AWS CLI Documentation: aws ec2 describe-security-groups
Controlling Command Output from the AWS Command Line Interface
If you are running on a server that is running with an assumed role you can't call aws sts get-caller-identity. Also, with describe-security-groups you can't always use the --group-names filter (it doesn't work if you don't have a default VPC), so just pick the first security group. I've found this to be the most reliable regardless of what sort of authentication you use or what sort of VPC you have.
aws ec2 describe-security-groups --query 'SecurityGroups[0].OwnerId' --output text
My favorite method is to use aws iam get-user [--profile <profile>] since you only need IAM self service role for this to work.

Can I tell what AWS loadbalancer my EC2 instance is associated with?

The problem I am trying to solve is how to make my code running within an EC2 instance which is part of a load balanced AWS cluster aware of how many other EC2 instances are withing the same cluster/loadbalancer.
I have the following code which when given the name of a LoadBalancer can tell me how many EC2 instances are associated with that Loadbalancer.
DescribeLoadBalancersResult dlbr = loadBalancingClient.describeLoadBalancers();
List<LoadBalancerDescription> lbds = dlbr.getLoadBalancerDescriptions();
for( LoadBalancerDescription lbd : lbds )
{
if( lbd.getDNSName().equalsIgnoreCase("MyLoadBalancer"))
{
System.out.println(lbd.getDNSName() + " has " + lbd.getInstances().size() + " instances") ;
}
}
which works fine and prints out the loadbalancer name and number of instances is has associated with it.
However I want to see if I can get this info without having to provide the Loadbalancer name. In our setup an EC2 instance will only ever be associated with one Loadbalancer so is there any way to go back the way from EC2 instance to Loadbalancer?
I figure I can go down the route of getting all loadbalancers from All regions, iterating through them until I find the one that contains my EC2 instance but I figured there might be an easier way?
An interesting challenge -- I would have to wrangle with the code myself to think this through, but my gut first response would be to use the AWS CLI here, and to just invoke it from within your Java/C#.
You can make this call:
aws elb describe-load-balancers
And get all manner of information about any and all ELBs, and could simply --query filter that by the instance ID of the instance making the call anyway -- in order to find out what other friends the instance has joined to its same ELB. Just call the internal instance metadata to get that ID:
http://169.254.169.254/latest/meta-data/instance-id
Or another fun way to go would be to bootstrap your instance AMIs so that when they are spawned and joined to an ELB, they register themselves in a SimpleDB or DynamoDB table. We do this all the time as a way of keeping current inventories of websites, or software installed, etc. So this way you would have a list, which you could then keep trimmed by checking for "running" status.
EDIT - 4/13/2015
#MayoMan I have hadto make use of this as well in some current work -- to identify healthy instances attached to an ELB in an auto-scaling group and then act upon them. I've found 'jq' to be a really helpful command-line tool. You could also make these calls directly to an ELB, but here it's describing an ASG:
aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names <ASG Name> | jq -r .AutoScalingGroups[0].Instances[0].HealthStatus
Or to list the InstanceIds themselves:
aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names <ASG Name> | jq -r .AutoScalingGroups[0].Instances[0-3].InstanceId