Logo Pastebin.fr
Pastebin

Retrouvez, créez et partagez vos snippets en temps réel.

script

[CmdletBinding()]
param(
  [Parameter(Mandatory)]
  [ValidateSet("DC1","PostDC1","DC2","FileServer")]
  [string]$Role
)

Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"

function Assert-Admin {
  $isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()
            ).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
  if (-not $isAdmin) { throw "Run this script in an elevated PowerShell session." }
}

function Install-Features {
  param([string[]]$Names)
  Import-Module ServerManager -ErrorAction Stop
  $missing = $Names | Where-Object { -not (Get-WindowsFeature $_).Installed }
  if ($missing) {
    Install-WindowsFeature -Name $missing -IncludeManagementTools | Out-Null
  }
}

function New-StrongPassword {
  param([int]$Length = 20)
  # Generates a random password with upper, lower, digits, special
  $upper = "ABCDEFGHJKLMNPQRSTUVWXYZ"
  $lower = "abcdefghijkmnopqrstuvwxyz"
  $digits = "23456789"
  $spec  = "!@#$%^&*()-_=+[]{}:,.?"
  $all   = ($upper + $lower + $digits + $spec).ToCharArray()

  $rand = New-Object System.Security.Cryptography.RNGCryptoServiceProvider
  function Get-RandInt([int]$max) {
    $b = New-Object byte[] 4
    $rand.GetBytes($b)
    [Math]::Abs([BitConverter]::ToInt32($b,0)) % $max
  }

  $chars = @()
  $chars += $upper[ (Get-RandInt $upper.Length) ]
  $chars += $lower[ (Get-RandInt $lower.Length) ]
  $chars += $digits[(Get-RandInt $digits.Length)]
  $chars += $spec[  (Get-RandInt $spec.Length)  ]
  while ($chars.Count -lt $Length) { $chars += $all[(Get-RandInt $all.Length)] }
  $chars = $chars | Sort-Object { Get-RandInt 100000 }
  -join $chars
}

function Get-Config {
  # Adjust these to your lab network
  [pscustomobject]@{
    DomainFqdn = "BaaS.com"
    Netbios    = "BAAS"
    Site1      = "Montreal"
    Site2      = "Quebec"

    # DHCP config (update for your subnet)
    DhcpScopeNetwork = "192.168.50.0"
    DhcpScopeMask    = "255.255.255.0"
    DhcpRangeStart   = "192.168.50.10"
    DhcpRangeEnd     = "192.168.50.254"
    DhcpExclusionStart = "192.168.50.1"
    DhcpExclusionEnd   = "192.168.50.9"
    DhcpLeaseDays      = 3
    DhcpRouter         = "192.168.50.1"
    DnsServers         = @("192.168.50.10") # DC1 IP

    # File services
    DataRoot     = "D:\DATA"
    HomeRoot     = "D:\USERS"
    ShareHost    = $env:COMPUTERNAME # set to FileServer name if separate, else DC1
    SharePrefix  = "" # keep empty for \\HOST\Marketing etc

    # Admin account settings
    BuiltinAdminNewName = "adm-rid500"
    NamedAdminGivenName = "Admin"
    NamedAdminSurname   = "BaaS"
    NamedAdminSam       = "adm.baas"
    # You will be prompted for the named admin password securely.

    # User naming convention: first initial + surname, normalized
    # Example: Linda Brown -> lbrown ; Valérie Tremblay -> vtremblay
    UserUPNSuffix = "BaaS.com"
  }
}

function Normalize-Sam {
  param([string]$FirstName,[string]$LastName)
  $raw = ($FirstName.Substring(0,1) + $LastName).ToLowerInvariant()
  # remove accents and non letters
  $norm = $raw.Normalize([Text.NormalizationForm]::FormD)
  $sb = New-Object System.Text.StringBuilder
  foreach ($c in $norm.ToCharArray()) {
    $cat = [Globalization.CharUnicodeInfo]::GetUnicodeCategory($c)
    if ($cat -ne [Globalization.UnicodeCategory]::NonSpacingMark) { [void]$sb.Append($c) }
  }
  $clean = ($sb.ToString() -replace "[^a-z0-9\.]","")
  $clean
}

function Ensure-ADModules {
  Import-Module ActiveDirectory -ErrorAction Stop
  Import-Module GroupPolicy -ErrorAction Stop
}

function Ensure-Folder {
  param([string]$Path)
  if (-not (Test-Path $Path)) { New-Item -ItemType Directory -Path $Path -Force | Out-Null }
}

function Set-NTFSPermissionsExact {
  param(
    [string]$Path,
    [bool]$DisableInheritance,
    [System.Security.AccessControl.FileSystemAccessRule[]]$Rules
  )
  $acl = Get-Acl -Path $Path

  if ($DisableInheritance) {
    # disable inheritance and remove inherited rules
    $acl.SetAccessRuleProtection($true, $false)
    foreach ($r in $acl.Access) { $acl.RemoveAccessRule($r) | Out-Null }
  }

  foreach ($r in $Rules) { $acl.AddAccessRule($r) | Out-Null }
  Set-Acl -Path $Path -AclObject $acl
}

function New-Rule {
  param([string]$Identity,[string]$Rights,[string]$Type = "Allow",[string]$Inherit = "ContainerInherit,ObjectInherit",[string]$Prop = "None")
  $inheritFlags = [System.Security.AccessControl.InheritanceFlags]$Inherit
  $propFlags    = [System.Security.AccessControl.PropagationFlags]$Prop
  $accessType   = [System.Security.AccessControl.AccessControlType]$Type
  $fsr          = [System.Security.AccessControl.FileSystemRights]$Rights
  New-Object System.Security.AccessControl.FileSystemAccessRule($Identity,$fsr,$inheritFlags,$propFlags,$accessType)
}

function Create-GPOAndLink {
  param(
    [string]$Name,
    [string]$LinkDn,
    [int]$Order = 1
  )
  $gpo = Get-GPO -Name $Name -ErrorAction SilentlyContinue
  if (-not $gpo) { $gpo = New-GPO -Name $Name }
  $link = Get-GPInheritance -Target $LinkDn
  $already = $link.GpoLinks | Where-Object { $_.DisplayName -eq $Name }
  if (-not $already) {
    New-GPLink -Name $Name -Target $LinkDn -LinkEnabled Yes -Order $Order | Out-Null
  }
  Get-GPO -Name $Name
}

function Get-GpoSysvolPath {
  param([Guid]$GpoId,[string]$DomainFqdn)
  $domain = $DomainFqdn
  "\\$domain\SYSVOL\$domain\Policies\{$GpoId}"
}

function Write-DrivesXml {
  param(
    [string]$GpoSysvol,
    [hashtable[]]$DriveMaps
  )
  $dir = Join-Path $GpoSysvol "User\Preferences\Drives"
  Ensure-Folder $dir
  $xmlPath = Join-Path $dir "Drives.xml"

  $doc = New-Object System.Xml.XmlDocument
  $doc.AppendChild($doc.CreateXmlDeclaration("1.0","utf-8",$null)) | Out-Null

  $root = $doc.CreateElement("Drives")
  $root.SetAttribute("clsid","{CCB7E38E-0DDB-4B3C-8B9E-000000000000}") | Out-Null
  $doc.AppendChild($root) | Out-Null

  foreach ($m in $DriveMaps) {
    # Item
    $drive = $doc.CreateElement("Drive")
    $drive.SetAttribute("clsid","{C631DF4C-088F-4156-B058-4375F0853CD8}") | Out-Null
    $drive.SetAttribute("name",$m.Name) | Out-Null
    $drive.SetAttribute("image","2") | Out-Null
    $drive.SetAttribute("changed",(Get-Date).ToString("yyyy-MM-dd HH:mm:ss")) | Out-Null
    $drive.SetAttribute("uid","{" + ([guid]::NewGuid().Guid) + "}") | Out-Null
    $drive.SetAttribute("userContext","1") | Out-Null
    $drive.SetAttribute("removePolicy","0") | Out-Null

    $props = $doc.CreateElement("Properties")
    $props.SetAttribute("action","U") | Out-Null
    $props.SetAttribute("thisDrive",$m.Letter) | Out-Null
    $props.SetAttribute("allDrives","NOCHANGE") | Out-Null
    $props.SetAttribute("userName","") | Out-Null
    $props.SetAttribute("path",$m.Path) | Out-Null
    $props.SetAttribute("label",$m.Label) | Out-Null
    $props.SetAttribute("persistent","1") | Out-Null
    $props.SetAttribute("useLetter","1") | Out-Null
    $props.SetAttribute("letter",$m.Letter.TrimEnd(":")) | Out-Null
    $props.SetAttribute("disconnect","0") | Out-Null
    $props.SetAttribute("showAll","0") | Out-Null
    $props.SetAttribute("useUNC","0") | Out-Null
    $props.SetAttribute("hide","0") | Out-Null
    $props.SetAttribute("noReconnect","0") | Out-Null
    $drive.AppendChild($props) | Out-Null

    # Optional targeting by security group
    if ($m.ContainsKey("GroupSid") -and $m.GroupSid) {
      $filters = $doc.CreateElement("Filters")
      $fg = $doc.CreateElement("FilterGroup")
      $fg.SetAttribute("clsid","{3610EDA5-77EF-11D2-8DC5-00C04FA31A66}") | Out-Null
      $fg.SetAttribute("name","") | Out-Null
      $fg.SetAttribute("sid",$m.GroupSid) | Out-Null
      $fg.SetAttribute("userContext","1") | Out-Null
      $fg.SetAttribute("not","0") | Out-Null
      $fg.SetAttribute("bool","AND") | Out-Null
      $filters.AppendChild($fg) | Out-Null
      $drive.AppendChild($filters) | Out-Null
    }

    $root.AppendChild($drive) | Out-Null
  }

  $doc.Save($xmlPath)
}

function Write-GptTmplUserRights {
  param(
    [string]$GpoSysvol,
    [string[]]$DenyLogonLocallySids,
    [string[]]$DenyLogonRdpSids
  )
  $secDir = Join-Path $GpoSysvol "Machine\Microsoft\Windows NT\SecEdit"
  Ensure-Folder $secDir
  $infPath = Join-Path $secDir "GptTmpl.inf"

  # Minimal security template for user rights assignment
  $content = @()
  $content += "[Unicode]"
  $content += "Unicode=yes"
  $content += "[Version]"
  $content += "signature=`"`$CHICAGO`$`""
  $content += "Revision=1"
  $content += "[Privilege Rights]"
  # SeDenyInteractiveLogonRight: Deny log on locally
  if ($DenyLogonLocallySids.Count -gt 0) {
    $content += "SeDenyInteractiveLogonRight = " + ($DenyLogonLocallySids -join ",")
  }
  # SeDenyRemoteInteractiveLogonRight: Deny log on through Remote Desktop Services
  if ($DenyLogonRdpSids.Count -gt 0) {
    $content += "SeDenyRemoteInteractiveLogonRight = " + ($DenyLogonRdpSids -join ",")
  }

  Set-Content -Path $infPath -Value $content -Encoding Unicode
}

function Set-DomainPasswordAndLockoutPolicy {
  param([string]$DomainFqdn)
  Ensure-ADModules

  Set-ADDefaultDomainPasswordPolicy -Identity $DomainFqdn `
    -MinPasswordLength 12 `
    -ComplexityEnabled $true `
    -PasswordHistoryCount 5 `
    -MaxPasswordAge (New-TimeSpan -Days 180) `
    -MinPasswordAge (New-TimeSpan -Days 1) `
    -ReversibleEncryptionEnabled $false

  # Lockout: 3 attempts, 15 minutes duration, reset counter 15 minutes
  Set-ADDefaultDomainPasswordPolicy -Identity $DomainFqdn `
    -LockoutThreshold 3 `
    -LockoutDuration (New-TimeSpan -Minutes 15) `
    -LockoutObservationWindow (New-TimeSpan -Minutes 15)
}

function Set-DnsHardening {
  # Secure dynamic updates for AD integrated zones
  Import-Module DnsServer -ErrorAction Stop
  $zones = Get-DnsServerZone | Where-Object { $_.IsDsIntegrated -eq $true -and $_.ZoneType -eq "Primary" }
  foreach ($z in $zones) {
    Set-DnsServerPrimaryZone -Name $z.ZoneName -SecureSecondaries NoTransfer | Out-Null
    Set-DnsServerZone -Name $z.ZoneName -DynamicUpdate Secure | Out-Null
  }
}

function Configure-Dhcp {
  param($cfg)
  Import-Module DhcpServer -ErrorAction Stop

  # Authorize DHCP in AD (requires domain admin)
  try { Add-DhcpServerInDC -DnsName "$($env:COMPUTERNAME).$($cfg.DomainFqdn)" -IPAddress $cfg.DnsServers[0] | Out-Null } catch {}

  # Create scope if missing
  $scope = Get-DhcpServerv4Scope -ErrorAction SilentlyContinue | Where-Object { $_.ScopeId -eq $cfg.DhcpScopeNetwork }
  if (-not $scope) {
    Add-DhcpServerv4Scope -Name "BaaS Scope" -StartRange $cfg.DhcpRangeStart -EndRange $cfg.DhcpRangeEnd -SubnetMask $cfg.DhcpScopeMask -State Active | Out-Null
  }

  # Exclusions 1-9
  Add-DhcpServerv4ExclusionRange -ScopeId $cfg.DhcpScopeNetwork -StartRange $cfg.DhcpExclusionStart -EndRange $cfg.DhcpExclusionEnd -ErrorAction SilentlyContinue | Out-Null

  # Lease duration
  Set-DhcpServerv4Scope -ScopeId $cfg.DhcpScopeNetwork -LeaseDuration (New-TimeSpan -Days $cfg.DhcpLeaseDays) | Out-Null

  # Options: router and DNS
  Set-DhcpServerv4OptionValue -ScopeId $cfg.DhcpScopeNetwork -Router $cfg.DhcpRouter -DnsServer $cfg.DnsServers -DnsDomain $cfg.DomainFqdn | Out-Null
}

function Build-OUAndGroupsAndUsers {
  param($cfg)

  Ensure-ADModules

  $domainDn = (Get-ADDomain).DistinguishedName

  # OU layout:
  # OU=BaaS,DC=...
  #   OU=Montreal
  #     OU=Users, OU=Computers, OU=Groups
  #   OU=Quebec
  #     OU=Users, OU=Computers, OU=Groups
  $rootOuName = "BaaS"
  $rootOuDn = "OU=$rootOuName,$domainDn"

  if (-not (Get-ADOrganizationalUnit -LDAPFilter "(distinguishedName=$rootOuDn)" -ErrorAction SilentlyContinue)) {
    New-ADOrganizationalUnit -Name $rootOuName -Path $domainDn -ProtectedFromAccidentalDeletion $true | Out-Null
  }

  foreach ($site in @($cfg.Site1,$cfg.Site2)) {
    $siteDn = "OU=$site,$rootOuDn"
    if (-not (Get-ADOrganizationalUnit -LDAPFilter "(distinguishedName=$siteDn)" -ErrorAction SilentlyContinue)) {
      New-ADOrganizationalUnit -Name $site -Path $rootOuDn -ProtectedFromAccidentalDeletion $true | Out-Null
    }
    foreach ($child in @("Users","Computers","Groups")) {
      $childDn = "OU=$child,OU=$site,$rootOuDn"
      if (-not (Get-ADOrganizationalUnit -LDAPFilter "(distinguishedName=$childDn)" -ErrorAction SilentlyContinue)) {
        New-ADOrganizationalUnit -Name $child -Path $siteDn -ProtectedFromAccidentalDeletion $true | Out-Null
      }
    }
  }

  # Role groups (domain wide)
  $groupsOuDn = "OU=Groups,OU=$($cfg.Site1),$rootOuDn" # keep groups in Montreal OU, but groups are domain wide
  $roleGroups = @(
    "GG_PDG",
    "GG_Informatique",
    "GG_Finance",
    "GG_Marketing",
    "GG_RH",
    "GG_Production",
    "GG_Direction",
    "GG_ServiceClients",
    "GG_TousEmployes"
  )

  foreach ($g in $roleGroups) {
    if (-not (Get-ADGroup -Filter "SamAccountName -eq '$g'" -ErrorAction SilentlyContinue)) {
      New-ADGroup -Name $g -SamAccountName $g -GroupScope Global -GroupCategory Security -Path $groupsOuDn | Out-Null
    }
  }

  # Users list from document
  $users = @(
    # Montreal
    @{ First="Linda";     Last="Brown";        Role="PDG";               Site=$cfg.Site1 }
    @{ First="Chris";     Last="Martinez";     Role="Informatique";      Site=$cfg.Site1 }
    @{ First="Paula";     Last="Rasmussen";    Role="Finance";           Site=$cfg.Site1 }
    @{ First="Nicole";    Last="Dion";         Role="Marketing";         Site=$cfg.Site1 }
    @{ First="Valerie";   Last="Tremblay";     Role="RH";                Site=$cfg.Site1 }
    @{ First="Donald";    Last="Campbell";     Role="RH";                Site=$cfg.Site1 }
    @{ First="Mark";      Last="Harlan";       Role="Production";        Site=$cfg.Site1 }
    @{ First="Donna";     Last="Jewett";       Role="Finance";           Site=$cfg.Site1 }
    @{ First="Freddie";   Last="Burkhardt";    Role="Direction";         Site=$cfg.Site1 }
    @{ First="James";     Last="Williams";     Role="Finance";           Site=$cfg.Site1 }
    @{ First="Christine"; Last="Mondou";       Role="Marketing";         Site=$cfg.Site1 }
    @{ First="Charles";   Last="Montgomery";   Role="ServiceClients";    Site=$cfg.Site1 }
    @{ First="Jeanie";    Last="Spencer";      Role="ServiceClients";    Site=$cfg.Site1 }
    @{ First="Sandra";    Last="McCarthy";     Role="ServiceClients";    Site=$cfg.Site1 }

    # Quebec
    @{ First="Justine";   Last="West";         Role="Direction";         Site=$cfg.Site2 }
    @{ First="Laura";     Last="Young";        Role="Finance";           Site=$cfg.Site2 }
    @{ First="Sandra";    Last="Novello";      Role="ServiceClients";    Site=$cfg.Site2 }
    @{ First="Tony";      Last="Brossard";     Role="ServiceClients";    Site=$cfg.Site2 }
    @{ First="Kristina";  Last="Lewis";        Role="Direction";         Site=$cfg.Site2 }
    @{ First="Paul";      Last="Samson";       Role="Finance";           Site=$cfg.Site2 }
    @{ First="Thomas";    Last="Levesque";     Role="ServiceClients";    Site=$cfg.Site2 }
    @{ First="Ronald";    Last="Turcotte";     Role="Marketing";         Site=$cfg.Site2 }
    @{ First="Michael";   Last="Richard";      Role="ServiceClients";    Site=$cfg.Site2 }
    @{ First="Robert";    Last="Jarrett";      Role="Marketing";         Site=$cfg.Site2 }
  )

  # Create users with random initial password, force change at logon
  foreach ($u in $users) {
    $sam = Normalize-Sam -FirstName $u.First -LastName $u.Last
    $upn = "$sam@$($cfg.UserUPNSuffix)"
    $path = "OU=Users,OU=$($u.Site),OU=$($rootOuName),$domainDn"

    $existing = Get-ADUser -Filter "SamAccountName -eq '$sam'" -ErrorAction SilentlyContinue
    if (-not $existing) {
      $pwd = New-StrongPassword -Length 18
      $sec = ConvertTo-SecureString $pwd -AsPlainText -Force
      New-ADUser -Name "$($u.First) $($u.Last)" `
        -GivenName $u.First -Surname $u.Last `
        -SamAccountName $sam `
        -UserPrincipalName $upn `
        -Path $path `
        -Enabled $true `
        -AccountPassword $sec `
        -ChangePasswordAtLogon $true | Out-Null

      Write-Host "Created user $sam with initial password (store it securely): $pwd"
    }

    # Membership: everyone in GG_TousEmployes, plus role group
    Add-ADGroupMember -Identity "GG_TousEmployes" -Members $sam -ErrorAction SilentlyContinue | Out-Null

    switch ($u.Role) {
      "PDG"            { Add-ADGroupMember -Identity "GG_PDG" -Members $sam -ErrorAction SilentlyContinue | Out-Null }
      "Informatique"   { Add-ADGroupMember -Identity "GG_Informatique" -Members $sam -ErrorAction SilentlyContinue | Out-Null }
      "Finance"        { Add-ADGroupMember -Identity "GG_Finance" -Members $sam -ErrorAction SilentlyContinue | Out-Null }
      "Marketing"      { Add-ADGroupMember -Identity "GG_Marketing" -Members $sam -ErrorAction SilentlyContinue | Out-Null }
      "RH"             { Add-ADGroupMember -Identity "GG_RH" -Members $sam -ErrorAction SilentlyContinue | Out-Null }
      "Production"     { Add-ADGroupMember -Identity "GG_Production" -Members $sam -ErrorAction SilentlyContinue | Out-Null }
      "Direction"      { Add-ADGroupMember -Identity "GG_Direction" -Members $sam -ErrorAction SilentlyContinue | Out-Null }
      "ServiceClients" { Add-ADGroupMember -Identity "GG_ServiceClients" -Members $sam -ErrorAction SilentlyContinue | Out-Null }
    }
  }
}

function Harden-BuiltinDomainAdministrator {
  param($cfg)

  Ensure-ADModules
  $rid500 = Get-ADUser -Filter 'ObjectSID -like "*-500"' -Properties ObjectSID
  if (-not $rid500) { throw "RID 500 account not found." }

  # Rename (CN) and set sAMAccountName and display name
  if ($rid500.SamAccountName -ne $cfg.BuiltinAdminNewName) {
    $newCn = $cfg.BuiltinAdminNewName
    Rename-ADObject -Identity $rid500.DistinguishedName -NewName $newCn
    Set-ADUser -Identity $rid500.ObjectSID.Value `
      -SamAccountName $cfg.BuiltinAdminNewName `
      -DisplayName "Domain Administrator (renamed)" `
      -Description "Built-in RID 500 account renamed for hardening"
  }

  # Set a strong password (printed once, you must store it securely)
  $newPwd = New-StrongPassword -Length 24
  Set-ADAccountPassword -Identity $rid500.ObjectSID.Value -Reset -NewPassword (ConvertTo-SecureString $newPwd -AsPlainText -Force)
  Write-Host "RID 500 account password set (store it securely): $newPwd"

  # Create a GPO that denies interactive and RDP logon for this account
  $domainDn = (Get-ADDomain).DistinguishedName
  $rootOuDn = "OU=BaaS,$domainDn"
  $gpo = Create-GPOAndLink -Name "GPO - Deny logon for RID500" -LinkDn $rootOuDn -Order 1

  $gpoSysvol = Get-GpoSysvolPath -GpoId $gpo.Id -DomainFqdn $cfg.DomainFqdn
  $sid = $rid500.ObjectSID.Value
  Write-GptTmplUserRights -GpoSysvol $gpoSysvol `
    -DenyLogonLocallySids @("*$sid") `
    -DenyLogonRdpSids @("*$sid")
}

function Create-NamedDomainAdmin {
  param($cfg)

  Ensure-ADModules
  $domainDn = (Get-ADDomain).DistinguishedName
  $path = "OU=Users,OU=$($cfg.Site1),OU=BaaS,$domainDn"

  $existing = Get-ADUser -Filter "SamAccountName -eq '$($cfg.NamedAdminSam)'" -ErrorAction SilentlyContinue
  if (-not $existing) {
    $sec = Read-Host "Enter password for named admin $($cfg.NamedAdminSam)" -AsSecureString
    New-ADUser -Name "$($cfg.NamedAdminGivenName) $($cfg.NamedAdminSurname)" `
      -GivenName $cfg.NamedAdminGivenName -Surname $cfg.NamedAdminSurname `
      -SamAccountName $cfg.NamedAdminSam `
      -UserPrincipalName "$($cfg.NamedAdminSam)@$($cfg.UserUPNSuffix)" `
      -Path $path `
      -Enabled $true `
      -AccountPassword $sec `
      -PasswordNeverExpires $false `
      -ChangePasswordAtLogon $false | Out-Null
  }

  Add-ADGroupMember -Identity "Domain Admins" -Members $cfg.NamedAdminSam -ErrorAction SilentlyContinue | Out-Null
  Write-Host "Named domain admin ensured: $($cfg.NamedAdminSam)"
}

function Configure-FileSharesAndPermissions {
  param($cfg)

  Ensure-ADModules

  # Folders
  Ensure-Folder $cfg.DataRoot
  Ensure-Folder $cfg.HomeRoot

  $folders = @(
    "Marketing","Finance","Direction","ServiceClients","RH","Production","Public"
  )
  foreach ($f in $folders) { Ensure-Folder (Join-Path $cfg.DataRoot $f) }

  # Special subfolders
  Ensure-Folder (Join-Path (Join-Path $cfg.DataRoot "ServiceClients") "VIP")
  Ensure-Folder (Join-Path (Join-Path $cfg.DataRoot "RH") "Confidentiel")

  # Shares (use simple names to match drive maps)
  Install-Features -Names @("FS-FileServer")
  foreach ($f in $folders) {
    $shareName = $f
    $path = Join-Path $cfg.DataRoot $f
    if (-not (Get-SmbShare -Name $shareName -ErrorAction SilentlyContinue)) {
      New-SmbShare -Name $shareName -Path $path -FullAccess "BUILTIN\Administrators" | Out-Null
    }
  }

  if (-not (Get-SmbShare -Name "Users" -ErrorAction SilentlyContinue)) {
    New-SmbShare -Name "Users" -Path $cfg.HomeRoot -FullAccess "BUILTIN\Administrators" | Out-Null
  }

  # Recommended approach: SMB share perms wide, enforce with NTFS
  # NTFS base rules per requirements:
  # - Role folder: role group Modify
  # - PDG and Informatique: admin rights to all except VIP and Confidentiel
  # - Direction: Finance RW, ServiceClients Modify, RH RW
  # - Production: Marketing RW
  # - RH: ServiceClients RW
  # - Everyone (all staff): Public Modify
  # Special:
  # - VIP: only Direction and ServiceClients Modify
  # - Confidentiel: RH + PDG Modify, Informatique Read, others none

  $domain = (Get-ADDomain).DNSRoot
  function DN([string]$name) { "$domain\$name" }

  $admins = @(
    New-Rule -Identity (DN "GG_PDG") -Rights "FullControl",
    New-Rule -Identity (DN "GG_Informatique") -Rights "FullControl",
    New-Rule -Identity "BUILTIN\Administrators" -Rights "FullControl",
    New-Rule -Identity "SYSTEM" -Rights "FullControl"
  )

  # Helper to set base ACL for a folder with role Modify plus cross-access rules
  function Set-RoleFolderAcl([string]$folderName) {
    $path = Join-Path $cfg.DataRoot $folderName
    $rules = @()
    $rules += $admins
    switch ($folderName) {
      "Marketing" {
        $rules += New-Rule -Identity (DN "GG_Marketing") -Rights "Modify"
        $rules += New-Rule -Identity (DN "GG_Production") -Rights "Modify"
      }
      "Finance" {
        $rules += New-Rule -Identity (DN "GG_Finance") -Rights "Modify"
        $rules += New-Rule -Identity (DN "GG_Direction") -Rights "Modify"
      }
      "Direction" {
        $rules += New-Rule -Identity (DN "GG_Direction") -Rights "Modify"
      }
      "ServiceClients" {
        $rules += New-Rule -Identity (DN "GG_ServiceClients") -Rights "Modify"
        $rules += New-Rule -Identity (DN "GG_Direction") -Rights "Modify"
        $rules += New-Rule -Identity (DN "GG_RH") -Rights "Modify"
      }
      "RH" {
        $rules += New-Rule -Identity (DN "GG_RH") -Rights "Modify"
        $rules += New-Rule -Identity (DN "GG_Direction") -Rights "Modify"
      }
      "Production" {
        $rules += New-Rule -Identity (DN "GG_Production") -Rights "Modify"
      }
      "Public" {
        $rules += New-Rule -Identity (DN "GG_TousEmployes") -Rights "Modify"
      }
    }
    Set-NTFSPermissionsExact -Path $path -DisableInheritance $true -Rules $rules
  }

  foreach ($f in $folders) { Set-RoleFolderAcl -folderName $f }

  # Special folder: VIP
  $vipPath = Join-Path (Join-Path $cfg.DataRoot "ServiceClients") "VIP"
  $vipRules = @(
    New-Rule -Identity (DN "GG_Direction") -Rights "Modify",
    New-Rule -Identity (DN "GG_ServiceClients") -Rights "Modify",
    New-Rule -Identity "BUILTIN\Administrators" -Rights "FullControl",
    New-Rule -Identity "SYSTEM" -Rights "FullControl"
  )
  Set-NTFSPermissionsExact -Path $vipPath -DisableInheritance $true -Rules $vipRules

  # Special folder: Confidentiel
  $confPath = Join-Path (Join-Path $cfg.DataRoot "RH") "Confidentiel"
  $confRules = @(
    New-Rule -Identity (DN "GG_RH") -Rights "Modify",
    New-Rule -Identity (DN "GG_PDG") -Rights "Modify",
    New-Rule -Identity (DN "GG_Informatique") -Rights "ReadAndExecute",
    New-Rule -Identity "BUILTIN\Administrators" -Rights "FullControl",
    New-Rule -Identity "SYSTEM" -Rights "FullControl"
  )
  Set-NTFSPermissionsExact -Path $confPath -DisableInheritance $true -Rules $confRules

  # Home folders per user (U:)
  $allUsers = Get-ADUser -Filter * -SearchBase ( (Get-ADDomain).DistinguishedName ) -Properties SamAccountName,HomeDirectory,HomeDrive
  foreach ($u in $allUsers) {
    if ($u.SamAccountName -in @("krbtgt",$cfg.NamedAdminSam,$cfg.BuiltinAdminNewName)) { continue }
    $userDir = Join-Path $cfg.HomeRoot $u.SamAccountName
    Ensure-Folder $userDir

    # ACL: user full control, admins full control, system full control
    $homeRules = @(
      New-Rule -Identity "$domain\$($u.SamAccountName)" -Rights "FullControl",
      New-Rule -Identity "BUILTIN\Administrators" -Rights "FullControl",
      New-Rule -Identity "SYSTEM" -Rights "FullControl"
    )
    Set-NTFSPermissionsExact -Path $userDir -DisableInheritance $true -Rules $homeRules

    $unc = "\\$($cfg.ShareHost)\Users\$($u.SamAccountName)"
    Set-ADUser -Identity $u.SamAccountName -HomeDirectory $unc -HomeDrive "U:" | Out-Null
  }

  Write-Host "File shares and NTFS permissions configured."
}

function Create-GPOs {
  param($cfg)

  Ensure-ADModules
  $domainDn = (Get-ADDomain).DistinguishedName
  $rootOuDn = "OU=BaaS,$domainDn"

  # 1) GPO for drive mappings (M,F,I,S,R,O,P) and home drive is already in AD user profile (U:)
  $gpoDrive = Create-GPOAndLink -Name "GPO - Drive mappings" -LinkDn $rootOuDn -Order 2
  $sysvolDrive = Get-GpoSysvolPath -GpoId $gpoDrive.Id -DomainFqdn $cfg.DomainFqdn

  $domain = (Get-ADDomain).DNSRoot
  function SidOf([string]$groupSam) { (Get-ADGroup -Identity $groupSam).SID.Value }

  $maps = @(
    @{ Name="Marketing (M:)";     Letter="M:"; Path="\\$($cfg.ShareHost)\Marketing";     Label="Marketing";     GroupSid=(SidOf "GG_Marketing") }
    @{ Name="Finance (F:)";       Letter="F:"; Path="\\$($cfg.ShareHost)\Finance";       Label="Finance";       GroupSid=(SidOf "GG_Finance") }
    @{ Name="Direction (I:)";     Letter="I:"; Path="\\$($cfg.ShareHost)\Direction";     Label="Direction";     GroupSid=(SidOf "GG_Direction") }
    @{ Name="ServiceClients (S:)";Letter="S:"; Path="\\$($cfg.ShareHost)\ServiceClients";Label="ServiceClients";GroupSid=(SidOf "GG_ServiceClients") }
    @{ Name="RH (R:)";            Letter="R:"; Path="\\$($cfg.ShareHost)\RH";            Label="RH";            GroupSid=(SidOf "GG_RH") }
    @{ Name="Production (O:)";    Letter="O:"; Path="\\$($cfg.ShareHost)\Production";    Label="Production";    GroupSid=(SidOf "GG_Production") }
    @{ Name="Public (P:)";        Letter="P:"; Path="\\$($cfg.ShareHost)\Public";        Label="Public";        GroupSid=(SidOf "GG_TousEmployes") }
  )
  Write-DrivesXml -GpoSysvol $sysvolDrive -DriveMaps $maps

  # 2) GPO for workstation standard desktop restrictions + privacy + autorun + lock screen + disable guest via startup script
  $gpoWs = Create-GPOAndLink -Name "GPO - Workstations baseline" -LinkDn $rootOuDn -Order 3

  # User settings (HKCU) via GPO registry values
  # Remove Run menu
  Set-GPRegistryValue -Name $gpoWs.DisplayName -Key "HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer" -ValueName "NoRun" -Type DWord -Value 1
  # Restrict system tools (Task Manager, Registry Tools, CMD)
  Set-GPRegistryValue -Name $gpoWs.DisplayName -Key "HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System" -ValueName "DisableTaskMgr" -Type DWord -Value 1
  Set-GPRegistryValue -Name $gpoWs.DisplayName -Key "HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System" -ValueName "DisableRegistryTools" -Type DWord -Value 1
  Set-GPRegistryValue -Name $gpoWs.DisplayName -Key "HKCU\Software\Policies\Microsoft\Windows\System" -ValueName "DisableCMD" -Type DWord -Value 1
  # Restrict recycle bin properties
  Set-GPRegistryValue -Name $gpoWs.DisplayName -Key "HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer" -ValueName "NoPropertiesRecycleBin" -Type DWord -Value 1

  # Screen lock after 15 minutes (user side)
  Set-GPRegistryValue -Name $gpoWs.DisplayName -Key "HKCU\Software\Policies\Microsoft\Windows\Control Panel\Desktop" -ValueName "ScreenSaveActive" -Type String -Value "1"
  Set-GPRegistryValue -Name $gpoWs.DisplayName -Key "HKCU\Software\Policies\Microsoft\Windows\Control Panel\Desktop" -ValueName "ScreenSaveTimeOut" -Type String -Value "900"
  Set-GPRegistryValue -Name $gpoWs.DisplayName -Key "HKCU\Software\Policies\Microsoft\Windows\Control Panel\Desktop" -ValueName "ScreenSaverIsSecure" -Type String -Value "1"

  # Computer settings (HKLM)
  # Disable autorun for removable media
  Set-GPRegistryValue -Name $gpoWs.DisplayName -Key "HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer" -ValueName "NoDriveTypeAutoRun" -Type DWord -Value 255

  # Lock screen policy (machine side backup)
  Set-GPRegistryValue -Name $gpoWs.DisplayName -Key "HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System" -ValueName "InactivityTimeoutSecs" -Type DWord -Value 900

  # Reduce diagnostic data (note: some editions enforce minimums)
  Set-GPRegistryValue -Name $gpoWs.DisplayName -Key "HKLM\Software\Policies\Microsoft\Windows\DataCollection" -ValueName "AllowTelemetry" -Type DWord -Value 0

  # Disable activity history
  Set-GPRegistryValue -Name $gpoWs.DisplayName -Key "HKLM\Software\Policies\Microsoft\Windows\System" -ValueName "PublishUserActivities" -Type DWord -Value 0
  Set-GPRegistryValue -Name $gpoWs.DisplayName -Key "HKLM\Software\Policies\Microsoft\Windows\System" -ValueName "UploadUserActivities" -Type DWord -Value 0

  # "Disable PowerShell" (practical approach):
  # - Block script execution via policy
  Set-GPRegistryValue -Name $gpoWs.DisplayName -Key "HKLM\Software\Policies\Microsoft\Windows\PowerShell" -ValueName "EnableScripts" -Type DWord -Value 0
  # - Optional: add Software Restriction Policy entries would be more complex; this blocks scripts but not interactive console.

  # Disable local Guest account using startup script in the GPO (reliable across Pro editions)
  $sysvolWs = Get-GpoSysvolPath -GpoId $gpoWs.Id -DomainFqdn $cfg.DomainFqdn
  $startupDir = Join-Path $sysvolWs "Machine\Scripts\Startup"
  Ensure-Folder $startupDir
  $startupScript = Join-Path $startupDir "Disable-Guest.cmd"
  Set-Content -Path $startupScript -Value "@echo off`r`nnet user Guest /active:no" -Encoding ASCII

  # Register startup script in scripts.ini
  $iniDir = Join-Path $sysvolWs "Machine\Scripts"
  Ensure-Folder $iniDir
  $iniPath = Join-Path $iniDir "scripts.ini"
  $ini = @()
  $ini += "[Startup]"
  $ini += "0CmdLine=Disable-Guest.cmd"
  $ini += "0Parameters="
  Set-Content -Path $iniPath -Value $ini -Encoding ASCII

  # 3) BitLocker GPO (store recovery keys in AD)
  $gpoBl = Create-GPOAndLink -Name "GPO - BitLocker (AD recovery)" -LinkDn $rootOuDn -Order 4
  # Core BitLocker policy keys (Windows Components\BitLocker Drive Encryption)
  # Enforce AD backup for OS drive recovery information
  Set-GPRegistryValue -Name $gpoBl.DisplayName -Key "HKLM\Software\Policies\Microsoft\FVE" -ValueName "OSActiveDirectoryBackup" -Type DWord -Value 1
  Set-GPRegistryValue -Name $gpoBl.DisplayName -Key "HKLM\Software\Policies\Microsoft\FVE" -ValueName "OSRequireActiveDirectoryBackup" -Type DWord -Value 1
  Set-GPRegistryValue -Name $gpoBl.DisplayName -Key "HKLM\Software\Policies\Microsoft\FVE" -ValueName "OSRecovery" -Type DWord -Value 1
  Set-GPRegistryValue -Name $gpoBl.DisplayName -Key "HKLM\Software\Policies\Microsoft\FVE" -ValueName "OSManageDRA" -Type DWord -Value 0
  # Require TPM (typical baseline; adjust if your VMs do not have vTPM)
  Set-GPRegistryValue -Name $gpoBl.DisplayName -Key "HKLM\Software\Policies\Microsoft\FVE" -ValueName "UseTPM" -Type DWord -Value 1
  Set-GPRegistryValue -Name $gpoBl.DisplayName -Key "HKLM\Software\Policies\Microsoft\FVE" -ValueName "UseTPMPIN" -Type DWord -Value 0
  Set-GPRegistryValue -Name $gpoBl.DisplayName -Key "HKLM\Software\Policies\Microsoft\FVE" -ValueName "UseTPMKey" -Type DWord -Value 0
  Set-GPRegistryValue -Name $gpoBl.DisplayName -Key "HKLM\Software\Policies\Microsoft\FVE" -ValueName "UseAdvancedStartup" -Type DWord -Value 1

  Write-Host "GPOs created: Drive mappings, Workstations baseline, BitLocker."
}

Assert-Admin
$cfg = Get-Config

switch ($Role) {
  "DC1" {
    # Install AD DS + DNS + DHCP now, then create the forest/domain
    Install-Features -Names @("AD-Domain-Services","DNS","DHCP","GPMC","RSAT-AD-Tools")

    Import-Module ADDSDeployment -ErrorAction Stop

    Write-Host "Promoting this server to new forest/domain $($cfg.DomainFqdn)."
    $dsrm = Read-Host "Enter DSRM password" -AsSecureString

    Install-ADDSForest `
      -DomainName $cfg.DomainFqdn `
      -DomainNetbiosName $cfg.Netbios `
      -SafeModeAdministratorPassword $dsrm `
      -InstallDNS:$true `
      -Force:$true

    Write-Host "DC1 promotion initiated. The server will reboot automatically."
  }

  "PostDC1" {
    Ensure-ADModules

    # Domain password and lockout policies
    Set-DomainPasswordAndLockoutPolicy -DomainFqdn $cfg.DomainFqdn

    # Harden built-in RID 500 admin and deny interactive/remote logon
    Harden-BuiltinDomainAdministrator -cfg $cfg

    # Create named Domain Admin
    Create-NamedDomainAdmin -cfg $cfg

    # DNS hardening for AD integrated zones and secure dynamic updates only
    Set-DnsHardening

    # DHCP config (lease 3 days, exclusions 1-9, range 10-254)
    Configure-Dhcp -cfg $cfg

    # Users, OUs, groups for Montreal and Quebec
    Build-OUAndGroupsAndUsers -cfg $cfg

    # File shares and permissions (DC1 acts as file server per project)
    Configure-FileSharesAndPermissions -cfg $cfg

    # GPOs: drive mapping, workstation baseline, BitLocker
    Create-GPOs -cfg $cfg

    Write-Host "Post-DC1 configuration completed."
  }

  "DC2" {
    Install-Features -Names @("AD-Domain-Services","RSAT-AD-Tools")
    Import-Module ADDSDeployment -ErrorAction Stop

    $cred = Get-Credential -Message "Enter Domain Admin credentials to promote DC2 into $($cfg.DomainFqdn)"
    $dsrm = Read-Host "Enter DSRM password for DC2" -AsSecureString

    Install-ADDSDomainController `
      -DomainName $cfg.DomainFqdn `
      -Credential $cred `
      -SafeModeAdministratorPassword $dsrm `
      -InstallDns:$false `
      -Force:$true

    Write-Host "DC2 promotion initiated. The server will reboot automatically."
  }

  "FileServer" {
    # Optional separate file server
    Install-Features -Names @("FS-FileServer","GPMC","RSAT-AD-Tools")
    Ensure-ADModules

    Configure-FileSharesAndPermissions -cfg $cfg
    Write-Host "File server configuration completed."
  }
}

Créé il y a 1 semaine.

Rechercher un Pastebin

Aucun paste trouvé.