getsentry-ldap-auth icon indicating copy to clipboard operation
getsentry-ldap-auth copied to clipboard

sentry-ldap-auth for Active Directory

Open Piknik1990 opened this issue 7 years ago • 7 comments

Hello!

I need to set up AD-authorization on Sentry. In the Internet on this theme I found this topic only: https://forum.sentry.io/t/how-to-set-up-to-auth-via-ms-active-directory-or-ldap/1880/5

But settings of this topic leads or not work AD-auth, or full non-work sentry (He not accept options "LOGGING").

I have next AD-server

IP 10.10.10.10 Domain: test.comp.com Users: test.comp.com/Users Groups: test.comp.com/Groups

Test User: test.comp.com/Users/user Test Groups: test.comp.com/Groups/adminsupport (full right) test.comp.com/Groups/support (read only)

Now my conf-file have follow parameters:

sentry.conf.py

from sentry.conf.server import *
 
import os.path
 
CONF_ROOT = os.path.dirname(__file__)
 
DATABASES = {
    'default': {
        'ENGINE': 'sentry.db.postgres',
        'NAME': 'sentry',
        'USER': 'sentry',
        'PASSWORD': '123',
        'HOST': '127.0.0.1',
        'PORT': '5432',
        'AUTOCOMMIT': True,
        'ATOMIC_REQUESTS': False,
    }
}
 
SENTRY_USE_BIG_INTS = True
SENTRY_SINGLE_ORGANIZATION = True
DEBUG = False
SENTRY_CACHE = 'sentry.cache.redis.RedisCache'
BROKER_URL = 'redis://localhost:6379'
SENTRY_RATELIMITER = 'sentry.ratelimits.redis.RedisRateLimiter'
SENTRY_BUFFER = 'sentry.buffer.redis.RedisBuffer'
SENTRY_QUOTAS = 'sentry.quotas.redis.RedisQuota'
SENTRY_TSDB = 'sentry.tsdb.redis.RedisTSDB'
SENTRY_DIGESTS = 'sentry.digests.backends.redis.RedisBackend'
# FORCE_SCRIPT_NAME = '/sentry'
SENTRY_WEB_HOST = '0.0.0.0'
SENTRY_WEB_PORT = 9000
SENTRY_WEB_OPTIONS = {
    # 'workers': 3,  # the number of web workers
    # 'protocol': 'uwsgi',  # Enable uwsgi protocol instead of http
}
 

import ldap
from django_auth_ldap.config import LDAPSearch, GroupOfUniqueNamesType

AUTH_LDAP_SERVER_URI = 'ldap://10.10.10.10.'
AUTH_LDAP_BIND_DN = 'CN=User,CN=Users,DC=test,DC=comp,DC=com'
AUTH_LDAP_BIND_PASSWORD = '123'

AUTH_LDAP_CONNECTION_OPTIONS = {
ldap.OPT_DEBUG_LEVEL: 0,
ldap.OPT_REFERRALS: 0,
}

AUTH_LDAP_USER_SEARCH = LDAPSearch(
    'dc=test,dc=comp,dc=com',
    ldap.SCOPE_SUBTREE,
    'member={1}',
)

AUTH_LDAP_GROUP_SEARCH = LDAPSearch(
    'dc=test,dc=comp,dc=comp',
    ldap.SCOPE_SUBTREE,
    'objectClass=group'
)

AUTH_LDAP_GROUP_TYPE = GroupOfUniqueNamesType()
AUTH_LDAP_REQUIRE_GROUP = None
AUTH_LDAP_DENY_GROUP = None

AUTH_LDAP_USER_ATTR_MAP = {
    'name': 'cn',
    'email': 'mail'
}

AUTH_LDAP_FIND_GROUP_PERMS = False
AUTH_LDAP_CACHE_GROUPS = True
AUTH_LDAP_GROUP_CACHE_TIMEOUT = 3600

AUTH_LDAP_DEFAULT_SENTRY_ORGANIZATION = u'TEST COMP COM'
AUTH_LDAP_SENTRY_ORGANIZATION_ROLE_TYPE = 'member'
AUTH_LDAP_SENTRY_ORGANIZATION_GLOBAL_ACCESS = True

AUTHENTICATION_BACKENDS = AUTHENTICATION_BACKENDS + (
    'sentry_ldap_auth.backend.SentryLdapBackend',
)

import logging
logger = logging.getLogger('django_auth_ldap')
logger.addHandler(logging.StreamHandler())
logger.addHandler(logging.FileHandler(r"/tmp/ldap2.log"))
logger.setLevel('DEBUG')

#LOGGING[‘overridable’] = [‘sentry’, ‘django_auth_ldap’ ]
#LOGGING[‘loggers’][‘django_auth_ldap’] = {
#‘handlers’: [‘console’],
#‘level’: ‘DEBUG’
#}

Tell me, do you have AD-like config file for Sentry for example?

Piknik1990 avatar Sep 04 '17 09:09 Piknik1990

After just a quick look at your configuration, it doesn't look like your AUTH_LDAP_USER_SEARCH is correct. The LDAP query (parameter 3 for LDAPSearch()) should be something like (uid=%(user)s)

barronhagerman avatar Sep 04 '17 19:09 barronhagerman

Slightly differently explain.

I experimented several days and now I have this:

Active Directory on Windows 2008R2

  1. domain test.comp.com
  2. User: user in catalog test.comp.com/Users/
  3. IP 10.10.10.1

Sentry on CentOS 7

  1. SELinux and Firewalld disable
  2. IP 10.10.10.10
  3. Installed: pip install redis==2.10.5 pip install sentry pyyaml sentry upgrade --noinput sentry createuser --email [email protected] --password '123' --superuser --no-input yum -y install openldap-devel openldap-clients pip install python-ldap django-auth-ldap sentry-ldap-auth sentry run worker sentry run web sentry run cron
  4. If enter command "ldapsearch -x -h 10.10.10.1 -D "[email protected]" -W -b "cn=users,dc=test,dc=comp,dc=com" -s sub "(&(objectClass=user)(objectClass=person))" cn mail" and password I see username and email. Wherein in Windows logging massage of successful/failed authorization.
  5. If I try authorization via Sentry interface I get failed auth, but in the Windows not no one messages of successful/failed authorization. No one. Such sensation, that at all does not try to unite with AD.

My sentry.conf.py:

...
import ldap
from django_auth_ldap.config import LDAPSearch, GroupOfUniqueNamesType

AUTH_LDAP_SERVER_URI = 'ldap://10.10.10.1'
AUTH_LDAP_BIND_DN = 'user'
AUTH_LDAP_BIND_PASSWORD = '1qaz@WSX'

AUTH_LDAP_USER_SEARCH = LDAPSearch(
    'cn=Users,dc=test,dc=comp,dc=com',
    ldap.SCOPE_SUBTREE,
    '(&(objectClass=user)(objectClass=person))',
)

AUTH_LDAP_GROUP_SEARCH = LDAPSearch(
    'cn=Groups,dc=test,dc=comp,dc=com',
    ldap.SCOPE_SUBTREE,
    '(objectClass=groupOfUniqueNames)'
)

AUTH_LDAP_GROUP_TYPE = GroupOfUniqueNamesType()
AUTH_LDAP_REQUIRE_GROUP = None
AUTH_LDAP_DENY_GROUP = None

AUTH_LDAP_USER_ATTR_MAP = {
    'name': 'cn',
    'email': 'mail'
}

AUTH_LDAP_FIND_GROUP_PERMS = False
AUTH_LDAP_CACHE_GROUPS = True
AUTH_LDAP_GROUP_CACHE_TIMEOUT = 3600

AUTH_LDAP_DEFAULT_SENTRY_ORGANIZATION = u'TEST Company'
AUTH_LDAP_SENTRY_ORGANIZATION_ROLE_TYPE = 'member'
AUTH_LDAP_SENTRY_ORGANIZATION_GLOBAL_ACCESS = True

AUTHENTICATION_BACKENDS = AUTHENTICATION_BACKENDS + (
    'sentry_ldap_auth.backend.SentryLdapBackend',
)

import logging
logger = logging.getLogger('django_auth_ldap')
logger.addHandler(logging.StreamHandler())
logger.setLevel('DEBUG')

I tried change ldap.SCOPE_SUBTREE: In the ldapsearch work (&(objectClass=user)(objectClass=person)) and (cn=*), not work (uid=%(user)s) (ldap_search_ext: Bad search filter (-7)) In the Sentry not work nothing.

Also I tried this config with diverse "dap.SCOPE_SUBTREE" and this not work too:

#########################
## LDAP Authentication ##
#########################

import ldap
from django_auth_ldap.config import LDAPSearch, GroupOfNamesType

# Baseline configuration.
AUTH_LDAP_SERVER_URI = "ldap://10.10.10.1"

AUTH_LDAP_USER_SEARCH = LDAPSearch("cn=Users,dc=test,dc=comp,dc=com",
    ldap.SCOPE_SUBTREE, "(&(objectClass=user)(objectClass=person))")

AUTHENTICATION_BACKENDS = (
    'sentry.utils.auth.EmailAuthBackend',
    'django_auth_ldap.backend.LDAPBackend',
    'django.contrib.auth.backends.ModelBackend',
)

Main question, why Sentry does not even try connecting on AD-server?

Piknik1990 avatar Sep 08 '17 12:09 Piknik1990

@Piknik1990 Try changing the search filter to (&(objectClass=user)(objectClass=person)(cn=%(user)s).

I don't understand why you say "Sentry does not even try connecting on AD-server". You received an error Bad search filter (-7), right? Can you connect to AD with a basic LDAP client?

Also, it's been a while since I did anything with AD, but I'm not sure you can bind a user to AD using an unencrypted channel. You should be able to connect anonymously by setting AUTH_LDAP_BIND_DN = '' and AUTH_LDAP_BIND_PASSWORD = ''

barronhagerman avatar Sep 08 '17 21:09 barronhagerman

Ok. I am poorly described problem.

At first I install Windows 2008R2, create AD domain and create user in this domain. IP: 10.10.10.1 Domain: test.comp.com

All connect to AD server (successful or unsuccessful) I see in the Event Viewer - Security log example: https://technet.microsoft.com/en-us/library/dd277415.w2kab163_big(l=en-us).gif

Sentry server installed in Centos 7. Now config Sentry is:

import ldap
from django_auth_ldap.config import LDAPSearch, GroupOfUniqueNamesType

AUTH_LDAP_SERVER_URI = 'ldap://10.10.10.1'
AUTH_LDAP_BIND_DN = ''
AUTH_LDAP_BIND_PASSWORD = ''

AUTH_LDAP_USER_SEARCH = LDAPSearch(
    'cn=Users,dc=test,dc=comp,dc=com',
    ldap.SCOPE_SUBTREE,
    '(&(objectClass=user)(objectClass=person)',
)

AUTH_LDAP_GROUP_SEARCH = LDAPSearch(
    'cn=Groups,dc=test,dc=comp,dc=com',
    ldap.SCOPE_SUBTREE,
    '(objectClass=groupOfUniqueNames)'
)

AUTH_LDAP_GROUP_TYPE = GroupOfUniqueNamesType()
AUTH_LDAP_REQUIRE_GROUP = None
AUTH_LDAP_DENY_GROUP = None

AUTH_LDAP_USER_ATTR_MAP = {
    'name': 'cn',
    'email': 'mail'
}

AUTH_LDAP_FIND_GROUP_PERMS = False
AUTH_LDAP_CACHE_GROUPS = True
AUTH_LDAP_GROUP_CACHE_TIMEOUT = 3600

AUTH_LDAP_DEFAULT_SENTRY_ORGANIZATION = u'TEST'
AUTH_LDAP_SENTRY_ORGANIZATION_ROLE_TYPE = 'member'
AUTH_LDAP_SENTRY_ORGANIZATION_GLOBAL_ACCESS = True

AUTHENTICATION_BACKENDS = AUTHENTICATION_BACKENDS + (
    'sentry_ldap_auth.backend.SentryLdapBackend',
)

import logging
logger = logging.getLogger('django_auth_ldap')
logger.addHandler(logging.StreamHandler())
logger.setLevel('DEBUG')

Besides Sentry I install openldap-clients package. He contains useful program ldapsearch

I use this program so:

# ldapsearch -x -h 10.10.10.1 -D "[email protected]" -W -b "cn=users,dc=test,dc=comp,dc=com" -s sub "(&(objectClass=user)(objectClass=person))" cn mail sn
Enter LDAP Password: 
# extended LDIF
#
# LDAPv3
# base <cn=users,dc=test,dc=comp,dc=com> with scope subtree
# filter: (&(objectClass=user)(objectClass=person))
# requesting: cn mail sn 
#
**** DATA OF AD-SERVER****
# search result
search: 2
result: 0 Success

# numResponses: 5
# numEntries: 4

Wherein in the Event Viewer Windows server writes logs about the successful entry and exit AD-user.

If I introduce incorrect password, I get follow:

# ldapsearch -x -h 10.10.10.1 -D "[email protected]" -W -b "cn=users,dc=test,dc=comp,dc=com" -s sub "(&(objectClass=user)(objectClass=person))" cn mail sn
Enter LDAP Password: 
ldap_bind: Invalid credentials (49)
	additional info: 80090308: LdapErr: DSID-0C0903A9, comment: AcceptSecurityContext error, data 52e, v1db1

... and in Event Viewer Windows server writes about unsuccessful entry.

The (&(objectClass=user)(objectClass=person)) I found in the Google and this one of two filters, which AD processes correctly (second - (cn=*) ). To all other filters I get follow error:

# ldapsearch -x -h 10.10.10.1 -D "[email protected]" -W -b "cn=users,dc=test,dc=comp,dc=com" -s sub "(uid=%(user)s)" cn mail
Enter LDAP Password: 
# extended LDIF
#
# LDAPv3
# base <cn=users,dc=test,dc=comp,dc=com> with scope subtree
# filter: (uid=%(user)s)
# requesting: cn mail 
#

ldap_search_ext: Bad search filter (-7)

And in the Event Viewer writes the successful entry.

So I'm currently using (&(objectClass=user)(objectClass=person)) in the Sentry config.

Generally, program ldapsearch makes me understand, that the LDAP-client is working fine.

Further on Sentry:

Whatever I filter and the credentials would not write to the config, nothing falls into Event Viewer when trying to enter through Web-interface.

I introduce login "user" and password "1qaz@WSX" I introduce login "[email protected]" and password "1qaz@WSX" I introduce login "[email protected]" and password "123" (incorrect) But nothing not writes in the Event Viewer. As if Sentry did not try to contact with AD. Maybe I'm misusing the data in the Web-interface?

(&(objectClass=user)(objectClass=person)(cn=%(user)s) in the ldapsearch output "ldap_search_ext: Bad search filter (-7). " Anonymously user in Sentry config does not affect the result in any way.

I do not understand why Sentry does not try to contact the AD server at all. Even if there was an incorrect filter, then the logs Event Viewer would at least have information about the wrong request or password. But he is not. Can really the whole point is that I incorrectly enter the login in the WEB interface?

Piknik1990 avatar Sep 11 '17 11:09 Piknik1990

Hello Piknik1990, have you found a solution? I have the same Problem.

wolfbo avatar Dec 19 '17 07:12 wolfbo

No, we moved to OpenLDAP and no solved this problem more.

Piknik1990 avatar Sep 04 '18 10:09 Piknik1990

Working confing for AD Testing on sentry 8-9.1

########
# LDAP #
########

import sys
reload(sys)
sys.setdefaultencoding('utf8')
import ldap

from django_auth_ldap.config import LDAPSearch, GroupOfUniqueNamesType

AUTH_LDAP_ALWAYS_UPDATE_USER = True
AUTH_LDAP_SERVER_URI = env('SENTRY_LDAP_SERVER_URI')
AUTH_LDAP_BIND_DN = env('SENTRY_LDAP_BIND_DN')
AUTH_LDAP_BIND_PASSWORD = env('SENTRY_LDAP_BIND_PASSWORD')
AUTH_LDAP_USER_SEARCH = LDAPSearch(u"dc=domain,dc=lan",ldap.SCOPE_SUBTREE,u"(sAMAccountName=%(user)s)"
)

AUTH_LDAP_GROUP_SEARCH = LDAPSearch(
    u'',
    ldap.SCOPE_SUBTREE,
    u'(objectClass=groupOfUniqueNames)'
)

AUTH_LDAP_GROUP_TYPE = GroupOfUniqueNamesType()
AUTH_LDAP_REQUIRE_GROUP = None
AUTH_LDAP_DENY_GROUP = None

AUTH_LDAP_USER_ATTR_MAP = {
    "username": "sAMAccountName",
    "first_name": u"givenName",
    "last_name": u"sn",
    "email": "mail",
}

AUTH_LDAP_FIND_GROUP_PERMS = False
AUTH_LDAP_CACHE_GROUPS = True
AUTH_LDAP_GROUP_CACHE_TIMEOUT = 3600

AUTH_LDAP_DEFAULT_SENTRY_ORGANIZATION = u'Sentry'
AUTH_LDAP_SENTRY_ORGANIZATION_ROLE_TYPE = 'member'
AUTH_LDAP_SENTRY_ORGANIZATION_GLOBAL_ACCESS = True
AUTH_LDAP_SENTRY_SUBSCRIBE_BY_DEFAULT = False

SENTRY_MANAGED_USER_FIELDS = ('email', 'first_name', 'last_name', 'password', )

AUTHENTICATION_BACKENDS = AUTHENTICATION_BACKENDS + (
    'sentry_ldap_auth.backend.SentryLdapBackend',
)

CBEPX avatar Apr 10 '19 14:04 CBEPX