Last active
September 20, 2019 21:15
-
-
Save realslacker/1636af2aa9a7a992089b868dd06b5d3c to your computer and use it in GitHub Desktop.
Latest version available now on GitHub -> https://github.com/realslacker/PSmRemoteNG
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# Module manifest for module 'PSmRemoteNG' | |
# | |
# Generated by: Shannon Graybrook | |
# | |
# Generated on: 7/18/2019 | |
# | |
@{ | |
# Script module or binary module file associated with this manifest. | |
RootModule = 'PSmRemoteNG.psm1' | |
# Version number of this module. | |
ModuleVersion = '2019.7.18' | |
# Supported PSEditions | |
# CompatiblePSEditions = @() | |
# ID used to uniquely identify this module | |
GUID = '53ef1dab-cabf-4a1a-afb3-af155182c9c3' | |
# Author of this module | |
Author = 'Shannon Graybrook' | |
# Company or vendor of this module | |
CompanyName = 'Brooksworks' | |
# Copyright statement for this module | |
Copyright = 'Shannon Graybrook (c) 2019' | |
# Description of the functionality provided by this module | |
Description = 'A module to create mRemoteNG connection files from PowerShell.' | |
# Minimum version of the Windows PowerShell engine required by this module | |
# PowerShellVersion = '' | |
# Name of the Windows PowerShell host required by this module | |
# PowerShellHostName = '' | |
# Minimum version of the Windows PowerShell host required by this module | |
# PowerShellHostVersion = '' | |
# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. | |
# DotNetFrameworkVersion = '' | |
# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. | |
# CLRVersion = '' | |
# Processor architecture (None, X86, Amd64) required by this module | |
# ProcessorArchitecture = '' | |
# Modules that must be imported into the global environment prior to importing this module | |
# RequiredModules = @() | |
# Assemblies that must be loaded prior to importing this module | |
# RequiredAssemblies = @() | |
# Script files (.ps1) that are run in the caller's environment prior to importing this module. | |
# ScriptsToProcess = @() | |
# Type files (.ps1xml) to be loaded when importing this module | |
# TypesToProcess = @() | |
# Format files (.ps1xml) to be loaded when importing this module | |
# FormatsToProcess = @() | |
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess | |
# NestedModules = @() | |
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. | |
FunctionsToExport = @() | |
# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. | |
CmdletsToExport = @() | |
# Variables to export from this module | |
VariablesToExport = '*' | |
# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. | |
AliasesToExport = @() | |
# DSC resources to export from this module | |
# DscResourcesToExport = @() | |
# List of all modules packaged with this module | |
# ModuleList = @() | |
# List of all files packaged with this module | |
# FileList = @() | |
# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. | |
PrivateData = @{ | |
PSData = @{ | |
# Tags applied to this module. These help with module discovery in online galleries. | |
# Tags = @() | |
# A URL to the license for this module. | |
# LicenseUri = '' | |
# A URL to the main website for this project. | |
# ProjectUri = '' | |
# A URL to an icon representing this module. | |
# IconUri = '' | |
# ReleaseNotes of this module | |
# ReleaseNotes = '' | |
} # End of PSData hashtable | |
} # End of PrivateData hashtable | |
# HelpInfo URI of this module | |
# HelpInfoURI = '' | |
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. | |
# DefaultCommandPrefix = '' | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# find mRemoteNG install location | |
$mRNGDirectory = 'HKLM:\SOFTWARE\mRemoteNG', 'HKLM:\SOFTWARE\WOW6432Node\mRemoteNG' | | |
ForEach-Object { Get-ItemProperty -Path $_ -Name InstallDir -ErrorAction SilentlyContinue } | | |
Select-Object -First 1 -ExpandProperty InstallDir | |
# load assemblies | |
try { | |
[void][System.Reflection.Assembly]::LoadFile( "$mRNGDirectory\mRemoteNG.exe" ) | |
[void][System.Reflection.Assembly]::LoadFile( "$mRNGDirectory\BouncyCastle.Crypto.dll" ) | |
} catch { | |
throw $Messages.AssemblyLoadError | |
} | |
<# | |
.SYNOPSIS | |
Import an mRemoteNG root connections node from a confCons.xml file. | |
.PARAMETER EncryptionKey | |
The encryption key for the confCons.xml file. | |
.EXAMPLE | |
$RootNode = Import-MRNGRootNode -Path .\confCons.xml -EncryptionKey ( Read-Host 'Encryiption Key' -AsSecureString ) | |
#> | |
function Import-MRNGRootNode { | |
[OutputType([mRemoteNG.Tree.Root.RootNodeInfo])] | |
param( | |
[Parameter(Mandatory)] | |
[System.IO.FileInfo] | |
$Path, | |
[securestring] | |
$EncryptionKey = ( ConvertTo-SecureString -String 'mR3m' -AsPlainText -Force ) | |
) | |
# resolve the path | |
$Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath( $Path ) | |
# load the XML | |
$DataProvider = [mRemoteNG.Config.DataProviders.FileDataProvider]::new( $Path ) | |
$XmlString = $DataProvider.Load() | |
# create a function to return the password | |
# this is what mRemoteNG expects | |
[Func[mRemoteNG.Tools.Optional[securestring]]]$Auth = { $EncryptionKey } | |
# create a deserializer | |
$Deserializer = [mRemoteNG.Config.Serializers.Xml.XmlConnectionsDeserializer]::new($Auth) | |
# return the connections | |
( $Deserializer.Deserialize( $XmlString ) ).RootNodes.Item(0) | |
} | |
<# | |
.SYNOPSIS | |
Create an empty mRemoteNG root connections node. | |
.PARAMETER EncryptionKey | |
The encryption key to use for this connections file. | |
.EXAMPLE | |
$RootNode = New-MRNGRootNode | |
#> | |
function New-MRNGRootNode { | |
[OutputType([mRemoteNG.Tree.Root.RootNodeInfo])] | |
param( | |
[securestring] | |
$EncryptionKey = ( ConvertTo-SecureString -String 'mR3m' -AsPlainText -Force ) | |
) | |
# convert the encryption key to plaintext | |
$EncryptionKeyBSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR( $EncryptionKey ) | |
$EncryptionKeyText = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto( $EncryptionKeyBSTR ) | |
$RootNode = [mRemoteNG.Tree.Root.RootNodeInfo]::new('Connection') | |
# set a password? | |
if ( $EncryptionKeyText -ne $RootNode.DefaultPassword ) { | |
$RootNode.Password = $true | |
$RootNode.PasswordString = $EncryptionKeyText | |
} | |
$RootNode | |
} | |
<# | |
.SYNOPSIS | |
Create an mRemoteNG container node. | |
.EXAMPLE | |
New-MRNGContainer -Name 'Test Container' -Parent $RootNode -Protocol SSH2 | |
.EXAMPLE | |
$Container = New-MRNGContainer -Name 'Test Container' | |
$RootContainer.AddChild( $Container ) | |
$Container2 = New-MRNGContainer -Name 'Child Container' | |
$Container.AddChild( $Container2 ) | |
#> | |
function New-MRNGContainer { | |
[OutputType([mRemoteNG.Container.ContainerInfo])] | |
[CmdletBinding()] | |
param() | |
dynamicparam { | |
$DPDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary | |
$SkipParameters = 'Inheritance', 'ConstantID', 'IsContainer' | |
[mRemoteNG.Container.ContainerInfo].GetProperties() | | |
Where-Object { $SkipParameters -notcontains $_.Name } | | |
ForEach-Object { | |
$Attribute = New-Object System.Management.Automation.ParameterAttribute | |
$Attribute.ParameterSetName = '__AllParameterSets' | |
$Collection = New-Object System.Collections.ObjectModel.Collection[System.Attribute] | |
$Collection.Add($Attribute) | |
$Parameter = New-Object System.Management.Automation.RuntimeDefinedParameter( $_.Name, $_.PropertyType, $Collection ) | |
$DPDictionary.Add( $_.Name, $Parameter ) | |
} | |
$Attribute = New-Object System.Management.Automation.ParameterAttribute | |
$Attribute.ParameterSetName = '__AllParameterSets' | |
$Collection = New-Object System.Collections.ObjectModel.Collection[System.Attribute] | |
$Collection.Add($Attribute) | |
$Parameter = New-Object System.Management.Automation.RuntimeDefinedParameter( 'Inheritance', [hashtable], $Collection ) | |
$DPDictionary.Add( 'Inheritance', $Parameter ) | |
return $DPDictionary | |
} | |
process { | |
$ContainerInfo = [mRemoteNG.Container.ContainerInfo]::new() | |
# set default port | |
if ( $PSBoundParameters.Keys -contains 'Protocol' -and $PSBoundParameters.Keys -notcontains 'Port' ) { | |
$PSBoundParameters.Port = switch ( $PSBoundParameters.Protocol ) { | |
'RDP' { 3389 } | |
'VNC' { 5900 } | |
'SSH1' { 22 } | |
'SSH2' { 22 } | |
'Telnet' { 23 } | |
'Rlogin' { 513 } | |
'RAW' { 23 } | |
'HTTP' { 80 } | |
'HTTPS' { 443 } | |
'IntApp' { 0 } | |
} | |
} | |
# set connection properties | |
$PSBoundParameters.Keys | | |
Where-Object { $_ -notmatch 'Parent|Children|Inheritance' } | | |
Where-Object { [mRemoteNG.Container.ContainerInfo].GetProperties().Name -contains $_ } | | |
ForEach-Object { $ContainerInfo.$_ = $PSBoundParameters.$_ } | |
# configure inheritance | |
if ( $PSBoundParameters.Keys -contains 'Inheritance' ) { | |
# process EverythingInherited first | |
if ( $PSBoundParameters.Inheritance.Keys -contains 'EverythingInherited' ) { | |
$ContainerInfo.Inheritance.EverythingInherited = $true | |
} | |
# process all other inheritence | |
$PSBoundParameters.Inheritance.Keys | | |
Where-Object { $_ -ne 'EverythingInherited' } | | |
ForEach-Object { | |
$ContainerInfo.Inheritance.$_ = $PSBoundParameters.Inheritance.$_ | |
} | |
} | |
# if children is specified we append | |
if ( $PSBoundParameters.Keys -contains 'Children' ) { | |
$PSBoundParameters.Children | | |
ForEach-Object { | |
$ContainerInfo.AddChild($_) | |
Write-Verbose ( 'Child ''{0}'' added to ''{1}''.' -f $_.Name, $ContainerInfo.Name ) | |
} | |
} | |
# if parent is specified we append, otherwise we output | |
if ( $PSBoundParameters.Keys -contains 'Parent' ) { | |
$PSBoundParameters.Parent.AddChild( $ContainerInfo ) | |
Write-Verbose ( 'Container ''{0}'' added to ''{1}''.' -f $ContainerInfo.Name, $PSBoundParameters.Parent.Name ) | |
} | |
$ContainerInfo | |
} | |
} | |
<# | |
.SYNOPSIS | |
Create an mRemoteNG connection node. | |
.EXAMPLE | |
New-MRNGConnection -Name 'Test Connection' -HostName '127.0.0.1' -Parent $RootNode -Protocol SSH2 -Inheritance (New-MRNGInheritanceConfiguration -EverythingInherited -Protocol:$false) | |
.EXAMPLE | |
$Connection = New-MRNGConnection -Name 'Test Connection' -HostName '127.0.0.1' | |
$RootContainer.AddChild( $Connection ) | |
#> | |
function New-MRNGConnection { | |
[OutputType([mRemoteNG.Connection.ConnectionInfo])] | |
[CmdletBinding()] | |
param() | |
dynamicparam { | |
$DPDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary | |
$SkipParameters = 'Inheritance', 'ConstantID', 'IsContainer' | |
[mRemoteNG.Connection.ConnectionInfo].GetProperties() | | |
Where-Object { $SkipParameters -notcontains $_.Name } | | |
ForEach-Object { | |
$Attribute = New-Object System.Management.Automation.ParameterAttribute | |
$Attribute.ParameterSetName = '__AllParameterSets' | |
$Collection = New-Object System.Collections.ObjectModel.Collection[System.Attribute] | |
$Collection.Add($Attribute) | |
$Parameter = New-Object System.Management.Automation.RuntimeDefinedParameter( $_.Name, $_.PropertyType, $Collection ) | |
$DPDictionary.Add( $_.Name, $Parameter ) | |
} | |
$Attribute = New-Object System.Management.Automation.ParameterAttribute | |
$Attribute.ParameterSetName = '__AllParameterSets' | |
$Collection = New-Object System.Collections.ObjectModel.Collection[System.Attribute] | |
$Collection.Add($Attribute) | |
$Parameter = New-Object System.Management.Automation.RuntimeDefinedParameter( 'Inheritance', [hashtable], $Collection ) | |
$DPDictionary.Add( 'Inheritance', $Parameter ) | |
return $DPDictionary | |
} | |
process { | |
$ConnectionInfo = [mRemoteNG.Connection.ConnectionInfo]::new() | |
# set default port | |
if ( $PSBoundParameters.Keys -contains 'Protocol' -and $PSBoundParameters.Keys -notcontains 'Port' ) { | |
$PSBoundParameters.Port = switch ( $PSBoundParameters.Protocol ) { | |
'RDP' { 3389 } | |
'VNC' { 5900 } | |
'SSH1' { 22 } | |
'SSH2' { 22 } | |
'Telnet' { 23 } | |
'Rlogin' { 513 } | |
'RAW' { 23 } | |
'HTTP' { 80 } | |
'HTTPS' { 443 } | |
'IntApp' { 0 } | |
} | |
} | |
# set connection properties | |
$PSBoundParameters.Keys | | |
Where-Object { $_ -notmatch 'Parent|Inheritance' } | | |
Where-Object { [mRemoteNG.Connection.ConnectionInfo].GetProperties().Name -contains $_ } | | |
ForEach-Object { $ConnectionInfo.$_ = $PSBoundParameters.$_ } | |
# configure inheritance | |
if ( $PSBoundParameters.Keys -contains 'Inheritance' ) { | |
# process EverythingInherited first | |
if ( $PSBoundParameters.Inheritance.Keys -contains 'EverythingInherited' ) { | |
$ConnectionInfo.Inheritance.EverythingInherited = $true | |
} | |
# process all other inheritence | |
$PSBoundParameters.Inheritance.Keys | | |
Where-Object { $_ -ne 'EverythingInherited' } | | |
ForEach-Object { | |
$ConnectionInfo.Inheritance.$_ = $PSBoundParameters.Inheritance.$_ | |
} | |
} | |
# if parent is specified we append, otherwise we output | |
if ( $PSBoundParameters.Keys -contains 'Parent' ) { | |
$PSBoundParameters.Parent.AddChild( $ConnectionInfo ) | |
Write-Verbose ( 'Connection ''{0}'' added to ''{1}''.' -f $ConnectionInfo.Name, $PSBoundParameters.Parent.Name ) | |
} | |
$ConnectionInfo | |
} | |
} | |
<# | |
.SYNOPSIS | |
Helper function to build an inheritance configuration. | |
.EXAMPLE | |
New-MRNGInheritanceConfiguration -EverythingInherited -Icon:$false | |
# inherits everything except the icon | |
#> | |
function New-MRNGInheritanceConfiguration { | |
[OutputType([hashtable])] | |
[CmdletBinding()] | |
param() | |
dynamicparam { | |
$DPDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary | |
[mRemoteNG.Connection.ConnectionInfoInheritance].GetProperties() | | |
Where-Object { $_.Name -ne 'Parent' } | | |
ForEach-Object { | |
$Attribute = New-Object System.Management.Automation.ParameterAttribute | |
$Attribute.ParameterSetName = '__AllParameterSets' | |
$Collection = New-Object System.Collections.ObjectModel.Collection[System.Attribute] | |
$Collection.Add($Attribute) | |
$Parameter = New-Object System.Management.Automation.RuntimeDefinedParameter( $_.Name, [switch], $Collection ) | |
$DPDictionary.Add( $_.Name, $Parameter ) | |
} | |
return $DPDictionary | |
} | |
process { | |
$ReturnHashtable = @{} | |
$PSBoundParameters.Keys | | |
Where-Object { [mRemoteNG.Connection.ConnectionInfoInheritance].GetProperties().Name -contains $_ } | | |
ForEach-Object { $ReturnHashtable.$_ = $PSBoundParameters.$_ } | |
$ReturnHashtable | |
} | |
} | |
<# | |
.SYNOPSIS | |
Exports the mRemoteNG connection file with the encryption parameters specified. | |
.PARAMETER RootNode | |
The mRemoteNG root connections node generated by New-MRNGRootNode. | |
.PARAMETER Path | |
The path to export the connection file to. | |
.PARAMETER EncryptionKey | |
The encryption key to use to secure the connections file. If no password is supplied the default mRemoteNG encryption key is "mR3m". | |
.PARAMETER EncryptionEngine | |
The encryption engine to use when encrypting the connection passwords. Choices are 'AES', 'Serpent', and 'Twofish'. The default is 'AES'. | |
.PARAMETER BlockCipherMode | |
The block cipher mode to use when encrypting the connection passwords. Choices are 'GCM', 'CCM', and 'EAX'. The default is 'GCM'. | |
.PARAMETER KeyDerivationIterations | |
The number of key derivation iterations to perform when encrypting the connection passwords. Valid values are in the range 1,000 to 50,000. | |
.PARAMETER SortConnections | |
Should the exported connections be sorted? | |
.EXAMPLE | |
Export-MRNGConnectionFile -RootNode $RootNode -Path .\Connections.xml (Get-Credential).Password -SortConnections | |
#> | |
function Export-MRNGConnectionFile { | |
param( | |
[Parameter(Mandatory)] | |
[mRemoteNG.Tree.Root.RootNodeInfo] | |
$RootNode, | |
[Parameter(Mandatory)] | |
[System.IO.FileInfo] | |
$Path, | |
[ValidateSet('AES', 'Serpent', 'Twofish')] | |
[string] | |
$EncryptionEngine = 'AES', | |
[ValidateSet('GCM', 'CCM', 'EAX')] | |
[string] | |
$BlockCipherMode = 'GCM', | |
[ValidateRange(1000, 50000)] | |
[int] | |
$KeyDerivationIterations = 1000, | |
[switch] | |
$SortConnections | |
) | |
# resolve the path | |
$Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath( $Path ) | |
# get the encryption key as [securestring] | |
if ( $RootNode.Password ) { | |
$EncryptionKey = $RootNode.PasswordString | | |
ConvertTo-SecureString -AsPlainText -Force | |
} else { | |
$EncryptionKey = $RootNode.DefaultPassword | | |
ConvertTo-SecureString -AsPlainText -Force | |
} | |
# choose the encryption engine | |
$Engine = switch ( $EncryptionEngine ) { | |
'AES' { [Org.BouncyCastle.Crypto.Engines.AesEngine]::new() } | |
'Serpent' { [Org.BouncyCastle.Crypto.Engines.SerpentEngine]::new() } | |
'Twofish' { [Org.BouncyCastle.Crypto.Engines.TwofishEngine]::new() } | |
} | |
# choose the cipher mode | |
$Cipher = switch ( $BlockCipherMode ) { | |
'GCM' { [Org.BouncyCastle.Crypto.Modes.GcmBlockCipher]::new( $Engine ) } | |
'CCM' { [Org.BouncyCastle.Crypto.Modes.CcmBlockCipher]::new( $Engine ) } | |
'EAX' { [Org.BouncyCastle.Crypto.Modes.EaxBlockCipher]::new( $Engine ) } | |
} | |
# XML serializer | |
$CryptoProvider = [mRemoteNG.Security.SymmetricEncryption.AeadCryptographyProvider]::new( $Cipher ) | |
$SaveFilter = [mRemoteNG.Security.SaveFilter]::new() | |
$ConnectionNodeSerializer = [mRemoteNG.Config.Serializers.Xml.XmlConnectionNodeSerializer26]::new($CryptoProvider, $EncryptionKey, $SaveFilter) | |
$XmlSerializer = [mRemoteNG.Config.Serializers.Xml.XmlConnectionsSerializer]::new($CryptoProvider, $ConnectionNodeSerializer) | |
# should we sort? | |
if ( $SortConnections ) { | |
$RootNode.SortRecursive() | |
} | |
# save the connection file | |
$FilePathProvider = [mRemoteNG.Config.DataProviders.FileDataProvider]::new( $Path ) | |
$FilePathProvider.Save( $XmlSerializer.Serialize( $RootNode ) ) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='High')] | |
param( | |
[string] | |
$ExportPath = "$env:APPDATA\mRemoteNG\PSmRemoteNG.xml", | |
[securestring] | |
$EncryptionKey = ( ConvertTo-SecureString -String 'mR3m' -AsPlainText -Force ), | |
[hashtable] | |
$CredentialMap = @{} | |
) | |
$ErrorActionPreference = 'Stop' | |
if ( $CredentialMap.Keys.Count -and ( [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($EncryptionKey)) -eq 'mR3m' ) ) { | |
throw 'You must supply an encryption key when storing credentials.' | |
} | |
#requires -modules PSmRemoteNG | |
Write-Host 'Generating config file...' -ForegroundColor White | |
# create the root node with the specified EncryptionKey | |
# note that you must ALWAYS supply an EncryptionKey, even | |
# if using the default value 'mR3m' or the config won't open | |
# in mRemoteNG. Supplying the default value with bypass the | |
# prompt. | |
$RootNode = New-MRNGRootNode -EncryptionKey $EncryptionKey | |
Write-Host 'Searching for AD Forests that your domain trusts...' -ForegroundColor White | |
# all forests container variable | |
$Forests = @() | |
# add your forest | |
$Forests += @(, (Get-ADForest).Name ) | |
# get all AD Forests that your domain trusts | |
$Forests += Get-ADTrust -Filter * | | |
Where-Object { $_.ForestTransitive -eq $true } | | |
Select-Object -ExpandProperty Target | | |
Sort-Object | |
foreach ( $Forest in $Forests ) { | |
# will hold inheritance for containers if defined | |
$InheritanceSplat = @{} | |
# find all domains in the forest | |
try { | |
$Domains = Get-ADForest -Server $Forest | | |
Select-Object -ExpandProperty Domains | |
} catch { | |
if ( ( Read-Host ( 'Could not contact forest ''{0}'', continue? [y/N]' -f $Forest ) ) -match '^y' ) { | |
continue | |
} else { | |
throw 'Cancelled' | |
} | |
} | |
# if the forest has more than one domain we make a forest container | |
if ( $Domains.Count -gt 1 ) { | |
Write-Host ( 'Create forest container: {0}' -f $Forest ) -ForegroundColor Cyan | |
$ForestContainer = New-MRNGContainer -Name $Forest -Parent $RootNode | |
# if the $CredentialMap has a key matching the forest | |
# we set the credential on the container and turn on | |
# inheritance | |
if ( $CredentialMap.Keys -contains $Forest ) { | |
$ForestContainer.Username = $CredentialMap[$Forest].GetNetworkCredential().Username | |
$ForestContainer.Domain = $CredentialMap[$Forest].GetNetworkCredential().Domain | |
$ForestContainer.Password = $CredentialMap[$Forest].GetNetworkCredential().Password | |
$InheritanceSplat.Inheritance = New-MRNGInheritanceConfiguration -EverythingInherited | |
} | |
# otherwise we just use the root node | |
} else { | |
$ForestContainer = $RootNode | |
} | |
# now we process the domains | |
foreach ( $Domain in $Domains ) { | |
Write-Host ( 'Searching for servers in {0}...' -f $Domain ) -ForegroundColor White | |
# find the domain controller | |
$DomainController = Get-ADDomainController -DomainName $Domain -Discover -Service ADWS | | |
Select-Object -ExpandProperty HostName | |
# look for servers in the domain | |
$Servers = Get-ADComputer -Filter 'OperatingSystem -like "*Windows Server*"' -Server $DomainController -Properties OperatingSystem, Description, IPv4Address, DNSHostName, Enabled | | |
Select-Object @{N='Name';E={ $_.Name + (' (disabled)','')[$_.Enabled] }}, | |
@{N='HostName';E={ $_.DNSHostName }}, | |
@{N='Description';E={ ( $_.Description, $_.OperatingSystem )[ [string]::IsNullOrEmpty($_.Description) ] }} | |
if ( $Servers.Count -eq 0 ) { | |
Write-Host 'No servers found, skipping...' -ForegroundColor Gray | |
continue | |
} | |
Write-Host ( 'Create domain container: {0}' -f $Domain ) -ForegroundColor DarkCyan | |
$DomainContainer = New-MRNGContainer -Name $Domain -Parent $ForestContainer @InheritanceSplat | |
if ( $CredentialMap.Keys -contains $Domain ) { | |
$DomainContainer.Username = $CredentialMap[$Domain].GetNetworkCredential().Username | |
$DomainContainer.Domain = $CredentialMap[$Domain].GetNetworkCredential().Domain | |
$DomainContainer.Password = $CredentialMap[$Domain].GetNetworkCredential().Password | |
$InheritanceSplat.Inheritance = New-MRNGInheritanceConfiguration -EverythingInherited | |
} | |
Write-Host ( 'Creating {0} servers connections...' -f $Servers.Count ) -ForegroundColor DarkGray | |
foreach ( $Server in $Servers ) { | |
$ServerInheritanceSplat = @{} | |
Write-Host ( 'Create server connection: {0}' -f $Server.Name ) -ForegroundColor Gray | |
if ( -not [string]::IsNullOrEmpty( $Server.Description ) -and $InheritanceSplat.Inheritance ) { | |
$ServerInheritanceSplat = $InheritanceSplat.Clone() | |
$ServerInheritanceSplat.Inheritance.Description = $false | |
} | |
$ServerConnection = New-MRNGConnection -Name $Server.Name -Hostname $Server.HostName -Description $Server.Description -Parent $DomainContainer @ServerInheritanceSplat | |
} | |
} | |
} | |
Write-Host '' | |
if ( -not( Test-Path -Path $ExportPath -PathType Leaf ) -or $PSCmdlet.ShouldProcess( $ExportPath, 'Replace Configuration' ) ) { | |
Export-MRNGConnectionFile -RootNode $RootNode -Path $ExportPath -SortConnections | |
Write-Host 'New configuration file path:' -ForegroundColor White | |
Write-Host $ExportPath -ForegroundColor White | |
} else { | |
Write-Host 'Cancelled' -ForegroundColor Red | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment