mirror of
				https://github.com/laurivosandi/certidude
				synced 2025-10-31 09:29:13 +00:00 
			
		
		
		
	Refactor LDAP authentication
* ldap uri can be specified in /etc/certidude/server.conf now * /etc/ldap/ldap.conf is ignored
This commit is contained in:
		| @@ -44,7 +44,6 @@ class SessionResource(object): | ||||
|     @login_required | ||||
|     @event_source | ||||
|     def on_get(self, req, resp): | ||||
|  | ||||
|         return dict( | ||||
|             user = dict( | ||||
|                 name=req.context.get("user").name, | ||||
|   | ||||
| @@ -122,9 +122,9 @@ def authenticate(optional=False): | ||||
|             import ldap | ||||
|  | ||||
|             if not req.auth: | ||||
|                 resp.append_header("WWW-Authenticate", "Basic") | ||||
|                 raise falcon.HTTPUnauthorized("Forbidden", | ||||
|                     "Please authenticate with %s domain account or supply UPN" % const.DOMAIN) | ||||
|                 raise falcon.HTTPUnauthorized("Unauthorized", | ||||
|                     "No authentication header provided", | ||||
|                     ("Basic",)) | ||||
|  | ||||
|             if not req.auth.startswith("Basic "): | ||||
|                 raise falcon.HTTPForbidden("Forbidden", "Bad header: %s" % req.auth) | ||||
| @@ -133,26 +133,35 @@ def authenticate(optional=False): | ||||
|             basic, token = req.auth.split(" ", 1) | ||||
|             user, passwd = b64decode(token).split(":", 1) | ||||
|  | ||||
|             for server in config.LDAP_SERVERS: | ||||
|                 click.echo("Connecting to %s as %s" % (server, user)) | ||||
|                 conn = ldap.initialize(server) | ||||
|                 conn.set_option(ldap.OPT_REFERRALS, 0) | ||||
|                 try: | ||||
|                     conn.simple_bind_s(user if "@" in user else "%s@%s" % (user, const.DOMAIN), passwd) | ||||
|                 except ldap.LDAPError, e: | ||||
|                     resp.append_header("WWW-Authenticate", "Basic") | ||||
|                     logger.critical(u"LDAP bind authentication failed for user %s from  %s", | ||||
|                         repr(user), req.context.get("remote_addr")) | ||||
|                     raise falcon.HTTPUnauthorized("Forbidden", | ||||
|                         "Please authenticate with %s domain account or supply UPN" % const.DOMAIN) | ||||
|             click.echo("Connecting to %s as %s" % (config.LDAP_AUTHENTICATION_URI, user)) | ||||
|             conn = ldap.initialize(config.LDAP_AUTHENTICATION_URI) | ||||
|             conn.set_option(ldap.OPT_REFERRALS, 0) | ||||
|  | ||||
|                 req.context["ldap_conn"] = conn | ||||
|                 break | ||||
|             else: | ||||
|                 raise ValueError("No LDAP servers!") | ||||
|             if "@" not in user: | ||||
|                 user = "%s@%s" % (user, const.DOMAIN) | ||||
|                 logger.debug("Expanded username to %s", user) | ||||
|  | ||||
|             try: | ||||
|                 conn.simple_bind_s(user, passwd) | ||||
|             except ldap.STRONG_AUTH_REQUIRED: | ||||
|                 logger.critical("LDAP server demands encryption, use ldaps:// instead of ldaps://") | ||||
|                 raise | ||||
|             except ldap.SERVER_DOWN: | ||||
|                 logger.critical("Failed to connect LDAP server at %s, are you sure LDAP server's CA certificate has been copied to this machine?", | ||||
|                     config.LDAP_AUTHENTICATION_URI) | ||||
|                 raise | ||||
|             except ldap.INVALID_CREDENTIALS: | ||||
|                 logger.critical(u"LDAP bind authentication failed for user %s from  %s", | ||||
|                     repr(user), req.context.get("remote_addr")) | ||||
|                 raise falcon.HTTPUnauthorized("Forbidden", | ||||
|                     "Please authenticate with %s domain account or supply UPN" % const.DOMAIN, | ||||
| 		("Basic",)) | ||||
|  | ||||
|             req.context["ldap_conn"] = conn | ||||
|             req.context["user"] = User.objects.get(user) | ||||
|             return func(resource, req, resp, *args, **kwargs) | ||||
|             retval = func(resource, req, resp, *args, **kwargs) | ||||
|             conn.unbind_s() | ||||
|             return retval | ||||
|  | ||||
|  | ||||
|         def pam_authenticate(resource, req, resp, *args, **kwargs): | ||||
|   | ||||
| @@ -18,8 +18,10 @@ AUTHENTICATION_BACKENDS = set([j for j in | ||||
| AUTHORIZATION_BACKEND = cp.get("authorization", "backend")  # whitelist, ldap, posix | ||||
| ACCOUNTS_BACKEND = cp.get("accounts", "backend")             # posix, ldap | ||||
|  | ||||
| if ACCOUNTS_BACKEND == "ldap": | ||||
|     LDAP_GSSAPI_CRED_CACHE = cp.get("accounts", "ldap gssapi credential cache") | ||||
| LDAP_AUTHENTICATION_URI = cp.get("authentication", "ldap uri") | ||||
| LDAP_GSSAPI_CRED_CACHE = cp.get("accounts", "ldap gssapi credential cache") | ||||
| LDAP_ACCOUNTS_URI = cp.get("accounts", "ldap uri") | ||||
| LDAP_BASE = cp.get("accounts", "ldap base") | ||||
|  | ||||
| USER_SUBNETS = set([ipaddress.ip_network(j) for j in | ||||
|     cp.get("authorization", "user subnets").split(" ") if j]) | ||||
| @@ -78,17 +80,4 @@ elif "ldap" == AUTHORIZATION_BACKEND: | ||||
| else: | ||||
|     raise NotImplementedError("Unknown authorization backend '%s'" % AUTHORIZATION_BACKEND) | ||||
|  | ||||
| for line in open("/etc/ldap/ldap.conf"): | ||||
|     line = line.strip().lower() | ||||
|     if "#" in line: | ||||
|         line, _ = line.split("#", 1) | ||||
|     if not " " in line: | ||||
|         continue | ||||
|     key, value = line.split(" ", 1) | ||||
|     if key == "uri": | ||||
|         LDAP_SERVERS = set([j for j in value.split(" ") if j]) | ||||
|         click.echo("LDAP servers: %s" % " ".join(LDAP_SERVERS)) | ||||
|     elif key == "base": | ||||
|         LDAP_BASE = value | ||||
|  | ||||
| # TODO: Check if we don't have base or servers | ||||
|   | ||||
| @@ -9,11 +9,12 @@ backends = pam | ||||
| ;backends = ldap | ||||
| ;backends = kerberos ldap | ||||
| ;backends = kerberos pam | ||||
| ldap uri = ldaps://dc1.example.com | ||||
|  | ||||
| [accounts] | ||||
| # The accounts backend specifies how the user's given name, surname and e-mail | ||||
| # address are looked up. In case of 'posix' basically 'getent passwd' is performed, | ||||
| # in case of 'ldap' a search is performed on LDAP server specified in /etc/ldap/ldap.conf | ||||
| # in case of 'ldap' a search is performed on LDAP server specified by ldap uri | ||||
| # with Kerberos credential cache initialized at path specified by environment variable KRB5CCNAME | ||||
| # If certidude setup authority was performed correctly the credential cache should be | ||||
| # updated automatically by /etc/cron.hourly/certidude | ||||
| @@ -21,6 +22,8 @@ backends = pam | ||||
| backend = posix | ||||
| ;backend = ldap | ||||
| ldap gssapi credential cache = /run/certidude/krb5cc | ||||
| ldap uri = ldap://dc1.example.com | ||||
| ldap base = {% if base %}{{ base }}{% else %}dc=example,dc=com{% endif %} | ||||
|  | ||||
| [authorization] | ||||
| # The authorization backend specifies how the users are authorized. | ||||
|   | ||||
| @@ -70,17 +70,15 @@ class DirectoryConnection(object): | ||||
|             raise ValueError("Ticket cache at %s not initialized, unable to " | ||||
|                 "authenticate with computer account against LDAP server!" % config.LDAP_GSSAPI_CRED_CACHE) | ||||
|         os.environ["KRB5CCNAME"] = config.LDAP_GSSAPI_CRED_CACHE | ||||
|         for server in config.LDAP_SERVERS: | ||||
|             self.conn = ldap.initialize(server) | ||||
|             self.conn.set_option(ldap.OPT_REFERRALS, 0) | ||||
|             click.echo("Connecing to %s using Kerberos ticket cache from %s" % | ||||
|                 (server, config.LDAP_GSSAPI_CRED_CACHE)) | ||||
|             self.conn.sasl_interactive_bind_s('', ldap.sasl.gssapi()) | ||||
|             return self.conn | ||||
|         raise ValueError("No LDAP servers specified!") | ||||
|         self.conn = ldap.initialize(config.LDAP_ACCOUNTS_URI) | ||||
|         self.conn.set_option(ldap.OPT_REFERRALS, 0) | ||||
|         click.echo("Connecing to %s using Kerberos ticket cache from %s" % | ||||
|             (config.LDAP_ACCOUNTS_URI, config.LDAP_GSSAPI_CRED_CACHE)) | ||||
|         self.conn.sasl_interactive_bind_s('', ldap.sasl.gssapi()) | ||||
|         return self.conn | ||||
|  | ||||
|     def __exit__(self, type, value, traceback): | ||||
|         self.conn.unbind_s | ||||
|         self.conn.unbind_s() | ||||
|  | ||||
|  | ||||
| class ActiveDirectoryUserManager(object): | ||||
|   | ||||
		Reference in New Issue
	
	Block a user