Last active
November 2, 2023 05:15
-
-
Save kalihman/eb8c8148b4aa2312343383eac3651f23 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
Hi @charltonstanley ! I'm glad to hear that my small contribution long time ago was meaningful to you 😄. Thank you for let me know and I do appreciate you want to contribute to open source too. I'm more than happy that you want to refer my code and credit me for your contribution. Looking forward to see your module being open sourced!