diff --git a/README.md b/README.md index 067ff96d3871e6b9937566116ac4004aaf44bcfc..c496b54345880adc9f23fe961bd5cbd93b7fd4e4 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ LDAP Proxy for Uffd =================== -LDAP server that provides a view on user data exposed by uffd's API. Based on python-ldapserver. +LDAP server that provides user and group data exposed by uffd's API. Based on python-ldapserver. -**Prototype! Do not use in production!** +Requires at least uffd v1.2.0! diff --git a/debian/contrib/uffd-ldap.conf b/debian/contrib/uffd-ldap.conf index d63bc0470e2b6d1a477fbfc2508abc13963f477b..03a8fa08cf870a438ce3dbb4a403fca5fa84f018 100644 --- a/debian/contrib/uffd-ldap.conf +++ b/debian/contrib/uffd-ldap.conf @@ -1,6 +1,7 @@ -# Both options must be set +# All of these options must be set: #SERVER_API_URL="https://localhost" -#SERVER_API_KEY="my_secret_api_token" +#SERVER_API_USER="client_id" +#SERVER_API_SECRET="my_secret_api_client_secret" #SERVER_BASE_DN="dc=example,dc=com" # If bind password is not set, anonymous binds have full read permissions. diff --git a/server.py b/server.py index a55095970bebe3f7a423382e33c9a06f3a6f486c..587c449e73021c409b7b66a3dacf60fd65ccc5ab 100755 --- a/server.py +++ b/server.py @@ -22,11 +22,14 @@ CUSTOM_SCHEMA = (RFC2307BIS_SCHEMA|RFC2798_SCHEMA).extend(attribute_type_definit ]) class UffdAPI: - def __init__(self, baseurl, key, cache_ttl=60): + def __init__(self, baseurl, client_id, client_secret, cache_ttl=60): self.baseurl = baseurl - self.key = key - self.session = CacheControl(requests.Session(), heuristic=ExpiresAfter(seconds=cache_ttl)) - self.session.headers['Authorization'] = 'Bearer '+self.key + self.client_id = client_id + self.client_secret = client_secret + self.session = requests.Session() + self.session.auth = (client_id, client_secret) + if cache_ttl: + self.session = CacheControl(self.session, heuristic=ExpiresAfter(seconds=cache_ttl)) def get(self, endpoint, **kwargs): resp = self.session.get(self.baseurl + endpoint, params=kwargs) @@ -263,11 +266,12 @@ class StdoutFilter(logging.Filter): @click.option('--socket-path', type=click.Path(), help='Path for UNIX domain socket') @click.option('--socket-fd', type=int, help='Use fd number as server socket (alternative to --socket-path)') @click.option('--api-url', required=True, help='Uffd base URL without API prefix or trailing slash (e.g. https://example.com)') -@click.option('--api-key', required=True, help='API secret, do not set this on the command-line, use environment variable SERVER_API_KEY instead') +@click.option('--api-user', required=True, help='API user/client id') +@click.option('--api-secret', required=True, help='API secret, do not set this on the command-line, use environment variable SERVER_API_SECRET instead') @click.option('--cache-ttl', default=60, help='Time-to-live for API response caching in seconds') @click.option('--base-dn', required=True, help='Base DN for user, group and system objects. E.g. "dc=example,dc=com"') @click.option('--bind-password', help='Authentication password for the service connection to LDAP. Bind DN is always "cn=service,ou=system,BASEDN". If set, anonymous access is disabled.') -def main(socket_address, socket_path, socket_fd, api_url, api_key, cache_ttl, base_dn, bind_password): +def main(socket_address, socket_path, socket_fd, api_url, api_user, api_secret, cache_ttl, base_dn, bind_password): # pylint: disable=too-many-locals if (socket_address is not None) \ + (socket_path is not None) \ @@ -284,7 +288,7 @@ def main(socket_address, socket_path, socket_fd, api_url, api_key, cache_ttl, ba root_logger.addHandler(stdout_handler) root_logger.addHandler(stderr_handler) - api = UffdAPI(api_url, api_key, cache_ttl) + api = UffdAPI(api_url, api_user, api_secret, cache_ttl) RequestHandler = make_requesthandler(api, base_dn, bind_password) if socket_address is not None: host, port = parse_network_address(socket_address)