Skip to content

Commit

Permalink
[DPE-2195] Add extra_sans config option (#62)
Browse files Browse the repository at this point in the history
  • Loading branch information
zmraul authored Sep 26, 2023
1 parent efd0d73 commit dfda5ad
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 1 deletion.
4 changes: 4 additions & 0 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,7 @@ options:
description: Specifies the enabled cipher suites to be used in ZooKeeper TLS negotiation (csv). Overrides any explicit value set via the zookeeper.ssl.ciphersuites system property (note the single word "ciphersuites"). The default value of null means the list of enabled cipher suites is determined by the Java runtime being used.
type: string
default: ""
certificate_extra_sans:
description: Config options to add extra-sans to the ones used when requesting server certificates. The extra-sans are specified by comma-separated names to be added when requesting signed certificates. Use "{unit}" as a placeholder to be filled with the unit number, e.g. "worker-{unit}" will be translated as "worker-0" for unit 0 and "worker-1" for unit 1 when requesting the certificate.
type: string
default: ""
1 change: 1 addition & 0 deletions src/structured_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class CharmConfig(BaseConfigModel):
ssl_cipher_suites: Optional[str]
replication_quota_window_num: int
zookeeper_ssl_cipher_suites: Optional[str]
certificate_extra_sans: Optional[str]

@validator("*", pre=True)
@classmethod
Expand Down
17 changes: 16 additions & 1 deletion src/tls.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,20 @@ def remove_stores(self) -> None:
logger.error(e.stdout)
raise

@property
def _extra_sans(self) -> List[str]:
"""Parse the certificate_extra_sans config option."""
extra_sans = self.charm.config.certificate_extra_sans or ""
parsed_sans = []

if extra_sans == "":
return parsed_sans

for sans in extra_sans.split(","):
parsed_sans.append(sans.replace("{unit}", self.charm.unit.name.split("/")[1]))

return parsed_sans

@property
def _sans(self) -> Dict[str, List[str]]:
"""Builds a SAN dict of DNS names and IPs for the unit."""
Expand All @@ -365,5 +379,6 @@ def _sans(self) -> Dict[str, List[str]]:
f"{self.charm.app.name}-{unit_id}",
f"{self.charm.app.name}-{unit_id}.{self.charm.app.name}-endpoints",
socket.getfqdn(),
],
]
+ self._extra_sans,
}
66 changes: 66 additions & 0 deletions tests/unit/test_tls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/usr/bin/env python3
# Copyright 2023 Canonical Ltd.
# See LICENSE file for licensing details.

from pathlib import Path

import pytest
import yaml
from ops.testing import Harness

from charm import KafkaK8sCharm
from literals import CHARM_KEY, PEER, ZOOKEEPER_REL_NAME

CONFIG = str(yaml.safe_load(Path("./config.yaml").read_text()))
ACTIONS = str(yaml.safe_load(Path("./actions.yaml").read_text()))
METADATA = str(yaml.safe_load(Path("./metadata.yaml").read_text()))


@pytest.fixture
def harness():
harness = Harness(KafkaK8sCharm, meta=METADATA)
harness.add_relation("restart", CHARM_KEY)
harness._update_config(
{
"log_retention_ms": "-1",
"compression_type": "producer",
}
)
harness.begin()

# Relate to ZK with tls enabled
zk_relation_id = harness.add_relation(ZOOKEEPER_REL_NAME, ZOOKEEPER_REL_NAME)
harness.add_relation_unit(zk_relation_id, "zookeeper/0")
harness.update_relation_data(
zk_relation_id,
harness.charm.app.name,
{
"username": "relation-1",
"password": "mellon",
"endpoints": "123.123.123",
"chroot": "/kafka",
"uris": "123.123.123/kafka",
"tls": "enabled",
},
)

return harness


def test_extra_sans_config(harness: Harness):
# Create peer relation
peer_relation_id = harness.add_relation(PEER, CHARM_KEY)
harness.update_relation_data(
peer_relation_id,
"kafka-k8s/0",
{"private-address": "treebeard", "tls": "enabled"},
)

harness.update_config({"certificate_extra_sans": ""})
assert harness.charm.tls._extra_sans == []

harness.update_config({"certificate_extra_sans": "worker{unit}.com"})
assert harness.charm.tls._extra_sans == ["worker0.com"]

harness.update_config({"certificate_extra_sans": "worker{unit}.com,{unit}.example"})
assert harness.charm.tls._extra_sans == ["worker0.com", "0.example"]

0 comments on commit dfda5ad

Please sign in to comment.