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>
234 lines
8.6 KiB
PowerShell
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
|