问题
This is the scenario I am trying to enable:
I wish to authenticate to an azure keyvault from my web service application (azure service fabric) via a client certificate.
These are the steps I'm following:
- Add a certificate to my keyvault in azure (self signed)
- Download certificate via azure powershell (pfx)
- Create Azure App Instance to identify my app
- Associate certificate with app
- Create service principal for the azure app
- Give principal access to keyvault
All looks good. When I spin up my service (local service fabric cluster), and try to connect to keyvault to retrieve a secret key+value that I have stored inside, I get error:
CryptographicException: "KeySet does not exist"
When I try to examine PrivateKey property value of the X509Certificate2 object at runtime, it throws the same exception.
The certificate is found, and the private key exists (I verified this via MMC as well as some command line tools).
What can I be missing? Only cause I can think of for this failure is that service fabric user context (Network Service, I think) does not have permission to look at private key? It is stored in "LocalMachine" certificate store, under Personal" folder (also referred to as "My"). From what I know, applications should be able to read from LocalMachine store without special permissions?
回答1:
An alternative easier way to grant NETWORK SERVICE
user permission on certificate private key (easier than my other answer):
- Open certificate snap-in in MMC:
WIN
+R
-> typemmc
-> File -> Add/Remove Snap-in -> Add Certificates (Computer Account). - Find your certificate -> Right click and choose All Tasks/Manage Private Keys
- Grant
Read
Permission forNETWORK SERVICE
user
回答2:
Ok, my suspicion was correct. I explicitly granted Network Service
user (the user context under which local service fabric cluster runs) access to private key file. Now I can authenticate with keyvault.
cacls.exe "C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys\{private-key-filename}" /e /g "Network Service":R
I found private key location via a tool program "FindPrivateKey.exe"
findprivatekey.exe My LocalMachine -t "{thumbprint}" -a
Tool can be obtained from https://www.microsoft.com/en-us/download/confirmation.aspx?id=21459
(It is a source code sample located in directory \WCF\Setup\FindPrivateKey\CS\FindPrivateKey.sln
, you need to build it yourself)
回答3:
I ran into the same problem and granting read permission to Network Service
worked for me. There is also another way to run run high-privilege service as Local System user described here:
https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-run-script-at-service-startup
You can modify your Service Fabric ApplicationManifest.xml to
- define a service principal corresponding to local machine
- use that service principal to run the service fabric package created
final ApplicationManifest.xml would look something like:
<?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>
来源:https://stackoverflow.com/questions/46964941/service-fabric-authenticating-with-azure-keyvault-via-cert-keyset-does-not-ex