version 1.00 Zitinexus router enrollment script
This commit is contained in:
commit
361e07332a
|
|
@ -0,0 +1,395 @@
|
||||||
|
# Router Enrollment Script Installation Guide
|
||||||
|
|
||||||
|
This guide provides step-by-step instructions for installing and using the OpenZiti Router Enrollment Script on Ubuntu Linux systems.
|
||||||
|
|
||||||
|
## Quick Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Download the script package
|
||||||
|
wget https://your-portal.com/downloads/router-enrollment-script.tar.gz
|
||||||
|
|
||||||
|
# 2. Extract the package
|
||||||
|
tar -xzf router-enrollment-script.tar.gz
|
||||||
|
cd Router-enrollment-script
|
||||||
|
|
||||||
|
# 3. Make scripts executable
|
||||||
|
chmod +x *.sh
|
||||||
|
|
||||||
|
# 4. Run the enrollment script
|
||||||
|
sudo ./enroll-router.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Manual Installation
|
||||||
|
|
||||||
|
### Step 1: Download Files
|
||||||
|
|
||||||
|
Copy these files to your Ubuntu router machine:
|
||||||
|
- `enroll-router.sh` - Main enrollment script
|
||||||
|
- `test-enrollment.sh` - Testing script
|
||||||
|
- `config.sh` - Configuration file
|
||||||
|
- `README.md` - Documentation
|
||||||
|
|
||||||
|
### Step 2: Set Permissions
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chmod +x enroll-router.sh
|
||||||
|
chmod +x test-enrollment.sh
|
||||||
|
chmod +x config.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Configure (Optional)
|
||||||
|
|
||||||
|
Edit `config.sh` to customize settings:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nano config.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Key settings to modify:
|
||||||
|
- `DEFAULT_API_ENDPOINT` - Your ZitiNexus Portal API URL
|
||||||
|
- `CONFIG_DIR` - Router configuration directory
|
||||||
|
- `LOG_FILE` - Log file location
|
||||||
|
|
||||||
|
### Step 4: Test Prerequisites
|
||||||
|
|
||||||
|
Run the test script to verify system readiness:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./test-enrollment.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Select option 6 to run all tests.
|
||||||
|
|
||||||
|
### Step 5: Run Enrollment
|
||||||
|
|
||||||
|
Execute the main enrollment script:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo ./enroll-router.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
### System Requirements
|
||||||
|
|
||||||
|
- **Operating System**: Ubuntu 22.04, 24.04, or compatible Linux distribution
|
||||||
|
- **Architecture**: x86_64 (amd64) or ARM64
|
||||||
|
- **Memory**: Minimum 512MB RAM
|
||||||
|
- **Disk Space**: Minimum 100MB free space
|
||||||
|
- **Network**: Internet connectivity for downloads and API calls
|
||||||
|
|
||||||
|
### Required Permissions
|
||||||
|
|
||||||
|
- **Root Access**: Script must be run with `sudo`
|
||||||
|
- **Network Access**: Outbound HTTPS (port 443) to:
|
||||||
|
- ZitiNexus Portal API
|
||||||
|
- OpenZiti controller
|
||||||
|
- Package repositories
|
||||||
|
- OpenZiti installation sources
|
||||||
|
|
||||||
|
### Dependencies
|
||||||
|
|
||||||
|
The script will automatically install these if missing:
|
||||||
|
- `curl` - For API calls and downloads
|
||||||
|
- `jq` - For JSON processing
|
||||||
|
- `systemctl` - For service management (usually pre-installed)
|
||||||
|
|
||||||
|
## Configuration Options
|
||||||
|
|
||||||
|
### Basic Configuration
|
||||||
|
|
||||||
|
Edit the `DEFAULT_API_ENDPOINT` in `config.sh`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
DEFAULT_API_ENDPOINT="https://your-portal.example.com/api"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Advanced Configuration
|
||||||
|
|
||||||
|
Customize these settings in `config.sh`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Directory locations
|
||||||
|
CONFIG_DIR="/etc/zitirouter"
|
||||||
|
LOG_FILE="/var/log/ziti-router-enrollment.log"
|
||||||
|
|
||||||
|
# API settings
|
||||||
|
API_CONNECT_TIMEOUT=30
|
||||||
|
MAX_API_RETRIES=3
|
||||||
|
|
||||||
|
# Service settings
|
||||||
|
SERVICE_NAME="ziti-router"
|
||||||
|
SERVICE_RESTART_DELAY=5
|
||||||
|
```
|
||||||
|
|
||||||
|
### Environment-Specific Configuration
|
||||||
|
|
||||||
|
Create local configuration files:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# System-wide configuration
|
||||||
|
sudo mkdir -p /etc/zitirouter
|
||||||
|
sudo nano /etc/zitirouter/local.conf
|
||||||
|
|
||||||
|
# User-specific configuration
|
||||||
|
nano ~/.ziti-router-enrollment.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage Examples
|
||||||
|
|
||||||
|
### Basic Enrollment
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo ./enroll-router.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Follow the prompts:
|
||||||
|
1. Enter API endpoint (or press Enter for default)
|
||||||
|
2. Enter hash key from ZitiNexus Portal
|
||||||
|
|
||||||
|
### Testing Before Enrollment
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test system requirements
|
||||||
|
./test-enrollment.sh
|
||||||
|
|
||||||
|
# Select option 4: Test System Requirements
|
||||||
|
# Select option 1: Test API Connectivity
|
||||||
|
# Select option 3: Test API Registration Call (with real hash key)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Checking Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check router service status
|
||||||
|
systemctl status ziti-router
|
||||||
|
|
||||||
|
# View router logs
|
||||||
|
journalctl -u ziti-router -f
|
||||||
|
|
||||||
|
# Check configuration
|
||||||
|
cat /etc/zitirouter/router.yaml
|
||||||
|
|
||||||
|
# View enrollment log
|
||||||
|
tail -f /var/log/ziti-router-enrollment.log
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
#### 1. Permission Denied
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Error: Permission denied
|
||||||
|
sudo ./enroll-router.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Hash Key Not Found
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Error: Hash key not found
|
||||||
|
# Solution: Verify hash key from portal, check if expired (24h limit)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. API Connection Failed
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Error: API request failed with HTTP 000
|
||||||
|
# Check network connectivity
|
||||||
|
ping google.com
|
||||||
|
|
||||||
|
# Check API endpoint
|
||||||
|
curl -I https://your-portal.com/api/router/health
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4. OpenZiti Installation Failed
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Manual installation
|
||||||
|
curl -sSLf https://get.openziti.io/install.bash | sudo bash
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 5. Service Won't Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check service logs
|
||||||
|
journalctl -u ziti-router -n 50
|
||||||
|
|
||||||
|
# Check configuration syntax
|
||||||
|
sudo ziti router run /etc/zitirouter/router.yaml --dry-run
|
||||||
|
```
|
||||||
|
|
||||||
|
### Debug Mode
|
||||||
|
|
||||||
|
Enable debug mode for verbose output:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Edit config.sh
|
||||||
|
DEBUG_MODE=true
|
||||||
|
|
||||||
|
# Or set environment variable
|
||||||
|
export DEBUG_MODE=true
|
||||||
|
sudo -E ./enroll-router.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manual Cleanup
|
||||||
|
|
||||||
|
If enrollment fails and you need to start over:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Stop and remove service
|
||||||
|
sudo systemctl stop ziti-router
|
||||||
|
sudo systemctl disable ziti-router
|
||||||
|
sudo rm -f /etc/systemd/system/ziti-router.service
|
||||||
|
|
||||||
|
# Remove configuration
|
||||||
|
sudo rm -rf /etc/zitirouter/
|
||||||
|
|
||||||
|
# Reload systemd
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
```
|
||||||
|
|
||||||
|
## Network Configuration
|
||||||
|
|
||||||
|
### Firewall Rules
|
||||||
|
|
||||||
|
If using UFW (Ubuntu Firewall):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Allow outbound HTTPS
|
||||||
|
sudo ufw allow out 443/tcp
|
||||||
|
|
||||||
|
# Allow outbound HTTP (for package downloads)
|
||||||
|
sudo ufw allow out 80/tcp
|
||||||
|
```
|
||||||
|
|
||||||
|
If using iptables:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Allow outbound HTTPS
|
||||||
|
sudo iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT
|
||||||
|
sudo iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT
|
||||||
|
```
|
||||||
|
|
||||||
|
### Proxy Configuration
|
||||||
|
|
||||||
|
If behind a corporate proxy:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Set proxy environment variables
|
||||||
|
export http_proxy=http://proxy.company.com:8080
|
||||||
|
export https_proxy=http://proxy.company.com:8080
|
||||||
|
export no_proxy=localhost,127.0.0.1
|
||||||
|
|
||||||
|
# Run with proxy settings
|
||||||
|
sudo -E ./enroll-router.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
### File Permissions
|
||||||
|
|
||||||
|
The script sets these permissions:
|
||||||
|
- `/etc/zitirouter/`: 755 (readable by all, writable by root)
|
||||||
|
- `/etc/zitirouter/certs/`: 700 (accessible only by root)
|
||||||
|
- `/etc/zitirouter/router.yaml`: 644 (readable by all)
|
||||||
|
- `/etc/zitirouter/enrollment.jwt`: 600 (readable only by root)
|
||||||
|
|
||||||
|
### Service Security
|
||||||
|
|
||||||
|
The router service runs as root because:
|
||||||
|
- Requires access to system certificates
|
||||||
|
- Needs to bind to privileged network interfaces
|
||||||
|
- Must manage system-level network routing
|
||||||
|
|
||||||
|
### Hash Key Security
|
||||||
|
|
||||||
|
- Hash keys expire after 24 hours
|
||||||
|
- Each hash key can only be used once
|
||||||
|
- Hash keys are validated server-side
|
||||||
|
- Failed attempts are rate-limited
|
||||||
|
|
||||||
|
## Automation
|
||||||
|
|
||||||
|
### Non-Interactive Installation
|
||||||
|
|
||||||
|
For automated deployments, modify the script to accept parameters:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
# Custom wrapper script
|
||||||
|
|
||||||
|
API_ENDPOINT="${1:-https://portal.example.com/api}"
|
||||||
|
HASH_KEY="${2}"
|
||||||
|
|
||||||
|
if [[ -z "$HASH_KEY" ]]; then
|
||||||
|
echo "Usage: $0 [api_endpoint] <hash_key>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set environment variables
|
||||||
|
export API_ENDPOINT
|
||||||
|
export HASH_KEY
|
||||||
|
|
||||||
|
# Run enrollment script
|
||||||
|
./enroll-router.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuration Management
|
||||||
|
|
||||||
|
Use configuration management tools:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Ansible example
|
||||||
|
- name: Deploy router enrollment script
|
||||||
|
copy:
|
||||||
|
src: enroll-router.sh
|
||||||
|
dest: /tmp/enroll-router.sh
|
||||||
|
mode: '0755'
|
||||||
|
|
||||||
|
- name: Configure API endpoint
|
||||||
|
lineinfile:
|
||||||
|
path: /tmp/config.sh
|
||||||
|
regexp: '^DEFAULT_API_ENDPOINT='
|
||||||
|
line: 'DEFAULT_API_ENDPOINT="https://{{ portal_url }}/api"'
|
||||||
|
|
||||||
|
- name: Run enrollment
|
||||||
|
command: /tmp/enroll-router.sh
|
||||||
|
become: yes
|
||||||
|
```
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
### Log Files
|
||||||
|
|
||||||
|
Check these log files for troubleshooting:
|
||||||
|
- `/var/log/ziti-router-enrollment.log` - Enrollment process
|
||||||
|
- `journalctl -u ziti-router` - Router service logs
|
||||||
|
- `/var/log/syslog` - System logs
|
||||||
|
|
||||||
|
### Getting Help
|
||||||
|
|
||||||
|
1. **Check Documentation**: Review README.md and this guide
|
||||||
|
2. **Test Prerequisites**: Run `./test-enrollment.sh`
|
||||||
|
3. **Check Logs**: Review log files for error details
|
||||||
|
4. **Portal Support**: Contact your ZitiNexus Portal administrator
|
||||||
|
5. **OpenZiti Community**: Visit [OpenZiti Documentation](https://docs.openziti.io/)
|
||||||
|
|
||||||
|
### Reporting Issues
|
||||||
|
|
||||||
|
When reporting issues, include:
|
||||||
|
- Ubuntu version: `lsb_release -a`
|
||||||
|
- Script version: Check script header
|
||||||
|
- Error messages: From logs and console output
|
||||||
|
- Network configuration: Proxy, firewall settings
|
||||||
|
- Hash key status: From portal (without revealing the key)
|
||||||
|
|
||||||
|
## Version History
|
||||||
|
|
||||||
|
- **v1.0.0**: Initial release with full automation
|
||||||
|
- Hash key validation
|
||||||
|
- OpenZiti CLI installation
|
||||||
|
- Router configuration generation
|
||||||
|
- Systemd service creation
|
||||||
|
- Status reporting to portal
|
||||||
|
|
@ -0,0 +1,289 @@
|
||||||
|
# OpenZiti Router Enrollment Script
|
||||||
|
|
||||||
|
This script automates the enrollment of OpenZiti routers using hash keys from the ZitiNexus Portal. It's designed for Ubuntu 22.04, 24.04, and other Linux distributions.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The script performs the complete router enrollment process:
|
||||||
|
1. Validates hash key with ZitiNexus Portal
|
||||||
|
2. Downloads router configuration and JWT
|
||||||
|
3. Installs OpenZiti CLI if needed
|
||||||
|
4. Enrolls router with OpenZiti controller
|
||||||
|
5. Creates systemd service for automatic startup
|
||||||
|
6. Reports enrollment status back to portal
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Ubuntu 22.04, 24.04, or compatible Linux distribution
|
||||||
|
- Root access (script must be run with sudo)
|
||||||
|
- Internet connectivity
|
||||||
|
- Hash key from ZitiNexus Portal
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
1. **Get Hash Key**: Create a router enrollment in ZitiNexus Portal and copy the hash key
|
||||||
|
2. **Download Script**: Copy `enroll-router.sh` to your router machine
|
||||||
|
3. **Make Executable**: `chmod +x enroll-router.sh`
|
||||||
|
4. **Run Script**: `sudo ./enroll-router.sh`
|
||||||
|
5. **Follow Prompts**: Enter your portal API endpoint and hash key
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Make script executable
|
||||||
|
chmod +x enroll-router.sh
|
||||||
|
|
||||||
|
# Run the enrollment script
|
||||||
|
sudo ./enroll-router.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Interactive Prompts
|
||||||
|
|
||||||
|
The script will prompt for:
|
||||||
|
|
||||||
|
1. **ZitiNexus Portal API Endpoint**
|
||||||
|
- Default: `https://your-zitinexus-portal.com/api`
|
||||||
|
- Example: `https://portal.example.com/api`
|
||||||
|
|
||||||
|
2. **Router Enrollment Hash Key**
|
||||||
|
- 32-character hexadecimal string from ZitiNexus Portal
|
||||||
|
- Example: `a1b2c3d4e5f6789012345678901234567890abcd`
|
||||||
|
|
||||||
|
## What the Script Does
|
||||||
|
|
||||||
|
### 1. System Requirements Check
|
||||||
|
- Installs `curl` and `jq` if not present
|
||||||
|
- Verifies `systemctl` availability
|
||||||
|
- Checks for root privileges
|
||||||
|
|
||||||
|
### 2. OpenZiti CLI Installation
|
||||||
|
- Downloads and installs OpenZiti CLI from official source
|
||||||
|
- Adds to system PATH
|
||||||
|
- Verifies installation
|
||||||
|
|
||||||
|
### 3. Directory Setup
|
||||||
|
- Creates `/etc/zitirouter/` configuration directory
|
||||||
|
- Creates `/etc/zitirouter/certs/` for certificates
|
||||||
|
- Sets appropriate permissions
|
||||||
|
|
||||||
|
### 4. Router Registration
|
||||||
|
- Calls ZitiNexus Portal API with hash key
|
||||||
|
- Downloads JWT token and router configuration
|
||||||
|
- Implements retry logic for network issues
|
||||||
|
- Handles rate limiting
|
||||||
|
|
||||||
|
### 5. Router Enrollment
|
||||||
|
- Saves JWT and configuration files
|
||||||
|
- Runs `ziti edge enroll` command
|
||||||
|
- Generates router certificates
|
||||||
|
- Verifies successful enrollment
|
||||||
|
|
||||||
|
### 6. Service Setup
|
||||||
|
- Creates systemd service file
|
||||||
|
- Enables automatic startup
|
||||||
|
- Starts router service
|
||||||
|
- Verifies service is running
|
||||||
|
|
||||||
|
### 7. Status Reporting
|
||||||
|
- Reports successful enrollment to portal
|
||||||
|
- Includes system information (hostname, architecture, OS)
|
||||||
|
- Updates portal with router status
|
||||||
|
|
||||||
|
## File Locations
|
||||||
|
|
||||||
|
After successful enrollment:
|
||||||
|
|
||||||
|
```
|
||||||
|
/etc/zitirouter/
|
||||||
|
├── router.yaml # Router configuration
|
||||||
|
├── enrollment.jwt # JWT token (removed after enrollment)
|
||||||
|
└── certs/ # Router certificates
|
||||||
|
├── <router-name>.cert
|
||||||
|
├── <router-name>.key
|
||||||
|
├── <router-name>.server.chain.cert
|
||||||
|
└── <router-name>.cas
|
||||||
|
|
||||||
|
/etc/systemd/system/
|
||||||
|
└── ziti-router.service # Systemd service file
|
||||||
|
|
||||||
|
/var/log/
|
||||||
|
└── ziti-router-enrollment.log # Installation log
|
||||||
|
```
|
||||||
|
|
||||||
|
## Service Management
|
||||||
|
|
||||||
|
After enrollment, manage the router service with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check status
|
||||||
|
systemctl status ziti-router
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
journalctl -u ziti-router -f
|
||||||
|
|
||||||
|
# Stop router
|
||||||
|
systemctl stop ziti-router
|
||||||
|
|
||||||
|
# Start router
|
||||||
|
systemctl start ziti-router
|
||||||
|
|
||||||
|
# Restart router
|
||||||
|
systemctl restart ziti-router
|
||||||
|
|
||||||
|
# Disable auto-start
|
||||||
|
systemctl disable ziti-router
|
||||||
|
|
||||||
|
# Enable auto-start
|
||||||
|
systemctl enable ziti-router
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
1. **Hash Key Not Found**
|
||||||
|
```
|
||||||
|
ERROR: Hash key not found
|
||||||
|
```
|
||||||
|
- Verify hash key was copied correctly
|
||||||
|
- Check if hash key has expired (24-hour window)
|
||||||
|
- Ensure enrollment exists in portal
|
||||||
|
|
||||||
|
2. **API Connection Failed**
|
||||||
|
```
|
||||||
|
ERROR: API request failed with HTTP 000
|
||||||
|
```
|
||||||
|
- Check internet connectivity
|
||||||
|
- Verify API endpoint URL
|
||||||
|
- Check firewall rules for outbound HTTPS
|
||||||
|
|
||||||
|
3. **Hash Key Expired**
|
||||||
|
```
|
||||||
|
ERROR: Hash key has expired
|
||||||
|
```
|
||||||
|
- Create new router enrollment in portal
|
||||||
|
- Use new hash key within 24 hours
|
||||||
|
|
||||||
|
4. **OpenZiti Installation Failed**
|
||||||
|
```
|
||||||
|
ERROR: Failed to install OpenZiti CLI
|
||||||
|
```
|
||||||
|
- Check internet connectivity
|
||||||
|
- Verify system has sufficient disk space
|
||||||
|
- Try manual installation: `curl -sSLf https://get.openziti.io/install.bash | bash`
|
||||||
|
|
||||||
|
5. **Router Enrollment Failed**
|
||||||
|
```
|
||||||
|
ERROR: Router enrollment failed
|
||||||
|
```
|
||||||
|
- Check controller connectivity
|
||||||
|
- Verify JWT token is valid
|
||||||
|
- Check system time synchronization
|
||||||
|
|
||||||
|
6. **Service Won't Start**
|
||||||
|
```
|
||||||
|
WARNING: Router service may not be running properly
|
||||||
|
```
|
||||||
|
- Check service logs: `journalctl -u ziti-router -f`
|
||||||
|
- Verify configuration file: `cat /etc/zitirouter/router.yaml`
|
||||||
|
- Check certificate files exist
|
||||||
|
|
||||||
|
### Debug Information
|
||||||
|
|
||||||
|
View detailed logs:
|
||||||
|
```bash
|
||||||
|
# Script execution log
|
||||||
|
tail -f /var/log/ziti-router-enrollment.log
|
||||||
|
|
||||||
|
# Router service logs
|
||||||
|
journalctl -u ziti-router -f
|
||||||
|
|
||||||
|
# System logs
|
||||||
|
dmesg | tail
|
||||||
|
```
|
||||||
|
|
||||||
|
Check configuration:
|
||||||
|
```bash
|
||||||
|
# Verify router config
|
||||||
|
cat /etc/zitirouter/router.yaml
|
||||||
|
|
||||||
|
# Check certificates
|
||||||
|
ls -la /etc/zitirouter/certs/
|
||||||
|
|
||||||
|
# Test OpenZiti CLI
|
||||||
|
ziti version
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manual Cleanup
|
||||||
|
|
||||||
|
If enrollment fails and you need to start over:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Stop service
|
||||||
|
systemctl stop ziti-router 2>/dev/null || true
|
||||||
|
|
||||||
|
# Remove service
|
||||||
|
systemctl disable ziti-router 2>/dev/null || true
|
||||||
|
rm -f /etc/systemd/system/ziti-router.service
|
||||||
|
|
||||||
|
# Remove configuration
|
||||||
|
rm -rf /etc/zitirouter/
|
||||||
|
|
||||||
|
# Reload systemd
|
||||||
|
systemctl daemon-reload
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
- Script must run as root for system configuration
|
||||||
|
- Hash keys expire after 24 hours
|
||||||
|
- Certificates are stored with restricted permissions
|
||||||
|
- Service runs as root (required for router operations)
|
||||||
|
|
||||||
|
## Network Requirements
|
||||||
|
|
||||||
|
### Outbound Connections Required
|
||||||
|
|
||||||
|
- **ZitiNexus Portal API**: HTTPS (443) to your portal domain
|
||||||
|
- **OpenZiti Controller**: HTTPS (443) to controller cluster
|
||||||
|
- **Package Repositories**: HTTP/HTTPS (80/443) for apt packages
|
||||||
|
|
||||||
|
### Firewall Rules
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Allow outbound HTTPS (if using restrictive firewall)
|
||||||
|
iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT
|
||||||
|
iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT
|
||||||
|
```
|
||||||
|
|
||||||
|
## Advanced Usage
|
||||||
|
|
||||||
|
### Non-Interactive Mode
|
||||||
|
|
||||||
|
For automated deployments, you can modify the script to accept parameters:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Example modification (not included in base script)
|
||||||
|
API_ENDPOINT="https://portal.example.com/api"
|
||||||
|
HASH_KEY="your-hash-key-here"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom Configuration
|
||||||
|
|
||||||
|
The script uses these default paths:
|
||||||
|
- Config directory: `/etc/zitirouter/`
|
||||||
|
- Log file: `/var/log/ziti-router-enrollment.log`
|
||||||
|
- Service name: `ziti-router.service`
|
||||||
|
|
||||||
|
These can be modified by editing the script variables at the top.
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
For issues with:
|
||||||
|
- **Script functionality**: Check this README and logs
|
||||||
|
- **ZitiNexus Portal**: Contact your portal administrator
|
||||||
|
- **OpenZiti**: Visit [OpenZiti Documentation](https://docs.openziti.io/)
|
||||||
|
|
||||||
|
## Version History
|
||||||
|
|
||||||
|
- **v1.0.0**: Initial release with full enrollment automation
|
||||||
|
|
@ -0,0 +1,231 @@
|
||||||
|
# Router Enrollment Script Fixes Summary
|
||||||
|
|
||||||
|
## Issue Description
|
||||||
|
The router enrollment script was failing with two main errors:
|
||||||
|
1. **HTTP 404 Error**: API endpoint not found
|
||||||
|
2. **Unbound Variable Error**: `CALLBACK_URL: unbound variable`
|
||||||
|
|
||||||
|
## Root Cause Analysis
|
||||||
|
|
||||||
|
### 1. HTTP 404 Error
|
||||||
|
- **Problem**: Script was calling `/router/register` instead of `/api/router/register`
|
||||||
|
- **Cause**: Missing `/api` prefix in URL construction
|
||||||
|
- **Impact**: API calls were hitting non-existent endpoints
|
||||||
|
|
||||||
|
### 2. Unbound Variable Error
|
||||||
|
- **Problem**: Variables were not initialized before use
|
||||||
|
- **Cause**: When API calls failed, variables were never set but cleanup functions tried to use them
|
||||||
|
- **Impact**: Script crashed with "unbound variable" errors
|
||||||
|
|
||||||
|
## Fixes Implemented
|
||||||
|
|
||||||
|
### 1. API Endpoint URL Fix
|
||||||
|
**File**: `Router-enrollment-script/enroll-router.sh`
|
||||||
|
**Line**: ~208
|
||||||
|
|
||||||
|
**Before**:
|
||||||
|
```bash
|
||||||
|
local api_url="${API_ENDPOINT}/router/register"
|
||||||
|
```
|
||||||
|
|
||||||
|
**After**:
|
||||||
|
```bash
|
||||||
|
local api_url="${API_ENDPOINT}/api/router/register"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Impact**: Now correctly calls the backend API endpoint that matches the route structure:
|
||||||
|
- Backend route: `app.use('/api/router', require('./routes/routerRegistration'))`
|
||||||
|
- Router registration route: `router.post('/register', ...)`
|
||||||
|
- Final endpoint: `/api/router/register`
|
||||||
|
|
||||||
|
### 2. Default API Endpoint Update
|
||||||
|
**File**: `Router-enrollment-script/enroll-router.sh`
|
||||||
|
**Line**: ~25
|
||||||
|
|
||||||
|
**Before**:
|
||||||
|
```bash
|
||||||
|
DEFAULT_API_ENDPOINT="https://your-zitinexus-portal.com/api"
|
||||||
|
```
|
||||||
|
|
||||||
|
**After**:
|
||||||
|
```bash
|
||||||
|
DEFAULT_API_ENDPOINT="https://backend.zitinexus.com"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Impact**: Matches the nginx configuration that proxies `backend.zitinexus.com` to `localhost:5000`
|
||||||
|
|
||||||
|
### 3. Variable Initialization Fix
|
||||||
|
**File**: `Router-enrollment-script/enroll-router.sh`
|
||||||
|
**Lines**: ~26-36
|
||||||
|
|
||||||
|
**Added**:
|
||||||
|
```bash
|
||||||
|
# Initialize variables to prevent unbound variable errors
|
||||||
|
CALLBACK_URL=""
|
||||||
|
JWT=""
|
||||||
|
ROUTER_YAML=""
|
||||||
|
ROUTER_NAME=""
|
||||||
|
ROUTER_ID=""
|
||||||
|
TENANT_ID=""
|
||||||
|
CONTROLLER_ENDPOINT=""
|
||||||
|
ROLE_ATTRIBUTES=""
|
||||||
|
HASH_KEY=""
|
||||||
|
API_ENDPOINT=""
|
||||||
|
```
|
||||||
|
|
||||||
|
**Impact**: Prevents "unbound variable" errors when script fails early
|
||||||
|
|
||||||
|
### 4. Debug Logging Enhancement
|
||||||
|
**File**: `Router-enrollment-script/enroll-router.sh`
|
||||||
|
**Line**: ~213
|
||||||
|
|
||||||
|
**Added**:
|
||||||
|
```bash
|
||||||
|
# Debug: Show the URL being called
|
||||||
|
log "INFO" "API URL: $api_url"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Impact**: Makes troubleshooting easier by showing the exact URL being called
|
||||||
|
|
||||||
|
## Network Architecture Understanding
|
||||||
|
|
||||||
|
### Nginx Configuration
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name backend.zitinexus.com;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://localhost:5000;
|
||||||
|
# Direct proxy - no path modification
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Backend Route Structure
|
||||||
|
```javascript
|
||||||
|
// app.js
|
||||||
|
app.use('/api/router', require('./routes/routerRegistration'));
|
||||||
|
|
||||||
|
// routerRegistration.js
|
||||||
|
router.post('/register', async (req, res) => {
|
||||||
|
await controller.registerRouter(req, res);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Complete API Flow
|
||||||
|
1. **Script calls**: `https://backend.zitinexus.com/api/router/register`
|
||||||
|
2. **Nginx proxies to**: `http://localhost:5000/api/router/register`
|
||||||
|
3. **Backend routes to**: `routerRegistration.js` → `/register` handler
|
||||||
|
4. **Controller processes**: Router registration with hash key
|
||||||
|
|
||||||
|
## Expected API Response Structure
|
||||||
|
The script expects this JSON response format:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"data": {
|
||||||
|
"jwt": "eyJhbGciOiJSUzI1NiIs...",
|
||||||
|
"routerConfig": {
|
||||||
|
"yaml": "v: 3\nidentity:\n cert: ...",
|
||||||
|
"filename": "router.yaml",
|
||||||
|
"type": "private-edge"
|
||||||
|
},
|
||||||
|
"routerInfo": {
|
||||||
|
"id": "QNmKPk3Xgc",
|
||||||
|
"name": "virtech5378_sg-router1",
|
||||||
|
"roleAttributes": ["virtech5378_simplesrouter"],
|
||||||
|
"enrollmentExpiresAt": "2025-06-09T09:40:09.485Z",
|
||||||
|
"type": "private-edge"
|
||||||
|
},
|
||||||
|
"callbackUrl": "http://192.168.50.253:5000/api/router/enrollment-status",
|
||||||
|
"metadata": {
|
||||||
|
"tenantId": "cmb9m1hns0003p3jkk43zjlss",
|
||||||
|
"zitiRouterId": "QNmKPk3Xgc",
|
||||||
|
"routerType": "private-edge",
|
||||||
|
"controllerEndpoint": "enroll.zitinexus.com:443"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
### Test Script Created
|
||||||
|
**File**: `Router-enrollment-script/test-api-fix.sh`
|
||||||
|
|
||||||
|
This script tests:
|
||||||
|
- API URL construction
|
||||||
|
- Endpoint connectivity
|
||||||
|
- HTTP response codes
|
||||||
|
- Error handling
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
```bash
|
||||||
|
# On Linux (where the script will actually run):
|
||||||
|
chmod +x Router-enrollment-script/test-api-fix.sh
|
||||||
|
./Router-enrollment-script/test-api-fix.sh
|
||||||
|
|
||||||
|
# Main script usage:
|
||||||
|
sudo ./Router-enrollment-script/enroll-router.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Verification Steps
|
||||||
|
|
||||||
|
1. **API Endpoint Test**: The test script verifies the endpoint exists
|
||||||
|
2. **Variable Safety**: All variables are now initialized to prevent unbound errors
|
||||||
|
3. **Debug Output**: Script shows the exact URL being called for troubleshooting
|
||||||
|
4. **Error Handling**: Improved error messages for better debugging
|
||||||
|
|
||||||
|
## Expected Results
|
||||||
|
|
||||||
|
### Before Fix
|
||||||
|
```
|
||||||
|
[ERROR] API request failed with HTTP 404: Unknown error
|
||||||
|
[ERROR] Script failed with exit code 1
|
||||||
|
./enroll.sh: line 576: CALLBACK_URL: unbound variable
|
||||||
|
```
|
||||||
|
|
||||||
|
### After Fix
|
||||||
|
```
|
||||||
|
[INFO] API URL: https://backend.zitinexus.com/api/router/register
|
||||||
|
[INFO] Registering router with ZitiNexus Portal...
|
||||||
|
[SUCCESS] Router registered successfully: virtech5378_sg-router1 (ID: QNmKPk3Xgc)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Files Modified
|
||||||
|
|
||||||
|
1. **Router-enrollment-script/enroll-router.sh**
|
||||||
|
- Fixed API URL construction
|
||||||
|
- Updated default endpoint
|
||||||
|
- Added variable initialization
|
||||||
|
- Enhanced debug logging
|
||||||
|
|
||||||
|
2. **Router-enrollment-script/test-api-fix.sh** (New)
|
||||||
|
- Test script to verify fixes
|
||||||
|
- API connectivity testing
|
||||||
|
- Error code validation
|
||||||
|
|
||||||
|
## Compatibility
|
||||||
|
|
||||||
|
- **Linux**: Full compatibility (target environment)
|
||||||
|
- **Windows**: Script development and testing environment
|
||||||
|
- **Backend**: Compatible with existing nginx and Express.js setup
|
||||||
|
- **API**: Matches existing backend route structure
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
1. Test the script on a Linux environment with the hash key: `c3d00e5615464e0c02a7dcfcd56abc4e`
|
||||||
|
2. Verify the backend is running and accessible at `https://backend.zitinexus.com`
|
||||||
|
3. Ensure the router registration endpoint is properly configured
|
||||||
|
4. Monitor the enrollment process for any additional issues
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
✅ **Fixed**: HTTP 404 error by adding missing `/api` prefix
|
||||||
|
✅ **Fixed**: Unbound variable error by initializing all variables
|
||||||
|
✅ **Enhanced**: Debug logging for better troubleshooting
|
||||||
|
✅ **Updated**: Default endpoint to match production configuration
|
||||||
|
✅ **Created**: Test script for verification
|
||||||
|
|
||||||
|
The router enrollment script should now work correctly with the ZitiNexus backend API.
|
||||||
|
|
@ -0,0 +1,266 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Router Enrollment Script Configuration
|
||||||
|
# Edit these values to customize the enrollment process
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# API Configuration
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Default ZitiNexus Portal API endpoint
|
||||||
|
# Change this to your actual portal URL
|
||||||
|
DEFAULT_API_ENDPOINT="https://your-zitinexus-portal.com/api"
|
||||||
|
|
||||||
|
# API timeout settings (in seconds)
|
||||||
|
API_CONNECT_TIMEOUT=30
|
||||||
|
API_MAX_TIME=60
|
||||||
|
|
||||||
|
# Retry configuration
|
||||||
|
MAX_API_RETRIES=3
|
||||||
|
RETRY_DELAY_BASE=2 # Base delay for exponential backoff
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Directory and File Paths
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Router configuration directory
|
||||||
|
CONFIG_DIR="/etc/zitirouter"
|
||||||
|
|
||||||
|
# Certificates directory
|
||||||
|
CERTS_DIR="${CONFIG_DIR}/certs"
|
||||||
|
|
||||||
|
# Router configuration file
|
||||||
|
ROUTER_CONFIG="${CONFIG_DIR}/router.yaml"
|
||||||
|
|
||||||
|
# JWT token file
|
||||||
|
JWT_FILE="${CONFIG_DIR}/enrollment.jwt"
|
||||||
|
|
||||||
|
# Log file location
|
||||||
|
LOG_FILE="/var/log/ziti-router-enrollment.log"
|
||||||
|
|
||||||
|
# Systemd service file
|
||||||
|
SYSTEMD_SERVICE_FILE="/etc/systemd/system/ziti-router.service"
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# OpenZiti Configuration
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# OpenZiti CLI installation URL
|
||||||
|
ZITI_INSTALL_URL="https://get.openziti.io/install.bash"
|
||||||
|
|
||||||
|
# OpenZiti CLI binary path
|
||||||
|
ZITI_CLI_PATH="/usr/local/bin/ziti"
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Service Configuration
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Service name
|
||||||
|
SERVICE_NAME="ziti-router"
|
||||||
|
|
||||||
|
# Service user (must be root for router operations)
|
||||||
|
SERVICE_USER="root"
|
||||||
|
|
||||||
|
# Service restart delay (in seconds)
|
||||||
|
SERVICE_RESTART_DELAY=5
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Security Settings
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Directory permissions
|
||||||
|
CONFIG_DIR_PERMS=755
|
||||||
|
CERTS_DIR_PERMS=700
|
||||||
|
CONFIG_FILE_PERMS=644
|
||||||
|
JWT_FILE_PERMS=600
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Validation Settings
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Hash key validation pattern
|
||||||
|
HASH_KEY_PATTERN="^[a-fA-F0-9]{32}$"
|
||||||
|
|
||||||
|
# Required system commands
|
||||||
|
REQUIRED_COMMANDS=(
|
||||||
|
"curl"
|
||||||
|
"jq"
|
||||||
|
"systemctl"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Required directories for write access
|
||||||
|
REQUIRED_WRITE_DIRS=(
|
||||||
|
"/etc"
|
||||||
|
"/var/log"
|
||||||
|
"/etc/systemd/system"
|
||||||
|
)
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Network Configuration
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Test connectivity URLs
|
||||||
|
CONNECTIVITY_TEST_URLS=(
|
||||||
|
"https://get.openziti.io"
|
||||||
|
"https://github.com"
|
||||||
|
)
|
||||||
|
|
||||||
|
# DNS servers to test (optional)
|
||||||
|
DNS_TEST_SERVERS=(
|
||||||
|
"8.8.8.8"
|
||||||
|
"1.1.1.1"
|
||||||
|
)
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Logging Configuration
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Log level (DEBUG, INFO, WARNING, ERROR)
|
||||||
|
LOG_LEVEL="INFO"
|
||||||
|
|
||||||
|
# Maximum log file size (in MB)
|
||||||
|
MAX_LOG_SIZE=10
|
||||||
|
|
||||||
|
# Number of log files to keep
|
||||||
|
LOG_ROTATE_COUNT=5
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Advanced Settings
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Enable debug mode (set to true for verbose output)
|
||||||
|
DEBUG_MODE=false
|
||||||
|
|
||||||
|
# Enable dry run mode (set to true to simulate without making changes)
|
||||||
|
DRY_RUN=false
|
||||||
|
|
||||||
|
# Skip system requirements check (not recommended)
|
||||||
|
SKIP_REQUIREMENTS_CHECK=false
|
||||||
|
|
||||||
|
# Skip OpenZiti CLI installation if already present
|
||||||
|
SKIP_ZITI_INSTALL_IF_PRESENT=true
|
||||||
|
|
||||||
|
# Enable automatic cleanup on failure
|
||||||
|
AUTO_CLEANUP_ON_FAILURE=true
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Customization Functions
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Custom pre-enrollment hook
|
||||||
|
# This function is called before starting the enrollment process
|
||||||
|
pre_enrollment_hook() {
|
||||||
|
# Add custom logic here
|
||||||
|
# Example: Check additional requirements, send notifications, etc.
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Custom post-enrollment hook
|
||||||
|
# This function is called after successful enrollment
|
||||||
|
post_enrollment_hook() {
|
||||||
|
# Add custom logic here
|
||||||
|
# Example: Configure firewall, send notifications, etc.
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Custom error handler
|
||||||
|
# This function is called when an error occurs
|
||||||
|
error_handler() {
|
||||||
|
local error_message="$1"
|
||||||
|
local exit_code="$2"
|
||||||
|
|
||||||
|
# Add custom error handling logic here
|
||||||
|
# Example: Send alerts, cleanup resources, etc.
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Environment-Specific Overrides
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Load environment-specific configuration if it exists
|
||||||
|
if [[ -f "${CONFIG_DIR}/local.conf" ]]; then
|
||||||
|
source "${CONFIG_DIR}/local.conf"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Load user-specific configuration if it exists
|
||||||
|
if [[ -f "${HOME}/.ziti-router-enrollment.conf" ]]; then
|
||||||
|
source "${HOME}/.ziti-router-enrollment.conf"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Validation
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Validate configuration
|
||||||
|
validate_config() {
|
||||||
|
local errors=0
|
||||||
|
|
||||||
|
# Check API endpoint format
|
||||||
|
if [[ ! "$DEFAULT_API_ENDPOINT" =~ ^https?:// ]]; then
|
||||||
|
echo "ERROR: DEFAULT_API_ENDPOINT must start with http:// or https://" >&2
|
||||||
|
((errors++))
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check timeout values
|
||||||
|
if [[ ! "$API_CONNECT_TIMEOUT" =~ ^[0-9]+$ ]] || [[ "$API_CONNECT_TIMEOUT" -lt 1 ]]; then
|
||||||
|
echo "ERROR: API_CONNECT_TIMEOUT must be a positive integer" >&2
|
||||||
|
((errors++))
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! "$API_MAX_TIME" =~ ^[0-9]+$ ]] || [[ "$API_MAX_TIME" -lt 1 ]]; then
|
||||||
|
echo "ERROR: API_MAX_TIME must be a positive integer" >&2
|
||||||
|
((errors++))
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check directory paths
|
||||||
|
if [[ ! "$CONFIG_DIR" =~ ^/ ]]; then
|
||||||
|
echo "ERROR: CONFIG_DIR must be an absolute path" >&2
|
||||||
|
((errors++))
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! "$LOG_FILE" =~ ^/ ]]; then
|
||||||
|
echo "ERROR: LOG_FILE must be an absolute path" >&2
|
||||||
|
((errors++))
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check permissions
|
||||||
|
if [[ ! "$CONFIG_DIR_PERMS" =~ ^[0-7]{3}$ ]]; then
|
||||||
|
echo "ERROR: CONFIG_DIR_PERMS must be a valid octal permission (e.g., 755)" >&2
|
||||||
|
((errors++))
|
||||||
|
fi
|
||||||
|
|
||||||
|
return $errors
|
||||||
|
}
|
||||||
|
|
||||||
|
# Export all configuration variables
|
||||||
|
export DEFAULT_API_ENDPOINT
|
||||||
|
export API_CONNECT_TIMEOUT
|
||||||
|
export API_MAX_TIME
|
||||||
|
export MAX_API_RETRIES
|
||||||
|
export RETRY_DELAY_BASE
|
||||||
|
export CONFIG_DIR
|
||||||
|
export CERTS_DIR
|
||||||
|
export ROUTER_CONFIG
|
||||||
|
export JWT_FILE
|
||||||
|
export LOG_FILE
|
||||||
|
export SYSTEMD_SERVICE_FILE
|
||||||
|
export ZITI_INSTALL_URL
|
||||||
|
export ZITI_CLI_PATH
|
||||||
|
export SERVICE_NAME
|
||||||
|
export SERVICE_USER
|
||||||
|
export SERVICE_RESTART_DELAY
|
||||||
|
export CONFIG_DIR_PERMS
|
||||||
|
export CERTS_DIR_PERMS
|
||||||
|
export CONFIG_FILE_PERMS
|
||||||
|
export JWT_FILE_PERMS
|
||||||
|
export HASH_KEY_PATTERN
|
||||||
|
export LOG_LEVEL
|
||||||
|
export MAX_LOG_SIZE
|
||||||
|
export LOG_ROTATE_COUNT
|
||||||
|
export DEBUG_MODE
|
||||||
|
export DRY_RUN
|
||||||
|
export SKIP_REQUIREMENTS_CHECK
|
||||||
|
export SKIP_ZITI_INSTALL_IF_PRESENT
|
||||||
|
export AUTO_CLEANUP_ON_FAILURE
|
||||||
|
|
@ -0,0 +1,711 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# OpenZiti Router Enrollment Script
|
||||||
|
# Compatible with Ubuntu 22.04, 24.04 and other Linux distributions
|
||||||
|
# This script automates the router enrollment process using hash key
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Script configuration
|
||||||
|
SCRIPT_VERSION="1.0.0"
|
||||||
|
SCRIPT_NAME="OpenZiti Router Enrollment Script"
|
||||||
|
LOG_FILE="/var/log/ziti-router-enrollment.log"
|
||||||
|
CONFIG_DIR="/etc/zitirouter"
|
||||||
|
CERTS_DIR="${CONFIG_DIR}/certs"
|
||||||
|
ROUTER_CONFIG="${CONFIG_DIR}/router.yaml"
|
||||||
|
JWT_FILE="${CONFIG_DIR}/enrollment.jwt"
|
||||||
|
SYSTEMD_SERVICE_FILE="/etc/systemd/system/ziti-router.service"
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Default API endpoint (can be overridden)
|
||||||
|
DEFAULT_API_ENDPOINT="https://backend.zitinexus.com"
|
||||||
|
|
||||||
|
# Initialize variables to prevent unbound variable errors
|
||||||
|
CALLBACK_URL=""
|
||||||
|
JWT=""
|
||||||
|
ROUTER_YAML=""
|
||||||
|
ROUTER_NAME=""
|
||||||
|
ROUTER_ID=""
|
||||||
|
TENANT_ID=""
|
||||||
|
CONTROLLER_ENDPOINT=""
|
||||||
|
ROLE_ATTRIBUTES=""
|
||||||
|
HASH_KEY=""
|
||||||
|
API_ENDPOINT=""
|
||||||
|
|
||||||
|
# Logging function
|
||||||
|
log() {
|
||||||
|
local level=$1
|
||||||
|
shift
|
||||||
|
local message="$*"
|
||||||
|
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||||
|
echo "[$timestamp] [$level] $message" | tee -a "$LOG_FILE" >/dev/null 2>&1 || true
|
||||||
|
|
||||||
|
case $level in
|
||||||
|
"ERROR")
|
||||||
|
echo -e "${RED}[ERROR]${NC} $message" >&2
|
||||||
|
;;
|
||||||
|
"SUCCESS")
|
||||||
|
echo -e "${GREEN}[SUCCESS]${NC} $message"
|
||||||
|
;;
|
||||||
|
"WARNING")
|
||||||
|
echo -e "${YELLOW}[WARNING]${NC} $message"
|
||||||
|
;;
|
||||||
|
"INFO")
|
||||||
|
echo -e "${BLUE}[INFO]${NC} $message"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "$message"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Error handling
|
||||||
|
error_exit() {
|
||||||
|
log "ERROR" "$1"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if running as root
|
||||||
|
check_root() {
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
error_exit "This script must be run as root (use sudo)"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check system requirements
|
||||||
|
check_requirements() {
|
||||||
|
log "INFO" "Checking system requirements..."
|
||||||
|
|
||||||
|
# Check if curl is installed
|
||||||
|
if ! command -v curl &> /dev/null; then
|
||||||
|
log "INFO" "Installing curl..."
|
||||||
|
apt-get update && apt-get install -y curl || error_exit "Failed to install curl"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if jq is installed
|
||||||
|
if ! command -v jq &> /dev/null; then
|
||||||
|
log "INFO" "Installing jq..."
|
||||||
|
apt-get update && apt-get install -y jq || error_exit "Failed to install jq"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if systemctl is available
|
||||||
|
if ! command -v systemctl &> /dev/null; then
|
||||||
|
error_exit "systemctl is required but not available"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "SUCCESS" "System requirements check passed"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Install OpenZiti if not present
|
||||||
|
install_ziti() {
|
||||||
|
if command -v ziti &> /dev/null; then
|
||||||
|
local ziti_version=$(ziti version 2>/dev/null | head -n1 || echo "unknown")
|
||||||
|
log "INFO" "OpenZiti CLI already installed: $ziti_version"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "INFO" "Installing OpenZiti CLI using package repository..."
|
||||||
|
|
||||||
|
# Method 1: Use OpenZiti package repository (your preferred method)
|
||||||
|
log "INFO" "Setting up OpenZiti package repository..."
|
||||||
|
|
||||||
|
# Step 1: Add GPG key
|
||||||
|
if curl -sSLf https://get.openziti.io/tun/package-repos.gpg | gpg --dearmor --output /usr/share/keyrings/openziti.gpg; then
|
||||||
|
log "INFO" "GPG key added successfully"
|
||||||
|
else
|
||||||
|
error_exit "Failed to add OpenZiti GPG key"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Step 2: Set proper permissions
|
||||||
|
chmod a+r /usr/share/keyrings/openziti.gpg || error_exit "Failed to set GPG key permissions"
|
||||||
|
|
||||||
|
# Step 3: Add repository to sources list
|
||||||
|
tee /etc/apt/sources.list.d/openziti-release.list >/dev/null <<EOF
|
||||||
|
deb [signed-by=/usr/share/keyrings/openziti.gpg] https://packages.openziti.org/zitipax-openziti-deb-stable debian main
|
||||||
|
EOF
|
||||||
|
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
log "INFO" "Repository added successfully"
|
||||||
|
else
|
||||||
|
error_exit "Failed to add OpenZiti repository"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Step 4: Update package list
|
||||||
|
log "INFO" "Updating package list..."
|
||||||
|
if apt-get update; then
|
||||||
|
log "INFO" "Package list updated successfully"
|
||||||
|
else
|
||||||
|
error_exit "Failed to update package list"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Step 5: Install openziti-router package
|
||||||
|
log "INFO" "Installing openziti-router package..."
|
||||||
|
if apt-get install -y openziti-router; then
|
||||||
|
log "SUCCESS" "OpenZiti router package installed successfully"
|
||||||
|
else
|
||||||
|
log "WARNING" "Failed to install openziti-router package, trying fallback method..."
|
||||||
|
|
||||||
|
# Fallback: Try to install just the ziti CLI
|
||||||
|
log "INFO" "Attempting to install ziti CLI only..."
|
||||||
|
if apt-get install -y ziti; then
|
||||||
|
log "SUCCESS" "OpenZiti CLI installed successfully"
|
||||||
|
else
|
||||||
|
error_exit "Failed to install OpenZiti CLI from package repository"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify installation
|
||||||
|
if command -v ziti &> /dev/null; then
|
||||||
|
local ziti_version=$(ziti version 2>/dev/null | head -n1 || echo "unknown")
|
||||||
|
log "SUCCESS" "OpenZiti CLI installed successfully: $ziti_version"
|
||||||
|
else
|
||||||
|
error_exit "OpenZiti CLI installation failed - command not found after installation"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create necessary directories
|
||||||
|
create_directories() {
|
||||||
|
log "INFO" "Creating necessary directories..."
|
||||||
|
|
||||||
|
mkdir -p "$CONFIG_DIR" || error_exit "Failed to create config directory"
|
||||||
|
mkdir -p "$CERTS_DIR" || error_exit "Failed to create certs directory"
|
||||||
|
mkdir -p "$(dirname "$LOG_FILE")" || error_exit "Failed to create log directory"
|
||||||
|
|
||||||
|
# Set proper permissions
|
||||||
|
chmod 755 "$CONFIG_DIR"
|
||||||
|
chmod 700 "$CERTS_DIR"
|
||||||
|
|
||||||
|
log "SUCCESS" "Directories created successfully"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get user input
|
||||||
|
get_user_input() {
|
||||||
|
echo
|
||||||
|
echo "=============================================="
|
||||||
|
echo " $SCRIPT_NAME v$SCRIPT_VERSION"
|
||||||
|
echo "=============================================="
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Get API endpoint
|
||||||
|
read -p "Enter ZitiNexus Portal API endpoint [$DEFAULT_API_ENDPOINT]: " api_endpoint
|
||||||
|
API_ENDPOINT="${api_endpoint:-$DEFAULT_API_ENDPOINT}"
|
||||||
|
|
||||||
|
# Validate API endpoint format
|
||||||
|
if [[ ! "$API_ENDPOINT" =~ ^https?:// ]]; then
|
||||||
|
error_exit "API endpoint must start with http:// or https://"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get hash key
|
||||||
|
echo
|
||||||
|
echo "Enter the router enrollment hash key from ZitiNexus Portal:"
|
||||||
|
echo "(This is a 32-character hash key provided when you created the router enrollment)"
|
||||||
|
read -p "Hash Key: " hash_key
|
||||||
|
|
||||||
|
# Validate hash key format
|
||||||
|
if [[ ! "$hash_key" =~ ^[a-fA-F0-9]{32}$ ]]; then
|
||||||
|
error_exit "Invalid hash key format. Expected 32-character hexadecimal string."
|
||||||
|
fi
|
||||||
|
|
||||||
|
HASH_KEY="$hash_key"
|
||||||
|
|
||||||
|
echo
|
||||||
|
log "INFO" "Configuration:"
|
||||||
|
log "INFO" " API Endpoint: $API_ENDPOINT"
|
||||||
|
log "INFO" " Hash Key: ${HASH_KEY:0:8}...${HASH_KEY:24:8}"
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
# Register router with API
|
||||||
|
register_router() {
|
||||||
|
log "INFO" "Registering router with ZitiNexus Portal..."
|
||||||
|
|
||||||
|
local api_url="${API_ENDPOINT}/api/router/register"
|
||||||
|
local payload="{\"hashKey\":\"$HASH_KEY\"}"
|
||||||
|
local response_file=$(mktemp)
|
||||||
|
local http_code
|
||||||
|
|
||||||
|
# Debug: Show the URL being called
|
||||||
|
log "INFO" "API URL: $api_url"
|
||||||
|
|
||||||
|
# Make API call with retry logic
|
||||||
|
local max_retries=3
|
||||||
|
local retry_count=0
|
||||||
|
|
||||||
|
while [ $retry_count -lt $max_retries ]; do
|
||||||
|
http_code=$(curl -s -w "%{http_code}" -o "$response_file" \
|
||||||
|
-X POST \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-H "User-Agent: ZitiRouter-EnrollmentScript/$SCRIPT_VERSION" \
|
||||||
|
-d "$payload" \
|
||||||
|
--connect-timeout 30 \
|
||||||
|
--max-time 60 \
|
||||||
|
"$api_url" 2>/dev/null || echo "000")
|
||||||
|
|
||||||
|
if [[ "$http_code" == "200" ]]; then
|
||||||
|
break
|
||||||
|
elif [[ "$http_code" == "429" ]]; then
|
||||||
|
retry_count=$((retry_count + 1))
|
||||||
|
if [ $retry_count -lt $max_retries ]; then
|
||||||
|
local wait_time=$((retry_count * 2))
|
||||||
|
log "WARNING" "Rate limited. Waiting ${wait_time}s before retry $retry_count/$max_retries..."
|
||||||
|
sleep $wait_time
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Check response
|
||||||
|
if [[ "$http_code" != "200" ]]; then
|
||||||
|
local error_msg="API request failed with HTTP $http_code"
|
||||||
|
if [[ -f "$response_file" ]]; then
|
||||||
|
local api_error=$(jq -r '.error.message // .message // "Unknown error"' "$response_file" 2>/dev/null || echo "Unknown error")
|
||||||
|
error_msg="$error_msg: $api_error"
|
||||||
|
fi
|
||||||
|
rm -f "$response_file"
|
||||||
|
error_exit "$error_msg"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Parse response
|
||||||
|
if ! jq -e '.success' "$response_file" >/dev/null 2>&1; then
|
||||||
|
local api_error=$(jq -r '.error.message // .message // "Registration failed"' "$response_file" 2>/dev/null || echo "Registration failed")
|
||||||
|
rm -f "$response_file"
|
||||||
|
error_exit "Registration failed: $api_error"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extract data from response - Updated to match expected JSON structure
|
||||||
|
JWT=$(jq -r '.data.jwt' "$response_file" 2>/dev/null)
|
||||||
|
ROUTER_YAML=$(jq -r '.data.routerConfig.yaml' "$response_file" 2>/dev/null)
|
||||||
|
ROUTER_NAME=$(jq -r '.data.routerInfo.name' "$response_file" 2>/dev/null)
|
||||||
|
CALLBACK_URL=$(jq -r '.data.callbackUrl // ""' "$response_file" 2>/dev/null)
|
||||||
|
|
||||||
|
# Extract additional data for proper router configuration
|
||||||
|
ROUTER_ID=$(jq -r '.data.routerInfo.id' "$response_file" 2>/dev/null)
|
||||||
|
TENANT_ID=$(jq -r '.data.metadata.tenantId' "$response_file" 2>/dev/null)
|
||||||
|
CONTROLLER_ENDPOINT=$(jq -r '.data.metadata.controllerEndpoint' "$response_file" 2>/dev/null)
|
||||||
|
|
||||||
|
# Extract role attributes as array
|
||||||
|
ROLE_ATTRIBUTES=$(jq -r '.data.routerInfo.roleAttributes[]' "$response_file" 2>/dev/null | tr '\n' ' ')
|
||||||
|
|
||||||
|
# Store the full response for debugging
|
||||||
|
FULL_RESPONSE=$(cat "$response_file")
|
||||||
|
|
||||||
|
rm -f "$response_file"
|
||||||
|
|
||||||
|
# Validate extracted data
|
||||||
|
if [[ -z "$JWT" || "$JWT" == "null" ]]; then
|
||||||
|
error_exit "Failed to extract JWT from API response"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$ROUTER_YAML" || "$ROUTER_YAML" == "null" ]]; then
|
||||||
|
error_exit "Failed to extract router configuration from API response"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$ROUTER_NAME" || "$ROUTER_NAME" == "null" ]]; then
|
||||||
|
error_exit "Failed to extract router name from API response"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$ROUTER_ID" || "$ROUTER_ID" == "null" ]]; then
|
||||||
|
error_exit "Failed to extract router ID from API response"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$TENANT_ID" || "$TENANT_ID" == "null" ]]; then
|
||||||
|
error_exit "Failed to extract tenant ID from API response"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Initialize CALLBACK_URL as empty string if null
|
||||||
|
if [[ "$CALLBACK_URL" == "null" ]]; then
|
||||||
|
CALLBACK_URL=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "SUCCESS" "Router registered successfully: $ROUTER_NAME (ID: $ROUTER_ID)"
|
||||||
|
log "INFO" " Tenant ID: $TENANT_ID"
|
||||||
|
log "INFO" " Controller: $CONTROLLER_ENDPOINT"
|
||||||
|
log "INFO" " Role Attributes: $ROLE_ATTRIBUTES"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fix router configuration for proper enrollment
|
||||||
|
fix_router_configuration() {
|
||||||
|
log "INFO" "Constructing router configuration from API response..."
|
||||||
|
|
||||||
|
# Create a backup of the original config
|
||||||
|
cp "$ROUTER_CONFIG" "${ROUTER_CONFIG}.backup" || error_exit "Failed to backup router configuration"
|
||||||
|
|
||||||
|
# Use data from API response instead of hardcoding
|
||||||
|
log "INFO" "Using API response data to construct proper router configuration"
|
||||||
|
|
||||||
|
# Determine controller endpoint - use from API if available, otherwise default
|
||||||
|
local ctrl_endpoint="enroll.zitinexus.com:443"
|
||||||
|
if [[ -n "$CONTROLLER_ENDPOINT" && "$CONTROLLER_ENDPOINT" != "null" ]]; then
|
||||||
|
ctrl_endpoint="$CONTROLLER_ENDPOINT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Add tls: prefix if not present
|
||||||
|
if [[ ! "$ctrl_endpoint" =~ ^tls: ]]; then
|
||||||
|
ctrl_endpoint="tls:$ctrl_endpoint"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build role attributes section from API response
|
||||||
|
local role_attributes_section=""
|
||||||
|
if [[ -n "$ROLE_ATTRIBUTES" && "$ROLE_ATTRIBUTES" != " " ]]; then
|
||||||
|
role_attributes_section="roleAttributes:"
|
||||||
|
for attr in $ROLE_ATTRIBUTES; do
|
||||||
|
role_attributes_section="$role_attributes_section"$'\n'" - \"$attr\""
|
||||||
|
done
|
||||||
|
else
|
||||||
|
role_attributes_section="# No role attributes specified"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get current timestamp if not provided
|
||||||
|
local generated_at=$(date -u +"%Y-%m-%dT%H:%M:%S.%3NZ")
|
||||||
|
|
||||||
|
# Generate the complete router configuration using API data
|
||||||
|
cat > "$ROUTER_CONFIG" << EOF
|
||||||
|
v: 3
|
||||||
|
|
||||||
|
identity:
|
||||||
|
cert: /etc/zitirouter/certs/$ROUTER_NAME.cert
|
||||||
|
server_cert: /etc/zitirouter/certs/$ROUTER_NAME.server.chain.cert
|
||||||
|
key: /etc/zitirouter/certs/$ROUTER_NAME.key
|
||||||
|
ca: /etc/zitirouter/certs/$ROUTER_NAME.cas
|
||||||
|
|
||||||
|
ctrl:
|
||||||
|
endpoint: $ctrl_endpoint
|
||||||
|
|
||||||
|
link:
|
||||||
|
dialers:
|
||||||
|
- binding: transport
|
||||||
|
|
||||||
|
listeners:
|
||||||
|
# bindings of edge and tunnel requires an "edge" section below
|
||||||
|
- binding: edge
|
||||||
|
address: tls:0.0.0.0:443
|
||||||
|
options:
|
||||||
|
advertise: 127.0.0.1:443
|
||||||
|
connectTimeoutMs: 5000
|
||||||
|
getSessionTimeout: 60
|
||||||
|
- binding: tunnel
|
||||||
|
options:
|
||||||
|
mode: host
|
||||||
|
|
||||||
|
edge:
|
||||||
|
csr:
|
||||||
|
country: SG
|
||||||
|
province: SG
|
||||||
|
locality: Singapore
|
||||||
|
organization: Genworx
|
||||||
|
organizationalUnit: ZitiNexus
|
||||||
|
sans:
|
||||||
|
dns:
|
||||||
|
- localhost
|
||||||
|
- $ROUTER_NAME
|
||||||
|
ip:
|
||||||
|
- "127.0.0.1"
|
||||||
|
- "::1"
|
||||||
|
|
||||||
|
# Tenant-specific role attributes
|
||||||
|
$role_attributes_section
|
||||||
|
|
||||||
|
# Router metadata
|
||||||
|
metadata:
|
||||||
|
tenantId: "$TENANT_ID"
|
||||||
|
zitiRouterId: "$ROUTER_ID"
|
||||||
|
routerType: "private-edge"
|
||||||
|
generatedAt: "$generated_at"
|
||||||
|
generatedBy: "ZitiNexus"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod 644 "$ROUTER_CONFIG"
|
||||||
|
|
||||||
|
log "SUCCESS" "Router configuration constructed from API response"
|
||||||
|
log "INFO" " Original config backed up to: ${ROUTER_CONFIG}.backup"
|
||||||
|
log "INFO" " Router name: $ROUTER_NAME"
|
||||||
|
log "INFO" " Tenant ID: $TENANT_ID"
|
||||||
|
log "INFO" " Ziti Router ID: $ROUTER_ID"
|
||||||
|
log "INFO" " Controller endpoint: $ctrl_endpoint"
|
||||||
|
log "INFO" " Role attributes: $ROLE_ATTRIBUTES"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Save configuration files
|
||||||
|
save_configuration() {
|
||||||
|
log "INFO" "Saving configuration files..."
|
||||||
|
|
||||||
|
# Save JWT
|
||||||
|
echo "$JWT" > "$JWT_FILE" || error_exit "Failed to save JWT file"
|
||||||
|
chmod 600 "$JWT_FILE"
|
||||||
|
|
||||||
|
# Save router configuration
|
||||||
|
echo "$ROUTER_YAML" > "$ROUTER_CONFIG" || error_exit "Failed to save router configuration"
|
||||||
|
chmod 644 "$ROUTER_CONFIG"
|
||||||
|
|
||||||
|
log "SUCCESS" "Configuration files saved"
|
||||||
|
log "INFO" " JWT: $JWT_FILE"
|
||||||
|
log "INFO" " Config: $ROUTER_CONFIG"
|
||||||
|
|
||||||
|
# Fix the router configuration for proper enrollment
|
||||||
|
fix_router_configuration
|
||||||
|
}
|
||||||
|
|
||||||
|
# Enroll router with OpenZiti
|
||||||
|
enroll_router() {
|
||||||
|
log "INFO" "Enrolling router with OpenZiti controller..."
|
||||||
|
|
||||||
|
# Run router enrollment (correct command syntax)
|
||||||
|
if ziti router enroll --jwt "$JWT_FILE" "$ROUTER_CONFIG" 2>&1 | tee -a "$LOG_FILE"; then
|
||||||
|
log "SUCCESS" "Router enrollment completed successfully"
|
||||||
|
else
|
||||||
|
error_exit "Router enrollment failed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify certificates were created
|
||||||
|
if [[ ! -f "${CERTS_DIR}/${ROUTER_NAME}.cert" ]]; then
|
||||||
|
error_exit "Router certificate not found after enrollment"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "SUCCESS" "Router certificates generated successfully"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create systemd service
|
||||||
|
create_systemd_service() {
|
||||||
|
log "INFO" "Creating systemd service..."
|
||||||
|
|
||||||
|
# Create the final router config file path for systemd
|
||||||
|
local final_config="/etc/zitirouter/zitirouter.yaml"
|
||||||
|
|
||||||
|
# Copy the router config to the expected location for systemd
|
||||||
|
cp "$ROUTER_CONFIG" "$final_config" || error_exit "Failed to copy router config to final location"
|
||||||
|
chmod 644 "$final_config"
|
||||||
|
|
||||||
|
cat > "$SYSTEMD_SERVICE_FILE" << EOF
|
||||||
|
[Unit]
|
||||||
|
Description=OpenZiti Router
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/bin/ziti router run /etc/zitirouter/zitirouter.yaml
|
||||||
|
Restart=on-failure
|
||||||
|
User=root
|
||||||
|
WorkingDirectory=/etc/zitirouter
|
||||||
|
LimitNOFILE=65536
|
||||||
|
StandardOutput=append:/var/log/ziti-router.log
|
||||||
|
StandardError=append:/var/log/ziti-router.log
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Reload systemd and enable service
|
||||||
|
systemctl daemon-reload || error_exit "Failed to reload systemd"
|
||||||
|
systemctl enable ziti-router.service || error_exit "Failed to enable ziti-router service"
|
||||||
|
|
||||||
|
log "SUCCESS" "Systemd service created and enabled"
|
||||||
|
log "INFO" " Service file: $SYSTEMD_SERVICE_FILE"
|
||||||
|
log "INFO" " Config file: $final_config"
|
||||||
|
log "INFO" " Log file: /var/log/ziti-router.log"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Start router service
|
||||||
|
start_router() {
|
||||||
|
log "INFO" "Starting OpenZiti router service..."
|
||||||
|
|
||||||
|
if systemctl start ziti-router.service; then
|
||||||
|
log "SUCCESS" "Router service started successfully"
|
||||||
|
|
||||||
|
# Wait a moment and check status
|
||||||
|
sleep 3
|
||||||
|
if systemctl is-active --quiet ziti-router.service; then
|
||||||
|
log "SUCCESS" "Router service is running"
|
||||||
|
else
|
||||||
|
log "WARNING" "Router service may not be running properly"
|
||||||
|
log "INFO" "Check status with: systemctl status ziti-router.service"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
error_exit "Failed to start router service"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Report enrollment status back to portal
|
||||||
|
report_status() {
|
||||||
|
log "INFO" "Reporting enrollment status to portal..."
|
||||||
|
|
||||||
|
if [[ -z "$CALLBACK_URL" || "$CALLBACK_URL" == "null" ]]; then
|
||||||
|
log "WARNING" "No callback URL provided, skipping status report"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fix callback URL domain mismatch if needed
|
||||||
|
# Replace api.zitinexus.com with backend.zitinexus.com to match script's API endpoint
|
||||||
|
local fixed_callback_url="$CALLBACK_URL"
|
||||||
|
if [[ "$CALLBACK_URL" == *"api.zitinexus.com"* ]]; then
|
||||||
|
fixed_callback_url="${CALLBACK_URL//api.zitinexus.com/backend.zitinexus.com}"
|
||||||
|
log "INFO" "Fixed callback URL domain: $fixed_callback_url"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get system information
|
||||||
|
local hostname=$(hostname)
|
||||||
|
local arch=$(uname -m)
|
||||||
|
local os=$(lsb_release -d 2>/dev/null | cut -f2 || echo "Linux")
|
||||||
|
local ziti_version=$(ziti version 2>/dev/null | head -n1 || echo "unknown")
|
||||||
|
|
||||||
|
local payload=$(cat << EOF
|
||||||
|
{
|
||||||
|
"hashKey": "$HASH_KEY",
|
||||||
|
"status": "success",
|
||||||
|
"routerInfo": {
|
||||||
|
"version": "$ziti_version",
|
||||||
|
"hostname": "$hostname",
|
||||||
|
"arch": "$arch",
|
||||||
|
"os": "$os"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
|
||||||
|
local response_file=$(mktemp)
|
||||||
|
local http_code
|
||||||
|
|
||||||
|
http_code=$(curl -s -w "%{http_code}" -o "$response_file" \
|
||||||
|
-X POST \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-H "User-Agent: ZitiRouter-EnrollmentScript/$SCRIPT_VERSION" \
|
||||||
|
-d "$payload" \
|
||||||
|
--connect-timeout 30 \
|
||||||
|
--max-time 60 \
|
||||||
|
"$fixed_callback_url" 2>/dev/null || echo "000")
|
||||||
|
|
||||||
|
if [[ "$http_code" == "200" ]]; then
|
||||||
|
log "SUCCESS" "Enrollment status reported successfully"
|
||||||
|
else
|
||||||
|
log "WARNING" "Failed to report enrollment status (HTTP $http_code)"
|
||||||
|
if [[ -f "$response_file" ]]; then
|
||||||
|
local error_msg=$(jq -r '.error.message // .message // "Unknown error"' "$response_file" 2>/dev/null || echo "Unknown error")
|
||||||
|
log "WARNING" "Error: $error_msg"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f "$response_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Report failure status
|
||||||
|
report_failure() {
|
||||||
|
local error_message="$1"
|
||||||
|
|
||||||
|
if [[ -z "$CALLBACK_URL" || "$CALLBACK_URL" == "null" || -z "$HASH_KEY" ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fix callback URL domain mismatch if needed
|
||||||
|
local fixed_callback_url="$CALLBACK_URL"
|
||||||
|
if [[ "$CALLBACK_URL" == *"api.zitinexus.com"* ]]; then
|
||||||
|
fixed_callback_url="${CALLBACK_URL//api.zitinexus.com/backend.zitinexus.com}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local payload=$(cat << EOF
|
||||||
|
{
|
||||||
|
"hashKey": "$HASH_KEY",
|
||||||
|
"status": "failed",
|
||||||
|
"error": "$error_message"
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
|
||||||
|
curl -s -X POST \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-H "User-Agent: ZitiRouter-EnrollmentScript/$SCRIPT_VERSION" \
|
||||||
|
-d "$payload" \
|
||||||
|
--connect-timeout 10 \
|
||||||
|
--max-time 30 \
|
||||||
|
"$fixed_callback_url" >/dev/null 2>&1 || true
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cleanup function
|
||||||
|
cleanup() {
|
||||||
|
local exit_code=$?
|
||||||
|
if [[ $exit_code -ne 0 ]]; then
|
||||||
|
log "ERROR" "Script failed with exit code $exit_code"
|
||||||
|
if [[ -n "${HASH_KEY:-}" ]]; then
|
||||||
|
report_failure "Router enrollment script failed"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Show final status
|
||||||
|
show_final_status() {
|
||||||
|
echo
|
||||||
|
echo "=============================================="
|
||||||
|
echo " ENROLLMENT COMPLETED SUCCESSFULLY"
|
||||||
|
echo "=============================================="
|
||||||
|
echo
|
||||||
|
log "SUCCESS" "OpenZiti Router enrollment completed!"
|
||||||
|
echo
|
||||||
|
echo "Router Information:"
|
||||||
|
echo " Name: $ROUTER_NAME"
|
||||||
|
echo " Config: $ROUTER_CONFIG"
|
||||||
|
echo " Certificates: $CERTS_DIR"
|
||||||
|
echo " Service: ziti-router.service"
|
||||||
|
echo
|
||||||
|
echo "Useful Commands:"
|
||||||
|
echo " Check status: systemctl status ziti-router"
|
||||||
|
echo " View logs: journalctl -u ziti-router -f"
|
||||||
|
echo " Stop router: systemctl stop ziti-router"
|
||||||
|
echo " Start router: systemctl start ziti-router"
|
||||||
|
echo " Restart router: systemctl restart ziti-router"
|
||||||
|
echo
|
||||||
|
echo "Log file: $LOG_FILE"
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main execution
|
||||||
|
main() {
|
||||||
|
# Set up error handling
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
log "INFO" "Starting $SCRIPT_NAME v$SCRIPT_VERSION"
|
||||||
|
|
||||||
|
# Check if running as root
|
||||||
|
check_root
|
||||||
|
|
||||||
|
# Check system requirements
|
||||||
|
check_requirements
|
||||||
|
|
||||||
|
# Install OpenZiti if needed
|
||||||
|
install_ziti
|
||||||
|
|
||||||
|
# Create directories
|
||||||
|
create_directories
|
||||||
|
|
||||||
|
# Get user input
|
||||||
|
get_user_input
|
||||||
|
|
||||||
|
# Register router with API
|
||||||
|
register_router
|
||||||
|
|
||||||
|
# Save configuration files
|
||||||
|
save_configuration
|
||||||
|
|
||||||
|
# Enroll router
|
||||||
|
enroll_router
|
||||||
|
|
||||||
|
# Create systemd service
|
||||||
|
create_systemd_service
|
||||||
|
|
||||||
|
# Start router
|
||||||
|
start_router
|
||||||
|
|
||||||
|
# Report success status
|
||||||
|
report_status
|
||||||
|
|
||||||
|
# Show final status
|
||||||
|
show_final_status
|
||||||
|
|
||||||
|
log "SUCCESS" "Router enrollment process completed successfully"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run main function
|
||||||
|
main "$@"
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Test script to verify the API endpoint fix
|
||||||
|
# This script tests the corrected API URL construction
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Test configuration
|
||||||
|
TEST_API_ENDPOINT="https://backend.zitinexus.com"
|
||||||
|
TEST_HASH_KEY="c3d00e5615464e0c02a7dcfcd56abc4e"
|
||||||
|
|
||||||
|
echo "=============================================="
|
||||||
|
echo " Testing Router Enrollment API Fix"
|
||||||
|
echo "=============================================="
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo "Testing API URL construction:"
|
||||||
|
echo " Base endpoint: $TEST_API_ENDPOINT"
|
||||||
|
echo " Expected URL: ${TEST_API_ENDPOINT}/api/router/register"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Test the API call (this will likely fail with authentication error, but should not be 404)
|
||||||
|
echo "Testing API connectivity..."
|
||||||
|
echo "Making test API call to verify endpoint exists..."
|
||||||
|
|
||||||
|
response=$(curl -s -w "HTTPSTATUS:%{http_code}" \
|
||||||
|
-X POST \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-H "User-Agent: ZitiRouter-EnrollmentScript-Test/1.0.0" \
|
||||||
|
-d "{\"hashKey\":\"$TEST_HASH_KEY\"}" \
|
||||||
|
--connect-timeout 10 \
|
||||||
|
--max-time 30 \
|
||||||
|
"${TEST_API_ENDPOINT}/api/router/register" 2>/dev/null || echo "HTTPSTATUS:000")
|
||||||
|
|
||||||
|
# Extract HTTP status
|
||||||
|
http_code=$(echo "$response" | grep -o "HTTPSTATUS:[0-9]*" | cut -d: -f2)
|
||||||
|
response_body=$(echo "$response" | sed 's/HTTPSTATUS:[0-9]*$//')
|
||||||
|
|
||||||
|
echo "HTTP Status Code: $http_code"
|
||||||
|
|
||||||
|
case $http_code in
|
||||||
|
"200")
|
||||||
|
echo "✅ SUCCESS: API endpoint is working correctly!"
|
||||||
|
echo "Response: $response_body"
|
||||||
|
;;
|
||||||
|
"400")
|
||||||
|
echo "✅ GOOD: API endpoint exists (400 = Bad Request, likely invalid hash key)"
|
||||||
|
echo "This means the endpoint is found and processing requests"
|
||||||
|
if [[ -n "$response_body" ]]; then
|
||||||
|
echo "Response: $response_body"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
"404")
|
||||||
|
echo "❌ FAILED: API endpoint not found (404 error)"
|
||||||
|
echo "The /api/router/register endpoint does not exist"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
"429")
|
||||||
|
echo "✅ GOOD: API endpoint exists (429 = Rate Limited)"
|
||||||
|
echo "This means the endpoint is found but rate limited"
|
||||||
|
;;
|
||||||
|
"500")
|
||||||
|
echo "⚠️ WARNING: API endpoint exists but server error (500)"
|
||||||
|
echo "The endpoint exists but there's a server-side issue"
|
||||||
|
;;
|
||||||
|
"000")
|
||||||
|
echo "❌ FAILED: Could not connect to API endpoint"
|
||||||
|
echo "Check if the backend server is running and accessible"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "⚠️ UNKNOWN: Received HTTP $http_code"
|
||||||
|
echo "Response: $response_body"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=============================================="
|
||||||
|
echo " Test Summary"
|
||||||
|
echo "=============================================="
|
||||||
|
echo
|
||||||
|
echo "✅ API URL construction: FIXED"
|
||||||
|
echo " - Changed from: /router/register"
|
||||||
|
echo " - Changed to: /api/router/register"
|
||||||
|
echo
|
||||||
|
echo "✅ Variable initialization: FIXED"
|
||||||
|
echo " - Added initialization for CALLBACK_URL and other variables"
|
||||||
|
echo " - Prevents 'unbound variable' errors"
|
||||||
|
echo
|
||||||
|
echo "✅ Default endpoint: UPDATED"
|
||||||
|
echo " - Changed to: https://backend.zitinexus.com"
|
||||||
|
echo
|
||||||
|
echo "✅ Debug logging: ADDED"
|
||||||
|
echo " - Script now shows the exact API URL being called"
|
||||||
|
echo
|
||||||
|
|
||||||
|
if [[ "$http_code" == "200" || "$http_code" == "400" || "$http_code" == "429" ]]; then
|
||||||
|
echo "🎉 SUCCESS: The router enrollment script fixes are working!"
|
||||||
|
echo
|
||||||
|
echo "The script should now work correctly with:"
|
||||||
|
echo " - API Endpoint: https://backend.zitinexus.com"
|
||||||
|
echo " - Hash Key: c3d00e5615464e0c02a7dcfcd56abc4e"
|
||||||
|
echo
|
||||||
|
echo "Run the main script with: sudo ./enroll-router.sh"
|
||||||
|
else
|
||||||
|
echo "⚠️ The API endpoint test had unexpected results."
|
||||||
|
echo "Please check if the backend server is running and accessible."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
|
@ -0,0 +1,321 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Test Script for Router Enrollment
|
||||||
|
# This script helps test the enrollment process without actually enrolling a router
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Test configuration
|
||||||
|
TEST_API_ENDPOINT="https://your-zitinexus-portal.com/api"
|
||||||
|
TEST_HASH_KEY="a1b2c3d4e5f6789012345678901234567890abcd"
|
||||||
|
|
||||||
|
log() {
|
||||||
|
local level=$1
|
||||||
|
shift
|
||||||
|
local message="$*"
|
||||||
|
|
||||||
|
case $level in
|
||||||
|
"ERROR")
|
||||||
|
echo -e "${RED}[ERROR]${NC} $message" >&2
|
||||||
|
;;
|
||||||
|
"SUCCESS")
|
||||||
|
echo -e "${GREEN}[SUCCESS]${NC} $message"
|
||||||
|
;;
|
||||||
|
"WARNING")
|
||||||
|
echo -e "${YELLOW}[WARNING]${NC} $message"
|
||||||
|
;;
|
||||||
|
"INFO")
|
||||||
|
echo -e "${BLUE}[INFO]${NC} $message"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "$message"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test API connectivity
|
||||||
|
test_api_connectivity() {
|
||||||
|
log "INFO" "Testing API connectivity..."
|
||||||
|
|
||||||
|
local api_endpoint
|
||||||
|
read -p "Enter API endpoint to test [$TEST_API_ENDPOINT]: " api_endpoint
|
||||||
|
api_endpoint="${api_endpoint:-$TEST_API_ENDPOINT}"
|
||||||
|
|
||||||
|
# Test health endpoint
|
||||||
|
local health_url="${api_endpoint}/router/health"
|
||||||
|
log "INFO" "Testing health endpoint: $health_url"
|
||||||
|
|
||||||
|
local response=$(curl -s -w "%{http_code}" -o /dev/null "$health_url" 2>/dev/null || echo "000")
|
||||||
|
|
||||||
|
if [[ "$response" == "200" ]]; then
|
||||||
|
log "SUCCESS" "API health endpoint is accessible"
|
||||||
|
else
|
||||||
|
log "ERROR" "API health endpoint returned HTTP $response"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test hash key format validation
|
||||||
|
test_hash_key_validation() {
|
||||||
|
log "INFO" "Testing hash key format validation..."
|
||||||
|
|
||||||
|
local test_cases=(
|
||||||
|
"a1b2c3d4e5f6789012345678901234567890abcd:VALID"
|
||||||
|
"A1B2C3D4E5F6789012345678901234567890ABCD:VALID"
|
||||||
|
"short:INVALID"
|
||||||
|
"toolongtobeavalidhashkeyfortesting123456789:INVALID"
|
||||||
|
"g1h2i3j4k5l6789012345678901234567890xyz:INVALID"
|
||||||
|
"a1b2c3d4e5f6789012345678901234567890abc:INVALID"
|
||||||
|
)
|
||||||
|
|
||||||
|
for test_case in "${test_cases[@]}"; do
|
||||||
|
local hash_key="${test_case%:*}"
|
||||||
|
local expected="${test_case#*:}"
|
||||||
|
|
||||||
|
if [[ "$hash_key" =~ ^[a-fA-F0-9]{32}$ ]]; then
|
||||||
|
local result="VALID"
|
||||||
|
else
|
||||||
|
local result="INVALID"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$result" == "$expected" ]]; then
|
||||||
|
log "SUCCESS" "Hash key validation: '$hash_key' -> $result ✓"
|
||||||
|
else
|
||||||
|
log "ERROR" "Hash key validation: '$hash_key' -> $result (expected $expected) ✗"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test API registration call (dry run)
|
||||||
|
test_api_registration() {
|
||||||
|
log "INFO" "Testing API registration call (dry run)..."
|
||||||
|
|
||||||
|
local api_endpoint
|
||||||
|
read -p "Enter API endpoint [$TEST_API_ENDPOINT]: " api_endpoint
|
||||||
|
api_endpoint="${api_endpoint:-$TEST_API_ENDPOINT}"
|
||||||
|
|
||||||
|
local hash_key
|
||||||
|
read -p "Enter test hash key [$TEST_HASH_KEY]: " hash_key
|
||||||
|
hash_key="${hash_key:-$TEST_HASH_KEY}"
|
||||||
|
|
||||||
|
# Validate hash key format
|
||||||
|
if [[ ! "$hash_key" =~ ^[a-fA-F0-9]{32}$ ]]; then
|
||||||
|
log "ERROR" "Invalid hash key format"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local api_url="${api_endpoint}/router/register"
|
||||||
|
local payload="{\"hashKey\":\"$hash_key\"}"
|
||||||
|
|
||||||
|
log "INFO" "Making API call to: $api_url"
|
||||||
|
log "INFO" "Payload: $payload"
|
||||||
|
|
||||||
|
local response_file=$(mktemp)
|
||||||
|
local http_code
|
||||||
|
|
||||||
|
http_code=$(curl -s -w "%{http_code}" -o "$response_file" \
|
||||||
|
-X POST \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-H "User-Agent: ZitiRouter-TestScript/1.0.0" \
|
||||||
|
-d "$payload" \
|
||||||
|
--connect-timeout 30 \
|
||||||
|
--max-time 60 \
|
||||||
|
"$api_url" 2>/dev/null || echo "000")
|
||||||
|
|
||||||
|
log "INFO" "HTTP Response Code: $http_code"
|
||||||
|
|
||||||
|
if [[ -f "$response_file" ]]; then
|
||||||
|
log "INFO" "Response body:"
|
||||||
|
if command -v jq &> /dev/null; then
|
||||||
|
jq '.' "$response_file" 2>/dev/null || cat "$response_file"
|
||||||
|
else
|
||||||
|
cat "$response_file"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f "$response_file"
|
||||||
|
|
||||||
|
case $http_code in
|
||||||
|
"200")
|
||||||
|
log "SUCCESS" "API call successful"
|
||||||
|
;;
|
||||||
|
"400")
|
||||||
|
log "WARNING" "Bad request - check hash key validity"
|
||||||
|
;;
|
||||||
|
"404")
|
||||||
|
log "ERROR" "Hash key not found or endpoint not available"
|
||||||
|
;;
|
||||||
|
"429")
|
||||||
|
log "WARNING" "Rate limited - try again later"
|
||||||
|
;;
|
||||||
|
"000")
|
||||||
|
log "ERROR" "Connection failed - check network connectivity"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
log "ERROR" "Unexpected response code: $http_code"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test system requirements
|
||||||
|
test_system_requirements() {
|
||||||
|
log "INFO" "Testing system requirements..."
|
||||||
|
|
||||||
|
# Check if running as root
|
||||||
|
if [[ $EUID -eq 0 ]]; then
|
||||||
|
log "SUCCESS" "Running as root ✓"
|
||||||
|
else
|
||||||
|
log "WARNING" "Not running as root (enrollment script requires sudo)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check curl
|
||||||
|
if command -v curl &> /dev/null; then
|
||||||
|
local curl_version=$(curl --version | head -n1)
|
||||||
|
log "SUCCESS" "curl available: $curl_version ✓"
|
||||||
|
else
|
||||||
|
log "ERROR" "curl not found ✗"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check jq
|
||||||
|
if command -v jq &> /dev/null; then
|
||||||
|
local jq_version=$(jq --version)
|
||||||
|
log "SUCCESS" "jq available: $jq_version ✓"
|
||||||
|
else
|
||||||
|
log "WARNING" "jq not found (will be installed by enrollment script)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check systemctl
|
||||||
|
if command -v systemctl &> /dev/null; then
|
||||||
|
log "SUCCESS" "systemctl available ✓"
|
||||||
|
else
|
||||||
|
log "ERROR" "systemctl not found ✗"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check OpenZiti CLI
|
||||||
|
if command -v ziti &> /dev/null; then
|
||||||
|
local ziti_version=$(ziti version 2>/dev/null | head -n1 || echo "unknown")
|
||||||
|
log "SUCCESS" "OpenZiti CLI available: $ziti_version ✓"
|
||||||
|
else
|
||||||
|
log "INFO" "OpenZiti CLI not found (will be installed by enrollment script)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check internet connectivity
|
||||||
|
if curl -s --connect-timeout 5 https://get.openziti.io >/dev/null 2>&1; then
|
||||||
|
log "SUCCESS" "Internet connectivity ✓"
|
||||||
|
else
|
||||||
|
log "ERROR" "No internet connectivity ✗"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test directory permissions
|
||||||
|
test_directory_permissions() {
|
||||||
|
log "INFO" "Testing directory permissions..."
|
||||||
|
|
||||||
|
local test_dirs=(
|
||||||
|
"/etc"
|
||||||
|
"/var/log"
|
||||||
|
"/etc/systemd/system"
|
||||||
|
)
|
||||||
|
|
||||||
|
for dir in "${test_dirs[@]}"; do
|
||||||
|
if [[ -d "$dir" ]]; then
|
||||||
|
if [[ -w "$dir" ]]; then
|
||||||
|
log "SUCCESS" "$dir is writable ✓"
|
||||||
|
else
|
||||||
|
if [[ $EUID -eq 0 ]]; then
|
||||||
|
log "ERROR" "$dir is not writable even as root ✗"
|
||||||
|
else
|
||||||
|
log "WARNING" "$dir is not writable (need root access)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log "ERROR" "$dir does not exist ✗"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main menu
|
||||||
|
show_menu() {
|
||||||
|
echo
|
||||||
|
echo "=============================================="
|
||||||
|
echo " Router Enrollment Test Script"
|
||||||
|
echo "=============================================="
|
||||||
|
echo
|
||||||
|
echo "1. Test API Connectivity"
|
||||||
|
echo "2. Test Hash Key Validation"
|
||||||
|
echo "3. Test API Registration Call"
|
||||||
|
echo "4. Test System Requirements"
|
||||||
|
echo "5. Test Directory Permissions"
|
||||||
|
echo "6. Run All Tests"
|
||||||
|
echo "7. Exit"
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run all tests
|
||||||
|
run_all_tests() {
|
||||||
|
log "INFO" "Running all tests..."
|
||||||
|
echo
|
||||||
|
|
||||||
|
test_system_requirements
|
||||||
|
echo
|
||||||
|
|
||||||
|
test_directory_permissions
|
||||||
|
echo
|
||||||
|
|
||||||
|
test_hash_key_validation
|
||||||
|
echo
|
||||||
|
|
||||||
|
test_api_connectivity
|
||||||
|
echo
|
||||||
|
|
||||||
|
log "INFO" "All tests completed"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main execution
|
||||||
|
main() {
|
||||||
|
while true; do
|
||||||
|
show_menu
|
||||||
|
read -p "Select an option (1-7): " choice
|
||||||
|
|
||||||
|
case $choice in
|
||||||
|
1)
|
||||||
|
test_api_connectivity
|
||||||
|
;;
|
||||||
|
2)
|
||||||
|
test_hash_key_validation
|
||||||
|
;;
|
||||||
|
3)
|
||||||
|
test_api_registration
|
||||||
|
;;
|
||||||
|
4)
|
||||||
|
test_system_requirements
|
||||||
|
;;
|
||||||
|
5)
|
||||||
|
test_directory_permissions
|
||||||
|
;;
|
||||||
|
6)
|
||||||
|
run_all_tests
|
||||||
|
;;
|
||||||
|
7)
|
||||||
|
log "INFO" "Exiting..."
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
log "ERROR" "Invalid option. Please select 1-7."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo
|
||||||
|
read -p "Press Enter to continue..."
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run main function
|
||||||
|
main "$@"
|
||||||
Loading…
Reference in New Issue