diff --git a/README.md b/README.md index 68c92b4..6906a7f 100644 --- a/README.md +++ b/README.md @@ -45,3 +45,8 @@ Im Ansible-Repo müssen diese Sachen hinzugefügt werden: * Individuelle Config für den Service. Wenn Docker Compose, hier weiterleiten auf den eigentlichen Dienst in Compose. * Cert-Dateinamen anpassen * `resources/chaosknoten/`*host*`/docker_compose/compose.yaml.j2`: Config für Docker Compose (wenn verwendet) + +## License + +This CCCHH ansible-ccchh repository is licensed under the [MIT License](./LICENSE). +[`custom_pipeline_oidc_group_and_role_mapping.py`](./roles/netbox/files/custom_pipeline_oidc_group_and_role_mapping.py) is licensed under the Creative Commons: CC BY-SA 4.0 license. diff --git a/inventories/chaosknoten/host_vars/netbox.yaml b/inventories/chaosknoten/host_vars/netbox.yaml new file mode 100644 index 0000000..2304112 --- /dev/null +++ b/inventories/chaosknoten/host_vars/netbox.yaml @@ -0,0 +1,16 @@ +netbox__version: "v4.1.7" +netbox__db_password: "{{ lookup('community.general.passwordstore', 'noc/vm-secrets/chaosknoten/netbox/DATABASE_PASSWORD', create=false, missing='error') }}" +netbox__config: "{{ lookup('ansible.builtin.template', 'resources/chaosknoten/netbox/netbox/configuration.py.j2') }}" +netbox__custom_pipeline_oidc_group_and_role_mapping: true + +nginx__version_spec: "" +nginx__configurations: + - name: netbox.hamburg.ccc.de + content: "{{ lookup('ansible.builtin.file', 'resources/chaosknoten/netbox/nginx/netbox.hamburg.ccc.de.conf') }}" + +certbot__version_spec: "" +certbot__acme_account_email_address: j+letsencrypt-ccchh@jsts.xyz +certbot__certificate_domains: + - "netbox.hamburg.ccc.de" +certbot__new_cert_commands: + - "systemctl reload nginx.service" diff --git a/inventories/chaosknoten/hosts.yaml b/inventories/chaosknoten/hosts.yaml index 911a87d..0f10bea 100644 --- a/inventories/chaosknoten/hosts.yaml +++ b/inventories/chaosknoten/hosts.yaml @@ -32,6 +32,10 @@ all: mumble: ansible_host: mumble.hamburg.ccc.de ansible_user: chaos + netbox: + ansible_host: netbox-intern.hamburg.ccc.de + ansible_user: chaos + ansible_ssh_common_args: -J ssh://chaos@public-reverse-proxy.hamburg.ccc.de onlyoffice: ansible_host: onlyoffice-intern.hamburg.ccc.de ansible_user: chaos @@ -64,6 +68,7 @@ all: keycloak: lists: mumble: + netbox: onlyoffice: pad: pretalx: @@ -94,6 +99,7 @@ all: keycloak: lists: mumble: + netbox: onlyoffice: pad: pretalx: @@ -112,6 +118,7 @@ all: keycloak: lists: mumble: + netbox: onlyoffice: pad: pretalx: @@ -123,6 +130,7 @@ all: eh22-wiki: tickets: keycloak: + netbox: onlyoffice: pad: pretalx: @@ -136,6 +144,7 @@ all: tickets: cloud: keycloak: + netbox: onlyoffice: pad: pretalx: @@ -146,3 +155,6 @@ all: hosts: eh22-wiki: wiki: + netbox_hosts: + hosts: + netbox: diff --git a/playbooks/deploy.yaml b/playbooks/deploy.yaml index da2937f..66f03de 100644 --- a/playbooks/deploy.yaml +++ b/playbooks/deploy.yaml @@ -29,6 +29,11 @@ roles: - dokuwiki +- name: Ensure NetBox deployment on netbox_hosts + hosts: netbox_hosts + roles: + - netbox + - name: Ensure NGINX deployment on nginx_hosts, which are also public_reverse_proxy_hosts, before certbot role runs hosts: nginx_hosts:&public_reverse_proxy_hosts roles: diff --git a/resources/chaosknoten/netbox/netbox/configuration.py.j2 b/resources/chaosknoten/netbox/netbox/configuration.py.j2 new file mode 100644 index 0000000..789a539 --- /dev/null +++ b/resources/chaosknoten/netbox/netbox/configuration.py.j2 @@ -0,0 +1,60 @@ +ALLOWED_HOSTS = [ "netbox.hamburg.ccc.de" ] +DATABASE = { + "HOST": "localhost", + "NAME": "netbox", + "USER": "netbox", + "PASSWORD": "{{ lookup('community.general.passwordstore', 'noc/vm-secrets/chaosknoten/netbox/DATABASE_PASSWORD', create=false, missing='error') }}", +} +REDIS = { + "tasks": { + "HOST": "localhost", + "PORT": 6379, + "USERNAME": "", + "PASSWORD": "", + "DATABASE": 0, + "SSL": False, + }, + "caching": { + "HOST": "localhost", + "PORT": 6379, + "USERNAME": "", + "PASSWORD": "", + "DATABASE": 1, + "SSL": False, + }, +} +SECRET_KEY = "{{ lookup('community.general.passwordstore', 'noc/vm-secrets/chaosknoten/netbox/SECRET_KEY', create=false, missing='error') }}" +SESSION_COOKIE_SECURE = True + +# CCCHH ID (Keycloak) integration. +# https://github.com/python-social-auth/social-core/blob/0925304a9e437f8b729862687d3a808c7fb88a95/social_core/backends/keycloak.py#L7 +# https://python-social-auth.readthedocs.io/en/latest/backends/keycloak.html +REMOTE_AUTH_BACKEND = "social_core.backends.keycloak.KeycloakOAuth2" +SOCIAL_AUTH_KEYCLOAK_ACCESS_TOKEN_URL = ( + "https://id.hamburg.ccc.de/realms/ccchh/protocol/openid-connect/token" +) +SOCIAL_AUTH_KEYCLOAK_AUTHORIZATION_URL = ( + "https://id.hamburg.ccc.de/realms/ccchh/protocol/openid-connect/auth" +) +SOCIAL_AUTH_KEYCLOAK_KEY = "netbox" +SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAi/Shi+b2OyYNGVFPsa6qf9SesEpRl5U5rpwgmt8H7NawMvwpPUYVW9o46QW0ulYcDmysT3BzpP3tagO/SFNoOjZdYe0D9nJ7vEp8KHbzR09KCfkyQIi0wLssKnDotVHL5JeUY+iKk+gjiwF9FSFSHPBqsST7hXVAut9LkOvs2aDod9AzbTH/uYbt4wfUm5l/1Ii8D+K7YcsFGUIqxv4XS/ylKqObqN4M2dac69iIwapoh6reaBQEm66vrOzJ+3yi4DZuPrkShJqi2hddtoyZihyCkF+eJJKEI5LrBf1KZB3Ec2YUrqk93ZGUGs/XY6R87QSfR3hJ82B1wnF+c2pw+QIDAQAB" +SOCIAL_AUTH_KEYCLOAK_SECRET = "{{ lookup('community.general.passwordstore', 'noc/vm-secrets/chaosknoten/netbox/SOCIAL_AUTH_KEYCLOAK_SECRET', create=false, missing='error') }}" +# Use custom OIDC group and role mapping pipeline functions added in via +# netbox__custom_pipeline_oidc_group_and_role_mapping. +# The default pipeline this is based on can be found here: +# https://github.com/netbox-community/netbox/blob/main/netbox/netbox/settings.py +SOCIAL_AUTH_PIPELINE = [ + "social_core.pipeline.social_auth.social_details", + "social_core.pipeline.social_auth.social_uid", + "social_core.pipeline.social_auth.social_user", + "social_core.pipeline.user.get_username", + "social_core.pipeline.user.create_user", + "social_core.pipeline.social_auth.associate_user", + "netbox.authentication.user_default_groups_handler", + "social_core.pipeline.social_auth.load_extra_data", + "social_core.pipeline.user.user_details", + # Custom OIDC group and role mapping functions. + "netbox.custom_pipeline_oidc_mapping.add_groups", + "netbox.custom_pipeline_oidc_mapping.remove_groups", + "netbox.custom_pipeline_oidc_mapping.set_roles", +] diff --git a/resources/chaosknoten/netbox/nginx/netbox.hamburg.ccc.de.conf b/resources/chaosknoten/netbox/nginx/netbox.hamburg.ccc.de.conf new file mode 100644 index 0000000..5550686 --- /dev/null +++ b/resources/chaosknoten/netbox/nginx/netbox.hamburg.ccc.de.conf @@ -0,0 +1,48 @@ +# partly generated 2022-01-08, Mozilla Guideline v5.6, nginx 1.17.7, OpenSSL 1.1.1k, intermediate configuration +# https://ssl-config.mozilla.org/#server=nginx&version=1.17.7&config=intermediate&openssl=1.1.1k&guideline=5.6 +server { + # Listen on a custom port for the proxy protocol. + listen 8443 ssl http2 proxy_protocol; + # Make use of the ngx_http_realip_module to set the $remote_addr and + # $remote_port to the client address and client port, when using proxy + # protocol. + # First set our proxy protocol proxy as trusted. + set_real_ip_from 172.31.17.140; + # Then tell the realip_module to get the addreses from the proxy protocol + # header. + real_ip_header proxy_protocol; + + server_name netbox.hamburg.ccc.de; + + ssl_certificate /etc/letsencrypt/live/netbox.hamburg.ccc.de/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/netbox.hamburg.ccc.de/privkey.pem; + # verify chain of trust of OCSP response using Root CA and Intermediate certs + ssl_trusted_certificate /etc/letsencrypt/live/netbox.hamburg.ccc.de/chain.pem; + + # HSTS (ngx_http_headers_module is required) (63072000 seconds) + add_header Strict-Transport-Security "max-age=63072000" always; + + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Port 443; + # This is https in any case. + proxy_set_header X-Forwarded-Proto https; + # Hide the X-Forwarded header. + proxy_hide_header X-Forwarded; + # Assume we are the only Reverse Proxy (well using Proxy Protocol, but that + # is transparent). + # Also provide "_hidden" for by, since it's not relevant. + proxy_set_header Forwarded "for=$remote_addr;proto=https;host=$host;by=_hidden"; + + client_max_body_size 25m; + + location /static/ { + alias /opt/netbox/netbox/static/; + } + + location / { + proxy_pass http://127.0.0.1:8001; + } +} diff --git a/resources/chaosknoten/public-reverse-proxy/nginx/acme_challenge.conf b/resources/chaosknoten/public-reverse-proxy/nginx/acme_challenge.conf index d5ae146..c3f9fed 100644 --- a/resources/chaosknoten/public-reverse-proxy/nginx/acme_challenge.conf +++ b/resources/chaosknoten/public-reverse-proxy/nginx/acme_challenge.conf @@ -17,7 +17,7 @@ map $host $upstream_acme_challenge_host { invite.hamburg.ccc.de 172.31.17.144:31820; keycloak-admin.hamburg.ccc.de 172.31.17.144:31820; matrix.hamburg.ccc.de 172.31.17.150:31820; - netbox.hamburg.ccc.de 172.31.17.149:31820; + netbox.hamburg.ccc.de 172.31.17.167:31820; onlyoffice.hamburg.ccc.de 172.31.17.147:31820; pad.hamburg.ccc.de 172.31.17.141:31820; pretalx.hamburg.ccc.de 172.31.17.157:31820; diff --git a/resources/chaosknoten/public-reverse-proxy/nginx/nginx.conf b/resources/chaosknoten/public-reverse-proxy/nginx/nginx.conf index 0529f4c..dfcf8d2 100644 --- a/resources/chaosknoten/public-reverse-proxy/nginx/nginx.conf +++ b/resources/chaosknoten/public-reverse-proxy/nginx/nginx.conf @@ -32,7 +32,7 @@ stream { onlyoffice.hamburg.ccc.de 172.31.17.147:8443; hackertours.hamburg.ccc.de 172.31.17.151:8443; staging.hackertours.hamburg.ccc.de 172.31.17.151:8443; - netbox.hamburg.ccc.de 172.31.17.149:8443; + netbox.hamburg.ccc.de 172.31.17.167:8443; matrix.hamburg.ccc.de 172.31.17.150:8443; element.hamburg.ccc.de 172.31.17.151:8443; branding-resources.hamburg.ccc.de 172.31.17.151:8443; diff --git a/roles/netbox/README.md b/roles/netbox/README.md new file mode 100644 index 0000000..594e8f8 --- /dev/null +++ b/roles/netbox/README.md @@ -0,0 +1,88 @@ +# `netbox` role + +A role for setting up NetBox. +It automatically pulls in all required dependencies like Redis and PostgreSQL, deploys the provided systemd services and gunicorn config and sets up a PostgreSQL database named `netbox` with an owner named `netbox` and the specified password. +However providing the [NetBox configuration](#netbox-configuration), [setting up a web server like nginx to proxy to gunicorn](#web-server-setup) and tasks like creating users, etc. you have to do yourself. + +## Supported Distributions + +Should work on Debian-based distributions. + +## Required Arguments + +- `netbox__version`: The NetBox version to deploy. +- `netbox__db_password`: The password to use for connection to the database. + This is required since the upgrade script runs as root and therefore peer authentication doesn't work. +- `netbox__config`: The NetBox config to deploy. + See [NetBox Configuration](#netbox-configuration) for more infos. + +## Optional Arguments + +- `netbox__custom_pipeline_oidc_group_and_role_mapping`: Whether or not to have custom pipeline code for OIDC group and role mapping present. + See [Custom Pipeline Code for OIDC Group and Role Mapping](#custom-pipeline-code-for-oidc-group-and-role-mapping) for more infos. + Defaults to `false`. + +## NetBox Configuration + +The NetBox configuration should include a connection to Redis as well as a connection to PostgreSQL. +Configuration for the Redis connection: + +```python +REDIS = { + "tasks": { + "HOST": "localhost", + "PORT": 6379, + "USERNAME": "", + "PASSWORD": "", + "DATABASE": 0, + "SSL": False, + }, + "caching": { + "HOST": "localhost", + "PORT": 6379, + "USERNAME": "", + "PASSWORD": "", + "DATABASE": 1, + "SSL": False, + }, +} +``` + +Configuration for the PostgreSQL connection: + +```python +DATABASE = { + "HOST": "localhost", + "NAME": "netbox", + "USER": "netbox", + "PASSWORD": "<same as netbox__db_password>", +} +``` + +Further configuration should take place. Some relevant resources can be found here: + +- Installation guide configuration docs: <https://netboxlabs.com/docs/netbox/en/stable/installation/3-netbox/#configuration> +- Configuration docs: <https://netboxlabs.com/docs/netbox/en/stable/configuration/> +- Example configuration: <https://github.com/netbox-community/netbox/blob/main/netbox/netbox/configuration_example.py> + +## Web Server Setup + +As this role just sets up gunicorn, but doesn't set up a web server, you need to do that yourself. +The relevant documentation on how to do that can be found here: + +- Web server setup docs: <https://netboxlabs.com/docs/netbox/en/stable/installation/5-http-server/> +- Example base nginx config: <https://github.com/netbox-community/netbox/blob/main/contrib/nginx.conf> + +## Custom Pipeline Code for OIDC Group and Role Mapping + +Setting the option `netbox__custom_pipeline_oidc_group_and_role_mapping` to `true` makes this role ensure custom pipeline code for OIDC group and role mapping is present. +Note that this role uses code for NetBox >= 4.0.0. +The code is available in `files/custom_pipeline_oidc_group_and_role_mapping.py`, licensed under the CC BY-SA 4.0 license and taken from [this authentik NetBox documentation](https://docs.goauthentik.io/integrations/services/netbox/). +The documentation also shows how to use the pipeline code by defining a custom `SOCIAL_AUTH_PIPELINE`, which you also need to do, as the configuration isn't provided by this role. +However instead of under `netbox.custom_pipeline.` the functions are available under `netbox.custom_pipeline_oidc_mapping.` with this role. +See also [the default settings.py](https://github.com/netbox-community/netbox/blob/main/netbox/netbox/settings.py) for the default `SOCIAL_AUTH_PIPELINE`. + +## Links & Resources + +- The NetBox Git Repo: <https://github.com/netbox-community/netbox> +- The NetBox installation docs: <https://netboxlabs.com/docs/netbox/en/stable/installation/> diff --git a/roles/netbox/defaults/main.yaml b/roles/netbox/defaults/main.yaml new file mode 100644 index 0000000..49b518e --- /dev/null +++ b/roles/netbox/defaults/main.yaml @@ -0,0 +1 @@ +netbox__custom_pipeline_oidc_group_and_role_mapping: false diff --git a/roles/netbox/files/custom_pipeline_oidc_group_and_role_mapping.py b/roles/netbox/files/custom_pipeline_oidc_group_and_role_mapping.py new file mode 100644 index 0000000..470f388 --- /dev/null +++ b/roles/netbox/files/custom_pipeline_oidc_group_and_role_mapping.py @@ -0,0 +1,55 @@ +# Licensed under Creative Commons: CC BY-SA 4.0 license. +# https://github.com/goauthentik/authentik/blob/main/LICENSE +# https://github.com/goauthentik/authentik/blob/main/website/integrations/services/netbox/index.md +# https://docs.goauthentik.io/integrations/services/netbox/ +from netbox.authentication import Group + +class AuthFailed(Exception): + pass + +def add_groups(response, user, backend, *args, **kwargs): + try: + groups = response['groups'] + except KeyError: + pass + + # Add all groups from oAuth token + for group in groups: + group, created = Group.objects.get_or_create(name=group) + user.groups.add(group) + +def remove_groups(response, user, backend, *args, **kwargs): + try: + groups = response['groups'] + except KeyError: + # Remove all groups if no groups in oAuth token + user.groups.clear() + pass + + # Get all groups of user + user_groups = [item.name for item in user.groups.all()] + # Get groups of user which are not part of oAuth token + delete_groups = list(set(user_groups) - set(groups)) + + # Delete non oAuth token groups + for delete_group in delete_groups: + group = Group.objects.get(name=delete_group) + user.groups.remove(group) + + +def set_roles(response, user, backend, *args, **kwargs): + # Remove Roles temporary + user.is_superuser = False + user.is_staff = False + try: + groups = response['groups'] + except KeyError: + # When no groups are set + # save the user without Roles + user.save() + pass + + # Set roles is role (superuser or staff) is in groups + user.is_superuser = True if 'superusers' in groups else False + user.is_staff = True if 'staff' in groups else False + user.save() diff --git a/roles/netbox/handlers/main.yaml b/roles/netbox/handlers/main.yaml new file mode 100644 index 0000000..fd7eb62 --- /dev/null +++ b/roles/netbox/handlers/main.yaml @@ -0,0 +1,24 @@ +- name: Run upgrade script + ansible.builtin.command: /opt/netbox/upgrade.sh + become: true + # When it runs, this should always report changed. + changed_when: true + +- name: Ensure netbox systemd services are set up and up-to-date + ansible.builtin.systemd_service: + daemon_reload: true + name: "{{ item }}" + enabled: true + state: restarted + become: true + loop: + - "netbox.service" + - "netbox-rq.service" + +- name: Ensure netbox housekeeping timer is set up and up-to-date + ansible.builtin.systemd_service: + daemon_reload: true + name: "netbox-housekeeping.timer" + enabled: true + state: restarted + become: true diff --git a/roles/netbox/meta/argument_specs.yaml b/roles/netbox/meta/argument_specs.yaml new file mode 100644 index 0000000..0506389 --- /dev/null +++ b/roles/netbox/meta/argument_specs.yaml @@ -0,0 +1,16 @@ +argument_specs: + main: + options: + netbox__version: + type: str + required: true + netbox__db_password: + type: str + required: true + netbox__config: + type: str + required: true + netbox__custom_pipeline_oidc_group_and_role_mapping: + type: bool + required: false + default: false diff --git a/roles/netbox/meta/main.yaml b/roles/netbox/meta/main.yaml new file mode 100644 index 0000000..79c845d --- /dev/null +++ b/roles/netbox/meta/main.yaml @@ -0,0 +1,11 @@ +--- +dependencies: + - role: redis + - role: postgresql + vars: + postgresql__dbs: + - name: netbox + owner: netbox + postgresql__users: + - name: netbox + password: "{{ netbox__db_password }}" diff --git a/roles/netbox/tasks/main.yaml b/roles/netbox/tasks/main.yaml new file mode 100644 index 0000000..dffa746 --- /dev/null +++ b/roles/netbox/tasks/main.yaml @@ -0,0 +1,124 @@ +- name: Ensure all dependencies are installed + ansible.builtin.apt: + name: + - python3 + - python3-pip + - python3-venv + - python3-dev + - build-essential + - libxml2-dev + - libxslt1-dev + - libffi-dev + - libpq-dev + - libssl-dev + - zlib1g-dev + - git + become: true + +- name: Ensure NetBox source is present + ansible.builtin.git: + repo: https://github.com/netbox-community/netbox.git + dest: /opt/netbox/ + version: "{{ netbox__version }}" + become: true + notify: + - Run upgrade script + - Ensure netbox systemd services are set up and up-to-date + +- name: Ensures custom pipeline code for OIDC group and role mapping is present + ansible.builtin.copy: + src: custom_pipeline_oidc_group_and_role_mapping.py + dest: /opt/netbox/netbox/netbox/custom_pipeline_oidc_mapping.py + mode: "0644" + owner: root + group: root + when: netbox__custom_pipeline_oidc_group_and_role_mapping + become: true + notify: + - Ensure netbox systemd services are set up and up-to-date + +- name: Ensures custom pipeline code for OIDC group and role mapping is not present + ansible.builtin.file: + path: /opt/netbox/netbox/netbox/custom_pipeline_oidc_mapping.py + state: absent + when: not netbox__custom_pipeline_oidc_group_and_role_mapping + become: true + notify: + - Ensure netbox systemd services are set up and up-to-date + +- name: Ensure netbox user + block: + - name: Ensure netbox group exists + ansible.builtin.group: + name: netbox + system: true + become: true + + - name: Ensure netbox user exists + ansible.builtin.user: + name: netbox + group: netbox + password: '!' + system: true + become: true + +- name: Ensure relevant directories are owned by netbox user + ansible.builtin.file: + path: "{{ item }}" + state: directory + owner: netbox + recurse: true + become: true + loop: + - "/opt/netbox/netbox/media/" + - "/opt/netbox/netbox/reports/" + - "/opt/netbox/netbox/scripts/" + +- name: Deploy configuration.py + ansible.builtin.copy: + content: "{{ netbox__config }}" + dest: "/opt/netbox/netbox/netbox/configuration.py" + mode: "0644" + owner: root + group: root + become: true + notify: Ensure netbox systemd services are set up and up-to-date + +- name: Ensure provided gunicorn config is copied + ansible.builtin.copy: + remote_src: true + src: "/opt/netbox/contrib/gunicorn.py" + dest: "/opt/netbox/gunicorn.py" + mode: "0644" + owner: root + group: root + become: true + notify: Ensure netbox systemd services are set up and up-to-date + +- name: Ensure provided netbox systemd service files are copied + ansible.builtin.copy: + remote_src: true + src: "/opt/netbox/contrib/{{ item }}" + dest: "/etc/systemd/system/{{ item }}" + mode: "0644" + owner: root + group: root + become: true + loop: + - "netbox.service" + - "netbox-rq.service" + notify: Ensure netbox systemd services are set up and up-to-date + +- name: Ensure provided housekeeping systemd service and timer are copied + ansible.builtin.copy: + remote_src: true + src: "/opt/netbox/contrib/{{ item }}" + dest: "/etc/systemd/system/{{ item }}" + mode: "0644" + owner: root + group: root + become: true + loop: + - "netbox-housekeeping.service" + - "netbox-housekeeping.timer" + notify: Ensure netbox housekeeping timer is set up and up-to-date diff --git a/roles/postgresql/README.md b/roles/postgresql/README.md new file mode 100644 index 0000000..6457931 --- /dev/null +++ b/roles/postgresql/README.md @@ -0,0 +1,37 @@ +# Role `postgresql` + +Ensures `postgresql` is installed by installing the distributions package. +Also ensures the optionally given databases and users are set up as specified. + +## Supported Distributions + +Should work on Debian-based distributions. + +## Required Arguments + +None. + +## Optional Arguments + +- `postgresql__dbs`: List of databases with their owner to ensure are set up. +- `postgresql__dbs.*.name`: Name of the database. +- `postgresql__dbs.*.owner`: Owner of the database. +- `postgresql__users`: List of users to ensure are set up. +- `postgresql__users.*.name`: Name of the user. +- `postgresql__users.*.password`: Optional password for the user. + If left unset, the user will have no password set, but can still connect using [peer authentication](https://www.postgresql.org/docs/current/auth-peer.html) on the local system. + (Peer authentication works when a password is set as well.) + +## Example Arguments + +```yaml +postgresql__dbs: + - name: netbox + owner: netbox + - name: foo + owner: bar +postgresql__users: + - name: netbox + password: super_secret + - name: bar +``` diff --git a/roles/postgresql/defaults/main.yaml b/roles/postgresql/defaults/main.yaml new file mode 100644 index 0000000..21fcd46 --- /dev/null +++ b/roles/postgresql/defaults/main.yaml @@ -0,0 +1,2 @@ +postgresql__dbs: [ ] +postgresql__users: [ ] diff --git a/roles/postgresql/meta/argument_specs.yaml b/roles/postgresql/meta/argument_specs.yaml new file mode 100644 index 0000000..28e5813 --- /dev/null +++ b/roles/postgresql/meta/argument_specs.yaml @@ -0,0 +1,28 @@ +argument_specs: + main: + options: + postgresql__dbs: + type: list + elements: dict + required: false + default: [ ] + options: + name: + type: str + required: true + owner: + type: str + required: true + postgresql__users: + type: list + elements: dict + required: false + default: [ ] + options: + name: + type: str + required: true + password: + type: str + required: false + default: "" diff --git a/roles/postgresql/tasks/main.yaml b/roles/postgresql/tasks/main.yaml new file mode 100644 index 0000000..8f89018 --- /dev/null +++ b/roles/postgresql/tasks/main.yaml @@ -0,0 +1,30 @@ +- name: Ensure postgresql is installed + ansible.builtin.apt: + name: + - postgresql + become: true + +- name: Ensure Python library for community.postgresql is installed if needed + ansible.builtin.apt: + name: + - python3-psycopg + become: true + when: postgresql__dbs != [ ] or postgresql__users != [ ] + +- name: Ensure users + community.postgresql.postgresql_user: + name: "{{ item.name }}" + password: "{{ item.password | default('') }}" + become: true + become_user: postgres + loop: "{{ postgresql__users }}" + loop_control: + label: "user {{ item.name }} with {{ 'a password' if item.password is defined else 'no password' }}" + +- name: Ensure dbs with owners + community.postgresql.postgresql_db: + name: "{{ item.name }}" + owner: "{{ item.owner }}" + become: true + become_user: postgres + loop: "{{ postgresql__dbs }}" diff --git a/roles/redis/README.md b/roles/redis/README.md new file mode 100644 index 0000000..dd30500 --- /dev/null +++ b/roles/redis/README.md @@ -0,0 +1,15 @@ +# Role `redis` + +Ensures `redis` is installed by installing the distributions package. + +## Supported Distributions + +Should work on Debian-based distributions. + +## Required Arguments + +None. + +## Optional Arguments + +None. diff --git a/roles/redis/tasks/main.yaml b/roles/redis/tasks/main.yaml new file mode 100644 index 0000000..ad70e44 --- /dev/null +++ b/roles/redis/tasks/main.yaml @@ -0,0 +1,5 @@ +- name: Ensure redis is installed + ansible.builtin.apt: + name: + - redis + become: true