### Run the Fleet example script Source: https://docs.readonlyrest.com/elasticsearch/fleet.md Executes the quickstart script to deploy a full working environment including Elasticsearch, Kibana, Fleet Server, and an Elastic Agent. ```bash curl -sL https://raw.githubusercontent.com/beshu-tech/readonlyrest-examples/master/quickstart.sh | bash -s fleet ``` -------------------------------- ### Starting Elasticsearch and Kibana Source: https://docs.readonlyrest.com/examples/multiuser_guide Commands to launch the Elasticsearch and Kibana services. ```bash $ bin/elasticsearch ``` ```bash $ bin/kibana ``` -------------------------------- ### Install ReadonlyREST plugin from local file Source: https://docs.readonlyrest.com/kibana Install the plugin using a local zip file path, requiring the file:// protocol and an absolute path. ```bash bin/kibana-plugin install file:///home/user/downloads/readonlyrest_kbn-X.Y.Z_esW.Q.U.zip ``` -------------------------------- ### Install ReadonlyREST plugin via URL Source: https://docs.readonlyrest.com/kibana Commands to install the plugin using various query parameters for versioning and email authentication. ```bash bin/kibana-plugin install "https://portal.readonlyrest.com/download/kbn?edition=kbn_universal&email=" # ReadonlyREST Universal Kibana plugin ``` ```bash bin/kibana-plugin install "https://portal.readonlyrest.com/download/kbn?edition=kbn_universal&esVersion=7.6.1&email=" ``` ```bash bin/kibana-plugin install "https://portal.readonlyrest.com/download/kbn?edition=kbn_universal&esVersion=8.6.0&pluginVersion=1.46.0&email=" ``` -------------------------------- ### Install ReadonlyREST Plugin via Command Prompt Source: https://docs.readonlyrest.com/examples/saml-sso/adfs.md Commands to navigate to the Elasticsearch bin directory and install the plugin from a local zip file. ```bash cd "C:\Program Files\Elastic\ElasticSearch\7.6.2\bin" elasticsearch-plugin.bat install file:///C:/Users/lc-admin.AD/Downloads/readonlyrest-1.19.4_es7.6.2.zip ``` -------------------------------- ### Start Docker Compose services Source: https://docs.readonlyrest.com/kibana Command to initialize the containers defined in the docker-compose.yml file. ```bash docker-compose up ``` -------------------------------- ### Query documentation via HTTP GET Source: https://docs.readonlyrest.com/develop Perform an HTTP GET request to the documentation index to retrieve answers based on a specific question and optional goal. ```http GET https://docs.readonlyrest.com/changelog.md?ask=&goal= ``` -------------------------------- ### SAML Assertion Object Example Source: https://docs.readonlyrest.com/examples/saml-sso/azure_ad.md Example of the JSON object structure returned by Azure AD after a successful SAML authentication. ```javascript { "http://schemas.microsoft.com/claims/authnmethodsreferences": "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport", "http://schemas.microsoft.com/identity/claims/displayname": "Simone Scarduzio", "http://schemas.microsoft.com/identity/claims/identityprovider": "https://sts.windows.net/88af1572-1347-45b6-8f65-xxxxxxxxx/", "http://schemas.microsoft.com/identity/claims/objectidentifier": "486abf50-a61f-40e9-8a37-3ff6a6eeda26", "http://schemas.microsoft.com/identity/claims/tenantid": "88af1572-1347-45b6-8f65-xxxxxxxxxxxx", "http://schemas.microsoft.com/ws/2008/06/identity/claims/groups": [ "00f22de3-0d59-4867-8e1a-xxxxxxxxxxxx", "dbe4ff5a-deba-419f-a653-xxxxxxxxxxxx", "3c19b288-263c-4dd1-9947-xxxxxxxxxxxx" ], "http://schemas.microsoft.com/ws/2008/06/identity/claims/wids": "62e90394-69f5-4237-9190-xxxxxxxxxxxx", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname": "Simone", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name": "Simone@ror-enterprise-test.com", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname": "Scarduzio", "issuer": "https://sts.windows.net/88af1572-1347-45b6-8f65-xxxxxxxxxxxx/", "nameID": "Simone@ror-enterprise-test.com", "nameIDFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", "sessionIndex": "_97f290ee-2ff6-445f-a0c6-xxxxxxxxxxxx", "user": "Simone Scarduzio" } ``` -------------------------------- ### Configure SAML Additional Parameters Source: https://docs.readonlyrest.com/kibana Example of setting additional SAML parameters within the readonlyrest_kbn configuration block. ```yaml readonlyrest_kbn: auth: saml_serv1: audience: "https://sp.example.com/metadata"` [...] ``` -------------------------------- ### Retrieve Index Templates with Visibility Filtering Source: https://docs.readonlyrest.com/elasticsearch/indices-rule-templates.md Examples showing how admin users see all templates versus how restricted users see only templates matching their allowed index patterns. ```bash $ curl -vk -u admin:admin "http://127.0.0.1:9200/_index_template?pretty" HTTP/1.1 200 OK content-type: application/json; charset=UTF-8 { "index_templates" : [ { "name" : "t1", "index_template" : { "index_patterns" : ["i*"], "template" : { "aliases" : { "idev2" : { }, "idev3" : { }, "idev1" : { } } }, "composed_of" : [ ] } }, { "name" : "t2", "index_template" : { "index_patterns" : ["idev1_*"], "template" : { "aliases" : { "admin_idev" : { }, "idev1" : { } } }, "composed_of" : [ ], "priority" : 1 } }, { "name" : "t3", "index_template" : { "index_patterns" : ["idev2_*"], "template" : { "aliases" : { "idev2" : { }, "admin_idev" : { } } }, "composed_of" : [ ], "priority" : 1 } }, { "name" : "t4", "index_template" : { "index_patterns" : ["idev1_*", "idev2_*"], "template" : { "aliases" : { "idev2" : { }, "admin_idev" : { }, "idev1" : { } } }, "composed_of" : [ ], "priority" : 2 } } ] } ``` ```bash $ curl -vk -u dev1:test "http://127.0.0.1:9200/_index_template?pretty" HTTP/1.1 200 OK content-type: application/json; charset=UTF-8 { "index_templates" : [ { "name" : "t1", "index_template" : { "index_patterns" : ["i*"], "template" : { "aliases" : { "idev1" : { } } }, "composed_of" : [ ] } }, { "name" : "t2", "index_template" : { "index_patterns" : ["idev1_*"], "template" : { "aliases" : { "idev1" : { } } }, "composed_of" : [ ], "priority" : 1 } }, { "name" : "t4", "index_template" : { "index_patterns" : ["idev1_*"], "template" : { "aliases" : { "idev1" : { } } }, "composed_of" : [ ], "priority" : 2 } } ] } ``` -------------------------------- ### Configure cookie settings Source: https://docs.readonlyrest.com/kibana Example configuration for cookie security and naming in kibana.yml. ```yaml readonlyrest_kbn.cookieName: rorCookie readonlyrest_kbn.cookiePass: readonlyrest_kbn.cookies.sameSite: strict # lax | strict | none readonlyrest_kbn.cookies.secure: true # explicit override for reverse-proxy setups ``` -------------------------------- ### Example JWT Authentication URL Source: https://docs.readonlyrest.com/kibana A sample URL structure for initiating a Kibana session using a JWT token. ```text http://kibana:5601/login?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ ``` -------------------------------- ### Create and Install gMSA Source: https://docs.readonlyrest.com/examples/saml-sso/adfs.md Creates a group Managed Service Account and associates it with the local computer for AD FS service usage. ```powershell $Name = 'sa_adfs' $Params = @{ "Name" = $Name "DNSHostName" = 'lc-win2019-02.ad.lc-test.local' "PrincipalsAllowedToRetrieveManagedPassword" = 'lc-win2019-02$' "ServicePrincipalNames" = 'http/lc-win2019-02.ad.lc-test.local' } $ServiceAccount = New-ADServiceAccount @Params Install-ADServiceAccount -Identity $Name Add-ADComputerServiceAccount -Identity 'lc-win2019-02' -ServiceAccount $ServiceAccount ``` -------------------------------- ### Run Keycloak Docker Container Source: https://docs.readonlyrest.com/examples/oidc-sso/keycloak_oidc Command to start a Keycloak instance using the official Docker image with specified admin credentials. ```bash docker run -e KEYCLOAK_USER= -e KEYCLOAK_PASSWORD= jboss/keycloak ``` -------------------------------- ### Activate via Environment Variable Source: https://docs.readonlyrest.com/universal-builds Set the ROR_ACTIVATION_KEY variable before starting Kibana, commonly used in Docker environments. ```bash $ export ROR_ACTIVATION_KEY= $ bin/kibana ``` -------------------------------- ### Testing index access with curl Source: https://docs.readonlyrest.com/elasticsearch/index-not-found-examples.md Examples of using curl to verify index access and observe how unauthorized or missing indices are handled. ```bash $ curl -v -u userA:secret "http://127.0.0.1:9200/index_a?pretty" HTTP/1.1 200 OK content-type: application/json; charset=UTF-8 content-length: 611 { "index_a" : { "aliases" : { }, "mappings" : { ... } "settings" : { ... } } } ``` ```bash $ curl -i -u userA:secret "http://127.0.0.1:9200/nonexistent?pretty" 18:15:28 HTTP/1.1 404 Not Found content-type: application/json; charset=UTF-8 content-length: 634 { "error" : { "root_cause" : [ ... ], "type" : "index_not_found_exception", "reason" : "no such index [nonexistent_ROR_ZA1FXDsR7M]", "resource.type" : "index_or_alias", "resource.id" : "nonexistent_ROR_ZA1FXDsR7M", "index_uuid" : "_na_", "index" : "nonexistent_ROR_ZA1FXDsR7M" }, "status" : 404 } ``` ```bash $ curl -v -u userA:secret "http://127.0.0.1:9200/index_b?pretty" HTTP/1.1 404 Not Found content-type: application/json; charset=UTF-8 content-length: 610 { "error" : { "root_cause" : [ ... ], "type" : "index_not_found_exception", "reason" : "no such index [index_b_ROR_QcskliAl8A]", "resource.type" : "index_or_alias", "resource.id" : "index_b_ROR_QcskliAl8A", "index_uuid" : "_na_", "index" : "index_b_ROR_QcskliAl8A" }, "status" : 404 } ``` ```bash $ curl -i -u userA:secret "http://127.0.0.1:9200/index*?pretty" 19:58:29 HTTP/1.1 200 OK content-type: application/json; charset=UTF-8 content-length: 611 { "index_a" : { "aliases" : { }, "mappings" : { ... }, "settings" : { ... } } } ``` ```bash $ curl -i -u userA:secret "http://127.0.0.1:9200/index_userA*?pretty" 20:05:10 HTTP/1.1 200 OK content-type: application/json; charset=UTF-8 content-length: 4 { } ``` ```bash $ curl -i -u userA:secret "http://127.0.0.1:9200/index_b*?pretty" 20:14:34 HTTP/1.1 200 OK content-type: application/json; charset=UTF-8 content-length: 4 { } ``` -------------------------------- ### Resulting JWT Deep Link Example Source: https://docs.readonlyrest.com/kibana An example of a fully encoded JWT deep link URL. ```text http://localhost:5601/login?nextUrl=%2Fapp%2Fkibana%23%2Fvisualize%2Fedit%2F28dcde30-2258-11e8-82a3-af58d04b3c02%3F_g%3D%28%29&jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ ``` -------------------------------- ### GET /changelog.md Source: https://docs.readonlyrest.com/develop Queries the documentation index with a specific question and optional goal to receive a direct answer and relevant excerpts. ```APIDOC ## GET /changelog.md ### Description Perform an HTTP GET request on the documentation index to ask a question and receive a direct answer along with relevant excerpts and sources. ### Method GET ### Endpoint https://docs.readonlyrest.com/changelog.md ### Parameters #### Query Parameters - **ask** (string) - Required - The immediate question to ask, written in natural language. - **goal** (string) - Optional - Describes the broader end goal to tailor the answer. ``` -------------------------------- ### Configure Impersonation with Wildcard Usernames Source: https://docs.readonlyrest.com/kibana/impersonation Example configuration for handling wildcard username patterns in access control rules, requiring manual entry for impersonation. ```yaml readonlyrest: access_control_rules: - name: "LDAP group g1" type: allow groups_any_of: ["g1"] users: - username: "admin*" // To impersonate a user with a username matching 'admin*' you need to enter the username manually, like 'admin123' groups: - g1: group1 ldap_auth: name: "ldap1" groups_any_of: ["group1"] ldaps: - name: ldap1 [..] impersonation: [...] ``` -------------------------------- ### Example SAML Metadata Response Source: https://docs.readonlyrest.com/kibana Sample XML metadata generated by the ReadonlyREST Kibana plugin for Identity Provider configuration. ```xml urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress ``` -------------------------------- ### Activate via Plugin License API Source: https://docs.readonlyrest.com/universal-builds Send a POST request to the Kibana instance to register an activation key after the service has started. ```http POST http://:5601/api/ror/license?overwrite=true { "token": "your activation key" } ``` -------------------------------- ### ReadonlyREST access control configuration Source: https://docs.readonlyrest.com/elasticsearch/index-not-found-examples.md Example configuration for defining index access rules for specific users. ```yaml readonlyrest: enable: true access_control_rules: - name: "user A indices" indices: ["index_a"] auth_key: userA:secret - name: "user B indices" indices: ["indexB"] auth_key: userB:secret ``` -------------------------------- ### ReadonlyREST Configuration for Index Template Examples Source: https://docs.readonlyrest.com/elasticsearch/indices-rule-templates.md Base configuration defining access control rules for admin and two developer users. ```yaml readonlyrest: access_control_rules: - name: "admin block" verbosity: error type: allow auth_key: admin:admin - name: "dev1 block" indices: ["idev1", "idev1_*"] auth_key: dev1:test - name: "dev2 block" indices: ["idev2", "idev2_*"] auth_key: dev2:test ``` -------------------------------- ### Build Kibana with ReadonlyREST Plugin Source: https://docs.readonlyrest.com/eck Dockerfile and build command to create a custom Kibana image with the ReadonlyREST plugin installed and patched. ```dockerfile # 'Dockerfile' file content ARG KBN_VERSION FROM docker.elastic.co/kibana/kibana:${KBN_VERSION} ARG KBN_VERSION ARG ROR_VERSION RUN /usr/share/kibana/bin/kibana-plugin install "https://portal.readonlyrest.com/download/kbn?esVersion=$KBN_VERSION&pluginVersion=$ROR_VERSION&edition=kbn_universal&email=[YOUR-EMAIL-ADDRESS]" USER root RUN /usr/share/kibana/node/bin/node plugins/readonlyrestkbn/ror-tools.js patch --I_UNDERSTAND_AND_ACCEPT_KBN_PATCHING=yes && \ chown -R kibana:kibana /usr/share/kibana/config USER 1000:0 ``` ```bash docker build --build-arg KBN_VERSION=8.14.3 --build-arg ROR_VERSION=1.59.0 -t kibana-with-ror . ``` -------------------------------- ### Configure FLS engine to use ES only Source: https://docs.readonlyrest.com/elasticsearch/fls-engine.md Example configuration for setting the global FLS engine to 'es' mode within the readonlyrest settings. ```yaml readonlyrest: global_settings: fls_engine: "es" access_control_rules: - name: "user_using_fields" auth_key: user:pass fields: ["~someNotAllowedField"] ``` -------------------------------- ### Attempt to Create Unauthorized Index Template Source: https://docs.readonlyrest.com/elasticsearch/indices-rule-templates.md Example of a forbidden request where the user lacks permissions for the specified index patterns and aliases. ```bash $ curl -vk -u dev1:test -XPUT "http://127.0.0.1:9200/_index_template/test?pretty" -H "Content-Type: application/json" -d \ '{ "index_patterns":["index*"], "template": { "aliases": { "dev1_index": {}, "dev2_index": {} } } }' HTTP/1.1 403 Forbidden content-type: application/json; charset=UTF-8 { "error" : { "root_cause" : [ { "reason" : "forbidden", "due_to" : ["OPERATION_NOT_ALLOWED"] } ], "reason" : "forbidden", "due_to" : ["OPERATION_NOT_ALLOWED"], "status" : 403 } } ``` -------------------------------- ### Example ECS Serialized Event Source: https://docs.readonlyrest.com/elasticsearch/audit.md A sample JSON output representing an audit event mapped to the ECS 1.6 schema. ```json { "@timestamp": "2017-06-30T09:41:58Z", "trace" : { "id" : "correlation_id_123" }, "ecs" : { "version" : "1.6.0" }, "source" : { "address" : "192.168.0.123" }, "destination" : { "address" : "192.168.100.100" }, "http" : { "request" : { "method" : "GET", "body" : { "bytes" : 123, "content" : "Full content of the request" } } }, "event" : { "duration" : 5000000000, "reason" : "RRTestConfigRequest", "action" : "cluster:internal_ror/user_metadata/get", "id" : "trace_id_123", "outcome" : "failure" }, "error" : {}, "user" : { "effective" : { "name" : "impersonated_by_user" }, "name" : "logged_user" }, "url" : { "path" : "/path/to/resource" }, "labels" : { "es_cluster_name" : "testEsCluster", "es_task_id" : 123, "es_node_name" : "testEsNode", "ror_acl_history" : "historyEntry1, historyEntry2", "ror_detailed_reason" : "default", "ror_involved_indices" : [], "ror_final_state" : "FORBIDDEN" } } ``` -------------------------------- ### Run Kibana with ReadonlyREST using Docker Compose Source: https://docs.readonlyrest.com/kibana Defines a multi-container setup for Kibana and Elasticsearch with ReadonlyREST plugins enabled. ```yaml # docker-compose.yml file content services: kbn-ror: image: beshultd/kibana-readonlyrest:8.14.3-ror-latest user: "0:0" ports: - "5601:5601" environment: - I_UNDERSTAND_AND_ACCEPT_KBN_PATCHING=yes - ELASTICSEARCH_HOSTS=https://es-ror:9200 - ELASTICSEARCH_USERNAME=kibana - ELASTICSEARCH_PASSWORD=kibana - ELASTICSEARCH_SSL_VERIFICATIONMODE=none - readonlyrest_kbn__cookiePass=abcd1234abcd1234abcd1234abcd1234 # this is an equivalent of the `readonlyrest_kbn.cookiePass` setting defined in kibana.yml depends_on: - es-ror es-ror: image: beshultd/elasticsearch-readonlyrest:8.14.3-ror-latest user: "0:0" ports: - "9200:9200" environment: - I_UNDERSTAND_AND_ACCEPT_ES_PATCHING=yes - KIBANA_USER_PASS=kibana - ADMIN_USER_PASS=admin - discovery.type=single-node ``` -------------------------------- ### Configure group mapping in ReadonlyREST Source: https://docs.readonlyrest.com/elasticsearch/groups-rule-mapping.md Example demonstrating plain local group assignment, common group mapping, and detailed group mapping using both simple and structured group definitions. ```yaml readonlyrest: access_control_rules: - name: "Viewer block" indices: ["logstash-viewers*"] groups_any_of: ["viewers"] - name: "DevOps block" indices: ["logstash-devops*"] groups_any_of: ["devops"] [...] users: # PLAIN LOCAL GROUPS EXAMPLE # Local user "joe" is associated to local group "editors" - username: "joe" groups: ["editors"] auth_key: joe:password # COMMON GROUP MAPPING EXAMPLE # Externally authenticated user + authorization via external groups provider + groups common mapping # Users belonging to "external_group1" OR "external_group2" are authorized as "viewers" AND "editors" in the ACL. - username: "*" groups: ["viewers", "editors"] external_authentication: "ext1" groups_provider_authorization: user_groups_provider: "ext2" groups_any_of: ["external_group1", "external_group2"] # DETAILED GROUP MAPPING EXAMPLE # LDAP authenticated user + authorization via LDAP + groups detailed mapping (any LDAP user is valid; groups from `ldap1` are mapped to local groups) # Users belonging to LDAP role `ldap_role_ops`, or any other LDAP role that matched `ldap_*_devops` pattern, will be mapped to "devops" local group # AND # Users belonging to LDAP `ldap_role_dev` are mapped to "developers" local group - username: "*" groups: - devops: ["ldap_role_ops", "ldap_*_devops"] - developers: ["ldap_role_dev"] ldap_auth: name: "ldap1" groups_any_of: ["ldap_*_devops", "ldap_role_ops", "ldap_role_dev"] # DETAILED GROUP MAPPING EXAMPLE (STRUCTURED GROUPS) # LDAP authenticated user + authorization via LDAP + groups detailed mapping (any LDAP user is valid; groups from `ldap1` are mapped to local groups) # Users belonging to LDAP role `ldap_role_ops`, or any other LDAP role that matched `ldap_*_devops` pattern, will be mapped to "devops" local group # AND # Users belonging to LDAP `ldap_role_dev` are mapped to "developers" local group - username: "*" groups: - local_group: id: "devops" name: "DevOps Group" external_group_ids: ["ldap_role_ops", "ldap_*_devops"] - local_group: id: "developers" name: "Developers Group" external_group_ids: ["ldap_role_dev"] ldap_auth: name: "ldap1" groups_any_of: ["ldap_*_devops", "ldap_role_ops", "ldap_role_dev"] external_authentication_service_configs: - name: "ext1" [...] user_groups_providers: - name: ext2 [...] ldaps: - name: ldap1 [...] ``` -------------------------------- ### Uninstall ReadonlyREST Plugin Source: https://docs.readonlyrest.com/kibana Remove the plugin after unpatching the Kibana installation. ```bash node/bin/node plugins/readonlyrestkbn/ror-tools.js unpatch bin/kibana-plugin remove readonlyrestkbn ``` ```bash node/glibc-217/bin/node plugins/readonlyrestkbn/ror-tools.js unpatch bin/kibana-plugin remove readonlyrestkbn ``` ```bash node/default/bin/node plugins/readonlyrestkbn/ror-tools.js unpatch bin/kibana-plugin remove readonlyrestkbn ``` ```shell node\default\node plugins\readonlyrestkbn\ror-tools.js unpatch bin/kibana-plugin remove readonlyrestkbn ``` ```bash bin/kibana-plugin remove readonlyrest_kbn ``` -------------------------------- ### Example audit event JSON structure Source: https://docs.readonlyrest.com/elasticsearch/audit.md A sample JSON object representing the data points captured in a single audit event. ```json { "error_message": null, "headers": [ "Accept", "Authorization", "content-length", "Host", "User-Agent" ], "acl_history": "[[::LOGSTASH::->[auth_key->false]], [kibana->[auth_key->false]], [::RO::->[auth_key->false]], [::RW::->[kibana->true, indices->true, auth_key->true]]]", "origin": "127.0.0.1", "final_state": "ALLOWED", "task_id": 1158, "type": "SearchRequest", "req_method": "GET", "path": "/readonlyrest_audit-2017-06-29/_search?pretty", "indices": [ "readonlyrest_audit-2017-06-29" ], "@timestamp": "2017-06-30T09:41:58Z", "content_len_kb": 0, "error_type": null, "processingMillis": 0, "action": "indices:data/read/search", "matched_block": "::RW::", "id": "933409190-292622897#1158", "content_len": 0, "logged_user": "simone", "presented_identity": "simone" } ``` -------------------------------- ### Delete Index Template Access Control Source: https://docs.readonlyrest.com/elasticsearch/indices-rule-templates.md Examples demonstrating forbidden and allowed attempts to delete an index template based on user permissions. ```bash $ curl -vk -u dev2:test -XDELETE "http://127.0.0.1:9200/_index_template/test?pretty" HTTP/1.1 403 Forbidden content-type: application/json; charset=UTF-8 { "error" : { "root_cause" : [ { "reason" : "forbidden", "due_to" : ["OPERATION_NOT_ALLOWED"] } ], "reason" : "forbidden", "due_to" : ["OPERATION_NOT_ALLOWED"], "status" : 403 } } ``` ```bash $ curl -vk -u dev1:test -XDELETE "http://127.0.0.1:9200/_index_template/test?pretty" HTTP/1.1 200 OK content-type: application/json; charset=UTF-8 { "acknowledged" : true } ``` -------------------------------- ### Example of Misconfigured Authentication ACL Source: https://docs.readonlyrest.com/kibana This configuration demonstrates a common error where an IP-based rule allows requests without proper authentication. ```yaml readonlyrest: access_control_rules: - name: "LDAP Auth" ldap_authentication: ... - name: "Allow requests from localhost" hosts: ["127.0.0.1"] ``` -------------------------------- ### Configure Login Screen Layout Source: https://docs.readonlyrest.com/kibana Set the login title and subtitle to enable the two-column layout. ```yaml readonlyrest_kbn.login_title: "Some Title" readonlyrest_kbn.login_subtitle: "Longer text any HTML is supported including ifrmaes" ``` -------------------------------- ### Copy Keystore to Elasticsearch Config Source: https://docs.readonlyrest.com/examples/secure_logstash.md Moves the generated keystore file into the Elasticsearch configuration directory. ```bash cp keystore.jks /elasticsearch/config/ ``` -------------------------------- ### Check Existing Index Templates Source: https://docs.readonlyrest.com/elasticsearch/indices-rule-templates.md Verify the current state of index templates using an admin account. ```bash $ curl -vk -u admin:admin "http://localhost:9200/_index_template?pretty" HTTP/1.1 200 OK content-type: application/json; charset=UTF-8 { "index_templates" : [ ] } ``` -------------------------------- ### Verify custom serializer initialization Source: https://docs.readonlyrest.com/elasticsearch/audit.md Log output to confirm the custom serializer is correctly loaded by the plugin. ```text [2023-03-26T16:28:40,471][INFO ][t.b.r.a.f.d.AuditingSettingsDecoder$] Using custom serializer: JavaCustomAuditLogSerializer ``` -------------------------------- ### Convert Keystore to BCFKS Format Source: https://docs.readonlyrest.com/elasticsearch/fips.md Use the keytool utility with the BouncyCastle FIPS provider to convert existing JKS or PKCS12 keystores to BCFKS. ```bash keytool \ -importkeystore \ -srckeystore SOURCE_KEYSTORE_FILENAME \ -destkeystore DEST_KEYSTORE_FILENAME \ -srcstoretype SOURCE_KEYSTORE_TYPE \ -deststoretype DEST_KEYSTORE_TYPE \ -srcstorepass SOURCE_KEYSTORE_PASSWORD \ -deststorepass DEST_KEYSTORE_PASSWORD \ -providerpath ./bc-fips-1.0.2.1.jar \ -provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider ``` -------------------------------- ### Enable AD FS IdP Signon Page Source: https://docs.readonlyrest.com/examples/saml-sso/adfs.md Run this command in an Administrative PowerShell session to enable the IdP-initiated sign-on page after restarting the server. ```powershell Set-ADFSProperties -EnableIdPInitiatedSignonPage $True ``` -------------------------------- ### Generate Self-Signed Keystore Source: https://docs.readonlyrest.com/examples/secure_logstash.md Creates a JKS keystore for SSL communication using keytool. ```bash keytool -genkey -keyalg RSA -alias selfsigned -keystore keystore.jks -storepass readonlyrest -validity 360 -keysize 2048 ``` -------------------------------- ### Generate Self-Signed Certificates with OpenSSL Source: https://docs.readonlyrest.com/examples/saml-sso/adfs.md Use this command in an administrative command prompt to create the X509 PEM certificates required by Kibana for SSL. ```bash "C:\Program Files\OpenSSL-Win64\bin\openssl.exe" req -x509 -sha256 -nodes -days 730 -newkey rsa:2048 -keyout localhost-key.pem -out localhost.pem -subj "/C=US/ST=IL/L=Bloomington/O=lc-test/CN=10.0.0.6" ``` -------------------------------- ### Configure OIDC client additional parameters Source: https://docs.readonlyrest.com/kibana Defines metadata, JWKS keys, and options for the OpenID Connect client configuration. ```yaml readonlyrest_kbn.auth: oidc_kc: [...] clientAdditionalParameters: metadata: response_types: ['code'] redirect_uris: ['https://my-app/callback'] jwks: keys: - kty: 'RSA' use: 'sig' alg: 'RS256' kid: 'key1' n: 'PLACEHOLDER_TO_CHANGE_INTO_REAL_CERTIFICATE' e: 'AQAB' options: additionalAuthorizedParties: 'my-app' ``` -------------------------------- ### Build Java serializer JAR Source: https://docs.readonlyrest.com/elasticsearch/audit.md Command to compile the Java-based custom audit serializer. ```bash mvn package ``` -------------------------------- ### Create Component Template with Forbidden Alias Source: https://docs.readonlyrest.com/elasticsearch/indices-rule-templates.md Attempting to create a component template with an unauthorized alias results in a 403 Forbidden error. ```bash $ curl -vk -u dev1:test "http://localhost:9200/_component_template/ctemp1?pretty" -XPUT -H "Content-Type: application/json" -d \ '{ "template": { "settings": { "index.number_of_replicas": 0 }, "aliases": { "idev1": {}, "idev2": {} } } }' HTTP/1.1 403 Forbidden content-type: application/json; charset=UTF-8 { "error" : { "root_cause" : [ { "reason" : "forbidden", "due_to" : ["OPERATION_NOT_ALLOWED"] } ], "reason" : "forbidden", "due_to" : ["OPERATION_NOT_ALLOWED"], "status" : 403 } } ``` -------------------------------- ### Create Component Template with Authorized Alias Source: https://docs.readonlyrest.com/elasticsearch/indices-rule-templates.md Successful creation of a component template when all defined aliases are authorized for the user. ```bash $ curl -vk -u dev1:test "http://localhost:9200/_component_template/ctemp1?pretty" -XPUT -H "Content-Type: application/json" -d \ '{ "template": { "settings": { "index.number_of_replicas": 0 }, "aliases": { "idev1": {} } } }' HTTP/1.1 200 OK content-type: application/json; charset=UTF-8 { "acknowledged" : true } ``` -------------------------------- ### Create Authorized Index Template Source: https://docs.readonlyrest.com/elasticsearch/indices-rule-templates.md Successful request where the user has explicit access to the index patterns and aliases defined in the template. ```bash $ curl -vk -u dev1:test -XPUT "http://127.0.0.1:9200/_index_template/test?pretty" -H "Content-Type: application/json" -d \ '{ "index_patterns":["idev1_test*"], "template": { "aliases": { "idev1": {}, "idev1_test": {} } } }' HTTP/1.1 200 OK content-type: application/json; charset=UTF-8 { "acknowledged" : true } ``` -------------------------------- ### Build Scala serializer JAR Source: https://docs.readonlyrest.com/elasticsearch/audit.md Command to compile the Scala-based custom audit serializer. ```bash sbt assembly ``` -------------------------------- ### Configure Data Stream Output Source: https://docs.readonlyrest.com/elasticsearch/audit.md Final configuration after migration to use only the data_stream output. ```yaml readonlyrest: audit: enabled: true outputs: - type: data_stream data_stream: "custom_audit_data_stream" ``` -------------------------------- ### Retrieve plugin checksums Source: https://docs.readonlyrest.com/kibana Use curl to verify the integrity of the plugin download by requesting a sha1 checksum. ```bash curl -vvv "https://portal.readonlyrest.com/download/kbn?esVersion=8.6.0&pluginVersion=1.46.0&email=your@emailaddress.com&edition=kbn_universal&checksum=true" [...] curl -vvv "https://portal.readonlyrest.com/download/es?esVersion=8.6.0&pluginVersion=1.46.0&checksum=true" [...] ``` -------------------------------- ### Clone ReadonlyREST repository Source: https://docs.readonlyrest.com/elasticsearch/audit.md Initial step to obtain the plugin source code for custom serializer development. ```bash git clone git@github.com:sscarduzio/elasticsearch-readonlyrest-plugin.git ``` -------------------------------- ### Configure Custom Login Logo Source: https://docs.readonlyrest.com/kibana Set a custom logo for the login page using a URL or a local file path. ```yaml readonlyrest_kbn.login_custom_logo: 'https://.../logo.png' ``` ```yaml readonlyrest_kbn.login_custom_logo: '/pkp/legacy/web/assets/' ``` -------------------------------- ### Enable Audit Events with Defaults Source: https://docs.readonlyrest.com/elasticsearch/audit.md Enables global audit logging while demonstrating how to disable it for specific access control blocks. ```yaml readonlyrest: audit: enabled: true access_control_rules: - name: Kibana type: allow auth_key: kibana:kibana verbosity: error audit: # the `audit` section is optional, by default audit is enabled for each block enabled: false - name: "::RO::" auth_key: simone:ro kibaba: access: ro ``` -------------------------------- ### Configure ADFS SAML Integration Source: https://docs.readonlyrest.com/kibana Required configuration adjustments for Active Directory Federation Services compatibility. ```yaml readonlyrest_kbn: auth: saml_adfs: authnContext: "http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/windows" # Name identifier format to request auth context.` identifierFormat: null # Name identifier format to request from identity provider.` [...] ``` -------------------------------- ### Configure OIDC Client Authentication Method Source: https://docs.readonlyrest.com/kibana Sets the method for sending client credentials to the identity provider. ```yaml readonlyrest_kbn: auth: oidc_kc: tokenEndpointAuthMethod: 'client_secret_post' #Available options: client_secret_basic (default) or client_secret_post [...] ``` -------------------------------- ### Provision Active Directory Test Users Source: https://docs.readonlyrest.com/examples/saml-sso/adfs.md Run this script on the domain controller to create multiple test users. It sets the mail attribute required for SAML username mapping. ```powershell Import-Module -Name 'ActiveDirectory' $Domain = 'ad.lc-test.local'\ $OU = 'CN=Users,DC=ad,DC=lc-test,DC=local' $Users = @{\ "TestUser1" = "testPass1"\ "TestUser2" = "testPass2"\ "TestUser3" = "testPass3"\ "TestUser4" = "testPass4"\ "TestUser5" = "testPass5"\ } $Users.GetEnumerator() | ForEach-Object {\ $Name = $_.Key\ $Password = $_.Value $Params = @{\ "Name" = $Name\ "Path" = $OU\ "AccountPassword" = (ConvertTo-SecureString -AsPlainText $Password -Force)\ "Enabled" = $True\ "DisplayName" = $Name\ "PasswordNeverExpires" = $True\ "CannotChangePassword" = $True\ "EmailAddres" = "$Name@$Domain"\ } New-ADUser @Params\ } ``` -------------------------------- ### Configure Dual Audit Outputs for Migration Source: https://docs.readonlyrest.com/elasticsearch/audit.md Temporarily enable both index and data_stream outputs to ensure no logs are lost during a rolling migration. ```yaml readonlyrest: audit: enabled: true outputs: - type: index - type: data_stream # add data stream output type to your config data_stream: "custom_audit_data_stream" ``` -------------------------------- ### Retrieve index templates as admin Source: https://docs.readonlyrest.com/elasticsearch/indices-rule-templates.md A cURL request to verify the current state of index templates. ```bash $ curl -vk -u admin:admin "http://127.0.0.1:9200/_index_template?pretty" HTTP/1.1 200 OK content-type: application/json; charset=UTF-8 { "error" : { "root_cause" : [ { "reason" : "forbidden", "due_to" : ["OPERATION_NOT_ALLOWED"] } ], "reason" : "forbidden", "due_to" : ["OPERATION_NOT_ALLOWED"], "status" : 403 } } ``` -------------------------------- ### Configure ReadonlyREST for FIPS Mode Source: https://docs.readonlyrest.com/elasticsearch/fips.md Enable FIPS mode and specify BCFKS keystore/truststore files in the readonlyrest.yml configuration file. ```yaml readonlyrest: fips_mode: SSL_ONLY ssl: enable: true keystore_file: "keystore.bcfks" keystore_pass: readonlyrest truststore_file: "truststore.bcfks" truststore_pass: readonlyrest ssl_internode: enable: true keystore_file: "keystore.bcfks" keystore_pass: readonlyrest truststore_file: "truststore.bcfks" truststore_pass: readonlyrest ``` -------------------------------- ### Configure OIDC User Info Source Source: https://docs.readonlyrest.com/kibana Defines the source from which the plugin retrieves user profile information. ```yaml readonlyrest_kbn: auth: oidc_kc: userInfoSource: 'access_token' # Available options: 'user_info_endpoint' (default), 'access_token', 'id_token' ``` -------------------------------- ### Verify Data Stream Creation Source: https://docs.readonlyrest.com/elasticsearch/audit.md Check the status of the newly created audit data stream. ```text GET _data_stream/custom_audit_data_stream ``` -------------------------------- ### Target a Tenant via Kibana API Source: https://docs.readonlyrest.com/kibana Use the x-ror-tenancy-id header to specify the target tenant when making requests to the Kibana API. ```bash curl -X GET "http://localhost:5601/api/saved_objects/_find?type=dashboard" \ -H "kbn-xsrf: true" \ -H "x-ror-tenancy-id: marketing-team" ``` -------------------------------- ### Multi-user ELK Configuration Source: https://docs.readonlyrest.com/kibana A sample configuration for readonlyrest.yml supporting multiple user roles and Kibana access levels in PRO and Enterprise editions. ```yaml readonlyrest: access_control_rules: - name: "::LOGSTASH::" auth_key: logstash:logstash actions: ["indices:data/read/*","indices:data/write/*","indices:admin/template/*","indices:admin/create"] indices: ["logstash-*"] - name: "::KIBANA-SRV::" auth_key: kibana:kibana # use the following block instead of the `::KIBANA-SRV::` block if you use service account tokens (see https://www.elastic.co/guide/en/elasticsearch/reference/current/service-accounts.html) # #- name: "::KIBANA-SRV-TOKEN::" # token_authentication: # token: "Bearer AAEAAWVsYXN0aWMva2liYW5hL3Rva2VuXzE6MVhQUXRubWhRd3FxUmlzNmhFVVZQdw" # generated token for Kibana # username: kibana - name: "::RO::" auth_key: ro:dev indices: ["logstash-*"] kibana: access: ro hide_apps: [ "Security", "Enterprise Search"] - name: "::RW::" auth_key: rw:dev indices: ["logstash-*"] kibana: access: rw hide_apps: [ "Security", "Enterprise Search"] - name: "::ADMIN::" auth_key: admin:dev # KIBANA ADMIN ACCESS NEEDED TO EDIT SECURITY SETTINGS IN ROR KIBANA APP! kibana: access: admin - name: "::WEBSITE SEARCH BOX::" indices: ["public"] actions: ["indices:data/read/*"] ``` -------------------------------- ### Add KDS Root Key Source: https://docs.readonlyrest.com/examples/saml-sso/adfs.md Adds a KDS root key with an effective time 10 hours in the past to prevent configuration warnings. ```powershell Add-KdsRootKey -EffectiveTime ((Get-Date).AddHours(-10)) ```