Skip to content

Instantly share code, notes, and snippets.

@charltonstanley
Forked from kalihman/AWS4-Request-Signer.ps1
Created November 2, 2023 04:47
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 charltonstanley/b9f3ab0037e110c30b20893a0cd89278 to your computer and use it in GitHub Desktop.
Save charltonstanley/b9f3ab0037e110c30b20893a0cd89278 to your computer and use it in GitHub Desktop.
Powershell AWS4 Signer for STS GetCallerIdentity Action
# 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