function Get-AwsCredentialConfiguration { <# .SYNOPSIS Used to read/parse the AWS credentials file entries to a queryable object array .DESCRIPTION Used to read/parse the AWS credentials file entries to a queryable object array. Runs parsed values through ConvertTo-AwsCredentialEntry .EXAMPLE Get-AwsCredentialConfiguration Name : GrandPooBah role_arn : arn:aws:iam::123430414321:role/CLI-God-Mode-On mfa_serial : arn:aws:iam::123410044321:mfa/poobah-cli region : canada-west-99 source_profile : default Name : Gibberish role_arn : arn:aws:iam::123495924321:role/CLI-NoGood-DoNothing mfa_serial : arn:aws:iam::123410044321:mfa/gwhiting-cli region : mexico-north-1 source_profile : default .LINK ConvertTo-AwsCredentialEntry #> [CmdletBinding()] [OutputType([object[]])] param() $logLead = Get-LogLeadName $userProfileDirectory = Get-EnvironmentVariable -StoreName Process -Name USERPROFILE $configurationSources = @() $configurationSources += Join-Path -Path $userProfileDirectory -ChildPath ".aws/config" $configurationSources += Join-Path -Path $userProfileDirectory -ChildPath ".aws/credentials" # ToDo - Add the AWS SDK Credentials Source [System.Collections.ArrayList]$objects = @() $awsProfile = @{} $lines = @() $propertiesToIgnore = @("aws_secret_access_key", "aws_session_token") foreach ($source in $configurationSources) { if (-NOT (Test-Path -Path $source)) { Write-Verbose "$logLead : Credential file does not exist at [$source]" continue } $fileContent = Get-Content -Path $source if (Test-IsCollectionNullOrEmpty -Collection $fileContent) { Write-Verbose "$logLead : Credential file at [$source] exists but is empty. Skipping." continue } $lines += $fileContent $lines += "EOF" } if (Test-IsCollectionNullOrEmpty -Collection $lines) { Write-Warning "$logLead : Unable to locate any configured AWS credentials sources. Have you set up your local profiles?" return } foreach ($line in $lines) { if ($line.StartsWith('#') -or (Test-StringIsNullOrWhitespace -Value $line)) { # This is a comment or empty line, ignore it continue } elseif ($line -eq "EOF" -and (-NOT (Test-StringIsNullOrWhitespace -Value $awsProfile.Name))) { # Save the final profile or in between file swaps $objects += $awsProfile } elseif ($line.StartsWith('[')) { # This is a new profile, push any old profile into the objects array and start fresh if ($null -ne $awsProfile.Name -and ($null -eq ($objects | Where-Object { $_.Name -eq $awsProfile.Name }))) { # $awsProfile object is populated, save it $objects += $awsProfile } $sanitizedProfileName = $line -replace "\[|\]|(profile\s+)", "" Write-Verbose "$logLead : Looking for existing parsed profiles named [$sanitizedProfileName]" $existingProfile = $objects | Where-Object { $_.Name -eq $sanitizedProfileName } if ($null -ne $existingProfile) { # Load the existing profile to attach properties, where unique Write-Verbose "$logLead : Duplicate profile name [$sanitizedProfileName] found. First-in properties win in this scenario." $awsProfile = $existingProfile $objects.Remove($existingProfile) } else { # This is a new profile $awsProfile = New-Object PSObject -Property @{ Name = $sanitizedProfileName } } } else { if ($null -eq $awsProfile.Name) { # We skip this step unless we're anchored to a profile # to avoid picking up trash or duplicate properties continue } # The only things left are valid properties to attach to an object # Unless we're specifically ignoring them $splits = $line -split '=' $propertyName = $splits[0].Trim() if ($propertiesToIgnore -contains $propertyName) { # This is a sensitive property that will never be recorded Write-Verbose "$logLead : Skipping excluded property [$propertyName] for profile [$($awsProfile.Name)]" continue } elseif ($null -ne $awsProfile.$propertyName) { # This property has been recorded already. It is a duplicate, and first read wins Write-Verbose ("$logLead : Skipping duplicate property [$propertyName] for profile [$($awsProfile.Name)] - existing value: [$($awsProfile.$propertyName)]") continue } $propertyValue = $splits[1].Trim() Add-Member -InputObject $awsProfile -NotePropertyName $propertyName -NotePropertyValue $propertyValue -Force } } return ($objects | ConvertTo-AwsCredentialEntry | Sort-Object -Property Name) }