How To Access AWS Securely From CLI With 1Password From Any Platform
Tl;dr: Copy & Paste the script and source it into your shell. But since this is about handling your secrets, you should know what is it doing and why.
Passwords secure your digital identity and everybody knows to keep them save. As its usage skyrocketed, more sophisticated users use password manager as the trade-off seems to favor completely unique passwords over the possible compromitation of the manager1.
Yet the computers that belong to the sophisticated users—developers—are often littered with passwords stored in clear text. Both SSH private key as well as AWS API key is a password in disguise and I’ve been always bothered that the default is to just dump it into
In a company setting, this can be solved in various ways, but all are fairly complicated for individual developers. I gravitated towards 1Password as my personal password manager and decided to use it for storing the AWS credentials as well.
Since I am using the subscription service2, I have decided to use a dedicated vault for my keys and put it into an online vault, also because it makes my cross-platform scripting easier. If you still favor locally stored vaults for privacy reasons, the scripts below will not work for you.
- 1Password subscription account
- 1Password CLI installed and you signed in once (run
op signin https://my.1password.com/ email@example.com see the linked page for details)
- Locally-installed jq package (because I am lazy)
- AWS account with generated
- 1Password Vault named “Dev” with a Login called “AWS Key”, where username is your
AWS_ACCESS_KEY_IDand password is your
AWS_SECRET_ACCESS_KEY(configurable; change below)
Put this script anywhere,
~/bin/enter-aws-session would be a good place. Note that in order for environment variables to be properly propagated, you have to source the script, not just run it:
computer:~ user$ source ~/bin/enter-aws-session
Here’s the non-magic. Configure the item name and the region.
#!/bin/bash # Configuration: change to your preferences VAULT_NAME="Dev" ITEM_NAME="DDCZ AWS Devel" export AWS_REGION=eu-central-1 # Prereqs: # 1) jq installed https://stedolan.github.io/jq/ # 2) 1Password client installed https://support.1password.com/command-line/ # 3) Signed in once before with op signin https://support.1password.com/command-line/#sign-in-or-out if [ ! $OP_SESSION_my ]; then eval $(op signin my); else # This is a void command to test whether your session is still valid, # to be updated with better check once/if available op list users > /dev/null 2>&1 test $? -eq 0 || eval $(op signin my); fi; ITEM=`op get item "$ITEM_NAME" --vault=$VAULT_NAME` export AWS_ACCESS_KEY_ID=`echo $ITEM | jq -Mcr '.details.fields | select(.name=="username") | .value'` export AWS_SECRET_ACCESS_KEY=`echo $ITEM | jq -Mcr '.details.fields | select(.name=="password") | .value'`
How it works
op (presumably One Password) connects to 1Password service via HTTPS API3. API returns the first item that matches configured
ITEM_NAME4. The username and password retrieved from that item are then exported as the appropriate variables to the environment.
Note that as mentioned earlier, in order for those variables to be exported in the parent terminal process, you must
source the script instead of just running it.
Definitely change your Valt Name, Item Name and Region based on your preferences. If you are using any other 1Password than the shared one on
my subdomain, you probably need to change the
OP_SESSION variable check.
Above can be easily altered to accept command line arguments, but I actually prefer to have multiple scripts per each of my “roles” and just change the values in the header.
You may want to store the key pair in secure note or some other container. In that case, look at the
$VAULT_CONTENT variable to alter the query properly.
Again, the script uses
ITEM_NAME as a unique key and random things will happen if you put in multiple logins under the same name. That resulting computer fire is on you.
The Alternatives and The Disclaimers
Alternative ways to handling the secrets include:
Your OS’s “default” secret chain:
- Keychain on MAC OS X
- DPAPI on Windows
- One of the zilion kinda-working alternatives on Linux: libsecret, Gnome.Keyring, KWallet, …
Command-line password manager (like pass on Unix)
Full-blown secret handling solution like Vault
Giving up, crying and relying on operating system privileges (encrypting hard drive and having secrets in clear text files)
Your secrets are of course still easily discoverable in your env vars, but this at least isolates you better from other programs.
It should also be noted that I am an unemployed writer, not a security engineer. If you are using this at work, this may violate your security policies and send your credentials to
Russian Chinese American hackers.
Use at your own risk under UPL.
- Script simplified at the suggestion of 1Password’s VPE and text updated accordingly on May 12, 2020
Although they do have surprising architectural vulnerabilities as outlined in this 2019 ISE report: https://www.ise.io/casestudies/password-manager-hacking/ ↩︎
Apparently a future for 1password with one-time fee licensing being deprecated and buried. Although I don’t like it, I understand why they do it from business perspective. ↩︎
In order to do that, you need working connection to your vault; here I assume my.1password.com. I consider this reasonable assumption given you are going to connect to AWS and cloud, but you may need to adjust your proxy or VPN settings accordingly. ↩︎
Uniqueness could be guaranteed using
uuidattribute instead of the name, but in that case, one would have to manually inspect for it using the CLI or parse it from the URL you are able to export. Having a dedicated vault with sensible and unique names sounds like a better option for personal usage. ↩︎