From 55e82469e841aa2e9acac3a8940077ea8d42b150 Mon Sep 17 00:00:00 2001 From: Frode Nordahl Date: Wed, 12 May 2021 10:36:37 +0200 Subject: [PATCH] ovsdb-subordinate: Provide chassis certificates to principal Enable the ovsdb-subordinate interface to provide chassis certificates to principal. This is useful for related charms providing payloads that expect direct communication with the OVN databases. While a principal and subordinate charm executes in the same environment, the payload usually execute under different service accounts and as such it is impractical and may be less secure to attempt to provide direct on-disk file access. Related-Bug: #1918271 Change-Id: I867817dfa7dd43cdb9035af87cbac3371dff13a5 --- src/ovsdb_subordinate/provides.py | 26 +++++++++++++++++++ src/ovsdb_subordinate/requires.py | 12 +++++++++ unit_tests/test_ovsdb_subordinate_provides.py | 10 +++++++ unit_tests/test_ovsdb_subordinate_requires.py | 7 +++++ 4 files changed, 55 insertions(+) diff --git a/src/ovsdb_subordinate/provides.py b/src/ovsdb_subordinate/provides.py index b8d374f..3cf8da7 100644 --- a/src/ovsdb_subordinate/provides.py +++ b/src/ovsdb_subordinate/provides.py @@ -67,6 +67,32 @@ class OVSDBSubordinateProvides(Endpoint): for relation in self.relations: relation.to_publish['ovn-configured'] = ovn_configured + def publish_chassis_certificates(self, ca_cert, certificate, private_key): + """Publish the chassis certificates. + + This is useful for related charms providing payloads that expect direct + communication with the OVN databases. + + While a principal and subordinate charm executes in the same + environment, the payload usually execute under different service + accounts and as such it is impractical and may be less secure to + attempt to provide direct on-disk file access. + + :param ca_cert: CA Certificate data + :type ca_cert: str + :param certificate: Certificate data + :type certificate: str + :param private_key: Private key data + :type private_key: str + :returns: Nothing, method called for its side effect + """ + for relation in self.relations: + relation.to_publish['chassis-certificates'] = { + 'ca_cert': ca_cert, + 'certificate': certificate, + 'private_key': private_key, + } + @property def interface_requests(self): """Retrieve current interface requests diff --git a/src/ovsdb_subordinate/requires.py b/src/ovsdb_subordinate/requires.py index 4245e02..239cee4 100644 --- a/src/ovsdb_subordinate/requires.py +++ b/src/ovsdb_subordinate/requires.py @@ -48,6 +48,18 @@ class OVSDBSubordinateRequires(Endpoint): """ return self.all_joined_units.received.get('ovn-configured', False) + @property + def chassis_certificates(self): + """Retrieve chassis certificates from relation data + + :returns: Certificate data + {'ca_cert': '-----BEGIN ...', + 'certificate': '-----BEGIN ...', + 'private_key': '-----BEGIN ...'} + :rtype: Dict[str,str] + """ + return self.all_joined_units.received.get('chassis-certificates', {}) + def _add_interface_request(self, bridge, ifname, ifdata): """Retrieve interface requests from relation and add/update requests diff --git a/unit_tests/test_ovsdb_subordinate_provides.py b/unit_tests/test_ovsdb_subordinate_provides.py index 8f94409..53f3815 100644 --- a/unit_tests/test_ovsdb_subordinate_provides.py +++ b/unit_tests/test_ovsdb_subordinate_provides.py @@ -142,3 +142,13 @@ class TestOVSDBSubordinateProvides(test_utils.PatchHelper): 'some-relation.interfaces.new_requests') self.clear_flag.assert_called_once_with( 'endpoint.some-relation.changed.create-interfaces') + + def test_publish_chassis_certificates(self): + to_publish = self.patch_topublish() + self.target.publish_chassis_certificates('a', 'b', 'c') + to_publish.__setitem__.assert_called_once_with( + 'chassis-certificates', { + 'ca_cert': 'a', + 'certificate': 'b', + 'private_key': 'c', + }) diff --git a/unit_tests/test_ovsdb_subordinate_requires.py b/unit_tests/test_ovsdb_subordinate_requires.py index 169b48a..de10c09 100644 --- a/unit_tests/test_ovsdb_subordinate_requires.py +++ b/unit_tests/test_ovsdb_subordinate_requires.py @@ -149,3 +149,10 @@ class TestOVSDBSubordinateRequires(test_utils.PatchHelper): 'some-relation.interfaces.created') self.clear_flag.assert_called_once_with( 'endpoint.some-relation.changed.interfaces-created') + + def test_chassis_certificates(self): + self.patch_target('_all_joined_units') + self._all_joined_units.received.get.return_value = {'fake': 'cert'} + self.assertEquals(self.target.chassis_certificates, {'fake': 'cert'}) + self._all_joined_units.received.get.assert_called_once_with( + 'chassis-certificates', {})