From e3ad018191db7e80d3215c176649d5386a62f865 Mon Sep 17 00:00:00 2001 From: Danny de Kooker Date: Fri, 5 Jul 2024 17:04:06 +0200 Subject: [PATCH] Initial setup --- Active Directory/Setup-ADDS-structure.ps1 | 170 +++++++++++++++++ Active Directory/Setup-ADForest.ps1 | 214 ++++++++++++++++++++++ 2 files changed, 384 insertions(+) create mode 100644 Active Directory/Setup-ADDS-structure.ps1 create mode 100644 Active Directory/Setup-ADForest.ps1 diff --git a/Active Directory/Setup-ADDS-structure.ps1 b/Active Directory/Setup-ADDS-structure.ps1 new file mode 100644 index 0000000..e77257d --- /dev/null +++ b/Active Directory/Setup-ADDS-structure.ps1 @@ -0,0 +1,170 @@ +<# +.SYNOPSIS + This script configures the basic settings for an Active Directory Domain Services (ADDS) environment. + It enables the Recycle Bin feature, creates a basic Organizational Unit (OU) structure, and logs the configuration process. + The script also generates a summary file with the configuration details. + +.DESCRIPTION + The script performs the following tasks: + + 1. Checks if the server is part of a domain and if the required PowerShell modules are available. + 2. Enables the Recycle Bin feature if it's not already enabled. + 3. Creates a basic OU structure with the following OUs: Users, Groups, Computers, Servers, Service Accounts, and Administrators. + 4. Logs the configuration process to a log file. + 5. Generates a summary file with the configuration details. + +.PARAMETER None + This script does not require any parameters. + +.EXAMPLE + Run the script in PowerShell to configure the ADDS environment. + +.NOTES + This script is intended for use in a test or production environment. Make sure to test the script in a non-production environment before running it in production. + Author: D.de Kooker - info@dcomputers.nl + Version: 1.0 + + DISCLAIMER: Use scripts at your own risk, if there is anything I can help you with I will try but I do not take responsibility for the way that anyone else uses my scripts. + Sharing is caring. Share your knowledge with the world so that everybody can learn from it. + +.LINK + The latest version can Always be found on my GIT page on the link below: + https://git.dcomputers.nl/Dcomputers/PowershellScripts +#> + +#region Global script settings and variables + $Version = "v1.0" + $logfilelocation = "$($MyInvocation.MyCommand.Path | Split-Path -Parent)\Logs" + $logfilename = "$(Get-Date -Format yyyyMMddHHmmss)-ADDS_Configuration.log" + $summaryfilename = "$(Get-Date -Format yyyyMMddHHmmss)-ADDS_Configuration_Summary.txt" +#endregion + +#region functions + function Initiate-Log { + # Get current user and session information + $username = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name + $computerName = $env:COMPUTERNAME + $sessionID = $pid + $date = Get-Date -Format "yyyy-MM-dd HH:mm:ss" + + # Write log header + $logHeader = "[$date] Log initiated by $username on $computerName (Session ID: $sessionID)" + Add-Content -Path $logfilelocation\$logfilename -Value "**********************" + Add-Content -Path $logfilelocation\$logfilename -Value "LogFile initiation" + Add-Content -Path $logfilelocation\$logfilename -Value "Start time: $date" + Add-Content -Path $logfilelocation\$logfilename -Value "Username: $username" + Add-Content -Path $logfilelocation\$logfilename -Value "Machine: $computerName" + Add-Content -Path $logfilelocation\$logfilename -Value "Process ID: $sessionID" + Add-Content -Path $logfilelocation\$logfilename -Value "Script Version: $Version" + Add-Content -Path $logfilelocation\$logfilename -Value "Script Source: https://git.dcomputers.nl/Dcomputers/PowershellScripts" + Add-Content -Path $logfilelocation\$logfilename -Value "**********************" + } + + function Write-Log { + [CmdletBinding()] + Param ( + [Parameter(Mandatory=$true)] + [string]$Message, + [Parameter(Mandatory=$false)] + [ValidateSet("INFO", "WARNING", "ERROR")] + [string]$Level = "INFO" + ) + $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" + $logmessage = "[$timestamp] [$Level] $Message" + Add-Content -Path $logfilelocation\$logfilename -Value $logmessage + } + + function Write-Summary { + [CmdletBinding()] + Param ( + [Parameter(Mandatory=$true)] + [string]$Message + ) + Add-Content -Path $logfilelocation\$summaryfilename -Value $Message + } +#endregion + +#region prerequisites check + #Create log directory if not present and initiate logfile + if (!(test-path $logfilelocation)) {mkdir $logfilelocation} + Initiate-Log + + #Check if the required Powershell Modules are available + $modules = @("ActiveDirectory","DnsServer") + foreach ($module in $modules) { + if (!(Get-Module -Name $module -ListAvailable)) { + Write-Host "The $module module is not installed. Please install it and try again." + Write-Log -Message "The $module module is not installed. Please install it and try again." -Level ERROR + exit 1 + } + else { + Import-Module $module + } + } + + #Check if the server is part of a domain + $domainController = Get-ADDomainController -ErrorAction SilentlyContinue + if (-not $domainController) { + Write-Host "The local server is not part of a domain." + Write-Log -Message "The local server is not part of a domain." -Level ERROR + exit 1 + } else { + Write-Host "The local server is part of the $($domainController.Site) site in the $($domainController.Domain) domain." + Write-Log -Message "The local server is part of the $($domainController.Site) site in the $($domainController.Domain) domain." -Level INFO + } +#endregion + +#region configure ADDS + #Enable Recycle bin + $recycleBinFeature = Get-ADOptionalFeature -Filter {Name -eq "Recycle Bin Feature"} -ErrorAction SilentlyContinue + if (-not $recycleBinFeature.EnabledScopes) { + Write-Host "The Recycle Bin feature is not enabled. Enabling it..." + Write-Log -Message "The Recycle Bin feature is not enabled. Enabling it..." -Level INFO + Enable-ADOptionalFeature -Identity "Recycle Bin Feature" -Scope ForestOrConfigurationSet -Target $domainController.Domain -Confirm:$false + Write-Host "The Recycle Bin feature has been enabled." + Write-Log -Message "The Recycle Bin feature has been enabled." -Level INFO + } else { + Write-Host "The Recycle Bin feature is already enabled." + Write-Log -Message "The Recycle Bin feature is already enabled." -Level INFO + } + + #Create a basic OU structure + $companyName = Read-Host "Please enter the company name" + $rootOU = Get-ADOrganizationalUnit -Filter {Name -eq $companyName} -ErrorAction SilentlyContinue + if (-not $rootOU) { + $rootOU = New-ADOrganizationalUnit -Name $companyName -Path $domainController.DefaultPartition -ProtectedFromAccidentalDeletion $true + Write-Host "The root OU '$companyName' has been created." + Write-Log -Message "The root OU '$companyName' has been created." -Level INFO + } else { + Write-Host "The root OU '$companyName' already exists." + Write-Log -Message "The root OU '$companyName' already exists." -Level INFO + } + + $ouList = @("Users", "Groups", "Computers", "Servers", "Service Accounts", "Administrators") + $rootOU = Get-ADOrganizationalUnit -Filter {Name -eq $companyName} -ErrorAction SilentlyContinue + foreach ($ou in $ouList) { + $newOU = Get-ADOrganizationalUnit -Filter "Name -eq '$ou' -and DistinguishedName -like '*,$($companyName),$($domainController.DefaultPartition)'" -ErrorAction SilentlyContinue + if (-not $newOU) { + $newOU = New-ADOrganizationalUnit -Name $ou -Path $rootOU.DistinguishedName -ProtectedFromAccidentalDeletion $true + Write-Host "The OU '$ou' has been created under '$companyName'." + Write-Log -Message "The OU '$ou' has been created under '$companyName'." + } else { + Write-Host "The OU '$ou' already exists under '$companyName'." + Write-Log -Message "The OU '$ou' already exists under '$companyName'." + } + } + Write-Host "The basic OU structure has been created or already exists." + Write-Log -Message "The basic OU structure has been created or already exists." +#endregion + +#region summary + Write-Summary "ADDS Structure configuration Summary:" + Write-Summary "---------------------------" + Write-Summary "Configuration date: $(Get-Date -Format "dd-MM-yyy HH:mm:ss")" + Write-Summary "Company Name: $companyName" + Write-Summary "Domain: $($domainController.Domain)" + Write-Summary "Site: $($domainController.Site)" + Write-Summary "Recycle Bin: Enabled" + Write-Summary "OU Structure: Created or already exists" + Write-Summary "---------------------------" +#endregion \ No newline at end of file diff --git a/Active Directory/Setup-ADForest.ps1 b/Active Directory/Setup-ADForest.ps1 new file mode 100644 index 0000000..d91642d --- /dev/null +++ b/Active Directory/Setup-ADForest.ps1 @@ -0,0 +1,214 @@ +<# +.SYNOPSIS + This PowerShell script configures a Windows server as a domain controller. + +.DESCRIPTION + The script performs the following tasks: + + 1. Checks for pending system reboots and creates a log directory if it doesn't exist. + 2. Validates the server's hostname and allows the user to edit it if necessary. + 3. Configures a static IP address if not already set. + 4. Installs required roles, including AD-Domain-Services, DNS, RSAT-AD-Tools, and gpmc. + 5. Configures Active Directory Domain Services (ADDS) Forest, including creating a DNS delegation, setting up the database, and configuring the domain mode and forest mode. + +.PARAMETER None + +.EXAMPLE + Run this script in PowerShell to configure a Windows server as a domain controller. + +.NOTES + This script requires administrative privileges to run. + Author: D.de Kooker - info@dcomputers.nl + Version: 1.0 + + DISCLAIMER: Use scripts at your own risk, if there is anything I can help you with I will try but I do not take responsibility for the way that anyone else uses my scripts. + Sharing is caring. Share your knowledge with the world so that everybody can learn from it. + +.LINK + The latest version can Always be found on my GIT page on the link below: + https://git.dcomputers.nl/Dcomputers/PowershellScripts +#> + +#region Global script settings and variables + $Version = "v1.0" + $logfilelocation = "$($MyInvocation.MyCommand.Path | Split-Path -Parent)\Logs" + $logfilename = "$(Get-Date -Format yyyyMMddHHmmss)-ADDS_Installation.log" + $summaryfilename = "$(Get-Date -Format yyyyMMddHHmmss)-ADDS_Installation_Summary.txt" +#endregion + +#region functions + function Initiate-Log { + # Get current user and session information + $username = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name + $computerName = $env:COMPUTERNAME + $sessionID = $pid + $date = Get-Date -Format "yyyy-MM-dd HH:mm:ss" + + # Write log header + $logHeader = "[$date] Log initiated by $username on $computerName (Session ID: $sessionID)" + Add-Content -Path $logfilelocation\$logfilename -Value "**********************" + Add-Content -Path $logfilelocation\$logfilename -Value "LogFile initiation" + Add-Content -Path $logfilelocation\$logfilename -Value "Start time: $date" + Add-Content -Path $logfilelocation\$logfilename -Value "Username: $username" + Add-Content -Path $logfilelocation\$logfilename -Value "Machine: $computerName" + Add-Content -Path $logfilelocation\$logfilename -Value "Process ID: $sessionID" + Add-Content -Path $logfilelocation\$logfilename -Value "Script Version: $Version" + Add-Content -Path $logfilelocation\$logfilename -Value "Script Source: https://git.dcomputers.nl/Dcomputers/PowershellScripts" + Add-Content -Path $logfilelocation\$logfilename -Value "**********************" + } + function Approve-Reboot { + Write-Host "The computer needs to be restarted in order to apply the changes" + Write-Host "Please confirm that you have read this message and are ready to reboot" + $confirmReboot = Read-Host "Type 'yes' to confirm" + if ($confirmReboot -eq "yes") { + Restart-Computer -Force + } else { + Write-Host "Reboot cancelled. Please restart the server manually to apply the changes" + exit 1 + } + } + + function Write-Log { + [CmdletBinding()] + Param ( + [Parameter(Mandatory=$true)] + [string]$Message, + [Parameter(Mandatory=$false)] + [ValidateSet("INFO", "WARNING", "ERROR")] + [string]$Level = "INFO" + ) + $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" + $logmessage = "[$timestamp] [$Level] $Message" + Add-Content -Path $logfilelocation\$logfilename -Value $logmessage + } + + function Write-Summary { + [CmdletBinding()] + Param ( + [Parameter(Mandatory=$true)] + [string]$Message + ) + Add-Content -Path $logfilelocation\$summaryfilename -Value $Message + } +#endregion + +#region prerequisites check + #Create log directory if not present + if (!(test-path $logfilelocation)) {mkdir $logfilelocation} + Initiate-Log + + #Check pending system reboot + if (Get-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Session Manager" -Name "PendingFileRenameOperations" -ErrorAction Ignore) { + Approve-Reboot + } + + #Server hostname validation + $hostname = [System.Net.Dns]::GetHostName() + Write-Host "Current hostname is: $hostname" + Write-Log -Message "Current hostname is: $hostname" -Level "INFO" + $editHostname = Read-Host "Do you want to edit the hostname? (y/n)" + if ($editHostname -eq "y") { + $newHostname = Read-Host "Enter new hostname" + Rename-Computer -NewName $newHostname -Force + Write-Host "Hostname changed to: $newHostname" + Write-Log -Message "Hostname changed to: $newHostname" -Level "INFO" + Write-Log -Message "Computer restart required after hostname change" -Level "WARNING" + [bool]$rebootneeded = $true + } + + #Static IP configuration + $staticIP = Get-NetIPAddress -AddressFamily IPv4 -PrefixOrigin Manual -ErrorAction SilentlyContinue + if ($staticIP) { + Write-Host "Static IP address is configured: $($staticIP.IPAddress)" + Write-Log -Message "Static IP address is configured: $($staticIP.IPAddress)" -Level "INFO" + } else { + Write-Host "No static IP address is configured, let's configure it" + Write-Log -Message "No static IP address is configured, let's configure it" -Level "INFO" + $ipAddress = Read-Host "Enter IP address" + $subnetMask = Read-Host "Enter subnet mask eg. 24" + $gateway = Read-Host "Enter gateway" + $dns = Read-Host "Enter DNS server address" + New-NetIPAddress -IPAddress $ipAddress -PrefixLength $subnetMask -InterfaceIndex $((Get-NetAdapter).ifIndex) -DefaultGateway $gateway + Set-DnsClientServerAddress -InterfaceIndex $((Get-NetAdapter).ifIndex) + Write-Host "Static IP address configured: $ipAddress" + Write-Log -Message "Static IP address configured: $ipAddress" -Level "INFO" + } + + #Reboot server if needed + if ($rebootneeded) { + Approve-Reboot + } +#endregion + +#region install required roles and features + #Check the required roles + $requiredRoles = @("AD-Domain-Services", "DNS", "RSAT-AD-Tools", "gpmc") + $progress = 0 + Write-Progress -Activity "Installing required roles" -Status "Starting installation" -PercentComplete $progress + foreach ($role in $requiredRoles) { + if (!(Get-WindowsFeature -Name $role).Installed) { + Write-Host "Installing required role: $role" + Write-Log -Message "Installing required role: $role" -Level "INFO" + Write-Progress -Activity "Installing required roles" -Status "Installing $role" -PercentComplete $progress + Add-WindowsFeature -Name $role -IncludeAllSubFeature -IncludeManagementTools + $progress += (100 / $requiredRoles.Count) + [bool]$rebootneeded = $true + } + } + Write-Progress -Activity "Installing required roles" -Status "Completed" -PercentComplete 100 + + #Reboot server if needed + if ($rebootneeded) { + Approve-Reboot + } + + #All role requirements are met + Write-Host "All role requirements are met continuing Forest configuration" + Write-Log -Message "All role requirements are met continuing Forest configuration" -Level "INFO" +#endregion + +#region configure ADDS + #Gather the required information + $domainName = Read-Host "Enter the domain name" + $domainNetBiosName = ($domainName.Split(".")[0] | ForEach-Object { $_.ToUpper() }) + + #Confirm domain name and netbios name + Write-Host "Domain name: $domainName" + Write-Log -Message "Domain name: $domainName" -Level "INFO" + Write-Host "NetBIOS name: $domainNetBiosName" + Write-Log -Message "NetBIOS name: $domainNetBiosName" -Level "INFO" + $confirmDomainInfo = Read-Host "Is this information correct? (y/n)" + if ($confirmDomainInfo -eq "y") { + #Perform the installation + Import-Module ADDSDeployment + Install-ADDSForest ` + -CreateDnsDelegation:$false ` + -DatabasePath "C:\Windows\NTDS" ` + -DomainMode "WinThreshold" ` + -DomainName $domainName ` + -DomainNetbiosName $domainNetBiosName ` + -ForestMode "WinThreshold" ` + -InstallDns:$true ` + -LogPath "C:\Windows\NTDS" ` + -NoRebootOnCompletion:$true ` + -SysvolPath "C:\Windows\SYSVOL" ` + -Force:$true + } else { + Write-Host "Domain configuration cancelled. Please restart the script to continue." + Write-Log -Message "Domain configuration cancelled. Please restart the script to continue." -Level "WARNING" + exit 1 + } + Write-Host "ADDS Forest configuration completed successfully" + Write-Log -Message "ADDS Forest configuration completed successfully" -Level "INFO" +#endregion + +#region summary + Write-Summary "ADDS Forest configuration Summary:" + Write-Summary "---------------------------" + Write-Summary "Configuration date: $(Get-Date -Format "dd-MM-yyy HH:mm:ss")" + Write-Summary "Domain name: $domainName" + Write-Summary "NetBIOS name: $domainNetBiosName" + Write-Summary "---------------------------" + + Approve-Reboot +#endregion \ No newline at end of file