# pyceo [![Build Status](https://ci.csclub.uwaterloo.ca/api/badges/public/pyceo/status.svg?ref=refs/heads/v1)](https://ci.csclub.uwaterloo.ca/public/pyceo) CEO (**C**SC **E**lectronic **O**ffice) is the tool used by CSC to manage club accounts and memberships. See [architecture.md](architecture.md) for an overview of its architecture. ## Development First, make sure that you have installed the [syscom dev environment](https://git.uwaterloo.ca/csc/syscom-dev-environment). This will setup all of the services needed for ceo to work. You should clone this repo in the phosphoric-acid container under ctdalek's home directory; you will then be able to access it from any container thanks to NFS. ### Environment setup Once you have the dev environment setup, there are a few more steps you'll need to do for ceo. #### Kerberos principals First, you'll need `ceod/` principals for each of phosphoric-acid, coffee and mail. (coffee is taking over the role of caffeine for the DB endpoints). For example, in the phosphoric-acid container: ```sh kadmin -p sysadmin/admin addprinc -randkey ceod/phosphoric-acid.csclub.internal ktadd ceod/phosphoric-acid.csclub.internal ``` Do this for coffee and mail as well. You need to actually be in the appropriate container when running these commands, since the credentials are being added to the local keytab. On phosphoric-acid, you will additionally need to create a principal called `ceod/admin` (remember to addprinc **and** ktadd). #### Database create superuser `mysql` with password `mysql` ``` mysql -u root CREATE USER 'mysql'@'localhost' IDENTIFIED BY 'mysql'; GRANT ALL PRIVILEGES ON *.* TO 'mysql'@'localhost' WITH GRANT OPTION; ``` modify superuser `postgres` for password authentication and restrict new users ``` su postgres psql ALTER USER postgres WITH PASSWORD 'postgres'; REVOKE ALL ON SCHEMA public FROM public; GRANT ALL ON SCHEMA public TO postgres; ``` create a new `pg_hba.conf` to force password authentication and reject non local ``` cd /etc/postgresql/// mv pg_hba.conf pg_hba.conf.old ``` ``` # new pg_hba.conf # TYPE DATABASE USER ADDRESS METHOD local all postgres md5 local sameuser all md5 host sameuser all 0.0.0.0/0 md5 ``` ``` systemctl restart postgresql ``` #### Mailman You should create the following mailing lists from the mail container: ```sh /opt/mailman3/bin/mailman create syscom@csclub.internal /opt/mailman3/bin/mailman create syscom-alerts@csclub.internal /opt/mailman3/bin/mailman create exec@csclub.internal /opt/mailman3/bin/mailman create ceo@csclub.internal ``` See https://git.uwaterloo.ca/csc/syscom-dev-environment/-/tree/master/mail for instructions on how to access the Mailman UI from your browser. If you want to actually see the archived messages, you'll need to tweak the settings for each list from the UI so that non-member messages get accepted (by default they get held). #### Dependencies Next, install and activate a virtualenv: ```sh sudo apt install libkrb5-dev libsasl2-dev python3-dev python3 -m venv venv . venv/bin/activate pip install -r requirements.txt pip install -r dev-requirements.txt ``` #### C bindings Due to the lack of a decent Python library for Kerberos we ended up writing our own C bindings using [cffi](https://cffi.readthedocs.io). Make sure you compile the bindings: ```sh cd ceo_common/krb5 python krb5_build.py ``` This should create a file named '_krb5.cpython-37m-x86_64-linux-gnu.so'. This will be imported by other modules in ceo. ## Running the application ceod is a distributed application, with instances on different hosts offering different services. Therefore, you will need to run ceod on multiple hosts. Currently, those are phosphoric-acid, mail and caffeine (in the dev environment, caffeine is replaced by coffee). To run ceod on a single host (as root, since the app needs to read the keytab): ```sh export FLASK_APP=ceod.api export FLASK_ENV=development flask run -h 0.0.0.0 -p 9987 ``` Sometimes changes you make in the source code don't show up while Flask is running. Stop the flask app (Ctrl-C), run `clear_cache.sh`, then restart the app. ## Interacting with the application The client part of ceo hasn't been written yet, so we'll use curl to interact with ceod for now. ceod uses [SPNEGO](https://en.wikipedia.org/wiki/SPNEGO) for authentication, and TLS for confidentiality and integrity. In development mode, TLS can be disabled. First, make sure that your version of curl has been compiled with SPNEGO support: ```sh curl -V ``` Your should see 'SPNEGO' in the 'Features' section. The API also uses unconstrained Kerberos delegation when interacting with the LDAP database. This means that the client obtains a forwarded TGT, then sends that to ceod, which then uses it to interact with LDAP on the client's behalf. There is a script called `gen_cred.py` which can generate this ticket for you. Here's an example of making a request to an endpoint which writes to LDAP: ```sh # Get a Kerberos TGT first kinit # Obtain a forwarded TGT ./gen_cred.py phosphoric-acid # Make the request curl --negotiate -u : --service-name ceod \ -H "X-KRB5-CRED: $(cat cred)" \ -d '{"uid":"test_1","cn":"Test One","program":"Math","terms":["s2021"]}' \ -X POST http://phosphoric-acid:9987/api/members ```