Remotely connecting to domain controller to use AD module

This topic contains 18 replies, has 3 voices, and was last updated by Profile photo of Anthony Anthony 4 months, 1 week ago.

  • Author
    Posts
  • #48786
    Profile photo of Ronnie Jorgensen
    Ronnie Jorgensen
    Participant

    Hi all,

    If I want to write a script where I do not assume that the local PC has RSAT tools installed in order to get the AD module and also I am not assuming the user is launching PowerShell with their admin credentials.

    How do I remotely connect to a domain controller in order to launch AD commands and at the end of my script terminate the remote connection?

    With Exchange it looks a bit like:

    $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $url -Credential $UserCredential
    Import-PSSession $Session -AllowClobber -DisableNameChecking
    
  • #48788
    Profile photo of Anthony
    Anthony
    Participant

    Pretty similar to Exchange the only difference is out of the box there is no configuration name configured for active directory so you will have to manually load the module before importing the session.

    $session = New-PSSession -ComputerName DC -Credential (Get-Credential)
    Invoke-Command $session -Scriptblock { Import-Module ActiveDirectory }
    Import-PSSession -Session $session
    Get-ADUser Administrator
    Get-PSSession | Remove-PSSession
    • This reply was modified 4 months, 1 week ago by Profile photo of Anthony Anthony.
  • #48793
    Profile photo of Ronnie Jorgensen
    Ronnie Jorgensen
    Participant

    Hi Anthony,

    that makes sense. So one final question. Obviously i cant stop someone from launching PowerShell as their admin account and perhaps they do indeed have RSAT tools installed.

    So i read earlier another way that you can connect to a remove domain controller and then export commands out so instead of running Get-ADComputer it becomes Get-REMADComputer

    I want my script / function to behave the same in all circumstances. not sure if that makes a difference as so which option i use?

    Update: this was the link i found: https://technet.microsoft.com/en-us/magazine/ff720181.aspx

    • This reply was modified 4 months, 1 week ago by Profile photo of Ronnie Jorgensen Ronnie Jorgensen. Reason: Adding link
  • #48796
    Profile photo of Ronnie Jorgensen
    Ronnie Jorgensen
    Participant

    Found this which is the same as what you are doing but with the -prefix 🙂

    At least i know if using Get-REMUser then it is from that session 🙂

  • #48798
    Profile photo of Anthony
    Anthony
    Participant

    You can add the prefix if you want, but do you want it? Naturally you'd want your script to work the same no matter the environment so I would try to keep using the same cmdlets no matter what. At which point I would try to work in a check on the local machine where the session is being executed from and see if the local machine has the AD module available and if it does just do it locally but if it doesn't open a remote session to a machine that does have it available. Something like this:

    if ((Get-Module ActiveDirectory -ErrorAction silentlycontinue)) {
      Import-Module ActiveDirectory
      Get-ADUser Administrator
    }
    else {
      $session = New-PSSession -ComputerName DC -Credential (Get-Credential)
      Invoke-Command $session -Scriptblock { Import-Module ActiveDirectory }
      Import-PSSession -Session $session
      Get-ADUser Administrator
    }

    The thing I would try to avoid is if you use the replacement cmdlet you created (REMUser) for long enough you are going to get used to that cmdlet and probably forget what the original is at some point then scratch your head later on if it ever stops working. Because I could see that happening in my environment with some less PowerShell savvy individuals 😛

    • This reply was modified 4 months, 1 week ago by Profile photo of Anthony Anthony.
    • This reply was modified 4 months, 1 week ago by Profile photo of Anthony Anthony.
    • #48802
      Profile photo of Ronnie Jorgensen
      Ronnie Jorgensen
      Participant

      Hi Anthony,

      thank you for that, I guess you are correct. Will look into how i can pass credentials with AD commands just in case someone open a PS console locally that has the ActiveDirectory module. Obviously a non admin account cant do New-ADUser 😉

    • #48827
      Profile photo of Ronnie Jorgensen
      Ronnie Jorgensen
      Participant

      @Anthony, hoping you can help again.

      I tried to make your code above into a function in a module bur seems it is not working so great.

      function Connect-ARWActiveDirectory {
      
          [CmdLetBinding()]
          Param(
              [Parameter(
                  Mandatory=$true
              )]
              [string]$ConnectTo = "Server.FQDN"
          )
      
          if ((Get-Module ActiveDirectory -ErrorAction silentlycontinue)) {
              Import-Module ActiveDirectory -Global
          }
          else {
              $session = New-PSSession -ComputerName $ConnectTo -Credential (Get-Credential)
              Invoke-Command $session -Scriptblock { Import-Module ActiveDirectory }
              Import-PSSession $Session
          }
      
      }
      

      It gives error:
      Import-PSSession : Running the Get-Command command in a remote session reported the following error: Processing data
      for a remote command failed with the following error message: For more information, see the
      about_Remote_Troubleshooting Help topic..
      At C:\home\Posh\Modules\ArrowADTools\ArrowADTools.psm1:17 char:9
      + Import-PSSession $Session
      + ~~~~~~~~~~~~~~~~~~~~~~~~~
      + CategoryInfo : InvalidResult: (:) [Import-PSSession], RuntimeException
      + FullyQualifiedErrorId : ErrorFromRemoteCommand,Microsoft.PowerShell.Commands.ImportPSSessionCommand

    • #48855
      Profile photo of Anthony
      Anthony
      Participant

      Using your function it works for me in my lab...

      function Connect-ARWActiveDirectory {
      
          [CmdLetBinding()]
          Param(
              [Parameter(
                  Mandatory=$true
              )]
              [string]$ConnectTo = "DC"
          )
      
          if ((Get-Module ActiveDirectory -ErrorAction silentlycontinue)) {
              Write-Verbose -Message "Importing AD module" -Verbose
              Import-Module ActiveDirectory -Global
          }
          else {
              Write-Verbose -Message "No AD module found starting remote connection" -Verbose
              $session = New-PSSession -ComputerName $ConnectTo -Credential (Get-Credential)
              Invoke-Command $session -Scriptblock { Import-Module ActiveDirectory }
              Import-PSSession $Session
          }
      
      }
      

      It imports the remote session

      ModuleType Version    Name                                ExportedCommands                                                                                                                                                                                                                                          
      ---------- -------    ----                                ----------------                                                                                                                                                                                                                                          
      Script     1.0        tmp_0mj4z1lk.lfe                    {Add-ADCentralAccessPolicyMember, Add-ADComputerServiceAccount, Add-ADDomainControllerPasswordReplicationPolicy, Add-ADFineGrainedPasswordPolicySubject...}

      Get-ADUser returns the source as the imported session

      PS C:\Users\Administrator.HOME> get-command Get-ADUser
      
      CommandType     Name                                               Version    Source                                                                                                                                                                                                                                
      -----------     ----                                               -------    ------                                                                                                                                                                                                                                
      Function        Get-ADUser                                         1.0        tmp_llxkgus4.0lf

      The error to me doesn't look like it's a problem with the code but more so a problem with permissions remoting?

      Check what permissions are set for remote powershell sessions by doing this:

      PS C:\Windows\system32> Get-PSSessionConfiguration |fl 
      
      
      Name          : microsoft.powershell
      PSVersion     : 4.0
      StartupScript : 
      RunAsUser     : 
      Permission    : BUILTIN\Administrators AccessAllowed, BUILTIN\Remote 
                      Management Users AccessAllowed
      
      Name          : microsoft.powershell.workflow
      PSVersion     : 4.0
      StartupScript : 
      RunAsUser     : 
      Permission    : BUILTIN\Administrators AccessAllowed, BUILTIN\Remote 
                      Management Users AccessAllowed
      
      Name          : microsoft.powershell32
      PSVersion     : 4.0
      StartupScript : 
      RunAsUser     : 
      Permission    : BUILTIN\Administrators AccessAllowed, BUILTIN\Remote 
                      Management Users AccessAllowed
      
      Name          : microsoft.windows.servermanagerworkflows
      PSVersion     : 3.0
      StartupScript : 
      RunAsUser     : 
      Permission    : NT AUTHORITY\INTERACTIVE AccessAllowed, BUILTIN\Administrators 
                      AccessAllowed

      If the account you are using isn't in one of those groups you may need to give it permissions using

      Set-PSSessionConfiguration -Name Microsoft.PowerShell -showSecurityDescriptorUI
  • #48851
    Profile photo of Ronnie Jorgensen
    Ronnie Jorgensen
    Participant

    So tried something that was mentioned to me for the same for Exchange. but still does not seem to work

    $session = New-PSSession -ComputerName "FRVCBVDC003P.euecs.corp.arrow.com" -Credential (Get-Credential)
    Invoke-Command -session $session -ScriptBlock { Import-Module ActiveDirectory }
    Import-Module (Import-PSSession -session $session -Module ActiveDirectory -Prefix ARW -DisableNameChecking -AllowClobber) -Global

    Any ideas? the commands are not available after function stops

  • #48874
    Profile photo of Ronnie Jorgensen
    Ronnie Jorgensen
    Participant

    @Anthony – Are you running this from a custom module? I have a module "ArrowADTools.psm1" that is imported in my PowerShell profile. so if i run Connect-ARWActiveDirectory it will connect and run but once done running i have no access to Get-ADUser

    • #48887
      Profile photo of Anthony
      Anthony
      Participant

      It technically shouldn't matter if it's a function or a module in this particular case but either way to be sure I created it as a module in

      C:\Program Files\WindowsPowerShell\Modules\

      called ARWActiveDirectory

      PS C:\Users\Administrator.HOME> Get-Module
      
      ModuleType Version    Name                                ExportedCommands                                                                                                                                                                                                                                          
      ---------- -------    ----                                ----------------                                                                                                                                                                                                                                          
      Script     0.0        ARWActiveDirectory                  Connect-ARWActiveDirectory                                                                                                                                                                                                                                
      Script     1.0.0.0    ISE                                 {Get-IseSnippet, Import-IseSnippet, New-IseSnippet}                                                                                                                                                                                                       
      Manifest   3.1.0.0    Microsoft.PowerShell.Management     {Add-Computer, Add-Content, Checkpoint-Computer, Clear-Content...}                                                                                                                                                                                        
      Manifest   3.0.0.0    Microsoft.PowerShell.Security       {ConvertFrom-SecureString, ConvertTo-SecureString, Get-Acl, Get-AuthenticodeSignature...}                                                                                                                                                                 
      Manifest   3.1.0.0    Microsoft.PowerShell.Utility        {Add-Member, Add-Type, Clear-Variable, Compare-Object...} 

      The script module has the following contents

      function Connect-ARWActiveDirectory {
      
          [CmdLetBinding()]
          Param(
              [Parameter(
                  Mandatory=$true
              )]
              [string]$ConnectTo = "DC"
          )
      
          if ((Get-Module ActiveDirectory -ErrorAction silentlycontinue)) {
              Write-Verbose -Message "Importing AD module" -Verbose
              Import-Module ActiveDirectory -Global
          }
          else {
              Write-Verbose -Message "No AD module found starting remote connection" -Verbose
              $session = New-PSSession -ComputerName $ConnectTo -Credential (Get-Credential)
              Invoke-Command $session -Scriptblock { Import-Module ActiveDirectory }
              Import-PSSession $Session -Module ActiveDirectory
          }
      
      }
      

      Once I run Connect-ARWActiveDirectory I connected with both an admin user and a normal user given specific permissions as mentioned above and I get the following

      PS C:\Users\Administrator.HOME> Connect-ARWActiveDirectory
      cmdlet Connect-ARWActiveDirectory at command pipeline position 1
      Supply values for the following parameters:
      ConnectTo: DC
      VERBOSE: No AD module found starting remote connection
      cmdlet Get-Credential at command pipeline position 1
      Supply values for the following parameters:
      
      ModuleType Version    Name                                ExportedCommands                                                                                                                                                                                                                                          
      ---------- -------    ----                                ----------------                                                                                                                                                                                                                                          
      Script     1.0        tmp_3vd0hdc1.2za                    {Add-ADCentralAccessPolicyMember, Add-ADComputerServiceAccount, Add-ADDomainControllerPasswordReplicationPolicy, Add-ADFineGrainedPasswordPolicySubject...} 
      • This reply was modified 4 months, 1 week ago by Profile photo of Anthony Anthony.
  • #48895
    Profile photo of Ronnie Jorgensen
    Ronnie Jorgensen
    Participant

    @Anthony,

    Ok so my domain controllers had PS 2.0 so i updated to OS 5.0 and now it work. however i get some errors but not sure if thats because i already have AD module on local machine?

    Import-PSSession : Proxy creation has been skipped for the '%' command, because Windows PowerShell could not verify
    the safety of the command name.
    At C:\home\Posh\Modules\ArrowADTools\ArrowADTools.psm1:19 char:9
    + Import-PSSession $Session
    + ~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Import-PSSession], InvalidOperationException
    + FullyQualifiedErrorId : ErrorSkippedUnsafeCommandName,Microsoft.PowerShell.Commands.ImportPSSessionCommand

    and then this error:

    WARNING: Proxy creation has been skipped for the following command: 'ac, asnp, cat, cd, CFS, chdir, clc, clear, clhy,
    cli, clp, cls, clv, cnsn, compare, copy, cp, cpi, cpp, curl, cvpa, dbp, del, diff, dir, dnsn, ebp, echo, epal, epcsv,
    epsn, erase, etsn, exsn, fc, fhx, fl, foreach, ft, fw, gal, gbp, gc, gci, gcm, gcs, gdr, ghy, gi, gjb, gl, gm, gmo, gp,
    gps, gpv, group, gsn, gsnp, gsv, gu, gv, gwmi, h, history, icm, iex, ihy, ii, ipal, ipcsv, ipmo, ipsn, irm, ise, iwmi,
    iwr, kill, lp, ls, man, md, measure, mi, mount, move, mp, mv, nal, ndr, ni, nmo, npssc, nsn, nv, ogv, oh, popd, ps,
    pushd, pwd, r, rbp, rcjb, rcsn, rd, rdr, ren, ri, rjb, rm, rmdir, rmo, rni, rnp, rp, rsn, rsnp, rujb, rv, rvpa, rwmi,
    sajb, sal, saps, sasv, sbp, sc, select, set, shcm, si, sl, sleep, sls, sort, sp, spjb, spps, spsv, start, sujb, sv,
    swmi, tee, trcm, type, wget, where, wjb, write, A:, B:, C:, cd.., cd\, Clear-Host, ConvertFrom-SddlString, D:, E:, F:,
    Format-Hex, G:, Get-FileHash, Get-Verb, H:, help, I:, Import-PowerShellDataFile, ImportSystemModules, J:, K:, L:, M:,
    mkdir, more, N:, New-Guid, New-TemporaryFile, O:, oss, P:, Pause, prompt, Q:, R:, S:, T:, TabExpansion2, U:, V:, W:,
    X:, Y:, Z:, Add-History, Add-Member, Add-PSSnapin, Add-Type, Clear-History, Clear-Variable, Compare-Object,
    Connect-PSSession, ConvertFrom-Csv, ConvertFrom-Json, ConvertFrom-String, ConvertFrom-StringData, Convert-String,
    ConvertTo-Csv, ConvertTo-Html, ConvertTo-Json, ConvertTo-Xml, Debug-Job, Debug-Runspace, Disable-PSBreakpoint,
    Disable-PSRemoting, Disable-PSSessionConfiguration, Disable-RunspaceDebug, Disconnect-PSSession, Enable-PSBreakpoint,
    Enable-PSRemoting, Enable-PSSessionConfiguration, Enable-RunspaceDebug, Enter-PSHostProcess, Enter-PSSession,
    Exit-PSHostProcess, Export-Alias, Export-Clixml, Export-Console, Export-Csv, Export-FormatData, Export-ModuleMember,
    Export-PSSession, ForEach-Object, Format-Custom, Format-List, Format-Table, Format-Wide, Get-Alias, Get-Culture,
    Get-Date, Get-Event, Get-EventSubscriber, Get-History, Get-Host, Get-Job, Get-Member, Get-Module, Get-PSBreakpoint,
    Get-PSCallStack, Get-PSHostProcessInfo, Get-PSSession, Get-PSSessionCapability, Get-PSSessionConfiguration,
    Get-PSSnapin, Get-Random, Get-Runspace, Get-RunspaceDebug, Get-TraceSource, Get-TypeData, Get-UICulture, Get-Unique,
    Get-Variable, Group-Object, Import-Alias, Import-Clixml, Import-Csv, Import-LocalizedData, Import-Module,
    Import-PSSession, Invoke-Command, Invoke-Expression, Invoke-History, Invoke-RestMethod, Invoke-WebRequest,
    Measure-Command, New-Alias, New-Event, New-Module, New-ModuleManifest, New-Object, New-PSRoleCapabilityFile,
    New-PSSession, New-PSSessionConfigurationFile, New-PSSessionOption, New-PSTransportOption, New-TimeSpan, New-Variable,
    Out-File, Out-GridView, Out-Host, Out-Null, Out-Printer, Out-String, Read-Host, Receive-Job, Receive-PSSession,
    Register-ArgumentCompleter, Register-EngineEvent, Register-ObjectEvent, Register-PSSessionConfiguration, Remove-Event,
    Remove-Job, Remove-Module, Remove-PSBreakpoint, Remove-PSSession, Remove-PSSnapin, Remove-TypeData, Remove-Variable,
    Resume-Job, Save-Help, Select-String, Select-Xml, Send-MailMessage, Set-Alias, Set-Date, Set-PSBreakpoint, Set-PSDebug,
    Set-PSSessionConfiguration, Set-StrictMode, Set-TraceSource, Set-Variable, Show-Command, Sort-Object, Start-Job,
    Start-Sleep, Stop-Job, Suspend-Job, Tee-Object, Test-ModuleManifest, Test-PSSessionConfigurationFile, Trace-Command,
    Unblock-File, Unregister-Event, Unregister-PSSessionConfiguration, Update-FormatData, Update-Help, Update-List,
    Update-TypeData, Wait-Debugger, Wait-Event, Wait-Job, Where-Object, Write-Debug, Write-Error, Write-Host,
    Write-Information, Write-Output, Write-Progress, Write-Verbose, Write-Warning', because it would shadow an existing
    local command. Use the AllowClobber parameter if you want to shadow existing local commands.

    ModuleType Version Name ExportedCommands
    ———- ——- —- —————-
    Script 1.0 tmp_1iaye12n.tvb {Add-ADComputerServiceAccount, Add-ADDomainControllerPassw...

  • #48897
    Profile photo of Anthony
    Anthony
    Participant

    Just add -Module ActiveDirectory to the end of import-session. It's trying to import all the commands from the domain controller that are loaded by default which as you can see is a lot of pointless ones that you generally should have locally already anyway.

  • #48915
    Profile photo of Ronnie Jorgensen
    Ronnie Jorgensen
    Participant

    Hi anthony,

    Done that and it looks better, however it is still not working for me.. the commands are "gone"

    Windows PowerShell
    Copyright (C) 2016 Microsoft Corporation. All rights reserved.

    PS C:\home\Posh> Connect-ARWActiveDirectory
    VERBOSE: No AD module found starting remote connection

    cmdlet Get-Credential at command pipeline position 1
    Supply values for the following parameters:
    Credential
    VERBOSE: Invoke Command
    VERBOSE: Import pssession

    ModuleType Version Name ExportedCommands
    ———- ——- —- —————-
    Script 1.0 tmp_gcgle5oh.1g4 {Add-ADComputerServiceAccount, Add-ADDomainControllerPassw...

    PS C:\home\Posh> get-command Get-ADUser

    CommandType Name Version Source
    ———– —- ——- ——
    Cmdlet Get-ADUser 1.0.0.0 ActiveDirectory

    PS C:\home\Posh>

  • #48920
    Profile photo of Anthony
    Anthony
    Participant

    Cool, I could replicate that on my end... really odd looks like a scoping issue. Few changes and the below is working on my end

    function Connect-ARWActiveDirectory {
    
        [CmdLetBinding()]
        Param(
            [Parameter(
                Mandatory=$true
            )]
            [string]$ConnectTo = "DC"
        )
    
        if ((Get-Module ActiveDirectory -ErrorAction silentlycontinue)) {
            Write-Verbose -Message "Importing AD module" -Verbose
            Import-Module ActiveDirectory -Global
        }
        else {
            Write-Verbose -Message "No AD module found starting remote connection" -Verbose
            $session = New-PSSession -ComputerName $ConnectTo -Credential (Get-Credential)
            Import-Module -PSSession $session -Name ActiveDirectory -Global
        }
    }
    
    • #48988
      Profile photo of Ronnie Jorgensen
      Ronnie Jorgensen
      Participant

      Hi Anthony,

      Will be checking this out now but i want to quickly ask you something. In the line:
      if ((Get-Module ActiveDirectory -ErrorAction silentlycontinue)) {

      Should that not really be with the -ListAvailable ?? Get-Module ActiveDirectory is sort of already loaded and active?

      Also i have been thinking. if my goal is to have a consistent experience regardless of locally RSAT is installed or not. is it not just a matter of i skip that IF ELSE block and just connect to AD?

      Import-Module ActiveDirectory in the IF block is ok but lets say like on my normal laptop i just open PowerShell console as administrator but not run as my domain admin. i get the AD commands but i will have access denied if i tried new-aduser for example

    • #49032
      Profile photo of Anthony
      Anthony
      Participant

      Yep it should definitely be Get-Module ActiveDirectory -listavailable

      You can totally do it that way if you want, just connect directly to the machine that has the AD module installed regardless of weather or not RSAT is installed on the local machine. The thing is though realistically not everyone has permissions to create implicit remote connections to other machines but if you have it installed locally then it's not a big deal, it all comes down to what permissions you've been delegated in AD. At the end of the day no matter which way you go the result is the same.

      I can't really replicate your new problem at the moment. Any testing I'm doing is from a pretty clean lab as I have a bit of time off before I start a new job which means at the moment I don't have access to a corporate environment with the nuances that come with it.

  • #49019
    Profile photo of Ronnie Jorgensen
    Ronnie Jorgensen
    Participant

    Hmm not working from me, but could be because i am at home on client vpn

    Import-Module : Failed to generate proxies for remote module 'ActiveDirectory'. Could not find a part of the path 'C:\
    Users\a47941\AppData\Local\Temp\remoteIpMoProxy_ActiveDirectory_1.0.0.0_FRVCBVDC003Peuecscorparrowcom_d781a3aa-e538-467
    d-86f1-9e052a31165e\remoteIpMoProxy_ActiveDirectory_1.0.0.0_FRVCBVDC003Peuecscorparrowcom_d781a3aa-e538-467d-86f1-9e052
    a31165e.format.ps1xml'.
    At C:\home\Posh\Modules\ArrowADTools\ArrowADTools.psm1:43 char:9
    + Import-Module -PSSession $session -Name ActiveDirectory -Glob ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Import-Module], InvalidOperationException
    + FullyQualifiedErrorId : CmdletProviderInvocationException,Microsoft.PowerShell.Commands.ImportModuleCommand

You must be logged in to reply to this topic.