-
-
Save charltonstanley/b9f3ab0037e110c30b20893a0cd89278 to your computer and use it in GitHub Desktop.
Powershell AWS4 Signer for STS GetCallerIdentity Action
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Define Helper Functions | |
function Get-Sha256Hash ($StringToHash) { | |
$hasher = [System.Security.Cryptography.SHA256]::Create() | |
$Hash = ([BitConverter]::ToString($hasher.ComputeHash([Text.Encoding]::UTF8.GetBytes($StringToHash))) -replace '-','').ToLower() | |
Write-Output $Hash | |
} | |
function ConvertTo-SortedDictionary($HashTable) { | |
$SortedDictionary = New-Object 'System.Collections.Generic.SortedDictionary[string, string]' | |
foreach ($Key in $HashTable.Keys) { | |
$SortedDictionary[$Key]=$HashTable[$Key] | |
} | |
Write-Output $SortedDictionary | |
} | |
function Sign($Key, $Message) { | |
$hmacsha = New-Object System.Security.Cryptography.HMACSHA256 | |
$hmacsha.Key = $Key | |
$hmacsha.ComputeHash([Text.Encoding]::UTF8.GetBytes($Message)) | |
} | |
function Get-SignatureKey($Key, $Date, $Region, $Service) { | |
$SignedDate = Sign ([Text.Encoding]::UTF8.GetBytes(('AWS4' + $Key).toCharArray())) $Date | |
$SignedRegion = Sign $SignedDate $Region | |
$SignedService = Sign $SignedRegion $Service | |
Sign $SignedService "aws4_request" | |
} | |
# Define Credentials | |
$Credentials = Invoke-RestMethod http://169.254.169.254/latest/meta-data/iam/security-credentials/BroservEc2InstanceRole | |
$AccessKey = $Credentials.AccessKeyId | |
$SecretAccessKey = $Credentials.SecretAccessKey | |
$Token = $Credentials.Token | |
# Define Keywords | |
$Action = 'Action=GetCallerIdentity&Version=2011-06-15' | |
$EndpointUrl = "sts.amazonaws.com" | |
$HTTPRequestMethod = "POST" | |
$CanonicalURI = "/" | |
$CanonicalQueryString = "" | |
$DateTime = [DateTime]::UtcNow.ToString("yyyyMMdd'T'HHmmss'Z'") | |
$DateString = [DateTime]::UtcNow.ToString('yyyyMMdd') | |
$RequestPayloadHash = Get-Sha256Hash($Action) | |
$Region = "us-east-1" | |
$Service = "sts" | |
$Headers = @{} | |
$ContentType = "application/x-www-form-urlencoded" | |
# 1. Create a Canonical Request for Signature Version 4 | |
if (!$Headers["Host"]) { $Headers["Host"] = $EndpointUrl } | |
if (!$Headers["X-Amz-Date"]) { $Headers["X-Amz-Date"] = $DateTime } | |
if (!$Headers["Content-Type"] -and $ContentType) { $Headers["Content-Type"] = $ContentType } | |
if (!$Headers["X-Amz-Security-Token"]) { $Headers["X-Amz-Security-Token"] = $Token } | |
if (!$Headers["X-Amz-Content-Sha256"]) { $Headers["X-Amz-Content-Sha256"] = $RequestPayloadHash } | |
$SortedHeaders = ConvertTo-SortedDictionary $Headers | |
$CanonicalHeaders = (($SortedHeaders.GetEnumerator() | ForEach-Object { "$($($_.Key).ToLower()):$($_.Value)" }) -join "`n") + "`n" | |
$SignedHeaders = ($SortedHeaders.Keys -join ";").ToLower() | |
$CanonicalRequest = "$HTTPRequestMethod`n$CanonicalURI`n$CanonicalQueryString`n$CanonicalHeaders`n$SignedHeaders`n$RequestPayloadHash" | |
$hasher = [System.Security.Cryptography.SHA256]::Create() | |
$CanonicalRequestHash = ([BitConverter]::ToString($hasher.ComputeHash([Text.Encoding]::UTF8.GetBytes($CanonicalRequest))) -replace '-','').ToLower() | |
# 2. Create a String to Sign for Signature Version 4 | |
$AlgorithmDesignation = "AWS4-HMAC-SHA256" | |
$CredentialScope = "$DateString/$Region/$Service/aws4_request" | |
$StringToSign = "$AlgorithmDesignation`n$DateTime`n$CredentialScope`n$CanonicalRequestHash" | |
# 3. Calculate the Signature for AWS Signature Version 4 | |
$SigningKey = Get-SignatureKey $SecretAccessKey $DateString $Region $Service | |
$Signature = ([BitConverter]::ToString((sign $SigningKey $StringToSign)) -replace '-','').ToLower() | |
# 4. Add the Signing Information to the Request | |
$Headers["Authorization"]="AWS4-HMAC-SHA256 Credential=$AccessKey/$DateString/$Region/$Service/aws4_request, SignedHeaders=$SignedHeaders, Signature=$Signature" | |
$Protocol = "https://" | |
$Url = $Protocol + $EndpointUrl + $CanonicalURI | |
# 5.Optional): Test Request by Sending to Service | |
# $Res = Invoke-RestMethod -Method 'POST' -Uri $Url -Headers $Headers -Body $Action | |
# Write-Output $res.OuterXml |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment