Last active
November 7, 2024 10:06
-
-
Save raandree/f75ebdc585013017fd3f1a5d900e0210 to your computer and use it in GitHub Desktop.
JEA: Register a new restricted endpoint with JEA roles
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Unlock-AAAccount | |
{ | |
param( | |
[Parameter(Mandatory)] | |
[string]$Identity | |
) | |
try | |
{ | |
$user = Get-ADUser -Identity $Identity | |
} | |
catch | |
{ | |
Write-Error "The user '$Identity' does not exist" | |
return | |
} | |
if (-not $user.LockedOut) | |
{ | |
Write-Error "The user '$Identity' is not locked out" | |
return | |
} | |
try | |
{ | |
$user | Unlock-ADAccount | |
$message = "User '$Identity' has been unlocked" | |
} | |
catch | |
{ | |
$message = "Failed to unlock user '$Identity'" | |
} | |
$logName = '{0:yyMMdd}ActivityLog.txt' -f (Get-Date) | |
Write-Host $message | |
'{0:yyMMdd HH:mm:ss} {1,20} {2} | {3}' -f (Get-Date), $MyInvocation.MyCommand.Name, $PSSenderInfo.ConnectedUser, $message | | |
Out-File C:\PowerShellTranscripts\$jeaModuleName\$logName -Append | |
} | |
function Reset-AAPassword | |
{ | |
param( | |
[Parameter(Mandatory)] | |
[string]$Identity | |
) | |
try | |
{ | |
$user = Get-ADUser -Identity $Identity | |
} | |
catch | |
{ | |
Write-Error "The user '$Identity' does not exist" | |
return | |
} | |
Add-Type -AssemblyName System.Web | |
$password = [System.Web.Security.Membership]::GeneratePassword(10,4) | |
$securePassword = $password | ConvertTo-SecureString -AsPlainText -Force | |
$user | Set-ADAccountPassword -NewPassword $securePassword | |
$user | Set-ADUser -ChangePasswordAtLogon $true | |
$message = "Password for user '$Identity' has been changed to '$password'. Password must be changed at next logon." | |
$logName = '{0:yyMMdd}ActivityLog.txt' -f (Get-Date) | |
Write-Host $message | |
'{0:yyMMdd HH:mm:ss} {1,20} {2} | {3}' -f (Get-Date), $MyInvocation.MyCommand.Name, $PSSenderInfo.ConnectedUser, $message | | |
Out-File C:\PowerShellTranscripts\$jeaModuleName\$logName -Append | |
} | |
function Add-AADnsServerRecordA | |
{ | |
param( | |
[Parameter(Mandatory)] | |
[string]$Name, | |
[Parameter(Mandatory)] | |
[ipaddress]$IpAddress, | |
[Parameter(Mandatory)] | |
[ValidateSet('contoso.com', 'tailspintoys.com')] | |
[string]$ZoneName | |
) | |
$dnsZone = Get-DnsServerZone -Name $ZoneName -ErrorAction SilentlyContinue | |
if (-not $dnsZone) | |
{ | |
Write-Error "DNS Zone '$ZoneName' does not exist" | |
return | |
} | |
$dnsRecord = Get-DnsServerResourceRecord -Name $Name -ZoneName $ZoneName -RRType A -ErrorAction SilentlyContinue | |
if ($dnsRecord) | |
{ | |
Write-Error "The DNS A record '$Name' does already exist in zone '$ZoneName'" | |
return | |
} | |
Add-DnsServerResourceRecordA -Name $Name -ZoneName $ZoneName -IPv4Address $IpAddress | |
$message = "DNS A record '$Name' created in zone '$ZoneName'" | |
$logName = '{0:yyMMdd}ActivityLog.txt' -f (Get-Date) | |
Write-Host $message | |
'{0:yyMMdd HH:mm:ss} {1,20} {2} | {3}' -f (Get-Date), $MyInvocation.MyCommand.Name, $PSSenderInfo.ConnectedUser, $message | | |
Out-File C:\PowerShellTranscripts\$jeaModuleName\$logName -Append | |
} | |
function Get-AAUser | |
{ | |
param( | |
[Parameter(Mandatory)] | |
[string]$Identity | |
) | |
try | |
{ | |
$user = Get-ADUser -Identity $Identity -Properties * | |
} | |
catch | |
{ | |
Write-Error "The user '$Identity' does not exist" | |
return | |
} | |
$user | |
} | |
function UserManagement | |
{ | |
$roleName = $MyInvocation.MyCommand.Name | |
$modulePath = Join-Path -Path $env:ProgramFiles -ChildPath "WindowsPowerShell\Modules\$jeaModuleName" | |
$rcFolder = Join-Path -Path $modulePath -ChildPath "RoleCapabilities" | |
if (-not (Test-Path -Path $rcFolder)) | |
{ | |
mkdir -Path $rcFolder -Force | Out-Null | |
} | |
New-PSRoleCapabilityFile -Path $rcFolder\$roleName.psrc ` | |
-ModulesToImport Microsoft.PowerShell.Management, ActiveDirectory ` | |
-VisibleProviders FileSystem ` | |
-VisibleCmdlets Get-Command, Get-Help ` | |
-FunctionDefinitions ` | |
@{ Name = 'Unlock-AAAccount'; ScriptBlock = (Get-Command Unlock-AAAccount).ScriptBlock }, | |
@{ Name = 'Reset-AAPassword'; ScriptBlock = (Get-Command Reset-AAPassword).ScriptBlock } | |
} | |
function UserInfo | |
{ | |
$roleName = $MyInvocation.MyCommand.Name | |
New-PSRoleCapabilityFile -Path C:\$roleName.psrc ` | |
-ModulesToImport Microsoft.PowerShell.Management, ActiveDirectory ` | |
-VisibleProviders FileSystem ` | |
-VisibleCmdlets Get-Command, Get-Help ` | |
-FunctionDefinitions ` | |
@{ Name = 'Get-AAUser'; ScriptBlock = (Get-Command Get-AAUser).ScriptBlock } | |
# Create the RoleCapabilities folder and copy in the PSRC file | |
$modulePath = Join-Path -Path $env:ProgramFiles -ChildPath "WindowsPowerShell\Modules\$jeaModuleName" | |
$rcFolder = Join-Path -Path $modulePath -ChildPath "RoleCapabilities" | |
if (-not (Test-Path -Path $rcFolder)) | |
{ | |
mkdir -Path $rcFolder -Force | Out-Null | |
} | |
Copy-Item -Path C:\$roleName.psrc -Destination $rcFolder | |
} | |
function DnsManagement | |
{ | |
$roleName = $MyInvocation.MyCommand.Name | |
New-PSRoleCapabilityFile -Path C:\$roleName.psrc ` | |
-ModulesToImport Microsoft.PowerShell.Management, DnsServer ` | |
-VisibleProviders FileSystem ` | |
-VisibleCmdlets Get-Command, Get-Help ` | |
-FunctionDefinitions ` | |
@{ Name = 'Add-AADnsServerRecordA'; ScriptBlock = (Get-Command Add-AADnsServerRecordA).ScriptBlock } | |
# Create the RoleCapabilities folder and copy in the PSRC file | |
$modulePath = Join-Path -Path $env:ProgramFiles -ChildPath "WindowsPowerShell\Modules\$jeaModuleName" | |
$rcFolder = Join-Path -Path $modulePath -ChildPath "RoleCapabilities" | |
if (-not (Test-Path -Path $rcFolder)) | |
{ | |
mkdir -Path $rcFolder -Force | Out-Null | |
} | |
Copy-Item -Path C:\$roleName.psrc -Destination $rcFolder | |
} | |
function Register-CustomPSSessionConfiguration | |
{ | |
param( | |
[string[]]$AllowedPrincipals, | |
[Parameter(Mandatory)] | |
[string]$EndpointName | |
) | |
if (-not (Test-Path -Path C:\PowerShellTranscripts)) | |
{ | |
mkdir -Path C:\PowerShellTranscripts | Out-Null | |
} | |
New-PSSessionConfigurationFile -Path c:\$EndpointName.pssc ` | |
-SessionType RestrictedRemoteServer ` | |
-LanguageMode NoLanguage ` | |
-RunAsVirtualAccount ` | |
-ExecutionPolicy Unrestricted ` | |
-TranscriptDirectory "C:\PowerShellTranscripts\$EndpointName" ` | |
-RoleDefinitions @{ | |
"$($env:USERDOMAIN)\UserManagement" = @{ RoleCapabilities = 'UserManagement', 'UserInfo' } | |
"$($env:USERDOMAIN)\DnsManagement" = @{ RoleCapabilities = 'UserInfo', 'DnsManagement' } | |
} | |
Register-PSSessionConfiguration -Name $EndpointName -Path C:\$EndpointName.pssc -Force | |
$pssc = Get-PSSessionConfiguration -Name $EndpointName | |
$psscSd = New-Object System.Security.AccessControl.CommonSecurityDescriptor($false, $false, $pssc.SecurityDescriptorSddl) | |
foreach ($allowedPrincipal in $AllowedPrincipals) | |
{ | |
$account = New-Object System.Security.Principal.NTAccount($allowedPrincipal) | |
$accessType = "Allow" | |
$accessMask = 268435456 | |
$inheritanceFlags = "None" | |
$propagationFlags = "None" | |
$psscSd.DiscretionaryAcl.AddAccess($accessType,$account.Translate([System.Security.Principal.SecurityIdentifier]),$accessMask,$inheritanceFlags,$propagationFlags) | |
} | |
Set-PSSessionConfiguration -Name $EndpointName -SecurityDescriptorSddl $psscSd.GetSddlForm("All") -Force | |
# Create a folder for the module | |
$modulePath = Join-Path -Path $env:ProgramFiles -ChildPath "WindowsPowerShell\Modules\$jeaModuleName" | |
if (-not (Test-Path -Path $modulePath)) | |
{ | |
mkdir -Path $modulePath | Out-Null | |
} | |
# Create an empty script module and module manifest. At least one file in the module folder must have the same name as the folder itself. | |
$path = Join-Path -Path $modulePath -ChildPath "$jeaModuleName.psm1" | |
if (-not (Test-Path -Path $path)) | |
{ | |
New-Item -ItemType File -Path $path | Out-Null | |
} | |
$path = Join-Path -Path $modulePath -ChildPath "$jeaModuleName.psd1" | |
if (-not (Test-Path -Path $path)) | |
{ | |
New-ModuleManifest -Path $path -RootModule "$jeaModuleName.psm1" | |
} | |
} | |
Install-WindowsFeature -Name RSAT-Role-Tools, RSAT-DNS-Server | |
$password = 'Somepass1' | ConvertTo-SecureString -AsPlainText -Force | |
$jeaModuleName = 'Support' | |
$endpointName = 'Support' | |
$modulePath = Join-Path -Path $env:ProgramFiles -ChildPath "WindowsPowerShell\Modules\$jeaModuleName" | |
Remove-Item -Path $modulePath -Recurse -Force -ErrorAction SilentlyContinue | |
UserManagement | |
UserInfo | |
DnsManagement | |
$rootDse = Get-ADRootDSE | |
if (-not ($ou = Get-ADOrganizationalUnit -Identity "OU=JeaTest,$($rootDse.defaultNamingContext)")) | |
{ | |
$ou = New-ADOrganizationalUnit -Name JeaTest -ProtectedFromAccidentalDeletion $false -PassThru | |
} | |
if (-not ($dnsManagementRoleGroup = Get-ADGroup -Identity DnsManagement)) | |
{ | |
$dnsManagementRoleGroup = New-ADGroup -Name DnsManagement -GroupScope Global -Path $ou -PassThru | |
} | |
if (-not ($userManagementRoleGroup = Get-ADGroup -Identity UserManagement)) | |
{ | |
$userManagementRoleGroup = New-ADGroup -Name UserManagement -GroupScope Global -Path $ou -PassThru | |
} | |
if (-not ($dnsManager = Get-ADUser -Identity Bob)) | |
{ | |
$dnsManager = New-ADUser -Name Bob -AccountPassword $password -Enabled $true -Path $ou -PassThru | |
} | |
if (-not ($userManager = Get-ADUser -Identity Sue)) | |
{ | |
$userManager = New-ADUser -Name Sue -AccountPassword $password -Enabled $true -Path $ou -PassThru | |
} | |
$dnsManagementRoleGroup | Add-ADGroupMember -Members $dnsManager | |
$userManagementRoleGroup | Add-ADGroupMember -Members $userManager | |
Register-CustomPSSessionConfiguration -EndpointName $endpointName -AllowedPrincipals "$($env:USERDOMAIN)\Domain Users" | |
return | |
Get-PSSessionCapability -ConfigurationName Support -Username Sue | |
Get-PSSessionCapability -ConfigurationName Support -Username Bob | |
#http://weiler.16mb.com/2016/10/17/jea-just-enough-administration-part-2/ | |
#https://sid-500.com/2018/02/11/powershell-implementing-just-enough-administration-jea-step-by-step/ | |
#https://blogs.technet.microsoft.com/datacentersecurity/2017/03/07/step-by-step-creating-a-jea-endpoint-for-dns-management/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment