Quick way to get AWS Account number from the AWS CLI tools? - amazon-web-services

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.

Related

How to retsrict AWS user to not spin more than one instance using cli?

I have a policy that allows the user to launch an EC2 instance in an AWS account, but I want to restrict the user to one instance only?
In the following command, I am using a --count keyword but this can be modified by the user to any number.
aws ec2 run-instances --image-id ami-00ee4df451840fa9d --count 1
--instance-type t2.micro --security-group-ids xxxxxxxxxxxx --key-name xxxxxxxxx --subnet-id xxxxxxxxx --profile userX --region us-west-2
Is there a way to restrict the user to run only one instance?
Thanks
It is not possible to use IAM Policies to restrict the quantity of Amazon EC2 instances that an IAM User can launch.
IAM Policies determine whether the user is permitted to make an API request (eg RunInstances()), but are not able to look at existing resources to make that decision.
You would need to create a 'service' that will launch instances on behalf of users, after first checking that no existing instance exists. For example, this could be a web-app that you write that verifies the conditions and then launches the instance on behalf of the user.
Also, please note that Amazon EC2 instances are not associated with 'users' -- they are associated with an AWS Account. Therefore, you would also need a means of associating existing instances with IAM Users, such as adding a Tag to identify the user who requested the instance. (Make sure that users don't have permission to modify this tag!)

Can AWS EC2 describe-volumes show ownerarn?

I am using the aws ec2 describe-volumes with the out showing this:
{
"Volumes": [
Is there anyway to include the ownerarn in this?
The AWS CLI describe-volumes documentation shows the output that will be returned.
I'm not sure what you mean by ownerarn, but Amazon EBS volumes belong to an AWS Account that is identified by a 12-digit number. The Account ID is not returned as part of the describe-volumes call, but you can obtain it by calling aws iam get-user and extracting the Account ID from the returned Arn for the user.
Within AWS, resources are linked to AWS Accounts. They are not linked to IAM Users.

How do I get the ARN for a security group in AWS

I'd like to be able to query the ARN of a security group, but queries like aws ec2 describe-security-groups only provide group IDs. Clearly security groups do have ARNs because API calls like aws datasync create-agent has options that require security group ARNs.
The ARN of security groups has known format:
arn:aws:ec2:<region>:<account>:security-group/<sg-group-id>
For example:
arn:aws:ec2:us-east-1:123445667:security-group/sg-11223344551122334
Thus you can always construct it yourself if its not explicitly given by AWS CLI.

Copy/Export AWS Security Group to multiple AWS accounts

I have multi-account AWS environment (set up using AWS Landing Zone) and I need to copy a specific security group to all the accounts. I do have a CFT written, but it's too much of a repetitive task to do this one by one.
The security group is in the central (shared-services) account, which has access to all the other accounts. It's better if there's a way to integrate this to Account Vending Machine (AVM) in order to avoid future tasks of exporting the SG to newly spawned accounts.
You should use CloudFormation Stacksets. StackSets is a feature of cloudformation in which you have a master account in which you create/update/remove the stackset, and you have children accounts. In the stackset, you configure your children aws accounts you want to deploy the CF template and the region as well.
From your comment, your master account is going to be the shared-services and the rest of your accounts, the children ones. You will need to deploy a couple of IAM roles to allow cross-account access, but after that, you will be able to deploy all your templates in up to 500 aws accounts automatically and update them as well.
More information here: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/what-is-cfnstacksets.html
You can export Security Group and other configuration with CloudFormation using CloudFormer, which creates a template from the existing account configuration. Check the steps in this guide https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-using-cloudformer.html It will upload the template on S3 and you can reuse it or some of its parts.
Since you are using AWS Landing Zone, you can add the security group to the aws_baseline templates, either as a new template or added to one of the existing files. When submitted, AWS Landing Zone uses Step Functions and AWS Stack Sets to deploy your SG to all existing and future accounts. If you choose to create the security group in a new file, you must add a reference to it in the manifest.yaml file (compare with how the other templates are referenced).
I was able to do this via the Account Vending Machine. But AGL's Stacksets should be a good alternative too.
To copy AWS Security Gp from one account of any region to other AWS account to any region is required lots of scripting(coding) in aws cli or boto3.
But one thing i done which is feasible to my usecase(Whitelist 14 IPs for HTTPS) is write a bash script
Here prior i create a blank SG on other AWS account(or u may use aws cli to create that too),
`
Region1=
SGFromCopy=
profilefromcopy=
Region2=
SGToCopy=
profiletocopy=
for IP in $(aws ec2 describe-security-groups --region $Region1 --group-id=$SGFromCopy --profile $profilefromcopy --query SecurityGroups[].IpPermissions[].IpRanges[].CidrIp --output text) ;
do
aws ec2 authorize-security-group-ingress --group-id=$SGToCopy --ip-permissions IpProtocol=TCP,FromPort=443,ToPort=443,IpRanges=[{CidrIp=$IP}] --profile $profiletocopy --region $Region2;
done ;
`
U may modify script if u have csv formated of SG and then just had iterated in while loop
BONUS
To get desire output you have to alter output in file or some where else
> aws ec2 describe-security-groups --region $Region1 --group-id $SGFromCopy --profile $profilefromcopy --query SecurityGroups[].IpPermissions[] --output text

AWS Cloudformation: Is it possible to access user id inside a Cloudformation template?

I would like to auto-tag certain AWS resources defined in a CloudFormation template with the user who uses the template to create a stack. Is it possible to access any sort of user id in the template?
I don't think this is possible.
AWS services are tied to AWS Accounts. Once IAM confirms that a particular user has permission to make an API call, resources that are generated become associated with an Account rather than a particular User. For example, it is not possible to look at an EC2 instance and determine who launched the instance.
This information is, however, available in AWS CloudTrail, but that is more of an audit log — it does not provide the user information back to the service.
So, I suspect that a stack is not provided with information about the User that launched it.
There is one way of doing it, but it isn't pretty and there is a caveat.
You can run a bash script like the below on an ec2 instance:
AWS_INSTANCE_ID=`curl -s http://169.254.169.254/latest/meta-data/instance-id`
USER_ID=`aws sts get-caller-identity --output text --query 'Arn'`
aws ec2 create-tags --resources "${AWS_INSTANCE_ID}" --tags 'Key=CreatedBy,Value="${USER_ID}"' --region eu-west-1
That will tag the current instance with the name of the user that run the CLI on that instance.
The caveat is however that the CLI needs to be run by the user - and not a role, so your users keys will have to be copied to the server - and then removed again at the end of the script.
Not ideal, but it gives you an option.