Hey all, I'm trying to use PKI authentication in my cluster, meaning the client will need to present certificates in order to get data.
I wrote the following in elasticsearch.yml: xpack: security: authc: realms: pki1: type: pki
And removed my "native" realm.
I changed nothing else in my code (c#). Right now, I can still get data using my "elastic" user, and if I don't use it I get"missing authentication token for REST request".
Unless I don't understand something, this seems wrong, as I'm expecting a security exception of some sort.
I tried setting xpack.security.http.ssl.client_authentication: required.
This changes everything. Now I'm getting: 'The underlying connection was closed: An unexpected error occurred on a send.'
Which is good, I think. I generated a certificate for my client using certgen, and used it to generate an x509Certificate in C#, I also added the autogenerated CA that signed it to xpack.ssl.certificate_authorities, and mapped the CN to a role. Still getting this error. Installing the client's CA on the elastic machine didn't help either.
Where possible please use the code button (</>) when pasting in your config files so that it retains the correct formatting. Thanks.
There's a few things going on here:
The elastic user isn't part of the native realm, so removing that realm won't change whether the elastic user works. (More Info)
Simply enabling a PKI realm doesn't force that users need to use TLS/PKI. If you want to enforce client certificates you need to do that at the http layer with the xpack.security.http.ssl.client_authentication setting . (More Info)
You say I'm expecting a security exception but the error message you received (missing authentication token for REST request)is a security exception (on the Elasticsearch side, I haven't looked at the C# side) . Can you clarify how that message doesn't meet your expectation?
A working configuration for PKI would typically look something like this:
You don't have to use it. But removing the native realm doesn't change whether that user is available or not.
As a general rule your code shouldn't ever use the elastic user. It's a superuser, roughly equivalent to root on a unix system. Your code should be using it's own user (either representing the person logged in, or the application itself, depending on your security mode). Whether you authenticate that user via password or TLS certificate is up to you.
No, if you authenticate via certificate you do not need to provide a user.
For example this curl command (my apologies for not having a more windows-oriented example) will successfully authenticate a user using only a certificate (the password supplied is the passphrase on the certificate file, it's not sent to the server).
Still didn't cut it. I guess I need to show you some code now, but the problem is I have an infrastructure for other types of REST applications that I'm using, and I'm using RESTSharp in it. Here's my code:
System.Net.NetworkCredential c = new System.Net.NetworkCredential("elastic", "password!");
httpRequest.Credentials = c;
X509Certificate cert = new X509Certificate(@"path\client1.crt");
httpRequest.ClientCertificates = new X509CertificateCollection();
The paths I'm using are correct, as I can generate the certificate, and the rest of this code works fine without PKI. Do you have an idea as to what could go wrong?
I see. certgen generated this file along with a .key file. How do I use both of them in this context?
Same goes for your curl command. I'm trying it and getting curl: (58) unable to set private key file: 'client1.crt' type PEM
So I guess I do have a problem with the .crt file.
Cool, I was looking for the openssl command but couldn't find it, thanks. I packaged the certificate and key, gave a password, and gave the X509Certificate object the p12 file and the password. Still didn't work.
Can you think about anything else that might cause my issue? Maybe the certificate itself? I gave it the IP and DNS name of the client that's running it, but I don't know if ES even checks that.
We also have documentation for working with certificates with NEST, with a helper class, ClientCertificate to make it a little easier to set up on the client (.NET Framework only, as .NET Core does not allow the PrivateKey property to be set on the crypto service provider that is used to generate the pfx file at runtime.)