Invoke Parameter into a CloudFormation Powershell script - json

it is possible to invoke a parameter into a PowerShell script running inside userdata?
I'm trying to assign a password, ADuser, and domain, in order to change the local computer name and join the server into the domain.
I can add the self input during the stack creation, but I don't know how to use the info inside userdata, is there any Ref that it can be used?
I'm able to do this using all the information inside userdata, but I don't want to save the stack with our domain information and credentials.
"Parameters" : {
"VMName":{
"Description":"Name of the EC2 Windows instance",
"Type":"String"
},
"DomainUser":{
"Description":"Name of Service/User domain account to be used to join the EC2 instance into CX domain",
"Type" : "String",
"MinLength" : "3",
"MaxLength" : "25",
"AllowedPattern" : "[a-zA-Z0-9]+\\..+"
},
"DomainCredential":{
"Description":"Password of the Service/User domain account to be used to join the EC2 instance into CX domain",
"Type" : "String",
"MinLength" : "8",
"MaxLength" : "32",
"AllowedPattern" : "(?=^.{6,255}$)((?=.*\\d)(?=.*[A-Z])(?=.*[a-z])|(?=.*\\d)(?=.*[^A-Za-z0-9])(?=.*[a-z])|(?=.*[^A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z])|(?=.*\\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9]))^.*",
"NoEcho" : "True"
},
"Resources" : {
"EC2InstanceOne":{
"Type":"AWS::EC2::Instance",
"DeletionPolicy" : "Retain",
"Properties":{
"InstanceType":{ "Ref" : "InstanceType" },
"SubnetId": { "Ref" : "MySubnetVM1" },
"SecurityGroupIds":[ { "Ref" : "SGUtilized" } ],
"SecurityGroupIds":[ { "Ref" : "SGUtilized2" } ],
"IamInstanceProfile" : { "Ref" : "RoleName" },
"KeyName": { "Ref" : "ServerKeyName" },
"ImageId":{ "Ref" : "AMIUtilized" },
"BlockDeviceMappings" : [
{
"DeviceName" : "/dev/sda1",
"Ebs" : {
"VolumeType" : "standard",
"DeleteOnTermination" : "false",
"VolumeSize" : "50"
}
}
],
"UserData" : { "Fn::Base64" : { "Fn::Join" : [ "", [
"<script>\n",
"PowerShell -Command \"& {$password = 'variable from parameter here' | ConvertTo-SecureString -asPlainText -Force ; $username = 'variable from parameter here'' ; $credential = New-Object System.Management.Automation.PSCredential($username,$password) ; Rename-Computer -NewName 'variable from parameter here'' -DomainCredential $credential}\" \n",
"PowerShell -Command \"& {$domain='variable from parameter here';$password = 'variable from parameter here'' | ConvertTo-SecureString -asPlainText -Force ;$username = 'variable from parameter here'' ; $credential = New-Object System.Management.Automation.PSCredential($username,$password) ; Add-Computer -DomainName $domain -Credential $credential}\" \n",
"PowerShell -Command \"& {Restart-Computer}\" \n",
"</script>"
]
]
}
}
}
Thanks, best regards.

you can to use Fn::Sub like this:
{
"Fn::Sub":
"PowerShell -Command \"& {$domain=${VMName};$password = ${DomainCredential}' | ConvertTo-SecureString -asPlainText -Force ;$username = ${DomainUser}' ; $credential = New-Object System.Management.Automation.PSCredential($username,$password) ; Add-Computer -DomainName $domain -Credential $credential}\" \n"
}
here's a yaml sample :
UserData:
Fn::Base64:
!Sub |
echo ${ParamPassword} | tee - | passwd ec2-user

Related

JSON file - how to delete entire node that contains a string

I have a JSON file:
{
"JSONS" : [
{
"id" : "ToRemove",
"First" : [
{
"id" : "geo",
"Name" : "Person1",
"model" : [
],
"adjustments" : [
{
"uid" : "3",
"name" : "4s",
"value" : "1"
},
{
"uid" : "5",
"name" : "3s",
"value" : "6"
}
]
},
{
"id" : "Meters",
"Dictionary" : "4.2"
},
{
"id" : "Moon",
"Filter" : "0.5",
"Saturn" : {
"s" : "0",
"v" : "1"
}
}
]
}
]
}
I would like to delete entire node, if the "id", in this example, contains "ToRemove" string. Everyting between { and }, including those lines also, to make the final JSON consistent.
This is a screenshot what I want to get rid of.
I only found how to delete properties, but not entire nodes. I've tried to appli something like this:
$ToRemove = Get-Content $SourceFile | ConvertFrom-Json
$ToRemove.PSObject.Object.Remove('id:','ToRemove')
$ToRemove | ConvertTo-Json -Depth 100 | Out-File $DestFile
but of course it didn't work.
How to delete the entire node? I would love to use an array to put all strings I would like to delete.
Based on your comment, you can remove that object having the property id = ToRemove by filtering where id is not equal to ToRemove and assigning that result to the .JSONS property:
$json = Get-Content path\to\json.json -Raw | ConvertFrom-Json
$json.JSONS = #($json.JSONS.Where{ $_.id -ne 'ToRemove' })
$json | ConvertTo-Json
The end result in this case would be an empty array for the .JSONS property:
{
"JSONS": []
}
.PSObject.Properties.Remove(...) wouldn't be useful in this case because what it does is remove properties from one object but what you want to do is filter out an entire object based on a condition.
You should be able to use just plain PowerShell, like this:
{
"JSONS" : [
{
"id" : "ToRemove",
"First" : [
{
"id" : "geo",
"Name" : "Person1",
"model" : [
]
},
{
"id" : "Meters",
"Dictionary" : "4.2"
}
]
},
{
"id" : "DontRemove",
"First" : []
}
]
}
$json = Get-Content -Path $SourceFile | ConvertFrom-Json
$json.JSONS = $json.JSONS | Where-Object { $_.Id -ne "ToRemove" }
$json | ConvertTo-Json -Depth 100 | Out-File -Path $DestFile

How to get perl json access hash reference

I am trying to get remote host value which is remotehost . I decoded the json and able to get $name and $id values. but getting
Bad index while coercing array into hash while accessing 'remote -> host value which is remotehost.
my $json input is
[
{
"auth":{
"req": "1234",
"link": "http://localhost"
},
"host": "localhost",
"name": "mytest",
"remote": [
{
"host": "remotehost",
"name": "remotetest"
}
]
}
]
#My code
use JSON qw( decode_json );
use Data::Dumper;
my $list = decode_json($json) ;
my #array = #{$list};
foreach(#array)
{
my %obj = %{$_};
my $id = $obj{'auth'}{'link'};
my $name = $obj{'name'};
my $remotehost = $obj{'auth'}->{'remote'}{'host'}; #getting error
}
"remote": [
{
"host": "remotehost",
"name": "remotetest"
}
]
This bit is an array of objects (hashes in Perl). You cannot coerce it. You need to access the 1st element.
# A
# | B
# | | C
# | | |
$obj{'remote'}->[0]->{'host'}
Note there's no auth in this, because that's on the same level as remote (marked as A).
{
"auth" : {
"req": "1234",
"link": "http://localhost"
},
"host" : "localhost",
"name" : "mytest",
// A
"remote" : [ // B
{ // C
"host": "remotehost",
"name": "remotetest"
}
]
}

Trying to convert complex JSON to CSV with Powershell

I'm fairly new to PowerShell and I am trying to convert this JSON file to CSV.
Using some simple code like this:
$sourceFilePath = "Records.json"
$destinationFilePath = "Records.csv"
((Get-Content -Path $sourceFilePath -Raw) | ConvertFrom-Json) | Export-CSV $destinationFilePath -NoTypeInformation
Results in:
Because I am getting System.Object[] I think I need to do some kind of expansion or "ForEach" of the contact_ids, site_ids, first name aliases, and aliases. I've done some searching and I can't seem to wrap my head around the examples I've been given. Also, "first name aliases" has spaces in it that add to the complexity.
I don't have any control over the source JSON. Here it is as an example:
[
{
"mdm id" : "947b2a12-3aac-480a-a0bf-626aff106f48",
"first name" : "Claude",
"last name" : "Bones",
"contact_ids" : [
"CTP70499"
],
"site_ids" : [
"5015"
],
"first name aliases" : [
"Claude"
],
"aliases" : [
"Claude Bones"
],
"createdDate" : "2020-06-03T19:59:08Z",
"updatedDate" : "2020-06-03T20:48:27Z",
"veevaID" : "V0B000000000569"
},
{
"mdm id" : "bce21b05-0b28-4ebb-a34d-761c1a397821",
"first name" : "Daniel",
"last name" : "Smith",
"contact_ids" : [
"CTP699"
],
"site_ids" : [
"5015"
],
"first name aliases" : [
"Dan",
"Danial",
"Danne",
"Danny",
"Daniel"
],
"aliases" : [
"Daniel Smith"
],
"createdDate" : "2020-06-03T19:59:08Z",
"updatedDate" : "2020-06-03T20:48:27Z",
"veevaID" : "V0B000000000566"
}
]
The values that are arrays will need to be combined into a single value. Regardless of how many values it may have, if it's designated as an array [] in json, it will need to be manipulated. There are several articles and custom functions written on the internet. Your example could be handled with this bit of code.
$JSONdata = #'
[
{
"mdm id" : "947b2a12-3aac-480a-a0bf-626aff106f48",
"first name" : "Claude",
"last name" : "Bones",
"contact_ids" : [
"CTP70499"
],
"site_ids" : [
"5015"
],
"first name aliases" : [
"Claude"
],
"aliases" : [
"Claude Bones"
],
"createdDate" : "2020-06-03T19:59:08Z",
"updatedDate" : "2020-06-03T20:48:27Z",
"veevaID" : "V0B000000000569"
},
{
"mdm id" : "bce21b05-0b28-4ebb-a34d-761c1a397821",
"first name" : "Daniel",
"last name" : "Smith",
"contact_ids" : [
"CTP699"
],
"site_ids" : [
"5015"
],
"first name aliases" : [
"Dan",
"Danial",
"Danne",
"Danny",
"Daniel"
],
"aliases" : [
"Daniel Smith"
],
"createdDate" : "2020-06-03T19:59:08Z",
"updatedDate" : "2020-06-03T20:48:27Z",
"veevaID" : "V0B000000000566"
}
]
'# | ConvertFrom-Json
$JSONdata | foreach {
$record = [ordered]#{}
foreach($property in $_.psobject.Properties)
{
if($property.value -is [string])
{
$record.Add($property.name,$property.value)
}
else
{
$record.Add($property.name,($property.value -join ', '))
}
}
[PSCustomObject]$record
} | ConvertTo-Csv -NoTypeInformation
Output
"mdm id","first name","last name","contact_ids","site_ids","first name aliases","aliases","createdDate","updatedDate","veevaID"
"947b2a12-3aac-480a-a0bf-626aff106f48","Claude","Bones","CTP70499","5015","Claude","Claude Bones","2020-06-03T19:59:08Z","2020-06-03T20:48:27Z","V0B000000000569"
"bce21b05-0b28-4ebb-a34d-761c1a397821","Daniel","Smith","CTP699","5015","Dan, Danial, Danne, Danny, Daniel","Daniel Smith","2020-06-03T19:59:08Z","2020-06-03T20:48:27Z","V0B000000000566"
Simply change it to Export-Csv

PowerShell Question using Azure ARM Template Parameter array (my implementation of ConvertFrom-Json using an array fails)

I'm trying to pass in a $paramObject into a new ARM template deployment. I think I am missing something in my PowerShell to correctly convert the arrays so they can be used in the template.
$ResourceGroupName = "rg-testtemplate"
New-AzResourceGroup -Name "rg-testtemplate" -Location "West US"
$addressPrefixes = '["10.0.0.0/24"]' | ConvertFrom-Json
$subnet = '[{"name":"default","properties":{"addressPrefix":"10.0.0.0/24"}}]' | ConvertFrom-Json
$paramObject = #{
'addressPrefixes' = $addressPrefixes
'subnets' = $subnet
'virtualNetworkName' = "vnet-testtemplate"
}
$parameters = #{
'ResourceGroupName' = $ResourceGroupName
'TemplateFile' = '.\testpowershell.json'
'TemplateParameterObject' = $paramObject
'Verbose' = $true
}
New-AzResourceGroupDeployment #parameters
My template takes arrays.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"addressPrefixes": {
"type": "array"
},
"subnets": {
"type": "array"
},
"virtualNetworkName": {
"type": "string"
}
},
"resources": [
{
"name": "[parameters('virtualNetworkName')]",
"type": "Microsoft.Network/virtualNetworks",
"apiVersion": "2019-09-01",
"location": "West US",
"properties": {
"addressSpace": {
"addressPrefixes": "[parameters('addressPrefixes')]"
},
"subnets": "[parameters('subnets')]"
}
}
]
}
But when I go to deploy, I get back:
New-AzResourceGroupDeployment : 8:35:23 AM - Error: Code=InvalidTemplate; Message=Deployment template validation
failed: 'Template parameter JToken type is not valid. Expected 'Array'. Actual 'Object'. Please see
https://aka.ms/resource-manager-parameter-files for usage details.'.
At D:\repo\foldername\TestVM\testpowershelldeploy.ps1:30 char:5
+ New-AzResourceGroupDeployment #parameters
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [New-AzResourceGroupDeployment], Exception
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implementation.NewAzureResourceGroupDep
loymentCmdlet
New-AzResourceGroupDeployment : The deployment validation failed
At D:\repo\foldername\TestVM\testpowershelldeploy.ps1:30 char:5
+ New-AzResourceGroupDeployment #parameters
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [New-AzResourceGroupDeployment], InvalidOperationException
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implementation.NewAzureResourceGroupDeploymentCmdlet
What is the "fix" for converting my Json to a PowerShell array that my template needs?
If you want to create an array object with PowerShell, please use the command $t=#() to create.
For example
My template.json
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"addressPrefixes": {
"type": "array"
},
"subnets": {
"type": "array"
},
"virtualNetworkName": {
"type": "string"
}
},
"resources": [
{
"name": "[parameters('virtualNetworkName')]",
"type": "Microsoft.Network/virtualNetworks",
"apiVersion": "2019-09-01",
"location": "West US",
"properties": {
"addressSpace": {
"addressPrefixes": "[parameters('addressPrefixes')]"
},
"subnets": "[parameters('subnets')]"
}
}
]
}
my deploy script
Connect-AzAccount
$addressPrefixes =#( "10.0.0.0/24")
$subnet1= #{
"name"= "default"
"properties"=#{
"addressPrefix"="10.0.0.0/24"
}
}
$subnets = #($subnet1)
$paramObject = #{
'addressPrefixes' = $addressPrefixes
'subnets' = $subnets
'virtualNetworkName' = "vnet-testtemplate"
}
$parameters = #{
'ResourceGroupName' = "testtable"
'TemplateFile' = 'E:\test1.json'
'TemplateParameterObject' = $paramObject
'Verbose' = $true
}
New-AzResourceGroupDeployment #parameters

Perl code for multiple JSON messages parsing

I am trying to write a perl code to parse multiple JSON messages. The perl code that I have written only parses the values if the JSON file contains only one json message. But it fails when there are multiple messages in that file. It throws error: "Undefined subroutine &Carp::shortmess_heavy". The JSON file is in the following format:
{
"/test/test1/test2/test3/supertest4" : [],
"/test/test1/test2/test3/supertest2" : [
{
"tag1" : "",
"tag2" : true,
"tag3" : [
{
"status" : "TRUE",
"name" : "DEF",
"age" : "28",
"sex" : "f"
},
{
"status" : "FALSE",
"name" : "PQR",
"age" : "39",
"sex" : "f"
}
],
"tag4" : "FAILED",
"tag5" : "/test/test1/test2/test3/supertest2/test02",
"tag6" : ""
}
],
"/test/test1/test2/test3/supertest1" : [
{
"tag1" : "",
"tag2" : false,
"tag3" : [
{
"status" : "TRUE",
"name" : "ABC",
"age" : "21",
"sex" : "m"
},
{
"status" : "FALSE",
"name" : "XYZ",
"age" : "34",
"sex" : "f"
}
],
"tag4" : "PASSED",
"tag5" : "/test/test1/test2/test3/supertest1/test01",
"tag6" : ""
}
],
"/test/test1/test2/test3/supertest6" : []
}
My perl code to parse a single JSON message:
use strict;
use warnings;
use Data::Dumper;
use JSON;
use JSON qw( decode_json );
my $json_file = "tmp1.json";
my $json;
open (my $fh, '<', $json_file) or die "can not open file $json_file";
{ local $/; $json = <$fh>; }
close($fh);
my $decoded = decode_json($json);
print "TAG4 = " . $decoded->{'tag4'} . "\n";
print "TAg5 = " . $decoded->{'tag5'} . "\n";
my #tag3 = #{ $decoded->{'tag3'} };
foreach my $tg3 ( #tag3 ) {
print "Name = ". $tg3->{"name"} . "\n";
print "Status = ". $tg3->{"status"} . "\n";
print "Age = ". $tg3->{"age"} . "\n";
}
To parse multiple JSON objects, use JSON::XS/Cpanel::JSON::XS's incremental parsing.
my $json = '{"foo":"bar"} ["baz"] true 1.23';
my #results = JSON::XS->new->allow_nonref->incr_parse($json);
use Data::Dumper;
print Dumper \#results;
Output:
$VAR1 = [
{
'foo' => 'bar'
},
[
'baz'
],
bless( do{\(my $o = 1)}, 'JSON::PP::Boolean' ),
'1.23'
];