community.postgresql icon indicating copy to clipboard operation
community.postgresql copied to clipboard

pg_user doesn't take password_encryption into account when checking if a password should be updated

Open dirkcuys opened this issue 1 year ago • 8 comments

SUMMARY

When the current password is stored as a md5 hash, but PGOPTIONS: "-c password_encryption=scram-sha-256" is passed, the new password will still be hashed with md5.

https://github.com/ansible-collections/community.postgresql/blob/0bc4754d88a4343a19b97e76e022e9a93fc1fdef/plugins/modules/postgresql_user.py#L473

ISSUE TYPE
  • Bug Report
COMPONENT NAME

postgresql_user

ANSIBLE VERSION
ansible [core 2.16.5]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/ZZZ/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  ansible collection location = /home/ZZZ/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] (/usr/bin/python3)
  jinja version = 3.0.3
  libyaml = True

COLLECTION VERSION
# /usr/lib/python3/dist-packages/ansible_collections
Collection           Version
-------------------- -------
community.postgresql 3.4.0  
STEPS TO REPRODUCE

Create a user

- name: create postgres user
  postgresql_user:
    name: user
    password: password
    login_host: "127.0.0.1"

Update the playbook to use SCRAM

- name: create postgres user
  postgresql_user:
    name: user
    password: password
    login_host: "127.0.0.1"
  environment:
    PGOPTIONS: "-c password_encryption=scram-sha-256"

And re-run the playbook. The password is reported as unchanged.

EXPECTED RESULTS

The password is updated using scram-sha-256

ACTUAL RESULTS

The password is unchanged

dirkcuys avatar Apr 18 '24 10:04 dirkcuys

Hi @dirkcuys Although the password_encryption variable may be changed, the password remains the same. Currently the module does not attempt to change the hashing algorithm while keeping the same password. If you change the password, the module will use the then-specified password_encryption.

betanummeric avatar Apr 18 '24 19:04 betanummeric

Thanks, that helps me work around the problem in my specific case! I ran into problems while migrating a db from postgres 11 to postgres 15. In postgres 15, the default encryption is set as scram-sha-256.

If I'm reading the code correctly, the password is updated using the following SQL

ALTER USER "user" WITH ENCRYPTED PASSWORD %(password)s

And the password passed as a parameter to the query:

cursor.execute(statement, query_password_data)

It doesn't seem like the encryption scheme is available within the function that checks if a password should be changed or where it is updated.

Could it be determined by checking the environment? Then something like

elif (password.startswith('md5') and 'PGOPTIONS' in os.environ and 'password_encryption=scram-sha-256' in os.environ['PGOPTIONS']:
    pwchanging = True

could be added here

dirkcuys avatar Apr 19 '24 08:04 dirkcuys

Yes, the password is set with ALTER USER.

The password_encryption variable can also be set in other ways, so checking the environment is not sufficient. But we can simply run the query show password_encryption;.

Do you want to submit a pull request? What issues did you run into during the upgrade to pg 15?

betanummeric avatar Apr 19 '24 17:04 betanummeric

Do you want to submit a pull request?

If I run into this again I'll try to get a PR together, but for my use-case changing the password was easy enough

What issues did you run into during the upgrade to pg 15?

The issue was that the default for encryption for passwords changed between pg 11 and 15

dirkcuys avatar Jul 01 '24 09:07 dirkcuys

Thanks for discussing the issue, folks! Can we close it? What do you think?

Andersson007 avatar Jul 02 '24 07:07 Andersson007

We run into the same problem, migration is not easy, we would like an option that the password is updated if not matched.

So we set:

PGOPTIONS: "-c password_encryption=scram-sha-256"

And would expect the password to be updated (even if not changed) if still saved as md5, the same when the new algorithm on the server is already scram-sha-256 and the password are still md5

jogoossens avatar Oct 22 '24 15:10 jogoossens

@jogoossens thanks for the feedback! I've put the help wanted label. If someone wants to contribute, here's the quick start dev guide that can help Feels like a relatively easy fix with what @betanummeric suggested. Any volunteers?

Andersson007 avatar Oct 25 '24 07:10 Andersson007

For now we use this ansible code to reset all passwords to something random, but we can break users which exist already like this :)

- block:
    - name: Get all users without SCRAM-SHA-256 password when postgres is 14 or higher
      community.postgresql.postgresql_query:
        query: >
          SELECT rolname FROM pg_authid
          WHERE rolcanlogin and rolpassword !~* '^SCRAM-SHA-256';
      register: users_to_update
        
    - name: Reset all passwords from users without SCRAM-SHA-256 password when postgres is 14 or higher
      community.postgresql.postgresql_user:
        name: "{{ item.rolname }}"
        password: "{{ lookup('community.general.random_string', length=32) }}"
      loop: "{{ users_to_update.query_result | list }}"
      
  become: true
  become_user: "{{ postgresql_user }}"
  when: postgresql_version is version('14', '>=')

Maybe this idea can be used to check the SCRAM-SHA-256.

jogoossens avatar Oct 28 '24 09:10 jogoossens

PR https://github.com/ansible-collections/community.postgresql/pull/764 , please read its description carefully, i also put a comment about testing, thanks

Andersson007 avatar Nov 08 '24 10:11 Andersson007

Thanks everyone! I'll ping you all here when we release the collection (probably soon)

Andersson007 avatar Nov 13 '24 10:11 Andersson007