SAML SSO Integration with Keycloak as an identity provider.
This document will guide you through the task of setting up an excellent, open-source identity provider (KeyCloak) to work as an external authenticator and authorizer system for your ELK stack. The scenario is the usual:
A centralized, large Elasticsearch cluster
A Kibana installation
We want one, centralized multi-tenant Elasticsearch + Kibana
But with some more enterprise requirements:
Users need to be able to change their passwords independently
Users need to verify their emails
Group managers need to be able to add, remove, block (only) their users.
Keycloak is an advanced authentication server that lets user administer their credentials and speaks many authentication protocols, Including SAML2.0 SSO.
Setup KeyCloak
This tutorial was created using KeyCloak 8.0.1.
Download the standalone version of Keycloak from their official website
Run Keycloak: run bin/standalone.sh or equivalent for your platform.
Navigate to http://localhost:8080 and configure the admin user's credentials don't forget to fill the email address!
Login as admin
Follow the explanation below, or (if your KC version is the same or close enough to this) use the import function to load this configuration file
If you imported the JSON file, you should have a "ror" realm, and a SAML client called "ror" (keep this ID or change the "issuer" setting in kibana.yml) in the "master" realm. Please now select "ror" realm, navigate to "clients", click "ror" client and double check everything matches with your use case, as this guide assumes both Kibana, Elasticsearch and Keycloak are running on "localhost".
Configure Keycloak to work with ROR
First, we want to create a new dedicated "ror" realm, so we don't interfere with any other use of this Keycloak installation.
Then, let's create a SAML client for this realm:
Then, configure the SAML client according to your Kibana URL, in this example, Kibana responds to "https://localhost:5601/k"
Now that the client is saved, let's observe the "configure" tab, here we will extract the two logout and login endpoints that we will use for configuring our SAML connector in "kibana.yml".
Install ReadonlyREST Enterprise for Kibana
Please refer to our documentation on how to obtain and install ReadonlyREST Enterprise for Kibana. Also, remember that it relies on the Elasticsearch plugin to be configured as well.
Setup the SAML connector
Provided that you have ReadonlyREST Enterprise installed and configured, you can add the following configuration:
kibana.yml
# More on how to enable SSL on the official documentation of Kibanaserver.ssl.enabled:trueserver.ssl.key:/home/xx/selfsigned_ssl_localhost/localhost.keyserver.ssl.certificate:/home/xx/selfsigned_ssl_localhost/localhost.crtxpack.security.enabled:false# Skip this setting in the Kibana configuration for version 8.x, as it has been removed.server.basePath:/k# <-- optional, remember to change it in KCelasticsearch:hosts: ["https://localhost:9200"] # <-- our Elasticsearch responds to httpsssl.verificationMode:noneusername:kibanapassword:kibanareadonlyrest_kbn:logLevel:debugauth:# this secret string has to be longer than 256 chars, use environmental variables to fill it in maybe. signature_key: "9yzBfnLaTYLfGPzyKW9es76RKYhUVgmuv6ZtehaScj5msGpBpa5FWpwk295uJYaaffTFnQC5tsknh2AguVDaTrqCLfM5zCTqdE4UGNL73h28Bg4dPrvTAFQyygQqv4xfgnevBED6VZYdfjXAQLc8J8ywaHQQSmprZqYCWGE6sM3vzNUEWWB3kmGrEKa4sGbXhmXZCvL6NDnEJhXPDJAzu9BMQxn8CzVLqrx6BxDgPYF8gZCxtyxMckXwCaYXrxAGbjkYH69F4wYhuAdHSWgRAQCuWwYmWCA6g39j4VPge5pv962XYvxwJpvn23Y5KvNZ5S5c6crdG4f4gTCXnU36x92fKMQzsQV9K4phcuNvMWkpqVB6xMA5aPzUeHcGytD93dG8D52P5BxsgaJJE6QqDrk3Y2vyLw9ZEbJhPRJxbuBKVCBtVx26Ldd46dq5eyyzmNEyQGLrjQ4qd978VtG8TNT5rkn4ETJQEju5HfCBbjm3urGLFVqxhGVawecT4YM9Rry4EqXWkRJGTFQWQRnweUFbKNbVTC9NxcXEp6K5rSPEy9trb5UYLYhhMJ9fWSBMuenGRjNSJxeurMRCaxPpNppBLFnp8qW5ezfHgCBpEjkSNNzP4uXMZFAXmdUfJ8XQdPTWuYfdHYc5TZWnzrdq9wcfFQRDpDB2zX5Myu96krDt9vA7wNKfYwkSczA6qUQV66jA8nV4Cs38cDAKVBXnxz22ddAVrPv8ajpu7hgBtULMURjvLt94Nc5FDKw79CTTQxffWEj9BJCDCpQnTufmT8xenywwVJvtj49yv2MP2mGECrVDRmcGUAYBKR8G6ZnFAYDVC9UhY46FGWDcyVX3HKwgtHeb45Ww7dsW8JdMnZYctaEU585GZmqTJp2LcAWRcQPH25JewnPX8pjzVpJNcy7avfA2bcU86bfASvQBDUCrhjgRmK2ECR6vzPwTsYKRgFrDqb62FeMdrKgJ9vKs435T5ACN7MNtdRXHQ4fj5pNpUMDW26Wd7tt9bkBTqEGf"
saml_kc:# <--- Our SAML connector name, used in the path configured in KCbuttonName:"KeyCloak SAML SSO"enabled:truetype:"saml"issuer:"ror"# <-- called exactly like the SAML client in KCentryPoint:"http://localhost:8080/auth/realms/ror/protocol/saml"# <-- from KC configuration tab!kibanaExternalHost:'localhost:5601'protocol:"https"# <--- our Kibana responds to HTTPSusernameParameter:"nameID"groupsParameter:"Role"logoutUrl:"http://localhost:8080/auth/realms/ror/protocol/saml"# <-- from KC configuration tab!cert:/etc/ror/integration/certs/dag.crt# from KC realm keys tab <-- It can be also provided a string value
You can find a public PEM-encoded X.509 signing certificate as a string value by selecting the "keys" tab in your newly created realm. After clicking on a cert button, you can copy the value into kibana.yml SAML config cert parameter.
Don't forget setting up SAML requires some changes to security settings in readonlyrest.yml (on the Elasticsearch side). Security settings can also be changed via the ReadonlyREST Kibana app.
Setup Elasticsearch with ReadonlyREST
Our Elasticsearch needs to be available on HTTPS (more detailed info in our documentation), so we modify the elasticsearch.yml
append to elasticsearch.yml
xpack.security.enabled:falsehttp.type:ssl_netty4# <-- needed for ROR SSL
Write in readonlyrest.yml
readonlyrest:ssl:enable:truekeystore_file:"keystore.jks"keystore_pass:readonlyrestkey_pass:readonlyrestaudit:enabled:trueoutputs: - type:indexaccess_control_rules: - name:"::KIBANA-SRV::"auth_key:kibana:kibanaverbosity:error - name:"ReadonlyREST Enterprise instance #1"kibana:access:roindex:".kibana_sso"ror_kbn_auth:name:"kbn1"ror_kbn: - name:kbn1# It has to be the same string as we declared in kibana.yml. signature_key: "9yzBfnLaTYLfGPzyKW9es76RKYhUVgmuv6ZtehaScj5msGpBpa5FWpwk295uJYaaffTFnQC5tsknh2AguVDaTrqCLfM5zCTqdE4UGNL73h28Bg4dPrvTAFQyygQqv4xfgnevBED6VZYdfjXAQLc8J8ywaHQQSmprZqYCWGE6sM3vzNUEWWB3kmGrEKa4sGbXhmXZCvL6NDnEJhXPDJAzu9BMQxn8CzVLqrx6BxDgPYF8gZCxtyxMckXwCaYXrxAGbjkYH69F4wYhuAdHSWgRAQCuWwYmWCA6g39j4VPge5pv962XYvxwJpvn23Y5KvNZ5S5c6crdG4f4gTCXnU36x92fKMQzsQV9K4phcuNvMWkpqVB6xMA5aPzUeHcGytD93dG8D52P5BxsgaJJE6QqDrk3Y2vyLw9ZEbJhPRJxbuBKVCBtVx26Ldd46dq5eyyzmNEyQGLrjQ4qd978VtG8TNT5rkn4ETJQEju5HfCBbjm3urGLFVqxhGVawecT4YM9Rry4EqXWkRJGTFQWQRnweUFbKNbVTC9NxcXEp6K5rSPEy9trb5UYLYhhMJ9fWSBMuenGRjNSJxeurMRCaxPpNppBLFnp8qW5ezfHgCBpEjkSNNzP4uXMZFAXmdUfJ8XQdPTWuYfdHYc5TZWnzrdq9wcfFQRDpDB2zX5Myu96krDt9vA7wNKfYwkSczA6qUQV66jA8nV4Cs38cDAKVBXnxz22ddAVrPv8ajpu7hgBtULMURjvLt94Nc5FDKw79CTTQxffWEj9BJCDCpQnTufmT8xenywwVJvtj49yv2MP2mGECrVDRmcGUAYBKR8G6ZnFAYDVC9UhY46FGWDcyVX3HKwgtHeb45Ww7dsW8JdMnZYctaEU585GZmqTJp2LcAWRcQPH25JewnPX8pjzVpJNcy7avfA2bcU86bfASvQBDUCrhjgRmK2ECR6vzPwTsYKRgFrDqb62FeMdrKgJ9vKs435T5ACN7MNtdRXHQ4fj5pNpUMDW26Wd7tt9bkBTqEGf"