Compare commits

..

No commits in common. "json-serialize-output" and "master" have entirely different histories.

15 changed files with 160 additions and 253 deletions

View File

@ -8,11 +8,11 @@ log = get_logger(__name__)
def api_startup(app): def api_startup(app):
app["ldap_client"].open() app['ldap_client'].open()
def api_shutdown(app): def api_shutdown(app):
app["ldap_client"].close() app['ldap_client'].close()
def api_app(config): def api_app(config):
@ -20,8 +20,8 @@ def api_app(config):
app = web.Application() app = web.Application()
ldap_client = Client(**config.get("ldap", {})) ldap_client = Client(**config.get('ldap', {}))
app["ldap_client"] = ldap_client app['ldap_client'] = ldap_client
app.on_startup.append(api_startup) app.on_startup.append(api_startup)
app.on_shutdown.append(api_shutdown) app.on_shutdown.append(api_shutdown)

View File

@ -10,12 +10,12 @@ log = get_logger(__name__)
class User(View): class User(View):
async def get(self): async def get(self):
uid = self.request.match_info.get("uid", None) uid = self.request.match_info.get('uid', None)
if uid is None: if uid is None:
return HTTPUnprocessableEntity() return HTTPUnprocessableEntity()
client = self.request.app["ldap_client"] client = self.request.app['ldap_client']
user = get_user_by_uid(client, uid) user = get_user_by_uid(client, uid)
if not user: if not user:

View File

@ -4,7 +4,7 @@ from phi.api.rest import User
api_routes = [ api_routes = [
route("*", "/user", User), route('*', '/user', User),
route("*", "/user/", User), route('*', '/user/', User),
route("*", "/user/{uid}", User), route('*', '/user/{uid}', User)
] ]

View File

@ -2,4 +2,5 @@ from datetime import datetime
def serialize(d): def serialize(d):
return {k: (v.isoformat() if isinstance(v, datetime) else v) for k, v in d.items()} return {k: (v.isoformat() if isinstance(v, datetime) else v)
for k, v in d.items()}

View File

@ -8,17 +8,15 @@ def setup_app(config):
loop = get_event_loop() loop = get_event_loop()
app = web.Application(loop=loop) app = web.Application(loop=loop)
app["config"] = config app['config'] = config
api = api_app(config) api = api_app(config)
app.add_subapp("/api", api) app.add_subapp('/api', api)
return app return app
def run_app(app): def run_app(app):
web.run_app( web.run_app(app,
app, host=app['config']['core']['listen'].get('host', '127.0.0.1'),
host=app["config"]["core"]["listen"].get("host", "127.0.0.1"), port=app['config']['core']['listen'].get('port', '8080'))
port=app["config"]["core"]["listen"].get("port", "8080"),
)

View File

@ -2,17 +2,16 @@ import sys
import argparse import argparse
import inspect import inspect
from phi.logging import setup_logging, get_logger from phi.logging import setup_logging, get_logger
from phi.compat.argparse import BooleanOptionalAction
log = get_logger(__name__) log = get_logger(__name__)
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
subparses = parser.add_subparsers(title="actions", dest="action") subparses = parser.add_subparsers(title='actions', dest='action')
cli_callbacks = {} cli_callbacks = {}
def register(action_info="", param_infos=[]): def register(action_info='', param_infos=[]):
def decorator(action): def decorator(action):
# Get function name and arguments # Get function name and arguments
action_name = action.__name__ action_name = action.__name__
@ -22,7 +21,7 @@ def register(action_info="", param_infos=[]):
subparser = subparses.add_parser(action_name, help=action_info) subparser = subparses.add_parser(action_name, help=action_info)
for i, name in enumerate(param_names): for i, name in enumerate(param_names):
info = param_infos[i] if i < len(param_infos) else "" info = param_infos[i] if i<len(param_infos) else ''
subparser.add_argument(dest=name, help=info) subparser.add_argument(dest=name, help=info)
# Register action # Register action
@ -34,7 +33,7 @@ def register(action_info="", param_infos=[]):
def run(args): def run(args):
for action_name, (action, param_names) in cli_callbacks.items(): for action_name, (action, param_names) in cli_callbacks.items():
if args["action"] == action_name: if args['action'] == action_name:
action(**{pname: args[pname] for pname in param_names}) action(**{pname: args[pname] for pname in param_names})
@ -42,12 +41,6 @@ def add_arg(name, example, info):
parser.add_argument(name, metavar=example, help=info) parser.add_argument(name, metavar=example, help=info)
def add_flag(name, info):
parser.add_argument(
name, action=BooleanOptionalAction, help=info, required=False, default=False
)
def get_args(): def get_args():
namespace = parser.parse_args(sys.argv[1:]) namespace = parser.parse_args(sys.argv[1:])
args = namespace.__dict__ args = namespace.__dict__

View File

@ -1,51 +0,0 @@
# -*- encoding: utf-8 -*-
# WARNING: This code has been copied verbatim from
# https://github.com/python/cpython/blob/3.9/Lib/argparse.py
# To be removed when the minimum python supported version
# will be >= 3.9
import argparse
class BooleanOptionalAction(argparse.Action):
def __init__(
self,
option_strings,
dest,
default=None,
type=None,
choices=None,
required=False,
help=None,
metavar=None,
):
_option_strings = []
for option_string in option_strings:
_option_strings.append(option_string)
if option_string.startswith("--"):
option_string = "--no-" + option_string[2:]
_option_strings.append(option_string)
if help is not None and default is not None:
help += f" (default: {default})"
super().__init__(
option_strings=_option_strings,
dest=dest,
nargs=0,
default=default,
type=type,
choices=choices,
required=required,
help=help,
metavar=metavar,
)
def __call__(self, parser, namespace, values, option_string=None):
if option_string in self.option_strings:
setattr(namespace, self.dest, not option_string.startswith("--no-"))
def format_usage(self):
return " | ".join(self.option_strings)

View File

@ -2,16 +2,15 @@ import os.path
import yaml import yaml
NAME = "phi" NAME = 'phi'
CONFIG_FILE = "config.yml" CONFIG_FILE = 'config.yml'
CONFIG_PATHS = [ CONFIG_PATHS = ['./',
"./", '~/.config/' + NAME + '/',
"~/.config/" + NAME + "/", '/usr/local/etc/' + NAME + '/',
"/usr/local/etc/" + NAME + "/", '/etc/' + NAME + '/']
"/etc/" + NAME + "/", CONFIG_FILES = [os.path.join(p, CONFIG_FILE)
] for p in CONFIG_PATHS]
CONFIG_FILES = [os.path.join(p, CONFIG_FILE) for p in CONFIG_PATHS]
def get_config(custom_config=None): def get_config(custom_config=None):
@ -26,7 +25,7 @@ def get_config(custom_config=None):
for f in CONFIG_FILES: for f in CONFIG_FILES:
try: try:
with open(f, "r") as c: with open(f, 'r') as c:
config = yaml.safe_load(c) config = yaml.safe_load(c)
return (f, config) return (f, config)
except FileNotFoundError: except FileNotFoundError:
@ -37,10 +36,9 @@ def get_config(custom_config=None):
pass pass
else: else:
if custom_config: if custom_config:
raise FileNotFoundError("Config file {} not found.".format(custom_config)) raise FileNotFoundError('Config file {} not found.'
.format(custom_config))
else: else:
raise FileNotFoundError( raise FileNotFoundError("Could not find {} in any of {}."
"Could not find {} in any of {}.".format( .format(CONFIG_FILE,
CONFIG_FILE, ", ".join(CONFIG_PATHS) ', '.join(CONFIG_PATHS)))
)
)

View File

@ -10,18 +10,11 @@ set_library_log_detail_level(PROTOCOL)
class Client: class Client:
def __init__( def __init__(self,
self, host=None, port=389,
host=None, encryption=None, ciphers=None, validate=False, ca_certs=None,
port=389, username=None, password=None,
encryption=None, base_dn=None):
ciphers=None,
validate=False,
ca_certs=None,
username=None,
password=None,
base_dn=None,
):
log.info("Initializing LDAP Client.") log.info("Initializing LDAP Client.")
self.host = host self.host = host
@ -38,16 +31,13 @@ class Client:
self.base_dn = base_dn self.base_dn = base_dn
self.connection_lock = Lock() self.connection_lock = Lock()
self.connection = make_connection( self.connection = make_connection(host=self.host, port=self.port,
host=self.host,
port=self.port,
encryption=self.encryption, encryption=self.encryption,
ciphers=self.ciphers, ciphers=self.ciphers,
validate=self.validate, validate=self.validate,
ca_certs=self.ca_certs, ca_certs=self.ca_certs,
username=self.username, username=self.username,
password=self.password, password=self.password)
)
def open(self): def open(self):
self.connection_lock.acquire() self.connection_lock.acquire()
@ -56,7 +46,8 @@ class Client:
self.connection_lock.release() self.connection_lock.release()
else: else:
self.connection_lock.release() self.connection_lock.release()
raise Exception("Trying to open a connection, " "but it is already open.") raise Exception("Trying to open a connection, "
"but it is already open.")
def close(self): def close(self):
self.connection_lock.acquire() self.connection_lock.acquire()

View File

@ -6,16 +6,9 @@ from phi.logging import get_logger
log = get_logger(__name__) log = get_logger(__name__)
def make_connection( def make_connection(host=None, port=389,
host=None, encryption=None, ciphers=None, validate=False,
port=389, ca_certs=None, username=None, password=None):
encryption=None,
ciphers=None,
validate=False,
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.warning("The connection to the LDAP server will not be encrypted.") log.warning("The connection to the LDAP server will not be encrypted.")
@ -27,26 +20,23 @@ def make_connection(
raise NotImplementedError("Sorry, use TLSv1.2.") raise NotImplementedError("Sorry, use TLSv1.2.")
if encryption is not None and ciphers is not None: if encryption is not None and ciphers is not None:
log.info( log.info("The connection to the LDAP server will use the "
"The connection to the LDAP server will use the " "following ciphers: {}".format(ciphers))
"following ciphers: {}".format(ciphers)
)
tls.ciphers = ciphers tls.ciphers = ciphers
if encryption is not None and validate is True: if encryption is not None and validate is True:
log.info( log.info("The certificate hostname will be checked to match the "
"The certificate hostname will be checked to match the " "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: 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)) log.info("Using the following CA certificates: {}"
.format(ca_certs))
tls.ca_certs_file = 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( connection = Connection(server, user=username, password=password,
server, user=username, password=password, client_strategy=ASYNC client_strategy=ASYNC)
)
return connection return connection

View File

@ -8,14 +8,13 @@ log = get_logger(__name__)
def get_group_by_cn(client, cn): def get_group_by_cn(client, cn):
log.info("Searching groups with common name: {}".format(cn)) log.info("Searching groups with common name: {}".format(cn))
dn = "cn={},ou=Groups,{}".format(cn, client.base_dn) dn = 'cn={},ou=Groups,{}'.format(cn, client.base_dn)
log.debug("Search dn: {}".format(dn)) log.debug("Search dn: {}".format(dn))
response_id = client.connection.search( response_id = client.connection.search(
dn, dn, '(objectclass=groupOfNames)',
"(objectclass=groupOfNames)", search_scope='SUBTREE',
search_scope="SUBTREE", attributes=[ALL_ATTRIBUTES]
attributes=[ALL_ATTRIBUTES],
) )
response = get_response(client, response_id) response = get_response(client, response_id)
@ -24,10 +23,9 @@ def get_group_by_cn(client, cn):
return None return None
if len(response) > 1: if len(response) > 1:
log.error( log.error("Looking for exactly one result but server gave {}. "
"Looking for exactly one result but server gave {}. " "Taking the first and ignoring the rest."
"Taking the first and ignoring the rest.".format(len(response)) .format(len(response)))
)
group = make_group_dict(client, response[0]) group = make_group_dict(client, response[0])
return group return group
@ -35,15 +33,14 @@ def get_group_by_cn(client, cn):
def get_all_groups(client): def get_all_groups(client):
log.info("Searching all the groups") log.info("Searching all the groups")
dn = "ou=Groups,{}".format(client.base_dn) dn = 'ou=Groups,{}'.format(client.base_dn)
log.debug("Search dn: {}".format(dn)) log.debug("Search dn: {}".format(dn))
response_id = client.connection.search( response_id = client.connection.search(
dn, dn, '(objectclass=groupOfNames)',
"(objectclass=groupOfNames)", search_scope='SUBTREE',
search_scope="SUBTREE", attributes=[ALL_ATTRIBUTES]
attributes=[ALL_ATTRIBUTES],
) )
response = get_response(client, response_id) response = get_response(client, response_id)
@ -52,12 +49,13 @@ def get_all_groups(client):
def add_group_member(client, group, user): def add_group_member(client, group, user):
group_dn = group["dn"] group_dn = group['dn']
member_dn = user["dn"] member_dn = user['dn']
log.debug("Found adding {} to {}".format(member_dn, group_dn)) log.debug('Found adding {} to {}'.format(member_dn, group_dn))
response_id = client.connection.modify( response_id = client.connection.modify(
group_dn, {"member": [(MODIFY_ADD, [member_dn])]} group_dn,
{'member': [(MODIFY_ADD, [member_dn])]}
) )
return get_response(client, response_id) return get_response(client, response_id)

View File

@ -9,11 +9,13 @@ log = get_logger(__name__)
def get_user_by_uid(client, uid): def get_user_by_uid(client, uid):
log.info("Searching entry with identifier: {}".format(uid)) log.info("Searching entry with identifier: {}".format(uid))
filter_ = "({}={})".format("uid", uid) filter_ = "({}={})".format('uid', uid)
log.debug("Search filter: {}".format(filter_)) log.debug("Search filter: {}".format(filter_))
response_id = client.connection.search( response_id = client.connection.search(
client.base_dn, filter_, search_scope="SUBTREE", attributes=[ALL_ATTRIBUTES] client.base_dn, filter_,
search_scope='SUBTREE',
attributes=[ALL_ATTRIBUTES]
) )
response = get_response(client, response_id) response = get_response(client, response_id)
@ -22,10 +24,9 @@ def get_user_by_uid(client, uid):
return None return None
if len(response) > 1: if len(response) > 1:
log.error( log.error("Looking for exactly one result but server gave {}. "
"Looking for exactly one result but server gave {}. " "Taking the first and ignoring the rest."
"Taking the first and ignoring the rest.".format(len(response)) .format(len(response)))
)
return make_user_dict(client, response[0]) return make_user_dict(client, response[0])
@ -33,11 +34,13 @@ def get_user_by_uid(client, uid):
def get_all_users(client): def get_all_users(client):
log.info("Searching all the users") log.info("Searching all the users")
dn = "ou=Hackers,{}".format(client.base_dn) dn = 'ou=Hackers,{}'.format(client.base_dn)
log.debug("Search dn: {}".format(dn)) log.debug("Search dn: {}".format(dn))
response_id = client.connection.search( response_id = client.connection.search(
dn, "(objectclass=person)", search_scope="SUBTREE", attributes=[ALL_ATTRIBUTES] dn, '(objectclass=person)',
search_scope='SUBTREE',
attributes=[ALL_ATTRIBUTES]
) )
response = get_response(client, response_id) response = get_response(client, response_id)
@ -47,24 +50,28 @@ def get_all_users(client):
def add_user(client, uid, cn, sn, mail, password): def add_user(client, uid, cn, sn, mail, password):
dn = "uid={},ou=Hackers,{}".format(uid, client.base_dn) dn = 'uid={},ou=Hackers,{}'.format(uid, client.base_dn)
hashed_password = hashed(HASHED_SALTED_SHA, password) hashed_password = hashed(HASHED_SALTED_SHA, password)
attributes = { attributes={
"objectClass": ["inetOrgPerson", "organizationalPerson", "person", "top"], 'objectClass': [
"cn": cn, 'inetOrgPerson',
"sn": sn, 'organizationalPerson',
"mail": mail, 'person', 'top'
"userPassword": hashed_password, ],
'cn': cn,
'sn': sn,
'mail': mail,
'userPassword': hashed_password
} }
add_entry(client, dn, attributes) add_entry(client, dn, attributes)
def delete_user(client, user): def delete_user(client, user):
delete_entry(client, user["dn"]) delete_entry(client, user['dn'])
def delete_user_by_uid(client, uid): def delete_user_by_uid(client, uid):
dn = "uid={},ou=Hackers,{}".format(uid, client.base_dn) dn = 'uid={},ou=Hackers,{}'.format(uid, client.base_dn)
delete_entry(client, dn) delete_entry(client, dn)

View File

@ -5,35 +5,37 @@ log = get_logger(__name__)
def make_user_dict(client, entry): def make_user_dict(client, entry):
attributes = entry["attributes"] attributes = entry['attributes']
user = {} user = {}
user["uid"] = attributes["uid"][0] user['uid'] = attributes['uid'][0]
user["dn"] = "uid={},ou=Hackers,{}".format(user["uid"], client.base_dn) user['dn'] = 'uid={},ou=Hackers,{}'.format(user['uid'], client.base_dn)
user["cn"] = attributes["cn"][0] user['cn'] = attributes['cn'][0]
user["sn"] = attributes["sn"][0] user['sn'] = attributes['sn'][0]
user["mail"] = attributes["mail"][0] user['mail'] = attributes['mail'][0]
user["password"] = attributes["userPassword"][0] user['password'] = attributes['userPassword'][0]
return user return user
def get_uid_from_dn(client, dn): def get_uid_from_dn(client, dn):
uid = re.search("uid=(.+?),ou=Hackers,{}".format(client.base_dn), dn).group(1) uid = re.search('uid=(.+?),ou=Hackers,{}'.format(client.base_dn),
dn).group(1)
return uid return uid
def make_group_dict(client, entry): def make_group_dict(client, entry):
attributes = entry["attributes"] attributes = entry['attributes']
cn = attributes["cn"][0] cn = attributes['cn'][0]
dn = "cn={},ou=Groups,{}".format(cn, client.base_dn) dn = 'cn={},ou=Groups,{}'.format(cn, client.base_dn)
members = [get_uid_from_dn(client, u_dn) for u_dn in attributes["member"]] members = [get_uid_from_dn(client, u_dn)
for u_dn in attributes['member']]
group = {} group = {}
group["dn"] = dn group['dn'] = dn
group["cn"] = cn group['cn'] = cn
group["members"] = members group['members'] = members
return group return group
@ -47,24 +49,22 @@ def get_response(client, response_id):
log.debug("Response: {}".format(response)) log.debug("Response: {}".format(response))
log.debug("Result: {}".format(result)) log.debug("Result: {}".format(result))
if result["description"] is not "success": if result['description'] is not 'success':
raise Exception(result["description"]) raise Exception(result['description'])
return response return response
def add_entry(client, dn, attributes): def add_entry(client, dn, attributes):
log.info( log.info('Adding entry with distinguiscet name: {}'
"Adding entry with distinguiscet name: {}" 'and attributes {}'.format(dn, attributes))
"and attributes {}".format(dn, attributes)
)
response_id = client.connection.add(dn, attributes=attributes) response_id = client.connection.add(dn, attributes=attributes)
response = get_response(client, response_id) response = get_response(client, response_id)
return response return response
def delete_entry(client, dn): def delete_entry(client, dn):
log.info("Deleting entry with distinguiscet name: {}") log.info('Deleting entry with distinguiscet name: {}')
response_id = client.connection.delete(dn) response_id = client.connection.delete(dn)
response = get_response(client, response_id) response = get_response(client, response_id)
return response return response

View File

@ -1,7 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from pprint import pformat as pp from pprint import pformat as pp
from getpass import getpass from getpass import getpass
import json
from phi.config import get_config from phi.config import get_config
from phi.logging import setup_logging, get_logger from phi.logging import setup_logging, get_logger
@ -12,36 +11,21 @@ from phi.ldap.group import get_group_by_cn, get_all_groups, add_group_member
log = get_logger(__name__) log = get_logger(__name__)
JSON_ENC = json.JSONEncoder()
SHOW_PASSWORDS = False
@cli.register('dispaly user fields', ['user identifier'])
def sanitize(obj):
if isinstance(obj, list):
return [sanitize(el) for el in obj]
elif isinstance(obj, dict):
return dict((sanitize(k), sanitize(v)) for k, v in obj.items())
elif isinstance(obj, bytes):
return [hex(el) for el in list(obj)]
return obj
@cli.register("dispaly user fields", ["user identifier"])
def showuser(uid): def showuser(uid):
user = get_user_by_uid(client, uid) user = get_user_by_uid(client, uid)
if user is None: if user is None:
print("User {} not found".format(uid)) print('User {} not found'.format(uid))
return return
if not SHOW_PASSWORDS:
user.pop("password")
print(JSON_ENC.encode(sanitize(user))) print(pp(user))
@cli.register("add a new user", ["user identifier"]) @cli.register('add a new user', ['user identifier'])
def adduser(uid): def adduser(uid):
def ask(prompt, default): def ask(prompt, default):
full_prompt = "{} [{}] ".format(prompt, default) full_prompt = '{} [{}] '.format(prompt, default)
return input(full_prompt) or default return input(full_prompt) or default
user = get_user_by_uid(client, uid) user = get_user_by_uid(client, uid)
@ -49,100 +33,98 @@ def adduser(uid):
print("User {} already existing".format(uid)) print("User {} already existing".format(uid))
return return
cn = ask("Common name:", uid) cn = ask('Common name:', uid)
sn = ask("Last name:", uid) sn = ask('Last name:', uid)
mail = ask("Mail:", "{}@localhost".format(uid)) mail = ask('Mail:', '{}@localhost'.format(uid))
password = getpass() password = getpass()
pass_check = getpass("Retype password: ") pass_check = getpass('Retype password: ')
if password != pass_check: if password != pass_check:
print("Password not matching") print('Password not matching')
return return
add_user(client, uid, cn, sn, mail, password) add_user(client, uid, cn, sn, mail, password)
# Check # Check
user = get_user_by_uid(client, uid) user = get_user_by_uid(client, uid)
if not SHOW_PASSWORDS: print()
user.pop("password") print(pp(user))
print(JSON_ENC.encode(sanitize(user)))
@cli.register("delete an user", ["user identifier"]) @cli.register('delete an user', ['user identifier'])
def deluser(uid): def deluser(uid):
check = input("Are you sure? [y/N] ") or "N" check = input('Are you sure? [y/N] ') or 'N'
if check.lower() != "y": if check.lower() != 'y':
print("Ok then") print('Ok then')
return return
user = get_user_by_uid(client, uid) user = get_user_by_uid(client, uid)
if user is not None: if user is not None:
delete_user(client, user) delete_user(client, user)
print("Done") print('Done')
else: else:
print("User {} not found".format(uid)) print('User {} not found'.format(uid))
@cli.register("show a group", ["group common name"]) @cli.register('show a group', ['group common name'])
def showgroup(cn): def showgroup(cn):
group = get_group_by_cn(client, cn) group = get_group_by_cn(client, cn)
if group is None: if group is None:
print("Group {} not found".format(gcn)) print('Group {} not found'.format(gcn))
return return
print(JSON_ENC.encode(sanitize(group))) print(pp(group))
@cli.register("list all groups") @cli.register('list all groups')
def listgroups(): def listgroups():
groups = get_all_groups(client) groups = get_all_groups(client)
for group in groups: for group in groups:
print(group["cn"]) print(group['cn'])
@cli.register("add an user to a group", ["user identifier", "group common name"]) @cli.register('add an user to a group',
['user identifier', 'group common name'])
def addtogroup(uid, gcn): def addtogroup(uid, gcn):
user = get_user_by_uid(client, uid) user = get_user_by_uid(client, uid)
group = get_group_by_cn(client, gcn) group = get_group_by_cn(client, gcn)
if user is None: if user is None:
print("User {} not found".format(uid)) print('User {} not found'.format(uid))
return return
if group is None: if group is None:
print("Group {} not found".format(gcn)) print('Group {} not found'.format(gcn))
return return
if uid in group["members"]: if uid in group['members']:
print("User {} is already in group {}".format(uid, gcn)) print('User {} is already in group {}'.format(uid, gcn))
return return
add_group_member(client, group, user) add_group_member(client, group, user)
if __name__ == "__main__": if __name__ == '__main__':
cli.add_arg("--config", "config.yml", "custom configuration file") cli.add_arg('--config', 'config.yml', 'custom configuration file')
cli.add_flag("--show-passwords", "show the passwords bytes")
args = cli.get_args() args = cli.get_args()
config_file = args["config"] config_file = args['config']
SHOW_PASSWORDS = args["show_passwords"]
config_file, config = get_config(config_file) config_file, config = get_config(config_file)
setup_logging(config.get("logging", {})) setup_logging(config.get('logging', {}))
log.info("Using configuration at '{}':\n{}".format(config_file, pp(config))) log.info("Using configuration at '{}':\n{}"
.format(config_file, pp(config)))
# TODO: check fields in config # TODO: check fields in config
client = phi.ldap.client.Client(**config["ldap"]) client = phi.ldap.client.Client(**config['ldap'])
log.info("Opening LDAP client") log.info('Opening LDAP client')
client.open() client.open()
log.info("Arguments: {}".format(pp(args))) log.info('Arguments: {}'.format(pp(args)))
cli.run(args) cli.run(args)
log.info("Closing LDAP client") log.info('Closing LDAP client')
client.close() client.close()