From e99df4d664c54d0b189fc3b9b6747c5763426cd4 Mon Sep 17 00:00:00 2001 From: Aaron Johnson <4023+aaronjohnson@users.noreply.github.com> Date: Wed, 30 Oct 2024 11:58:01 -0700 Subject: [PATCH 1/6] Update examples.md with clean up a node in Python Document the several steps in code which are required to both deauthorize and remove the secret required during a _logout_. --- docs/api/central/examples.md | 104 ++++++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 3 deletions(-) diff --git a/docs/api/central/examples.md b/docs/api/central/examples.md index 922421b..98e683c 100644 --- a/docs/api/central/examples.md +++ b/docs/api/central/examples.md @@ -11,7 +11,7 @@ In the examples below use the following placeholder variables to match commonly- - `$ZT_TOKEN`: an API token associated with an active account on [Central](https://my.zerotier.com) - `$NWID`: an active network ID -Please note, if you encounter an error, System.String and System.Collections.IDictionary when using curl within Powershell, be advised this is because of an _alias_ which can leads to a less than obvious error message. `curl` in PowerShell is a wrapper for `Invoke-WebRequest` which has different parameter syntax than `curl` on non-windows operating systems. As an alternative solution to using `Invoke-WebRequest`, `curl.exe` could be used. This however may not be available on your system without first installing. The _native_ approach is to use `Invoke-WebRequest`. Caveat emptor. +Please note, if you encounter an error, System.String and System.Collections.IDictionary when using curl within Powershell, be advised this is because of an _alias_ which lead to a less than obvious error message. `curl` in PowerShell is a wrapper for `Invoke-WebRequest` which has different parameter syntax than `curl` on non-windows operating systems. As an alternative solution to using `Invoke-WebRequest`, use `curl.exe`. This however may not be available on your system without first installing. The _native_ approach on Microsoft Windows is to use `Invoke-WebRequest`. Caveat emptor. :::info See the [Central API Tokens](/api/tokens) guide for an explanation of how to create and manage API tokens. @@ -31,7 +31,7 @@ Each of them will fetch network information and produce CSV as output. You can t defaultValue="list-networks" values={[ {label: 'Networks', value: 'list-networks'}, - {label: 'Network Members', value: 'list-members'} + {label: 'Network Members', value: 'list-members'}, ]}> @@ -140,7 +140,8 @@ If you want to save the output to a file, you can add `| Out-File -FilePath "out defaultValue="authorize-member" values={[ {label: 'Authorize Member', value: 'authorize-member'}, - {label: 'Deauthorize Member', value: 'deauthorize-member'} + {label: 'Deauthorize Member', value: 'deauthorize-member'}, + {label: 'Clean up a node', value: 'clean-up-a-node'} ]}> @@ -186,6 +187,8 @@ curl -H "Authorization: token $ZT_TOKEN" -X POST \ --data '{"config": {"authorized": false}}' ``` +In addition to notifying Central with this API call, and in order to not require waiting until the current credentials expire, the ZeroTierOne service needs to be stopped and the authtoken.secret needs to be removed. The API call in addition to the removal of the local secret file prevents incremental billing to increase unbounded in cases of repeat auth/deauth use cases. Also note, the deauthorize is required per individual network within an organization the node is present. + ### Deauthorize a network member ( Powershell Invoke-WebRequest ) ```code @@ -207,6 +210,101 @@ Invoke-WebRequest -Uri "https://api.zerotier.com/api/v1/network/$NWID/member/$ME -Method Post -Headers $headers -Body $body -ContentType "application/json" ``` +In addition to notifying Central with this API call, and in order to not require waiting until the current credentials expire, the ZeroTierOne service needs to be stopped and the authtoken.secret needs to be removed. The API call in addition to the removal of the local secret file prevents incremental billing to increase unbounded in cases of repeat auth/deauth use cases. Also note, the deauthorize is required per individual network within an organization the node is present. + + + + + +### Cleanup a node ( Python ) + +```code +import os +import requests +import subprocess +import time +import sys + +def cleanup_zerotier_node(api_token, node_id, network_ids): + """ + Comprehensive cleanup of a ZeroTier node: + 1. Deauthorize from each network + 2. Stop ZeroTier service + 3. Remove auth token + 4. Restart ZeroTier service + """ + # Base URL for ZeroTier Central API + base_url = "https://api.zerotier.com/api/v1" + headers = { + "Authorization": f"Bearer {api_token}" + } + + # 1. Deauthorize from each network + for network_id in network_ids: + url = f"{base_url}/network/{network_id}/member/{node_id}" + try: + requests.delete(url, headers=headers) + print(f"Deauthorized from network {network_id}") + except Exception as e: + print(f"Error deauthorizing from network {network_id}: {e}") + + # 2. Stop ZeroTier service + try: + if os.name == 'nt': # Windows + subprocess.run(['net', 'stop', 'ZeroTierOne'], check=True) + else: # Linux/MacOS + subprocess.run(['sudo', 'systemctl', 'stop', 'zerotier-one'], check=True) + print("ZeroTier service stopped") + except Exception as e: + print(f"Error stopping ZeroTier service: {e}") + + # 3. Remove authtoken.secret + try: + if os.name == 'nt': + token_path = r'C:\ProgramData\ZeroTier\One\authtoken.secret' + else: + token_path = '/var/lib/zerotier-one/authtoken.secret' + + if os.path.exists(token_path): + os.remove(token_path) + print("Removed authtoken.secret") + except Exception as e: + print(f"Error removing authtoken.secret: {e}") + + # 4. Restart ZeroTier service + try: + time.sleep(2) # Brief pause before restart + if os.name == 'nt': # Windows + subprocess.run(['net', 'start', 'ZeroTierOne'], check=True) + else: # Linux/MacOS + subprocess.run(['sudo', 'systemctl', 'start', 'zerotier-one'], check=True) + print("ZeroTier service restarted") + except Exception as e: + print(f"Error restarting ZeroTier service: {e}") + +# Example usage +if __name__ == "__main__": + # Read required environment variables + API_TOKEN = os.getenv('ZEROTIER_API_TOKEN') + NODE_ID = os.getenv('ZEROTIER_NODE_ID') + + # Validate environment variables + if not API_TOKEN: + print("Error: ZEROTIER_API_TOKEN environment variable is not set") + sys.exit(1) + if not NODE_ID: + print("Error: ZEROTIER_NODE_ID environment variable is not set") + sys.exit(1) + + # Network IDs can be passed as command line arguments + NETWORK_IDS = sys.argv[1:] if len(sys.argv) > 1 else [] + if not NETWORK_IDS: + print("Warning: No network IDs provided. Please provide network IDs as command line arguments.") + sys.exit(1) + + cleanup_zerotier_node(API_TOKEN, NODE_ID, NETWORK_IDS) +``` + From 4b44a6c54064f037e7439ce4ea5f14687e0d7f2b Mon Sep 17 00:00:00 2001 From: Aaron Johnson <4023+aaronjohnson@users.noreply.github.com> Date: Wed, 30 Oct 2024 16:17:15 -0700 Subject: [PATCH 2/6] Update examples.md identity.secret _not_ authtoken.secret --- docs/api/central/examples.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/docs/api/central/examples.md b/docs/api/central/examples.md index 98e683c..f6fe570 100644 --- a/docs/api/central/examples.md +++ b/docs/api/central/examples.md @@ -210,13 +210,20 @@ Invoke-WebRequest -Uri "https://api.zerotier.com/api/v1/network/$NWID/member/$ME -Method Post -Headers $headers -Body $body -ContentType "application/json" ``` -In addition to notifying Central with this API call, and in order to not require waiting until the current credentials expire, the ZeroTierOne service needs to be stopped and the authtoken.secret needs to be removed. The API call in addition to the removal of the local secret file prevents incremental billing to increase unbounded in cases of repeat auth/deauth use cases. Also note, the deauthorize is required per individual network within an organization the node is present. - -### Cleanup a node ( Python ) +In addition to notifying Central with an API call, and in order to not require waiting until the current credentials expire, the ZeroTierOne service can to be stopped, authtoken.secret removed, and service restarted. For example, on a device which is shared and requires each user to provide separate SSO credentials to access the network. +This also prevents unbounded incremental billing in repeat auth/deauth use cases. + +NB: the deauthorize is required per individual network within an organization the node is present. + +### logout immediately ( Python ) + +Here be dragons. + +Below are additional steps which will cause a node to immediately no longer be on a network. This is _only_ required when calling the Central API and waiting to let the change propagate to all nodes is not fast enough. This is only required when network access needs to be halted immediately. ```code import os @@ -261,9 +268,9 @@ def cleanup_zerotier_node(api_token, node_id, network_ids): # 3. Remove authtoken.secret try: if os.name == 'nt': - token_path = r'C:\ProgramData\ZeroTier\One\authtoken.secret' + token_path = r'C:\ProgramData\ZeroTier\One\identity.secret' else: - token_path = '/var/lib/zerotier-one/authtoken.secret' + token_path = '/var/lib/zerotier-one/identity.secret' if os.path.exists(token_path): os.remove(token_path) From 1ee4c22273b094ed637bc3fba4c64e3e7a83490d Mon Sep 17 00:00:00 2001 From: Aaron Johnson <4023+aaronjohnson@users.noreply.github.com> Date: Wed, 30 Oct 2024 16:27:15 -0700 Subject: [PATCH 3/6] Update examples.md Add link to troubleshooting reset-node-id --- docs/api/central/examples.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/api/central/examples.md b/docs/api/central/examples.md index f6fe570..d911117 100644 --- a/docs/api/central/examples.md +++ b/docs/api/central/examples.md @@ -225,6 +225,8 @@ Here be dragons. Below are additional steps which will cause a node to immediately no longer be on a network. This is _only_ required when calling the Central API and waiting to let the change propagate to all nodes is not fast enough. This is only required when network access needs to be halted immediately. +For more information, see Troubleshooting [reset-node-id](/troubleshooting#reset-node-id). + ```code import os import requests From 8ee04afebc0f144e0ec0e61f01575287ccc6a171 Mon Sep 17 00:00:00 2001 From: Aaron Johnson <4023+aaronjohnson@users.noreply.github.com> Date: Wed, 30 Oct 2024 16:28:47 -0700 Subject: [PATCH 4/6] Update examples.md --- docs/api/central/examples.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api/central/examples.md b/docs/api/central/examples.md index d911117..bcc33e0 100644 --- a/docs/api/central/examples.md +++ b/docs/api/central/examples.md @@ -141,7 +141,7 @@ If you want to save the output to a file, you can add `| Out-File -FilePath "out values={[ {label: 'Authorize Member', value: 'authorize-member'}, {label: 'Deauthorize Member', value: 'deauthorize-member'}, - {label: 'Clean up a node', value: 'clean-up-a-node'} + {label: 'Logout', value: 'logout'} ]}> @@ -212,7 +212,7 @@ Invoke-WebRequest -Uri "https://api.zerotier.com/api/v1/network/$NWID/member/$ME - + In addition to notifying Central with an API call, and in order to not require waiting until the current credentials expire, the ZeroTierOne service can to be stopped, authtoken.secret removed, and service restarted. For example, on a device which is shared and requires each user to provide separate SSO credentials to access the network. This also prevents unbounded incremental billing in repeat auth/deauth use cases. From d8a3c329044fd0448328bd498c0d8bfc5c905c6a Mon Sep 17 00:00:00 2001 From: Aaron Johnson <4023+aaronjohnson@users.noreply.github.com> Date: Wed, 30 Oct 2024 16:32:13 -0700 Subject: [PATCH 5/6] Update examples.md separate logout from auth/deauth --- docs/api/central/examples.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/api/central/examples.md b/docs/api/central/examples.md index bcc33e0..9af03fc 100644 --- a/docs/api/central/examples.md +++ b/docs/api/central/examples.md @@ -141,7 +141,6 @@ If you want to save the output to a file, you can add `| Out-File -FilePath "out values={[ {label: 'Authorize Member', value: 'authorize-member'}, {label: 'Deauthorize Member', value: 'deauthorize-member'}, - {label: 'Logout', value: 'logout'} ]}> @@ -187,8 +186,6 @@ curl -H "Authorization: token $ZT_TOKEN" -X POST \ --data '{"config": {"authorized": false}}' ``` -In addition to notifying Central with this API call, and in order to not require waiting until the current credentials expire, the ZeroTierOne service needs to be stopped and the authtoken.secret needs to be removed. The API call in addition to the removal of the local secret file prevents incremental billing to increase unbounded in cases of repeat auth/deauth use cases. Also note, the deauthorize is required per individual network within an organization the node is present. - ### Deauthorize a network member ( Powershell Invoke-WebRequest ) ```code @@ -212,9 +209,18 @@ Invoke-WebRequest -Uri "https://api.zerotier.com/api/v1/network/$NWID/member/$ME + + + + -In addition to notifying Central with an API call, and in order to not require waiting until the current credentials expire, the ZeroTierOne service can to be stopped, authtoken.secret removed, and service restarted. For example, on a device which is shared and requires each user to provide separate SSO credentials to access the network. +In addition to notifying Central with an API call, and in order to not require waiting until the current credentials expire, the ZeroTierOne service can to be stopped, identity.secret file removed, and service restarted. For example, on a device which is shared and requires each user to provide separate SSO credentials to access the network. This also prevents unbounded incremental billing in repeat auth/deauth use cases. NB: the deauthorize is required per individual network within an organization the node is present. From db58590c27f130b85ca41d1637a5a4bf0a143d81 Mon Sep 17 00:00:00 2001 From: Aaron Johnson <4023+aaronjohnson@users.noreply.github.com> Date: Wed, 30 Oct 2024 16:33:28 -0700 Subject: [PATCH 6/6] Update examples.md remove tailing comma --- docs/api/central/examples.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api/central/examples.md b/docs/api/central/examples.md index 9af03fc..2c12a4d 100644 --- a/docs/api/central/examples.md +++ b/docs/api/central/examples.md @@ -31,7 +31,7 @@ Each of them will fetch network information and produce CSV as output. You can t defaultValue="list-networks" values={[ {label: 'Networks', value: 'list-networks'}, - {label: 'Network Members', value: 'list-members'}, + {label: 'Network Members', value: 'list-members'} ]}> @@ -140,7 +140,7 @@ If you want to save the output to a file, you can add `| Out-File -FilePath "out defaultValue="authorize-member" values={[ {label: 'Authorize Member', value: 'authorize-member'}, - {label: 'Deauthorize Member', value: 'deauthorize-member'}, + {label: 'Deauthorize Member', value: 'deauthorize-member'} ]}>