trouble with aws, powershell and the Signature - amazon-web-services

i want to play with the Amazon Selling Partner API. From Postman everything works fine. From Powershell not.
I tried to derive my powershell script from the documentation https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html and the python example.
I try it all the day, but i do not find the solution.
What i have done:
Test functionality from Postman -> Works
Read about Signing AWS requests with Signature Version 4 -> OK
Understanding signing key functionality with the test input from
https://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html -> Works
Try to translate the Python example to Powershell: https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html -> does not work
Use Google to find a solution from examples and found this: http://www.laurierhodes.info/?q=node/114 -> does not work - maybe because it is for aws lambda
Whatever i do, i receive error Message Sender SignatureDoesNotMatch
I attached a screenshot from Postman, it shows the response from this endpoint. I know it is "Access denied", it is just really near on the example from amazon. Later on i need to make a sts request to receive temp credentials on each call and i also need to sign every call to the amazon selling partner API.
Maybe someone can help me, please? I'm going nuts :D
Here is my Powershell code from the python example: https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html
I tried both get variants,
Using GET with an authorization header (Python)
Using GET with authentication information in the Query string (Python)
This code is from the 2nd -> Using GET with authentication information in the Query string
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
[cultureinfo]::CurrentCulture = 'de-DE'
#powershell variant with example test input from #https://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html
<#
.Synopsis
HMACSHA256 signing function used in the construction of a "Signature 4 " request
#>
# translated function from Deriving a signing key using .NET (C#)
function hmacSHA256(
[string]$data,
[byte[]]$key)
{
$hmacsha = New-Object System.Security.Cryptography.HMACSHA256
$hmacsha.key = $key
$signature = $hmacsha.ComputeHash([Text.Encoding]::UTF8.GetBytes($data))
return $signature
}
<#
.Synopsis
The AWS Signature version 4 creation routine
#>
function getSignatureKey(
[String]$AWSAccessKey,
[String]$dateStamp,
[String]$regionName,
[String]$serviceName)
{
[Byte[]]$kSecret = [System.Text.Encoding]::UTF8.GetBytes("AWS4" + $AWSAccessKey)
$kDate = hmacSHA256 -data $dateStamp -key $kSecret
$kRegion = hmacSHA256 -data $regionName -key $kDate
$kService = hmacSHA256 -data $serviceName -key $kRegion
$kSigningKey = hmacSHA256 -data "aws4_request" -key $kService
return $kSigningKey
}
<#
.Synopsis
Retrieves an SHA hash of a string as required by AWS Signature 4
#>
function hash($request) {
$sha256 = new-object -TypeName System.Security.Cryptography.SHA256Managed
$utf8 = new-object -TypeName System.Text.UTF8Encoding
$hash = [System.BitConverter]::ToString($sha256.ComputeHash($utf8.GetBytes($request)))
return $hash.replace('-','').toLower()
}
# ************* REQUEST VALUES *************
$method = 'GET'
$service = 'iam'
$host1 = 'iam.amazonaws.com'
$region = 'us-east-1'
$endpoint = 'https://iam.amazonaws.com'
$access_key = 'AKIA4KA7FVL7SN2EXAMPLE'
$secret_key = 'EXPL[enter image description here][1]Y59hS5KWKAnfOSnWLjNsiKaK/EXAMPLE'
$now = [DateTime]::UtcNow
$amz_date = $now.ToString('yyyyMMddTHHmmssZ')
$datestamp = $now.ToString('yyyyMMdd')
# ************* TASK 1: CREATE A CANONICAL REQUEST *************
# http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
# Step 2: Create canonical URI--the part of the URI from domain to query
# string (use '/' if no path)
$canonical_uri = '/'
# Step 3: Create the canonical headers and signed headers. Header names
# must be trimmed and lowercase, and sorted in code point order from
# low to high. Note trailing \n in canonical_headers.
# signed_headers is the list of headers that are being included
# as part of the signing process. For requests that use query strings,
# only "host" is included in the signed headers.
$canonical_headers = "host:" + $host1 + "`n"
$signed_headers = "host"
# Match the algorithm to the hashing algorithm you use, either SHA-1 or
# SHA-256 (recommended)
$algorithm = 'AWS4-HMAC-SHA256'
$credential_scope = $datestamp + '/' + $region + '/' + $service + '/' + 'aws4_request'
# Step 4: Create the canonical query string. In this example, request
# parameters are in the query string. Query string values must
# be URL-encoded (space=%20). The parameters must be sorted by name.
$canonical_querystring = "Action=CreateUser&UserName=NewUser&Version=2010-05-08"
$canonical_querystring += "&X-Amz-Algorithm=AWS4-HMAC-SHA256 `n"
$canonical_querystring += "&X-Amz-Credential=" + [uri]::EscapeDataString(($access_key + "/" + $credential_scope))
$canonical_querystring += "&X-Amz-Date=" + $amz_date
$canonical_querystring += "&X-Amz-Expires=30"
$canonical_querystring += "&X-Amz-SignedHeaders=" + $signed_headers
# Step 5: Create payload hash. For GET requests, the payload is an
# empty string ("").
$payload_hash = hash ''
# Step 6: Combine elements to create canonical request
$canonical_request = $method + "`n" +
$canonical_uri + "`n" +
$canonical_querystring + "`n" +
$canonical_headers + "`n" +
$signed_headers + "`n" +
$payload_hash
#$canonical_request_hash = hash -request $canonical_request
#write-host $canonical_request_hash
# *************************************************************#
# ************* TASK 2: CREATE THE STRING TO SIGN *************#
$string_to_sign = $algorithm + "`n" +
$amz_date + "`n" +
$credential_scope + "`n" +
$canonical_request_hash
# *************************************************************#
# ************* TASK 3: CALCULATE THE SIGNATURE ***************#
# Create the signing key
$signing_key = getSignatureKey($secret_key, $datestamp, $region, $service)
#write-host "signing-key: $($signing_key)"
# Sign the string_to_sign using the signing_key
$signature = HmacSHA256 -data $string_to_sign -key $signing_key
$signature = [System.BitConverter]::ToString($signature).Replace('-','').ToLower()
# ************* TASK 4: ADD SIGNING INFORMATION TO THE REQUEST *************
# The auth information can be either in a query string
# value or in a header named Authorization. This code shows how to put
# everything into a query string.
$canonical_querystring += '&X-Amz-Signature=' + $signature
# ************* SEND THE REQUEST *************
# The 'host' header is added automatically by the Python 'request' lib. But it
# must exist as a header in the request.
###
#I am not sure how to work with headers, because i used the Get Variant with authentication information in the Query string
####
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("authorization", "AWS4-HMAC-SHA256 Credential=$($AWSAccessID)/$($shortdate)/$($AWSRegion)/$($AWSService)/aws4_request, SignedHeaders=$($SignedHeadersList), Signature=$($signature)")
$request_url = $endpoint + "/?" + $canonical_querystring
Invoke-RestMethod $request_url -Method 'GET' -Headers $headers
Best regards and many many thanks
Patrick
Postman screenshot

Related

Private API gateway with IAM authentication not liking my security token

I have a private API gateway with a / endpoint and a /foo with IAM auth enabled.
I created a policy which I attached to my instance's role :
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"execute-api:Invoke"
],
"Resource": [
"arn:aws:execute-api:*:*:*"
]
}
]
}
I have some code to do the AWS signature stuff and also used Postman to create a snippet with the same key/secret/session token. Both give the same result on /foo. It always says :
{"message":"The security token included in the request is invalid"}
I had a concern that the docs do not say you can attach the policy to a role only a user or group.
https://aws.amazon.com/premiumsupport/knowledge-center/iam-authentication-api-gateway/
That whole page doesn't mention roles once... Can I attach a policy to a role to use it with IAM auth'ed API gateway??
The / endpoint returns me a 200 response, and my API GW resource policy denies/allows access to *. If I can get to /, I can get to /foo. (And if I disable the IAM auth, I can get /foo)
The VPC endpoint allows * on *.
In the execution logs I see nothing for the failed attempts.
The attempts to / log : API Key authorized because method 'GET /' does not require API Key. Request will not contribute to throttle or quota limits
And I can see the X-Amz-Security-Token in the payload.
But requests to /foo don't appear there, only the access logs. And I've added some fields but nothing that sheds any light on the problem.
Anything I'm forgetting?? And any ideas why isn't it working?
Here is my signing python, there may be a bug, but it is getting the same error as Postman, which makes me think not! Replace the host/endpoint and path to your own. I added a few print debug lines to show the intermediate steps because I did get some errors about the canonical URL being wrong to start with.
#!/usr/bin/python3
# This is based on the AWS General Reference
# Signing AWS API Requests top available at
# https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html
# To use it :
# pip3 install requests
# To use it on instance with instance role :
# sudo yum -y -q install jq
# export AWS_ACCESS_KEY_ID=$(curl 169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance | jq -r .AccessKeyId)
# export AWS_SECRET_ACCESS_KEY=$(curl 169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance | jq -r .SecretAccessKey)
# export AWS_SESSION_TOKEN=$(curl 169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance | jq -r .Token)
# See: http://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html
# This version makes a GET request and passes the signature
# in the Authorization header.
import sys, os, base64, datetime, hashlib, hmac
import requests # pip install requests
# ************* REQUEST VALUES *************
method = 'GET'
service = 'execute-api'
host = 'xxx.execute-api.eu-west-2.amazonaws.com'
region = 'eu-west-2'
endpoint = 'https://xxx.execute-api.eu-west-2.amazonaws.com'
path='/stage/foo/'
request_parameters = ''
# Key derivation functions. See:
# http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-python
def sign(key, msg):
return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()
def getSignatureKey(key, dateStamp, regionName, serviceName):
kDate = sign(('AWS4' + key).encode('utf-8'), dateStamp)
kRegion = sign(kDate, regionName)
kService = sign(kRegion, serviceName)
kSigning = sign(kService, 'aws4_request')
return kSigning
# Read AWS access key from env. variables or configuration file. Best practice is NOT
# to embed credentials in code.
access_key = os.environ.get('AWS_ACCESS_KEY_ID')
secret_key = os.environ.get('AWS_SECRET_ACCESS_KEY')
session_token = os.environ.get('AWS_SESSION_TOKEN')
if access_key is None or secret_key is None:
print('No access key is available.')
sys.exit()
# Create a date for headers and the credential string
t = datetime.datetime.utcnow()
amzdate = t.strftime('%Y%m%dT%H%M%SZ')
datestamp = t.strftime('%Y%m%d') # Date w/o time, used in credential scope
# ************* TASK 1: CREATE A CANONICAL REQUEST *************
# http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
# Step 1 is to define the verb (GET, POST, etc.)--already done.
# Step 2: Create canonical URI--the part of the URI from domain to query
# string (use '/' if no path)
canonical_uri = path
# Step 3: Create the canonical query string. In this example (a GET request),
# request parameters are in the query string. Query string values must
# be URL-encoded (space=%20). The parameters must be sorted by name.
# For this example, the query string is pre-formatted in the request_parameters variable.
canonical_querystring = request_parameters
# Step 4: Create the canonical headers and signed headers. Header names
# must be trimmed and lowercase, and sorted in code point order from
# low to high. Note that there is a trailing \n.
canonical_headers = 'host:' + host + '\n' + 'x-amz-date:' + amzdate + '\n' 'x-amz-security-token:' + session_token + '\n'
# Step 5: Create the list of signed headers. This lists the headers
# in the canonical_headers list, delimited with ";" and in alpha order.
# Note: The request can include any headers; canonical_headers and
# signed_headers lists those that you want to be included in the
# hash of the request. "Host" and "x-amz-date" are always required.
signed_headers = 'host;x-amz-date;x-amz-security-token'
# Step 6: Create payload hash (hash of the request body content). For GET
# requests, the payload is an empty string ("").
payload_hash = hashlib.sha256(('').encode('utf-8')).hexdigest()
# Step 7: Combine elements to create canonical request
canonical_request = method + '\n' + canonical_uri + '\n' + canonical_querystring + '\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash
print ("CANONICAL REQUEST : " + canonical_request)
print ()
# ************* TASK 2: CREATE THE STRING TO SIGN*************
# Match the algorithm to the hashing algorithm you use, either SHA-1 or
# SHA-256 (recommended)
algorithm = 'AWS4-HMAC-SHA256'
credential_scope = datestamp + '/' + region + '/' + service + '/' + 'aws4_request'
string_to_sign = algorithm + '\n' + amzdate + '\n' + credential_scope + '\n' + hashlib.sha256(canonical_request.encode('utf-8')).hexdigest()
print ("STRING TO SIGN : " + string_to_sign )
# ************* TASK 3: CALCULATE THE SIGNATURE *************
# Create the signing key using the function defined above.
signing_key = getSignatureKey(secret_key, datestamp, region, service)
# Sign the string_to_sign using the signing_key
signature = hmac.new(signing_key, (string_to_sign).encode('utf-8'), hashlib.sha256).hexdigest()
# ************* TASK 4: ADD SIGNING INFORMATION TO THE REQUEST *************
# The signing information can be either in a query string value or in
# a header named Authorization. This code shows how to use a header.
# Create authorization header and add to request headers
authorization_header = algorithm + ' ' + 'Credential=' + access_key + '/' + credential_scope + ', ' + 'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + signature
# The request can include any headers, but MUST include "host", "x-amz-date",
# and (for this scenario) "Authorization". "host" and "x-amz-date" must
# be included in the canonical_headers and signed_headers, as noted
# earlier. Order here is not significant.
# Python note: The 'host' header is added automatically by the Python 'requests' library.
headers = {'x-amz-date':amzdate, 'Authorization':authorization_header, 'X-Amz-Security-Token':session_token}
# ************* SEND THE REQUEST *************
request_url = endpoint + path + canonical_querystring
print('\nBEGIN REQUEST++++++++++++++++++++++++++++++++++++')
print('Request URL = ' + request_url)
print('Headers = ' + str(headers))
r = requests.get(request_url, headers=headers)
print('\nRESPONSE++++++++++++++++++++++++++++++++++++')
print('Response code: %d\n' % r.status_code)
print(r.text)
Aha, I found an answer. I was pulling the credentials from the wrong endpoint. https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-categories.html shows "identity-credentials/ec2/security-credentials/ec2-instance" are "Internal use only". There is an iam/security-credentials/{role} that works a LOT better!!

Is it possible to download files/data during the build pipeline on Azure DevOps?

We would like to transfer the development via azure devops to another company and we ask ourselves whether not only new releases can be pushed through this pipeline. But also data could be downloaded from the productive environment via the azure devops or aws devops pipeline?
I researched myself but found nothing about it.
does any of you have more information on this?
Thank you
Is it possible to download files/data during the build pipeline on Azure DevOps?
In Azure DevOps, there isn't a task to download files/data, but you can use the PowerShell task to connect to FTP server and download files.
For detailed information, you can refer to this similar question.
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
#FTP Server Information - SET VARIABLES
$ftp = "ftp://XXX.com/"
$user = 'UserName'
$pass = 'Password'
$folder = 'FTP_Folder'
$target = "C:\Folder\Folder1\"
#SET CREDENTIALS
$credentials = new-object System.Net.NetworkCredential($user, $pass)
function Get-FtpDir ($url,$credentials) {
$request = [Net.WebRequest]::Create($url)
$request.Method = [System.Net.WebRequestMethods+FTP]::ListDirectory
if ($credentials) { $request.Credentials = $credentials }
$response = $request.GetResponse()
$reader = New-Object IO.StreamReader $response.GetResponseStream()
while(-not $reader.EndOfStream) {
$reader.ReadLine()
}
#$reader.ReadToEnd()
$reader.Close()
$response.Close()
}
#SET FOLDER PATH
$folderPath= $ftp + "/" + $folder + "/"
$files = Get-FTPDir -url $folderPath -credentials $credentials
$files
$webclient = New-Object System.Net.WebClient
$webclient.Credentials = New-Object System.Net.NetworkCredential($user,$pass)
$counter = 0
foreach ($file in ($files | where {$_ -like "*.txt"})){
$source=$folderPath + $file
$destination = $target + $file
$webclient.DownloadFile($source, $target+$file)
#PRINT FILE NAME AND COUNTER
$counter++
$counter
$source
}
Certificate comes from: PowerShell Connect to FTP server and get files.
You should use artifacts when it is inside your "environment".
Otherwise you can use the normal command line tools like git or curl and wget this depends on your build agent.

List of Google API endpoints call by the SDK

We have previously generated a list of Google's API end-points utilised by the SDK by grepping the source repo. Now that that doesn't seem to be available, has anyone else found a way of obtaining such a list? We need to be able to whitelist these end-points on our corporate firewall/proxy.
Thanks!
PART 1
If your objective is to whitelist URLs for your firewall, the URL *.googleapis.com will cover 99% of everything you need. There are only a few endpoints left:
bookstore.endpoints.endpoints-portal-demo.cloud.goog
cloudvolumesgcp-api.netapp.com
echo-api.endpoints.endpoints-portal-demo.cloud.goog
elasticsearch-service.gcpmarketplace.elastic.co
gcp.redisenterprise.com
payg-prod.gcpmarketplace.confluent.cloud
prod.cloud.datastax.com
PART 2
List the Google API endpoints that are available for your project with this command:
gcloud services list --available --format json | jq -r ".[].config.name"
https://cloud.google.com/sdk/gcloud/reference/services/list
Refer to PART 5 for a PowerShell script that produces a similar list.
PART 3
Process the Discovery Document which provides machine readable information:
Google API Discovery Service
curl https://www.googleapis.com/discovery/v1/apis | jq -r ".items[].discoveryRestUrl"
Once you have a list of discovery documents, process each document and extract the rootUrl key.
curl https://youtubereporting.googleapis.com/$discovery/rest?version=v1 | jq -r ".rootUrl"
PART 4
PowerShell script to process the Discovery Document and generate an API endpoint list:
Copy this code to a file named list_google_apis.ps1. Run the command as follows:
powershell ".\list_google_apis.ps1 | Sort-Object -Unique | Out-File -Encoding ASCII -FilePath apilist.txt"
There will be some errors displayed as some of the discovery document URLs result in 404 (NOT FOUND) errors.
$url_discovery = "https://www.googleapis.com/discovery/v1/apis"
$params = #{
Uri = $url_discovery
ContentType = 'application/json'
}
$r = Invoke-RestMethod #params
foreach($item in $r.items) {
$url = $item.discoveryRestUrl
try {
$p = #{
Uri = $url
ContentType = 'application/json'
}
$doc = Invoke-RestMethod #p
$doc.rootUrl
} catch {
Write-Host "Failed:" $url -ForegroundColor Red
}
}
PART 5
PowerShell script that I wrote a while back that produces similar output to gcloud services list.
Documentation for the API:
https://cloud.google.com/service-usage/docs/reference/rest/v1/services/list
<#
.SYNOPSIS
This program displays a list of Google Cloud services
.DESCRIPTION
Google Service Management allows service producers to publish their services on
Google Cloud Platform so that they can be discovered and used by service consumers.
.NOTES
This program requires the Google Cloud SDK CLI is installed and set up.
https://cloud.google.com/sdk/docs/quickstarts
.LINK
PowerShell Invoke-RestMethod
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-restmethod?view=powershell-5.1
Google Cloud CLI print-access-token Documentation
https://cloud.google.com/sdk/gcloud/reference/auth/print-access-token
Google Cloud API Documentation
https://cloud.google.com/service-infrastructure/docs/service-management/reference/rest
https://cloud.google.com/service-usage/docs/reference/rest/v1/services
https://cloud.google.com/service-infrastructure/docs/service-management/reference/rest/v1/services/list
#>
function Get-AccessToken {
# Get an OAuth Access Token
$accessToken=gcloud auth print-access-token
return $accessToken
}
function Display-ServiceTable {
Param([array][Parameter(Position = 0, Mandatory = $true)] $serviceList)
if ($serviceList.Count -lt 1) {
Write-Output "No services were found"
return
}
# Display as a table
$serviceList.serviceConfig | Select name, title | Format-Table -Wrap | more
}
function Get-ServiceList {
Param([string][Parameter(Position = 0, Mandatory = $true)] $accessToken)
# Build the url
# https://cloud.google.com/service-infrastructure/docs/service-management/reference/rest/v1/services/list
$url="https://servicemanagement.googleapis.com/v1/services"
# Build the Invoke-RestMethod parameters
# https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-restmethod?view=powershell-5.1
$params = #{
Headers = #{
Authorization = "Bearer " + $accessToken
}
Method = 'Get'
ContentType = "application/json"
}
# Create an array to store the API output which is an array of services
$services = #()
# Google APIs page the output
$nextPageToken = $null
do {
if ($nextPageToken -eq $null)
{
$uri = $url
} else {
$uri = $url + "?pageToken=$nextPageToken"
}
try {
# Get the list of services
$output = Invoke-RestMethod #params -Uri $uri
} catch {
Write-Host "Error: REST API failed." -ForegroundColor Red
Write-Host "URL: $url" -ForegroundColor Red
Write-Host $_.Exception.Message -ForegroundColor Red
return $services
}
# Debug: Display as JSON
# $output | ConvertTo-Json
# Append services to list
$services += $output.services
$nextPageToken = $output.nextPageToken
} while ($nextPageToken -ne $null)
return $services
}
############################################################
# Main Program
############################################################
$accessToken = Get-AccessToken
$serviceList = Get-ServiceList $accessToken
Display-ServiceTable $serviceList
Command-line tool JQ

Unable to register targets on AWS Target group

I am trying to setup an automated DNS deployment using powershell. I have written a powershell script that creates TargetGroup, registers instances to the TG, creates an ALB and adds a listener to it. Once, that is done, it creates R53 RecordSet and creates an A record to the ALB DNS.
I am having issues in having the instances registered to the TargetGroup.
This is my code snippet to that section:
$searchFor1 =#( #{name = 'tag:Name'; values = $target1})
$searchFor2 =#( #{name = 'tag:Name'; values = $target2})
$id1 = (Get-EC2Instance -Filter $searchFor1).Instances | select InstanceId
$id2 = (Get-EC2Instance -Filter $searchFor2).Instances | select InstanceId
# Create Target Group
$tg = New-ELB2TargetGroup -TargetType "instance" -HealthyThresholdCount 4 -Name $custname -Port $siteport -Protocol "HTTP" -UnhealthyThresholdCount 4 -VpcId $vpcid
Start-Sleep -s 120
$addid1 = New-Object Amazon.ElasticLoadBalancingV2.Model.TargetDescription
$addid2 = New-Object Amazon.ElasticLoadBalancingV2.Model.TargetDescription
$addid1.Id = $id1.InstanceId
$addid2.Id = $id2.InstanceId
$addid1.Port = $siteport
$addid2.Port = $siteport
$tgarn = (Get-ELB2TargetGroup -Name $custname).TargetGroupArn
Register-ELB2Target -TargetGroupArn $tgarn -Target #($addid1)
Register-ELB2Target -TargetGroupArn $tgarn -Target #($addid2)
It throws below error:
Register-ELB2Target : An instance ID must be specified
At C:\scripts\Distinct-DNS-Deployment.ps1:107 char:1
+ Register-ELB2Target -TargetGroupArn $tgarn -Target #($addid1)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (Amazon.PowerShe...LB2TargetCmdlet:RegisterELB2TargetCmdlet) [Register
-ELB2Target], InvalidOperationException
+ FullyQualifiedErrorId : Amazon.ElasticLoadBalancingV2.AmazonElasticLoadBalancingV2Exception,Amazon.PowerShell.Cm
dlets.ELB2.RegisterELB2TargetCmdlet
I have checked a similar post here. And the corresponding posts, so far nothing helped. I am wondering if anyone can guide me what am I doing wrong?
I have tried to run each line one by one and that happens to register the instance to the TargetGroup, just the script fails.
Instances are t2.micro and they are in running state.
As per the https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/ElasticLoadBalancingV2/TTargetDescription.html -
the Amazon.ElasticLoadBalancingV2.Model.TargetDescription is about 'Information about a target' -
which means, you should be assigning a single instance id Also, if you take a close look at the properties:
AvailabilityZone System.String
Id System.String
Port System.Int32
The result of your instance search may or may not be single output - you should keep them in loop to create each target via TargetDescription
$Instances = (Get-EC2Instance -Filter #{Name="tag:auto-delete";Value="no"}).instances |select instanceid
$theVpc = get-ec2vpc -VpcId vpc-4565e5c4
$name = "new-tg"
$port = "80"
$protocol = "HTTP"
$tg = New-ELB2TargetGroup -TargetType "instance" -HealthyThresholdCount 4 -Name $name -Port $port -Protocol "HTTP" -UnhealthyThresholdCount 4 -VpcId $theVpc.VpcId
$tgarn = (Get-ELB2TargetGroup -Name $name).TargetGroupArn
If($instances -ne $null){
foreach ($instance in $instances ){
$addid1 = New-Object Amazon.ElasticLoadBalancingV2.Model.TargetDescription
$addid1.Id = $Instance.instanceid
$addid1.Port = $port
Register-ELB2Target -TargetGroupArn $tgarn -Target #($addid1)
Remove-Variable addid1
}
}
else {
echo "There were no instances with the matching filter"
}

Issue with a Powershell script transferring files to a S3 Bucket

I am trying to setup a powershell script in an attempt to setup a automated transfer of a directory to a S3 Bucket, I have been following instructions listed at http://todhilton.com/technicalwriting/upload-backup-your-files-to-amazon-s3-with-powershell/ but when I run it I get the following error.
Unable to find type [Amazon.AWSClientFactory].
At line:18 char:9
+ $client=[Amazon.AWSClientFactory]::CreateAmazonS3Client($accessKeyID, ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (Amazon.AWSClientFactory:TypeName) [], RuntimeException
+ FullyQualifiedErrorId : TypeNotFound
The Code I have is pasted in below... If someone has some insight that would be awsome :)
# Constants
$sourceDrive = "C:\"
$sourceFolder = "Users\Administrator\AppData\Roaming\folder"
$sourcePath = $sourceDrive + $sourceFolder
$s3Bucket = "bucket"
$s3Folder = "Archive"
# Constants – Amazon S3 Credentials
$accessKeyID="KEY"
$secretAccessKey="Secret"
# Constants – Amazon S3 Configuration
$config=New-Object Amazon.S3.AmazonS3Config
$config.RegionEndpoint=[Amazon.RegionEndpoint]::"ap-southeast-2"
$config.ServiceURL = "https://s3-ap-southeast-2.amazonaws.com/"
# Instantiate the AmazonS3Client object
$client=[Amazon.AWSClientFactory]::CreateAmazonS3Client($accessKeyID,$secretAccessKey,$config)
# FUNCTION – Iterate through subfolders and upload files to S3
function RecurseFolders([string]$path) {
$fc = New-Object -com Scripting.FileSystemObject
$folder = $fc.GetFolder($path)
foreach ($i in $folder.SubFolders) {
$thisFolder = $i.Path
# Transform the local directory path to notation compatible with S3 Buckets and Folders
# 1. Trim off the drive letter and colon from the start of the Path
$s3Path = $thisFolder.ToString()
$s3Path = $s3Path.SubString(2)
# 2. Replace back-slashes with forward-slashes
# Escape the back-slash special character with a back-slash so that it reads it literally, like so: "\\"
$s3Path = $s3Path -replace "\\", "/"
$s3Path = "/" + $s3Folder + $s3Path
# Upload directory to S3
Write-S3Object -BucketName $s3Bucket -Folder $thisFolder -KeyPrefix $s3Path
}
# If subfolders exist in the current folder, then iterate through them too
foreach ($i in $folder.subfolders) {
RecurseFolders($i.path)
}
}
# Upload root directory files to S3
$s3Path = "/" + $s3Folder + "/" + $sourceFolder
Write-S3Object -BucketName $s3Bucket -Folder $sourcePath -KeyPrefix $s3Path
# Upload subdirectories to S3
RecurseFolders($sourcePath)
Please check below:
Amazon AWSClientFactory does not exists
Change: AWSClientFactory is removed
I used below script:
# Bucket region details
$RegionEndpoint = 'us-east-1'
#$ServiceURL = 'https://s3-us-east-1.amazonaws.com/'
#Credentials initialized
$credsCSV = Get-ChildItem "E:\myAPIUser_credentials.csv"
$credsContent = Import-Csv $credsCSV.FullName
$accessKeyID = $credsContent.'Access key ID'
$secretAccessKey = $credsContent.'Secret access key'
Initialize-AWSDefaults -Region $RegionEndpoint -AccessKey $accessKeyID -SecretKey $secretAccessKey
$sourceFolder = "E:\Code\powershell\PSmy\git\AWSPowerShell"
$targetFolder = Get-Date -Format "dd-MMM-yyyy"
Write-S3Object -BucketName $s3Bucket.BucketName -Folder $sourceFolder -Recurse -KeyPrefix $targetFolder\