feat(enrollment): implement token-based enrollment flow

Changes:
1.  Updated SHA256SUMS with new ostp-server binary
2.  Made oncp-master optional in deploy.sh (two deployment modes)
3.  Added enrollment_token support to ostp-server
4.  Updated config examples with token field

Deployment Modes:
- Mode 1 (Standalone): Connect to existing master with enrollment token
- Mode 2 (Full Stack): Deploy both master + server on one host

ostp-server Enrollment Flow:
1. Admin generates token on master: \oncp-master node token --expiry 60\
2. Node submits enrollment with token in config (psk: 'AUTO')
3. Master validates token (silent drop if invalid - security)
4. Admin approves node: \oncp-master node approve <node-id>\
5. Node receives PSK + IP from 10.X.0.0/16 pool
6. Update config with PSK, restart server

deploy.sh Features:
- Interactive mode selection
- Conditional oncp-master installation
- Automated token generation (full stack mode)
- Enrollment submission (standalone mode)

Config Examples:
- server.json.example: Full stack with local master
- server-enrollment.json.example: Standalone with token

Security:
- Token validation before enrollment acceptance
- Silent drop on invalid token (prevents enumeration)
- One-time use tokens with expiration
- IPAM automatic IP allocation from pool

Documentation:
- Updated README with deployment modes
- Added enrollment workflow explanation
- Security features documented
- CLI examples for both modes
This commit is contained in:
2026-01-02 03:36:20 +03:00
parent ec6b608cf7
commit a7ec878518
8 changed files with 231 additions and 65 deletions

View File

@@ -45,15 +45,26 @@ fi
# Configuration prompts
echo
echo -e "${YELLOW}═══ Configuration ═══${NC}"
read -p "Network octet (10.X.0.0/16, default 42): " NETWORK_OCTET
NETWORK_OCTET=${NETWORK_OCTET:-42}
echo "Deployment mode:"
echo " 1) Standalone server (connect to existing Master Node)"
echo " 2) Full stack (ostp-server + oncp-master on this host)"
read -p "Select mode (1 or 2, default 2): " DEPLOY_MODE
DEPLOY_MODE=${DEPLOY_MODE:-2}
if [ "$DEPLOY_MODE" = "1" ]; then
read -p "Master Node URL (e.g., http://master.example.com:8080): " MASTER_URL
read -p "Enrollment token: " ENROLL_TOKEN
NETWORK_OCTET=0 # Will be assigned by master
else
read -p "Network octet (10.X.0.0/16, default 42): " NETWORK_OCTET
NETWORK_OCTET=${NETWORK_OCTET:-42}
read -p "oncp-master listen port (default 8080): " ONCP_PORT
ONCP_PORT=${ONCP_PORT:-8080}
fi
read -p "ostp-server listen port (default 443): " OSTP_PORT
OSTP_PORT=${OSTP_PORT:-443}
read -p "oncp-master listen port (default 8080): " ONCP_PORT
ONCP_PORT=${ONCP_PORT:-8080}
read -p "Install directory (default /usr/local/bin): " INSTALL_DIR
INSTALL_DIR=${INSTALL_DIR:-/usr/local/bin}
@@ -63,12 +74,16 @@ CONFIG_DIR=${CONFIG_DIR:-/etc/ostp}
read -p "Database directory (default /var/lib/ostp): " DATA_DIR
DATA_DIR=${DATA_DIR:-/var/lib/ostp}
# Generate PSK
echo
echo -e "${YELLOW}${NC} Generating PSK..."
PSK=$(openssl rand -hex 32)
echo -e "${GREEN}${NC} PSK generated: ${YELLOW}${PSK}${NC}"
echo -e "${RED}⚠ SAVE THIS PSK! It will be stored in ${CONFIG_DIR}/server.json${NC}"
# Generate PSK (only for full stack mode)
if [ "$DEPLOY_MODE" = "2" ]; then
echo
echo -e "${YELLOW}${NC} Generating PSK..."
PSK=$(openssl rand -hex 32)
echo -e "${GREEN}${NC} PSK generated: ${YELLOW}${PSK}${NC}"
echo -e "${RED}⚠ SAVE THIS PSK! It will be stored in ${CONFIG_DIR}/server.json${NC}"
else
PSK="AUTO" # Will be assigned by master after approval
fi
# Create directories
echo
@@ -85,19 +100,36 @@ chmod +x "$INSTALL_DIR/ostp-server" "$INSTALL_DIR/oncp-master"
echo -e "${GREEN}${NC} Binaries installed to $INSTALL_DIR"
# Create ostp-server config
cat > "$CONFIG_DIR/server.json" <<EOF
if [ "$DEPLOY_MODE" = "1" ]; then
# Standalone mode - enrollment config
cat > "$CONFIG_DIR/server.json" <<EOF
{
"listen_addr": "0.0.0.0:${OSTP_PORT}",
"listen": "0.0.0.0:${OSTP_PORT}",
"psk": "${PSK}",
"master_url": "http://127.0.0.1:${ONCP_PORT}",
"master_node_url": "${MASTER_URL}",
"enrollment_token": "${ENROLL_TOKEN}",
"node_name": "$(hostname)",
"country_code": "US",
"max_clients": 1000
"max_connections": 1000
}
EOF
else
# Full stack mode
cat > "$CONFIG_DIR/server.json" <<EOF
{
"listen": "0.0.0.0:${OSTP_PORT}",
"psk": "${PSK}",
"master_node_url": "http://127.0.0.1:${ONCP_PORT}",
"country_code": "US",
"max_connections": 1000
}
EOF
fi
chmod 600 "$CONFIG_DIR/server.json"
echo -e "${GREEN}${NC} Configuration saved to $CONFIG_DIR/server.json"
# Create systemd service for oncp-master
# Create systemd service for oncp-master (only in full stack mode)
if [ "$DEPLOY_MODE" = "2" ]; then
cat > /etc/systemd/system/oncp-master.service <<EOF
[Unit]
Description=ONCP Master Node - Control Plane API
@@ -125,13 +157,14 @@ ReadWritePaths=${DATA_DIR} /var/log/ostp
[Install]
WantedBy=multi-user.target
EOF
fi
# Create systemd service for ostp-server
cat > /etc/systemd/system/ostp-server.service <<EOF
[Unit]
Description=OSTP VPN Server
After=network.target oncp-master.service
Requires=oncp-master.service
After=network.target
# Requires oncp-master.service only in full stack mode
[Service]
Type=simple
@@ -173,19 +206,28 @@ fi
# Enable and start services
echo
echo -e "${YELLOW}${NC} Starting services..."
systemctl enable oncp-master ostp-server
systemctl start oncp-master
# Wait for oncp-master to start
sleep 2
# Generate enrollment token
echo -e "${YELLOW}${NC} Generating enrollment token..."
TOKEN=$(${INSTALL_DIR}/oncp-master node token --expiry 60 2>/dev/null | grep -A1 "Token:" | tail -1 | xargs)
echo -e "${GREEN}${NC} Enrollment token (60 min): ${YELLOW}${TOKEN}${NC}"
# Start ostp-server
systemctl start ostp-server
if [ "$DEPLOY_MODE" = "2" ]; then
# Full stack mode
systemctl enable oncp-master ostp-server
systemctl start oncp-master
# Wait for oncp-master to start
sleep 2
# Generate enrollment token
echo -e "${YELLOW}${NC} Generating enrollment token..."
TOKEN=$(${INSTALL_DIR}/oncp-master node token --expiry 60 2>/dev/null | grep -A1 "Token:" | tail -1 | xargs)
echo -e "${GREEN}${NC} Enrollment token (60 min): ${YELLOW}${TOKEN}${NC}"
# Start ostp-server
systemctl start ostp-server
else
# Standalone mode - just enable and start ostp-server
systemctl enable ostp-server
systemctl start ostp-server
TOKEN="N/A (using enrollment token from config)"
fi
echo
echo -e "${GREEN}╔════════════════════════════════════════╗${NC}"
@@ -193,23 +235,40 @@ echo -e "${GREEN}║ Deployment Complete! ✓ ║${NC}"
echo -e "${GREEN}╚════════════════════════════════════════╝${NC}"
echo
echo -e "${YELLOW}Services Status:${NC}"
systemctl status oncp-master --no-pager -l || true
if [ "$DEPLOY_MODE" = "2" ]; then
systemctl status oncp-master --no-pager -l || true
fi
systemctl status ostp-server --no-pager -l || true
echo
echo -e "${YELLOW}Important Information:${NC}"
echo -e " • Network: ${GREEN}10.${NETWORK_OCTET}.0.0/16${NC}"
echo -e " • Master IP: ${GREEN}10.${NETWORK_OCTET}.0.1${NC}"
echo -e "PSK: ${YELLOW}${PSK}${NC}"
echo -e "Enrollment Token: ${YELLOW}${TOKEN}${NC} (expires in 60 minutes)"
if [ "$DEPLOY_MODE" = "2" ]; then
echo -e " • Mode: ${GREEN}Full Stack (Master + Server)${NC}"
echo -e "Network: ${GREEN}10.${NETWORK_OCTET}.0.0/16${NC}"
echo -e "Master IP: ${GREEN}10.${NETWORK_OCTET}.0.1${NC}"
echo -e " • PSK: ${YELLOW}${PSK}${NC}"
echo -e " • Enrollment Token: ${YELLOW}${TOKEN}${NC} (expires in 60 minutes)"
echo -e " • Database: ${DATA_DIR}/oncp.db"
else
echo -e " • Mode: ${GREEN}Standalone Server${NC}"
echo -e " • Master URL: ${GREEN}${MASTER_URL}${NC}"
echo -e " • Status: ${YELLOW}Waiting for approval${NC}"
fi
echo -e " • Listen: ${GREEN}0.0.0.0:${OSTP_PORT}${NC}"
echo -e " • Config: ${CONFIG_DIR}/server.json"
echo -e " • Database: ${DATA_DIR}/oncp.db"
echo -e " • Logs: /var/log/ostp/"
echo
echo -e "${YELLOW}Next Steps:${NC}"
echo -e " 1. Enroll nodes: ${GREEN}ostp-server --token ${TOKEN} --master https://your-master${NC}"
echo -e " 2. Approve nodes: ${GREEN}oncp-master node pending${NC}${GREEN}oncp-master node approve <id>${NC}"
echo -e " 3. Create users: ${GREEN}oncp-master user create --quota 100 --days 30${NC}"
echo -e " 4. Monitor logs: ${GREEN}journalctl -u ostp-server -f${NC}"
if [ "$DEPLOY_MODE" = "2" ]; then
echo -e "${YELLOW}Next Steps (Master Node):${NC}"
echo -e " 1. Approve nodes: ${GREEN}oncp-master node pending${NC}${GREEN}oncp-master node approve <id>${NC}"
echo -e " 2. Create users: ${GREEN}oncp-master user create --quota 100 --days 30${NC}"
echo -e " 3. Monitor logs: ${GREEN}journalctl -u oncp-master -f${NC}"
else
echo -e "${YELLOW}Next Steps (Standalone Server):${NC}"
echo -e " 1. Ask admin to approve node on master"
echo -e " 2. Check approval status: ${GREEN}journalctl -u ostp-server -f${NC}"
echo -e " 3. After approval, server will auto-restart with assigned PSK and IP"
fi
echo -e " 4. Monitor server: ${GREEN}journalctl -u ostp-server -f${NC}"
echo
echo -e "${RED}⚠ Security Reminder:${NC}"
echo -e " • Save PSK in password manager"