Skip to content

Commit

Permalink
[Fix] Add subject and ingress address to subject alt names (#39)
Browse files Browse the repository at this point in the history
  • Loading branch information
gboutry authored Sep 19, 2023
1 parent c70f037 commit 05dcf27
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 24 deletions.
32 changes: 27 additions & 5 deletions src/charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def __init__(
super().__init__(self.message)


def generate_vault_certificates(subject: str, sans_ip: str) -> Tuple[str, str, str]:
def generate_vault_certificates(subject: str, sans_ip: List[str]) -> Tuple[str, str, str]:
"""Generate Vault certificates valid for 50 years.
Returns:
Expand All @@ -73,7 +73,9 @@ def generate_vault_certificates(subject: str, sans_ip: str) -> Tuple[str, str, s
validity=365 * 50,
)
vault_private_key = generate_private_key()
csr = generate_csr(private_key=vault_private_key, subject=subject, sans_ip=[sans_ip])
csr = generate_csr(
private_key=vault_private_key, subject=subject, sans_ip=sans_ip, sans_dns=[subject]
)
vault_certificate = generate_certificate(
ca=ca_certificate,
ca_key=ca_private_key,
Expand Down Expand Up @@ -121,8 +123,10 @@ def _on_install(self, event: InstallEvent):
self.unit.status = WaitingStatus("Waiting for peer relation to be created")
event.defer()
return
if not self._bind_address:
self.unit.status = WaitingStatus("Waiting for bind address to be available")
if not self._bind_address or not self._ingress_address:
self.unit.status = WaitingStatus(
"Waiting for bind and ingress addresses to be available"
)
event.defer()
return
self.unit.status = MaintenanceStatus("Initializing vault")
Expand All @@ -136,7 +140,7 @@ def _on_install(self, event: InstallEvent):
logger.info("Vault certificate secret not set in peer relation")
private_key, certificate, ca_certificate = generate_vault_certificates(
subject=self._certificate_subject,
sans_ip=self._bind_address,
sans_ip=[self._bind_address, self._ingress_address],
)
self._set_certificates_secret_in_peer_relation(
private_key=private_key, certificate=certificate, ca_certificate=ca_certificate
Expand Down Expand Up @@ -430,6 +434,24 @@ def _bind_address(self) -> Optional[str]:
except ModelError:
return None

@property
def _ingress_address(self) -> Optional[str]:
"""Fetches ingress address from peer relation and returns it.
Returns:
str: Ingress address
"""
peer_relation = self.model.get_relation(PEER_RELATION_NAME)
if not peer_relation:
return None
try:
binding = self.model.get_binding(peer_relation)
if not binding:
return None
return str(binding.network.ingress_address)
except ModelError:
return None

@property
def _vault_layer(self) -> Layer:
"""Returns pebble layer to start Vault.
Expand Down
83 changes: 64 additions & 19 deletions tests/unit/test_charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@


class MockNetwork:
def __init__(self, bind_address: str):
def __init__(self, bind_address: str, ingress_address: str):
self.bind_address = bind_address
self.ingress_address = ingress_address


class MockBinding:
def __init__(self, bind_address: str):
self.network = MockNetwork(bind_address=bind_address)
def __init__(self, bind_address: str, ingress_address: str):
self.network = MockNetwork(bind_address=bind_address, ingress_address=ingress_address)


class TestCharm(unittest.TestCase):
Expand Down Expand Up @@ -120,7 +121,7 @@ def test_given_peer_relation_not_created_when_install_then_status_is_waiting(sel
)

@patch("ops.model.Model.get_binding")
def test_given_bind_address_not_available_when_install_then_status_is_waiting(
def test_given_binding_addresses_not_available_when_install_then_status_is_waiting(
self, patch_get_binding
):
self._set_peer_relation()
Expand All @@ -132,7 +133,7 @@ def test_given_bind_address_not_available_when_install_then_status_is_waiting(

self.assertEqual(
self.harness.charm.unit.status,
WaitingStatus("Waiting for bind address to be available"),
WaitingStatus("Waiting for bind and ingress addresses to be available"),
)

@patch("ops.model.Container.push", new=Mock)
Expand All @@ -141,7 +142,7 @@ def test_given_bind_address_not_available_when_install_then_status_is_waiting(
@patch("vault.Vault.initialize")
@patch("vault.Vault.is_api_available")
@patch("ops.model.Model.get_binding")
def test_given_binding_address_when_install_then_vault_is_initialized(
def test_given_binding_addresses_when_install_then_vault_is_initialized(
self,
patch_get_binding,
patch_is_api_available,
Expand All @@ -152,7 +153,10 @@ def test_given_binding_address_when_install_then_vault_is_initialized(
root_token = "root token content"
unseal_keys = ["unseal key 1"]
bind_address = "1.2.1.2"
patch_get_binding.return_value = MockBinding(bind_address=bind_address)
ingress_address = "10.1.0.1"
patch_get_binding.return_value = MockBinding(
bind_address=bind_address, ingress_address=ingress_address
)
patch_is_api_available.return_value = True
self.harness.set_leader(is_leader=True)
self.harness.set_can_connect(container=self.container_name, val=True)
Expand All @@ -170,11 +174,14 @@ def test_given_binding_address_when_install_then_vault_is_initialized(
@patch("vault.Vault.initialize")
@patch("vault.Vault.is_api_available")
@patch("ops.model.Model.get_binding")
def test_given_binding_address_when_install_then_pebble_is_planned(
def test_given_binding_addresses_when_install_then_pebble_is_planned(
self, patch_get_binding, patch_is_api_available, patch_vault_initialize
):
bind_address = "1.2.1.2"
patch_get_binding.return_value = MockBinding(bind_address=bind_address)
ingress_address = "10.1.0.1"
patch_get_binding.return_value = MockBinding(
bind_address=bind_address, ingress_address=ingress_address
)
patch_is_api_available.return_value = True
self.harness.set_leader(is_leader=True)
self.harness.set_can_connect(container=self.container_name, val=True)
Expand Down Expand Up @@ -227,7 +234,11 @@ def test_given_vault_not_available_when_install_then_status_is_waiting(
self._set_peer_relation()
self.harness.set_leader(is_leader=True)
self.harness.set_can_connect(container=self.container_name, val=True)
patch_get_binding.return_value = MockBinding(bind_address="1.2.1.2")
bind_address = "1.2.1.2"
ingress_address = "10.1.0.1"
patch_get_binding.return_value = MockBinding(
bind_address=bind_address, ingress_address=ingress_address
)
patch_is_api_available.return_value = False

self.harness.charm.on.install.emit()
Expand All @@ -254,7 +265,11 @@ def test_given_can_connect_when_install_then_certificate_secret_stored_in_peer_r
private_key = "private key content"
ca_certificate = "ca certificate content"
patch_generate_certs.return_value = private_key, certificate, ca_certificate
patch_get_binding.return_value = MockBinding(bind_address="1.2.1.2")
bind_address = "1.2.1.2"
ingress_address = "10.1.0.1"
patch_get_binding.return_value = MockBinding(
bind_address=bind_address, ingress_address=ingress_address
)
patch_is_api_available.return_value = True
patch_vault_initialize.return_value = "root token content", "unseal key content"
relation_id = self._set_peer_relation()
Expand Down Expand Up @@ -292,7 +307,11 @@ def test_given_can_connect_when_install_then_certificate_pushed_to_workload(
private_key = "private key content"
ca_certificate = "ca certificate content"
patch_generate_certs.return_value = private_key, certificate, ca_certificate
patch_get_binding.return_value = MockBinding(bind_address="1.2.1.2")
bind_address = "1.2.1.2"
ingress_address = "10.1.0.1"
patch_get_binding.return_value = MockBinding(
bind_address=bind_address, ingress_address=ingress_address
)
patch_is_api_available.return_value = True
patch_vault_initialize.return_value = "root token content", "unseal key content"
self._set_peer_relation()
Expand Down Expand Up @@ -337,7 +356,11 @@ def test_given_certificates_pushed_when_install_then_certificate_not_pushed_to_w
StringIO(ca_certificate),
]
patch_generate_certs.return_value = private_key, certificate, ca_certificate
patch_get_binding.return_value = MockBinding(bind_address="1.2.1.2")
bind_address = "1.2.1.2"
ingress_address = "10.1.0.1"
patch_get_binding.return_value = MockBinding(
bind_address=bind_address, ingress_address=ingress_address
)
patch_is_api_available.return_value = True
patch_vault_initialize.return_value = "root token content", "unseal key content"
self._set_peer_relation()
Expand Down Expand Up @@ -417,6 +440,7 @@ def test_given_initialization_secret_is_stored_when_config_changed_then_pebble_p
patch_get_binding,
):
bind_address = "1.2.3.4"
ingress_address = "10.1.0.1"
patch_vault_is_sealed.return_value = False
patch_is_api_available.return_value = True
patch_is_initialized.return_value = True
Expand All @@ -434,7 +458,9 @@ def test_given_initialization_secret_is_stored_when_config_changed_then_pebble_p
private_key="private key content",
ca_certificate="ca certificate content",
)
patch_get_binding.return_value = MockBinding(bind_address=bind_address)
patch_get_binding.return_value = MockBinding(
bind_address=bind_address, ingress_address=ingress_address
)

self.harness.charm.on.config_changed.emit()

Expand Down Expand Up @@ -505,7 +531,11 @@ def test_given_initialization_secret_is_stored_when_config_changed_then_status_i
private_key="private key content",
ca_certificate="ca certificate content",
)
patch_get_binding.return_value = MockBinding(bind_address="1.2.3.4")
bind_address = "1.2.3.4"
ingress_address = "10.1.0.1"
patch_get_binding.return_value = MockBinding(
bind_address=bind_address, ingress_address=ingress_address
)

self.harness.charm.on.config_changed.emit()

Expand Down Expand Up @@ -544,7 +574,11 @@ def test_given_vault_is_sealed_when_config_changed_then_vault_is_unsealed(
private_key="private key content",
ca_certificate="ca certificate content",
)
patch_get_binding.return_value = MockBinding(bind_address="1.2.3.4")
bind_address = "1.2.3.4"
ingress_address = "10.1.0.1"
patch_get_binding.return_value = MockBinding(
bind_address=bind_address, ingress_address=ingress_address
)

self.harness.charm.on.config_changed.emit()

Expand Down Expand Up @@ -583,7 +617,11 @@ def test_given_vault_api_not_available_when_config_changed_then_status_is_waitin
relation_id=peer_relation_id,
unit_name=other_unit_name,
)
patch_get_binding.return_value = MockBinding(bind_address="1.2.3.4")
bind_address = "1.2.3.4"
ingress_address = "10.1.0.1"
patch_get_binding.return_value = MockBinding(
bind_address=bind_address, ingress_address=ingress_address
)

self.harness.charm.on.config_changed.emit()

Expand Down Expand Up @@ -626,7 +664,11 @@ def test_given_vault_is_not_initialized_when_config_changed_then_status_is_waiti
relation_id=peer_relation_id,
unit_name=other_unit_name,
)
patch_get_binding.return_value = MockBinding(bind_address="1.2.3.4")
bind_address = "1.2.3.4"
ingress_address = "10.1.0.1"
patch_get_binding.return_value = MockBinding(
bind_address=bind_address, ingress_address=ingress_address
)

self.harness.charm.on.config_changed.emit()

Expand Down Expand Up @@ -751,7 +793,10 @@ def test_given_node_in_raft_when_on_remove_then_node_is_removed_from_raft(
):
patch_get_num_raft_peers.return_value = 2
bind_address = "1.2.3.4"
patch_get_binding.return_value = MockBinding(bind_address=bind_address)
ingress_address = "10.1.0.1"
patch_get_binding.return_value = MockBinding(
bind_address=bind_address, ingress_address=ingress_address
)
self.harness.set_can_connect(container=self.container_name, val=True)
patch_is_api_available.return_value = True
patch_is_node_in_raft_peers.return_value = True
Expand Down

0 comments on commit 05dcf27

Please sign in to comment.