Skip to content

[DPE-6902] Replace md5 with scram-sha-256 in patroni/pg_hba.conf #1004

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: 16/edge
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -2366,6 +2366,7 @@ def update_config(
no_peers=no_peers,
user_databases_map=self.relations_user_databases_map,
slots=replication_slots or None,
instance_password_encryption=self.config.instance_password_encryption,
)
if no_peers:
return True
Expand Down
3 changes: 3 additions & 0 deletions src/cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,7 @@ def render_patroni_yml_file(
no_peers: bool = False,
user_databases_map: dict[str, str] | None = None,
slots: dict[str, str] | None = None,
instance_password_encryption: str | None = None,
) -> None:
"""Render the Patroni configuration file.

Expand All @@ -670,6 +671,7 @@ def render_patroni_yml_file(
no_peers: Don't include peers.
user_databases_map: map of databases to be accessible by each user.
slots: replication slots (keys) with assigned database name (values).
instance_password_encryption: algorithm to use to encrypt the users passwords.
"""
if not self._are_passwords_set:
logger.warning("Passwords are not yet generated by the leader")
Expand Down Expand Up @@ -724,6 +726,7 @@ def render_patroni_yml_file(
patroni_password=self.patroni_password,
user_databases_map=user_databases_map,
slots=slots,
instance_password_encryption=instance_password_encryption,
)
self.render_file(f"{PATRONI_CONF_PATH}/patroni.yaml", rendered, 0o600)

Expand Down
29 changes: 17 additions & 12 deletions templates/patroni.yml.j2
Original file line number Diff line number Diff line change
Expand Up @@ -181,28 +181,33 @@ postgresql:
- {{ 'hostssl' if enable_tls else 'host' }} all +charmed_admin 0.0.0.0/0 scram-sha-256
- {{ 'hostssl' if enable_tls else 'host' }} all +charmed_databases_owner 0.0.0.0/0 scram-sha-256
{%- if not connectivity %}
- {{ 'hostssl' if enable_tls else 'host' }} all all {{ self_ip }} md5
- {{ 'hostssl' if enable_tls else 'host' }} all all {{ self_ip }} {{ instance_password_encryption }}
- {{ 'hostssl' if enable_tls else 'host' }} all all 0.0.0.0/0 reject
{%- elif enable_ldap %}
- {{ 'hostssl' if enable_tls else 'host' }} all +identity_access 0.0.0.0/0 ldap {{ ldap_parameters }}
- {{ 'hostssl' if enable_tls else 'host' }} all +internal_access 0.0.0.0/0 md5
{%- for user, databases in user_databases_map.items() %}
- {{ 'hostssl' if enable_tls else 'host' }} {{ databases }} {{ user }} 0.0.0.0/0 md5
{%- endfor %}
- {{ 'hostssl' if enable_tls else 'host' }} all +internal_access 0.0.0.0/0 {{ instance_password_encryption }}
{%- for user, databases in user_databases_map.items() %}
- {{ 'hostssl' if enable_tls else 'host' }} {{ databases }} {{ user }} 0.0.0.0/0 {{ instance_password_encryption }}
{%- endfor %}
{%- else %}
- {{ 'hostssl' if enable_tls else 'host' }} all +internal_access 0.0.0.0/0 md5
{%- for user, databases in user_databases_map.items() %}
- {{ 'hostssl' if enable_tls else 'host' }} all +internal_access 0.0.0.0/0 scram-sha-256
{%- for user, databases in user_databases_map.items() %}
{%- if 'pgbouncer_auth_relation_' in user %}
- {{ 'hostssl' if enable_tls else 'host' }} {{ databases }} {{ user }} 0.0.0.0/0 md5
{%- endfor %}
{%- else %}
- {{ 'hostssl' if enable_tls else 'host' }} {{ databases }} {{ user }} 0.0.0.0/0 {{ instance_password_encryption }}
{%- endif %}
{%- endfor %}
{%- endif %}
- {{ 'hostssl' if enable_tls else 'host' }} replication replication 127.0.0.1/32 md5
- {{ 'hostssl' if enable_tls else 'host' }} replication replication 127.0.0.1/32 scram-sha-256
# Allow replications connections from other cluster members.
{%- for endpoint in extra_replication_endpoints %}
- {{ 'hostssl' if enable_tls else 'host' }} replication replication {{ endpoint }}/32 md5
- {{ 'hostssl' if enable_tls else 'host' }} replication replication {{ endpoint }}/32 scram-sha-256
{%- endfor %}
{%- for peer_ip in peers_ips %}
- {{ 'hostssl' if enable_tls else 'host' }} replication replication {{ peer_ip }}/0 md5
{% endfor %}
- {{ 'hostssl' if enable_tls else 'host' }} replication replication {{ peer_ip }}/0 scram-sha-256
{%- endfor %}

pg_ident:
- operator _daemon_ backup
authentication:
Expand Down
3 changes: 3 additions & 0 deletions tests/integration/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ async def test_config_parameters(ops_test: OpsTest, charm) -> None:
{
"instance_max_locks_per_transaction": ["-1", "64"]
}, # config option is between 64 and 2147483647
{
"instance_password_encryption": [test_string, "md5"]
}, # config option is one of `md5` or `scram-sha-256`
{
"instance_password_encryption": [test_string, "scram-sha-256"]
}, # config option is one of `md5` or `scram-sha-256`
Expand Down
2 changes: 2 additions & 0 deletions tests/unit/test_charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -1163,6 +1163,7 @@ class _MockSnap:
no_peers=False,
user_databases_map={"operator": "all", "replication": "all", "rewind": "all"},
slots=None,
instance_password_encryption="scram-sha-256",
)
_handle_postgresql_restart_need.assert_called_once_with()
_restart_ldap_sync_service.assert_called_once()
Expand Down Expand Up @@ -1194,6 +1195,7 @@ class _MockSnap:
no_peers=False,
user_databases_map={"operator": "all", "replication": "all", "rewind": "all"},
slots=None,
instance_password_encryption="scram-sha-256",
)
_handle_postgresql_restart_need.assert_called_once()
_restart_ldap_sync_service.assert_called_once()
Expand Down
6 changes: 5 additions & 1 deletion tests/unit/test_cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ def test_render_patroni_yml_file(peers_ips, patroni):
raft_password = "fake-raft-password"
patroni_password = "fake-patroni-password"
postgresql_version = "16"
instance_password_encryption = "scram-sha-256"

# Get the expected content from a file.
with open("templates/patroni.yml.j2") as file:
Expand All @@ -331,6 +332,7 @@ def test_render_patroni_yml_file(peers_ips, patroni):
synchronous_node_count=0,
raft_password=raft_password,
patroni_password=patroni_password,
instance_password_encryption=instance_password_encryption,
)

# Setup a mock for the `open` method, set returned data to patroni.yml template.
Expand All @@ -340,7 +342,9 @@ def test_render_patroni_yml_file(peers_ips, patroni):
# Patch the `open` method with our mock.
with patch("builtins.open", mock, create=True):
# Call the method.
patroni.render_patroni_yml_file()
patroni.render_patroni_yml_file(
instance_password_encryption=instance_password_encryption
)

# Check the template is opened read-only in the call to open.
assert mock.call_args_list[0][0] == ("templates/patroni.yml.j2",)
Expand Down
Loading