Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update examples.md with logout in Python #217

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 114 additions & 1 deletion docs/api/central/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -210,3 +210,116 @@ Invoke-WebRequest -Uri "https://api.zerotier.com/api/v1/network/$NWID/member/$ME
</TabItem>

</Tabs>

<Tabs
groupId="central-api-tasks-auth"
defaultValue="logout"
values={[
{label: 'Logout', value: 'logout'}
]}>

<TabItem value="logout">

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.

### 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.

For more information, see Troubleshooting [reset-node-id](/troubleshooting#reset-node-id).

```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\identity.secret'
else:
token_path = '/var/lib/zerotier-one/identity.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)
```

</TabItem>

</Tabs>
Loading