Service Fabric Local Cluster fails to get certificate(s) private key(s) - x509certificate

For every Service Fabric application I attempt to run which utilizes one or more SecretsCertificate instances, the application fails to launch in my local Service Fabric cluster with the following error on the Node > Application in the SF Explorer:
Error event: SourceId='System.Hosting', Property='Activation:1.0'.
There was an error during activation.Failed to configure certificate permissions. Error E_FAIL.
Service Fabric also logs a few relevant items in to the Event Viewer > Applications and Services Logs > Microsoft-Service Fabric > Admin section:
CryptAcquireCertificatePrivateKey failed. Error:0x8009200b
Can't get private key filename for certificate. Error: 0x8009200b
All tries to get private key filename failed.
Failed to get the Certificate's private key.
Thumbprint:4XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXC. Error: E_FAIL
Failed to get private key file. x509FindValue: 4XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXC, x509StoreName: My, findType: FindByThumbprint, Error E_FAIL
ACLing private key filename for thumbprint 4XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXC. ErrorCode=E_FAIL
ConfigureCertificateACLs: error=E_FAIL
I have removed and reinstalled the certificate (which is confirmed to work in multiple other developers' local Service Fabric cluster development environments), and set the private key to have explicit full control permissions for the NETWORK SERVICE user on my computer, which didn't help.
I have followed the instructions in this answer which actually prints out the private key details correctly despite SF local cluster not being able to access it.
I have reinstalled Microsoft Service Fabric SDK, and Microsoft Visual Studio 2017 which also didn't resolve this problem.
All attempts to recreate this error in C# and PowerShell have been fruitless, yet the Service Fabric service doesn't seem to be able to access private keys from my cert store.
Edit: Further progress, no solution.
I am able to successfully decrypt data using the PowerShell Invoke-ServiceFabricDecryptText cmdlet, yet the SF Local Cluster still has the same error.
I determined that the file specified in the certificate's metadata (from the previously referenced SO answer) PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName doesn't exist on my disk at the path C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys\ or any neighboring paths. Has anyone seen this before?

As discussed in the comments, the issue is related to how the (self-signed) certificate is created. When using Powershell to create your certs make sure to use:
So when I specified -Provider "Microsoft Enhanced Cryptographic
Provider v1.0" for the
New-SelfsignedCertificate command to create a cert, it works.
Source: https://github.com/Azure/service-fabric-issues/issues/235#issuecomment-292667379

An alternative, in case you can't or don't want to use a self-signed certificate, is to "remove" the CNG storage of the private key (which is the part that Service Fabric can't yet handle).
The steps outlined in this article show how to convert a CNG cert to a non-CNG one:
https://blog.davidchristiansen.com/2016/05/521/
Extract your public key and full certificate chain from your PFX file
openssl pkcs12 -in "yourcertificate.pfx" -nokeys -out "yourcertificate.cer"
-passin "pass:password"
Extract the CNG private key
openssl pkcs12 -in "yourcertificate.pfx" -nocerts –out “yourcertificate.pem"
-nodes -passin "pass:password" -passout "pass:password"
Convert the private key to RSA format
openssl rsa -inform PEM -in "yourcertificate.pem" -out "yourcertificate.rsa"
-passin "pass:password" -passout "pass:password"
Merge public keys with RSA private key to a new PFX file
openssl pkcs12 -export -in "yourcertificate.cer" -inkey "yourcertificate.rsa"
-out "yourcertificate-converted.pfx"
-passin "pass:password" -passout "pass:password"

Related

How to run 'dotnet dev-certs https --trust'?

I'm new in ASP.NET.
Environment:
Ubuntu 18.04
Visual Studio Code
.NET SDK 2.2.105
I'm in trouble with some command running.
I was reading tutorial at
https://learn.microsoft.com/ja-jp/aspnet/core/tutorials/razor-pages/razor-pages-start?view=aspnetcore-2.2&tabs=visual-studio-code
and ran this command:
dotnet dev-certs https --trust
I expect https://localhost should be trusted.
but I found the error message;
$ Specify --help for a list of available options and commands.
It seems that the command "dotnet dev-certs https" has no --trust options.
How to resolve this problem?
On Ubuntu the standard mechanism would be:
dotnet dev-certs https -v to generate a self-signed cert
convert the generated cert in ~/.dotnet/corefx/cryptography/x509stores/my from pfx to pem using openssl pkcs12 -in <certname>.pfx -nokeys -out localhost.crt -nodes
copy localhost.crt to /usr/local/share/ca-certificates
trust the certificate using sudo update-ca-certificates
verify if the cert is copied to /etc/ssl/certs/localhost.pem (extension changes)
verify if it's trusted using openssl verify localhost.crt
Unfortunately this does not work:
dotnet dev-certs https generates certificates that are affected by the issue described on https://github.com/openssl/openssl/issues/1418 and https://github.com/dotnet/aspnetcore/issues/7246:
$ openssl verify localhost.crt
CN = localhost
error 20 at 0 depth lookup: unable to get local issuer certificate
error localhost.crt: verification failed
due to that it's impossible to have a dotnet client trust the certificate
Workaround: (tested on Openssl 1.1.1c)
manually generate self-signed cert
trust this cert
force your application to use this cert
In detail:
manually generate self-signed cert:
create localhost.conf file with the following content:
[req]
default_bits = 2048
default_keyfile = localhost.key
distinguished_name = req_distinguished_name
req_extensions = req_ext
x509_extensions = v3_ca
[req_distinguished_name]
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_default = localhost
commonName_max = 64
[req_ext]
subjectAltName = #alt_names
[v3_ca]
subjectAltName = #alt_names
basicConstraints = critical, CA:false
keyUsage = keyCertSign, cRLSign, digitalSignature,keyEncipherment
[alt_names]
DNS.1 = localhost
DNS.2 = 127.0.0.1
generate cert using openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout localhost.key -out localhost.crt -config localhost.conf
convert cert to pfx using openssl pkcs12 -export -out localhost.pfx -inkey localhost.key -in localhost.crt
(optionally) verify cert using openssl verify -CAfile localhost.crt localhost.crt which should yield localhost.crt: OK
as it's not trusted yet using openssl verify localhost.crt should fail with
CN = localhost
error 18 at 0 depth lookup: self signed certificate
error localhost.crt: verification failed
trust this cert:
copy localhost.crt to /usr/local/share/ca-certificates
trust the certificate using sudo update-ca-certificates
verify if the cert is copied to /etc/ssl/certs/localhost.pem (extension changes)
verifying the cert without the CAfile option should work now
$ openssl verify localhost.crt
localhost.crt: OK
force your application to use this cert
update your appsettings.json with the following settings:
"Kestrel": {
"Certificates": {
"Default": {
"Path": "localhost.pfx",
"Password": ""
}
}
}
While the answer provided by #chrsvdb is helpful it does not solve all problems. I still had issue with service-to-service communication (HttpClient - PartialChain error) and also you must reconfigure Kestrel to use your own certificate. It is possible to create a self-signed certificate and import it to the .NET SDK. All you need is to specify the 1.3.6.1.4.1.311.84.1.1 extension in the certificate.
After that the cert can be imported into .NET Core SDK and trusted. Trusting in Linux is a bit hard as each application can have it's own certificate store. E.g. Chromium and Edge use nssdb which can be configured with certutil as described John Duffy. Unfortunately the location to the nssdb maybe different when you install application as snap. Then each application has its own database. E.g. for Chromium Snap the path will be $HOME/snap/chromium/current/.pki/nssdb, for Postman Snap the will be $HOME/snap/postman/current/.pki/nssdb and so on.
Therefor I have created a script which generates the cert, trusts it for Postman Snap, Chmromium Snap, current user nssdb and on system level. It also imports the script into the .NET SDK so it will be used by ASP.NET Core without changing the configuration. You can find more informations about the script in my blog post https://blog.wille-zone.de/post/aspnetcore-devcert-for-ubuntu
In adition to crisvdb answer, I've several information to add and is the continuation of the walktrough. I don't comment because is pretty complex comment this, but before this answer take a look to crisvdb answer first and then return to continue.
Take the "in detail" crisdb answer.
You can make your cert in any folder, can be or can't be in the same folder of the app.
Take openssl verify -CAfile localhost.crt localhost.crt as not optional step, mandatory. It will help.
Do not recompile or touch the code meanwhile you are doing this, in order to get first scenario clean.
If you run sudo update-ca-certificates that will answer you in wich folder the certified should be copied.
In some distributions, as Raspbian for Raspberry Pi, CA certificates are located in /etc/ssl/certs as well as /usr/share/ca-certificates/ and in some cases /usr/local/share/certificates.
Do not copy the cert manually to trusted certs, run sudo update-ca-certificates after you copy the cert in the right folder. If it doesn't work (doesn't update or add any certificate) copy it to every folder possible.
If you use a password while making the certificate, you should use it in the appsettings.json
If you get this error:
Interop+Crypto+OpenSslCryptographicException: error:2006D002:BIO
routines:BIO_new_file:system lib
Take in consideration that error means "access denied". It can be because you don't have permissions or related.
7b) Could be also that the file is not found, I use the entire path in the config:
"Path": "/home/user/www/myfolder1/myapp/localhost.pfx",
After that, and if everything works, you could see a 500 error if you are using Apache or Apache2.
If you get the following error in the apache logs of the site:
[ssl:error] [remote ::1:yourport] AH01961: SSL Proxy requested for
yoursite.com:443 but not enabled [Hint: SSLProxyEngine] [proxy:error]
AH00961: HTTPS: failed to enable ssl support for [::1]:yourport
(localhost)
you must set in the VirtualHost the following configuration after SSLEngine On and before your ProxyPass
SSLProxyEngine on
After that, and if everything works, you could see a 500 error if you are using Apache or Apache2.
If you get the following error in the apache logs of the site:
[proxy:error] [client x.x.x.x:port] AH00898: Error during SSL
Handshake with remote server returned by /
[proxy_http:error] [client x.x.x.x:port] AH01097: pass request body failed to [::1]:port
(localhost) from x.x.x.x()
you must set in the VirtualHost the following configuration after SSLProxyEngine on and before your ProxyPass
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
UPDATE
If you are renovating this, and using the same names, take in consideration that you should remove your pem file from etc/ssl/certs
UPDATE 2
If it returns:
Unhandled exception. Interop+Crypto+OpenSslCryptographicException: error:2006D002:BIO routines:BIO_new_file:system lib
Check that your pfx file is on 755 permissions.
If appsettings.json seems to be don't load (on port 5000 by default or SQL or any configuration doesn't load or can't be read), take in consideration that the dotnet must be executed on the same directory where is appsettings.json
Looks like this is a known issue with dotnet global tools and that specific command is only available for MacOS and Windows. See this issue on github: Issue 6066.
It seems like there may be a work around for Linux users based on this SO post: ASP.Net Core application service only listening to Port 5000 on Ubuntu.
For Chrome:
Click "Not Secure" in address bar.
Click Certificate.
Click Details.
Click Export.
Run: certutil -d sql:$HOME/.pki/nssdb -A -t "P,," -n {FILE_NAME} -i {FILE_NAME}
Restart Chrome.
It looks like the following could help to trust the dotnet dev certs:
https://blog.wille-zone.de/post/aspnetcore-devcert-for-ubuntu/
Then you will see also in the browser that certificate is OK and valid for the next yeat.
Give it a try...
Good luck!

QSslCertificate::importPkcs12 fails to parse PFX file

I'm trying to unpack my pkcs12 file in my Qt application - but having no luck. I'm building a Qt Console App (GUI disabled).
(I've followed this guide: https://github.com/trueos/sysadm-ui-qt/blob/master/src-qt5/gui_client/SSLNotes.txt)
Pkcs12 creation commands:
"openssl req -newkey rsa:2048 -nodes -keyout test_key.pem"
"openssl req -key test_key -new -x509 -out test_crt.crt"
"openssl pkcs12 -inkey test_key.pem -in test_crt.crt -export -passout stdin -out new.pfx"
Qt Code:
QString password="1234";
QFile pkcs("/Users/test/Desktop/certs/new.pfx");
pkcs.open(QFile::ReadOnly);
QSslKey key;
QSslCertificate cert;
QList<QSslCertificate> imported_certs;
static bool import=QSslCertificate::importPkcs12(&pkcs,&key,&cert,&imported_certs,QByteArray::fromStdString(password.toStdString()));
pkcs.close();
qDebug()<<import;
Manually extracting the key and the file have worked using openssl commands.
Error Message:
"Unimplemented Code."
Any ideas?
Try using Qt < 5.6 like Qt 5.5.
In the Qt 5.6 the default SSL backend was changed from OpenSSL to Secure Transport on the Mac OS platform.
This problem already filled as a Bug: https://bugreports.qt.io/browse/QTBUG-56596
After beating my head against the wall with this a few times with this sort of thing, I found a good shortcut.
I import the certificate into a Windows machine (ensuring that the private key is marked as exportable) and verify that the certificate path is valid in the certificate manager. If I need to import certificates, I do it here until the issued certificate path is good. Once this is done, I re-export the certificate and private key into a new PKCS12 file, including the root and intermediary certificates. This produces a single file that can be imported into an ASA or IOS router and works flawlessly because everything the unit needs is present in one file.
Be sure to delete the certificate from the Windows machine when you're done exporting the certificate set.
Maybe this link will help you out:
TAKEN FROM: https://supportforums.cisco.com/discussion/12347971/failed-parse-or-verify-imported-certifiate-asa-5505-831
QSslCertificate::importPkcs12() will return "Unimplemented code." on macOS or iOS platforms because those Qt kits were been configured to use Secure Transport instead of OpenSSL.
To get the best of both worlds, I found that one could keep their Qt kits configured for Secure Transport, but, at the same time, link to OpenSSL to implement an OpenSSL specific implementation of importPkcs12.
The following is a snippet where we turn on our custom implementation for macOS and iOS:
#ifdef Q_OS_IOS
#define IMPORTPKCS12_OPENSSL
#endif
#ifdef Q_OS_MACOS
#define IMPORTPKCS12_OPENSSL
#endif
bool ImportPkcs12Patch::importPkcs12(QIODevice *device, QSslKey *key, QSslCertificate *certificate, QList<QSslCertificate> *caCertificates, const QByteArray &passPhrase)
{
#ifdef IMPORTPKCS12_OPENSSL
return importPkcs12_openssl(device, key, certificate, caCertificates, passPhrase );
#else
return QSslCertificate::importPkcs12(device, key, certificate, caCertificates, passPhrase );
#endif
}
For a complete working example, consult the sample here:
https://github.com/stephenquan/QtImportPKCS12
To build OpenSSL prerequisites for iOS and macOS, consult here:
https://github.com/stephenquan/build_openssl

"unable to load Private Key" error when try to open openssl private key file on mac

How can I open a private key created on a linux server from a Mac ?
Some context : I'm using a local script called mup to deploy a Meteor app which requires the openssl private key.
I created the openssl private key on a linux ubuntu server I'm deploying to.
I am deploying from my Mac OS 10.9.5.
The mup script throws this error :
-----------------------------------STDERR-----------------------------------
Trying to initialize SSL contexts with your certificatesError loading rsa private key
-----------------------------------STDOUT-----------------------------------
So, the local mac can't open or access the private key.
This command works on the ubuntu server where the key was created :
openssl rsa -in private-key.nopass.key -check
However, If I run that same command on my local Mac on the same file ( which I copied and pasted from the terminal into Sublime text, with normal settings. ) , the local Mac throws this error :
unable to load Private Key
... routines:PEM_read_bio:no start line:pem_lib.c:701:Expecting: ANY PRIVATE KEY
So, I'm assuming the mup error has something to do with this.
On the local mac the openssl version is OpenSSL 1.0.2f 28 Jan 2016.
On the remote linux server the openssl version is OpenSSL 1.0.1f 6 Jan 2014.
so, the good folks at namecheap.com support helped me with this question. Turns out I was missing one dash!! haha.
This (4 dashes):
----BEGIN RSA PRIVATE KEY-----
Should have been this (5 dashes):
-----BEGIN RSA PRIVATE KEY-----
The takeaway is count your dashes when manually copying/pasting these files! It's far too easy to mistake four dashes for five.

java.security.InvalidKeyException: Algorithm not supported with Java WS Core 4.0.8

I'm trying to start the Java WS Core container version 4.0.8 from the Globus Tooklit. Before I can start the container, I need to create a grid proxy using grid-proxy-init. I am using my CERN certificate for this purpose. I have also downloaded the CERN Root CA and the CERN Trusted Certificate Authority certificates and configured globus to trust them. However, when I do grid-proxy-init, I get the following error:
Files used:
proxy : /tmp/x509up_u501
user key : ~/.globus/userkey.pem
user cert : ~/.globus/usercert.pem
Your identity: (correct identity)
Error: Wrong pass phrase
java.security.InvalidKeyException: Algorithm not supported.
at org.globus.gsi.OpenSSLKey.readPEM(OpenSSLKey.java:169)
at org.globus.gsi.OpenSSLKey.<init>(OpenSSLKey.java:105)
at org.globus.gsi.bc.BouncyCastleOpenSSLKey.<init>(BouncyCastleOpenSSLKey.java:45)
at org.globus.tools.DefaultProxyInit.loadKey(ProxyInit.java:608)
at org.globus.tools.ProxyInit.createProxy(ProxyInit.java:204)
at org.globus.tools.ProxyInit.main(ProxyInit.java:518)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.globus.bootstrap.BootstrapBase.launch(BootstrapBase.java:95)
at org.globus.bootstrap.Bootstrap.main(Bootstrap.java:37)
Please note that my CA certificates are in a non-standard location (~/.globus/certificates). I've tried using X509_CERT_DIR=~/.globus/certificates, but to no avail. Also, grid-proxy-init doesn't actually ask me for a passphrase. It just gives that error. I have no idea how to debug this further. I would appreciate any ideas about how to procee. Also, I would like to verify that globus is indeed recognising my CA certificates without any problems. Thanks!
Ok so I figured out what the problem was. I was converting the certificate to PEM from PKCS using:
openssl pkcs12 -in cert.p12 -out usercert.pem -nokeys
openssl pkcs12 -in cert.p12 -out userkey.pem -nocerts -nodes
Apparently this only extracts the private key from the certificate file but does not actually convert it to PEM format. For that I had to use the following command:
openssl pkcs12 -in cert.p12 -nocerts -nodes|openssl rsa -out userkey.pem -des3
This outputs the private key in the required format and grid-proxy-init works fine now.

godaddy cert not working with filezilla

here is what i have, running MS server 2008, IIS 7
from godaddy, a p7b intermediate file from godaddy and the cert in crt format. this is all they gave me. I need to get a private key file out of this to go with the crt and configure it to be used in filezilla. i tried just loading the p7b file into the private key section of filezilla server and that didnt work, didnt think it would. I have tried to extract the private key from the cert by creating a pfx file in the MMC then using openssl to extract the key using
openssl pkcs12 -in file.pfx -nocerts -out key.key
this returns something showing that the Microsofot Local Key set has no value.
I am completely lost on how to get this work, have been trying for a few days. Does anyone know how to get this to work with filezilla? Godaddy's support just doesnt seem to want to help.
Turns out this is what i needed:
c:\OpenSSL-Win32\bin>openssl pkcs12 -in file.pfx -nocerts –nodes -passin pass:123 | openssl rsa -out privatekey.pem
this got me a private RSA key, which is then put into filezilla as the private key and the cert in the cert field in filezillas settings. both of these files should be in a folder not protected by permissions and (not 100% sure on this part) should be in the same folder.
NOTE: this is after exporting private key from the MMC, this is the pfx file in question here, be sure the certificate is installed in IIS before doing this.

Resources