avatarTeri Radichel

Summarize

Getting Account Number by Account Name with the AWS CLI

ACM.239 Also, the joys of AWS CLI Filtering and Querying

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

⚙️ Check out my series on Automating Cybersecurity Metrics | Code.

🔒 Related Stories: AWS Security | AWS Organizations

💻 Free Content on Jobs in Cybersecurity | ✉️ Sign up for the Email List

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In the last post I took a look at possible processes to require multiple people to update domain name NS records.

I was going to jump into a simplified version of the above but it’s just not simple. I started down a few paths and backtracked. In the end, a couple of the paths had the same problem. I’m trying to update an account that I didn’t create with this framework. In need the account number and I can’t get it from CloudFormation. What I thought would be two lines of code turned into this post.

TLDR; Spaces in account names mess with grep and cut solutions. AWS CLI querying and filtering is easy to mess up. See the final function at the end. It was literally a single line of code to query the account number from the account name, in the end.

Getting the account number from CloudFormation stack outputs

I’ve been using a function that gets the account number for an account name if the account was deployed my CloudFormation functionality. It looks up the ID from the CloudFormation stack.

I recently needed to get an AWS account number for all my accounts including those I had migrated to my organization. The migrated accounts won’t be in CloudFormation stacks. What to do?

I renamed the existing function in case anyone wants to use it. It is a handy function if you want to validate that an account was created by CloudFormation before taking some action on it:

Looking up AWS account information with he AWS CLI directly

Then I created a new function that looks up the account number using other CLI functions. This will work when I need to get the account number for any account, not just those that I created via CloudFormation.

I’m going to use the list-accounts function, which as you can see outputs both the name and account number:

Filtering and Querying with the AWS CLI

What I need to do is filter on the account that has a name matching the one I’m trying to find. At first I tried to use grep and cut as that is way simpler than than the AWS CLI query options. However, I hit a glitch when one of my account names had a space in it. Back to the drawing board and AWS CLI filtering options. I could also use jq but I find that equally as unappealing. Let’s see if the built in querying can get the job done.

We could use server side filtering, if possible, because we don’t need all the accounts to be pulled down. Unfortunately that only works if the CLI supports it and this one does not. I don’t see filters in the documentation at the time of this writing.

Let’s try the query option which is client side filtering.

Interesting. I don’t recall seeing this note on quotes before. I probably just missed it. Good to know.

So after looking at the examples in the above this should work:

--query 'Accounts[?Name == `$account_name`]'

Think of it like this. If we wanted all the accounts we would write:

--query 'Accounts[*]

Instead of the asterisk I’m adding a query to filter on a specific account name. I don’t know why but the positioning of all these things trips me up and I want to write:

--query 'Accounts[*].[?Name == `$account_name`]'

I think of the above as “give me all the accounts and then filter on the one with the right account name”.

So anyway…it can be confusing to query and filter with the AWS CLI. The syntax is not intuitive. At least not to me, and I’ve been programming for a long time. I can figure out a lot of things in a new language without looking it up after I get the gist of it. And I still can’t remember or easily determine the query I need for an AWS CLI command.

Note that the backticks in the above example around account name are not single quotes. I’ve made that mistake before as well.

Also, I only want the Id of the account, not all the other data above.

--query 'Accounts[?Name == `$account_name`].Id'

And…troubleshooting AWS CLI filters and queries

Here’s where it gets weird. I wasn’t getting an account number back so I printed out the exact command being executed in my function.

And it works:

aws organizations list-accounts --query 'Accounts[?Name == `Domains`].Id' --output text --profile OrgRoot

So why doesn’t it work in my function when concatenated and executed as a command?

I changed the function to create a string with the command first, and then execute the command string:

I copied and pasted what went into the echo statement so I know there are no typos. I get this:

Bad value for --query 'Accounts[?Name: Bad jmespath expresion: Unclosed 'delimiter: 
'Accounts [?Name
^

If I leave out the escape slashes in front of the backticks I get this because it appears that quotes are ending the command — which is usually not a good thing when it comes to security, but I digress.

command not found

Next I tried this without trying to output the command into a variable and to see if the account number gets printed out.

No output from the second line even though the first line works if I copy and paste it directly into the console.

I tried numerous variations of quotes and then I finally copied the account name into the query like this:

aws organizations list-accounts --query 'Accounts[?Name == `Domains`].Id' --output text --profile OrgRoot

That worked. Now you might start to understand why I am not a fan of AWS filtering and querying.

After an excessive amount of fiddling I figured out that the syntax I needed in this case with both backticks and quotes. No examples like that in the documentation…the whole resolution of variables in this case is strange.

'Accounts[?Name == `'$account_name'`].Id'

So anyway this works:

I added it to my account_functions.sh file under Org/stacks/Account rather than the shared functions file.

I intend to continue refining code and function inclusion for a specific resource easier, rather than stuffing everything into the shared functions file.

That feels like way too long for a single line of code. Perhaps better error messages would help. Perhaps there is something strange going on with the way the library handles variables that someone should investigate a bit further.

Now I can get back to updating NS records for a domain.

Follow for updates.

Teri Radichel | © 2nd Sight Lab 2023

About Teri Radichel:
~~~~~~~~~~~~~~~~~~~~
⭐️ Author: Cybersecurity Books
⭐️ Presentations: Presentations by Teri Radichel
⭐️ Recognition: SANS Award, AWS Security Hero, IANS Faculty
⭐️ Certifications: SANS ~ GSE 240
⭐️ Education: BA Business, Master of Software Engineering, Master of Infosec
⭐️ Company: Penetration Tests, Assessments, Phone Consulting ~ 2nd Sight Lab
Need Help With Cybersecurity, Cloud, or Application Security?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
🔒 Request a penetration test or security assessment
🔒 Schedule a consulting call
🔒 Cybersecurity Speaker for Presentation
Follow for more stories like this:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
❤️ Sign Up my Medium Email List
❤️ Twitter: @teriradichel
❤️ LinkedIn: https://www.linkedin.com/in/teriradichel
❤️ Mastodon: @teriradichel@infosec.exchange
❤️ Facebook: 2nd Sight Lab
❤️ YouTube: @2ndsightlab
Aws Cli
Filter
Query
Account
Organization
Recommended from ReadMedium