Pws.psm1
#Region './_PrefixCode.ps1' 0 # Code in here will be prepended to top of the psm1-file. # Set Module Registry Path $Global:PwsRegistryPath = 'HKLM:\SOFTWARE\Partitio\Pws' # In Powershell v6+ $IsMacOS, $IsLinux, $IsWindows are defined # Since the module is for Windows, and powershell may be older, # these variables wont be defined, so we cannot use $IsWindows as # it would failed if (!$IsMacOS -and !$IsLinux) { if ( !(Test-Path $Global:PwsRegistryPath)) { New-Item $Global:PwsRegistryPath -Force|Out-Null } } #EndRegion './_PrefixCode.ps1' 13 #Region './Classes/ADUser.ps1' 0 class ADUser { } #EndRegion './Classes/ADUser.ps1' 4 #Region './Private/Compare-CertificateIssuer.ps1' 0 <# .SYNOPSIS Checks if the Certificate Issuer matches the CA Root Name. .PARAMETER Issuer The Certificate Issuer. .PARAMETER CARootName The CA Root Name to compare with the Certificate Issuer. #> function Compare-CertificateIssuer { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $Issuer, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $CARootName ) return ((Get-CertificateCommonName -DistinguishedName $Issuer) -eq $CARootName) } #EndRegion './Private/Compare-CertificateIssuer.ps1' 27 #Region './Private/DscADCSConfiguration.ps1' 0 Configuration DscADCSConfiguration { param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $DataPath, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $LogPath, [Parameter(Mandatory = $true)] [ValidateNotNullorEmpty()] [System.Management.Automation.PSCredential] $Credential ) Import-DscResource -Module ActiveDirectoryCSDsc Node localhost { WindowsFeature ADCS-Cert-Authority { Ensure = 'Present' Name = 'ADCS-Cert-Authority' } WindowsFeature ADCS-Web-Enrollment { Ensure = 'Present' Name = 'ADCS-Web-Enrollment' } AdcsCertificationAuthority CertificateAuthority { IsSingleInstance = 'Yes' Ensure = 'Present' Credential = $Credential CAType = 'EnterpriseRootCA' ValidityPeriod = "Years" ValidityPeriodUnits = 99 DatabaseDirectory = $DataPath LogDirectory = $LogPath DependsOn = '[WindowsFeature]ADCS-Cert-Authority' } AdcsWebEnrollment WebEnrollment { Ensure = 'Present' IsSingleInstance = 'Yes' Credential = $Credential DependsOn = '[WindowsFeature]ADCS-Web-Enrollment' } } } #EndRegion './Private/DscADCSConfiguration.ps1' 59 #Region './Private/DscADDCConfiguration.ps1' 0 Configuration DscADDCConfiguration { param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Domain, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $DatabasePath, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $LogPath, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $SysvolPath, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.Management.Automation.PSCredential] $Credential, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.Management.Automation.PSCredential] $SafeModePassword ) Import-DscResource -ModuleName PSDscResources Import-DscResource -ModuleName ActiveDirectoryDsc node 'localhost' { WindowsFeature 'ADDS' { Name = 'AD-Domain-Services' Ensure = 'Present' } WindowsFeature 'RSAT' { Name = 'RSAT-AD-PowerShell' Ensure = 'Present' } ADDomain $Domain { DomainName = $Domain Credential = $Credential SafemodeAdministratorPassword = $SafeModePassword ForestMode = 'WinThreshold' DatabasePath = $DatabasePath SysvolPath = $SysvolPath LogPath = $LogPath } } } #EndRegion './Private/DscADDCConfiguration.ps1' 64 #Region './Private/DscADStructureConfiguration.ps1' 0 Configuration DscADStructureConfiguration { $RootPath = (Get-ADDomain).DistinguishedName $RootName = ((Get-Culture).TextInfo).ToTitleCase($env:userdomain.ToLower()) $RootOU = "OU=$RootName,$RootPath" $OUs = @("Computers", "Servers", "Groups", "Users") Import-DscResource -Module ActiveDirectoryDsc Node localhost { # TODO : Wait For AD Domain # WaitForADDomain ADOrganizationalUnit RootOU { Name = $RootName Path = $RootPath Description = "$RootName root Organization Unit" Ensure = "Present" } WaitForAll RootOU { NodeName = "localhost" ResourceName = "[ADOrganizationalUnit]RootOU" } foreach ($OU in $OUs) { $ResourceName = $OU + "OU" ADOrganizationalUnit $ResourceName { Name = $OU Path = $RootOU Description = "Root Organization Unit for $OU" Ensure = "Present" } } ADGroup RDSUsersGroup { GroupName = 'RDS-Users' GroupScope = 'Universal' Category = 'Security' Ensure = 'Present' } } } #EndRegion './Private/DscADStructureConfiguration.ps1' 51 #Region './Private/DscComputerConfiguration.ps1' 0 Configuration DscComputerConfiguration { param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $ComputerName, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $IP, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Gateway, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $DnsServer ) Import-DscResource -Module ComputerManagementDsc Import-DscResource -Module NetworkingDsc Import-DscResource -Module PSDesiredStateConfiguration Node localhost { Computer RenameComputer { Name = $ComputerName } IPAddress IPv4Address { IPAddress = "$IP/24" InterfaceAlias = 'Ethernet0' AddressFamily = 'IPV4' KeepExistingAddress = $true } DefaultGatewayAddress DefaultGateway { Address = $Gateway InterfaceAlias = 'Ethernet0' AddressFamily = 'IPv4' } DnsServerAddress DnsServerAddress { Address = $DnsServer InterfaceAlias = 'Ethernet0' AddressFamily = 'IPv4' Validate = $true } } } #EndRegion './Private/DscComputerConfiguration.ps1' 59 #Region './Private/DscDomainController.ps1' 0 Configuration DscDomainController { param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Domain, [Parameter(Mandatory = $true)] [ValidateNotNullorEmpty()] [String] $DomainControllerIP, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [String] $DatabasePath, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [String] $LogPath, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [String] $SysvolPath, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.Management.Automation.PSCredential] $Credential, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.Management.Automation.PSCredential] $SafeModePassword ) Import-DscResource -ModuleName PSDscResources Import-DscResource -ModuleName ActiveDirectoryDsc Import-DscResource -Module NetworkingDsc Node localhost { DnsServerAddress DnsServerAddress { Address = $DomainControllerIP InterfaceAlias = 'Ethernet0' AddressFamily = 'IPv4' Validate = $true } WindowsFeature 'InstallADDomainServicesFeature' { Ensure = 'Present' Name = 'AD-Domain-Services' DependsOn = '[DnsServerAddress]DnsServerAddress' } WindowsFeature 'RSATADPowerShell' { Ensure = 'Present' Name = 'RSAT-AD-PowerShell' DependsOn = '[WindowsFeature]InstallADDomainServicesFeature' } WaitForADDomain 'WaitForestAvailability' { DomainName = $Domain Credential = $Credential DependsOn = '[WindowsFeature]RSATADPowerShell' } ADDomainController 'DomainController' { DomainName = $Domain Credential = $Credential SafeModeAdministratorPassword = $SafeModePassword DatabasePath = $DatabasePath SysvolPath = $SysvolPath LogPath = $LogPath DependsOn = '[WaitForADDomain]WaitForestAvailability' } } } #EndRegion './Private/DscDomainController.ps1' 87 #Region './Private/DscDomainJoinConfiguration.ps1' 0 Configuration DscDomainJoinConfiguration { param ( [Parameter(Mandatory = $true)] [ValidateNotNullorEmpty()] [String] $ComputerName, [Parameter(Mandatory = $true)] [ValidateNotNullorEmpty()] [String] $OrganizationUnit, [Parameter(Mandatory = $true)] [ValidateNotNullorEmpty()] [String] $DomainControllerIP, [Parameter(Mandatory = $false)] [String] $Description, [Parameter(Mandatory = $true)] [ValidateNotNullorEmpty()] [System.Management.Automation.PSCredential] $Credential ) $Domain = Get-DomainFromDN $OrganizationUnit Import-DscResource -Module NetworkingDsc Import-DscResource -Module ComputerManagementDsc Import-DscResource -Module PSDesiredStateConfiguration Node localhost { DnsServerAddress DnsServerAddress { Address = $DomainControllerIP, "8.8.8.8" InterfaceAlias = 'Ethernet0' AddressFamily = 'IPv4' } WaitForAll DnsServerAddress { NodeName = "localhost" ResourceName = "[DnsServerAddress]DnsServerAddress" } Computer JoinDomain { Name = $ComputerName JoinOU = $OrganizationUnit DomainName = $Domain Description = $Description Credential = $Credential DependsOn = "[WaitForAll]DnsServerAddress" } } } #EndRegion './Private/DscDomainJoinConfiguration.ps1' 59 #Region './Private/DscICMPConfiguration.ps1' 0 Configuration DscICMPConfiguration { param ( [Parameter(Mandatory = $false)] [Switch] $Disable ) if ($Disable) { $Action = "Block" } else { $Action = "Allow" } Import-DSCResource -ModuleName NetworkingDsc Node localhost { Firewall EnableICMPv4 { Name = 'ICMPv4' DisplayName = 'Allow inbound ICMPv4' Ensure = 'Present' Enabled = 'True' Action = $Action Profile = ('Domain', 'Private') Direction = 'Inbound' Protocol = 'ICMPv4' IcmpType = ('8') } Firewall EnableICMPv6 { Name = 'ICMPv6' DisplayName = 'Allow inbound ICMPv6' Ensure = 'Present' Enabled = 'True' Action = $Action Profile = ('Domain', 'Private') Direction = 'Inbound' Protocol = 'ICMPv6' IcmpType = ('8') } } } #EndRegion './Private/DscICMPConfiguration.ps1' 47 #Region './Private/DscInitializeDataDisks.ps1' 0 Configuration DscInitializeDataDisks { Import-DSCResource -ModuleName StorageDsc Node 'localhost' { $Count = 0 $Letters = 67..90 | % { "$( [char]$_ ):" }|Where-Object { !(Test-Path $_) } | %{ $_[0] } if (!$Letters) { return } foreach ($Disk in (Get-Disk | Where-Object { $_.OperationalStatus -eq "Offline" })) { $DiskNumber = $Disk.Number $DiskName = "Disk" + $DiskNumber $Letter = $Letters[$Count] WaitForDisk $DiskName { DiskId = $Disk.Number RetryIntervalSec = 60 RetryCount = 60 } Disk $DiskName { DiskId = $Disk.Number DriveLetter = $Letter FSFormat = 'NTFS' FSLabel = "Data$DiskNumber" PartitionStyle = "MBR" DependsOn = "[WaitForDisk]$DiskName" } $Count++ } } } #EndRegion './Private/DscInitializeDataDisks.ps1' 37 #Region './Private/DscMountSmbShareConfiguration.ps1' 0 Configuration DscMountSmbShareConfiguration { param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $DriveLetter, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $NetworkDriveRoot ) Import-DscResource -ModuleName PSDesiredStateConfiguration Node localhost { Script MountSmbShare { GetScript = { @{ Result = (Get-PSDrive | Where-Object { $_.Name -eq $using:DriveLetter -and $_.DisplayRoot -eq $using:NetworkDriveRoot }) } } SetScript = { if (Get-PSDrive | Where-Object { $_.Name -eq $using:DriveLetter}) { Write-Error "A Drive named $using:DriveLetter already exists" exit 1 } if (Get-PSDrive | Where-Object { $_.DisplayRoot -eq $using:NetworkDriveRoot}) { Write-Warning "A Drive with Root $using:NetworkDriveRoot already exists" } New-PSDrive -Name $using:DriveLetter -PSProvider FileSystem -Root $NetworkDriveRoot -Persist -Scope 'Global' } TestScript = { return (Get-PSDrive | Where-Object { $_.Name -eq $using:DriveLetter -and $_.DisplayRoot -eq $using:NetworkDriveRoot }) -ne $null } } } } #EndRegion './Private/DscMountSmbShareConfiguration.ps1' 47 #Region './Private/DscRDSCertificateConfiguration.ps1' 0 Configuration DscRDSCertificateConfiguration { param ( [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [String] $GatewayAddress, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $CAServerFQDN, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [PSCredential] $Credential ) Import-DscResource -ModuleName CertificateDsc Import-DscResource -ModuleName PSDesiredStateConfiguration Import-Module RemoteDesktop $CARootName = Get-CARootName $CAServerFQDN $FQDN = [System.Net.Dns]::GetHostByName($env:computerName).Hostname Node localhost { CertReq RDSGatewayCert { CARootName = $CARootName CAServerFQDN = $CAServerFQDN Subject = $GatewayAddress AutoRenew = $true FriendlyName = 'SSL Cert for RDS Gateway' Credential = $Credential } CertReq RDSCert { CARootName = $CARootName CAServerFQDN = $CAServerFQDN Subject = $FQDN AutoRenew = $true FriendlyName = 'SSL Cert for RDS' Credential = $Credential } WaitForAll RDSGatewayCert { NodeName = 'localhost' ResourceName = '[CertReq]RDSGatewayCert' RetryIntervalSec = 15 RetryCount = 50 } WaitForAll RDSCert { NodeName = 'localhost' ResourceName = '[CertReq]RDSCert' RetryIntervalSec = 15 RetryCount = 50 } # TODO : Spit to parallelize certs registration Script InstallRDSCerts { GetScript = { return @{ Result = Get-RDCertificate } } SetScript = { $publicCert = Get-Childitem -Path Cert:\LocalMachine\My | Where-Object -FilterScript { $_.Subject -eq "CN=$using:GatewayAddress" -and (Compare-CertificateIssuer -Issuer $_.Issuer -CARootName $using:CARootName) } if(!$publicCert) { Write-Error "Cert for $($using:GatewayAddress) not found" exit 1 } Write-Verbose "Using Cert: $($GatewayAddress) $($publicCert.Thumbprint)" $localCert = Get-Childitem -Path Cert:\LocalMachine\My | Where-Object -FilterScript { $_.Subject -eq "CN=$using:FQDN" -and (Compare-CertificateIssuer -Issuer $_.Issuer -CARootName $using:CARootName) } if(!$publicCert) { Write-Error "Cert for $($using:FQDN) not found" exit 1 } Write-Verbose "Using Cert: $($using:FQDN) $($localCert.Thumbprint)" foreach ($s in Get-RDCertificate) { Write-Verbose "$($s.Role) Status: $($s.Level)" if($s.Level -ne "NotConfigured") { continue } if($s.Role -eq 'RDWebAccess' -or $s.Role -eq 'RDGateway') { $cert = $publicCert } else { $cert = $localCert } $RDCertParams = @{ Role = $s.Role ConnectionBroker = $using:FQDN Thumbprint = $cert.Thumbprint Force = $true ErrorAction = 'Stop' } try { Write-Verbose "Installing $($s.Role) Certificate" Set-RDCertificate @RDCertParams } catch { Write-Error $_.Exception.Message } } } TestScript = { try { $res = $true $certs = Get-RDCertificate if (!$certs) { return $false } foreach ($s in $certs) { Write-Verbose "$($s.Role) Status: $($s.Level)" if($s.Level -eq "NotConfigured") { $res = $false } } return $res } catch { Write-Error $_.Exception.Message return $false } } } } } #EndRegion './Private/DscRDSCertificateConfiguration.ps1' 147 #Region './Private/DscRDSConfiguration.ps1' 0 Configuration DscRDSConfiguration { param ( [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [String] $GatewayAddress, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [String] $UserGroup = 'RDS-Users', [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [String] $CollectionName = 'RDS', # [Parameter(Mandatory = $true)] # [ValidateNotNullOrEmpty()] # [String] # $UserProfileDiskPath, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [PSCredential] $Credential ) $FQDN = [System.Net.Dns]::GetHostByName($env:computerName).Hostname if ($Join) { $FQDN = $Join } if (!$Join -and !$GatewayAddress) { ThrowError "GatewayAddress is required when not joining a RDS Cluster" } $ConnectionBroker = $FQDN $SessionHost = $FQDN $WebAccessServer = $FQDN $AutomaticReconnectionEnabled = $true $DisconnectedSessionLimitMin = 180 $IdleSessionLimitMin = 0 $BrokenConnectionAction = 'Disconnect' $LicenseServer = $FQDN $LicenseMode = 'PerUser' Import-DscResource -ModuleName PSDesiredStateConfiguration Import-DscResource -ModuleName xRemoteDesktopSessionHost # TODO : Join A cluster # TODO : Gateway Certificate (https://github.com/PowerShell/xRemoteDesktopSessionHost/pull/67) Node localhost { WindowsFeature SessionHost { Name = 'RDS-RD-Server' Ensure = 'Present' } WindowsFeature WebAccess { Name = 'RDS-Web-Access' Ensure = 'Present' } WindowsFeature RDSConnectionBroker { Name = 'RDS-Connection-Broker' Ensure = 'Present' } WindowsFeature RDLicensing { Ensure = "Present" Name = "RDS-Licensing" } WaitForAll SessionHost { NodeName = 'localhost' ResourceName = '[WindowsFeature]SessionHost' RetryIntervalSec = 15 RetryCount = 50 DependsOn = '[WindowsFeature]RDLicensing' } WaitForAll WebAccess { NodeName = 'localhost' ResourceName = '[WindowsFeature]WebAccess' RetryIntervalSec = 15 RetryCount = 50 DependsOn = '[WaitForAll]SessionHost' } xRDSessionDeployment NewDeployment { ConnectionBroker = $ConnectionBroker SessionHost = $SessionHost WebAccessServer = $WebAccessServer DependsOn = '[WaitForAll]WebAccess' PsDscRunAsCredential = $Credential } # Should Reboot after xRDSessionDeployment xRDSessionCollection Collection { CollectionName = $CollectionName SessionHost = $SessionHost ConnectionBroker = $ConnectionBroker DependsOn = '[xRDSessionDeployment]NewDeployment' PsDscRunAsCredential = $Credential } xRDSessionCollectionConfiguration CollectionConfig { CollectionName = $CollectionName ConnectionBroker = $ConnectionBroker AutomaticReconnectionEnabled = $true DisconnectedSessionLimitMin = $DisconnectedSessionLimitMin IdleSessionLimitMin = $IdleSessionLimitMin BrokenConnectionAction = $BrokenConnectionAction # TODO : Specifies a domain group authorized to connect to the RD Session Host servers in a session collection # UserGroup = $UserGroup # TODO : Specifies the target path to store the User Profile Disks # DiskPath = $UserProfileDiskPath # TODO : Specifies if this collection uses UserProfileDisks # EnableUserProfileDisk = $true # TODO : Specifies whether to enable the Remote Desktop Easy Print driver # RDEasyPrintDriverEnabled = DependsOn = '[xRDSessionCollection]Collection' PsDscRunAsCredential = $Credential } xRDLicenseConfiguration LicenseConfig { ConnectionBroker = $ConnectionBroker LicenseServer = $LicenseServer LicenseMode = $LicenseMode DependsOn = '[xRDSessionCollectionConfiguration]CollectionConfig' PsDscRunAsCredential = $Credential } xRDGatewayConfiguration Gateway { ConnectionBroker = $ConnectionBroker GatewayServer = $FQDN ExternalFqdn = $GatewayAddress GatewayMode = "Custom" LogonMethod = "Password" UseCachedCredentials = $false BypassLocal = $true } } } #EndRegion './Private/DscRDSConfiguration.ps1' 163 #Region './Private/DscSmbShareConfiguration.ps1' 0 Configuration DscSmbShareConfiguration { param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Name, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Path, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $FullAccessUser ) Import-DscResource -ModuleName PSDesiredStateConfiguration Import-DscResource -ModuleName ComputerManagementDsc Node localhost { File "$( $Name )Folder" { DestinationPath = $Path Type = "Directory" Force = $true Ensure = "Present" } SmbShare "$( $Name )Share" { Name = $Name Path = $Path DependsOn = "[File]$( $Name )Folder" # TODO : Permissions FullAccess = @($FullAccessUser) } } } #EndRegion './Private/DscSmbShareConfiguration.ps1' 40 #Region './Private/DscSNMPConfiguration.ps1' 0 Configuration DscSNMPConfiguration { param ( [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [String] $Community = "public", [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [String] $Manager = "Any" ) Import-DscResource -ModuleName PSDesiredStateConfiguration Import-DscResource -ModuleName cSNMP Import-DSCResource -ModuleName NetworkingDsc Node localhost{ WindowsFeature SNMPService { Name = "SNMP-Service" Ensure = "Present" } WindowsFeature SNMPWMI { Name = "SNMP-WMI-Provider" Ensure = "Present" } WindowsFeature SNMPRSAT { Name = 'RSAT-SNMP' Ensure = 'Present' } cSNMPCommunity Community { Community = $Community Right = "ReadOnly" Ensure = "Present" DependsOn = '[WindowsFeature]SNMPRSAT' } cSNMPManager Manager { Manager = $Manager Ensure = "Present" } Firewall EnableBuiltInFirewallRule { Name = 'SNMP-In-UDP' Ensure = 'Present' Enabled = 'True' RemoteAddress = @('Any') } } } #EndRegion './Private/DscSNMPConfiguration.ps1' 60 #Region './Private/DscWinRMConfiguration.ps1' 0 Configuration DscWinRMConfiguration { Import-DscResource -Module xWinRM xWinRM WinRMHTTPS { Protocol = "HTTPS" Ensure = "Present" Service_AllowUnencrypted = 'false' RestartService = $true } } #EndRegion './Private/DscWinRMConfiguration.ps1' 11 #Region './Private/Find-DscConfiguration.ps1' 0 function Find-DscConfiguration { param( [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [String] $ConfigurationName ) $confgs = Get-DscConfiguration foreach ($c in $configs) { if ($c.ConfigurationName -eq $ConfigurationName) { return $c } } } #EndRegion './Private/Find-DscConfiguration.ps1' 16 #Region './Private/Get-CARootName.ps1' 0 function Get-CARootName { param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $CAServerFQDN ) $CAServer = $CAServerFQDN.Substring(0, $CAServerFQDN.LastIndexOf('.')) $Parts = $CAServer.Split('.') [Array]::Reverse($Parts) $CARootName = ($Parts -join '-') + "-CA" return $CARootName } #EndRegion './Private/Get-CARootName.ps1' 15 #Region './Private/Get-CertificateCommonName.ps1' 0 function Get-CertificateCommonName { <# .SYNOPSIS Finds the Common Name in a X500 Distinguished Name. .PARAMETER DistinguishedName The X500 Distinguished Name. #> [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $DistinguishedName ) return ($DistinguishedName.split(',') | ForEach-Object -Process { $_.TrimStart(' ') } | Where-Object -FilterScript { $_ -match 'CN=' }).replace('CN=', '') } #EndRegion './Private/Get-CertificateCommonName.ps1' 23 #Region './Private/Get-DomainFromDN.ps1' 0 function Get-DomainFromDN { param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $DN ) return $DN -replace '^.*?,dc=' -replace ',dc=', '.' } #EndRegion './Private/Get-DomainFromDN.ps1' 12 #Region './Private/Get-DomainNameFromDN.ps1' 0 function Get-DomainNameFromDN { param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $DN ) $domain = $DN -replace '^.*?,dc=' -replace ',dc=', '.' $parts = $domain.Split('.') return $parts[$parts.Length - 2] } #EndRegion './Private/Get-DomainNameFromDN.ps1' 14 #Region './Private/Get-DscNodeConfigurationData.ps1' 0 function Get-DscNodeConfigurationData { param ( [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [String] $Hostname = "localhost" ) return @{ NodeName = $Hostname PSDscAllowPlainTextPassword = $true PSDscAllowDomainUser = $true } } #EndRegion './Private/Get-DscNodeConfigurationData.ps1' 16 #Region './Private/Get-RDServerWithRetry.ps1' 0 function Get-RDServerWithRetry { param ( [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [Int16] $Count ) $s try { Import-Module RemoteDesktop $s = Get-RDServer } catch { Write-Error "Failed to get RDServer" $Count -= 1 if ($Count -gt 0) { Write-Host "Remaining attempts: " $Count Get-RDServerWithRetry $Count } else { throw $_ } } return $s } #EndRegion './Private/Get-RDServerWithRetry.ps1' 31 #Region './Public/Backup-AD.ps1' 0 function Backup-AD { <# .SYNOPSIS Backup Active Directory Objects .DESCRIPTION Backup Active Directory Objects .ROLE Administrators #> param( [Parameter(Mandatory = $true)] [String] $BackupPath ) #Backup all Distinguished Name of Objects in the Root Domain.START $DNFolderDelPath = "$BackupPath\*" Test-Path -Path $BackupPath -PathType Container if (-Not(Test-Path $BackupPath)) { New-Item -Path $BackupPath -ItemType Directory } $DNFileName = "ADBackup_$( get-date -Uformat "%Y%m%d-%H%M%S" ).txt" $DNFilePath = "$BackupPath\$DNFileName" $DNList_command = "dsquery * domainroot -scope subtree -attr modifytimestamp distinguishedname -limit 0 > $DNFilePath" Invoke-expression $DNList_command Get-ChildItem $DNFolderDelPath | Where-Object { $_.Lastwritetime -lt (date).adddays(-10) } | Remove-Item -force -recurse -Confirm:$false } #EndRegion './Public/Backup-AD.ps1' 35 #Region './Public/Backup-ADDC.ps1' 0 function Backup-ADDC { <# .SYNOPSIS Backup Active Directory Domain Controller .DESCRIPTION Backup Active Directory Domain Controller .ROLE Administrators #> param( [Parameter(Mandatory = $true)] [String] $BackupPath ) if (!(Test-Path $BackupPath)) { New-Item -ItemType Directory $BackupPath } Backup-Gpo "$BackupPath\GPO" Backup-AD "$BackupPath\AD" Backup-Dns "$BackupPath\DNS" } #EndRegion './Public/Backup-ADDC.ps1' 28 #Region './Public/Backup-Dns.ps1' 0 #********************************************************************************************* # BareMetalADDisasterBackupScript.ps1 # Version 1.0 # Date: 8/03/2013 # Author: Cengiz KUSKAYA (www.Kuskaya.Info) # Description: A PowerShell script to make a full server backup of a Domain Controller, # all group policies, all group policy links, # all Distinguished Name of objects and AD integrated DNS. #********************************************************************************************* # Requirements: # Create a folder named "C:\Script" prior executing the Script and a BATCH file # named C:\Script\DNSBackup.bat . Copy and paste the following commands # into the BATCH file. # dnscmd /enumzones > C:\Script\AllZones.txt # for /f %%a in (C:\Script\AllZones.txt) do dnscmd /ZoneExport %%a Export\%%a.dns #********************************************************************************************* function Backup-Dns { <# .SYNOPSIS Backup Active Directory DNS .DESCRIPTION Backup Active Directory DNS .ROLE Administrators #> param( [Parameter(Mandatory = $true)] [String] $BackupPath ) $tmp = "C:\Windows\Temp" $BatScript = "$tmp\DNSBacckup.bat" Set-Content $BatScript -Value " dnscmd /enumzones > $tmp\AllZones.txt for /f %%a in ($tmp\AllZones.txt) do dnscmd /ZoneExport %%a Export\%%a.dns " $DNSDestFolderPath = "$BackupPath\$Computer-$date" $DNSOldLogDelPath = "$BackupPath\*" $DNSExportFolderPath = "$tmp\DNSExport" Test-Path -Path $BackupPath -PathType Container if (-Not(Test-Path $BackupPath)) { New-Item -Path $BackupPath -ItemType Directory } Test-Path -Path $DNSExportFolderPath -PathType Container if (-Not(Test-Path $DNSExportFolderPath)) { New-Item -Path $DNSExportFolderPath -ItemType Directory } $BatScript New-Item -Path $DNSDestFolderPath -ItemType Directory Copy-Item "$DNSExportFolderPath\*" $DNSDestFolderPath Get-ChildItem $DNSOldLogDelPath | Where-Object { $_.Lastwritetime -lt (date).adddays(-5) } | Remove-Item -force -recurse -Confirm:$false } #EndRegion './Public/Backup-Dns.ps1' 64 #Region './Public/Backup-Gpo.ps1' 0 function Backup-GPO { <# .SYNOPSIS Backup Active Directory GPO .DESCRIPTION Backup Active Directory GPO .ROLE Administrators #> param( [Parameter(Mandatory = $true)] [String] $BackupPath ) Import-Module ActiveDirectory Import-Module GroupPolicy $Computer = Get-Content env:COMPUTERNAME $date = Get-Date -format H.m.d.M.yyyy $GPOPath = "$BackupPath\GPObjects" $DestGPO = "$GPOPath\$Computer-$date" $DestDelGPO = "$GPOPath\*" Test-Path -Path $GPOPath -PathType Container if ( -Not (Test-Path $GPOPath)) { New-Item -Path $GPOPath -ItemType Directory } New-Item -Path $DestGPO -ItemType Directory Get-GPO -all | Backup-GPO -path $DestGPO Get-ChildItem $DestDelGPO | Where-Object {$_.Lastwritetime -lt (date).adddays(-2)} | Remove-Item -force -recurse -Confirm:$false $GPLinkPath = "$BackupPath\GPLink" $DestGPLinkPath = "$GPLinkPath\$Computer-$date" $DestGPLinkDelPath = "$GPLinkPath\*" Test-Path -Path $GPLinkPath -PathType Container if ( -Not (Test-Path $GPLinkPath)) { New-Item -Path $GPLinkPath -ItemType Directory } New-Item -Path $DestGPLinkPath -ItemType Directory Get-ADOrganizationalUnit -Filter 'Name -like "*"' | foreach-object {(Get-GPInheritance -Target $_.DistinguishedName).GpoLinks} | export-csv $DestGPLinkPath\GPLinkBackup.csv -notypeinformation -delimiter ';' Get-ChildItem $DestGPLinkDelPath | Where-Object {$_.Lastwritetime -lt (date).adddays(-5)} | Remove-Item -force -recurse -Confirm:$false } #EndRegion './Public/Backup-Gpo.ps1' 54 #Region './Public/Disable-Firewall.ps1' 0 function Disable-Firewall { Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False } #EndRegion './Public/Disable-Firewall.ps1' 4 #Region './Public/Disable-Ping.ps1' 0 function Disable-Ping { $tmp = "C:\Windows\Temp" DscICMPConfiguration -Disable -OutputPath $tmp | Out-Null Start-DscConfiguration -Wait -Force -Path $tmp -Verbose } #EndRegion './Public/Disable-Ping.ps1' 6 #Region './Public/Enable-Firewall.ps1' 0 function Enable-Firewall { Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled True } #EndRegion './Public/Enable-Firewall.ps1' 4 #Region './Public/Enable-Ping.ps1' 0 function Enable-Ping { $tmp = "C:\Windows\Temp" DscICMPConfiguration -OutputPath $tmp | Out-Null Start-DscConfiguration -Wait -Force -Path $tmp -Verbose } #EndRegion './Public/Enable-Ping.ps1' 6 #Region './Public/Enable-WinRM.ps1' 0 function Enable-WinRM { $tmp = "C:\Windows\Temp" DscWinRMConfiguration -OutputPath $tmp | Out-Null Start-DscConfiguration -Wait -Force -Path $tmp -Verbose } #EndRegion './Public/Enable-WinRM.ps1' 6 #Region './Public/Get-ADDitReport.ps1' 0 Function Get-DitReport { <# .SYNOPSIS Scans the registry for NTDS parameters. Very useful in confirm NTDS changes .DESCRIPTION Scans the registry for NTDS parameters. Very useful in confirm NTDS changes Based on https://gallery.technet.microsoft.com/scriptcenter/PS-NTDSUTIL-b7e9e815 .ROLE Administrators #> $NTDSDIT = (get-item -Path "HKLM:\SYSTEM\CurrentcontrolSet\Services\NTDS\Parameters").GetValue("DSA Database File") $DITSize = (get-item -Path $NTDSDIT).Length $DitStats = Get-item -Path "HKLM:\SYSTEM\CurrentcontrolSet\Services\NTDS\Parameters" $DitStats Write-Host " Present NTDS DB Size : $DitSize" } #EndRegion './Public/Get-ADDitReport.ps1' 21 #Region './Public/Initialize-DataDisks.ps1' 0 function Initialize-DataDisks { <# .SYNOPSIS Initialize-DataDisks use Storage Dsc to ensure data disks are initializes .DESCRIPTION Initialize-DataDisks use Storage Dsc to ensure data disks are initializes .ROLE Administrators #> $tmp = "C:\Windows\Temp" DscInitializeDataDisks -OutputPath $tmp | Out-Null Start-DscConfiguration -Wait -Force -Path $tmp -Verbose } #EndRegion './Public/Initialize-DataDisks.ps1' 18 #Region './Public/Install-ADCS.ps1' 0 function Install-ADCS { param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $DataPath, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Username, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Password ) $CertsPath = "$DataPath\CERTS" $CertsLogPath = "$DataPath\LOGS" if (!(Test-Path $DataPath)) { try { New-Item -Type Directory -Force $DataPath | Out-Null } catch { throw $_ } } New-Item -Type Directory -Force $CertsPath | Out-Null New-Item -Type Directory -Force $CertsLogPath | Out-Null $cd = @{ AllNodes = @( @{ NodeName = 'localhost' PSDscAllowPlainTextPassword = $true PSDscAllowDomainUser = $true } ) } $tmp = "C:\Windows\Temp" $Credential = New-Object System.Management.Automation.PSCredential($Username, (ConvertTo-SecureString $Password -AsPlainText -Force)) $Params = @{ DataPath = $CertsPath LogPath = $CertsLogPath OutputPath = $tmp Credential = $Credential ConfigurationData = $cd } # Use DscADCS to install Active Directory CA Services DscADCSConfiguration @Params | Out-Null Start-DscConfiguration -Wait -Force -Path $tmp -Verbose } #EndRegion './Public/Install-ADCS.ps1' 59 #Region './Public/Install-ADDC.ps1' 0 function Install-ADDC { param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Domain, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $DataPath, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Username, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Password, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $SafeModePassword ) $DatabasePath = "$DataPath\NTDS" $ADSysvolPath = "$DataPath\SYSVOL" $ADLogPath = "$DataPath\LOGS" if (!(Test-Path $DataPath)) { try { New-Item -Type Directory -Force $DataPath | Out-Null } catch { throw $_ } } New-Item -Type Directory -Force $DatabasePath | Out-Null New-Item -Type Directory -Force $ADSysvolPath | Out-Null New-Item -Type Directory -Force $ADLogPath | Out-Null $cd = @{ AllNodes = @( @{ NodeName = 'localhost' PSDscAllowPlainTextPassword = $true } ) } # Use DscADDC to install new AD Forest $tmp = "C:\Windows\Temp" $smp = New-Object System.Management.Automation.PSCredential('(Password Only)', (ConvertTo-SecureString $SafeModePassword -AsPlainText -Force)) $Credential = New-Object System.Management.Automation.PSCredential($Username, (ConvertTo-SecureString $Password -AsPlainText -Force)) $Params = @{ Domain = $Domain DatabasePath = $DatabasePath LogPath = $ADLogPath SysvolPath = $ADSysvolPath SafeModePassword = $smp Credential = $Credential OutputPath = $tmp ConfigurationData = $cd } DscADDCConfiguration @Params | Out-Null Start-DscConfiguration -Wait -Force -Path $tmp -Verbose } #EndRegion './Public/Install-ADDC.ps1' 74 #Region './Public/Install-RDS.ps1' 0 function Install-RDS { param ( [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [String] $GatewayAddress, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [String] $UserGroup = 'RDS_Users', [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [String] $CollectionName = 'RDS', [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Username, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Password ) $tmp = "C:\Windows\Temp" $cd = @{ AllNodes = @( @{ NodeName = 'localhost' PSDscAllowPlainTextPassword = $true ActionAfterReboot = 'StopConfiguration' } ) } $Credential = New-Object System.Management.Automation.PSCredential($Username, (ConvertTo-SecureString $Password -AsPlainText -Force)) $Params = @{ Credential = $Credential GatewayAddress = $GatewayAddress UserGroup = $UserGroup CollectionName = $CollectionName OutputPath = $tmp ConfigurationData = $cd } DscRDSConfiguration @Params | Out-Null Start-DscConfiguration -Wait -Force -Path $tmp -Verbose } #EndRegion './Public/Install-RDS.ps1' 54 #Region './Public/Install-RDSCertificates.ps1' 0 function Install-RDSCertificates { param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $CAServerFQDN, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [String] $GatewayAddress, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Username, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Password ) $tmp = "C:\Windows\Temp" $cd = @{ AllNodes = @( @{ NodeName = 'localhost' PSDscAllowPlainTextPassword = $true ActionAfterReboot = 'StopConfiguration' } ) } $Credential = New-Object System.Management.Automation.PSCredential($Username, (ConvertTo-SecureString $Password -AsPlainText -Force)) $Params = @{ Credential = $Credential GatewayAddress = $GatewayAddress CAServerFQDN = $CAServerFQDN OutputPath = $tmp ConfigurationData = $cd } DscRDSCertificateConfiguration @Params | Out-Null Start-DscConfiguration -Wait -Force -Path $tmp -Verbose } #EndRegion './Public/Install-RDSCertificates.ps1' 50 #Region './Public/Install-SNMP.ps1' 0 function Install-SNMP { param ( [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [String] $Community = "public", [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [String] $Manager = "Any" ) $tmp = "C:\Windows\Temp" DscSNMPConfiguration -Community $Community -Manager $Manager -OutputPath $tmp | Out-Null Start-DscConfiguration -Wait -Force -Path $tmp -Verbose Remove-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Services\SNMP\Parameters\PermittedManagers -Name * } #EndRegion './Public/Install-SNMP.ps1' 19 #Region './Public/Join-Domain.ps1' 0 function Join-Domain { param ( [Parameter(Mandatory = $true)] [ValidateNotNullorEmpty()] [String] $ComputerName, [Parameter(Mandatory = $true)] [ValidateNotNullorEmpty()] [String] $OrganizationUnit, [Parameter(Mandatory = $true)] [ValidateNotNullorEmpty()] [String] $DomainControllerIP, [Parameter(Mandatory = $false)] [String] $Description, [Parameter(Mandatory = $true)] [ValidateNotNullorEmpty()] [String] $Username, [Parameter(Mandatory = $true)] [ValidateNotNullorEmpty()] [String] $Password ) $cd = @{ AllNodes = @( @{ NodeName = 'localhost' PSDscAllowPlainTextPassword = $true } ) } $tmp = "C:\Windows\Temp" $Credential = New-Object System.Management.Automation.PSCredential($Username, (ConvertTo-SecureString $Password -AsPlainText -Force)) $Params = @{ ComputerName = $ComputerName OrganizationUnit = $OrganizationUnit DomainControllerIP = $DomainControllerIP Description = $Description Credential = $Credential ConfigurationData = $cd OutputPath = $tmp } DscDomainJoinConfiguration @Params | Out-Null Start-DscConfiguration -Wait -Force -Path $tmp -Verbose } #EndRegion './Public/Join-Domain.ps1' 56 #Region './Public/Mount-SmbShare.ps1' 0 function Mount-SmbShare { param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $DriveLetter, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $NetworkDriveRoot ) $tmp = "C:\Windows\Temp" $Params = @{ DriveLetter = $DriveLetter NetworkDriveRoot = $NetworkDriveRoot OutputPath = $tmp } DscMountSmbShareConfiguration @Params | Out-Null Start-DscConfiguration -Wait -Force -Path $tmp -Verbose } #EndRegion './Public/Mount-SmbShare.ps1' 24 #Region './Public/Move-ADDit.ps1' 0 Function Move-ADDIT { <# .SYNOPSIS Move NTDS.DIT and make DS-related registry changes .DESCRIPTION Move NTDS.DIT and make DS-related registry changes Based on https://gallery.technet.microsoft.com/scriptcenter/PS-NTDSUTIL-b7e9e815 .ROLE Administrators #> param( # target path for new NTDS location. EX: D:\Windows\NTDS" [Parameter(Mandatory = $true)] [String] $NewPath ) if ($NewPath -eq "") { Write-Host "Target Path unspecified. Cannot continue..." -ForegroundColor Red Break } # Extract Target's drive letter from given path $Newdrive = $NewPath.substring(0, 2) # Get the target drive's free space $freespace = (Get-WmiObject -Class Win32_volume -Filter "Driveletter = '$newdrive'").freespace # Get the target drive's file format $FS = (Get-WmiObject -Class Win32_volume -Filter "DriveLetter = '$newdrive'").FileSystem $NewDit = $NewPath + "\ntds.dit" $NewDitBak = $NewPath + "\dsadata.bak" #Extract NTDS parameters from registry $NTDSDIT = (get-item -Path "HKLM:\SYSTEM\CurrentcontrolSet\Services\NTDS\Parameters").GetValue("DSA Database File") $NTDSPath = (get-item -Path "HKLM:\SYSTEM\CurrentcontrolSet\Services\NTDS\Parameters").GetValue("DSA Working Directory") $DITSize = (get-item -Path $NTDSDIT).Length #Check target disk free space If ($DITSize -le $Freespace) { Write-Host "Available Free space on $NewPath = $Freespace - Good" -foregroundColor Green } Else { Write-Host "Not enough free space on $NewPath = $Freespace " -foregroundColor Red Break } #Check target disk format If ($FS -notmatch "NTFS") { Write-Host "Cannot continue NTDS database move. $newDrive is not a NTFS formatted drive." -foregroundColor Red Break } #Check for older NTDS.DIT file If ((get-childitem -Path $NewPath -Recurse -Filter "NTDS.DIT").Exists -eq "True") { Write-Host "Cannot continue. Old NTDS.DIT file exists in $NewPath ." Break } Write-Host "Moving NTDS database from $NTDSpath to $NewPath" #Set DS registry keys to reflect new path set-itemproperty -Path "HKLM:\SYSTEM\CurrentcontrolSet\Services\NTDS\Parameters" -Name "DSA Database File" -value $NewDit set-itemproperty -Path "HKLM:\SYSTEM\CurrentcontrolSet\Services\NTDS\Parameters" -Name "DSA Working Directory" -value $NewPath set-itemproperty -Path "HKLM:\SYSTEM\CurrentcontrolSet\Services\NTDS\Parameters" -Name "Database backup path" -value $NewDitBak #Move the NTDS.Dit file Move-Item $NTDSDIT $NewPath If ($NewNTDSPath + "\NTDS.DIT") { Write-Host "NTDS.DIT file sucessfully moved to $NewPath" -ForegroundColor Green Test-ADDit Write-Host "NTDS database operation sucessfully completed!!!" -ForegroundColor Green Write-Host "" } } #EndRegion './Public/Move-ADDit.ps1' 89 #Region './Public/Move-ADLogs.ps1' 0 Function Move-ADLogs { <# .SYNOPSIS Move EDB.Log and make DS-related registry changes .DESCRIPTION Move EDB.Log and make DS-related registry changes Based on https://gallery.technet.microsoft.com/scriptcenter/PS-NTDSUTIL-b7e9e815 .ROLE Administrators #> param( # Target path for new EDB Log location. EX: D:\Windows\NTDS [Parameter(Mandatory = $true)] [String] $NewPath ) if ($NewPath -eq "") { Write-Host "Target Path unspecified. Cannot continue..." -ForegroundColor Red Break } #Variables #Extract the Target drive letter from the given path $NewLogdrive = $NewPath.substring(0, 2) # Get the target drive's free space $NewLogfreespace = (Get-WmiObject -Class Win32_volume -Filter "Driveletter = '$newlogdrive'").freespace #Extract NTDS parameters from registry $DitLogPath = (get-item -Path "HKLM:\SYSTEM\CurrentcontrolSet\Services\NTDS\Parameters").GetValue("Database log files path") $Log = $DitLogPath + "\EDB.Log" $LogSize = (get-item -Path $Log).Length # Get the target drive's file format $LogFS = (Get-WmiObject -Class Win32_volume -Filter "DriveLetter = '$newlogdrive'").FileSystem # Check target disk free space If ($LOGSize -le $NewLogfreespace) { Write-Host "Available Free space on $NewNTDS_Path = $NewLogfreespace - Good" -foregroundColor Green } Else { Write-Host "Not enough free space on $NewPath = $NewLogfreespace " -foregroundColor Red Start-Service NTDS -Confirm Break } # Check the target drive's file format If ($LogFS -ne "NTFS") { Write-Host "Cannot continue EDB Log move. $newlogDrive is not a NTFS formatted drive." -foregroundColor Red Start-Service NTDS -Confirm Break } # Check the target path for old EDB.Logs If ((get-childitem -Path $NewPath -Recurse -Filter "EDB.Log").Exists -eq "True") { Write-Host "Cannot continue. EDB Logs already exists." Break } Write-Host "Moving EDB Logs from $DitLogPath to $NewPath" set-itemproperty -Path "HKLM:\SYSTEM\CurrentcontrolSet\Services\NTDS\Parameters" -Name "Database log files path" -value $NewPath Move-Item $Log $NewPath Get-ChildItem -Path C:\ntds -Filter "*EDB*" |Remove-item Write-Host "" If ((get-childitem -Path $NewPath -Recurse -Filter "EDB.LOG").Exists -eq "True") { Write-Host "EDB Log move operation sucessfully completed!!!" -ForegroundColor Green Write-Host "" } } #EndRegion './Public/Move-ADLogs.ps1' 81 #Region './Public/Move-DnsData.ps1' 0 function Move-DnsData { <# .SYNOPSIS Move DNS Data location .DESCRIPTION Move DNS Data location .ROLE Administrators #> param( # Where to move data [Parameter(Mandatory = $true)] [String] $NewLocation ) $RegPath = 'HKLM:\System\CurrentControlSet\Services\DNS\Parameters' $RegKey = 'DatabaseDirectory' $Location $DefaultLocation = "C:\Windows\System32\DNS" $LocationItem = Get-ItemProperty -Path $RegPath -Name $RegKey -ErrorAction 'SilentlyContinue' if (!$LocationItem -or !$LocationItem.DatabaseDirectory) { $Location = $DefaultLocation } else { $Location = $LocationItem.DatabaseDirectory } if (!(Test-Path $Location)) { return @{ Code = 1; Message = "DNS Data directory not found" } } try { if (!(Test-Path $NewLocation)) { New-Item -ItemType Directory -Force $NewLocation | Out-Null } if ($Location -eq (Resolve-Path $NewLocation).Path) { return @{ Code = 0; Message = "Dns data already at $Location" } } Write-Host "Copying C:\Windows\System32\dns to $NewLocation" Copy-Item -Recurse -Force "$Location\*" $NewLocation Write-Host "Setting DNS Data location in registry" Set-ItemProperty -Path $RegPath -Name $RegKey -Value $NewLocation } catch { return @{ Code = 1; Message = $_.Exception } } } #EndRegion './Public/Move-DnsData.ps1' 65 #Region './Public/New-AD.ps1' 0 function New-AD { param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Domain, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $DataPath, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Password, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $SafeModePassword ) $ErrorActionPreference = 'Stop' $Username = "Administrator" $ADDataPath = "$DataPath\AD" $ADDCParams = @{ Domain = $Domain DataPath = $ADDataPath Username = $Username Password = $Password SafeModePassword = $SafeModePassword } Install-ADDC @ADDCParams $ADCSDataPath = "$DataPath\ADCS" Install-ADCS -DataPath $ADCSDataPath -Username $Username -Password $Password $DnsDataPath = "$DataPath\DNS" Move-DnsData -NewLocation $DnsDataPath } #EndRegion './Public/New-AD.ps1' 47 #Region './Public/New-ADIfmSnapshot.ps1' 0 Function New-ADIfmSnapshot { <# .SYNOPSIS Performs IFM (AD Snapshot) using NTDSUTIL .DESCRIPTION Performs IFM (AD Snapshot) using NTDSUTIL Based on https://gallery.technet.microsoft.com/scriptcenter/PS-NTDSUTIL-b7e9e815 .ROLE Administrators #> param( # A secured Target path for IFM files [Parameter(Mandatory = $true)] [String] $IfmPath ) if ($IfmPath -eq "") { Write-Host "Target Path unspecified. Cannot continue..." -ForegroundColor Red Break } $IFMdrive = $IfmPath.substring(0, 2) $IFMfreespace = (Get-WmiObject -Class Win32_volume -Filter "Driveletter = '$IFMdrive'").freespace $NTDSDIT = (get-item -Path "HKLM:\SYSTEM\CurrentcontrolSet\Services\NTDS\Parameters").GetValue("DSA Database File") $NTDSPath = (get-item -Path "HKLM:\SYSTEM\CurrentcontrolSet\Services\NTDS\Parameters").GetValue("DSA Working Directory") $DITSize = (get-item -Path $NTDSDIT).Length If ($DITSize -le $IFMFreespace) { Write-Host "Available Free space on $IfmPath = $IFMfreespace - Good" -foregroundColor Green } Else { Write-Host "Not enough free space on $IfmPath = $IFMFreespace " -foregroundColor Red Break } If ((get-childitem -Path $IfmPath -Recurse -Filter "*.dit").Exists -eq "True") { Write-Host "AD Snapshot file already exists in $IfmPath. Cannot continue operation" -ForegroundColor Red Break } # Check for running AD service. IF AD services are stopped, service will be started $DSSRV = (Get-Service NTDS).Status IF ($DSSRV -ne "Running") { Start-Service NTDS -Confirm } Write-Host "Creating Full IFM File package in $IfmPath ..." Write-Host "" Write-Host "____________________________________________________________" -ForegroundColor Blue $IFMCMD = ntdsutil "activate instance NTDS" IFM "Create Full $IfmPath" quit quit $IFMCMD $IFMFS = get-childitem -Path $IfmPath -Recurse -Verbose foreach ($IFMF in $IFMFS) { $IFMTS = $IFMF.length + $IFMF.length } Write-Host "" Write-Host "Total size for IFM is $IFMTS" Write-Host "" } #EndRegion './Public/New-ADIfmSnapshot.ps1' 70 #Region './Public/New-ADOfflineDefrag.ps1' 0 Function New-ADOfflineDefrag { <# .SYNOPSIS Performs AD Offline Deframentation using NTDSUtil .DESCRIPTION Performs AD Offline Deframentation using NTDSUtil Based on https://gallery.technet.microsoft.com/scriptcenter/PS-NTDSUTIL-b7e9e815 .ROLE Administrators #> param( # Temp path for NTDS.Dit file defragmentation process Default= C:\Temp [Parameter(Mandatory = $false)] [String] $TempPath ) if ($TempPath -eq "") { $TempPath = "C:\temp" } #Varibles $Tempdrive = $TempPath.substring(0, 2) $Tempfreespace = (Get-WmiObject -Class Win32_volume -Filter "Driveletter = '$Tempdrive'").freespace $NTDSDIT = (get-item -Path "HKLM:\SYSTEM\CurrentcontrolSet\Services\NTDS\Parameters").GetValue("DSA Database File") $DITSize = (get-item -Path $NTDSDIT).Length If ($DITSize -ge $Tempfreespace) { Write-Host "Not Enough Disk Space on $TempPath for defragmentation process. Cannot continue.." -ForegroundColor Red Break } IF ((get-childitem -Path $TempPath -Recurse -Filter "*.dit").Exists -eq "True") { Write-Host "NTDS.DIT already exists - please remove first" -ForegroundColor Red Break } Write-Host "" Write-Host "Compacting NTDS database..." Write-Host "" Write-Host "____________________________________________________________" -ForegroundColor Blue # Compile NTDSUTIL required commands in series $NTDSdbCompactor = ntdsutil "activate instance ntds" "files" "Compact to $TempPath" "q" "q" #Execute compiled NTDSUTIL commands $NTDSdbCompactor $NewDit = $TempPath + "\ntds.dit" Write-Host "" # Move newly compacted NTDS.DIT to the working DSA directory Move-Item $NewDit $NTDSPath # Clear the DSA Database Epoch key to indicate backup. Note: Future DS operations will error if this parameter isn't cleared Remove-itemproperty -Path "HKLM:\SYSTEM\CurrentcontrolSet\Services\NTDS\Parameters" -name "DSA Database Epoch" -ErrorAction SilentlyContinue # Delete all logs for DB consistency Remove-item $DitLogPath\*.log Write-Host "" Write-Host "NTDS Defragmentation Completed" -ForegroundColor Green Write-Host "" } #EndRegion './Public/New-ADOfflineDefrag.ps1' 72 #Region './Public/New-ADStructure.ps1' 0 function New-ADStructure { $tmp = "C:\Windows\Temp" DscADStructureConfiguration -OutputPath $tmp | Out-Null Start-DscConfiguration -Wait -Force -Path $tmp -Verbose } #EndRegion './Public/New-ADStructure.ps1' 6 #Region './Public/New-ComputerConfiguration.ps1' 0 function New-ComputerConfiguration { param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $ComputerName, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $IP, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Gateway, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $DnsServer, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [String] $Password ) $tmp = "C:\Windows\Temp" $Params = @{ ComputerName = $ComputerName IP = $IP Gateway = $Gateway DnsServer = $DnsServer OutputPath = $tmp } DscComputerConfiguration @Params | Out-Null Start-DscConfiguration -Wait -Force -Path $tmp -Verbose if($Password) { Get-LocalUser -Name "Administrator" | Set-LocalUser -Password (New-SecureString $Password) } } #EndRegion './Public/New-ComputerConfiguration.ps1' 48 #Region './Public/New-DomainController.ps1' 0 function New-DomainController { param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Domain, [Parameter(Mandatory = $true)] [ValidateNotNullorEmpty()] [String] $DomainControllerIP, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $DataPath, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Username, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Password, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $SafeModePassword ) $DatabasePath = "$DataPath\NTDS" $ADSysvolPath = "$DataPath\SYSVOL" $ADLogPath = "$DataPath\LOGS" if (!(Test-Path $DataPath)) { try { New-Item -Type Directory -Force $DataPath | Out-Null } catch { throw $_ } } New-Item -Type Directory -Force $DatabasePath | Out-Null New-Item -Type Directory -Force $ADSysvolPath | Out-Null New-Item -Type Directory -Force $ADLogPath | Out-Null $cd = @{ AllNodes = @( @{ NodeName = 'localhost' PSDscAllowPlainTextPassword = $true } ) } # Use DscADDC to install new AD Forest $tmp = "C:\Windows\Temp" $smp = New-Object System.Management.Automation.PSCredential('(Password Only)', (ConvertTo-SecureString $SafeModePassword -AsPlainText -Force)) $Credential = New-Object System.Management.Automation.PSCredential($Username, (ConvertTo-SecureString $Password -AsPlainText -Force)) $Params = @{ Domain = $Domain DomainControllerIP = $DomainControllerIP DatabasePath = $DatabasePath LogPath = $ADLogPath SysvolPath = $ADSysvolPath SafeModePassword = $smp Credential = $Credential OutputPath = $tmp ConfigurationData = $cd } DscDomainController @Params | Out-Null Start-DscConfiguration -Wait -Force -Path $tmp -Verbose } #EndRegion './Public/New-DomainController.ps1' 80 #Region './Public/New-SecureString.ps1' 0 function New-SecureString { <# .SYNOPSIS Convert given string as secure string .DESCRIPTION Convert given string as secure string .ROLE Administrators #> param( # String to secure [Parameter(Mandatory = $true)] [String] $String ) return ConvertTo-SecureString $String -AsPlainText -Force } #EndRegion './Public/New-SecureString.ps1' 22 #Region './Public/New-SmbShare.ps1' 0 function New-SmbShare { param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Name, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Path, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [String] $FullAccessUser = $env:USER ) $tmp = "C:\Windows\Temp" $Params = @{ Name = $Name Path = $Path FullAccessUser = $FullAccessUser OutputPath = $tmp } DscSmbShareConfiguration @Params | Out-Null Start-DscConfiguration -Wait -Force -Path $tmp -Verbose } #EndRegion './Public/New-SmbShare.ps1' 29 #Region './Public/Register-AsLibreNMSDevice.ps1' 0 function Register-AsLibreNMSDevice { param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $BaseUrl, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Token, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [String] $Community = "public", [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [String] $SNMPVersion = "v2c" ) $url = $BaseUrl.TrimEnd("/") + "/api/v0/devices" $hostname = [System.Net.Dns]::GetHostByName($env:computerName).Hostname $headers = @{ "X-Auth-Token" = $Token } $body = @{ hostname = $hostname version = $SNMPVersion community = $Community } | ConvertTo-Json Invoke-WebRequest -Method Post -Headers $headers -Uri $url -Body $body -UseBasicParsing } #EndRegion './Public/Register-AsLibreNMSDevice.ps1' 33 #Region './Public/Rename-ADDomain.ps1' 0 function Rename-ADDomain { <# .SYNOPSIS Remame-ADDomain rename the active directory domain on all Domain Controllers .DESCRIPTION Remame-ADDomain rename the active directory domain on all Domain Controllers .ROLE Administrators #> param( [Parameter(Mandatory = $true)] [String] $NewDomain, [Parameter(Mandatory = $true)] [String] $NewNetBIOSName, [Switch] $Restart ) $ErrorActionPreference = 'Stop' $ProgressPreference = 'SilentlyContinue' # Get domain name $oldDomain = (Get-ADDomain).Forest $oldName = (Get-ADDomain).NetBIOSName $tmpDir = "C:\Windows\Temp" Write-Host "Saving old domain and old netbios name in registry" New-Item -Force $Global:PwsRegistryPath Set-ItemProperty $Global:PwsRegistryPath -Name "OldDomain" -Value $oldDomain Set-ItemProperty $Global:PwsRegistryPath -Name "OldNetBiosName" -Value $oldName # We will move to temp directory during the script # So we need to store the current location go back there at the end $originalLocation = Get-Location Set-Location $tmpDir $listFile = "$tmpDir\Domainlist.xml" $listFileBkp = "$listFile.bkp" Write-Host "Dumping Domain listfile to $listFile" rendom /list /listfile:$listFile Write-Debug "Moving $listFile to $listFileBkp" Move-Item $listFile $listFileBkp -Force Write-Debug "Updating listfile $listFile" Get-Content $listFileBkp | ForEach-Object { $_ -Replace "$oldDomain", "$NewDomain" } | ForEach-Object { $_ -Replace "$oldName", "$NewNetBIOSName" } > $listFile Write-Host "New Domain" rendom /showforest /listfile:$listFile Write-Host "Uploading new Domain listfile" rendom /upload /listfile:$listFile | Out-Null Write-Host "Preparing to rename domain" rendom /prepare /listfile:$listFile | Out-Null Write-Host "Executing domain rename" rendom /execute /listfile:$listFile | Out-Null Write-Debug "Cleaning $listFile" Remove-Item -Force $listFile | Out-Null Write-Debug "Cleaning $listFileBkp" Remove-Item -Force $listFileBkp | Out-Null Set-Location $originalLocation Write-Warning "The computer must be restarted twice to finish domain renaming" if ($Restart) { Write-Host "Restarting" Restart-Computer -Force } } #EndRegion './Public/Rename-ADDomain.ps1' 74 #Region './Public/Start-ADDS.ps1' 0 Function Start-ADDS { <# .SYNOPSIS Start AD and its dependant services .DESCRIPTION Start AD and its dependant services Based on https://gallery.technet.microsoft.com/scriptcenter/PS-NTDSUTIL-b7e9e815 .ROLE Administrators #> Write-Output "Starting Active directory Domain Service.... " Start-Service NTDS -Confirm:$false #Routine to Confirm Service Status $DSSRV = (Get-Service NTDS).Status IF ($DSSRV -eq "Running") { Write-Host "Active Directory Domain Service is $DSSRV" -ForegroundColor Green } IF ($DSSRV -eq "Stopped") { Write-Host "Active Directory Domain Service is $DSSRV" -ForegroundColor Red } } #EndRegion './Public/Start-ADDS.ps1' 30 #Region './Public/Stop-ADDS.ps1' 0 Function Stop-ADDS { <# .SYNOPSIS Stop AD and its dependant services .DESCRIPTION Stop AD and its dependant services Based on https://gallery.technet.microsoft.com/scriptcenter/PS-NTDSUTIL-b7e9e815 .ROLE Administrators #> Write-Output "Stopping Active directory Domain Service.... " Stop-Service NTDS -Force } #EndRegion './Public/Stop-ADDS.ps1' 18 #Region './Public/Sync-DnsDomain.ps1' 0 function Sync-DnsDomain { <# .SYNOPSIS Sync-DNSDomain synchronize DNS Server Name with Active Directory Domain .DESCRIPTION Sync-DNSDomain synchronize DNS Server Name with Active Directory Domain .ROLE Administrators #> param( [Switch] $Restart ) $dnsDomain = (Get-DnsServerSetting).ComputerName -Replace "$env:ComputerName.", "" if (!$dnsDomain) { Write-Error "Cannot find Dns Server Domain" return 1 } $dcDomain = (Get-ADDomain).DNSRoot if (!$dcDomain) { Write-Error "Cannot find Active Directory Domain" return 1 } if ($dcDomain -eq $dnsDomain) { Write-Host "DC domain and DNS domain are already synched: $dnsDomain" return 0 } netdom computername "$env:ComputerName.$dnsDomain" /add:"$env:ComputerName.$dcDomain" netdom computername "$env:ComputerName.$dnsDomain" /makeprimary:"$env:ComputerName.$dcDomain" if ($Restart) { Write-Host "Restarting Computer" Restart-Computer -Force return 0 } Write-Host "The computer must be restarted" } #EndRegion './Public/Sync-DnsDomain.ps1' 45 #Region './Public/Sync-GpoDomain.ps1' 0 function Sync-GpoDomain { <# .SYNOPSIS Sync-GpoDomain synchronize DNS name and NetBiosName with Active Directory Domain .DESCRIPTION Sync-GpoDomain synchronize DNS name and NetBiosName with Active Directory Domain .ROLE Administrators #> param( # The old NetBiosName [Parameter(Mandatory = $false)] [String] $OldNetBIOSName, # The old Dns Domain [Parameter(Mandatory = $false)] [String] $OldDomain ) if (!$OldNetBIOSName) { $OldNetBIOSName = (Get-ItemProperty -Path $Global:PwsRegistryPath).OldNetBiosName if (!$OldNetBIOSName) { Write-Error "Cannot get old NetBIOSName from Registry, please provide -OldNetBIOSName" return 1 } } if (!$OldDomain) { $OldDomain = (Get-ItemProperty -Path $Global:PwsRegistryPath).OldDomain if (!$OldDomain) { Write-Error "Cannot get old Domain from Registry, please povide -OldDomain" return 1 } } $adDomain = Get-ADDomain $domain = $adDomain.DNSRoot $netBIOSName = $adDomain.NetBIOSName Write-Host "Synching Group Policy Dns Domain" gpfixup /olddns:$OldDomain /newdns:$domain | Out-Null Write-Host "Synching Group Policy NetBIOS name" gpfixup /oldnb:$OldNetBIOSName /newnb:$netBIOSName | Out-Null } #EndRegion './Public/Sync-GpoDomain.ps1' 51 #Region './Public/Test-ADDit.ps1' 0 Function Test-ADDit { <# .SYNOPSIS Trigger NTDSUTIL's semantic database analysis in non-repair mode .DESCRIPTION Trigger NTDSUTIL's semantic database analysis in non-repair mode Based on https://gallery.technet.microsoft.com/scriptcenter/PS-NTDSUTIL-b7e9e815 .ROLE Administrators #> Write-Output "Checking NTDS database for errors (semantic database analysis)..." Write-Host "" ntdsutil "activate instance ntds" "semantic database analysis" "Go" q "files" "checksum" q q } #EndRegion './Public/Test-ADDit.ps1' 19 |