OK, in this picture is my test environment. In test group is user1 which needs to authenticate to Easticsearch
in service_account OU is service account which searches AD for users
In UA OU is user1 (member of test security group)
sg_config.yml
authc:
kerberos_auth_domain:
http_enabled: false
transport_enabled: false
order: 6
http_authenticator:
type: kerberos # NOT FREE FOR COMMERCIAL USE
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:
http_enabled: true
transport_enabled: true
order: 4
http_authenticator:
type: basic
challenge: true
authentication_backend:
type: intern
proxy_auth_domain:
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:
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:
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:
http_enabled: false
transport_enabled: false
order: 2
http_auithenticator:
type: basic
challenge: false
authentication_backend:
# LDAP authentication backend (authenticate users against a LDAP or Active Directory)
type: ldap # NOT FREE FOR COMMERCIAL USE
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:
- dc.test.com:389
bind_dn: 'CN=service,OU=service_accounts,DC=test,DC=com'
password: 'Pass'
userbase: 'CN=test,OU=groups,DC=test,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: cn
authz:
roles_from_myldap:
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 # NOT FREE FOR COMMERCIAL USE
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:
- dc.test.com:389
bind_dn: 'CN=service,OU=service_accounts,DC=test,DC=com'
password: 'Pass'
rolebase: 'OU=UA,DC=test,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={1})'
# Specify the name of the attribute which value should be substituted with {2} above
userroleattribute: cn
# 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: 'CN=test,OU=groups,DC=test,DC=com'
# Filter to search for users (currently in the whole subtree beneath userbase)
# {0} is substituted with the username
usersearch: "(cn={0})"
username_attribute: "cn"
# 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:
enabled: false
authorization_backend:
type: ldap # NOT FREE FOR COMMERCIAL USE
#config goes here ...
sg_roles.yml
sg_ad_admin:
readonly: true
cluster:
- UNLIMITED
indices:
'*':
'*':
- UNLIMITED
tenants:
admin_tenant: RW
sg_roles_mapping.yml
sg_ad_admin:
readonly: true
backendroles:
- "CN=test,OU=groups,DC=test,DC=com"
user1 is cn
curl -Ss -k https://user1:Pass1@ekl.test.com:9200/_cluster/health
logs:
[2019-04-02T07:51:59,275][DEBUG][c.f.s.a.BackendRegistry ] [ekl.test.com] user1 not cached, return from internal backend directly
[2019-04-02T07:51:59,275][DEBUG][c.f.s.a.BackendRegistry ] [ekl.test.com] Can not authenticate user1 due to com.google.common.util.concurrent.UncheckedExecutionException: ElasticsearchSecurityException[user1 not found]
com.google.common.util.concurrent.UncheckedExecutionException: ElasticsearchSecurityException[user1 not found]
at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2050) ~[guava-25.1-jre.jar:?]
at com.google.common.cache.LocalCache.get(LocalCache.java:3951) ~[guava-25.1-jre.jar:?]
at com.google.common.cache.LocalCache$LocalManualCache.get(LocalCache.java:4870) ~[guava-25.1-jre.jar:?]
at com.floragunn.searchguard.auth.BackendRegistry.authcz(BackendRegistry.java:694) [search-guard-6-6.6.2-24.2.jar:6.6.2-24.2]
at com.floragunn.searchguard.auth.BackendRegistry.authenticate(BackendRegistry.java:523) [search-guard-6-6.6.2-24.2.jar:6.6.2-24.2]
at com.floragunn.searchguard.filter.SearchGuardRestFilter.checkAndAuthenticateRequest(SearchGuardRestFilter.java:134) [search-guard-6-6.6.2-24.2.jar:6.6.2-24.2]
at com.floragunn.searchguard.filter.SearchGuardRestFilter.access$000(SearchGuardRestFilter.java:50) [search-guard-6-6.6.2-24.2.jar:6.6.2-24.2]
at com.floragunn.searchguard.filter.SearchGuardRestFilter$1.handleRequest(SearchGuardRestFilter.java:80) [search-guard-6-6.6.2-24.2.jar:6.6.2-24.2]
at org.elasticsearch.rest.RestController.dispatchRequest(RestController.java:240) [elasticsearch-6.6.2.jar:6.6.2]
at org.elasticsearch.rest.RestController.tryAllHandlers(RestController.java:336) [elasticsearch-6.6.2.jar:6.6.2]
at org.elasticsearch.rest.RestController.dispatchRequest(RestController.java:174) [elasticsearch-6.6.2.jar:6.6.2]
at com.floragunn.searchguard.ssl.http.netty.ValidatingDispatcher.dispatchRequest(ValidatingDispatcher.java:63) [search-guard-ssl-6.6.2-25.6.jar:6.6.2-25.6]
at org.elasticsearch.http.netty4.Netty4HttpServerTransport.dispatchRequest(Netty4HttpServerTransport.java:551) [transport-netty4-client-6.6.2.jar:6.6.2]
at org.elasticsearch.http.netty4.Netty4HttpRequestHandler.channelRead0(Netty4HttpRequestHandler.java:137) [transport-netty4-client-6.6.2.jar:6.6.2]
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105) [netty-transport-4.1.32.Final.jar:4.1.32.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) [netty-transport-4.1.32.Final.jar:4.1.32.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) [netty-transport-4.1.32.Final.jar:4.1.32.Final]
Made some progress:
Now can authenticate but role is not mapped:
ldap:
http_enabled: true
transport_enabled: true
order: 2
http_authenticator:
type: basic
challenge: false
authentication_backend:
# LDAP authentication backend (authenticate users against a LDAP or Active Directory)
type: ldap # NOT FREE FOR COMMERCIAL USE
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:
- dc.test.com:389
bind_dn: "CN=service,OU=service_accounts,DC=test,DC=com"
password: "Pass"
userbase: "OU=UA,DC=test,DC=com"
# Filter to search for users (currently in the whole subtree beneath userbase)
# {0} is substituted with the username
usersearch: "(cn={0})"
# Use this attribute from the user as username (if not set then DN is used)
username_attribute: "cn"
authz:
roles_from_myldap:
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 # NOT FREE FOR COMMERCIAL USE
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:
- "dc.test.com:389"
bind_dn: "CN=service,OU=service_accounts,DC=test,DC=com"
password: "Pass"
#rolebase: "OU=UA,DC=test,DC=com"
rolebase: "CN=test,OU=groups,DC=test,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: 'CN=test,OU=groups,DC=test,DC=com'
# Filter to search for users (currently in the whole subtree beneath userbase)
# {0} is substituted with the username
usersearch: "(cn={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:
enabled: false
authorization_backend:
curl -Ss -k https://user1:Pass@ekl.test.com:9200/_cluster/health
{"error":{"root_cause":[{"type":"security_exception","reason":"no permissions for [cluster:monitor/health] and User [name=user1, roles=[], requestedTenant=null]"}],"type":"security_exception","reason":"no permissions for [cluster:monitor/health] and User [name=user1, roles=[], requestedTenant=null]"},"status":403}