diff --git a/docs/source/backends/zerotier.rst b/docs/source/backends/zerotier.rst index 046aabd79..25d925734 100644 --- a/docs/source/backends/zerotier.rst +++ b/docs/source/backends/zerotier.rst @@ -323,7 +323,7 @@ Example: server_config = { "id": ["9536600adf654321"], - "name": "zerotier-openwisp-network", + "name": "ow_zt", } client_config = OpenWrt.zerotier_auto_client( nwid=server_config['id'], name=server_config['name'] @@ -336,9 +336,10 @@ Will be rendered as: package zerotier - config zerotier 'zerotier_openwisp_network' + config zerotier 'ow_zt' option enabled '1' list join '9536600adf654321' + option secret '{{zt_identity_secret}}' .. note:: @@ -362,3 +363,49 @@ configuration settings, please refer to the following OpenAPI API specifications - `ZeroTier Service (schema: ControllerNetwork) `_ - `ZeroTier Central (schema: NetworkConfig) `_ + +Advanced configuration +~~~~~~~~~~~~~~~~~~~~~~ + +The OpenWRT ZeroTier service can be configured to run on multiple ports, +for example, **9993 (default)** and **9994**. This can be achieved by creating +a file named ``zt_local.conf`` in a persistent filesystem location, such as +``/etc/config/zt_local.conf``, and then adding the option ``local_conf`` +to the ZeroTier UCI configuration. + +``/etc/config/zt_local.conf`` + +.. code-block:: json + + { + "settings": { + "primaryPort": 9994 + } + } + +``/etc/config/zerotier`` + +.. code-block:: text + + package zerotier + + # This config utilizes port 9993 (default) + + config zerotier 'ow_zt1' + option enabled '1' + list join '9536600adf654321' + option secret '{{zt_identity_secret}}' + + # This config utilizes port 9994 + + config zerotier 'ow_zt2' (new) + option enabled '1' + list join '9536600adf654322' + option secret '{{zt_identity_secret}}' + option local_conf '/etc/config/zerotier.local.conf' + + +**More information** + +- `ZeroTier Controller Local Configuration `_ +- `OpenWRT ZeroTier Advance Configuration `_ diff --git a/netjsonconfig/backends/openwrt/converters/zerotier.py b/netjsonconfig/backends/openwrt/converters/zerotier.py index eb9c37495..00e3d9914 100644 --- a/netjsonconfig/backends/openwrt/converters/zerotier.py +++ b/netjsonconfig/backends/openwrt/converters/zerotier.py @@ -20,7 +20,7 @@ def __intermediate_vpn(self, vpn): def __netjson_vpn(self, vpn): vpn['id'] = vpn.pop('join') - vpn['name'] = vpn.pop('.name').replace('_', '-') + vpn['name'] = vpn.pop('.name') # 'disabled' defaults to False in OpenWRT vpn['disabled'] = vpn.pop('enabled', '0') == '0' del vpn['.type'] diff --git a/netjsonconfig/backends/zerotier/zerotier.py b/netjsonconfig/backends/zerotier/zerotier.py index 87c9f53ce..7cd9623e7 100644 --- a/netjsonconfig/backends/zerotier/zerotier.py +++ b/netjsonconfig/backends/zerotier/zerotier.py @@ -15,10 +15,17 @@ class ZeroTier(BaseVpnBackend): config_suffix = config_suffix @classmethod - def auto_client(cls, name='', nwid=None, disabled=False): + def auto_client( + cls, + name='ow_zt', + nwid=None, + identity_secret='{{zt_identity_secret}}', + disabled=False, + ): nwid = nwid or [''] return { 'id': nwid, 'name': name, + 'secret': identity_secret, 'disabled': disabled, } diff --git a/tests/openwrt/test_backend.py b/tests/openwrt/test_backend.py index 77b30d9f8..b0f98d6f3 100644 --- a/tests/openwrt/test_backend.py +++ b/tests/openwrt/test_backend.py @@ -548,14 +548,24 @@ def test_vxlan_wireguard_auto_client(self): def test_zerotier_auto_client(self): with self.subTest('No arguments provided'): - expected = {'zerotier': [{'id': [''], 'name': '', 'disabled': False}]} + expected = { + 'zerotier': [ + { + 'name': 'ow_zt', + 'id': [''], + 'secret': '{{zt_identity_secret}}', + 'disabled': False, + } + ] + } self.assertDictEqual(OpenWrt.zerotier_auto_client(), expected) with self.subTest('Required arguments provided'): expected = { 'zerotier': [ { + 'name': 'ow_zt', 'id': ['9536600adf654321'], - 'name': 'zerotier-openwisp-network', + 'secret': '{{zt_identity_secret}}', 'disabled': False, } ] @@ -563,7 +573,6 @@ def test_zerotier_auto_client(self): self.assertDictEqual( OpenWrt.zerotier_auto_client( nwid=['9536600adf654321'], - name='zerotier-openwisp-network', ), expected, ) diff --git a/tests/openwrt/test_zerotier.py b/tests/openwrt/test_zerotier.py index a94b81a41..8ce33fa1c 100644 --- a/tests/openwrt/test_zerotier.py +++ b/tests/openwrt/test_zerotier.py @@ -6,21 +6,85 @@ class TestZeroTier(unittest.TestCase, _TabsMixin): maxDiff = None - _TEST_CONFIG = { + # This configuration is used when we want to join multiple networks + # and the ZT service is running on a single default port 9993 + _TEST_SAME_NAME_MULTIPLE_CONFIG = { "zerotier": [ { + "name": "ow_zt", "id": ["9536600adf654321", "9536600adf654322"], - "name": "zerotier-openwisp-network", }, ] } + # This ZT configuration is used when ZT services + # are configured to run on multiple ports, e.g., 9993 and 9994. + # For more information, refer to: + # https://docs.zerotier.com/zerotier/zerotier.conf/#local-configuration-options + _TEST_DIFF_NAME_MULTIPLE_CONFIG = { + "zerotier": [ + { + "name": "ow_zt1", + "id": ["9536600adf654321"], + }, + { + "name": "ow_zt2", + "id": ["9536600adf654322"], + }, + ] + } + + def test_zt_multiple_render_diff_name(self): + o = OpenWrt(self._TEST_DIFF_NAME_MULTIPLE_CONFIG) + expected = self._tabs( + """package zerotier + +config zerotier 'ow_zt1' + option enabled '1' + list join '9536600adf654321' + +config zerotier 'ow_zt2' + option enabled '1' + list join '9536600adf654322' +""" + ) + self.assertEqual(o.render(), expected) + + def test_zt_mutiple_parse_diff_name(self): + native = self._tabs( + """package zerotier + +config zerotier 'ow_zt1' + option enabled '1' + list join '9536600adf654321' + +config zerotier 'ow_zt2' + option enabled '1' + list join '9536600adf654322' +""" + ) + expected = { + "zerotier": [ + { + "id": ["9536600adf654321"], + "name": "ow_zt1", + "disabled": False, + }, + { + "id": ["9536600adf654322"], + "name": "ow_zt2", + "disabled": False, + }, + ] + } + o = OpenWrt(native=native) + self.assertEqual(o.config, expected) - def test_render_zerotier(self): - o = OpenWrt(self._TEST_CONFIG) + def test_zt_multiple_render_same_name(self): + o = OpenWrt(self._TEST_SAME_NAME_MULTIPLE_CONFIG) expected = self._tabs( """package zerotier -config zerotier 'zerotier_openwisp_network' +config zerotier 'ow_zt' option enabled '1' list join '9536600adf654321' list join '9536600adf654322' @@ -28,11 +92,11 @@ def test_render_zerotier(self): ) self.assertEqual(o.render(), expected) - def test_parse_zerotier(self): + def test_zt_mutiple_parse_same_name(self): native = self._tabs( """package zerotier -config zerotier 'zerotier_openwisp_network' +config zerotier 'ow_zt' option enabled '0' list join '9536600adf654321' list join '9536600adf654322' @@ -42,7 +106,7 @@ def test_parse_zerotier(self): "zerotier": [ { "id": ["9536600adf654321", "9536600adf654322"], - "name": "zerotier-openwisp-network", + "name": "ow_zt", "disabled": True, }, ] diff --git a/tests/zerotier/test_backend.py b/tests/zerotier/test_backend.py index 177369250..7ff565bdf 100644 --- a/tests/zerotier/test_backend.py +++ b/tests/zerotier/test_backend.py @@ -385,15 +385,17 @@ def test_generate(self): def test_auto_client(self): expected = { + "name": "ow_zt", "id": ["9536600adf654321"], - "name": "zerotier-openwisp-network", + "secret": "test_secret", "disabled": False, } test_config = self._TEST_CONFIG["zerotier"][0] self.assertEqual( ZeroTier.auto_client( + name="ow_zt", nwid=[test_config['id']], - name=test_config['name'], + identity_secret="test_secret", ), expected, )