PowerShell 7 Cmdlets not recognized when using AWS SSM Automation document script

580 views Asked by At

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...")
0

There are 0 answers