wazuh / wazuh-documentation

Wazuh - Project documentation
https://wazuh.com
193 stars 339 forks source link

Considering adding a new section for the configuration of Opendistro and LDAP #2983

Open MiguelCasaresRobles opened 4 years ago

MiguelCasaresRobles commented 4 years ago

Hello team,

Opendistro has many security features that we may consider to add as a guide in our documentation. For instance:

LDAP INTEGRATION

Config.yml

Reference: https://opendistro.github.io/for-elasticsearch-docs/docs/security/configuration/ldap/

LDAP can handle both feature authentication and authorization. auhtc handling the configuration for authentication, for authorization we will need to use authz sections. Authorization is the process of retrieving backend roles for an authenticated user from an LDAP server. The file where both of the sections are configured is located here: /usr/share/elasticsearch/plugins/opendistro_security/securityconfig/config.yml.

In the authc section you will need to have/modify the ldap configuration.

authc:
  ldap:
    http_enabled: true
    transport_enabled: false
    order: 1
    http_authenticator:
      type: "basic"
      challenge: false
    authentication_backend:
      type: "ldap"
      config:
        enable_ssl: true
        enable_start_tls: false
        enable_ssl_client_auth: false
        verify_hostnames: true
        hosts:
          - "example.com:389"
        bind_dn: "cn=admin,dc=example,dc=com"
        password: "<< password >>"
        userbase: "OU=people,dc=example,dc=com"
        usersearch: "(sAMAccountName={0})"
        username_attribute: "cn"

Where in the config:

The Security plugin first takes the configured LDAP query and replaces the placeholder {0} with the user name from the user’s credentials.

usersearch: '(sAMAccountName={0})'

Then it issues this query against the user subtree. Currently, the entire subtree under the configured userbase is searched:

userbase: 'ou=people,dc=example,dc=com'

Name Description
userbase Specifies the subtree in the directory where user information is stored.
usersearch The actual LDAP query that the Security plugin executes when trying to authenticate a user. The variable {0} is substituted with the user name.
username_attribute The Security plugin uses this attribute of the directory entry to look for the user name. If set to null, the DN is used (default).

To configure authorization in the same file add authz section:

authz:
  roles_from_myldap:
    http_enabled: true
    transport_enabled: false
    authorization_backend:
      type: "ldap"
      config:
        enable_ssl: true
        enable_start_tls: false
        enable_ssl_client_auth: false
        verify_hostnames: true
        hosts:
        - "example.com:389"
        bind_dn: "cn=admin,dc=example,dc=com"
        password: "<< password >>"
        userbase: "OU=people,dc=example,dc=com"
        usersearch: "(uid={0})"
        rolebase: "ou=groups,dc=example,dc=com"
        rolesearch: "(member={0})"
        userrolename: "memberOf"
        rolename: "cn"

The Security plugin then issues the substituted query against the configured role subtree. The whole subtree below rolebase is searched.

The Security plugin first takes the LDAP query for fetching roles (“rolesearch”) and substitutes any variables found in the query. Here {0} is substituted with the DN of the user: rolesearch: '(member={0})'

To update the Security plugin of OpenDistro you will need to run:

/usr/share/elasticsearch/plugins/opendistro_security/tools/securityadmin.sh \
    -cacert /etc/elasticsearch/root-ca.pem \
-cert /etc/elasticsearch/kirk.pem \ 
-key /etc/elasticsearch/kirk-key.pem \
-f /usr/share/elasticsearch/plugins/opendistro_security/securityconfig/config.yml -t config

To create a new role with readonly permission. In the file roles.yml:

ReadOnlyRole:
  cluster:
  - "CLUSTER_COMPOSITE_OPS_RO"
  indices:
    '*':
      '*':
      - "READ"

In the roles_mapping.yml:

ReadOnlyRole:
  backendroles:
  - "LDAP-Read-Group" hosts: [] users: []

This file will map ReadOnlyRole to the LDAP-Read-Group from LDAP.

This command will udpate roles:

/usr/share/elasticsearch/plugins/opendistro_security/tools/securityadmin.sh \
    -cacert /etc/elasticsearch/root-ca.pem \
-cert /etc/elasticsearch/kirk.pem \ 
-key /etc/elasticsearch/kirk-key.pem \
-f ./roles.yml -t roles

This command will update role mapping:

/usr/share/elasticsearch/plugins/opendistro_security/tools/securityadmin.sh \
    -cacert /etc/elasticsearch/root-ca.pem \
-cert /etc/elasticsearch/kirk.pem \ 
-key /etc/elasticsearch/kirk-key.pem \
-f ./roles_mapping.yml -t rolesmapping

Elasticsearch.yml

The config map for the elasticsearch.yml:

apiVersion: v1
kind: ConfigMap
metadata:
  name: odfe-elasticsearch-yml
  namespace: env-8c013448fea8
data:
  configmap_elasticsearch.yml: |-
    cluster.name: "odfe-cluster"
    network.host: 0.0.0.0
    opendistro_security.ssl.transport.enabled: true
    opendistro_security.ssl.transport.pemcert_filepath: node.cert.pem
    opendistro_security.ssl.transport.pemkey_filepath: node-key.pem
    opendistro_security.ssl.transport.pemtrustedcas_filepath: ca-chain-us-east-2.cert.pem
    opendistro_security.ssl.transport.enforce_hostname_verification: false
    opendistro_security.ssl.transport.truststore_filepath: truststore.jks
    opendistro_security.ssl.transport.truststore_password: binpassword
    opendistro_security.ssl.transport.truststore_alias: thealias
    opendistro_security.ssl.http.enabled: true
    opendistro_security.ssl.http.pemcert_filepath: node.cert.pem
    opendistro_security.ssl.http.pemkey_filepath: node-key.pem
    opendistro_security.ssl.http.pemtrustedcas_filepath: ca-chain-us-east-2.cert.pem
    opendistro_security.allow_default_init_securityindex: true
    opendistro_security.authcz.admin_dn:
    - CN=Admin,OU=Wazuh Cloud,O=Wazuh Cloud,ST=California,C=US
    opendistro_security.nodes_dn:
    - 'CN=odfe,OU=Wazuh Cloud,O=Wazuh Cloud,ST=California,C=US'
    opendistro_security.audit.type: internal_elasticsearch
    opendistro_security.audit.enable_transport: false
    opendistro_security.audit.config.disabled_rest_categories: AUTHENTICATED
    opendistro_security.audit.config.index: "'security-auditlog-'YYYY.MM"
    opendistro_security.audit.ignore_users:
    - elastic
    - service_kibana
    - service_logstash
    - service_monitoring
    - service_readiness
    opendistro_security.enable_snapshot_restore_privilege: true
    opendistro_security.check_snapshot_restore_write_privileges: true
    opendistro_security.restapi.roles_enabled: ["all_access", "security_rest_api_access", "service_full_access"]
    cluster.routing.allocation.disk.threshold_enabled: false
    node.max_local_storage_nodes: 5
    # cluster node
    bootstrap.memory_lock: false
    node.name: odfe-0
    discovery.seed_hosts:
    - odfe-cluster
    cluster.initial_master_nodes:
    - odfe-0
    # end cluster config"

These three configurations were added to default config map:

    opendistro_security.ssl.transport.truststore_filepath: truststore.jks
    opendistro_security.ssl.transport.truststore_password: binpassword
    opendistro_security.ssl.transport.truststore_alias: google-ca

truststore.jks is the path to the trustore file that we will generate below. binpassword the password you set during the generation of the trustore certificate google-ca the alias you set during the generation of the trustore certificate

Generate the trustore (google_ldap)

In this example, we will work with ldap.google.com.

To generate a truststore we will need to have CA authority certificate. In our case it will be the one from ldap.google.com

We have the file google-ca.pem:

-----BEGIN CERTIFICATE-----
MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G
A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp
Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1
MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG
A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL
v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8
eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq
tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd
C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa
zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB
mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH
V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n
bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG
3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs
J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO
291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS
ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd
AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
-----END CERTIFICATE-----

We will need to add this file to

To generate we need to run the following commands:

keytool -genkeypair -alias boguscert -storetype jks -storepass binpassword -keypass binpassword -keystore truststore.jks -dname "CN=Developer, OU=Department, O=Company, L=City, ST=State, C=CA"

keytool -delete -alias boguscert -storepass binpassword -keystore truststore.jks

keytool -import -v -trustcacerts -alias google-ca -file google-ca.pem -keystore truststore.jks -storepass binpassword -noprompt

keytool -list -keystore truststore.jks -storepass binpassword

It will create the file trusture.jks.

Note: need more testing

Regards,

Miguel Casares

elwali10 commented 3 years ago

Hello Team,

I think it is better to add the LDAP server CA cert within the config.yml ( https://opendistro.github.io/for-elasticsearch-docs/docs/security/configuration/ldap/#certificate-validation OR https://opendistro.github.io/for-elasticsearch-docs/docs/security/configuration/ldap/#client-authentication) instead of using trustore in all Elasticserch nodes, An example :

  ldap:
        description: "Authenticate via LDAP or Active Directory"
        http_enabled: true
        transport_enabled: true
        order: 1
        http_authenticator:
          type: basic
          challenge: false
        authentication_backend:
          type: ldap
          config:
            enable_ssl: true
            enable_start_tls: false
            enable_ssl_client_auth: false
            pemtrustedcas_filepath: /etc/elasticsearch/certs/ldapcacert.pem
            verify_hostnames: true
            hosts:
            - test.ldap.com:636
            bind_dn: 'cn=wali,ou=groups,dc=ldap,dc=com'
            password: 'wazuh'
            userbase: 'ou=groups,dc=ldap,dc=com'
            usersearch: '(uid={0})'
            username_attribute: uid

Then upload it to the .security index using the securityadmin.sh script:

/usr/share/elasticsearch/plugins/opendistro_security/tools/securityadmin.sh -cacert /etc/elasticsearch/certs/root-ca.pem -cert /etc/elasticsearch/certs/admin.pem -key /etc/elasticsearch/certs/admin.key -f /usr/share/elasticsearch/plugins/opendistro_security/securityconfig/config.yml -t config -icl -nhnv -h localhost

This way, we will not have to change/restart every Elasticsearch node and can be easily implemented.

Regards, El Wali