Skip to content

fix(utils): swallow ssl.SSLError from empty/corrupt CA bundle#187

Draft
marceloneppel wants to merge 1 commit into
16/edgefrom
fix/dpe-empty-ca-bundle-ssl
Draft

fix(utils): swallow ssl.SSLError from empty/corrupt CA bundle#187
marceloneppel wants to merge 1 commit into
16/edgefrom
fix/dpe-empty-ca-bundle-ssl

Conversation

@marceloneppel

@marceloneppel marceloneppel commented Jul 14, 2026

Copy link
Copy Markdown
Member

Issue

Scaling down a postgresql-k8s unit fails the storage-detaching hook with an uncaught exception:

File ".../single_kernel_postgresql/utils/__init__.py", line 163, in _httpx_get_request
    ssl_ctx.load_verify_locations(cafile=cafile)
ssl.SSLError: [X509: NO_CERTIFICATE_OR_CRL_FOUND] no certificate or crl found (_ssl.c:4146)

The unit is left in error and the data storage stays attached.

Solution

load_verify_locations raises FileNotFoundError when the CA bundle file is missing (already suppressed), but ssl.SSLError (NO_CERTIFICATE_OR_CRL_FOUND) when the file exists yet holds no certificates. The suppress(FileNotFoundError) guard did not catch the latter, so the error escaped parallel_patroni_get_requestcluster_statusget_primary (which only catches RetryError) and crashed the storage-detaching hook.

An empty CA bundle can arise at storage-detaching time: the charm touches an empty /tmp/peer_ca_bundle.pem on _on_start and rewrites it from get_peer_ca_bundle(), which returns "" while the unit's TLS material is being torn down.

Broaden the guard to also swallow ssl.SSLError, so a missing OR certless bundle degrades to an unreachable request (returns None) instead of propagating — matching the degradation the original suppress was reaching for. Adds a regression test asserting an empty CA bundle no longer crashes parallel_patroni_get_request.

Checklist

  • I have added or updated any relevant documentation.
  • I have cleaned any remaining cloud resources from my accounts.

load_verify_locations raises FileNotFoundError when the CA bundle file is
absent (already suppressed), but ssl.SSLError (NO_CERTIFICATE_OR_CRL_FOUND)
when the file exists yet holds no certificates. The suppress(FileNotFoundError)
guard did not catch the latter, so the error escaped
parallel_patroni_get_request -> cluster_status -> get_primary (which only
catches RetryError) and crashed the storage-detaching hook during scale-down,
leaving the unit in error and the data storage attached.

An empty CA bundle can arise at storage-detaching time because the charm
touches an empty /tmp/peer_ca_bundle.pem on _on_start and rewrites it from
get_peer_ca_bundle(), which returns "" while the unit's TLS material is being
torn down. Treat a missing OR certless bundle as "cannot verify this endpoint"
and degrade to an unreachable request (returns None) rather than propagating.

Signed-off-by: Marcelo Henrique Neppel <marcelo.neppel@canonical.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant