--- # Playbook: Create PostgreSQL User # Description: Creates a PostgreSQL user with specified privileges # Usage: # Basic user: # ansible-playbook playbooks/create-postgres-user.yml -e "pg_username=myuser" # # With specific password: # ansible-playbook playbooks/create-postgres-user.yml -e "pg_username=myuser pg_password=mypassword" # # With specific privileges: # ansible-playbook playbooks/create-postgres-user.yml -e "pg_username=myuser pg_superuser=true" # ansible-playbook playbooks/create-postgres-user.yml -e "pg_username=myuser pg_createdb=true" # # Variables: # pg_username: Username to create (required) # pg_password: Password for user (optional, will generate random if not provided) # pg_superuser: Grant SUPERUSER privilege (default: false) # pg_createdb: Grant CREATEDB privilege (default: false) # pg_createrole: Grant CREATEROLE privilege (default: false) # pg_login: Allow user to login (default: true) - name: Create PostgreSQL User hosts: postgres become: true gather_facts: false vars: pg_superuser: false pg_createdb: false pg_createrole: false pg_login: true pg_generate_password: "{{ pg_password is not defined }}" tasks: - name: Validate required variables ansible.builtin.assert: that: - pg_username is defined - pg_username | length > 0 fail_msg: "pg_username is required. Usage: ansible-playbook playbooks/create-postgres-user.yml -e 'pg_username=myuser'" - name: Generate random password if not provided ansible.builtin.shell: openssl rand -base64 32 register: generated_password delegate_to: localhost become: false when: pg_generate_password | bool changed_when: false - name: Set password variable ansible.builtin.set_fact: pg_password: "{{ generated_password.stdout if pg_generate_password | bool else pg_password }}" - name: Build role attributes ansible.builtin.set_fact: role_attrs: >- {{ (pg_superuser | bool) | ternary('SUPERUSER', 'NOSUPERUSER') }} {{ (pg_createdb | bool) | ternary('CREATEDB', 'NOCREATEDB') }} {{ (pg_createrole | bool) | ternary('CREATEROLE', 'NOCREATEROLE') }} {{ (pg_login | bool) | ternary('LOGIN', 'NOLOGIN') }} - name: Check if user already exists ansible.builtin.shell: | psql -tAc "SELECT 1 FROM pg_roles WHERE rolname='{{ pg_username }}'" become_user: postgres register: user_exists changed_when: false failed_when: false - name: Create PostgreSQL user ansible.builtin.shell: | psql -c "CREATE USER {{ pg_username }} WITH {{ role_attrs }} PASSWORD '{{ pg_password }}';" become_user: postgres when: user_exists.stdout != "1" register: user_created - name: Update existing user ansible.builtin.shell: | psql -c "ALTER USER {{ pg_username }} WITH {{ role_attrs }} PASSWORD '{{ pg_password }}';" become_user: postgres when: user_exists.stdout == "1" register: user_updated - name: Verify user creation ansible.builtin.shell: | psql -c '\du {{ pg_username }}' become_user: postgres register: user_details changed_when: false - name: Display user information ansible.builtin.debug: msg: - "==========================================" - "PostgreSQL User Created Successfully" - "==========================================" - "Username: {{ pg_username }}" - "Password: {{ pg_password }}" - "Server: {{ ansible_host }}" - "Port: 5432" - "" - "Connection String:" - "postgresql://{{ pg_username }}:{{ pg_password }}@{{ ansible_host }}:5432/database_name" - "" - "Privileges:" - " Superuser: {{ pg_superuser }}" - " Create DB: {{ pg_createdb }}" - " Create Role: {{ pg_createrole }}" - " Login: {{ pg_login }}" - "" - "User Details:" - "{{ user_details.stdout_lines }}" - "" - "⚠️ IMPORTANT: Save this password securely!" - "==========================================" - name: Save credentials to file (optional) ansible.builtin.copy: content: | # PostgreSQL User Credentials # Created: {{ ansible_date_time.iso8601 }} Username: {{ pg_username }} Password: {{ pg_password }} Server: {{ ansible_host }} Port: 5432 Connection String: postgresql://{{ pg_username }}:{{ pg_password }}@{{ ansible_host }}:5432/database_name Privileges: - Superuser: {{ pg_superuser }} - Create DB: {{ pg_createdb }} - Create Role: {{ pg_createrole }} - Login: {{ pg_login }} dest: "/tmp/postgres-user-{{ pg_username }}-{{ ansible_date_time.epoch }}.txt" mode: '0600' delegate_to: localhost become: false when: pg_save_credentials | default(false) | bool