diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..fac1c60 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changelog + +## 1.0.0 + +* Initial Release \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..81c7767 --- /dev/null +++ b/README.md @@ -0,0 +1,52 @@ +# Ansible Collection - enbewe.uffd +Collecion to deploy uffd as oauth authentication service. + +## Playbooks +### enbewe.uffd.deployment +Deploys the role `enbewe.uffd.uffd` to all hosts of the `uffd` group. + +## Roles +### enbewe.uffd.uffd +Deploys [uffd (**U**ser**F**erwaltungs**F**ronten**d**)](https://git.cccv.de/uffd/uffd) through a podman container. +Additionally deploys an nginx container as a HTTP server for static files as well as uWSGI proxy. + +#### Required variables + +**uffd_secret_key** +The secret key to use for uffd data. + +**uffd_initial_admin_user** +Name of the initial admin user. + +**uffd_initial_admin_pw** +Password of the initial admin user. + +**uffd_initial_admin_mail** +E-Mail address of the initial admin user. + +#### Optional Variables + +**uffd_build_tempdir** *(Default: '/tmp/podman-uffd-build')* +Path to use for building the uffd OCI container in. This path will be created as needed and removed again afterwards. + +**uffd_build_debian_version** *(Default: 'bullseye')* +The debian version name to use for the uffd container. + +**uffd_build_force_rebuild** *(Default: false)* +Flag to force the reduilding of the uffd container even if it already exists. + +**uffd_podman_network** *(Default: 'uffd-net')* +Name of the podman network to use for uffd container and the nginx server. + +**uffd_data_dir** *(Default: '/srv/www/uffd')* +The directory to use for config files. + +**uffd_static_files_volume** *(Default: 'uffd-static-files')* +The name of the podman volume to use for the static files of the uffd. + +**uffd_data_volume** *(Default: 'uffd-data')* +The name of the podman volume to use for the runtime data of uffd. + +**uffd_nginx_listen_port** *(Default: '127.0.0.1:8081')* +The port to expose the uffd service on. +Can either be a local port only (as the default) or a global port if desired. diff --git a/galaxy.yml b/galaxy.yml new file mode 100644 index 0000000..62072a9 --- /dev/null +++ b/galaxy.yml @@ -0,0 +1,67 @@ +--- +### REQUIRED +# The namespace of the collection. This can be a company/brand/organization or product namespace under which all +# content lives. May only contain alphanumeric lowercase characters and underscores. Namespaces cannot start with +# underscores or numbers and cannot contain consecutive underscores +namespace: 'enbewe' + +# The name of the collection. Has the same character restrictions as 'namespace' +name: 'uffd' + +# The version of the collection. Must be compatible with semantic versioning +version: '1.0.0' + +# The path to the Markdown (.md) readme file. This path is relative to the root of the collection +readme: 'README.md' + +# A list of the collection's content authors. Can be just the name or in the format 'Full Name (url) +# @nicks:irc/im.site#channel' +authors: + - 'Nis Wechselberg ' + + +### OPTIONAL but strongly recommended +# A short summary description of the collection +description: 'Deployment tools for uffd oauth software' + +# Either a single license or a list of licenses for content inside of a collection. Ansible Galaxy currently only +# accepts L(SPDX,https://spdx.org/licenses/) licenses. This key is mutually exclusive with 'license_file' +license: + - 'MIT' + +# A list of tags you want to associate with the collection for indexing/searching. A tag name has the same character +# requirements as 'namespace' and 'name' +tags: + - 'linux' + +# Collections that this collection requires to be installed for it to be usable. The key of the dict is the +# collection label 'namespace.name'. The value is a version range +# L(specifiers,https://python-semanticversion.readthedocs.io/en/latest/#requirement-specification). Multiple version +# range specifiers can be set and are separated by ',' +dependencies: + containers.podman: '1.13.0' + +# The URL of the originating SCM repository +repository: 'https://git.enbewe.de/Coding/ansible-collection-uffd' + +# The URL to any online docs +# documentation: http://docs.example.com + +# The URL to the homepage of the collection/project +# homepage: http://example.com + +# The URL to the collection issue tracker +# issues: http://example.com/issue/tracker + +# A list of file glob-like patterns used to filter any files or directories that should not be included in the build +# artifact. A pattern is matched from the relative path of the file or directory of the collection directory. This +# uses 'fnmatch' to match the files or directories. Some directories and files like 'galaxy.yml', '*.pyc', '*.retry', +# and '.git' are always filtered. Mutually exclusive with 'manifest' +# build_ignore: [] + +# A dict controlling use of manifest directives used in building the collection artifact. The key 'directives' is a +# list of MANIFEST.in style +# L(directives,https://packaging.python.org/en/latest/guides/using-manifest-in/#manifest-in-commands). The key +# 'omit_default_directives' is a boolean that controls whether the default directives are used. Mutually exclusive +# with 'build_ignore' +# manifest: null diff --git a/meta/runtime.yml b/meta/runtime.yml new file mode 100644 index 0000000..d6c6f44 --- /dev/null +++ b/meta/runtime.yml @@ -0,0 +1,52 @@ +--- +# Collections must specify a minimum required ansible version to upload +# to galaxy +requires_ansible: '>=2.17.0' + +# Content that Ansible needs to load from another location or that has +# been deprecated/removed +# plugin_routing: +# action: +# redirected_plugin_name: +# redirect: ns.col.new_location +# deprecated_plugin_name: +# deprecation: +# removal_version: "4.0.0" +# warning_text: | +# See the porting guide on how to update your playbook to +# use ns.col.another_plugin instead. +# removed_plugin_name: +# tombstone: +# removal_version: "2.0.0" +# warning_text: | +# See the porting guide on how to update your playbook to +# use ns.col.another_plugin instead. +# become: +# cache: +# callback: +# cliconf: +# connection: +# doc_fragments: +# filter: +# httpapi: +# inventory: +# lookup: +# module_utils: +# modules: +# netconf: +# shell: +# strategy: +# terminal: +# test: +# vars: + +# Python import statements that Ansible needs to load from another location +# import_redirection: +# ansible_collections.ns.col.plugins.module_utils.old_location: +# redirect: ansible_collections.ns.col.plugins.module_utils.new_location + +# Groups of actions/modules that take a common set of options +# action_groups: +# group_name: +# - module1 +# - module2 diff --git a/playbooks/deployment.yml b/playbooks/deployment.yml new file mode 100644 index 0000000..456b0cb --- /dev/null +++ b/playbooks/deployment.yml @@ -0,0 +1,5 @@ +--- +- name: 'Deploy collection roles to matching host groups' + hosts: 'uffd' + roles: + - 'enbewe.uffd.uffd' diff --git a/plugins/README.md b/plugins/README.md new file mode 100644 index 0000000..269a4c2 --- /dev/null +++ b/plugins/README.md @@ -0,0 +1,31 @@ +# Collections Plugins Directory + +This directory can be used to ship various plugins inside an Ansible collection. Each plugin is placed in a folder that +is named after the type of plugin it is in. It can also include the `module_utils` and `modules` directory that +would contain module utils and modules respectively. + +Here is an example directory of the majority of plugins currently supported by Ansible: + +``` +└── plugins + ├── action + ├── become + ├── cache + ├── callback + ├── cliconf + ├── connection + ├── filter + ├── httpapi + ├── inventory + ├── lookup + ├── module_utils + ├── modules + ├── netconf + ├── shell + ├── strategy + ├── terminal + ├── test + └── vars +``` + +A full list of plugin types can be found at [Working With Plugins](https://docs.ansible.com/ansible-core/2.17/plugins/plugins.html). diff --git a/roles/uffd/defaults/main.yml b/roles/uffd/defaults/main.yml new file mode 100644 index 0000000..8ff29b7 --- /dev/null +++ b/roles/uffd/defaults/main.yml @@ -0,0 +1,12 @@ +--- +uffd_build_tempdir: '/tmp/podman-uffd-build' +uffd_build_debian_version: 'bullseye' +uffd_build_force_rebuild: false + +uffd_podman_network: 'uffd-net' + +uffd_data_dir: '/srv/www/uffd' +uffd_static_files_volume: 'uffd-static-files' +uffd_data_volume: 'uffd-data' + +uffd_nginx_listen_port: '127.0.0.1:8081' diff --git a/roles/uffd/handlers/main.yml b/roles/uffd/handlers/main.yml new file mode 100644 index 0000000..b32b9f7 --- /dev/null +++ b/roles/uffd/handlers/main.yml @@ -0,0 +1,15 @@ +--- +- name: 'Restart uffd container' + become: true + ansible.builtin.service: + name: 'container-uffd' + state: 'restarted' + daemon_reload: true + notify: 'Restart uffd nginx container' + +- name: 'Restart uffd nginx container' + become: true + ansible.builtin.service: + name: 'container-uffd-nginx' + state: 'restarted' + daemon_reload: true diff --git a/roles/uffd/tasks/main.yml b/roles/uffd/tasks/main.yml new file mode 100644 index 0000000..e6f618d --- /dev/null +++ b/roles/uffd/tasks/main.yml @@ -0,0 +1,123 @@ +--- +- name: 'Install required software' + become: true + ansible.builtin.apt: + name: 'podman' + state: 'present' + update_cache: true + cache_valid_time: 3600 + +# Build image to run uffd in +- name: 'Create temporary build directory' + become: true + ansible.builtin.file: + path: '{{ uffd_build_tempdir }}' + state: 'directory' + mode: 'u=rwx,g=rx,o=rx' + +- name: 'Copy required files for image' + become: true + ansible.builtin.template: + src: 'container/{{ item.file }}' + dest: '{{ uffd_build_tempdir }}/{{ item.file }}' + owner: 'root' + group: 'root' + mode: '{{ item.mode }}' + loop: + - file: 'cccv-archive.list' + mode: 'u=rw,g=r,o=r' + - file: 'cccv-archive-key.asc' + mode: 'u=rw,g=r,o=r' + - file: 'Containerfile' + mode: 'u=rw,g=r,o=r' + - file: 'entrypoint.sh' + mode: 'u=rwx,g=rx,o=rx' + +- name: 'Create uffd container' + become: true + containers.podman.podman_image: + build: + cache: false + force_rm: true + rm: true + pull: false + push: false + force: '{{ uffd_build_force_rebuild }}' + name: 'uffd' + path: '{{ uffd_build_tempdir }}' + +- name: 'Cleanup temporary build directory' + become: true + ansible.builtin.file: + state: 'absent' + path: '{{ uffd_build_tempdir }}' + +# Create things needed by the uffd container +- name: 'Prepare uffd network' + become: true + containers.podman.podman_network: + name: '{{ uffd_podman_network }}' + state: 'present' + +- name: 'Prepare uffd volumes' + become: true + containers.podman.podman_volume: + name: '{{ item }}' + state: 'present' + loop: + - '{{ uffd_static_files_volume }}' + - '{{ uffd_data_volume }}' + +- name: 'Create uffd data directory' + become: true + ansible.builtin.file: + path: '{{ uffd_data_dir }}' + state: 'directory' + mode: 'u=rwx,g=rx,o=rx' + +- name: 'Copy required files for uffd' + become: true + ansible.builtin.template: + src: '{{ item.src }}' + dest: '{{ item.dest }}' + owner: 'root' + group: 'root' + mode: 'u=rw,g=r,o=r' + notify: 'Restart uffd container' + loop: + - src: 'uffd/uffd.cfg' + dest: '{{ uffd_data_dir }}/uffd.cfg' + - src: 'systemd/container-uffd.service.j2' + dest: '/etc/systemd/system/container-uffd.service' + +- name: 'Start and enable uffd service' + become: true + ansible.builtin.systemd: + name: 'container-uffd.service' + state: 'started' + daemon_reload: true + enabled: true + +### Create nginx frontend +- name: 'Copy required files for nginx' + become: true + ansible.builtin.template: + src: '{{ item.src }}' + dest: '{{ item.dest }}' + owner: 'root' + group: 'root' + mode: 'u=rw,g=r,o=r' + notify: 'Restart uffd nginx container' + loop: + - src: 'nginx/nginx.conf' + dest: '{{ uffd_data_dir }}/nginx.conf' + - src: 'systemd/container-uffd-nginx.service.j2' + dest: '/etc/systemd/system/container-uffd-nginx.service' + +- name: 'Start and enable uffd-nginx service' + become: true + ansible.builtin.systemd: + name: 'container-uffd-nginx.service' + state: 'started' + daemon_reload: true + enabled: true diff --git a/roles/uffd/templates/container/Containerfile b/roles/uffd/templates/container/Containerfile new file mode 100644 index 0000000..1c6af85 --- /dev/null +++ b/roles/uffd/templates/container/Containerfile @@ -0,0 +1,40 @@ +# We start with Debian bullseye, even though bookworm is out. +# uffd throws some errors with bookworm python, so some programs fail +FROM docker.io/library/debian:{{ uffd_build_debian_version }}-slim +# Disable interactivity for debconf +ENV DEBIAN_FRONTEND=noninteractive +# Configure uwsgi parameters for running uffd as an app in there +ENV UWSGI_DEB_CONFNAMESPACE="app" +ENV UWSGI_DEB_CONFNAME="uffd" +# Prepare the package sources and install needed software +RUN apt-get -qq update && \ + apt-get -qq dist-upgrade && \ + apt-get -qq install ca-certificates +# Place the pacakge sources data in the image to download uffd +COPY cccv-archive-key.asc /etc/apt/trusted.gpg.d/ +COPY cccv-archive.list /etc/apt/sources.list.d/ + +# Install uffd from (new) package sources +RUN apt-get -qq update && \ + apt-get -qq install --no-install-recommends uffd && \ +# Create a "new" config from the inital config without the preset secret key + cat /etc/uffd/uffd.cfg | grep -v "SECRET_KEY=" > /etc/uffd/uffd.cfg.tmp && \ + mv /etc/uffd/uffd.cfg.tmp /etc/uffd/uffd.cfg && \ +# Create the needed paths for the app + mkdir --parents /var/www/uffd && \ + mkdir -p /run/uwsgi/app/uffd && \ + chown root:uffd /var/www/uffd + +COPY entrypoint.sh /entrypoint.sh + +USER uffd +USER root + +# Uffd application is exposed on port 3031 +EXPOSE 3031/tcp +# Statistics are exposed on port 9191 +EXPOSE 9191/tcp + +CMD bash /entrypoint.sh + +LABEL project="https://git.cccv.de/uffd/uffd" diff --git a/roles/uffd/templates/container/cccv-archive-key.asc b/roles/uffd/templates/container/cccv-archive-key.asc new file mode 100644 index 0000000..1dc3423 --- /dev/null +++ b/roles/uffd/templates/container/cccv-archive-key.asc @@ -0,0 +1,41 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +JRWMzY9EoBOHB1PubZuzUNIUQeui1vyX +=uRc5 +-----END PGP PUBLIC KEY BLOCK----- \ No newline at end of file diff --git a/roles/uffd/templates/container/cccv-archive.list b/roles/uffd/templates/container/cccv-archive.list new file mode 100644 index 0000000..8ad6e71 --- /dev/null +++ b/roles/uffd/templates/container/cccv-archive.list @@ -0,0 +1 @@ +deb [signed-by=/etc/apt/trusted.gpg.d/cccv-archive-key.asc] https://packages.cccv.de/uffd {{ uffd_build_debian_version }} main diff --git a/roles/uffd/templates/container/entrypoint.sh b/roles/uffd/templates/container/entrypoint.sh new file mode 100644 index 0000000..6266dfa --- /dev/null +++ b/roles/uffd/templates/container/entrypoint.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +echo "Copying static files ..." +cp -r /usr/share/uffd/uffd/static /var/www/uffd + +db_ready="false" +count=0 +while [ $count -lt 4 ] && [ "$db_ready" != "true" ] ;do + if uffd-admin db current >> /dev/null 2>&1 ;then + db_ready="true" + else + echo "Waiting for db to become ready..." + ((duration=2**$count)) + sleep $duration + ((count=$count+1)) + fi +done + +if [ "$db_ready" == "true" ] ;then + echo "Running datbase migrations ..." + uffd-admin db upgrade + + if [ -n "$UFFD_INITIAL_ADMIN_PW" ] && [ "$(uffd-admin user list)" == "" ]; then + echo "Creating groups and roles for initial admin user ..." + if ! uffd-admin group show 'uffd_admin' >> /dev/null 2>&1 ;then + uffd-admin group create 'uffd_admin' + fi + if ! uffd-admin group show 'uffd_access' >> /dev/null 2>&1 ;then + uffd-admin group create 'uffd_access' + fi + if ! uffd-admin role show 'uffd_admin' >> /dev/null 2>&1 ;then + uffd-admin role create 'uffd_admin' --add-group 'uffd_admin' --add-group 'uffd_access' + fi + if [ -z "$UFFD_INITIAL_ADMIN_USER" ] ;then + UFFD_INITIAL_ADMIN_USER='uffd_admin' + fi + if [ -z "$UFFD_INITIAL_ADMIN_MAIL" ] ;then + UFFD_INITIAL_ADMIN_MAIL='uffd_admin@localhost' + fi + echo "Creating initial admin user ..." + uffd-admin user create "$UFFD_INITIAL_ADMIN_USER" --password "$UFFD_INITIAL_ADMIN_PW" --mail "$UFFD_INITIAL_ADMIN_MAIL" --add-role 'uffd_admin' + fi +else + echo "WARNING: Database is not ready yet, skipping migration and initialization" +fi + +echo "Starting server ..." +runuser --preserve-environment -u uffd -- \ + uwsgi --ini /etc/uwsgi/apps-enabled/uffd.ini --socket 0.0.0.0:3031 --master --stats 0.0.0.0:9191 diff --git a/roles/uffd/templates/nginx/nginx.conf b/roles/uffd/templates/nginx/nginx.conf new file mode 100644 index 0000000..995cfbb --- /dev/null +++ b/roles/uffd/templates/nginx/nginx.conf @@ -0,0 +1,13 @@ +server { + listen 80; + server_name _; + + location / { + uwsgi_pass uffd:3031; + include uwsgi_params; + } + + location /static { + alias /var/www/uffd/static; + } +} \ No newline at end of file diff --git a/roles/uffd/templates/systemd/container-uffd-nginx.service.j2 b/roles/uffd/templates/systemd/container-uffd-nginx.service.j2 new file mode 100644 index 0000000..dbb68d2 --- /dev/null +++ b/roles/uffd/templates/systemd/container-uffd-nginx.service.j2 @@ -0,0 +1,42 @@ +[Unit] +Description=Podman container-uffd-nginx.service +Documentation=man:podman-generate-systemd(1) +Wants=network-online.target +After=network-online.target +RequiresMountsFor=%t/containers + +[Service] +Environment=PODMAN_SYSTEMD_UNIT=%n +Restart=on-failure +TimeoutStopSec=70 +Type=notify +NotifyAccess=all + +ExecStartPre=/bin/rm -f %t/%n.ctr-id + +ExecStart=/usr/bin/podman run \ + --cidfile=%t/%n.ctr-id \ + --cgroups=no-conmon \ + --rm \ + --sdnotify=conmon \ + --replace \ + --network={{ uffd_podman_network }} \ + --detach \ + --tty \ + --publish {{ uffd_nginx_listen_port }}:80 \ + --volume {{ uffd_static_files_volume }}:/var/www/uffd:Z \ + --volume {{ uffd_data_dir }}/nginx.conf:/etc/nginx/conf.d/default.conf:ro \ + --name=uffd-nginx \ + docker.io/nginx:latest + +ExecStop=/usr/bin/podman stop \ + --ignore \ + --cidfile=%t/%n.ctr-id + +ExecStopPost=/usr/bin/podman rm \ + --force \ + --ignore \ + --cidfile=%t/%n.ctr-id + +[Install] +WantedBy=default.target diff --git a/roles/uffd/templates/systemd/container-uffd.service.j2 b/roles/uffd/templates/systemd/container-uffd.service.j2 new file mode 100644 index 0000000..68e103b --- /dev/null +++ b/roles/uffd/templates/systemd/container-uffd.service.j2 @@ -0,0 +1,45 @@ +[Unit] +Description=Podman container-uffd.service +Documentation=man:podman-generate-systemd(1) +Wants=network-online.target +After=network-online.target +RequiresMountsFor=%t/containers + +[Service] +Environment=PODMAN_SYSTEMD_UNIT=%n +Restart=on-failure +TimeoutStopSec=70 +Type=notify +NotifyAccess=all + +ExecStartPre=/bin/rm -f %t/%n.ctr-id + +ExecStart=/usr/bin/podman run \ + --cidfile=%t/%n.ctr-id \ + --cgroups=no-conmon \ + --rm \ + --sdnotify=conmon \ + --replace \ + --network={{ uffd_podman_network }} \ + --detach \ + --tty \ + --volume {{ uffd_static_files_volume }}:/var/www/uffd:Z \ + --volume {{ uffd_data_volume }}:/var/lib/uffd:Z \ + --volume {{ uffd_data_dir }}/uffd.cfg:/etc/uffd/uffd.cfg:ro \ + --env UFFD_INITIAL_ADMIN_USER='{{ uffd_initial_admin_user }}' \ + --env UFFD_INITIAL_ADMIN_PW='{{ uffd_initial_admin_pw }}' \ + --env UFFD_INITIAL_ADMIN_MAIL='{{ uffd_initial_admin_mail }}' \ + --name=uffd \ + localhost/uffd:latest + +ExecStop=/usr/bin/podman stop \ + --ignore \ + --cidfile=%t/%n.ctr-id + +ExecStopPost=/usr/bin/podman rm \ + --force \ + --ignore \ + --cidfile=%t/%n.ctr-id + +[Install] +WantedBy=default.target diff --git a/roles/uffd/templates/uffd/uffd.cfg b/roles/uffd/templates/uffd/uffd.cfg new file mode 100644 index 0000000..74cf8c8 --- /dev/null +++ b/roles/uffd/templates/uffd/uffd.cfg @@ -0,0 +1,3 @@ +FLASK_ENV="production" +SQLALCHEMY_DATABASE_URI="sqlite:////var/lib/uffd/db.sqlite" +SECRET_KEY="{{ uffd_secret_key }}"