Skip to content

Instantly share code, notes, and snippets.

@serban-petrescu
Last active June 30, 2021 03:59
Show Gist options
  • Save serban-petrescu/e05dcc39a8ff899f263ff847bb5c9a6a to your computer and use it in GitHub Desktop.
Save serban-petrescu/e05dcc39a8ff899f263ff847bb5c9a6a to your computer and use it in GitHub Desktop.
BW-AWS: Main

External script for securely sourcing AWS credentials from Bitwarden

Prerequisites:

  • AWS CLI and Bitwarden CLI must be installed and on the path.
  • PowerShell must be installed. I used PowerShell version 5.1.
  • You must be logged onto Bitwarden and the vault must be synced.
  • Your AWS login items must have the following custom fields: -- ACCOUNT (the AWS Account ID), -- ACCESS_KEY_ID, -- SECRET_ACCESS_KEY, -- IS_ROOT (optional; if it is "true" it indicates that this is a root account).

Installation:

  • Clone this gist into a folder on your path.
  • Create a new AWS CLI profile as you would normally do.
  • Adjust the ~/.aws/credentials file as shown in the example below.
@echo off
cd /d "%~dp0"
powershell.exe -file ".\bw-aws.ps1" %1
param (
[string] $id
)
$ErrorActionPreference = "Stop"
$sessionLifetime = 3600
$sessionBuffer = 120
$path = ".\$($id).xml"
function Unlock-Bw() {
$status = bw status | ConvertFrom-Json
if ($status.status -eq "locked") {
$password = (Get-Credential "Bitwarden").GetNetworkCredential().Password
$session = bw unlock $password --raw
$env:BW_SESSION = $session
}
}
function Find-BWField() {
param (
$item,
$name
)
[Array]::Find($item.fields, [Predicate[Object]] { $args[0].name -eq $name }).value
}
function Get-AwsToken() {
$item = bw get item $id | ConvertFrom-Json
$account = Find-BWField -item $item -name "ACCOUNT"
$env:AWS_ACCESS_KEY_ID = Find-BWField -item $item -name "ACCESS_KEY_ID"
$env:AWS_SECRET_ACCESS_KEY = Find-BWField -item $item -name "SECRET_ACCESS_KEY"
if ((Find-BWField -item $item -name "IS_ROOT") -eq "true") {
$mfaArn = "arn:aws:iam::$($account):mfa/root-account-mfa-device"
}
else {
$mfaArn = "arn:aws:iam::$($account):mfa/$($item.login.username)"
}
if ($item.login.totp) {
$token = bw get totp $id
$result = aws sts get-session-token `
--serial-number $mfaArn `
--token-code $token `
--duration-seconds $sessionLifetime `
| ConvertFrom-Json
} else {
$result = aws sts get-session-token --duration-seconds $sessionLifetime | ConvertFrom-Json
}
$env:AWS_ACCESS_KEY_ID = ""
$env:AWS_SECRET_ACCESS_KEY = ""
$credentials = $result.Credentials
$credentials | Add-Member -MemberType NoteProperty -Name "Version" -Value 1
return $credentials | ConvertTo-Json
}
function Test-Cache() {
if (-not(Test-Path -Path $path -PathType Leaf)) {
return 0
}
else {
$lastWrite = (Get-Item $path).LastWriteTime
$timespan = New-Timespan -seconds ($sessionLifetime - $sessionBuffer)
if (((Get-Date) - $lastWrite) -lt $timespan) {
return 1
}
else {
return 0
}
}
}
function Read-Cache() {
$obj = Import-Clixml -Path $path
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($obj.Password)
$password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR)
return $password
}
function Write-Cache() {
param (
$value
)
$secure = ConvertTo-SecureString -AsPlainText -Force -String $value
$obj = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "myusername", $secure
$obj | Export-Clixml $path
}
try {
if ((Test-Cache) -eq 0) {
Unlock-Bw
$output = Get-AwsToken
Write-Cache -value $output
$env:BW_SESSION = ""
}
else {
$output = Read-Cache
}
Write-Output $output
} catch {
Write-Error $_ -ErrorAction Continue
exit 1
}
# Example AWS credential profile configuration file
[personal]
credential_process = bw-aws.cmd "Name of the BW item"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment