Skip to content

Commit 38ceda6

Browse files
Update mysql and s3_helpers charm lib to include secret related fixes (#403)
1 parent 433e5e0 commit 38ceda6

File tree

3 files changed

+54
-21
lines changed

3 files changed

+54
-21
lines changed

lib/charms/mysql/v0/mysql.py

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ def wait_until_mysql_connection(self) -> None:
9999
PEER,
100100
ROOT_PASSWORD_KEY,
101101
ROOT_USERNAME,
102+
SECRET_KEY_FALLBACKS,
102103
SERVER_CONFIG_PASSWORD_KEY,
103104
SERVER_CONFIG_USERNAME,
104105
)
@@ -114,7 +115,7 @@ def wait_until_mysql_connection(self) -> None:
114115

115116
# Increment this PATCH version before using `charmcraft publish-lib` or reset
116117
# to 0 if you are raising the major API version
117-
LIBPATCH = 56
118+
LIBPATCH = 57
118119

119120
UNIT_TEARDOWN_LOCKNAME = "unit-teardown"
120121
UNIT_ADD_LOCKNAME = "unit-add"
@@ -411,8 +412,8 @@ def __init__(self, *args):
411412
additional_secret_fields=[
412413
"key",
413414
"csr",
414-
"cert",
415-
"cauth",
415+
"certificate",
416+
"certificate-authority",
416417
"chain",
417418
],
418419
secret_field_name=SECRET_INTERNAL_LABEL,
@@ -580,6 +581,13 @@ def has_cos_relation(self) -> bool:
580581

581582
return len(active_cos_relations) > 0
582583

584+
def peer_relation_data(self, scope: Scopes) -> DataPeer:
585+
"""Returns the peer relation data per scope."""
586+
if scope == APP_SCOPE:
587+
return self.peer_relation_app
588+
elif scope == UNIT_SCOPE:
589+
return self.peer_relation_unit
590+
583591
def get_secret(
584592
self,
585593
scope: Scopes,
@@ -591,11 +599,15 @@ def get_secret(
591599
Else retrieve from peer databag. This is to account for cases where secrets are stored in
592600
peer databag but the charm is then refreshed to a newer revision.
593601
"""
602+
if scope not in get_args(Scopes):
603+
raise ValueError("Unknown secret scope")
604+
594605
peers = self.model.get_relation(PEER)
595-
if scope == APP_SCOPE:
596-
value = self.peer_relation_app.fetch_my_relation_field(peers.id, key)
597-
else:
598-
value = self.peer_relation_unit.fetch_my_relation_field(peers.id, key)
606+
if not (value := self.peer_relation_data(scope).fetch_my_relation_field(peers.id, key)):
607+
if key in SECRET_KEY_FALLBACKS:
608+
value = self.peer_relation_data(scope).fetch_my_relation_field(
609+
peers.id, SECRET_KEY_FALLBACKS[key]
610+
)
599611
return value
600612

601613
def set_secret(self, scope: Scopes, key: str, value: Optional[str]) -> None:
@@ -607,24 +619,30 @@ def set_secret(self, scope: Scopes, key: str, value: Optional[str]) -> None:
607619
raise MySQLSecretError("Can only set app secrets on the leader unit")
608620

609621
if not value:
610-
return self.remove_secret(scope, key)
622+
if key in SECRET_KEY_FALLBACKS:
623+
self.remove_secret(scope, SECRET_KEY_FALLBACKS[key])
624+
self.remove_secret(scope, key)
625+
return
611626

612627
peers = self.model.get_relation(PEER)
613-
if scope == APP_SCOPE:
614-
self.peer_relation_app.update_relation_data(peers.id, {key: value})
615-
elif scope == UNIT_SCOPE:
616-
self.peer_relation_unit.update_relation_data(peers.id, {key: value})
628+
629+
fallback_key_to_secret_key = {v: k for k, v in SECRET_KEY_FALLBACKS.items()}
630+
if key in fallback_key_to_secret_key:
631+
if self.peer_relation_data(scope).fetch_my_relation_field(peers.id, key):
632+
self.remove_secret(scope, key)
633+
self.peer_relation_data(scope).update_relation_data(
634+
peers.id, {fallback_key_to_secret_key[key]: value}
635+
)
636+
else:
637+
self.peer_relation_data(scope).update_relation_data(peers.id, {key: value})
617638

618639
def remove_secret(self, scope: Scopes, key: str) -> None:
619640
"""Removing a secret."""
620641
if scope not in get_args(Scopes):
621642
raise RuntimeError("Unknown secret scope.")
622643

623644
peers = self.model.get_relation(PEER)
624-
if scope == APP_SCOPE:
625-
self.peer_relation_app.delete_relation_data(peers.id, [key])
626-
else:
627-
self.peer_relation_unit.delete_relation_data(peers.id, [key])
645+
self.peer_relation_data(scope).delete_relation_data(peers.id, [key])
628646

629647

630648
class MySQLMemberState(str, enum.Enum):
@@ -2617,3 +2635,8 @@ def _run_mysqlcli_script(
26172635
timeout: (optional) time before the query should timeout
26182636
"""
26192637
raise NotImplementedError
2638+
2639+
@abstractmethod
2640+
def reset_data_dir(self) -> None:
2641+
"""Reset the data directory."""
2642+
raise NotImplementedError

lib/charms/mysql/v0/s3_helpers.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131

3232
# Increment this PATCH version before using `charmcraft publish-lib` or reset
3333
# to 0 if you are raising the major API version
34-
LIBPATCH = 7
34+
LIBPATCH = 8
3535

3636
# botocore/urllib3 clutter the logs when on debug
3737
logging.getLogger("botocore").setLevel(logging.WARNING)
@@ -50,17 +50,17 @@ def upload_content_to_s3(content: str, content_path: str, s3_parameters: Dict) -
5050
5151
Returns: a boolean indicating success.
5252
"""
53+
ca_file = None
5354
try:
5455
logger.info(f"Uploading content to bucket={s3_parameters['bucket']}, path={content_path}")
55-
ca_file = tempfile.NamedTemporaryFile()
5656
session = boto3.session.Session(
5757
aws_access_key_id=s3_parameters["access-key"],
5858
aws_secret_access_key=s3_parameters["secret-key"],
5959
region_name=s3_parameters["region"] or None,
6060
)
6161
verif = True
62-
ca_chain = s3_parameters.get("tls-ca-chain")
63-
if ca_chain:
62+
if ca_chain := s3_parameters.get("tls-ca-chain"):
63+
ca_file = tempfile.NamedTemporaryFile()
6464
ca = "\n".join([base64.b64decode(s).decode() for s in ca_chain])
6565
ca_file.write(ca.encode())
6666
ca_file.flush()
@@ -86,7 +86,8 @@ def upload_content_to_s3(content: str, content_path: str, s3_parameters: Dict) -
8686
)
8787
return False
8888
finally:
89-
ca_file.close()
89+
if ca_file:
90+
ca_file.close()
9091

9192
return True
9293

src/constants.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,12 @@
4949
COS_AGENT_RELATION_NAME = "metrics-endpoint"
5050
LOG_ROTATE_CONFIG_FILE = "/etc/logrotate.d/flush_mysql_logs"
5151
ROOT_SYSTEM_USER = "root"
52+
SECRET_KEY_FALLBACKS = {
53+
"root-password": "root_password",
54+
"server-config-password": "server_config_password",
55+
"cluster-admin-password": "cluster_admin_password",
56+
"monitoring-password": "monitoring_password",
57+
"backups-password": "backups_password",
58+
"certificate": "cert",
59+
"certificate-authority": "ca",
60+
}

0 commit comments

Comments
 (0)