Skip to content

Commit 6512e9c

Browse files
authored
Add support for using a SID to grant permissions to the key created by EnrollAik.ps1. (#13)
1 parent b827dc5 commit 6512e9c

File tree

2 files changed

+121
-103
lines changed

2 files changed

+121
-103
lines changed

EnrollAik.ps1

Lines changed: 117 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,118 @@
1-
<#
2-
.DESCRIPTION
3-
This script is designed to create a TPM Attestation Identity Key (AIK) and retrieve an AIK certificate for use with the Microsoft Azure Attestation service.
4-
.NOTES
5-
This script must be run from an Admin window.
6-
.PARAMETER KeyName
7-
Name of the key to be created.
8-
.PARAMETER AclIdentity
9-
Changes the ACL on the key so it can be read by the user/group specified by this parameter. This can be used to configure the account under which the MAA client executes so it does not have to be run with elevated permissions.
10-
The script can also be used to configure the ACL on a previously created key.
11-
.EXAMPLE
12-
EnrollAik.ps1 MyOrgAik
13-
=> Creates an AIK called "MyOrgAik" and enrolls it with Azure Certificate Services to get an associated AIK certificate.
14-
.EXAMPLE
15-
EnrollAik.ps1 MyOrgAik -AclIdentity TestAccount
16-
=> Creates an AIK called "MyOrgAIK" and enrolls it with Azure Certificate Services to get an associated AIK certificate.
17-
Additionally, grants read permission on the key to "TestAccount".
18-
.EXAMPLE
19-
EnrollAik.ps1 MyOrgAik -AclIdentity "NT AUTHORITY\Authenticated Users"
20-
=> Creates an AIK called "MyOrgAIK" and enrolls it with Azure Certificate Services to get an associated AIK certificate.
21-
Additionally, grants read permission on the key to all Authenticated users (those signed into the domain).
22-
#>
23-
24-
<# Copyright (c) Microsoft Corporation. All rights reserved. #>
25-
26-
Param(
27-
[Parameter(Mandatory = $true)][string]$KeyName,
28-
[Parameter()][string]$AclIdentity
29-
)
30-
31-
function PrettyPrintCapturedOutput {
32-
param (
33-
[Parameter(Mandatory = $true)]$output,
34-
[Parameter()][switch]$isError
35-
)
36-
if ($isError) {
37-
foreach ($line in $output) {
38-
# Write-Host instead of Write-Error since Error will print the line number and make it seem like the error comes from this function.
39-
Write-Host "$line`n" -ForegroundColor Red
40-
}
41-
}
42-
else {
43-
foreach ($line in $output) {
44-
Write-Debug "$line`n"
45-
}
46-
}
47-
}
48-
49-
Write-Host "Beginning request... (This can take up to a few minutes depending on the TPM performance)" -ForegroundColor Green
50-
$cmdLine = "certreq.exe -enrollaik -f -machine -config ```"```" $KeyName"
51-
Write-Debug "Create AIK and request cert: $cmdLine"
52-
$reqOutput = Invoke-Expression -Command $cmdLine
53-
54-
# If the key has been previously created certreq will return NTE_EXISTS. By allowing this or S_OK, the script can also ACL keys that have been previously created.
55-
$NTE_KEY_EXISTS = -2146893809
56-
if ($LASTEXITCODE -eq 0 -or $LASTEXITCODE -eq $NTE_KEY_EXISTS) {
57-
PrettyPrintCapturedOutput $reqOutput
58-
Write-Host "Key is available." -ForegroundColor Green
59-
60-
if ($AclIdentity) {
61-
Write-Host "Granting read access to $AclIdentity..." -ForegroundColor Green
62-
63-
# Retrieve the disk location for the key
64-
$cmdLine = "certutil.exe -CSP TPM -key $KeyName"
65-
Write-Debug "Find key location: $cmdLine"
66-
$utilOutput = Invoke-Expression -Command $cmdLine
67-
PrettyPrintCapturedOutput $utilOutput
68-
69-
if ($LASTEXITCODE -eq 0) {
70-
$keyPath = $utilOutput[2].trim()
71-
if (-not($keyPath -like "$($env:ProgramData)\Microsoft\Crypto\PCPKSP\*")) {
72-
Write-Error "The format of CertUtil output doesn't match the expected value and might have changed."
73-
Write-Error "Please adjust the script accordingly to ensure the proper file is ACL'd correctly for read access."
74-
PrettyPrintCapturedOutput $utilOutput -isError
75-
return
76-
}
77-
78-
$acl = Get-Acl -Path $keyPath
79-
# Set read ACE
80-
$identity = $AclIdentity
81-
$fileSystemRights = "Read"
82-
$type = "Allow"
83-
# Create new rule
84-
$fileSystemAccessRuleArgumentList = $identity, $fileSystemRights, $type
85-
$fileSystemAccessRule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $fileSystemAccessRuleArgumentList
86-
# Apply new rule to object (setting same ACL multiple times has no effect, so no need to check if rule is already set)
87-
$acl.SetAccessRule($fileSystemAccessRule)
88-
Set-Acl -Path $keyPath -AclObject $acl
89-
90-
$acl = Get-Acl -path $keyPath
91-
Write-Debug ($acl.Access | Format-List | out-string)
92-
Write-Host "Key is accessible by $AclIdentity now." -ForegroundColor Green
93-
}
94-
else {
95-
Write-Error "Unexpected return from certutil ($($LASTEXITCODE)) when searching for $KeyName. The key has *not* been ACL'd."
96-
PrettyPrintCapturedOutput $utilOutput -isError
97-
}
98-
}
99-
}
100-
else {
101-
# CertReq failed, print output to user
102-
PrettyPrintCapturedOutput $reqOutput -isError
1+
<#
2+
.DESCRIPTION
3+
This script is designed to create a TPM Attestation Identity Key (AIK) and retrieve an AIK certificate for use with the Microsoft Azure Attestation service.
4+
.NOTES
5+
This script must be run from an Admin window.
6+
.PARAMETER KeyName
7+
Name of the key to be created.
8+
.PARAMETER AclIdentity
9+
Changes the ACL on the key so it can be read by the user/group specified by this parameter. This can be used to configure the account under which the MAA client executes so it does not have to be run with elevated permissions.
10+
The script can also be used to configure the ACL on a previously created key.
11+
.PARAMETER AclIdentitySid
12+
Changes the ACL on the key so it can be read by the SID specified by this parameter. This can be used to configure the account under which the MAA client executes so it does not have to be run with elevated permissions.
13+
The script can also be used to configure the ACL on a previously created key.
14+
.EXAMPLE
15+
EnrollAik.ps1 MyOrgAik
16+
=> Creates an AIK called "MyOrgAik" and enrolls it with Azure Certificate Services to get an associated AIK certificate.
17+
.EXAMPLE
18+
EnrollAik.ps1 MyOrgAik -AclIdentity TestAccount
19+
=> Creates an AIK called "MyOrgAIK" and enrolls it with Azure Certificate Services to get an associated AIK certificate.
20+
Additionally, grants read permission on the key to "TestAccount".
21+
.EXAMPLE
22+
EnrollAik.ps1 MyOrgAik -AclIdentity "NT AUTHORITY\Authenticated Users"
23+
=> Creates an AIK called "MyOrgAIK" and enrolls it with Azure Certificate Services to get an associated AIK certificate.
24+
Additionally, grants read permission on the key to all Authenticated users (those signed into the domain).
25+
.EXAMPLE
26+
EnrollAik.ps1 MyOrgAik -AclIdentitySid "S-1-5-11"
27+
=> Creates an AIK called "MyOrgAIK" and enrolls it with Azure Certificate Services to get an associated AIK certificate.
28+
Additionally, grants read permission on the key to all Authenticated users (those signed into the domain) using a SID.
29+
#>
30+
31+
<# Copyright (c) Microsoft Corporation. All rights reserved. #>
32+
33+
[CmdletBinding(DefaultParameterSetName = 'AclIdentity')]
34+
Param(
35+
[Parameter(Mandatory = $true, Position = 0)][string]$KeyName,
36+
[Parameter(ParameterSetName = 'AclIdentity')][string]$AclIdentity,
37+
[Parameter(ParameterSetName = 'AclIdentitySid')][string]$AclIdentitySid
38+
)
39+
40+
function PrettyPrintCapturedOutput {
41+
param (
42+
[Parameter(Mandatory = $true)]$output,
43+
[Parameter()][switch]$isError
44+
)
45+
if ($isError) {
46+
foreach ($line in $output) {
47+
# Write-Host instead of Write-Error since Error will print the line number and make it seem like the error comes from this function.
48+
Write-Host "$line`n" -ForegroundColor Red
49+
}
50+
}
51+
else {
52+
foreach ($line in $output) {
53+
Write-Debug "$line`n"
54+
}
55+
}
56+
}
57+
58+
Write-Host "Beginning request... (This can take up to a few minutes depending on the TPM performance)" -ForegroundColor Green
59+
$cmdLine = "certreq.exe -enrollaik -f -machine -config ```"```" $KeyName"
60+
Write-Debug "Create AIK and request cert: $cmdLine"
61+
$reqOutput = Invoke-Expression -Command $cmdLine
62+
63+
# If the key has been previously created certreq will return NTE_EXISTS. By allowing this or S_OK, the script can also ACL keys that have been previously created.
64+
$NTE_KEY_EXISTS = -2146893809
65+
if ($LASTEXITCODE -eq 0 -or $LASTEXITCODE -eq $NTE_KEY_EXISTS) {
66+
PrettyPrintCapturedOutput $reqOutput
67+
Write-Host "Key is available." -ForegroundColor Green
68+
69+
if ($AclIdentity -or $AclIdentitySid) {
70+
if ($AclIdentity) {
71+
$identity = $AclIdentity
72+
}
73+
else {
74+
$identity = New-Object System.Security.Principal.SecurityIdentifier($AclIdentitySid)
75+
}
76+
77+
Write-Host "Granting read access to $identity..." -ForegroundColor Green
78+
79+
# Retrieve the disk location for the key
80+
$cmdLine = "certutil.exe -CSP TPM -key $KeyName"
81+
Write-Debug "Find key location: $cmdLine"
82+
$utilOutput = Invoke-Expression -Command $cmdLine
83+
PrettyPrintCapturedOutput $utilOutput
84+
85+
if ($LASTEXITCODE -eq 0) {
86+
$keyPath = $utilOutput[2].trim()
87+
if (-not($keyPath -like "$($env:ProgramData)\Microsoft\Crypto\PCPKSP\*")) {
88+
Write-Error "The format of CertUtil output doesn't match the expected value and might have changed."
89+
Write-Error "Please adjust the script accordingly to ensure the proper file is ACL'd correctly for read access."
90+
PrettyPrintCapturedOutput $utilOutput -isError
91+
return
92+
}
93+
94+
$acl = Get-Acl -Path $keyPath
95+
# Set read ACE
96+
$fileSystemRights = "Read"
97+
$type = "Allow"
98+
# Create new rule
99+
$fileSystemAccessRuleArgumentList = $identity, $fileSystemRights, $type
100+
$fileSystemAccessRule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $fileSystemAccessRuleArgumentList
101+
# Apply new rule to object (setting same ACL multiple times has no effect, so no need to check if rule is already set)
102+
$acl.SetAccessRule($fileSystemAccessRule)
103+
Set-Acl -Path $keyPath -AclObject $acl
104+
105+
$acl = Get-Acl -path $keyPath
106+
Write-Debug ($acl.Access | Format-List | out-string)
107+
Write-Host "Key is accessible by $identity now." -ForegroundColor Green
108+
}
109+
else {
110+
Write-Error "Unexpected return from certutil ($($LASTEXITCODE)) when searching for $KeyName. The key has *not* been ACL'd."
111+
PrettyPrintCapturedOutput $utilOutput -isError
112+
}
113+
}
114+
}
115+
else {
116+
# CertReq failed, print output to user
117+
PrettyPrintCapturedOutput $reqOutput -isError
103118
}

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ This sample creates a TPM key named "att_sample_key" which is attested by Micros
2626

2727
* An AIK named "att_sample_aik" must be available. Run the EnrollAik.ps1 script to create the key and retrieve an AIK certificate for it (notice that the command below allows the key to be accessed by all users on the machine):
2828

29-
EnrollAik.ps1 att_sample_aik BUILTIN\Users
29+
```EnrollAik.ps1 att_sample_aik -AclIdentity BUILTIN\Users``` [^1]
30+
31+
[^1]: Some Windows built-in security group names may be localized. EnrollAik.ps1 also accepts a SID to grant permissions to a key: `EnrollAik.ps1 att_sample_aik -AclIdentitySid S-1-5-32-545` (allows the key to be accessed by all users on the machine). More information about Windows security groups can be found [here](https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/understand-security-groups). Well-known SIDs are listed [here](https://learn.microsoft.com/en-us/windows/win32/secauthz/well-known-sids).
32+
3033

3134
## Running attestation samples
3235

0 commit comments

Comments
 (0)