-
-
Save kalihman/eb8c8148b4aa2312343383eac3651f23 to your computer and use it in GitHub Desktop.
# 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 |
@kalihman Thanks for posting this code! The company I work for iterated off of what you posted here to create a Powershell module for this so that we could more easily maintain it internally. Since this was open sourced to begin with, we are throwing around the idea of open sourcing our version as well. If we decide to to that, would you be opposed to this? We would of course give you credit for the original work and would provide a link back to this page.
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!
@kalihman Thanks for posting this code! The company I work for iterated off of what you posted here to create a Powershell module for this so that we could more easily maintain it internally. Since this was open sourced to begin with, we are throwing around the idea of open sourcing our version as well. If we decide to to that, would you be opposed to this? We would of course give you credit for the original work and would provide a link back to this page.