Refactor LDAP Client
* Enable LDAP traffic logging * Specify CA certificates file * Move client creation to actual parent * Fix OpenLDAP container certificate generation
This commit is contained in:
parent
ced97f549c
commit
9ee69fb907
|
@ -6,12 +6,13 @@ core:
|
||||||
|
|
||||||
|
|
||||||
ldap:
|
ldap:
|
||||||
host: 127.0.0.1
|
host: localhost
|
||||||
port: 389
|
port: 389
|
||||||
|
|
||||||
encryption: TLSv1.2 # Can either be None or TLSv1.2. Default: None
|
encryption: TLSv1.2 # Can either be None or TLSv1.2. Default: None
|
||||||
ciphers: "HIGH"
|
ciphers: "HIGH"
|
||||||
validate: False # Can either be True or False. Default: False
|
validate: True # Can either be True or False. Default: False
|
||||||
|
ca_certs: openldap/cert.pem
|
||||||
|
|
||||||
username: uid=phi,ou=Services,dc=unit,dc=macaomilano,dc=org
|
username: uid=phi,ou=Services,dc=unit,dc=macaomilano,dc=org
|
||||||
password: phi
|
password: phi
|
||||||
|
@ -42,3 +43,6 @@ logging:
|
||||||
aiohttp:
|
aiohttp:
|
||||||
level: DEBUG
|
level: DEBUG
|
||||||
handlers: [console, file]
|
handlers: [console, file]
|
||||||
|
ldap3:
|
||||||
|
level: DEBUG
|
||||||
|
handlers: [console, file]
|
||||||
|
|
|
@ -9,7 +9,7 @@ build: gen-cert
|
||||||
gen-cert:
|
gen-cert:
|
||||||
openssl req \
|
openssl req \
|
||||||
-x509 -nodes -days 365 -sha256 \
|
-x509 -nodes -days 365 -sha256 \
|
||||||
-subj '/C=IT/ST=Lombardia/L=Milano/CN=unit.macaomilano.org' \
|
-subj '/C=IT/ST=Lombardia/L=Milano/CN=localhost' \
|
||||||
-newkey rsa:2048 -keyout key.pem -out cert.pem
|
-newkey rsa:2048 -keyout key.pem -out cert.pem
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
|
|
|
@ -1,14 +1,31 @@
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
|
|
||||||
from phi.logging import get_logger
|
from phi.logging import get_logger
|
||||||
|
from phi.ldap.client import Client
|
||||||
from phi.api.routes import api_routes
|
from phi.api.routes import api_routes
|
||||||
|
|
||||||
log = get_logger(__name__)
|
log = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def api_app(ldap_client=None):
|
def api_startup(app):
|
||||||
|
app['ldap_client'].open()
|
||||||
|
|
||||||
|
|
||||||
|
def api_shutdown(app):
|
||||||
|
app['ldap_client'].close()
|
||||||
|
|
||||||
|
|
||||||
|
def api_app(config):
|
||||||
log.info("Initializing API sub-app.")
|
log.info("Initializing API sub-app.")
|
||||||
|
|
||||||
app = web.Application()
|
app = web.Application()
|
||||||
app.router.add_routes(api_routes)
|
|
||||||
|
ldap_client = Client(**config.get('ldap', {}))
|
||||||
app['ldap_client'] = ldap_client
|
app['ldap_client'] = ldap_client
|
||||||
|
|
||||||
|
app.on_startup.append(api_startup)
|
||||||
|
app.on_shutdown.append(api_shutdown)
|
||||||
|
|
||||||
|
app.router.add_routes(api_routes)
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
from aiohttp.web import Response
|
from aiohttp.web import json_response
|
||||||
|
|
||||||
|
|
||||||
def status(request):
|
def status(request):
|
||||||
Response(text="Status: it's working!")
|
response = {
|
||||||
|
'ldap': {
|
||||||
|
'connected': not request.app['ldap_client'].connection.closed,
|
||||||
|
'bound': request.app['ldap_client'].connection.bound
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return json_response(response)
|
||||||
|
|
|
@ -2,7 +2,6 @@ from asyncio import get_event_loop
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
|
|
||||||
from phi.api.app import api_app
|
from phi.api.app import api_app
|
||||||
from phi.ldap.client import Client
|
|
||||||
|
|
||||||
|
|
||||||
def setup_app(config):
|
def setup_app(config):
|
||||||
|
@ -11,14 +10,17 @@ def setup_app(config):
|
||||||
app = web.Application(loop=loop)
|
app = web.Application(loop=loop)
|
||||||
app['config'] = config
|
app['config'] = config
|
||||||
|
|
||||||
ldap_client = Client(**config.get('ldap', {}))
|
|
||||||
|
|
||||||
api = api_app(ldap_client=ldap_client)
|
api = api_app(config)
|
||||||
app.add_subapp('/api', api)
|
app.add_subapp('/api', api)
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
|
||||||
|
|
||||||
|
def shutdown_app(app):
|
||||||
|
app['ldap_client'].close()
|
||||||
|
|
||||||
|
|
||||||
def run_app(app):
|
def run_app(app):
|
||||||
web.run_app(app,
|
web.run_app(app,
|
||||||
host=app['config']['core']['listen'].get('host', '127.0.0.1'),
|
host=app['config']['core']['listen'].get('host', '127.0.0.1'),
|
||||||
|
|
|
@ -1,24 +1,26 @@
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
from ldap3.utils.log import set_library_log_detail_level, PROTOCOL
|
from ldap3.utils.log import set_library_log_detail_level, BASIC
|
||||||
|
|
||||||
from phi.logging import get_logger
|
from phi.logging import get_logger
|
||||||
from phi.ldap.connection import make_connection
|
from phi.ldap.connection import make_connection
|
||||||
from phi.ldap.connection import open_connection, close_connection
|
from phi.ldap.connection import open_connection, close_connection
|
||||||
|
|
||||||
log = get_logger(__name__)
|
log = get_logger(__name__)
|
||||||
set_library_log_detail_level(PROTOCOL)
|
set_library_log_detail_level(BASIC)
|
||||||
|
|
||||||
|
|
||||||
class Client:
|
class Client:
|
||||||
def __init__(self, host=None, port=389,
|
def __init__(self, host=None, port=389,
|
||||||
encryption=None, ciphers=None, validate=False,
|
encryption=None, ciphers=None, validate=False,
|
||||||
username=None, password=None,
|
ca_certs=None, username=None, password=None,
|
||||||
base_dn=None):
|
base_dn=None):
|
||||||
|
log.info("Initializing LDAP Client.")
|
||||||
self.host = host
|
self.host = host
|
||||||
self.port = port
|
self.port = port
|
||||||
self.encryption = encryption
|
self.encryption = encryption
|
||||||
self.ciphers = ciphers
|
self.ciphers = ciphers
|
||||||
self.validate = validate
|
self.validate = validate
|
||||||
|
self.ca_certs = ca_certs
|
||||||
self.username = username
|
self.username = username
|
||||||
self.password = password
|
self.password = password
|
||||||
self.base_dn = base_dn
|
self.base_dn = base_dn
|
||||||
|
@ -28,6 +30,7 @@ class Client:
|
||||||
encryption=self.encryption,
|
encryption=self.encryption,
|
||||||
ciphers=self.ciphers,
|
ciphers=self.ciphers,
|
||||||
validate=self.validate,
|
validate=self.validate,
|
||||||
|
ca_certs=self.ca_certs,
|
||||||
username=self.username,
|
username=self.username,
|
||||||
password=self.password)
|
password=self.password)
|
||||||
|
|
||||||
|
@ -35,11 +38,10 @@ class Client:
|
||||||
self.connection_lock.acquire()
|
self.connection_lock.acquire()
|
||||||
if self.connection.closed is True:
|
if self.connection.closed is True:
|
||||||
open_connection(self.connection)
|
open_connection(self.connection)
|
||||||
|
self.connection_lock.release()
|
||||||
else:
|
else:
|
||||||
self.connection_lock.release()
|
self.connection_lock.release()
|
||||||
raise Exception("Connection is already open. "
|
raise Exception("Trying to open a connection, but it is already open.")
|
||||||
"Cannot open again.")
|
|
||||||
self.connection_lock.release()
|
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
self.connection_lock.acquire()
|
self.connection_lock.acquire()
|
||||||
|
|
|
@ -8,10 +8,10 @@ log = get_logger(__name__)
|
||||||
|
|
||||||
def make_connection(host=None, port=389,
|
def make_connection(host=None, port=389,
|
||||||
encryption=None, ciphers=None, validate=False,
|
encryption=None, ciphers=None, validate=False,
|
||||||
username=None, password=None):
|
ca_certs=None, username=None, password=None):
|
||||||
# TLSv1.2 is supported since Python 3.4
|
# TLSv1.2 is supported since Python 3.4
|
||||||
if encryption is None:
|
if encryption is None:
|
||||||
log.info("The connection to the LDAP server will not be encrypted.")
|
log.warning("The connection to the LDAP server will not be encrypted.")
|
||||||
tls = None
|
tls = None
|
||||||
elif encryption == "TLSv1.2":
|
elif encryption == "TLSv1.2":
|
||||||
log.info("The connection to the LDAP server will use TLSv1.2.")
|
log.info("The connection to the LDAP server will use TLSv1.2.")
|
||||||
|
@ -29,6 +29,11 @@ def make_connection(host=None, port=389,
|
||||||
"remote hostname.")
|
"remote hostname.")
|
||||||
tls.validate = CERT_REQUIRED
|
tls.validate = CERT_REQUIRED
|
||||||
|
|
||||||
|
if encryption is not None and validate is True and ca_certs is not None:
|
||||||
|
log.info("Using the following CA certificates: {}"
|
||||||
|
.format(ca_certs))
|
||||||
|
tls.ca_certs_file = ca_certs
|
||||||
|
|
||||||
server = Server(host=host, port=port, tls=tls)
|
server = Server(host=host, port=port, tls=tls)
|
||||||
connection = Connection(server, user=username, password=password,
|
connection = Connection(server, user=username, password=password,
|
||||||
client_strategy=ASYNC)
|
client_strategy=ASYNC)
|
||||||
|
@ -49,5 +54,6 @@ def open_connection(connection):
|
||||||
|
|
||||||
|
|
||||||
def close_connection(connection):
|
def close_connection(connection):
|
||||||
|
log.info("Closing connection to LDAP server.")
|
||||||
log.info("Issuing UNBIND command.")
|
log.info("Issuing UNBIND command.")
|
||||||
connection.unbind()
|
connection.unbind()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user