Skip to content
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

[DPE-5932] Remove cert-available check for CA rotation #502

Merged
merged 9 commits into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from 7 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
35 changes: 21 additions & 14 deletions lib/charms/opensearch/v0/opensearch_tls.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,23 +210,30 @@ def _on_certificate_available(self, event: CertificateAvailableEvent) -> None:
if not self.charm.unit.is_leader() and scope == Scope.APP:
return

if not self.ca_rotation_complete_in_cluster():
phvalguima marked this conversation as resolved.
Show resolved Hide resolved
event.defer()
return

old_cert = secrets.get("cert", None)
ca_chain = "\n".join(event.chain[::-1])

self.charm.secrets.put_object(
scope,
cert_type.val,
{
"chain": ca_chain,
"cert": event.certificate,
"ca-cert": event.ca,
},
merge=True,
)
current_secret_obj = self.charm.secrets.get_object(scope, cert_type.val) or {}
secret = {
"chain": current_secret_obj.get("chain"),
"cert": current_secret_obj.get("cert"),
"ca-cert": current_secret_obj.get("ca-cert"),
}

if secret != {"chain": ca_chain, "cert": event.certificate, "ca-cert": event.ca}:
phvalguima marked this conversation as resolved.
Show resolved Hide resolved
# Juju is not able to check if secrets' content changed between revisions
# this IF is intended to reduce a storm of secret-removed/-changed events
# for the same content
self.charm.secrets.put_object(
scope,
cert_type.val,
{
"chain": ca_chain,
"cert": event.certificate,
"ca-cert": event.ca,
},
merge=True,
)

current_stored_ca = self.read_stored_ca()
if current_stored_ca != event.ca:
Expand Down
74 changes: 48 additions & 26 deletions tests/unit/lib/test_opensearch_tls.py
Original file line number Diff line number Diff line change
Expand Up @@ -1623,7 +1623,6 @@ def test_on_certificate_available_rotation_ongoing_on_this_unit(
)

self.harness.set_leader(is_leader=leader)
original_status = self.harness.model.unit.status

# This unit is within the process of certificate renewal
with self.harness.hooks_disabled():
Expand All @@ -1633,20 +1632,32 @@ def test_on_certificate_available_rotation_ongoing_on_this_unit(

self.charm.tls._on_certificate_available(self.charm.on.certificate_available)

# No action taken, no change on status or certificates
assert run_cmd.call_count == 0
assert self.harness.model.unit.status == original_status
# exactly three run_cmd commands to be executed: checking the current CA for the
# admin cert, the unit_http cert and the unit_transport cert
if leader:
self.charm.on.certificate_available.defer.assert_called_once()
assert run_cmd.call_count == 3
assert self.harness.model.unit.status == MaintenanceStatus(
"Applying new CA certificate..."
)
assert self.secret_store.get_object(Scope.APP, CertType.APP_ADMIN.val) == {
"csr": csr,
"chain": "new_chain",
"keystore-password": "keystore_12345",
"truststore-password": "truststore_12345",
"ca-cert": "new_ca",
"cert": "new_cert",
}
else:
self.charm.on.certificate_available.defer.assert_not_called()
assert self.secret_store.get_object(Scope.APP, CertType.APP_ADMIN.val) == {
"csr": csr,
"keystore-password": "keystore_12345",
"truststore-password": "truststore_12345",
"ca-cert": "old_ca_cert",
"cert": "old_cert",
}
# We have scope == Scope.APP, so we will skip the entire logic
assert run_cmd.call_count == 0
assert self.harness.model.unit.status == MaintenanceStatus("")
assert self.secret_store.get_object(Scope.APP, CertType.APP_ADMIN.val) == {
"csr": csr,
"keystore-password": "keystore_12345",
"truststore-password": "truststore_12345",
"ca-cert": "old_ca_cert",
"cert": "old_cert",
}

# Mock to investigate/compare/alter
@parameterized.expand(
Expand Down Expand Up @@ -1721,7 +1732,6 @@ def test_on_certificate_available_rotation_ongoing_on_another_unit(
)

self.harness.set_leader(is_leader=leader)
original_status = self.harness.model.unit.status

# This unit has updated CA certificate
# but another unit of the cluster is still within the process
Expand All @@ -1736,17 +1746,29 @@ def test_on_certificate_available_rotation_ongoing_on_another_unit(

self.charm.tls._on_certificate_available(self.charm.on.certificate_available)

# No action taken, no change on status or certificates
assert run_cmd.call_count == 0
assert self.harness.model.unit.status == original_status
# exactly three run_cmd commands to be executed: checking the current CA for the
# admin cert, the unit_http cert and the unit_transport cert
if leader:
self.charm.on.certificate_available.defer.assert_called_once()
assert run_cmd.call_count == 3
assert self.harness.model.unit.status == MaintenanceStatus(
"Applying new CA certificate..."
)
assert self.secret_store.get_object(Scope.APP, CertType.APP_ADMIN.val) == {
"csr": csr,
"chain": "new_chain",
"keystore-password": "keystore_12345",
"truststore-password": "truststore_12345",
"ca-cert": "new_ca",
"cert": "new_cert",
}
else:
self.charm.on.certificate_available.defer.assert_not_called()
assert self.secret_store.get_object(Scope.APP, CertType.APP_ADMIN.val) == {
"csr": csr,
"keystore-password": "keystore_12345",
"truststore-password": "truststore_12345",
"ca-cert": "old_ca_cert",
"cert": "old_cert",
}
# We have scope == Scope.APP, so we will skip the entire logic
assert run_cmd.call_count == 0
assert self.harness.model.unit.status == MaintenanceStatus("")
assert self.secret_store.get_object(Scope.APP, CertType.APP_ADMIN.val) == {
"csr": csr,
"keystore-password": "keystore_12345",
"truststore-password": "truststore_12345",
"ca-cert": "old_ca_cert",
"cert": "old_cert",
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@ _meta:

## Demo users

kibanaserver:
hash: $2b$12$UPS8q4bPIUaycBLIXPqcsOBcd/2BjDBY6opZYtPmJXjTmau6CmuLm
reserved: false
description: Kibanaserver user
admin:
hash: $2b$12$l3s/BwbEQwuvZrGOMN.7EeIuNSiU5c2FYSO/LZDOOCX4qCSmrWTT.
hash: $2b$12$Cts2k6vk.emW.E1mQN.B5u/5DfwKybaXFRREHfIwUs7RUHNp8h.c.
reserved: false
backend_roles:
- admin
opendistro_security_roles:
- security_rest_api_access
- all_access
description: Admin user
kibanaserver:
hash: $2b$12$0ZYW/CiICy1.7YXpRYDjeOLD75qnPAu4I3w5KXZmJvFp1rRiCm8qa
reserved: false
description: Kibanaserver user
Loading