problem with var once it gest converted to json

I working on a script to configure aws end points in a backup tool. I am not seeing why the data is getting treated differently.

 

Here is the script:

#Add AWS Account

$key="key"
$skey="skey"
$region="eu-west-1, us-east-1"
$region = $region.Replace(' ','')
$region = $region.Replace(',','","')
$region="`"$region`""
$region

$awsadd = @{
accesskey="$key"
secretkey="$skey"
#regions=@("eu-west-1", "us-east-1")

regions=@($region)
}
$json = $awsadd |ConvertTo-Json
$json

 

 

These two get treated different and i am not sure why:

#regions=@("eu-west-1", "us-east-1")

regions=@($region)

When i have the text typed out it works right:

$json = $awsadd |ConvertTo-Json
$json
{
"regions": [
"eu-west-1",
"us-east-1"
],

 

When i use the var it looks like this:

{
"regions": [
"\"eu-west-1\",\"us-east-1\""
],

 

The second way does not work. Thoughts on how i can do this?

 

Hey Nick, you seem like you’re used to linux bash or something like that. Windows is different in the sense that you deal with objects not text. So the first 10 lines trying to format the regions are completely unnecessary in Windows/PowerShell. All you need to define your AWS regions is put them in an array like:

$AWSRegions = @(
    'eu-west-1'
    'us-east-1'
)

Also, I recommend you make it a habit to not type in passwords/keys in a script. Use the securestring cmdlets to keep secrets encrypted. for example:

#region Input
$AccessKey  = 'Type in your AWS Access Key here' # Common misnomer, this is no 'key', it's a login/user name
$SecretKey  = Read-Host "Please enter secret key for $AccessKey" -AsSecureString # again not a key, this is a password
$AWSRegions = @(
    'eu-west-1'
    'us-east-1'
)
#endregion


$AWSCred = New-Object PSCredential -ArgumentList $AccessKey, $SecretKey 

$JSON = @{
    accesskey = $AccessKey
    secretkey = $AWSCred.GetNetworkCredential().Password
    regions   = $AWSRegions
} | ConvertTo-Json

$JSON

Finally, since the secret key is visible in the JSON, I recommend that it be encrypted in transit.

For the initial I have 100+ aws accounts to add .I need the key and skey for each and they each are in different regions .I have this data in a csv file and I am going to iterate throughthe file once I can dynamicly set the regions .

Having 100’s of account access credentials in a spreadsheet is a security nightmare. I would put that in a password management system that keeps them properly protected, and go through the extra effort of having API access to it from PowerShell for this script…

I don’t disagree but that still leaves me with my problem . Do you have any insight to help me with that?

what are the names of the fields in the csv? Can you provide sample?

Here is some sample data:

 

veritascloudpoint_aws_iam_access_key_id veritascloudpoint_aws_iam_access_key_secret Region
key1 skey1 us-east-1, us-east-2
key2 skey2 eu-west-1, us-east-1
key3 skey3 ap-northeast-1, ap-northeast-2, ap-southeast-1, ap-southeast-2, eu-central-1, eu-west-1, us-east-1, us-west-1, us-west-2
 

 

$CSVFilename = 'd:\sandbox\myfile1.csv'

##########################################

$AccountList = Import-Csv $CSVFilename 

foreach ($Account in $AccountList) {
    $JSON = @{
        accesskey = $Account.veritascloudpoint_aws_iam_access_key_id
        secretkey = $Account.veritascloudpoint_aws_iam_access_key_secret
        regions   = $Account.Region.Split(',').Trim()
    } | ConvertTo-Json

    $JSON
}

CSV sample file:

"veritascloudpoint_aws_iam_access_key_id","veritascloudpoint_aws_iam_access_key_secret","Region"
"key1","skey1","us-east-1, us-east-2"
"key2","skey2","eu-west-1, us-east-1"
"key3","skey3","ap-northeast-1, ap-northeast-2, ap-southeast-1, ap-southeast-2, eu-central-1, eu-west-1, us-east-1, us-west-1, us-west-2"
"key4","skey4","eu-west-4"
$AccountList

veritascloudpoint_aws_iam_access_key_id veritascloudpoint_aws_iam_access_key_secret Region                                                                                       
--------------------------------------- ------------------------------------------- ------                                                                                       
key1                                    skey1                                       us-east-1, us-east-2                                                                         
key2                                    skey2                                       eu-west-1, us-east-1                                                                         
key3                                    skey3                                       ap-northeast-1, ap-northeast-2, ap-southeast-1, ap-southeast-2, eu-central-1, eu-west-1, u...
key4                                    skey4                                       eu-west-4                     

JSON:

{
    "regions":  [
                    "us-east-1",
                    "us-east-2"
                ],
    "secretkey":  "skey1",
    "accesskey":  "key1"
}
{
    "regions":  [
                    "eu-west-1",
                    "us-east-1"
                ],
    "secretkey":  "skey2",
    "accesskey":  "key2"
}
{
    "regions":  [
                    "ap-northeast-1",
                    "ap-northeast-2",
                    "ap-southeast-1",
                    "ap-southeast-2",
                    "eu-central-1",
                    "eu-west-1",
                    "us-east-1",
                    "us-west-1",
                    "us-west-2"
                ],
    "secretkey":  "skey3",
    "accesskey":  "key3"
}
{
    "regions":  "eu-west-4",
    "secretkey":  "skey4",
    "accesskey":  "key4"
}

I see that it works with the rest call when there is more than one region , but on a single it fails. Which is farther than i had before. Here is what i am seeing thoughts?

 

{
“regions”: [
“ap-northeast-1”,
“ap-southeast-1”,
“ap-southeast-2”,
“eu-west-1”,
“us-east-1”,
“us-west-1”
],
“secretkey”: “skey”,
“accesskey”: “key”
}
status : configuring
taskid : 9885e3fe-15e1-46c1-8b74-6e53dad233c2
configId : aws.811a338d-4aa2-4c19-897d-c2bcb029777e
configuration : @{regions=System.Object[]; accesskey=key}
configHash : caba490fdac817dba80b1bb0f192c9c497453e2585ee90477588f45953b86be6
errmsg :

{
“regions”: “us-east-1”,
“secretkey”: “skey”,
“accesskey”: “key”
}
Invoke-RestMethod : {
“msg”: “Value for ‘regions’ not a list: us-east-1”,
“errMsg”: “Value for ‘regions’ not a list: us-east-1”,
“httpStatusCode”: 500,
“type”: “error”
}
At line:49 char:5

  • Invoke-RestMethod -uri "https://led36461/cloudpoint/api/v2/agents
  • CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
  • FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

We can also see a difference in the display of the var. How can we make that consistant?

 

“regions”: [
“ap-northeast-1”,
“ap-northeast-2”,
“ap-southeast-1”,
“ap-southeast-2”,
“eu-central-1”,
“eu-west-1”,
“us-east-1”,
“us-west-1”,
“us-west-2”
],
“secretkey”: “skey3”,
“accesskey”: “key3”
}
{
“regions”: “eu-west-4”,
“secretkey”: “skey4”,
“accesskey”: “key4”
}

Note the square brackets, which indicates an array. The single variable is scalar. If you build the object like this, Powershell converts the comma separated values to an array automatically and the variable that is not comma separated it leaves it scalar:

$regions = @()
$regions += [pscustomobject]@{
    regions = "us-east-1","us-east-2"
    secretkey = 'skey1'
    accesskey = 'key1'
}
$regions += [pscustomobject]@{
    $regions = "eu-west-1","us-east-1"
    secretkey = 'skey2'
    accesskey = 'key2'
}
$regions += [pscustomobject]@{
    $regions = "ap-northeast-1",
               "ap-northeast-2",
               "ap-southeast-1",
               "ap-southeast-2",
               "eu-central-1",
               "eu-west-1",
               "us-east-1",
               "us-west-1",
               "us-west-2"
    secretkey = 'skey2'
    accesskey = 'key2'
}
$regions += [pscustomobject]@{
    regions = "eu-west-4"
    secretkey = 'skey1'
    accesskey = 'key1'
}

$regions | ConvertTo-Json

Generating from a CSV would be like this:

$csv = Import-CSV C:\Scripts\my.csv


$regions = foreach ($row in $csv)  {
    [pscustomobject]@{
        regions   = if ($row.region -like '*,*') {$row.region -split ","} else {$row.region}
        secretkey = $row.veritascloudpoint_aws_iam_access_key_secret
        accesskey = $row.veritascloudpoint_aws_iam_access_key_id
    }
}

$regions | ConvertTo-Json

Generating:

[
    {
        "regions":  [
                        "us-east-1",
                        " us-east-2"
                    ],
        "secretkey":  "skey1",
        "accesskey":  "key1"
    },
    {
        "regions":  [
                        "eu-west-1",
                        " us-east-1"
                    ],
        "secretkey":  "skey2",
        "accesskey":  "key2"
    },
    {
        "regions":  [
                        "ap-northeast-1",
                        " ap-northeast-2",
                        " ap-southeast-1",
                        " ap-southeast-2",
                        " eu-central-1",
                        " eu-west-1",
                        " us-east-1",
                        " us-west-1",
                        " us-west-2"
                    ],
        "secretkey":  "skey3",
        "accesskey":  "key3"
    },
    {
        "regions":  "eu-west-4",
        "secretkey":  "skey4",
        "accesskey":  "key4"
    }
]

I think thats still going to cause the same problem. The api end point is expecting a list it looks like so when the single entity does not show up as a list in [] it looks to be a problem.

 

“regions”: [
“ap-northeast-1”,
" ap-northeast-2",
" ap-southeast-1",
" ap-southeast-2",
" eu-central-1",
" eu-west-1",
" us-east-1",
" us-west-1",
" us-west-2"
],
“secretkey”: “skey3”,
“accesskey”: “key3”
},
{
“regions”: “eu-west-4”,
“secretkey”: “skey4”,
“accesskey”: “key4”
}
]

 

See what i bolded above for where it seems to not be the same.

$CSVFilename = '.\myfile1.csv'

##########################################

$AccountList = Import-Csv $CSVFilename 

foreach ($Account in $AccountList) {
    $JSON = @{
        accesskey = $Account.veritascloudpoint_aws_iam_access_key_id
        secretkey = $Account.veritascloudpoint_aws_iam_access_key_secret
        regions   = $Account.Region.Split(',').Trim() -as [String[]]
    } | ConvertTo-Json

    $JSON
}

Or…

$csv = Import-CSV C:\Scripts\my.csv


$regions = foreach ($row in $csv)  {
    [pscustomobject]@{
        regions   = $row.region -split ","
        secretkey = $row.veritascloudpoint_aws_iam_access_key_secret
        accesskey = $row.veritascloudpoint_aws_iam_access_key_id
    }
}

$regions | ConvertTo-Json

Thanks Guys. I appricate the help. Here is where i ended and it all worked great for me. On top of that i understand what you did and why you did it after seeing it. Again thanks.

 

$AccountList = Import-Csv $CSVFilename 
foreach ($Account in $AccountList) {
$JSON = @{
accesskey = $Account.veritascloudpoint_aws_iam_access_key_id
secretkey = $Account.veritascloudpoint_aws_iam_access_key_secret
regions = $Account.Region.Split(',').Trim() -as [String[]]
} | ConvertTo-Json

$JSON
Invoke-RestMethod -uri "https://led36461/cloudpoint/api/v2/agents/$agentid/plugins/aws/configs" -Headers @{"Authorization" = "Bearer $token"} -Method Post -ContentType 'application/json' -Body $JSON
}