Trying to figure out why 3 powershell cmdlets are not working when using AWS SM Automation inputs Script, but they do work when running them in a local script directly on my Windows instances.
The cmdlets: get-ciminstance
and rename-computer
work in Powershell 7, but add-computer
requires importing the module Microsoft.PowerShell.Management
for using the cmdlet Add-Computer
in PS7, which does work in my automation document execution. However, the Import-Module CimCmdlets does not work in aws ssm automation execution, I get the error: Could not load file or assembly 'Microsoft.Management.Infrastructure.CimCmdlets, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.The 'Get-CimInstance' command was found in the module 'CimCmdlets', but the module could not be loaded
. And if importing the required module for add-computer cmdlet works, why do I get an error for this cmdlet still? Very confused.
And the error for the 2 computer cmdlets is this:
The term 'Rename-Computer' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.The term 'Add-Computer' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again`
Note that the Import-Module CimCmdlets works when running it locally when I am in the Windows instance powerhshell terminal directly.
I also noticed that the cmdlets for Rename and Add computer have the disclaimer | This cmdlet is only available on the Windows platform.
Could it be that because I am using AWS SSM Automation to execute the script on my Windows instances that the "platform" is not Windows?
Just seeking any insight on this. I have read that it could be related the reference dll of Infrastructure file?
This is my systems manager automation document with the ps1 script contents inserted:
description: |-
---
# Automation to domain join Windows EC2 instance
schemaVersion: '0.3'
assumeRole: 'arn:***REDACTED***:role/AutomationServiceRole'
parameters:
secretParam:
type: String
hostnameParam:
type: String
InstanceId:
type: 'AWS::EC2::Instance::Id'
default: i-0983ac4bfa3d22189
mainSteps:
- name: domainjoin
action: 'aws:executeScript'
inputs:
Runtime: PowerShell 7.0
InputPayload:
host_name: '{{hostnameParam}}'
secret_set: '{{secretParam}}'
Script: |-
# Install-Module AWSPowerShell -Force
# Import-Module AWSPowerShell
Install-Module -Name AWS.Tools.Installer -Force
# Install-Module AWS.Tools.CloudWatchLogs -Force
# Install-Module AWS.Tools.SecretsManager -Force
# Import-Module AWS.Tools.Installer
Install-Module -Name AWS.Tools.CloudWatchLogs -Force
Install-Module -Name AWS.Tools.SecretsManager -Force
Install-Module -Name AWS.Tools.EC2 -Force
Install-Module -Name AWS.Tools.SecurityToken -Force
# Install-AWSToolsModule AWS.Tools.CloudWatchLogs,AWS.Tools.SecretsManager -Force -CleanUp
# Import-Module AWS.Tools.CloudWatchLogs
# Import-Module AWS.Tools.SecretsManager
# For using Add-Computer cmdlet
Import-Module Microsoft.PowerShell.Management -UseWindowsPowerShell -WarningAction SilentlyContinue
# For using Cim
Import-Module CimCmdlets
$inputPayload = $env:InputPayload | ConvertFrom-Json
[string]$hostnameparam = $inputPayload.host_name
[string]$secretparam = $inputPayload.secret_set
class Logger {
#----------------------------------------------
[string] hidden $cwlGroup
[string] hidden $cwlStream
[string] hidden $sequenceToken
#----------------------------------------------
# Log Initialization
#----------------------------------------------
Logger([string] $Action, [string] $HostName) {
$this.cwlGroup = "/ps/boot/configuration/"
$this.cwlStream = "{0}/{1}/{2}" -f $HostName, $Action,
(Get-Date -UFormat "%Y-%m-%d_%H.%M.%S")
$this.sequenceToken = ""
#------------------------------------------
if ( !(Get-CWLLogGroup -LogGroupNamePrefix $this.cwlGroup) ) {
New-CWLLogGroup -LogGroupName $this.cwlGroup
Write-CWLRetentionPolicy -LogGroupName $this.cwlGroup -RetentionInDays 3
}
if ( !(Get-CWLLogStream -LogGroupName $this.cwlGroup -LogStreamNamePrefix $this.cwlStream) ) {
New-CWLLogStream -LogGroupName $this.cwlGroup -LogStreamName $this.cwlStream
}
}
#----------------------------------------
[void] WriteLine([string] $msg) {
$logEntry = New-Object -TypeName "Amazon.CloudWatchLogs.Model.InputLogEvent"
#-----------------------------------------------------------
$logEntry.Message = $msg
$logEntry.Timestamp = (Get-Date).ToUniversalTime()
if ("" -eq $this.sequenceToken) {
# First write into empty log...
$this.sequenceToken = Write-CWLLogEvent -LogGroupName $this.cwlGroup `
-LogStreamName $this.cwlStream `
-LogEvent $logEntry
}
else {
# Subsequent write into the log...
$this.sequenceToken = Write-CWLLogEvent -LogGroupName $this.cwlGroup `
-LogStreamName $this.cwlStream `
-SequenceToken $this.sequenceToken `
-LogEvent $logEntry
}
}
}
[Logger]$log = [Logger]::new("UserData", $hostnameparam)
$log.WriteLine("------------------------------")
$log.WriteLine("Log Started - V4.0")
$RunUser = $env:username
$log.WriteLine("PowerShell session user:" + $RunUser + " executed.")
$log.WriteLine("Loading Secret <" + $secretparam + ">")
$SecretObj = (Get-SECSecretValue -SecretId $secretparam -ErrorVariable SecretObjProcessError)
if ($SecretObjProcessError) {
$log.WriteLine($SecretObjProcessError)
$log.WriteLine("Could not load secret <" + $secretparam + "> - terminating execution")
return
}
[PSCustomObject]$Secret = ($SecretObj.SecretString | ConvertFrom-Json)
$password = $Secret.password | ConvertTo-SecureString -asPlainText -Force
$username = $Secret.username
$credential = New-Object System.Management.Automation.PSCredential($username, $password)
$log.WriteLine("Domain (from Secret): <" + $Secret.domainname + ">")
# Verify domain membership
$compSys = Get-CimInstance -ClassName Win32_ComputerSystem | Select-Object -Property *
#------------------------------------------------------------------------------
if ( ($compSys.PartOfDomain) -and ($compSys.Domain -eq $Secret.domainname)) {
$log.WriteLine("Already member of: <" + $compSys.Domain + "> - Verifying RSAT Status")
$RSAT = (Get-WindowsFeature RSAT-AD-PowerShell)
if ($null -eq $RSAT) {
$log.WriteLine("<RSAT-AD-PowerShell> feature not found - terminating script")
return
}
if ( (-Not $RSAT.Installed) -and ($RSAT.InstallState -eq "Available") ) {
$log.WriteLine("Installing <RSAT-AD-PowerShell> feature")
Install-WindowsFeature RSAT-AD-PowerShell
}
$comProp = (Get-ADComputer -Identity $hostnameparam -Properties Description)
if ($null -eq $comProp.Description) {
$log.WriteLine("Adding instance metadata to description attribute")
$instanceId = Get-EC2InstanceMetadata -Category instanceId
$instanceAz = Get-EC2InstanceMetadata -Category AvailabilityZone
$instanceAccountId = (Get-STSCallerIdentity).Account
$instanceDescription = $instanceId + "|" + $instanceAccountId + "|" + $instanceAz
$log.WriteLine("Adding description <" + $instanceDescription + ">")
Set-ADComputer -Identity $hostnameparam -Credential $credential -Description $instanceDescription
}
# Adding DNS Suffix for WFM domain
$dnssuffixeslist = get-DnsClientGlobalSetting
if ($Secret.domainname -in $dnssuffixeslist.SuffixSearchList) {
$log.WriteLine("DNS suffix <" + $Secret.domainname + "> already exists.")
}
else {
$log.WriteLine("Existing DNS suffixes <" + $dnssuffixeslist.SuffixSearchList + ">")
$log.WriteLine("Adding DNS suffix for <" + $Secret.domainname + ">")
$dnssuffixeslist.SuffixSearchList += $Secret.domainname
Set-DnsClientGlobalSetting -SuffixSearchList @($dnssuffixeslist.SuffixSearchList) -ErrorVariable DnsSuffixAddError
if ($AddCoDnsSuffixAddErrorputerProcessError) {
$log.WriteLine($DnsSuffixAddError)
$log.WriteLine("Error occured while adding DNS suffix for <" + $Secret.domainname + "> domain")
return
}
$updateddnssuffixeslist = get-DnsClientGlobalSetting
$log.WriteLine("Updated DNS suffixes <" + $updateddnssuffixeslist.SuffixSearchList + ">")
}
$log.WriteLine("Terminating script - ")
return
}
# Performing Domain Join
$log.WriteLine("Performing Domain Join")
Rename-Computer -NewName $hostnameparam -Force
$log.WriteLine("Attempting to join domain <" + $Secret.domainname + ">")
Add-Computer -ComputerName $hostnameparam -DomainName $Secret.domainname -Credential $credential -OUPath $Secret.oupath -Restart -Force -Verbose -ErrorVariable AddComputerProcessError
if ($AddComputerProcessError) {
$log.WriteLine($AddComputerProcessError)
$log.WriteLine("Error occured while performing domain join operation on host - terminating execution")
return
}
$log.WriteLine("Requesting restart...")