Goto Top

Bitlocker recovery key delegation via Powershell

Hello admins!

In the A better way to delegate control for Bitlocker recovery keys post by @DerWoWusste we've been introduced by the approach that allows to avoid delegating full control to IT Techs who are supposed to be able to find bitocker recovery keys.

I have a question regarding implementation of the same thing but in Powershell.
I work in the education organization that supports 140 schools. One of the MSPs that we're working with services 83 of them.
I need to delegate their (MSP) IT Tech AD group a bitlocker keys read permissions in their corresponding OUs (domain/Resources/<SchoolCode>/Windows Computers)
The closest I found was in TechNet's post that the OP was complaining about as not working.

dsacls.exe "OU=Computers,$OrganizationalUnitDN" /G $prefixlocation-$type":RP;msFVE-RecoveryPassword;msFVE-RecoveryInformation" /I:S

I have some PS experience in ExchangeOnline (link leads to SpiceWorks O365 related question of mine that I answer myself), but I'm not sure what to start with in this case.
Please nudge me in the right direction.

Content-Key: 1638502270


Printed on: June 3, 2023 at 20:06 o'clock

Member: DerWoWusste
DerWoWusste Dec 20, 2021 at 08:42:25 (UTC)
Goto Top

The confidentiality bit is set using the control access parameter CA.
DSACLS "OU=Test,OU=computers,DC=dom,DC=local" /I:S /G "mydom\helpdesk:CA"
However, testing that, I did not succeed to limit this control access to certain attributes only.
Member: colinardo
Solution colinardo Dec 20, 2021 updated at 15:18:34 (UTC)
Goto Top
Hi @nekku6, welcome to!

If you want create the delegation with pure powershell you can do it like this. This will grant read access, sets the confidentially bit on subordinate msFVE-RecoveryInformation objects for a defined OU and user/group.

    Delegate read access to Bitlocker-RecoveryInformation objects in AD Organizational Units
Import-Module ActiveDirectory
# OU
$OU = 'OU=MyAdmins,DC=testlab,dc=intern'
# Group/Account
$account = ([System.Security.Principal.NTAccount]"MyAdminGroup")
# get acl of the OU
$acl = Get-ACL "AD:$OU"   
# create the access rule
$rule = New-Object System.DirectoryServices.ActiveDirectoryAccessRule ($account,'ReadProperty,ExtendedRight','Allow','{00000000-0000-0000-0000-000000000000}','All',"{ea715d30-8f53-40d0-bd1e-6109186d782c}")
# add the rule to acl
# save acl back to the OU
Set-ACL "AD:$OU" $acl

As @DerWoWusste already mentioned, restricting the extended right for only the attribute msFVE-RecoveryPassword is not possible, it must be delegated to the whole msFVE-RecoveryInformation object .

Regards @colinardo
Member: DerWoWusste
DerWoWusste Dec 20, 2021 at 13:42:41 (UTC)
Goto Top
I could confirm this to be working!
Member: nekku6
nekku6 Dec 21, 2021 updated at 02:13:27 (UTC)
Goto Top
Hi @colinardo,
Thank you, that worked for me! It gives all sorts of those additional reading rights, but it should be fine.
Although, I still have a quick question for you on how did you find the IDs used in the rule creation. I assume there should be something describing that on like they have for exchange cmdlets' switches, but I'm not sure what to ask for to look it up.

And thank you @DerWoWusste for inspiring me to keep investigating and introducing to this site!

BTW, it took less than 2 seconds compared to what I'd imagine be a tedious whole day clicking face-smile
Script started at 12/21/2021 11:24:57
Script completed at 12/21/2021 11:24:59
Script took 00:00:01.9687952 to complete
Just in case anyone who's new to PS reads the article and maybe finds this useful, here's my foreach modification for this script.
#Import-Module ActiveDirectory

$Import = Import-Csv d:\temp\INC\NF-BL-import.csv
$LIF = $Import | Measure-Object
$LIFC = $LIF.count
Write-host "$LIFC lines in file" -ForegroundColor Yellow

$RL = 0
$ScriptStartTime = Get-Date
Write-Host "Script started at $ScriptStartTime"

foreach ($Line in $Import) { 
    ### Defining OU from the import ###
    $Group = ([System.Security.Principal.NTAccount]$Line.Group)
    ### Defining OU from the import ###
    $ACL = Get-ACL "AD:$($Line.DN)"
    ### Creating the access rule ###
    $Rule = New-Object System.DirectoryServices.ActiveDirectoryAccessRule ($Group,'ReadProperty,ExtendedRight','Allow','{00000000-0000-0000-0000-000000000000}','All',"{ea715d30-8f53-40d0-bd1e-6109186d782c}")
    ### Adding created rule to ACL ###
    ### Setting the rule for the defined OU ###
    Set-ACL "AD:$($Line.DN)" $ACL

    Write-Host "Progress: $($Line.DN) has been delegated to $($Line.Group)" -ForegroundColor Yellow
    Write-Host "Progress: $RL of $LIFC" -ForegroundColor Yellow

$ScriptEndTime = Get-Date
$TTR = $ScriptEndTime - $ScriptStartTime
Write-Host "Script started at $ScriptStartTime"
Write-Host "Script completed at $ScriptEndTime"
Write-Host "Script took $TTR to complete" -ForegroundColor Green
Member: colinardo
colinardo Dec 21, 2021 updated at 06:44:56 (UTC)
Goto Top
You can find the GUIDs easly in your AD Schema, for example, for the attributes
Get-ADObject -Searchbase (Get-ADRootDSE).schemaNamingContext -Filter {objectClass -eq 'attributeSchema'}
Or via GUI by opening adsiedit.msc, and connecting to your schema context.