Jeremy Gifford's Website


Scripts

I mostly created this page to play around with some tools that are supposed to auto-format script code with pretty HTML colors. The powershell code is formated with the Powershell ISE extension, IsePack, Copy-ColoredAsHtml function. You'd think it would be plug-n-play but I ran into some issues as IsePack support seems to be abandoned.

I wrote a small php class to pull each script source code from my private GitLab server via HTTP/S. The main con to this method is the overhead of the web server having to request the code from multiple externally hosted pages before generating and returning this page. Additionally, the source code blocks will not be populated if this webserver cannot contact my GitLab server for whatever reason. The benefit of this method, however, is that the source code is always current with the GitLab repositories without having to manually sync via a method like git from this web server. I might introduce a caching-like functionality to the php code as a fallback.


Fix Hyper-V VM Permissions v1

This script came about because of an interesting facet of Hyper-V's NTFS file system access control restrictions to a virtual machine's files. Hyper V creates a unique Window's SID for each VM upon creation and then assigns that SID permissions to the necessary files (like the .vhd) on the host system. In Windows, all identities, such as user accounts, are assigned a unique 'security identifier' (SID) that will remain static for the life of that identity. A running virtual machine will be accessing its associated .vhd and config files from the context of its specific SID.

The problem with Hyper-V's permission scheme is if the file system permissions get lost/reset, (like from copying the files to another storage drive/system as a crude backup) the restored virtual machine will no longer be able to start. It is necessary to set the files as read/write for everyone or lookup the correct SID and apply it via the command line (the SID will not be found in the GUI). This script uses the later method and is to be executed once the virtual machine is imported into Hyper-V's registry.

  1. Write-Host "`nFix Hyper-V VM Permissions v1 `n`nThis interactive script allows you replace the VM specific NTFS permissions on each VM's resourse files.`n`n" -ForegroundColor Yellow
  2. function Import_Dependencies(){
  3.     try{
  4.         Import-Module Hyper-V;
  5.     } catch {
  6.         Write-Host "Powershell could not import the required Hyper-V module. Please ensure Hyper-V is installed on this machine.";
  7.         Read-Host "Press any key to exit..."
  8.         Exit;
  9.     }
  10. }
  11. function Confirm_Admin_Privilege(){
  12.     #Test if the script is being run as Administrator and exit if false.
  13.     If (-Not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')){
  14.         Write-Host "You do not have rights to run this script! Please re-run this script as an Administrator!";
  15.         Read-Host "Press any key to exit..."
  16.         Exit;
  17.     }
  18. }
  19. function Expand_VHD_Parent_Paths(){
  20.     param(
  21.         [Parameter(Mandatory=$true)]
  22.         [String]$path
  23.         )
  24.      
  25.     $parentPath = (Get-VHD -Path $path -ErrorAction Stop).ParentPath;
  26.     $pathTree = New-Object System.Collections.Generic.List[System.String];
  27.     $pathTree.Add($path);
  28.     while(-not [String]::IsNullOrEmpty($parentPath)){
  29.         $pathTree.Add($parentPath);
  30.         $parentPath = (Get-VHD -Path $parentPath).ParentPath;
  31.     }
  32.     return $pathTree.ToArray();
  33. }
  34. function Build_VM_List(){
  35.     $vms = New-Object System.Collections.Generic.List[System.Object];
  36.     foreach($vm in $(Get-VM)) {
  37.         $harddrives = New-Object System.Collections.Generic.List[System.Array];
  38.         foreach($drivePath in $($vm | Select -ExpandProperty HardDrives | select -property Path)){
  39.             $harddrives.Add((Expand_VHD_Parent_Paths -Path $drivePath.path));
  40.         }
  41.         $harddrives = $harddrives.ToArray();
  42.         $vms.Add( [PSCustomObject]@{
  43.                     'Name' =  $vm.VMName;
  44.                     'ID' = $vm.VMId;
  45.                     'HDDs' = $harddrives;
  46.                     }
  47.                 )
  48.     }
  49.     return $vms.ToArray();
  50. }
  51. function Add_Permissions(){
  52.     param(
  53.         [Parameter(Mandatory=$true)]
  54.         [Array]$virtualMachineList
  55.         )
  56.     Write-Host "`nBeginning to process registered virtual machines:`n"
  57.     foreach($vm in $virtualMachineList){
  58.         Write-Host $vm.Name;
  59.         foreach($drive in $vm.HDDs){
  60.             foreach($path in $drive){
  61.                 try{
  62.                     $null = Invoke-Expression -Command:"icacls '$path' /grant 'NT VIRTUAL MACHINE\$($vm.ID):(F)'";
  63.                     $account = New-Object System.Security.Principal.NTAccount($vm.ID);
  64.                     $acl = Get-Acl -Path $path;
  65.                     $acl.SetOwner($account);
  66.                     Set-Acl -Path $path -AclObject $acl;
  67.                 }
  68.                 catch{
  69.                     Write-Host $Error[0].Exception.GetType().FullName $Error[0] -ForegroundColor Red;
  70.                 }
  71.             }
  72.         }
  73.     }
  74.     return;
  75. }
  76. #Call functions to begin execution
  77. Confirm_Admin_Privilege;
  78. Import_Dependencies;
  79. Add_Permissions -virtualMachineList $(Build_VM_List);
  80. Exit;

Poll AD Users v6

  1. Write-Host "`nPoll AD Users v6 `n`nThis script queries all user accounts in Active Directory and generates a CSV listing STIG pertinent attributes.`n`n"
  2. function Test_If_Admin(){ <#Test if the script is being run as Administrator and exit if false. #>
  3.     If (([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')){
  4.         return true;
  5.     }Else{
  6.         Write-Host "You do not have rights to run this script! Please re-run this script as an Administrator!"
  7.         Read-Host "Press Enter to exit..."
  8.         Exit;
  9.     }
  10. }
  11. function Poll_Users(){
  12.     #Create an array to store the custom objects that will be created below
  13.     $output = @()
  14.     
  15.     #Get the full AD user list with all attributes (properties)
  16.     $users = Get-ADUser -filter * -Properties *
  17.     
  18.     $userCount = $users.Count
  19.     $WACount=0
  20.     $SACount=0
  21.     $DACount=0
  22.     $EACount=0
  23.     $MTAAllowCount=0
  24.     $MTABlockCount=0
  25.     $smartcardCount=0
  26.     $passExpiredCount=0
  27.     $passNeverExpiresCount=0
  28.     $enabledCount=0
  29.     $lockedCount=0
  30.     $disableAccounts=$false
  31.     $response=''
  32.     #Iterate through each AD user to test the associated individual properties
  33.     foreach($user in $users)
  34.     {
  35.         $isWA = ''
  36.         $isSA = ''
  37.         $isDA = ''
  38.         $isEA = ''
  39.         $isMTA = ''
  40.         $isNotMTA = ''
  41.         $smartcardLogonRequired = ''
  42.         $passExpired = ''
  43.         $passNeverExpires = ''
  44.         $enabled = ''
  45.         $locked = ''
  46.         if(($user | where memberof -like '*Workstation_Admin*') -or ($user | where PrimaryGroup -like '*Workstation Admins*')){
  47.             $isWA = $true
  48.             $WACount++
  49.         }
  50.         if(($user | where memberof -like '*Server_Admin*') -or ($user | where PrimaryGroup -like '*Server Admins*')){
  51.             $isSA = $true
  52.             $SACount++
  53.         }
  54.         if(($user | where memberof -like '*Domain Admins*') -or ($user | where PrimaryGroup -like '*Domain Admins*')){
  55.             $isDA = $true
  56.             $DACount++
  57.         }
  58.         if(($user | where memberof -like '*Enterprise Admins*') -or ($user | where PrimaryGroup -like '*Enterprise Admins*')){
  59.             $isEA = $true
  60.             $EACount++
  61.         }
  62.         if(($user | where memberof -like '*MTA-DTA_Allow*') -or ($user | where PrimaryGroup -like '*MTA-DTA_Allow*')){
  63.             $isMTA = $true
  64.             $MTAAllowCount++
  65.         }
  66.         if(($user | where memberof -like '*MTA-DTA_Block*') -or ($user | where PrimaryGroup -like '*MTA-DTA_Block*')){
  67.             $isNotMTA = $true
  68.             $MTABlockCount++
  69.         }
  70.         if(($user.SmartCardLogonRequired)){
  71.             $smartcardLogonRequired = $true
  72.             $smartcardCount++
  73.         }
  74.         if(($user.PasswordExpired)){
  75.             $passExpired = $true
  76.             $passExpiredCount++
  77.         }
  78.         if(($user.PasswordNeverExpires)){
  79.             $passNeverExpires = $true
  80.             $passNeverExpiresCount++
  81.         }
  82.         if(($user.Enabled)){
  83.             $enabled = $true
  84.             $enabledCount++
  85.         }
  86.         if(($user.LockedOut)){
  87.             $locked = $true
  88.             $lockedCount++
  89.         }
  90.         #Creates a PSCustomObject of the resulting user attributes and adds it to $output array list
  91.         $output += [PSCustomObject]@{
  92.                         'Account Name'=$user.SamAccountName
  93.                         'UserPrincipalName'=$user.UserPrincipalName
  94.                         'Enabled'=$enabled
  95.                         'LockedOut'=$locked
  96.                         'MTA-DTA_Allow'=$isMTA
  97.                         'MTA-DTA_Block'=$isNotMTA
  98.                         'Workstation Admin'=$isWA
  99.                         'Server Admin'=$isSA
  100.                         'Domain Admin'=$isDA
  101.                         'Enterprise Admin'=$isEA
  102.                         'SmartCardLogonRequired'=$smartcardLogonRequired
  103.                         'PasswordExpired'=$passExpired
  104.                         'PasswordNeverExpires'=$passNeverExpires
  105.                         'PasswordLastSet'=$user.PasswordLastSet
  106.                         'LastLogonDate*DC1 Only*'=$user.LastLogonDate
  107.                         }
  108.     }
  109.     #Add the total counts
  110.     $output += [PSCustomObject]@{
  111.                     'Account Name'=$userCount
  112.                     'UserPrincipalName'=''
  113.                     'Enabled'=$enabledCount
  114.                     'LockedOut'=$lockedCount
  115.                     'MTA-DTA_Allow'=$MTAAllowCount
  116.                     'MTA-DTA_Block'=$MTABlockCount
  117.                     'Workstation Admin'=$WACount
  118.                     'Server Admin'=$SACount
  119.                     'Domain Admin'=$DACount
  120.                     'Enterprise Admin'=$EACount
  121.                     'SmartCardLogonRequired'=$smartcardCount
  122.                     'PasswordExpired'=$passExpiredCount
  123.                     'PasswordNeverExpires'=$passNeverExpiresCount
  124.                     'PasswordLastSet'=''
  125.                     'LastLogonDate*DC1 Only*'=''
  126.                     }
  127.     #Uncomment the line below to see the output inside the console
  128.     #$($output) | Format-Table -AutoSize
  129.     #Save the output as a tab-delimited csv file for export to excel
  130.     $($output) | export-csv "$env:USERPROFILE\Documents\AD_USER_LIST_$(Get-Date -format 'MMddyyyy_HHmmss').csv"
  131.     
  132.     Write-Host "The CSV has been generated at $env:USERPROFILE\Documents\AD_USER_LIST_$(Get-Date -format 'MMddyyyy_HHmmss').csv"
  133. }
  134. #Comment out the below line if Administrator permissions are not required to query AD user fields in your environment
  135. Test_If_Admin;
  136. Poll_Users;
  137. Read-Host "Press Enter to exit..."
  138. Exit;