ps/Modules/Alkami.PowerShell.Common/Public/Get-InstanceMetadata.ps1

81 lines
3.1 KiB
PowerShell
Raw Normal View History

2023-05-30 22:51:22 -07:00
function Get-InstanceMetadata {
<#
.SYNOPSIS
This function wraps the web-request to get the Instance Metadata (IMDS) from an EC2 instance.
.DESCRIPTION
Defaults to using V2 of the service, which requires a token. This function takes care of the token
generation and use.
There's also the option to use V1 of the service with the switch $UseImdsV1, which requires no token.
.PARAMETER Endpoint
The endpoint in the IMDS servicec to fetch. Ex. '/meta-data/hostname'
.PARAMETER UseImdsV1
Switch to change to the IMDS V1 request instead of V2.
.EXAMPLE
$result = Get-InstanceMetadata -Endpoint "/meta-data/hostname"
$result = Get-InstanceMetadata -Endpoint "/meta-data/hostname" -UseImdsV1
.NOTES
https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html
#>
[CmdletBinding()]
[OutputType([System.String])]
Param (
[Parameter(Mandatory = $true)]
[string]$Endpoint,
[Parameter(Mandatory = $false)]
[switch]$UseImdsV1
)
$logLead = (Get-LogLeadName)
# Script block to be used when Imds V2 is selected. This is default unless switch $UseImdsV1 is specified.
$V2Script = {
param ($sbImdsUri, $sbEndpoint, $sbImdsV2Token)
$endpoint = ("{0}/{1}" -f $sbImdsUri, $sbEndpoint)
try {
$metadata = (Invoke-WebRequest -Headers @{"X-aws-ec2-metadata-token" = $sbImdsV2Token} -Method GET -UseBasicParsing -TimeoutSec 5 -Uri $endpoint)
} catch [System.Net.WebException] {
# Only on 401
$unauthorizedStatusCode = [System.Net.HttpStatusCode]::Unauthorized
$response = $_.Exception.Response
if($response.StatusCode -eq $unauthorizedStatusCode) {
Write-Verbose "401 Unauthorized caught. Trying again with new token."
$newToken = Get-ImdsV2Token -InvalidateCache
$metadata = (Invoke-WebRequest -Headers @{"X-aws-ec2-metadata-token" = $newToken} -Method GET -UseBasicParsing -TimeoutSec 5 -Uri $endpoint)
}
}
return $metadata
}
# Script block to be used when ImdsV1 is specified.
$V1Script = {
param($sbImdsUri, $sbEndpoint)
$endpoint = ("{0}/{1}" -f $sbImdsUri, $sbEndpoint)
$metadata = (Invoke-WebRequest -Method GET -UseBasicParsing -TimeoutSec 5 -Uri $endpoint)
return $metadata
}
# Set up variables to be passed into the script blocks.
$imdsUri = Get-ImdsBaseUri
# Switch between the two commands based on the $UseImdsV1 switch param.
if($UseImdsV1) {
Write-Verbose "$logLead Imds V1 specified, trying command with V1 URI."
$result = (Invoke-CommandWithRetry -Arguments ($imdsUri, $Endpoint) -MaxRetries 3 -Exponential -ScriptBlock $V1Script)
} else {
Write-Verbose "$logLead Imds V2 specified, trying command with V2 URI."
$token = Get-ImdsV2Token
$result = (Invoke-CommandWithRetry -Arguments ($imdsUri, $Endpoint, $token) -MaxRetries 3 -Exponential -ScriptBlock $V2Script)
}
return $result
}