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