Skip to content

Instantly share code, notes, and snippets.

@infamousjoeg
Last active May 15, 2023 16:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save infamousjoeg/1123f44682737e2bd8239ccb1129d8a1 to your computer and use it in GitHub Desktop.
Save infamousjoeg/1123f44682737e2bd8239ccb1129d8a1 to your computer and use it in GitHub Desktop.
PowerShell AWS STS Signed Headers w/ Conjur's authn-iam
# Please note that this script uses a C# helper class for HMAC-SHA256 calculations.
# This is because PowerShell does not natively support this kind of operations.
# Also, this script assumes that you are calling Get-SignedHeaders with the proper
# parameters to generate your signed headers.
# Create a C# class for HMACSHA256 Helper which is used to compute HMACSHA256 hash
Add-Type -TypeDefinition @"
using System;
using System.Text;
using System.Security.Cryptography;
public class HMACSHA256Helper
{
// Compute HMACSHA256 hash and return the hash as a lowercase string
public static string ComputeHash(string key, string data)
{
var secretKeyBytes = Encoding.UTF8.GetBytes(key);
using (var hmac = new HMACSHA256(secretKeyBytes))
{
var dataBytes = Encoding.UTF8.GetBytes(data);
var hashBytes = hmac.ComputeHash(dataBytes);
return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
}
}
// Compute HMACSHA256 hash and return the hash as a byte array
public static byte[] ComputeHashBytes(string key, string data)
{
var secretKeyBytes = Encoding.UTF8.GetBytes(key);
using (var hmac = new HMACSHA256(secretKeyBytes))
{
var dataBytes = Encoding.UTF8.GetBytes(data);
return hmac.ComputeHash(dataBytes);
}
}
}
"@ -Language CSharpVersion3
# Function to compute the signature key
function Get-SignatureKey {
param(
$key, # Secret key for signing
$dateStamp, # Date stamp
$regionName, # AWS region name
$serviceName # AWS service name
)
# Compute hashes for the date, region and service
$kDate = [HMACSHA256Helper]::ComputeHashBytes("AWS4$key", $dateStamp)
$kRegion = [HMACSHA256Helper]::ComputeHashBytes([System.Text.Encoding]::UTF8.GetString($kDate), $regionName)
$kService = [HMACSHA256Helper]::ComputeHashBytes([System.Text.Encoding]::UTF8.GetString($kRegion), $serviceName)
# Compute the final signing key
$kSigning = [HMACSHA256Helper]::ComputeHashBytes([System.Text.Encoding]::UTF8.GetString($kService), 'aws4_request')
return $kSigning
}
# Function to get signed headers
function Get-SignedHeaders {
param(
$access_key, # AWS access key
$secret_key, # AWS secret key
$session_token, # AWS session token
$region # AWS region
)
# Define the AWS host and request parameters
$aws_host = 'sts.amazonaws.com'
$request_parameters = 'Action=GetCallerIdentity&Version=2011-06-15'
$service = 'sts'
$method = 'GET'
# Get current date and time in the specific format
$t = Get-Date -Format "yyyyMMddTHHmmssZ"
$amzdate = $t
$datestamp = $t.Substring(0,8)
# Create canonical URI, query string, headers and signed headers
$canonical_uri = '/'
$canonical_querystring = $request_parameters
$canonical_headers = 'host:' + $aws_host + "`n" + 'x-amz-date:' + $amzdate + "`n" + 'x-amz-security-token:' + $session_token + "`n"
$signed_headers = 'host;x-amz-date;x-amz-security-token'
# Compute payload hash
$payload_hash = [HMACSHA256Helper]::ComputeHash("", "")
# Create canonical request
$canonical_request = $method + "`n" + $canonical_uri + "`n" + $canonical_querystring + "`n" + $canonical_headers + "`n" + $signed_headers + "`n" + $payload_hash
# Define the algorithm to be used
$algorithm = 'AWS4-HMAC-SHA256'
# Create the credential scope string
$credential_scope = $datestamp + '/' + $region + '/' + $service + '/' + 'aws4_request'
# Create the string to sign using the previously defined elements
$string_to_sign = $algorithm + "`n" + $amzdate + "`n" + $credential_scope + "`n" + [HMACSHA256Helper]::ComputeHash("", $canonical_request)
# Call the Get-SignatureKey function to get the signing key
$signing_key = Get-SignatureKey $secret_key $datestamp $region $service
# Compute the signature by signing the string_to_sign using the signing_key
$signature = [HMACSHA256Helper]::ComputeHash([System.Text.Encoding]::UTF8.GetString($signing_key), $string_to_sign)
# Create the authorization header
$authorization_header = $algorithm + ' ' + 'Credential=' + $access_key + '/' + $credential_scope + ', ' + 'SignedHeaders=' + $signed_headers + ', ' + 'Signature=' + $signature
# Create a hashtable for headers
$headers = @{
'host' = $aws_host
'x-amz-date' = $amzdate
'x-amz-security-token' = $session_token
'Authorization' = $authorization_header
}
# Return the headers in JSON format
return $headers | ConvertTo-Json -Compress
}
. "$PSScriptRoot\Get-SignedHeaders.ps1"
# Make a request to the IMDS to get the role name
$roleName = Invoke-RestMethod -Uri http://169.254.169.254/latest/meta-data/iam/security-credentials
# Make a second request to get the security credentials for the role
$credentials = Invoke-RestMethod -Uri http://169.254.169.254/latest/meta-data/iam/security-credentials/$roleName
# Extract the access key, secret key, and session token from the response
$access_key = $credentials.AccessKeyId
$secret_key = $credentials.SecretAccessKey
$session_token = $credentials.Token
# Conjur is hard-coded to always validate AWS signed headers against sts.amazonaws.com (us-east-1)
$region = "us-east-1"
# You can now use these values with the Get-SignedHeaders function
$headers = Get-SignedHeaders -access_key $access_key -secret_key $secret_key -session_token $session_token -region $region
Write-Host $headers
$conjurApplianceURL = "https://conjur.joegarcia.dev"
$conjurServiceID = "prod"
$conjurAccount = "cyberarkdemo"
$conjurHostID = "host%2Fcloud%2Faws%2Fec2%2F735280068473%2FConjurAWSRoleEC2"
$conjurAuthnURL = "${conjurApplianceURL}/api/authn-iam/${conjurServiceID}/${conjurAccount}/${conjurHostID}/authenticate"
$accessToken = Invoke-RestMethod -Uri $conjurAuthnURL -Method "POST" -Body $headers
write-host ""
write-host "Results..."
write-host $accessToken
write-host "...end."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment