diff --git a/README.md b/README.md index 27b4c8437ec8eeb60a29a75adb1997a8a89360f3..fe0f14215cbffcd6d290879382206a96da1cc5de 100644 --- a/README.md +++ b/README.md @@ -41,13 +41,12 @@ export FLASK_APP=uffd flask group create 'uffd_access' --description 'Access to Single-Sign-On and Selfservice' flask group create 'uffd_admin' --description 'Admin access to uffd' flask role create 'base' --default --add-group 'uffd_access' -flask role create 'admin' --default --add-group 'uffd_admin' +flask role create 'admin' --add-group 'uffd_admin' flask user create 'testuser' --password 'userpassword' --mail 'test@example.com' --displayname 'Test User' flask user create 'testadmin' --password 'adminpassword' --mail 'admin@example.com' --displayname 'Test Admin' --add-role 'admin' ``` -Afterwards you can login as a normal user with "testuser" and "userpassword", or as an admin with "testad -min" and "adminpassword". +Afterwards you can login as a normal user with "testuser" and "userpassword", or as an admin with "testadmin" and "adminpassword". ## Deployment @@ -72,43 +71,6 @@ The Debian package uses uwsgi to run uffd and ships an `uffd-admin` to execute f If you upgrade, make sure to run `flask db upgrade` after every update! The Debian package takes care of this by itself using uwsgi pre start hooks. For an example uwsgi config, see our [uswgi.ini](uwsgi.ini). You might find our [nginx include file](nginx.include.conf) helpful to setup a web server in front of uwsgi. -## Migration from version 1 - -If a custom config file name was set with `CONFIG_FILENAME`, this must be replaced with `CONFIG_PATH`. -The new variable must be set to a full path instead of a filename relative to the application's instance directory. - -Prior to version 2 uffd stored users, groups and mail aliases in an LDAP server. -To migrate from version 1 to a later version, make sure to keep the v1 config file as it is with all LDAP settings. -Running the database migrations with `flask db upgrade` automatically imports all users, groups and mail forwardings from LDAP to the database. -Note that all LDAP attributes must be readable, including the password field. -Make sure to have a working backup of the database before running the database upgrade! -Downgrading is not supported. - -After running the migrations you can remove all `LDAP_*`-prefixed settings from the config file except the following ones that are renamed: - -* `LDAP_USER_GID` -> `USER_GID` -* `LDAP_USER_MIN_UID` -> `USER_MIN_UID` -* `LDAP_USER_MAX_UID` -> `USER_MAX_UID` -* `LDAP_USER_SERVICE_MIN_UID` -> `USER_SERVICE_MIN_UID` -* `LDAP_USER_SERVICE_MAX_UID` -> `USER_SERVICE_MAX_UID` -* `LDAP_GROUP_MIN_GID` -> `GROUP_MIN_GID` -* `LDAP_GROUP_MAX_GID` -> `GROUP_MAX_GID` - -Upgrading will not perform any write access to the LDAP server. - -If the config option `ACL_SELFSERVICE_GROUP` is set but not `ACL_ACCESS_GROUP`, make sure to set `ACL_ACCESS_GROUP` to the same value as `ACL_SELFSERVICE_GROUP`, - -OAuth2 and API client definitions moved from the config (`OAUTH2_CLIENTS` and `API_CLIENTS_2`) to the database. -The database migration automatically imports clients from the config. -After upgrading the config options should be removed. - -Note that the `login_message` option is no longer supported for OAuth2 clients. -The `required_group` is only correctly imported if it is set to a single group name (or absent). - -Also note that uffd can group OAuth2 and API clients of a service together. -Set the `service_name` key in `OAUTH2_CLIENTS` and `API_CLIENTS_2` items to the same value to group them together. -Without this key the import creates individual service objects for each client. - ## Python Coding Style Conventions PEP 8 without double new lines, tabs instead of spaces and a max line length of 160 characters. diff --git a/UPGRADE.md b/UPGRADE.md new file mode 100644 index 0000000000000000000000000000000000000000..f4c5c93365a60e1fc6f805cd832211f1aa399c4a --- /dev/null +++ b/UPGRADE.md @@ -0,0 +1,152 @@ +# Upgrading from v1 to v2 + +Prior to v2 uffd stored users, groups and mail aliases on an LDAP server. +OAuth2 and API client credentials were defined in the config. Starting with +v2 uffd stores all of this in its database and no longer supports LDAP. +A number of other features and configurations are no longer supported. See the +changelog for details on changed and removed features. + +## Preparations + +Create a backup of the database before attempting an upgrade. The database +migration scripts are quite complex and somewhat fragile. If anything fails, +you will end up with a broken database that is difficult or impossible to +recover from. Furthermore downgrading from v2 to v1 is not supported. + +Make sure no service (besides uffd) directly accesses your LDAP server. +Migrate any remaining services to [uffd-ldapd][] or other solutions that +solely rely on uffds API and OAuth2 endpoints. Uffd will cease to update +any data stored in the LDAP directory. + +Migrate all API clients defined with the `API_CLIENTS` config option to the +`API_CLIENTS_2` option. This includes changing authentication from a +token-based mechanism to HTTP Basic Authentication and consequently replacing +affected credentials. + +The imported OAuth2 and API clients are grouped by service objects. These +service objects will be auto-created for each client with unique names derived +from the `client_id` parameter. Add the `service_name` parameter to clients to +set a custom name. This name is visible to users in place of the OAuth2 +`client_id`. Use the same `service_name` for multiple clients to group them +together. This is recommended for OAuth2 and API credentials used by the same +services, as future features like service-specific email addresses will be +added as service-level options. The OAuth2 client parameter `required_group` is +imported as a service-level option. Make sure that grouped OAuth2 clients have +the same `required_group` value, otherwise nobody will be able to access the +service. Note that values other than a single group name are not supported. + +Adjust the ACLs of your LDAP server so uffd can read the `userPassword` +attribute of user objects. Note that uffd will not perform any writes to the +LDAP server during or after the upgrade. + +If you use user bind (config option `LDAP_SERVICE_USER_BIND`), i.e. if you +have uffd authenticate with the LDAP server using the credentials of the +currently logged in user, you will have to replace this configuration and +grant uffd full read access to all user, group and mail alias data with +config-defined credentials. + +Install the new dependency `python3-argon2`. (Dist-)Upgrading the Debian +package will do that for you. Do not uninstall the removed dependency +`python3-ldap3` (i.e. do not run `apt autoremove`)! It is required to import +data from the LDAP server. + +There is a safeguard in place to prevent accidental upgrades. Add the +following line to your config file to disable the safeguard: + +``` +UPGRADE_V1_TO_V2=True +``` + +## Running the Upgrade + +Upgrade the Debian package to v2. This will restart the uffd UWSGI app. With +the default UWSGI configuration, the database migration scripts will run +automatically. + +Otherwise run them manually: + +``` +uffd-admin db upgrade +``` + +The database migration scripts import users, groups and mail aliases from the +configured LDAP server. They also import OAuth2 and API clients defined with +the `OAUTH2_CLIENTS` and `API_CLIENTS_2` config options to the database. + +Due to data being split between the LDAP server and the database, uffd v1 +tended to accumulate orphaned database objects (e.g. role memberships of +deleted users). All orphaned objects are deleted during the upgrade. + +As a side-effect upgrading resets all rate limits. + +## Follow-up + +Rename the following config options: + +* `LDAP_USER_GID` -> `USER_GID` +* `LDAP_USER_MIN_UID` -> `USER_MIN_UID` +* `LDAP_USER_MAX_UID` -> `USER_MAX_UID` +* `LDAP_USER_SERVICE_MIN_UID` -> `USER_SERVICE_MIN_UID` +* `LDAP_USER_SERVICE_MAX_UID` -> `USER_SERVICE_MAX_UID` + +Add the following config options: + +* `GROUP_MIN_GID` +* `GROUP_MAX_GID` + +Remove the following config options: + +* `UPGRADE_V1_TO_V2` +* `LDAP_USER_SEARCH_BASE` +* `LDAP_USER_SEARCH_FILTER` +* `LDAP_USER_OBJECTCLASSES` +* `LDAP_USER_DN_ATTRIBUTE` +* `LDAP_USER_UID_ATTRIBUTE` +* `LDAP_USER_UID_ALIASES` +* `LDAP_USER_LOGINNAME_ATTRIBUTE` +* `LDAP_USER_LOGINNAME_ALIASES` +* `LDAP_USER_DISPLAYNAME_ATTRIBUTE` +* `LDAP_USER_DISPLAYNAME_ALIASES` +* `LDAP_USER_MAIL_ATTRIBUTE` +* `LDAP_USER_MAIL_ALIASES` +* `LDAP_USER_DEFAULT_ATTRIBUTES` +* `LDAP_GROUP_SEARCH_BASE` +* `LDAP_GROUP_SEARCH_FILTER` +* `LDAP_GROUP_GID_ATTRIBUTE` +* `LDAP_GROUP_NAME_ATTRIBUTE` +* `LDAP_GROUP_DESCRIPTION_ATTRIBUTE` +* `LDAP_GROUP_MEMBER_ATTRIBUTE` +* `LDAP_MAIL_SEARCH_BASE` +* `LDAP_MAIL_SEARCH_FILTER` +* `LDAP_MAIL_OBJECTCLASSES` +* `LDAP_MAIL_DN_ATTRIBUTE` +* `LDAP_MAIL_UID_ATTRIBUTE` +* `LDAP_MAIL_RECEIVERS_ATTRIBUTE` +* `LDAP_MAIL_DESTINATIONS_ATTRIBUTE` +* `LDAP_SERVICE_URL` +* `LDAP_SERVICE_USE_STARTTLS` +* `LDAP_SERVICE_BIND_DN` +* `LDAP_SERVICE_BIND_PASSWORD` +* `LDAP_SERVICE_USER_BIND` +* `ENABLE_INVITE` +* `ENABLE_PASSWORDRESET` +* `ENABLE_ROLESELFSERVICE` +* `OAUTH2_CLIENTS` +* `API_CLIENTS` (should not be set, see "Preperation") +* `API_CLIENTS_2` +* `LDAP_SERVICE_MOCK` (development option, should not be set) + +If you set a custom config filename with the environment variable +`CONFIG_FILENAME`, replace it with `CONFIG_PATH`. The new variable must be +set to a full path instead of a filename. + +If you set the config option `ACL_SELFSERVICE_GROUP`, but not +`ACL_ACCESS_GROUP`, make sure to set `ACL_ACCESS_GROUP` to the same value as +`ACL_SELFSERVICE_GROUP`. + +Add a cron job that runs `uffd-admin cleanup` at least daily. Unless you +modified `/etc/cron.d/uffd`, upgrading the Debian package will do this for you. + +Uninstall the previous dependency `python3-ldap3` (i.e. run `apt autoremove`). + +[uffd-ldapd]: https://git.cccv.de/uffd/uffd-ldapd diff --git a/debian/install b/debian/install index 0bf845aad31438e8fda6b2af62928d4363a03cfc..5767f478b53de686552358e473f7c1b434e89fde 100644 --- a/debian/install +++ b/debian/install @@ -2,3 +2,5 @@ uwsgi.ini /etc/uffd/ nginx.include.conf /etc/uffd/ debian/contrib/uffd.cfg /etc/uffd/ debian/contrib/uffd-admin /usr/bin/ +README.md /usr/share/doc/uffd/ +UPGRADE.md /usr/share/doc/uffd/ diff --git a/uffd/migrations/versions/878b25c4fae7_ldap_to_db.py b/uffd/migrations/versions/878b25c4fae7_ldap_to_db.py index b03c059c989eca51ad7e5f370d6cfa624d5f50cf..2249f75919e1bf6a605b7684707e46bf2fb6997d 100644 --- a/uffd/migrations/versions/878b25c4fae7_ldap_to_db.py +++ b/uffd/migrations/versions/878b25c4fae7_ldap_to_db.py @@ -23,6 +23,8 @@ def encode_filter(filter_params): return '(&%s)'%(''.join(['(%s=%s)'%(attr, escape_filter_chars(value)) for attr, value in filter_params])) def get_ldap_conn(): + if 'LDAP_SERVICE_URL' in current_app.config and not current_app.config.get('UPGRADE_V1_TO_V2'): + raise Exception('Refusing to run v1 to v2 migrations: UPGRADE_V1_TO_V2 not set. Make sure to read upgrade instructions first!') critical = True if 'LDAP_SERVICE_URL' not in current_app.config: critical = False