Thanks Oren for the explanation and the link to the scripts, that helped. I could get the server certificate running, I'm still struggling with the client certificates, will continue next week.
I'll describe issues I encountered, it might help you write the documentation.
1. Not sure which certificate generation script should I use so let's go with the Windows script (generate-server-cert.ps1).
- Edit the values to match my needs and successfully generate the certificate.
- Server startup fails with the following:
- System.InvalidOperationException: Unable to start the server due to invalid certificate configuration! Admin assistance required. ---> System.InvalidOperationException: Could not load certificate file C:\[...].pfx ---> Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: The specified network password is not correct
2. I honestly have no idea what this means so I fall back to the Linux script (generate-selfsigned-cert.sh), as I'm a bit familiar with openssl.
- Edit the values, generate the key and certificates.
- Same error, The specified network password is not correct.
- Realize that the certificate file is encrypted, no idea if is there a way to specify the certificate passphrase in the config.
3. -nodes to the rescue, generate the certificate unencrypted, server starts up successfully.
- Unable to do anything in the studio as I don't have a client certificate.
- When looking around in the studio (with SSL disabled), I can't find any way to manage client certificates.
4. Handy script obtain-client-cert.ps1 is available, let's give it a try: changed the URL and certificate file (to point to the server certificate).
...
Sending client cert request: {
"SecurityClearance": "ClusterAdmin",
"Name": "client-test",
"Password": null,
"Permissions": {
}
}
Invoke-WebRequest : The remote server returned an error: (500) Internal Server Error.
...
- -1-byte payload - I'm not very familiar with Invoke-WebRequest so I just assume this is not a problem.
- Fire up Fiddler and the output changes (no idea why - when I run the script directly it always returns 500):
...
Sending client cert request: {
"SecurityClearance": "ClusterAdmin",
"Name": "client-test",
"Password": null,
"Permissions": {
}
}
Invoke-WebRequest : The remote server returned an error: (403) Forbidden.
...
- Response in Fiddler says: {"Type":"InvalidAuth","Message":"This server requires client certificate for authentication, but none was provided by the client"}
- Ok, so I need to bootstrap the first client certificate without SSL enabled.
5. Disable SSL in the server, change the URL in the script, run the script, 500 Internal Server Error again, no way to find out why without Fiddler.
- - Response in Fiddler: {"Error":"System.FormatException: Could not convert Sparrow.Json.BlittableJsonReaderObject ('{}') to Sparrow.Json.BlittableJsonReaderArray ---> System.InvalidCastException: Object must implement IConvertible.\r\n... ...
- {"Error":"System.NullReferenceException: Object reference not set to an instance of an object.\r\n at Raven.Server.Utils.CertificateUtils.CreateSelfSignedClientCertificate(String subjectName, CertificateHolder certificateHolder) in C:\\Builds\\RavenDB-4.0-Beta\\src\\Raven.Server\\Utils\\CertificateUtils.cs:line 30\r\n at Raven.Server.Web.Authentication.AdminCertificatesHandler.<Generate>d__0.MoveNext() in C:\\Builds\\RavenDB-4.0-Beta\\src\\Raven.Server\\Web\\Authentication\\AdminCertificatesHandler.cs:line 34\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Raven.Server.Routing.RequestRouter.<HandlePath>d__5.MoveNext() in C:\\Builds\\RavenDB-4.0-Beta\\src\\Raven.Server\\Routing\\RequestRouter.cs:line 108\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()\r\n at Raven.Server.RavenServerStartup.<RequestHandler>d__12.MoveNext() in C:\\Builds\\RavenDB-4.0-Beta\\src\\Raven.Server\\RavenServerStartup.cs:line 154","Message":"Object reference not set to an instance of an object.","Type":"System.NullReferenceException","Url":"/admin/certificates"}
It's getting really late, I'll tackle this next week, but I'm starting to get lost. Not sure if I should have generated an authority certificate (generate-authority-cert.ps1) and use it for generating the server certificate or I'm missing some server configuration option or there is another problem somewhere. Also, I have several questions:
- - What is the recommended sequence of SSL certificate generation? Is my process okay (generate the certificate in a Linux machine, nothing else)? Or when running the server on a Windows system, I need to generate the authority certificate?
- - Is there a way to configure the certificate passphrase in the server config?
- - Is there a way to manage client certificates using the studio?
- - Do I need to bootstrap the first client certificate before enabling SSL?
- - What is the correct usage of obtain-client-cert.ps1?
- - Is $CertPath supposed to be configured to the server certificate (it's used in a variable $serverCert later, which implies yes, but is sent in -Certificate parameter in Invoke-WebRequest, which specifies the client certificate so I'm confused here).
- - Is $permissions supposed to be a dictionary?
- - What values can be used in $DatabaseAccess?
Sorry for the wall of text and lots of questions but although I try to follow the RavenDB 4 development and the news on the blog and in this group, it's difficult to figure out certain details. Also, I guess that documentation for all this is not (yet) available so I might be missing the understanding of crucial concepts behind the system. All of this would be very useful if included in official documentation.
Thanks
Andrej