Do not use the postgresql_user/postgresql_db modules

While these modules are really nice and helpful, we can't use them
for at least 2 reasons:

- for us, Postgres runs in a container on a private Docker network
(`--network=matrix`) without usually being exposed to the host.
These modules execute on the host so they won't be able to reach it.

- these modules require `psycopg2`, so we need to install it before
using it. This might or might not be its own can of worms.
This commit is contained in:
Slavi Pantaleev 2020-12-14 00:25:13 +02:00
parent bbc09d013b
commit da4cb2f639
3 changed files with 63 additions and 25 deletions

View File

@ -0,0 +1,34 @@
---
# TODO - ensure `additional_db` contains all keys that we expect
# The SQL statements that we'll run against Postgres are stored in a file that others can't read.
# This file will be mounted into the container and fed to Postgres.
# This way, we avoid passing sensitive data around in CLI commands that other users on the system can see.
- name: Create additional database initialization SQL file for {{ additional_db.name }}
template:
src: "{{ role_path }}/templates/init-additional-db-user-and-role.sql.j2"
dest: "/tmp/matrix-postgres-init-additional-db-user-and-role.sql"
mode: 0600
owner: "{{ matrix_user_uid }}"
group: "{{ matrix_user_gid }}"
- name: Execute Postgres additional database initialization SQL file for {{ additional_db.name }}
command:
cmd: >-
{{ matrix_host_command_docker }} run
--rm
--user={{ matrix_user_uid }}:{{ matrix_user_gid }}
--cap-drop=ALL
--env-file={{ matrix_postgres_base_path }}/env-postgres-psql
--network {{ matrix_docker_network }}
--mount type=bind,src=/tmp/matrix-postgres-init-additional-db-user-and-role.sql,dst=/matrix-postgres-init-additional-db-user-and-role.sql,ro
--entrypoint=/bin/sh
{{ matrix_postgres_docker_image_to_use }}
-c
'psql -h {{ matrix_postgres_connection_hostname }} --file=/matrix-postgres-init-additional-db-user-and-role.sql'
- name: Delete additional database initialization SQL file for {{ additional_db.name }}
file:
path: /tmp/matrix-postgres-init-additional-db-user-and-role.sql
state: absent

View File

@ -1,28 +1,13 @@
--- ---
- name: Retrieve IP of postgres container # TODO - we should ensure matrix-postgres.service is started.
command: "{{ matrix_host_command_docker }} inspect matrix-postgres --format='{% raw %}{{ .NetworkSettings.Networks.{% endraw %}{{ matrix_docker_network }}{% raw %}.IPAddress }}{% endraw %}'" # .. and that if we had just started it, we've given it ample time to initialize,
register: matrix_postgres_container_ip # before we attempt to run queries against it.
- name: Create additional users in postgres - name: Create additional Postgers user and database
postgresql_user: include_tasks: "{{ role_path }}/tasks/util/create_additional_database.yml"
name: "{{ item.username }}" with_items: "{{ matrix_postgres_additional_databases }}"
password: "{{ item.pass }}" loop_control:
login_host: "{{ matrix_postgres_container_ip.stdout }}" loop_var: additional_db
login_port: 5432 # Suppress logging to avoid dumping the credentials to the shell
login_user: "{{ matrix_postgres_connection_username }}" no_log: true
login_password: "{{ matrix_postgres_connection_password }}"
login_db: "{{ matrix_postgres_db_name }}"
loop: "{{ matrix_postgres_additional_databases }}"
- name: Create additional users in postgres
postgresql_db:
name: "{{ item.name }}"
owner: "{{ item.username }}"
lc_ctype: 'C'
lc_collate: 'C'
login_host: "{{ matrix_postgres_container_ip.stdout }}"
login_port: 5432
login_user: "{{ matrix_postgres_connection_username }}"
login_password: "{{ matrix_postgres_connection_password }}"
loop: "{{ matrix_postgres_additional_databases }}"

View File

@ -0,0 +1,19 @@
-- `CREATE USER` does not support `IF NOT EXISTS`, so we use this workaround to prevent an error and raise a notice instead.
-- Seen here: https://stackoverflow.com/a/49858797
DO $$
BEGIN
CREATE USER {{ additional_db.username }};
EXCEPTION WHEN DUPLICATE_OBJECT THEN
RAISE NOTICE 'not creating role {{ additional_db.username }}, since it already exists';
END
$$;
-- This is useful for initial user creation (since we don't assign a password above) and for handling subsequent password changes
-- TODO - we should escape quotes in the password.
ALTER ROLE {{ additional_db.username }} PASSWORD '{{ additional_db.pass }}';
-- This will generate an error on subsequent execution
CREATE DATABASE {{ additional_db.name }} WITH LC_CTYPE 'C' LC_COLLATE 'C' OWNER {{ additional_db.username }};
-- This is useful for changing the database owner subsequently
ALTER DATABASE {{ additional_db.name }} OWNER TO {{ additional_db.username }};