Import
This commit is contained in:
commit
4bd5d74975
104
.gitignore
vendored
Normal file
104
.gitignore
vendored
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
.hypothesis/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
.static_storage/
|
||||||
|
.media/
|
||||||
|
local_settings.py
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
.python-version
|
||||||
|
|
||||||
|
# celery beat schedule file
|
||||||
|
celerybeat-schedule
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
30
README.md
Normal file
30
README.md
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# Phi
|
||||||
|
|
||||||
|
Post-Human Interface.
|
||||||
|
|
||||||
|
APIs for the Unit hacklab.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
|
||||||
|
* Python >= 3.4
|
||||||
|
|
||||||
|
Create a new virtualenv and run `pip install .` inside of it.
|
||||||
|
|
||||||
|
## LDAP client example
|
||||||
|
|
||||||
|
```
|
||||||
|
>>> from phi.config import get_config
|
||||||
|
>>> config_file, config = get_config()
|
||||||
|
>>> ldap_config = config['ldap']
|
||||||
|
>>>
|
||||||
|
>>> from phi.ldap.client import Client
|
||||||
|
>>> ldap_client = Client(**ldap_config)
|
||||||
|
>>>
|
||||||
|
>>> from phi.ldap.connection import open_connection
|
||||||
|
>>> open_connection(ldap_client.connection)
|
||||||
|
>>>
|
||||||
|
>>> from phi.ldap.commands import whoami
|
||||||
|
>>> whoami(client)
|
||||||
|
```
|
44
config.yml
Normal file
44
config.yml
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
---
|
||||||
|
core:
|
||||||
|
listen:
|
||||||
|
host: 127.0.0.1
|
||||||
|
port: 8080
|
||||||
|
|
||||||
|
|
||||||
|
ldap:
|
||||||
|
host: 127.0.0.1
|
||||||
|
port: 389
|
||||||
|
|
||||||
|
encryption: TLSv1.2 # Can either be None or TLSv1.2. Default: None
|
||||||
|
ciphers: "HIGH"
|
||||||
|
validate: False # Can either be True or False. Default: False
|
||||||
|
|
||||||
|
username: cn=root,dc=unit,dc=macaomilano,dc=org
|
||||||
|
password: root
|
||||||
|
|
||||||
|
base_dn: dc=unit,dc=macaomilano,dc=org
|
||||||
|
|
||||||
|
|
||||||
|
logging:
|
||||||
|
version: 1
|
||||||
|
formatters:
|
||||||
|
default:
|
||||||
|
format: '[%(name)s %(levelname)s] %(message)s'
|
||||||
|
|
||||||
|
handlers:
|
||||||
|
console:
|
||||||
|
class: logging.StreamHandler
|
||||||
|
formatter: default
|
||||||
|
stream: ext://sys.stdout
|
||||||
|
file:
|
||||||
|
class: logging.FileHandler
|
||||||
|
formatter: default
|
||||||
|
filename: phi.log
|
||||||
|
|
||||||
|
loggers:
|
||||||
|
phi:
|
||||||
|
level: DEBUG
|
||||||
|
handlers: [console, file]
|
||||||
|
aiohttp:
|
||||||
|
level: DEBUG
|
||||||
|
handlers: [console, file]
|
1
openldap/.gitignore
vendored
Normal file
1
openldap/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
*.pem
|
20
openldap/Dockerfile
Normal file
20
openldap/Dockerfile
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
FROM alpine:3.7
|
||||||
|
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
openldap \
|
||||||
|
openldap-back-mdb \
|
||||||
|
openldap-overlay-refint openldap-overlay-memberof \
|
||||||
|
openldap-clients
|
||||||
|
|
||||||
|
COPY slapd.conf /etc/openldap/slapd.conf
|
||||||
|
COPY key.pem /var/slapd/key.pem
|
||||||
|
COPY cert.pem /var/slapd/cert.pem
|
||||||
|
|
||||||
|
RUN chown -R ldap:ldap /var/slapd /etc/openldap
|
||||||
|
|
||||||
|
EXPOSE 389
|
||||||
|
ENTRYPOINT ["/usr/sbin/slapd",\
|
||||||
|
"-u","ldap","-g","ldap",\
|
||||||
|
"-f","/etc/openldap/slapd.conf",\
|
||||||
|
"-d","1",\
|
||||||
|
"-h","ldap://"]
|
38
openldap/Makefile
Normal file
38
openldap/Makefile
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
.PHONY: all
|
||||||
|
all: build run
|
||||||
|
|
||||||
|
.PHONY: build
|
||||||
|
build: gen-cert
|
||||||
|
docker build --no-cache -t unit/slapd .
|
||||||
|
|
||||||
|
.PHONY: gen-cert
|
||||||
|
gen-cert:
|
||||||
|
openssl req \
|
||||||
|
-x509 -nodes -days 365 -sha256 \
|
||||||
|
-subj '/C=IT/ST=Lombardia/L=Milano/CN=unit.macaomilano.org' \
|
||||||
|
-newkey rsa:2048 -keyout key.pem -out cert.pem
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
rm -f key.pem cert.pem
|
||||||
|
|
||||||
|
.PHONY: run
|
||||||
|
run:
|
||||||
|
docker run -p 389:389 --rm unit/slapd
|
||||||
|
|
||||||
|
.PHONY: shell
|
||||||
|
shell:
|
||||||
|
LDAPTLS_REQCERT=never zsh
|
||||||
|
|
||||||
|
.PHONY: populate
|
||||||
|
populate:
|
||||||
|
ldapmodify -ZZ -H ldap://127.0.0.1 \
|
||||||
|
-x -D "cn=root,dc=unit,dc=macaomilano,dc=org" -w root \
|
||||||
|
-a -f init.ldif
|
||||||
|
|
||||||
|
.PHONY: inspect
|
||||||
|
inspect:
|
||||||
|
ldapsearch -ZZ -h 127.0.0.1 \
|
||||||
|
-x -D "cn=root,dc=unit,dc=macaomilano,dc=org" -w root \
|
||||||
|
-b "dc=unit,dc=macaomilano,dc=org" \
|
||||||
|
'(objectclass=*)'
|
62
openldap/README.md
Normal file
62
openldap/README.md
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
# OpenLDAP container
|
||||||
|
|
||||||
|
Beware that this is intended for development purposes only and should not
|
||||||
|
be used in production.
|
||||||
|
|
||||||
|
Make sure the latest Docker version in installed and the Docker daemon
|
||||||
|
is running.
|
||||||
|
|
||||||
|
## Building the container image
|
||||||
|
|
||||||
|
Before being able to use this container you must build it. Just run `make build`
|
||||||
|
from within the `openldap` directory in the root of this project.
|
||||||
|
|
||||||
|
The created Docker image should be now present in your library.
|
||||||
|
|
||||||
|
```
|
||||||
|
% docker images 'unit/slapd'
|
||||||
|
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||||
|
unit/slapd latest c04d952b53d3 2 minutes ago 8.92MB
|
||||||
|
```
|
||||||
|
|
||||||
|
This will also create in the `openldap` directory in the root of this repository
|
||||||
|
two files containing the private key and the server certificate for the just
|
||||||
|
built docker image.
|
||||||
|
|
||||||
|
```
|
||||||
|
% ls -l *.pem
|
||||||
|
-rw-r--r-- 1 crudo users 1265 16 dic 22.25 cert.pem
|
||||||
|
-rw------- 1 crudo users 1704 16 dic 22.25 key.pem
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running the container image
|
||||||
|
|
||||||
|
Just run `make run`. This will start an OpenLDAP daemon bound to `127.0.0.1`
|
||||||
|
on port `389`.
|
||||||
|
|
||||||
|
The root user DN is `cn=root,dn=unit,dc=macaomilano,dc=org` and its password
|
||||||
|
is `root`.
|
||||||
|
|
||||||
|
Sending `SIGINT` (or pressing `Ctrl+C`) will stop the daemon and remove the
|
||||||
|
running docker instance..
|
||||||
|
|
||||||
|
## Issuing client commands
|
||||||
|
|
||||||
|
In order to operate LDAP commands you need the `ldapsearch` and `ldapmodify`
|
||||||
|
binaries.
|
||||||
|
|
||||||
|
Such commands require some environment variables to be set. The `make shell`
|
||||||
|
command will start a new shell with those variables already set. Currently
|
||||||
|
only Zsh is supported.
|
||||||
|
|
||||||
|
## Populate the server
|
||||||
|
|
||||||
|
The `init.ldif` file that can be found in the `openldap` directory in the root
|
||||||
|
of this repository contains a basic structure that can be imported to the
|
||||||
|
OpenLDAP directory server. Just run `make populate` from withing the same directory.
|
||||||
|
|
||||||
|
## Inspect the server
|
||||||
|
|
||||||
|
Running the command `make inspect` from within the `openldap` directory in
|
||||||
|
the root of this repository will show all the stored information in the
|
||||||
|
OpenLDAP directory server.
|
22
openldap/init.ldif
Normal file
22
openldap/init.ldif
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
version: 1
|
||||||
|
|
||||||
|
dn: dc=unit,dc=macaomilano,dc=org
|
||||||
|
objectClass: organization
|
||||||
|
objectClass: dcObject
|
||||||
|
dc: unit
|
||||||
|
o: Unit
|
||||||
|
|
||||||
|
dn: ou=Hackers,dc=unit,dc=macaomilano,dc=org
|
||||||
|
objectClass: organizationalUnit
|
||||||
|
objectClass: top
|
||||||
|
ou: Hackers
|
||||||
|
|
||||||
|
dn: ou=Services,dc=unit,dc=macaomilano,dc=org
|
||||||
|
objectClass: top
|
||||||
|
objectClass: organizationalUnit
|
||||||
|
ou: Services
|
||||||
|
|
||||||
|
dn: ou=Groups,dc=unit,dc=macaomilano,dc=org
|
||||||
|
objectClass: top
|
||||||
|
objectClass: organizationalUnit
|
||||||
|
ou: Groups
|
127
openldap/slapd.conf
Normal file
127
openldap/slapd.conf
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
#######################################################################
|
||||||
|
# Modules
|
||||||
|
#######################################################################
|
||||||
|
|
||||||
|
include /etc/openldap/schema/core.schema
|
||||||
|
include /etc/openldap/schema/cosine.schema
|
||||||
|
include /etc/openldap/schema/corba.schema
|
||||||
|
include /etc/openldap/schema/inetorgperson.schema
|
||||||
|
include /etc/openldap/schema/nis.schema
|
||||||
|
include /etc/openldap/schema/collective.schema
|
||||||
|
include /etc/openldap/schema/openldap.schema
|
||||||
|
|
||||||
|
modulepath /usr/lib/openldap
|
||||||
|
moduleload back_mdb
|
||||||
|
moduleload refint
|
||||||
|
moduleload memberof
|
||||||
|
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
# Core
|
||||||
|
#######################################################################
|
||||||
|
|
||||||
|
pidfile /var/slapd/slapd.pid
|
||||||
|
argsfile /var/slapd/slapd.args
|
||||||
|
loglevel conns
|
||||||
|
|
||||||
|
serverID 0
|
||||||
|
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
# Security
|
||||||
|
#######################################################################
|
||||||
|
|
||||||
|
#TLSCACertificateFile /var/slapd/fullchain.pem
|
||||||
|
TLSCertificateFile /var/slapd/cert.pem
|
||||||
|
TLSCertificateKeyFile /var/slapd/key.pem
|
||||||
|
TLSCipherSuite HIGH
|
||||||
|
|
||||||
|
# Sample security restrictions
|
||||||
|
# Define global ACLs to disable default read access.
|
||||||
|
# Require integrity protection (prevent hijacking)
|
||||||
|
# Require 112-bit (3DES or better) encryption for updates
|
||||||
|
# Require 63-bit encryption for simple bind
|
||||||
|
security ssf=1 simple_bind=256 update_ssf=256
|
||||||
|
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
# MDB database definitions
|
||||||
|
#######################################################################
|
||||||
|
|
||||||
|
database mdb
|
||||||
|
maxsize 1073741824
|
||||||
|
suffix "dc=unit,dc=macaomilano,dc=org"
|
||||||
|
|
||||||
|
# Overlays to be loaded for the database.
|
||||||
|
overlay memberof
|
||||||
|
|
||||||
|
# Cleartext passwords, especially for the rootdn, should
|
||||||
|
# be avoid. See slappasswd(8) and slapd.conf(5) for details.
|
||||||
|
# Use of strong authentication encouraged.
|
||||||
|
rootdn "cn=root,dc=unit,dc=macaomilano,dc=org"
|
||||||
|
rootpw {SHA}3Hbp8MAAbo+RngxRXGbbujmC94U=
|
||||||
|
|
||||||
|
# The database directory MUST exist prior to running slapd AND
|
||||||
|
# should only be accessible by the slapd and slap tools.
|
||||||
|
# Mode 700 recommended.
|
||||||
|
directory /var/slapd
|
||||||
|
mode 0700
|
||||||
|
|
||||||
|
password-hash {CRYPT}
|
||||||
|
password-crypt-salt-format "$6$%.16s"
|
||||||
|
|
||||||
|
# Indices to maintain
|
||||||
|
index objectClass pres,eq
|
||||||
|
index uid,cn,sn,mail eq,sub
|
||||||
|
index memberof pres,eq
|
||||||
|
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
# MemberOf configuration
|
||||||
|
#######################################################################
|
||||||
|
|
||||||
|
memberof-group-oc groupOfNames
|
||||||
|
memberof-memberof-ad memberOf
|
||||||
|
memberof-member-ad member
|
||||||
|
memberof-dangling error
|
||||||
|
memberof-refint true
|
||||||
|
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
# ACLs
|
||||||
|
#######################################################################
|
||||||
|
|
||||||
|
# Sample access control policy:
|
||||||
|
# Root DSE: allow anyone to read it
|
||||||
|
# Subschema (sub)entry DSE: allow anyone to read it
|
||||||
|
# Other DSEs:
|
||||||
|
# Allow self write access
|
||||||
|
# Allow authenticated users read access
|
||||||
|
# Allow anonymous users to authenticate
|
||||||
|
# Directives needed to implement policy:
|
||||||
|
#access to dn.base="" by * read
|
||||||
|
#access to dn.base="cn=Subschema" by * read
|
||||||
|
#access to *
|
||||||
|
# by self write
|
||||||
|
# by users read
|
||||||
|
# by anonymous auth
|
||||||
|
#
|
||||||
|
# if no access controls are present, the default policy
|
||||||
|
# allows anyone and everyone to read anything but restricts
|
||||||
|
# updates to rootdn. (e.g., "access to * by * read")
|
||||||
|
#
|
||||||
|
# rootdn can always read and write EVERYTHING!
|
||||||
|
|
||||||
|
access to dn.base=""
|
||||||
|
by * read
|
||||||
|
|
||||||
|
access to attrs=entry
|
||||||
|
by * read
|
||||||
|
|
||||||
|
access to attrs=userPassword
|
||||||
|
by self write
|
||||||
|
by anonymous auth
|
||||||
|
|
||||||
|
access to dn.subtree="ou=Hackers,dc=unit,dc=macaomilano,dc=org"
|
||||||
|
by self write
|
||||||
|
by dn.subtree="ou=Services,dc=unit,dc=macaomilano,dc=org" read
|
20
setup.py
Normal file
20
setup.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
from setuptools import setup
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name='phi',
|
||||||
|
version='0.0.1',
|
||||||
|
|
||||||
|
description='Post-Human Interface',
|
||||||
|
# license='',
|
||||||
|
url='https://git.unit.macaomilano.org/unit/panel',
|
||||||
|
|
||||||
|
author='unit',
|
||||||
|
author_email='unit@paranoici.org',
|
||||||
|
|
||||||
|
package_dir={'': 'src'},
|
||||||
|
packages=['phi', 'phi.api', 'phi.ldap'],
|
||||||
|
scripts=['src/phi.py'],
|
||||||
|
|
||||||
|
install_requires=['aiohttp', 'pyYAML', 'ldap3'],
|
||||||
|
tests_require=['pytest', 'pytest-aiohttp']
|
||||||
|
)
|
22
src/phi.py
Normal file
22
src/phi.py
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
from pprint import pformat as pp
|
||||||
|
|
||||||
|
from phi.config import get_config
|
||||||
|
from phi.logging import setup_logging, get_logger
|
||||||
|
from phi.app import setup_app, run_app
|
||||||
|
|
||||||
|
|
||||||
|
log = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
config_file, config = get_config()
|
||||||
|
|
||||||
|
# Beware that everything happened until now
|
||||||
|
# could not possibly get logged.
|
||||||
|
setup_logging(config.get('logging', {}))
|
||||||
|
|
||||||
|
log.info("Found configuration at '{}':\n{}"
|
||||||
|
.format(config_file, pp(config)))
|
||||||
|
|
||||||
|
app = setup_app(config)
|
||||||
|
run_app(app)
|
0
src/phi/__init__.py
Normal file
0
src/phi/__init__.py
Normal file
0
src/phi/api/__init__.py
Normal file
0
src/phi/api/__init__.py
Normal file
14
src/phi/api/app.py
Normal file
14
src/phi/api/app.py
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
from aiohttp import web
|
||||||
|
|
||||||
|
from phi.logging import get_logger
|
||||||
|
from phi.api.routes import api_routes
|
||||||
|
|
||||||
|
log = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def api_app(ldap_client=None):
|
||||||
|
log.info("Initializing API sub-app.")
|
||||||
|
app = web.Application()
|
||||||
|
app.router.add_routes(api_routes)
|
||||||
|
app['ldap_client'] = ldap_client
|
||||||
|
return app
|
5
src/phi/api/rest.py
Normal file
5
src/phi/api/rest.py
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
from aiohttp.web import Response
|
||||||
|
|
||||||
|
|
||||||
|
def status(request):
|
||||||
|
Response(text="Status: it's working!")
|
8
src/phi/api/routes.py
Normal file
8
src/phi/api/routes.py
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
from aiohttp.web import get
|
||||||
|
|
||||||
|
from phi.api.rest import status
|
||||||
|
|
||||||
|
|
||||||
|
api_routes = [
|
||||||
|
get('/status', status)
|
||||||
|
]
|
25
src/phi/app.py
Normal file
25
src/phi/app.py
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
from asyncio import get_event_loop
|
||||||
|
from aiohttp import web
|
||||||
|
|
||||||
|
from phi.api.app import api_app
|
||||||
|
from phi.ldap.client import Client
|
||||||
|
|
||||||
|
|
||||||
|
def setup_app(config):
|
||||||
|
loop = get_event_loop()
|
||||||
|
|
||||||
|
app = web.Application(loop=loop)
|
||||||
|
app['config'] = config
|
||||||
|
|
||||||
|
ldap_client = Client(**config.get('ldap', {}))
|
||||||
|
|
||||||
|
api = api_app(ldap_client=ldap_client)
|
||||||
|
app.add_subapp('/api', api)
|
||||||
|
|
||||||
|
return app
|
||||||
|
|
||||||
|
|
||||||
|
def run_app(app):
|
||||||
|
web.run_app(app,
|
||||||
|
host=app['config']['core']['listen'].get('host', '127.0.0.1'),
|
||||||
|
port=app['config']['core']['listen'].get('port', '8080'))
|
35
src/phi/config.py
Normal file
35
src/phi/config.py
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import os.path
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
|
||||||
|
NAME = 'phi'
|
||||||
|
|
||||||
|
CONFIG_FILE = 'config.yml'
|
||||||
|
CONFIG_PATHS = ['./',
|
||||||
|
'~/.config/' + NAME + '/',
|
||||||
|
'/usr/local/etc/' + NAME + '/',
|
||||||
|
'/etc/' + NAME + '/']
|
||||||
|
CONFIG_FILES = [os.path.join(p, CONFIG_FILE)
|
||||||
|
for p in CONFIG_PATHS]
|
||||||
|
|
||||||
|
|
||||||
|
def get_config():
|
||||||
|
"""Return the path of the found configuration file and its content
|
||||||
|
|
||||||
|
:returns: (path, config)
|
||||||
|
:rtype: (str, dict)
|
||||||
|
"""
|
||||||
|
for f in CONFIG_FILES:
|
||||||
|
try:
|
||||||
|
with open(f, 'r') as c:
|
||||||
|
config = yaml.safe_load(c)
|
||||||
|
return (f, config)
|
||||||
|
except FileNotFoundError:
|
||||||
|
# Skip to the next file.
|
||||||
|
# We only care if the file is preset but it's not
|
||||||
|
# accessible or if the file is not present at all
|
||||||
|
# in any of CONFIG_PATHS.
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise FileNotFoundError("Could not find {} in any of {}."
|
||||||
|
.format(CONFIG_FILE, ', '.join(CONFIG_PATHS)))
|
0
src/phi/ldap/__init__.py
Normal file
0
src/phi/ldap/__init__.py
Normal file
29
src/phi/ldap/client.py
Normal file
29
src/phi/ldap/client.py
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
from ldap3.utils.log import set_library_log_detail_level, PROTOCOL
|
||||||
|
|
||||||
|
from phi.logging import get_logger
|
||||||
|
from phi.ldap.connection import make_connection
|
||||||
|
|
||||||
|
log = get_logger(__name__)
|
||||||
|
set_library_log_detail_level(PROTOCOL)
|
||||||
|
|
||||||
|
|
||||||
|
class Client:
|
||||||
|
def __init__(self, host=None, port=389,
|
||||||
|
encryption=None, ciphers=None, validate=False,
|
||||||
|
username=None, password=None,
|
||||||
|
base_dn=None):
|
||||||
|
self.host = host
|
||||||
|
self.port = port
|
||||||
|
self.encryption = encryption
|
||||||
|
self.ciphers = ciphers
|
||||||
|
self.validate = validate
|
||||||
|
self.username = username
|
||||||
|
self.password = password
|
||||||
|
self.base_dn = base_dn
|
||||||
|
|
||||||
|
self.connection = make_connection(host=self.host, port=self.port,
|
||||||
|
encryption=self.encryption,
|
||||||
|
ciphers=self.ciphers,
|
||||||
|
validate=self.validate,
|
||||||
|
username=self.username,
|
||||||
|
password=self.password)
|
10
src/phi/ldap/commands.py
Normal file
10
src/phi/ldap/commands.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
def inspect(client):
|
||||||
|
id = client.connection.search(client.base_dn,
|
||||||
|
'(objectclass=*)')
|
||||||
|
response, result = client.connection.get_response(id)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
def whoami(client):
|
||||||
|
response = client.connection.extend.standard.who_am_i()
|
||||||
|
return response
|
53
src/phi/ldap/connection.py
Normal file
53
src/phi/ldap/connection.py
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
from ssl import CERT_REQUIRED, PROTOCOL_TLSv1_2
|
||||||
|
from ldap3 import Tls, Server, Connection, ASYNC
|
||||||
|
|
||||||
|
from phi.logging import get_logger
|
||||||
|
|
||||||
|
log = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def make_connection(host=None, port=389,
|
||||||
|
encryption=None, ciphers=None, validate=False,
|
||||||
|
username=None, password=None):
|
||||||
|
# TLSv1.2 is supported since Python 3.4
|
||||||
|
if encryption is None:
|
||||||
|
log.info("The connection to the LDAP server will not be encrypted.")
|
||||||
|
tls = None
|
||||||
|
elif encryption == "TLSv1.2":
|
||||||
|
log.info("The connection to the LDAP server will use TLSv1.2.")
|
||||||
|
tls = Tls(version=PROTOCOL_TLSv1_2)
|
||||||
|
else:
|
||||||
|
raise NotImplementedError("Sorry, use TLSv1.2.")
|
||||||
|
|
||||||
|
if encryption is not None and ciphers is not None:
|
||||||
|
log.info("The connection to the LDAP server will use the "
|
||||||
|
"following ciphers: {}".format(ciphers))
|
||||||
|
tls.ciphers = ciphers
|
||||||
|
|
||||||
|
if encryption is not None and validate is True:
|
||||||
|
log.info("The certificate hostname will be checked to match the "
|
||||||
|
"remote hostname.")
|
||||||
|
tls.validate = CERT_REQUIRED
|
||||||
|
|
||||||
|
server = Server(host=host, port=port, tls=tls)
|
||||||
|
connection = Connection(server, user=username, password=password,
|
||||||
|
client_strategy=ASYNC)
|
||||||
|
|
||||||
|
return connection
|
||||||
|
|
||||||
|
|
||||||
|
def open_connection(connection):
|
||||||
|
log.info("Opening connection to LDAP server.")
|
||||||
|
connection.open()
|
||||||
|
|
||||||
|
if connection.server.tls is not None and connection.server.ssl is False:
|
||||||
|
log.info("Issuing StartTLS command.")
|
||||||
|
connection.start_tls()
|
||||||
|
|
||||||
|
log.info("Issuing BIND command.")
|
||||||
|
connection.bind()
|
||||||
|
|
||||||
|
|
||||||
|
def close_connection(connection):
|
||||||
|
log.info("Issuing UNBIND command.")
|
||||||
|
connection.unbind()
|
15
src/phi/logging.py
Normal file
15
src/phi/logging.py
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
from logging import getLogger
|
||||||
|
from logging.config import dictConfig
|
||||||
|
|
||||||
|
from phi.config import NAME
|
||||||
|
|
||||||
|
|
||||||
|
root = getLogger(NAME)
|
||||||
|
|
||||||
|
|
||||||
|
def setup_logging(config):
|
||||||
|
dictConfig(config)
|
||||||
|
|
||||||
|
|
||||||
|
def get_logger(name):
|
||||||
|
return root.getChild(name)
|
2
test/test_dummy.py
Normal file
2
test/test_dummy.py
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
def test_dummy():
|
||||||
|
assert True
|
Loading…
Reference in New Issue
Block a user