一种选择是以SYSTEM 身份运行Service Fabric 设置任务(只有SYSTEM 有权更改证书上的ACL)并授予NETWORK SERVICE 读取证书的权限
下面的完整示例,注意我在所有 LocalMachine / 我的证书上设置了 ACL,修改 PS 脚本以仅获取您需要的证书
ServiceManifest.xml
<CodePackage Name="Code" Version="1.0.0">
<SetupEntryPoint>
<ExeHost>
<Program>setup.cmd</Program>
<WorkingFolder>CodePackage</WorkingFolder>
</ExeHost>
</SetupEntryPoint>
<EntryPoint>
<ExeHost>
<Program>XXX.exe</Program>
<WorkingFolder>CodePackage</WorkingFolder>
</ExeHost>
</EntryPoint>
</CodePackage>
setup.cmd
powershell.exe -NoLogo -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File configure-certs.ps1
configure-certs.ps1
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store @(
[System.Security.Cryptography.X509Certificates.StoreName]::My,
[System.Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine)
try
{
$store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadOnly)
$certs = $store.Certificates
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule @(
"NETWORK SERVICE",
[System.Security.AccessControl.FileSystemRights]::Read,
[System.Security.AccessControl.AccessControlType]::Allow)
foreach ($cert in $certs)
{
$privateKeyPath = "$($ENV:ProgramData)\Microsoft\Crypto\RSA\MachineKeys\$($cert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName)"
$privateKeyInfo = New-Object System.IO.FileInfo @($privateKeyPath)
$privateKeyAccessControl = $privateKeyInfo.GetAccessControl()
$privateKeyAccessControl.AddAccessRule($rule)
$privateKeyInfo.SetAccessControl($privateKeyAccessControl)
}
}
finally
{
$store.Close()
}
ApplicationManifest.xml
在 ConfigOverrides 作为您要添加设置的包的 ServiceManifestImport 的子项之后
...
<Policies>
<RunAsPolicy CodePackageRef="Code" UserRef="LocalSystem" EntryPointType="Setup" />
</Policies>
...
在 DefaultServices 之后作为 ApplicationManifest
的子项
...
<Principals>
<Users>
<User Name="LocalSystem" AccountType="LocalSystem" />
</Users>
</Principals>
...