From a9170a4362c500bb1cb0d586df78cebf9f516fb4 Mon Sep 17 00:00:00 2001 From: ssi444 <55582328+ssi444@users.noreply.github.com> Date: Wed, 13 Jul 2022 20:45:56 +0300 Subject: [PATCH] OIDC auth, custom configs (#63) * Update dashboards.yml. Fix owner and permissions for home folder Signed-off-by: Sergey Shubin * The validity period of certificates is set to a variable Signed-off-by: Sergey Shubin * change HOME directory for {{ os_user }} and {{ os_dashboards_user }} and set them /bin/false shell Signed-off-by: Sergey Shubin * auth_type (internal, openid). Custom configs, IaC 1. Added the ability to log in via OpenID 2. Added the ability to install custom configuration files for the cluster 3. Added the ability to reconfigure the cluster (in particular, update certificates) when expanding it 4. Added the ability not to change certificates if the cluster composition has not changed, but only the settings have changed. Signed-off-by: Sergey Shubin * readme. description for OpenID, IaC, custom configuration files Signed-off-by: Sergey Shubin * refactoring. see https://github.com/opensearch-project/ansible-playbook/pull/63 Signed-off-by: Sergey Shubin --- README.md | 42 +++ files/internal_users.yml | 26 ++ files/roles.yml | 54 ++++ files/roles_mapping.yml | 59 ++++ files/tenants.yml | 12 + inventories/opensearch/group_vars/all/all.yml | 62 ++++ roles/linux/dashboards/defaults/main.yml | 3 + roles/linux/dashboards/tasks/dashboards.yml | 12 +- .../templates/opensearch_dashboards.yml | 12 + roles/linux/opensearch/defaults/main.yml | 3 + roles/linux/opensearch/tasks/opensearch.yml | 10 +- roles/linux/opensearch/tasks/security.yml | 149 ++++++++- .../templates/security_plugin_conf.yml | 287 ++++++++++++++++++ .../linux/opensearch/templates/tlsconfig.yml | 4 +- 14 files changed, 712 insertions(+), 23 deletions(-) create mode 100644 files/internal_users.yml create mode 100644 files/roles.yml create mode 100644 files/roles_mapping.yml create mode 100644 files/tenants.yml create mode 100644 roles/linux/opensearch/templates/security_plugin_conf.yml diff --git a/README.md b/README.md index 30312de..c7e6983 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,8 @@ This ansible playbook supports the following, - Configure TLS/SSL for OpenSearch transport layer(Nodes to Nodes communication) and REST API layer - Generate self-signed certificates to configure TLS/SSL for opensearch - Configure the Internal Users Database with limited users and user-defined passwords +- Configuration of authentication and authorization via OpenID +- Overriding default settings with your own - Install and configure the Apache2.0 opensource OpenSearch Dashboards ### Prerequisite @@ -97,6 +99,9 @@ cluster_type: single-node You should set the reserved users(`admin` and `kibanaserver`) password using `admin_password` and `kibanaserver_password` variables. +If you define your own internal users (in addition to the reserved `admin` and `kibanaserver`) in custom configuration +files, then passwords to them should be set via variables on the principle of `_password` + It will install and configure the opensearch. Once the deployment completed, you can access the opensearch Dashboards with user `admin` and password which you provided for variable `admin_password`. # Deploy with ansible playbook - run the playbook as non-root user which have sudo privileges, @@ -104,6 +109,43 @@ It will install and configure the opensearch. Once the deployment completed, you **Note**: Change the user details in `ansible_user` parameter in `inventories/opensearch/hosts` inventory file. +### OpenID authentification +To enable authentication via OpenID, you need to change the `auth_type` variable in the inventory file +`inventories/opensearch/group_vars/all/all.yml` by setting the value `oidc` and prescribe the necessary settings +in the `oidc:` block. + +### Custom configuration files + +To override the default settings files, you need to put your settings in the `files` directory. The files should be +named exactly the same as the original ones (internal_users.yml, roles.yml, tenants.yml, etc.) + +Especially note the file `files/internal_users.yml`. If it exists and the `copy_custom_security_configs: true` setting is enabled, +then only in this case the task of setting passwords for internal users from variables is started. If the file `internal_users.yml` +is not located in the `files` directory, but, for example, in one of its subdirectories, then playbook will not work correctly + +### IaC (Infrastructure-as-Code) + +If you want to use the role not only for the initial deployment of the cluster, but also for further management of it, +then set the `iac_enable` parameter to `true`. + +By default, if the /tmp/opensearch-nodecerts directory with certificates exists on the server from which the playbook +is launched, it is assumed that the configuration has not changed and some settings are not copied to the target servers. + +Conversely, if the /tmp/opensearch-nodecerts directory does not exist on the server from which the playbook is launched, +then new certificates and settings are generated and they are copied to the target servers. + +If you use this repository not only for the initial deployment of the cluster, but also for its automatic configuration +via CI/CD, then new certificates will be generated every time the pipeline is launched, overwriting existing ones, which +is not always necessary if the cluster is already in production. + +When iac_enable enabling, and all the cluster servers have all the necessary certificates, they will not be copied again. +If at least on one server (for example, when adding a new server to the cluster) if there is not at least one certificate +from the list, then all certificates on all cluster servers will be updated + +Also, if the option is enabled, the settings files will be updated with each execution (previously, the settings were +updated only if the /tmp/opensearch-nodecerts directory was missing on the server from which the playbook was launched +and new certificates were generated) + ## Contributing See [developer guide](DEVELOPER_GUIDE.md) and [how to contribute to this project](CONTRIBUTING.md). diff --git a/files/internal_users.yml b/files/internal_users.yml new file mode 100644 index 0000000..e19bb07 --- /dev/null +++ b/files/internal_users.yml @@ -0,0 +1,26 @@ +--- +# This is the internal user database +# The hash value is a bcrypt hash and can be generated with plugin/tools/hash.sh + +_meta: + type: "internalusers" + config_version: 2 + +# Define your internal users here + +admin: + hash: "{{ admin_password }}" + reserved: true + backend_roles: + - "admin" + description: "admin user" + +kibanaserver: + hash: "{{ kibanaserver_password }}" + reserved: true + description: "kibanaserver user" + +logstash: + hash: "{{ logstash_password }}" + reserved: true + description: "logstash user" \ No newline at end of file diff --git a/files/roles.yml b/files/roles.yml new file mode 100644 index 0000000..36a2af7 --- /dev/null +++ b/files/roles.yml @@ -0,0 +1,54 @@ +--- +_meta: + type: "roles" + config_version: 2 + + +indexes_full_access: + reserved: false + index_permissions: + - index_patterns: + - "*" + allowed_actions: + - "*" + tenant_permissions: + - tenant_patterns: + - "*" + allowed_actions: + - "kibana_all_write" +# ---------------------------------------------------- +indexes_security_search_full_access: + reserved: true + index_permissions: + - index_patterns: + - "kube-apiserver-audit-*" + - "syslog-*" + allowed_actions: + - "indices:data/read/search*" + - "read" + - "view_index_metadata" + tenant_permissions: + - tenant_patterns: + - "SECURITY" + allowed_actions: + - "kibana_all_write" +# ---------------------------------------------------- +indexes_web_search_full_access: + reserved: true + index_permissions: + - index_patterns: + - "ingress-nginx-*" + - "mywebapp-*" + allowed_actions: + - "indices:data/read/search*" + - "read" + - "view_index_metadata" + tenant_permissions: + - tenant_patterns: + - "WEB" + allowed_actions: + - "kibana_all_write" +# ---------------------------------------------------- +# Restrict users so they can only view visualization and dashboard on OpenSearchDashboards +kibana_read_only: + reserved: true diff --git a/files/roles_mapping.yml b/files/roles_mapping.yml new file mode 100644 index 0000000..acd807c --- /dev/null +++ b/files/roles_mapping.yml @@ -0,0 +1,59 @@ +--- +# In this file users, backendroles and hosts can be mapped to Security roles. +# Permissions for OpenSearch roles are configured in roles.yml + +_meta: + type: "rolesmapping" + config_version: 2 + +kibana_server: + reserved: true + users: + - "kibanaserver" + +logstash: + reserved: true + users: + - "logstash" + +# Define your roles mapping here +all_access: + reserved: false + backend_roles: + - "admin" + - "opensearch_admin" + description: "Maps admin to all_access" +# ---------------------------------------------------- +indexes_full_access: + reserved: false + backend_roles: + - "opensearch_admin" + description: "Maps admin to indexes_full_access" +# ---------------------------------------------------- +own_index: + reserved: false + users: + - "*" + description: "Allow full access to an index named like the username" +# ---------------------------------------------------- +readall: + reserved: false + backend_roles: + - "opensearch_index_read_all" +# ---------------------------------------------------- +indexes_security_search_full_access: + reserved: true + backend_roles: + - "opensearch_index_read_all" + - "opensearch_index_read_security" + description: "Maps users to indexes_security_search_full_access" +# ---------------------------------------------------- +indexes_web_search_full_access: + reserved: true + backend_roles: + - "opensearch_index_read_all" + - "opensearch_index_read_web" + description: "Maps users to indexes_web_search_full_access" + + + diff --git a/files/tenants.yml b/files/tenants.yml new file mode 100644 index 0000000..da8ce76 --- /dev/null +++ b/files/tenants.yml @@ -0,0 +1,12 @@ +--- +_meta: + type: "tenants" + config_version: 2 + +# Define your tenants here +SECURITY: + reserved: false + description: "Tenant for security logs (e.g. kubernetes audit or opensearch audit)" +WEB: + reserved: false + description: "Tenant for web-app logs" diff --git a/inventories/opensearch/group_vars/all/all.yml b/inventories/opensearch/group_vars/all/all.yml index d494362..5fe0614 100644 --- a/inventories/opensearch/group_vars/all/all.yml +++ b/inventories/opensearch/group_vars/all/all.yml @@ -30,3 +30,65 @@ cluster_type: multi-node os_user: opensearch os_dashboards_user: opensearch-dashboards + +# Number of days that certificates are valid +cert_valid_days: 730 + +# Auth type: 'internal' or 'oidc' (OpenID). Default: internal +auth_type: internal + +# OIDC settings +oidc: + description: "Authenticate via IdP" + # OpenID server URI + connect_url: https://oidc.example.com/auth/realms//.well-known/openid-configuration + # The JWT token field that contains the user name + subject_key: preferred_username + # the JWT token field that contains a list of user roles + roles_key: roles + # Scopes + scopes: "openid profile email" + # The address of Dashboards to redirect the user to after successful authentication + dashboards_url: http(s)://.example.com + # IdP client ID + client_id: opensearch + # IdP client secret + client_secret: "00000000-0000-0000-0000-000000000000" + +# Overwrite demo configurations with your own +copy_custom_security_configs: false + +# To override demo configurations, you can use your own configuration files. +# Place them in the "files" directory. Specify the path to the files +custom_security_plugin_configs: + - files/tenants.yml + - files/roles.yml + - files/roles_mapping.yml + - files/internal_users.yml + +# By default, if the /tmp/opensearch-nodecerts directory with certificates +# exists on the server from which the playbook is launched, it is assumed +# that the configuration has not changed and some settings are not copied +# to the target servers. +# +# Conversely, if the /tmp/opensearch-nodecerts directory does not exist on +# the server from which the playbook is launched, then new certificates and +# settings are generated and they are copied to the target servers. +# +# If you use this repository not only for the initial deployment of the +# cluster, but also for its automatic configuration via CI/CD, then new +# certificates will be generated every time the pipeline is launched, +# overwriting existing ones, which is not always necessary if the cluster is +# already in production. +# +# When iac_enable enabling, and all the cluster servers have all the necessary +# certificates, they will not be copied again. If at least on one server (for +# example, when adding a new server to the cluster) if there is not at least one +# certificate from the list, then all certificates on all cluster servers will +# be updated +# +# Also, if the option is enabled, the settings files will be updated with each +# execution (previously, the settings were updated only if the +# /tmp/opensearch-nodecerts directory was missing on the server from which the +# playbook was launched and new certificates were generated) +iac_enable: false \ No newline at end of file diff --git a/roles/linux/dashboards/defaults/main.yml b/roles/linux/dashboards/defaults/main.yml index d257a22..13c224d 100644 --- a/roles/linux/dashboards/defaults/main.yml +++ b/roles/linux/dashboards/defaults/main.yml @@ -17,3 +17,6 @@ os_nodes_dashboards: |- {%- endfor %} systemctl_path: /etc/systemd/system + +# Auth type: 'internal' or 'oidc' (OpenID). Default: internal +auth_type: internal diff --git a/roles/linux/dashboards/tasks/dashboards.yml b/roles/linux/dashboards/tasks/dashboards.yml index c39c9f7..0999a4a 100644 --- a/roles/linux/dashboards/tasks/dashboards.yml +++ b/roles/linux/dashboards/tasks/dashboards.yml @@ -6,12 +6,14 @@ dest: "/tmp/opensearch-dashboards.tar.gz" register: download -- name: Dashboards Install | Create opensearch user +- name: Dashboards Install | Create opensearch dashboard user user: name: "{{ os_dashboards_user }}" state: present - shell: /bin/bash - when: download.changed + shell: /bin/false + create_home: true + home: "{{ os_dashboards_home }}" + when: download.changed or iac_enable - name: Dashboards Install | Create home directory file: @@ -19,11 +21,11 @@ state: directory owner: "{{ os_dashboards_user }}" group: "{{ os_dashboards_user }}" - when: download.changed + when: download.changed or iac_enable - name: Dashboards Install | Extract the tar file command: chdir=/tmp/ tar -xvzf opensearch-dashboards.tar.gz -C "{{ os_dashboards_home }}" --strip-components=1 - when: download.changed + when: download.changed or iac_enable - name: Dashboards Install | Copy Configuration File template: diff --git a/roles/linux/dashboards/templates/opensearch_dashboards.yml b/roles/linux/dashboards/templates/opensearch_dashboards.yml index ebcf8ff..b7b06a5 100644 --- a/roles/linux/dashboards/templates/opensearch_dashboards.yml +++ b/roles/linux/dashboards/templates/opensearch_dashboards.yml @@ -11,3 +11,15 @@ opensearch_security.multitenancy.tenants.preferred: ["Private", "Global"] opensearch_security.readonly_mode.roles: ["kibana_read_only"] # Use this setting if you are running dashboards without https opensearch_security.cookie.secure: false + + +# OpenID settings +{% if auth_type == 'oidc' %} +opensearch_security.auth.type: openid +opensearch_security.openid.base_redirect_url: "{{ oidc.dashboards_url }}" +opensearch_security.openid.client_id: "{{ oidc.client_id }}" +opensearch_security.openid.scope: "{{ oidc.scopes }}" +opensearch_security.openid.client_secret: "{{ oidc.client_secret }}" +opensearch_security.openid.connect_url: "{{ oidc.connect_url }}" +opensearch_security.openid.verify_hostnames: true +{% endif %} \ No newline at end of file diff --git a/roles/linux/opensearch/defaults/main.yml b/roles/linux/opensearch/defaults/main.yml index d35701e..c2ccd98 100644 --- a/roles/linux/opensearch/defaults/main.yml +++ b/roles/linux/opensearch/defaults/main.yml @@ -20,3 +20,6 @@ os_sec_plugin_tools_path: /usr/share/opensearch/plugins/opensearch-security/tool os_api_port: 9200 systemctl_path: /etc/systemd/system + +# Auth type: 'internal' or 'oidc' (OpenID). Default: internal +auth_type: internal diff --git a/roles/linux/opensearch/tasks/opensearch.yml b/roles/linux/opensearch/tasks/opensearch.yml index d54fbfd..4c44988 100644 --- a/roles/linux/opensearch/tasks/opensearch.yml +++ b/roles/linux/opensearch/tasks/opensearch.yml @@ -10,8 +10,10 @@ user: name: "{{ os_user }}" state: present - shell: /bin/bash - when: download.changed + shell: /bin/false + create_home: true + home: "{{ os_home }}" + when: download.changed or iac_enable - name: OpenSearch Install | Create home directory file: @@ -19,11 +21,11 @@ state: directory owner: "{{ os_user }}" group: "{{ os_user }}" - when: download.changed + when: download.changed or iac_enable - name: OpenSearch Install | Extract the tar file command: chdir=/tmp/ tar -xvzf opensearch.tar.gz -C "{{ os_home }}" --strip-components=1 - when: download.changed + when: download.changed or iac_enable - name: OpenSearch Install | Copy Configuration File blockinfile: diff --git a/roles/linux/opensearch/tasks/security.yml b/roles/linux/opensearch/tasks/security.yml index 9aca582..e2d6a32 100644 --- a/roles/linux/opensearch/tasks/security.yml +++ b/roles/linux/opensearch/tasks/security.yml @@ -2,6 +2,15 @@ ## Here we are going to use self-signed certificates for Transport (Node-Node communication) & REST API layer ## Using searchguard offline TLS tool to create node & root certificates +- name: Security Plugin configuration | Force remove local temporary directory for certificates generation + local_action: + module: file + path: /tmp/opensearch-nodecerts + state: absent + run_once: true + become: false + when: iac_enable + - name: Security Plugin configuration | Create local temporary directory for certificates generation local_action: module: file @@ -51,7 +60,59 @@ when: configuration.changed become: false -- name: Security Plugin configuration | Copy the node & admin certificates to opensearch nodes +- name: Security Plugin configuration | IaC enabled - Check certificate + block: + - name: Security Plugin configuration | Check cert exists + stat: + path: "{{ item }}" + get_attributes: no + get_checksum: no + get_mime: no + register: cert_stat_result + with_items: + - "{{ os_conf_dir }}/root-ca.pem" + - "{{ os_conf_dir }}/root-ca.key" + - "{{ os_conf_dir }}/{{ inventory_hostname }}.key" + - "{{ os_conf_dir }}/{{ inventory_hostname }}.pem" + - "{{ os_conf_dir }}/{{ inventory_hostname }}_http.key" + - "{{ os_conf_dir }}/{{ inventory_hostname }}_http.pem" + - "{{ os_conf_dir }}/admin.key" + - "{{ os_conf_dir }}/admin.pem" + + - name: Security Plugin configuration | Set fact. The initial value "Don't update certs" + set_fact: + force_update_cert: false + + - name: Security Plugin configuration | Set fact. Update certificates if at least one certificate is not found + set_fact: + force_update_cert: true + with_items: "{{ cert_stat_result.results }}" + when: item.stat.exists == False + + - name: Security Plugin configuration | Show the force_update_cert setting + debug: + msg: "force_update_cert: {{ force_update_cert }}" + + - name: Security Plugin configuration | Count force_update_cert nodes + set_fact: + force_update_cert_nodes_count: "{{ hostvars | dict2items | selectattr('value.force_update_cert', 'defined') | rejectattr('value.force_update_cert', 'equalto', false) | map(attribute='value.force_update_cert') | list | length }}" + + - name: Security Plugin configuration | Show the force_update_cert_nodes_count setting + debug: + msg: "force_update_cert_nodes_count: {{ force_update_cert_nodes_count }}" + + - name: Security Plugin configuration | Do need to update certificates + debug: + msg: "Need to update certificates..." + when: force_update_cert_nodes_count | int > 0 + when: iac_enable + +- name: Security Plugin configuration | IaC disabled - Count force_update_cert nodes + set_fact: + force_update_cert_nodes_count: 0 + when: not iac_enable + +- name: Security Plugin configuration | Copy the node & admin certificates to opensearch nodes if at least one certificate is not found on at least one server copy: src: "/tmp/opensearch-nodecerts/config/{{ item }}" dest: "{{ os_conf_dir }}" @@ -65,7 +126,7 @@ - "{{ inventory_hostname }}_http.pem" - admin.key - admin.pem - when: configuration.changed + when: (configuration.changed and not iac_enable) or (iac_enable and force_update_cert_nodes_count | int > 0) - name: Security Plugin configuration | Copy the security configuration file 1 to cluster blockinfile: @@ -74,7 +135,7 @@ backup: yes insertafter: EOF marker: "## {mark} OpenSearch Security common configuration ##" - when: configuration.changed + when: configuration.changed or iac_enable - name: Security Plugin configuration | Copy the security configuration file 2 to cluster blockinfile: @@ -83,11 +144,22 @@ backup: yes insertafter: EOF marker: "## {mark} opensearch Security Node & Admin certificates configuration ##" - when: configuration.changed + when: configuration.changed or iac_enable + +- name: Security Plugin configuration | Copy the security configuration file 3 to cluster + template: + src: security_plugin_conf.yml + dest: "{{ os_sec_plugin_conf_path }}/config.yml" + backup: yes + owner: "{{ os_user }}" + group: "{{ os_user }}" + mode: 0600 + force: yes + when: auth_type == 'oidc' - name: Security Plugin configuration | Prepare the opensearch security configuration file command: sed -i 's/searchguard/plugins.security/g' {{ os_conf_dir }}/opensearch.yml - when: configuration.changed + when: configuration.changed or iac_enable - name: Security Plugin configuration | Set the file ownerships file: @@ -109,9 +181,9 @@ state: restarted enabled: yes -- name: Pause for 3 seconds to provide sometime for OpenSearch start +- name: Pause for 10 seconds to provide sometime for OpenSearch start pause: - seconds: 3 + seconds: 10 - name: Security Plugin configuration | Copy the opensearch security internal users template template: @@ -119,7 +191,19 @@ dest: "{{ os_sec_plugin_conf_path }}/internal_users.yml" mode: 0644 run_once: true - when: configuration.changed + when: configuration.changed or iac_enable + +- name: Security Plugin configuration | Copy custom configuration files to cluster + template: + src: "{{ item }}" + dest: "{{ os_sec_plugin_conf_path }}/" + owner: "{{ os_user }}" + group: "{{ os_user }}" + backup: yes + mode: 0640 + force: yes + with_items: "{{ custom_security_plugin_configs }}" + when: copy_custom_security_configs - name: Security Plugin configuration | Set the Admin user password shell: > @@ -128,7 +212,7 @@ environment: JAVA_HOME: "{{ os_home }}/jdk" run_once: true - when: configuration.changed + when: configuration.changed or iac_enable - name: Security Plugin configuration | Set the kibanaserver user pasword shell: > @@ -137,7 +221,48 @@ environment: JAVA_HOME: "{{ os_home }}/jdk" run_once: true - when: configuration.changed + when: configuration.changed or iac_enable + +- name: Security Plugin configuration | Check that the files/internal_users.yml exists + stat: + path: files/internal_users.yml + register: custom_users_result + delegate_to: localhost + run_once: true + +- name: Security Plugin configuration | Check for a custom configuration for internal users and hash passwords for them + block: + + - name: Security Plugin configuration | Load custom internal users configuration + include_vars: + file: files/internal_users.yml + name: custom_users + run_once: true + + # In the internal_users file.yml each user is described by the block: + # username: + # hash: "{{ username_password }}"In addition to the user description blocks, there is a _meta block + # ... + # In addition to the user description blocks, there is a _meta block + # In this task, all usernames are selected from the file (excluding the _meta block), for which hashed + # passwords will be written next + - name: Security Plugin configuration | Filter service keys from the list of users + set_fact: + custom_users_filtered: '{{ custom_users|dict2items|rejectattr("key", "equalto", "_meta")|list|items2dict }}' + + # Hashed passwords are written for all users found in the previous task. Passwords are searched in variables + # set by the user when starting the role (admin_password, kibanaserver_password, etc.). + - name: Security Plugin configuration | Set passwords for all users from custom config + shell: > + sed -i '/hash: / s,{{ lookup('vars', item + '_password') }},'$(bash {{ os_sec_plugin_tools_path }}/hash.sh -p {{ lookup('vars', item + '_password') }} | tail -1)',' + {{ os_sec_plugin_conf_path }}/internal_users.yml + environment: + JAVA_HOME: "{{ os_home }}/jdk" + run_once: true + when: configuration.changed or copy_custom_security_configs + with_items: "{{ custom_users_filtered }}" + + when: custom_users_result.stat.exists - name: Security Plugin configuration | Initialize the opensearch security index in opensearch shell: > @@ -145,13 +270,13 @@ -cacert {{ os_conf_dir }}/root-ca.pem -cert {{ os_conf_dir }}/admin.pem -key {{ os_conf_dir }}/admin.key - -f {{ os_sec_plugin_conf_path }}/internal_users.yml + -cd {{ os_sec_plugin_conf_path }} -nhnv -icl -h {{ hostvars[inventory_hostname]['ip'] }} environment: JAVA_HOME: "{{ os_home }}/jdk" run_once: true - when: configuration.changed + when: configuration.changed or copy_custom_security_configs - name: Security Plugin configuration | Cleanup local temporary directory local_action: diff --git a/roles/linux/opensearch/templates/security_plugin_conf.yml b/roles/linux/opensearch/templates/security_plugin_conf.yml new file mode 100644 index 0000000..249058c --- /dev/null +++ b/roles/linux/opensearch/templates/security_plugin_conf.yml @@ -0,0 +1,287 @@ +--- + +# This is the main OpenSearch Security configuration file where authentication +# and authorization is defined. +# +# You need to configure at least one authentication domain in the authc of this file. +# An authentication domain is responsible for extracting the user credentials from +# the request and for validating them against an authentication backend like Active Directory for example. +# +# If more than one authentication domain is configured the first one which succeeds wins. +# If all authentication domains fail then the request is unauthenticated. +# In this case an exception is thrown and/or the HTTP status is set to 401. +# +# After authentication authorization (authz) will be applied. There can be zero or more authorizers which collect +# the roles from a given backend for the authenticated user. +# +# Both, authc and auth can be enabled/disabled separately for REST and TRANSPORT layer. Default is true for both. +# http_enabled: true +# transport_enabled: true +# +# For HTTP it is possible to allow anonymous authentication. If that is the case then the HTTP authenticators try to +# find user credentials in the HTTP request. If credentials are found then the user gets regularly authenticated. +# If none can be found the user will be authenticated as an "anonymous" user. This user has always the username "anonymous" +# and one role named "anonymous_backendrole". +# If you enable anonymous authentication all HTTP authenticators will not challenge. +# +# +# Note: If you define more than one HTTP authenticators make sure to put non-challenging authenticators like "proxy" or "clientcert" +# first and the challenging one last. +# Because it's not possible to challenge a client with two different authentication methods (for example +# Kerberos and Basic) only one can have the challenge flag set to true. You can cope with this situation +# by using pre-authentication, e.g. sending a HTTP Basic authentication header in the request. +# +# Default value of the challenge flag is true. +# +# +# HTTP +# basic (challenging) +# proxy (not challenging, needs xff) +# kerberos (challenging) +# clientcert (not challenging, needs https) +# jwt (not challenging) +# host (not challenging) #DEPRECATED, will be removed in a future version. +# host based authentication is configurable in roles_mapping + +# Authc +# internal +# noop +# ldap + +# Authz +# ldap +# noop + + + +_meta: + type: "config" + config_version: 2 + +config: + dynamic: + # Set filtered_alias_mode to 'disallow' to forbid more than 2 filtered aliases per index + # Set filtered_alias_mode to 'warn' to allow more than 2 filtered aliases per index but warns about it (default) + # Set filtered_alias_mode to 'nowarn' to allow more than 2 filtered aliases per index silently + #filtered_alias_mode: warn + #do_not_fail_on_forbidden: false + #kibana: + # Kibana multitenancy + #multitenancy_enabled: true + #server_username: kibanaserver + #index: '.kibana' +# OpenID settings +{% if auth_type == 'oidc' %} + http: + anonymous_auth_enabled: false + xff: + enabled: false + internalProxies: ".*" + remoteIpHeader: "x-forwarded-for" + authc: + # In order for Dashboards to access OpenSearch, you must first use + # authentication_backend.type: internal + basic_internal_auth_domain: + description: "Authenticate via HTTP Basic against internal users database" + http_enabled: true + transport_enabled: false + order: 0 + http_authenticator: + type: basic + challenge: false + authentication_backend: + type: internal + openid_auth_domain: + description: "Authenticate via OpenID" + http_enabled: true + transport_enabled: true + order: 1 + http_authenticator: + type: openid + challenge: false + config: + enable_ssl: false + verify_hostnames: false + subject_key: {{ oidc.subject_key}} + roles_key: {{ oidc.roles_key}} + openid_connect_url: {{ oidc.connect_url}} + kibana_url: {{ oidc.dashboards_url}} + authentication_backend: + type: noop + authz: {} +{% else %} + http: + anonymous_auth_enabled: false + xff: + enabled: false + internalProxies: '192\.168\.0\.10|192\.168\.0\.11' # regex pattern + #internalProxies: '.*' # trust all internal proxies, regex pattern + #remoteIpHeader: 'x-forwarded-for' + ###### see https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html for regex help + ###### more information about XFF https://en.wikipedia.org/wiki/X-Forwarded-For + ###### and here https://tools.ietf.org/html/rfc7239 + ###### and https://tomcat.apache.org/tomcat-8.0-doc/config/valve.html#Remote_IP_Valve + authc: + kerberos_auth_domain: + http_enabled: false + transport_enabled: false + order: 6 + http_authenticator: + type: kerberos + challenge: true + config: + # If true a lot of kerberos/security related debugging output will be logged to standard out + krb_debug: false + # If true then the realm will be stripped from the user name + strip_realm_from_principal: true + authentication_backend: + type: noop + basic_internal_auth_domain: + description: "Authenticate via HTTP Basic against internal users database" + http_enabled: true + transport_enabled: true + order: 4 + http_authenticator: + type: basic + challenge: true + authentication_backend: + type: intern + proxy_auth_domain: + description: "Authenticate via proxy" + http_enabled: false + transport_enabled: false + order: 3 + http_authenticator: + type: proxy + challenge: false + config: + user_header: "x-proxy-user" + roles_header: "x-proxy-roles" + authentication_backend: + type: noop + jwt_auth_domain: + description: "Authenticate via Json Web Token" + http_enabled: false + transport_enabled: false + order: 0 + http_authenticator: + type: jwt + challenge: false + config: + signing_key: "base64 encoded HMAC key or public RSA/ECDSA pem key" + jwt_header: "Authorization" + jwt_url_parameter: null + roles_key: null + subject_key: null + authentication_backend: + type: noop + clientcert_auth_domain: + description: "Authenticate via SSL client certificates" + http_enabled: false + transport_enabled: false + order: 2 + http_authenticator: + type: clientcert + config: + username_attribute: cn #optional, if omitted DN becomes username + challenge: false + authentication_backend: + type: noop + ldap: + description: "Authenticate via LDAP or Active Directory" + http_enabled: false + transport_enabled: false + order: 5 + http_authenticator: + type: basic + challenge: false + authentication_backend: + # LDAP authentication backend (authenticate users against a LDAP or Active Directory) + type: ldap + config: + # enable ldaps + enable_ssl: false + # enable start tls, enable_ssl should be false + enable_start_tls: false + # send client certificate + enable_ssl_client_auth: false + # verify ldap hostname + verify_hostnames: true + hosts: + - localhost:8389 + bind_dn: null + password: null + userbase: 'ou=people,dc=example,dc=com' + # Filter to search for users (currently in the whole subtree beneath userbase) + # {0} is substituted with the username + usersearch: '(sAMAccountName={0})' + # Use this attribute from the user as username (if not set then DN is used) + username_attribute: null + authz: + roles_from_myldap: + description: "Authorize via LDAP or Active Directory" + http_enabled: false + transport_enabled: false + authorization_backend: + # LDAP authorization backend (gather roles from a LDAP or Active Directory, you have to configure the above LDAP authentication backend settings too) + type: ldap + config: + # enable ldaps + enable_ssl: false + # enable start tls, enable_ssl should be false + enable_start_tls: false + # send client certificate + enable_ssl_client_auth: false + # verify ldap hostname + verify_hostnames: true + hosts: + - localhost:8389 + bind_dn: null + password: null + rolebase: 'ou=groups,dc=example,dc=com' + # Filter to search for roles (currently in the whole subtree beneath rolebase) + # {0} is substituted with the DN of the user + # {1} is substituted with the username + # {2} is substituted with an attribute value from user's directory entry, of the authenticated user. Use userroleattribute to specify the name of the attribute + rolesearch: '(member={0})' + # Specify the name of the attribute which value should be substituted with {2} above + userroleattribute: null + # Roles as an attribute of the user entry + userrolename: disabled + #userrolename: memberOf + # The attribute in a role entry containing the name of that role, Default is "name". + # Can also be "dn" to use the full DN as rolename. + rolename: cn + # Resolve nested roles transitive (roles which are members of other roles and so on ...) + resolve_nested_roles: true + userbase: 'ou=people,dc=example,dc=com' + # Filter to search for users (currently in the whole subtree beneath userbase) + # {0} is substituted with the username + usersearch: '(uid={0})' + # Skip users matching a user name, a wildcard or a regex pattern + #skip_users: + # - 'cn=Michael Jackson,ou*people,o=TEST' + # - '/\S*/' + roles_from_another_ldap: + description: "Authorize via another Active Directory" + http_enabled: false + transport_enabled: false + authorization_backend: + type: ldap + #config goes here ... + # auth_failure_listeners: + # ip_rate_limiting: + # type: ip + # allowed_tries: 10 + # time_window_seconds: 3600 + # block_expiry_seconds: 600 + # max_blocked_clients: 100000 + # max_tracked_clients: 100000 + # internal_authentication_backend_limiting: + # type: username + # authentication_backend: intern + # allowed_tries: 10 + # time_window_seconds: 3600 + # block_expiry_seconds: 600 + # max_blocked_clients: 100000 +{% endif %} diff --git a/roles/linux/opensearch/templates/tlsconfig.yml b/roles/linux/opensearch/templates/tlsconfig.yml index 2125ed6..5b7408f 100644 --- a/roles/linux/opensearch/templates/tlsconfig.yml +++ b/roles/linux/opensearch/templates/tlsconfig.yml @@ -2,13 +2,13 @@ ca: root: dn: CN=root.ca.{{ domain_name }},OU=CA,O={{ domain_name }}\, Inc.,DC={{ domain_name }} keysize: 2048 - validityDays: 730 + validityDays: {{ cert_valid_days }} pkPassword: none file: root-ca.pem ### Default values and global settings defaults: - validityDays: 730 + validityDays: {{ cert_valid_days }} pkPassword: none # Set this to true in order to generate config and certificates for # the HTTP interface of nodes