Files
safetynet/scripts/debug-collector-acl.mjs
T

32 lines
2.6 KiB
JavaScript
Raw Normal View History

import {spawnSync} from 'node:child_process';
// Do not reapply ownership to an already private directory: Windows may require
// restore privileges for SetOwner even when the current account already owns it.
const command=`$ErrorActionPreference='Stop';
$sid=[System.Security.Principal.WindowsIdentity]::GetCurrent().User;
function Test-PrivateAcl($acl){
if(-not $acl.AreAccessRulesProtected -or $acl.GetOwner([System.Security.Principal.SecurityIdentifier]).Value -ne $sid.Value){return $false;}
$rules=@($acl.GetAccessRules($true,$true,[System.Security.Principal.SecurityIdentifier]));
if($rules.Count -ne 1){return $false;}
$rule=$rules[0];
return (-not $rule.IsInherited -and $rule.IdentityReference.Value -eq $sid.Value -and $rule.AccessControlType -eq [System.Security.AccessControl.AccessControlType]::Allow -and $rule.FileSystemRights -eq [System.Security.AccessControl.FileSystemRights]::FullControl -and $rule.InheritanceFlags -eq ([System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor [System.Security.AccessControl.InheritanceFlags]::ObjectInherit) -and $rule.PropagationFlags -eq [System.Security.AccessControl.PropagationFlags]::None);
}
$existing=Get-Acl -LiteralPath $env:SAFETYNET_COLLECTOR_DIRECTORY;
$changed=$false;
if(-not (Test-PrivateAcl $existing)){
$private=New-Object System.Security.AccessControl.DirectorySecurity;
$private.SetOwner($sid);$private.SetAccessRuleProtection($true,$false);
$private.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule($sid,'FullControl','ContainerInherit,ObjectInherit','None','Allow')));
Set-Acl -LiteralPath $env:SAFETYNET_COLLECTOR_DIRECTORY -AclObject $private;
$changed=$true;
}
$verified=Get-Acl -LiteralPath $env:SAFETYNET_COLLECTOR_DIRECTORY;
if(-not (Test-PrivateAcl $verified)){throw 'Collector directory protection verification failed';}
@{verified=$true;changed=$changed}|ConvertTo-Json -Compress;`;
export function protectCollectorDirectory(directory,{run=spawnSync}={}){
const result=run('powershell.exe',['-NoProfile','-NonInteractive','-Command',command],{windowsHide:true,timeout:10000,env:{SystemRoot:process.env.SystemRoot,SAFETYNET_COLLECTOR_DIRECTORY:directory},stdio:'pipe',encoding:'utf8'});
if(result.status!==0)throw Error('Collector directory protection failed');
let proof;try{proof=JSON.parse(result.stdout);}catch{throw Error('Collector directory protection verification failed');}
if(proof?.verified!==true||typeof proof.changed!=='boolean')throw Error('Collector directory protection verification failed');
return Object.freeze({verified:true,changed:proof.changed});
}