Files
claudetools/clients/cascades-tucson/docs/migration/scripts/phase2-file-shares.ps1
Howard Enos 8d975c1b44 import: ingested 160 files from C:\Users\howar\Clients
Howard's personal MSP client documentation folder imported into shared
ClaudeTools repo via /import command. Scope:

Clients (structured MSP docs under clients/<name>/docs/):
- anaise       (NEW)  - 13 files
- cascades-tucson     - 47 files merged (existing had only reports/)
- dataforth           - 18 files merged (alongside incident reports)
- instrumental-music-center - 14 files merged
- khalsa       (NEW)  - 22 files, multi-site (camden, river)
- kittle       (NEW)  - 16 files incl. fix-pdf-preview, gpo-intranet-zone
- lens-auto-brokerage (NEW) - 3 files (name matches SOPS vault)
- _client_template    - 13-file scaffold for new clients

MSP tooling (projects/msp-tools/):
- msp-audit-scripts/ - server_audit.ps1, workstation_audit.ps1, README
- utilities/         - clean_printer_ports, win11_upgrade,
                       screenconnect-toolbox-commands

Credential handling:
- Extracted 1 inline password (Anaise DESKTOP-O8GF4SD / david)
  to SOPS vault: clients/anaise/desktop-o8gf4sd.sops.yaml
- Redacted overview.md with vault reference pattern
- Scanned all 160 files for keys/tokens/connection strings -
  no other credentials found

Skipped:
- Cascades/.claude/settings.local.json (per-machine config)
- Source-root CLAUDE.md (personal, claudetools has its own)
- scripts/server_audit.ps1 and workstation_audit.ps1 at source root
  (identical duplicates of msp-audit-scripts versions)

Memory updates:
- reference_client_docs_structure.md (layout, conventions, active list)
- reference_msp_audit_scripts.md (locations, ScreenConnect 80-char rule)

Session log: session-logs/2026-04-16-howard-client-docs-import.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 19:43:58 -07:00

234 lines
8.6 KiB
PowerShell

#Requires -RunAsAdministrator
<#
.SYNOPSIS
Phase 2.4: Set up file share permissions on CS-SERVER.
.DESCRIPTION
Creates SMB shares for folders synced from Synology and sets NTFS
permissions using security groups from phase2-ad-setup.ps1.
Run on CS-SERVER via ScreenConnect AFTER phase2-sync-synology.ps1.
.NOTES
Permissions mapped from Synology NAS permission report.
Existing shares (Culinary, IT, Receptionist, directoryshare) are updated.
New shares (Management, SalesDept, Server, chat, Public, homes) are created.
SaleShare (old) is left alone — SalesDept is the real folder.
#>
Import-Module ActiveDirectory -ErrorAction Stop
Write-Host "=== Phase 2.4: File Share Permissions ===" -ForegroundColor Cyan
Write-Host ""
$DestRoot = "D:\Shares"
# --- Share definitions ---
# Each entry: share Name, folder Path, security group for RW, description
$shares = @(
# Synology-sourced shares (new on CS-SERVER)
@{
Name = "Management"
Path = "$DestRoot\Management"
Group = "CASCADES\SG-Management-RW"
Desc = "Management share (from Synology)"
},
@{
Name = "SalesDept"
Path = "$DestRoot\SalesDept"
Group = "CASCADES\SG-Sales-RW"
Desc = "Sales department (from Synology)"
},
@{
Name = "Server"
Path = "$DestRoot\Server"
Group = "CASCADES\SG-Server-RW"
Desc = "Server/office share (from Synology)"
},
@{
Name = "chat"
Path = "$DestRoot\chat"
Group = "CASCADES\SG-Chat-RW"
Desc = "Chat share (from Synology)"
},
@{
Name = "Public"
Path = "$DestRoot\Public"
Group = $null # Everyone gets access
Desc = "Public share (all users)"
},
# Existing shares on CS-SERVER (update permissions)
@{
Name = "Culinary"
Path = "$DestRoot\Culinary"
Group = "CASCADES\SG-Culinary-RW"
Desc = "Culinary department"
},
@{
Name = "IT"
Path = "$DestRoot\IT"
Group = "CASCADES\SG-IT-RW"
Desc = "IT department"
},
@{
Name = "Receptionist"
Path = "$DestRoot\Receptionist"
Group = "CASCADES\SG-Receptionist-RW"
Desc = "Receptionist/front desk"
},
@{
Name = "directoryshare"
Path = "$DestRoot\directoryshare"
Group = "CASCADES\SG-Directory-RW"
Desc = "Directory share"
}
)
# --- Process each share ---
foreach ($s in $shares) {
Write-Host "`n--- $($s.Name) ---" -ForegroundColor Yellow
# Check path exists
if (-not (Test-Path $s.Path)) {
Write-Host " [SKIP] Path not found: $($s.Path) — run phase2-sync-synology.ps1 first" -ForegroundColor Yellow
continue
}
# Set NTFS permissions
try {
$acl = Get-Acl $s.Path
$acl.SetAccessRuleProtection($true, $false) # Break inheritance
# SYSTEM: Full Control
$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule(
"SYSTEM", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow"
)))
# Domain Admins: Full Control
$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule(
"CASCADES\Domain Admins", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow"
)))
if ($s.Group) {
# Specific group: Modify
$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule(
$s.Group, "Modify", "ContainerInherit,ObjectInherit", "None", "Allow"
)))
# Read-only group
$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule(
"CASCADES\SG-AllShares-RO", "ReadAndExecute", "ContainerInherit,ObjectInherit", "None", "Allow"
)))
} else {
# Public share: Authenticated Users get Modify
$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule(
"Authenticated Users", "Modify", "ContainerInherit,ObjectInherit", "None", "Allow"
)))
}
Set-Acl $s.Path $acl
Write-Host " [OK] NTFS permissions set" -ForegroundColor Green
}
catch {
Write-Host " [ERROR] NTFS permissions failed: $_" -ForegroundColor Red
continue
}
# Create or update SMB share
try {
$existingShare = Get-SmbShare -Name $s.Name -ErrorAction SilentlyContinue
if (-not $existingShare) {
New-SmbShare -Name $s.Name -Path $s.Path -FullAccess "Authenticated Users" -Description $s.Desc
Write-Host " [OK] Created SMB share: \\CS-SERVER\$($s.Name)" -ForegroundColor Green
} else {
Grant-SmbShareAccess -Name $s.Name -AccountName "Authenticated Users" -AccessRight Full -Force | Out-Null
Write-Host " [OK] Updated SMB share: \\CS-SERVER\$($s.Name)" -ForegroundColor Green
}
}
catch {
Write-Host " [ERROR] SMB share failed: $_" -ForegroundColor Red
}
}
# --- Set up homes share for folder redirection ---
Write-Host "`n--- homes (Folder Redirection) ---" -ForegroundColor Yellow
$homesPath = "$DestRoot\homes"
if (Test-Path $homesPath) {
# Special permissions for homes: users create their own folders
try {
$acl = Get-Acl $homesPath
$acl.SetAccessRuleProtection($true, $false)
# SYSTEM: Full Control
$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule(
"SYSTEM", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow"
)))
# Domain Admins: Full Control
$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule(
"CASCADES\Domain Admins", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow"
)))
# Authenticated Users: Create folders only (at root level)
# This lets folder redirection auto-create user folders
$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule(
"Authenticated Users", "CreateDirectories", "ThisFolder", "None", "Allow"
)))
$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule(
"Authenticated Users", "ListDirectory", "ThisFolder", "None", "Allow"
)))
# CREATOR OWNER: Full Control on subfolders/files only
# This gives each user full control of their own folder
$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule(
"CREATOR OWNER", "FullControl", "ContainerInherit,ObjectInherit", "InheritOnly", "Allow"
)))
Set-Acl $homesPath $acl
Write-Host " [OK] NTFS permissions set (folder redirection ready)" -ForegroundColor Green
}
catch {
Write-Host " [ERROR] homes NTFS permissions failed: $_" -ForegroundColor Red
}
# Create SMB share
try {
$existingShare = Get-SmbShare -Name "homes" -ErrorAction SilentlyContinue
if (-not $existingShare) {
New-SmbShare -Name "homes" -Path $homesPath -FullAccess "Authenticated Users" `
-Description "User home folders (folder redirection)" `
-FolderEnumerationMode AccessBased # ABE: users only see their own folder
Write-Host " [OK] Created SMB share: \\CS-SERVER\homes (ABE enabled)" -ForegroundColor Green
} else {
Write-Host " [SKIP] homes share already exists" -ForegroundColor DarkGray
}
}
catch {
Write-Host " [ERROR] homes SMB share failed: $_" -ForegroundColor Red
}
} else {
Write-Host " [SKIP] $homesPath not found — run phase2-sync-synology.ps1 first" -ForegroundColor Yellow
}
# --- Update main Shares share ---
Write-Host "`n--- Updating main Shares ---" -ForegroundColor Yellow
try {
$sharesShare = Get-SmbShare -Name "Shares" -ErrorAction SilentlyContinue
if ($sharesShare) {
Grant-SmbShareAccess -Name "Shares" -AccountName "Authenticated Users" -AccessRight Full -Force | Out-Null
Write-Host " [OK] Updated Shares SMB permissions" -ForegroundColor Green
}
}
catch {
Write-Host " [WARN] Could not update Shares: $_" -ForegroundColor Yellow
}
# --- Summary ---
Write-Host "`n=== File Share Summary ===" -ForegroundColor Cyan
Write-Host "`nAll SMB Shares:" -ForegroundColor Yellow
Get-SmbShare | Where-Object { $_.Path -like "D:\*" } |
Select-Object Name, Path, Description |
Format-Table -AutoSize -Wrap
Write-Host "=== File Share Setup Complete ===" -ForegroundColor Cyan
Write-Host "Next: Run phase2-print-server.ps1" -ForegroundColor Green