Service Fabric:通过证书使用 Azure KeyVault 进行身份验证:"KeySet does not exist"
Service Fabric: Authenticating with Azure KeyVault via cert: "KeySet does not exist"
这是我要启用的场景:
我希望通过客户端证书从我的 Web 服务应用程序(azure 服务结构)向 azure keyvault 进行身份验证。
这些是我要执行的步骤:
- 将证书添加到我的 keyvault in azure(自签名)
- 通过 azure powershell (pfx) 下载证书
- 创建 Azure 应用程序实例以识别我的应用程序
- 将证书与应用相关联
- 为 Azure 应用程序创建服务主体
- 授予委托人访问密钥库的权限
一切看起来都不错。当我启动我的服务(本地服务结构集群)并尝试连接到 keyvault 以检索我存储在其中的密钥+值时,出现错误:
CryptographicException: "KeySet does not exist"
当我尝试在运行时检查 X509Certificate2 对象的 PrivateKey 属性 值时,它抛出相同的异常。
找到证书,并且私钥存在(我通过MMC以及一些命令行工具验证了这一点)。
我可以缺少什么?对于这种失败,我能想到的唯一原因是服务结构用户上下文(我认为是网络服务)没有查看私钥的权限?它存储在 "LocalMachine" 证书库中,在
Personal”文件夹(也称为 "My")。据我所知,应用程序应该能够在没有特殊权限的情况下从 LocalMachine 存储中读取?
好的,我的猜测是正确的。我明确授予 Network Service
用户(本地服务结构集群运行的用户上下文)访问私钥文件的权限。现在我可以使用 keyvault 进行身份验证了。
cacls.exe "C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys\{private-key-filename}" /e /g "Network Service":R
我通过工具程序找到了私钥位置"FindPrivateKey.exe"
findprivatekey.exe My LocalMachine -t "{thumbprint}" -a
工具可以从https://www.microsoft.com/en-us/download/confirmation.aspx?id=21459
获得
(源代码示例位于目录\WCF\Setup\FindPrivateKey\CS\FindPrivateKey.sln
,需要自行构建)
另一种更简单的方法来授予 NETWORK SERVICE
用户对证书私钥的权限(比我的其他答案更容易):
- 在 MMC 中打开证书管理单元:
WIN
+ R
-> 输入 mmc
-> 文件 -> Add/Remove 管理单元 -> 添加证书 (计算机帐户)。
- 找到您的证书 -> 右键单击并选择所有 Tasks/Manage 私钥
- 授予
NETWORK SERVICE
用户Read
权限
我 运行 遇到了同样的问题,g运行 对 Network Service
的读取权限对我有用。还有另一种方法 运行 运行 作为本地系统用户的高权限服务描述如下:
https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-run-script-at-service-startup
您可以将 Service Fabric ApplicationManifest.xml 修改为
- 定义本地机器对应的服务主体
- 使用该服务主体运行创建的服务结构包
最终 ApplicationManifest.xml 看起来像:
<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
...
<ServiceManifestImport>
...
<Policies>
<RunAsPolicy CodePackageRef="Code" UserRef="LocalSystemUser" /> <!-- 2. run service fabric as defined principal -->
</Policies>
</ServiceManifestImport>
<Principals>
<Users>
<User Name="LocalSystemUser" AccountType="LocalSystem" /> <!-- 1. define principal -->
</Users>
</Principals>
</ApplicationManifest>
这是我要启用的场景:
我希望通过客户端证书从我的 Web 服务应用程序(azure 服务结构)向 azure keyvault 进行身份验证。
这些是我要执行的步骤:
- 将证书添加到我的 keyvault in azure(自签名)
- 通过 azure powershell (pfx) 下载证书
- 创建 Azure 应用程序实例以识别我的应用程序
- 将证书与应用相关联
- 为 Azure 应用程序创建服务主体
- 授予委托人访问密钥库的权限
一切看起来都不错。当我启动我的服务(本地服务结构集群)并尝试连接到 keyvault 以检索我存储在其中的密钥+值时,出现错误:
CryptographicException: "KeySet does not exist"
当我尝试在运行时检查 X509Certificate2 对象的 PrivateKey 属性 值时,它抛出相同的异常。
找到证书,并且私钥存在(我通过MMC以及一些命令行工具验证了这一点)。
我可以缺少什么?对于这种失败,我能想到的唯一原因是服务结构用户上下文(我认为是网络服务)没有查看私钥的权限?它存储在 "LocalMachine" 证书库中,在 Personal”文件夹(也称为 "My")。据我所知,应用程序应该能够在没有特殊权限的情况下从 LocalMachine 存储中读取?
好的,我的猜测是正确的。我明确授予 Network Service
用户(本地服务结构集群运行的用户上下文)访问私钥文件的权限。现在我可以使用 keyvault 进行身份验证了。
cacls.exe "C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys\{private-key-filename}" /e /g "Network Service":R
我通过工具程序找到了私钥位置"FindPrivateKey.exe"
findprivatekey.exe My LocalMachine -t "{thumbprint}" -a
工具可以从https://www.microsoft.com/en-us/download/confirmation.aspx?id=21459
获得(源代码示例位于目录\WCF\Setup\FindPrivateKey\CS\FindPrivateKey.sln
,需要自行构建)
另一种更简单的方法来授予 NETWORK SERVICE
用户对证书私钥的权限(比我的其他答案更容易):
- 在 MMC 中打开证书管理单元:
WIN
+R
-> 输入mmc
-> 文件 -> Add/Remove 管理单元 -> 添加证书 (计算机帐户)。 - 找到您的证书 -> 右键单击并选择所有 Tasks/Manage 私钥
- 授予
NETWORK SERVICE
用户Read
权限
我 运行 遇到了同样的问题,g运行 对 Network Service
的读取权限对我有用。还有另一种方法 运行 运行 作为本地系统用户的高权限服务描述如下:
https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-run-script-at-service-startup
您可以将 Service Fabric ApplicationManifest.xml 修改为
- 定义本地机器对应的服务主体
- 使用该服务主体运行创建的服务结构包
最终 ApplicationManifest.xml 看起来像:
<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
...
<ServiceManifestImport>
...
<Policies>
<RunAsPolicy CodePackageRef="Code" UserRef="LocalSystemUser" /> <!-- 2. run service fabric as defined principal -->
</Policies>
</ServiceManifestImport>
<Principals>
<Users>
<User Name="LocalSystemUser" AccountType="LocalSystem" /> <!-- 1. define principal -->
</Users>
</Principals>
</ApplicationManifest>