feat: add native deployment and separate docker|native structure
- Restructure repo into docker/ and native/ deployment types with a shared common/wallarm-lib.sh (logging, detection, validation, connectivity, env parsing) - Move Docker scripts + artifacts (binaries/, images/) under docker/ (git mv, history preserved) - Refactor Docker scripts to source the shared library; update artifact URLs - Add native/ scripts for no-Docker deployment using the Wallarm all-in-one installer (check, deploy, reconfigure, uninstall) with version pinning via WALLARM_VERSION - Add native/wallarm-native.sh unified node manager (Wallarm Native Node, connector mode) with preflight checks, parallel multi-node install, config/remove/status - Update setup.sh to download scripts per deployment type (DEPLOYMENT_TYPE=...) - Update README.md and changelog.md
This commit is contained in:
parent
424786b181
commit
aa3d716f61
19 changed files with 3091 additions and 859 deletions
337
README.md
337
README.md
|
|
@ -1,23 +1,34 @@
|
|||
# Wallarm Deployment System
|
||||
|
||||
A comprehensive solution for deploying Wallarm filtering nodes on virtual machines or bare metal servers. This system provides automated deployment, preflight checks, and management of Wallarm security nodes with support for multiple instances on the same server.
|
||||
A comprehensive solution for deploying Wallarm filtering nodes on virtual machines or bare metal servers. This system provides automated deployment, preflight checks, and management of Wallarm security nodes with **two deployment types**: **Docker** (containerized) and **Native** (installed directly on the OS, no Docker required).
|
||||
|
||||
## Deployment Types
|
||||
|
||||
| | **Docker** | **Native** |
|
||||
|---|---|---|
|
||||
| Runtime | Wallarm container on Docker engine | Wallarm NGINX module installed directly on the OS |
|
||||
| Artifacts | Docker static binaries + Wallarm image (from Git repo or local) | Wallarm all-in-one installer (`meganode.wallarm.com`) |
|
||||
| Multi-node on one host | ✅ Yes (unique ports) | ⚠️ One node per host (single system NGINX) |
|
||||
| Directory | `docker/` | `native/` |
|
||||
| Requires Docker | ✅ (installed automatically) | ❌ Never installed |
|
||||
| Best for | LXC/containers, multiple nodes, air-gapped | Simple single VM, minimal footprint, no containers |
|
||||
|
||||
## Features
|
||||
|
||||
- **Automated Preflight Checks** – Validates system readiness, network connectivity, and resource availability
|
||||
- **Smart Artifact Management** – Git Repositorys-first approach with local fallback support
|
||||
- **Multiple Node Support** – Deploy multiple Wallarm instances on the same VM with unique port configurations
|
||||
- **Automated Preflight Checks** – Validates system readiness, network connectivity, and resource availability (per deployment type)
|
||||
- **Smart Artifact Management** – Git Repositorys-first approach with local fallback support (Docker type)
|
||||
- **Multiple Node Support (Docker)** – Deploy multiple Wallarm instances on the same VM with unique port configurations
|
||||
- **Interactive Configuration** – User-friendly prompts for cloud region, ports, token, and upstream applications
|
||||
- **Comprehensive Validation** – Network tests, port availability checks, and deployment verification
|
||||
- **Persistence & Management** – Automatic service creation, start scripts, and health monitoring
|
||||
- **Persistence & Management** – Automatic service creation (systemd/OpenRC/SysV), start scripts, and health monitoring
|
||||
- **Post‑Deployment Reconfiguration** – Easily update trusted proxy IPs and change operation mode without redeploying
|
||||
- **Clean Uninstallation** – Safe removal of containers, images, and configuration files
|
||||
- **Clean Uninstallation** – Safe removal of containers, packages, and configuration files
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### System Requirements
|
||||
- **Operating System**: Linux (Ubuntu 20.04+, CentOS/RHEL 8+, Debian 11+)
|
||||
- **Architecture**: x86_64 (amd64)
|
||||
- **Operating System**: Linux (Ubuntu 20.04+, CentOS/RHEL 8+, Debian 11+, Alpine)
|
||||
- **Architecture**: x86_64 (amd64) or aarch64 (arm64) for native; x86_64 for Docker artifacts
|
||||
- **Memory**: Minimum 2GB RAM (4GB recommended for production)
|
||||
- **Storage**: Minimum 10GB free disk space
|
||||
- **Network**: Outbound connectivity to Wallarm cloud endpoints
|
||||
|
|
@ -25,52 +36,71 @@ A comprehensive solution for deploying Wallarm filtering nodes on virtual machin
|
|||
### Software Dependencies
|
||||
- **Bash**: Version 4.0+ (included with most Linux distributions)
|
||||
- **curl** or **wget**: For downloading scripts and artifacts
|
||||
- **sudo**: For Docker installation and system configuration
|
||||
- **systemd** or **sysvinit**: For service management
|
||||
- **sudo**: For package installation and system configuration
|
||||
- **systemd**, **OpenRC** or **sysvinit**: For service management
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 1. Download the Scripts
|
||||
|
||||
Use the wrapper script to download all necessary tools:
|
||||
Use the wrapper script to download all necessary tools. You will be asked to select the deployment type (`docker` or `native`):
|
||||
|
||||
```bash
|
||||
curl -fsSL "https://git.sechpoint.app/customer-engineering/wallarm/raw/branch/main/setup.sh" | bash
|
||||
```
|
||||
|
||||
This will download and make executable:
|
||||
To select non-interactively (e.g. for automation):
|
||||
|
||||
- `wallarm-ct-check.sh` – Preflight validation
|
||||
- `wallarm-ct-deploy.sh` – Main deployment script
|
||||
- `wallarm-ct-reconfigure.sh` – Modify configuration after deployment
|
||||
- `wallarm-ct-uninstall.sh` – Remove a Wallarm node
|
||||
```bash
|
||||
DEPLOYMENT_TYPE=native curl -fsSL "https://git.sechpoint.app/customer-engineering/wallarm/raw/branch/main/setup.sh" | bash
|
||||
```
|
||||
|
||||
The setup script downloads the shared library and makes executable:
|
||||
|
||||
- `common/wallarm-lib.sh` – Shared functions for both deployment types
|
||||
- `docker/wallarm-ct-check.sh` – Preflight validation (Docker)
|
||||
- `docker/wallarm-ct-deploy.sh` – Main deployment script (Docker)
|
||||
- `docker/wallarm-ct-reconfigure.sh` – Modify configuration after deployment (Docker)
|
||||
- `docker/wallarm-ct-uninstall.sh` – Remove a Wallarm node (Docker)
|
||||
- `native/wallarm-ct-check.sh` – Preflight validation (Native)
|
||||
- `native/wallarm-ct-deploy.sh` – Main deployment script (Native)
|
||||
- `native/wallarm-ct-reconfigure.sh` – Modify configuration after deployment (Native)
|
||||
- `native/wallarm-ct-uninstall.sh` – Remove a Wallarm node (Native)
|
||||
- `native/wallarm-native.sh` – Unified single-script manager for the Wallarm Native Node (connector mode)
|
||||
|
||||
### 2. Run Preflight Check
|
||||
|
||||
```bash
|
||||
./wallarm-ct-check.sh
|
||||
# Docker deployment
|
||||
./docker/wallarm-ct-check.sh
|
||||
|
||||
# Native deployment
|
||||
./native/wallarm-ct-check.sh
|
||||
```
|
||||
|
||||
The preflight check will:
|
||||
- Verify system compatibility (OS, architecture, init system)
|
||||
- Test network connectivity to Wallarm cloud endpoints
|
||||
- Check for existing Docker installations
|
||||
- Validate artifact availability (Docker: Git repo / local files; Native: all-in-one installer)
|
||||
- Validate resource availability
|
||||
- Generate a `.env` file with results
|
||||
|
||||
### 3. Deploy Wallarm Node
|
||||
|
||||
```bash
|
||||
sudo ./wallarm-ct-deploy.sh
|
||||
# Docker deployment
|
||||
sudo ./docker/wallarm-ct-deploy.sh
|
||||
|
||||
# Native deployment
|
||||
sudo ./native/wallarm-ct-deploy.sh
|
||||
```
|
||||
|
||||
The deployment script will:
|
||||
1. Read preflight check results
|
||||
2. Prompt for configuration (ports, upstream application, Wallarm token, trusted proxies)
|
||||
3. Install Docker if not present
|
||||
4. Download and load Wallarm Docker image
|
||||
5. Configure and start the Wallarm container
|
||||
6. Verify deployment with health checks
|
||||
3. **Docker**: Install Docker, download and load the Wallarm image, configure and start the container
|
||||
4. **Native**: Download and run the Wallarm all-in-one installer, configure NGINX, reload and verify
|
||||
5. Verify deployment with health checks
|
||||
|
||||
## Required Information Before Deployment
|
||||
|
||||
|
|
@ -79,17 +109,17 @@ To ensure a smooth deployment, have the following information ready before start
|
|||
| Item | Description | Example | Notes |
|
||||
|------|-------------|---------|-------|
|
||||
| **Inbound Port** | The port on which the Wallarm node will listen for incoming HTTP traffic. | `80` (HTTP) or `8080` | Must be unused on the server. If port 80 is already in use, choose another. |
|
||||
| **Application Server (Upstream) IP/Hostname** | The IP address or hostname of the backend application that Wallarm will forward traffic to. | `192.168.1.100` or `app.internal.local` | Must be reachable from the Wallarm **container**. If the application runs on the same physical machine, do **not** use `127.0.0.1` – use the host’s actual IP (e.g., `172.17.0.1` for the default Docker bridge, or the machine’s LAN IP). |
|
||||
| **Application Server (Upstream) IP/Hostname** | The IP address or hostname of the backend application that Wallarm will forward traffic to. | `192.168.1.100` or `app.internal.local` | Must be reachable from the Wallarm node. If the application runs on the same physical machine, do **not** use `127.0.0.1` – use the host's actual IP. |
|
||||
| **Application Server Port** | The port on which the backend application listens. | `8080` | Must be open and listening. |
|
||||
| **Wallarm Node Token** | A token obtained from the Wallarm Console when creating a new "Wallarm node". | `base64_encoded_string` | Copy it exactly. It will be pasted during the deployment process. |
|
||||
| **Trusted Proxy IPs/CIDRs** (Optional) | The IP address(es) of any load balancers, firewalls, or CDNs that sit in front of the Wallarm node and set the `X-Real-IP` header. | `10.0.0.10` or `192.168.0.0/24` | If the node is directly accessible from the internet (no proxy in front), leave empty. If there is a proxy, you must list its IP(s) so that Wallarm can extract the real client IP. Multiple entries can be space-separated. |
|
||||
| **Trusted Proxy IPs/CIDRs** (Optional) | The IP address(es) of any load balancers, firewalls, or CDNs that sit in front of the Wallarm node and set the `X-Real-IP` header. | `10.0.0.10` or `192.168.0.0/24` | If the node is directly accessible from the internet (no proxy in front), leave empty. Multiple entries can be space-separated. |
|
||||
| **Wallarm Cloud Region** | Which Wallarm cloud to use – US or EU. | `US` or `EU` | The script will test connectivity to both and only show reachable ones. |
|
||||
| **Operation Mode** (Optional, can be changed later) | The initial operation mode. `monitoring` only logs attacks, `block` actively blocks. | `monitoring` (recommended for first deployment) | The script defaults to `monitoring`. You can change it later using the reconfigure script. |
|
||||
|
||||
### Additional Preparation Steps
|
||||
|
||||
- **Ensure the backend application is running** and reachable from the Wallarm server. Test with `telnet <upstream_ip> <upstream_port>`.
|
||||
- **If you plan to use a custom domain**, be prepared to configure DNS to point to the server’s public IP (or the load balancer) – the Wallarm node itself does not require a domain for basic setup.
|
||||
- **If you plan to use a custom domain**, be prepared to configure DNS to point to the server's public IP (or the load balancer) – the Wallarm node itself does not require a domain for basic setup.
|
||||
- **If the server is behind a firewall**, open the inbound port (e.g., 80) to allow traffic from the internet or the load balancer.
|
||||
|
||||
## Detailed Usage
|
||||
|
|
@ -104,7 +134,7 @@ To ensure a smooth deployment, have the following information ready before start
|
|||
Before deployment, you need a Wallarm Node Token from the Wallarm Console:
|
||||
- **Create Token**: Navigate to Wallarm Console → **Nodes** → **Create node**
|
||||
- **Token Format**: Base64 encoded string (alphanumeric with `+`, `/`, `=`, `-`, `_`)
|
||||
- **Documentation**: [Official Wallarm Documentation](https://docs.wallarm.com/admin-en/installation-docker-en/)
|
||||
- **Documentation**: [Official Wallarm Documentation](https://docs.wallarm.com/)
|
||||
|
||||
#### Header Configuration for Firewalls/Ingress Controllers
|
||||
To ensure proper IP address detection and metadata forwarding, configure your firewall or ingress controller to include these headers:
|
||||
|
|
@ -116,7 +146,9 @@ proxy_set_header X-Forwarded-Proto $scheme;
|
|||
proxy_set_header X-Forwarded-Host $host;
|
||||
```
|
||||
|
||||
**Note**: The deployment script configures the first three headers automatically. You must manually add `X-Forwarded-Host: "$host"` to your existing firewall/ingress configuration.
|
||||
**Note**: The deployment scripts configure the first three headers automatically. You must manually add `X-Forwarded-Host: "$host"` to your existing firewall/ingress configuration.
|
||||
|
||||
## Docker Deployment (`docker/`)
|
||||
|
||||
### Multiple Node Deployment on Same VM
|
||||
|
||||
|
|
@ -133,7 +165,7 @@ You can deploy multiple Wallarm nodes on the same virtual machine by:
|
|||
|
||||
3. **Isolated Configuration**: Each instance has its own:
|
||||
- Docker container with unique name
|
||||
- Configuration directory (`/opt/wallarm/<instance-name>/`)
|
||||
- Configuration directory (`/opt/wallarm-<instance-name>/`)
|
||||
- Port binding and network namespace
|
||||
- Log files and start scripts
|
||||
|
||||
|
|
@ -142,6 +174,47 @@ You can deploy multiple Wallarm nodes on the same virtual machine by:
|
|||
- Each instance requires ~2GB disk space
|
||||
- Consider CPU allocation (1 vCPU core per 2-3 instances for moderate traffic)
|
||||
|
||||
## Native Deployment (`native/`)
|
||||
|
||||
The native deployment installs Wallarm directly on the operating system **without Docker**, using the official Wallarm **all-in-one installer**:
|
||||
|
||||
- The installer is downloaded from `https://meganode.wallarm.com/` (version configurable via the `WALLARM_VERSION` environment variable, default `6.12.7`)
|
||||
- It automatically detects your OS and NGINX version, adds the Wallarm repositories, installs `wallarm-node` + the NGINX dynamic module, and registers the node
|
||||
- Node registration is performed by the installer itself in batch mode (using your Wallarm token)
|
||||
- The node configuration is written to `/opt/wallarm/etc/wallarm/node.yaml`
|
||||
- The system NGINX is configured with a `wallarm-<instance>.conf` server block in `/etc/nginx/conf.d/`
|
||||
|
||||
**Notes on native deployment:**
|
||||
- **One node per host**: native uses the system NGINX, so multiple Wallarm nodes on one host are not supported (unlike Docker). Use unique ingress ports only if you run a single node alongside other services.
|
||||
- The deploy script keeps a copy of the generated NGINX config in `/opt/wallarm/<instance-name>/nginx.conf` and a log of the `nginx -t` test.
|
||||
- `curl http://127.0.0.8/wallarm-status` reports Wallarm module statistics after deployment.
|
||||
|
||||
### Example: Version Pinning
|
||||
|
||||
```bash
|
||||
WALLARM_VERSION=6.12.7 sudo ./native/wallarm-ct-deploy.sh
|
||||
```
|
||||
|
||||
### Unified Node Manager (`native/wallarm-native.sh`)
|
||||
|
||||
For the **Wallarm Native Node** product (go-node, `connector-server` mode, no NGINX module), the repository provides a unified single-script manager. It manages multiple isolated nodes under `/opt/wallarm/nodes/` via a systemd template unit (`wallarm-node@<name>.service`):
|
||||
|
||||
```bash
|
||||
sudo ./native/wallarm-native.sh --preflight # preflight checks only
|
||||
sudo ./native/wallarm-native.sh --install # interactive multi-node install (parallel)
|
||||
sudo ./native/wallarm-native.sh --config --node node1 --address 0.0.0.0:9090
|
||||
sudo ./native/wallarm-native.sh --remove --node node2
|
||||
sudo ./native/wallarm-native.sh --status [NODE] # node status (all or one)
|
||||
```
|
||||
|
||||
Key characteristics:
|
||||
- **Preflight checks** run automatically before `--install` and are available standalone via `--preflight` (root, systemd, architecture, required commands, installer + Wallarm cloud connectivity, disk/memory, listen-port availability)
|
||||
- Per-node isolated directories (`etc/`, `var/log/`, `var/run/`), with the Wallarm token stored in a `chmod 600` env file
|
||||
- All-in-one installer is downloaded from `https://repo.wallarm.com/linux/wallarm-native-node/latest/all-in-one/` (override with `WALLARM_INSTALLER_URL`, architecture with `WALLARM_INSTALLER_ARCH`)
|
||||
- Parallel installation with per-node install logs (`install.log`)
|
||||
|
||||
> **Note:** This script targets the Wallarm **Native Node** (connector mode). The `native/wallarm-ct-*.sh` scripts target the **NGINX-module** native deployment. Both are no-Docker options; choose the one that matches your Wallarm product.
|
||||
|
||||
## Reconfiguration Script (`wallarm-ct-reconfigure.sh`)
|
||||
|
||||
After deployment, you may need to adjust:
|
||||
|
|
@ -149,44 +222,54 @@ After deployment, you may need to adjust:
|
|||
- **Trusted proxy IPs/CIDRs** – When the network topology changes (new load balancer, CDN, firewall)
|
||||
- **Operation mode** – Switch from `monitoring` to `block` after verifying correct operation
|
||||
|
||||
The reconfigure script safely modifies the `nginx.conf` of an existing instance, creates a backup, and restarts the container.
|
||||
The reconfigure script safely modifies the configuration of an existing instance, creates a backup, and applies the changes (Docker: restarts the container; Native: tests and reloads NGINX).
|
||||
|
||||
**Usage**:
|
||||
```bash
|
||||
sudo ./wallarm-ct-reconfigure.sh
|
||||
# Docker
|
||||
sudo ./docker/wallarm-ct-reconfigure.sh
|
||||
|
||||
# Native
|
||||
sudo ./native/wallarm-ct-reconfigure.sh
|
||||
```
|
||||
|
||||
It will detect installed instances, show current settings, and guide you through the changes.
|
||||
|
||||
## Uninstallation (`wallarm-ct-uninstall.sh`)
|
||||
|
||||
To completely remove a Wallarm node and optionally Docker:
|
||||
To completely remove a Wallarm node:
|
||||
|
||||
```bash
|
||||
sudo ./wallarm-ct-uninstall.sh
|
||||
# Docker: remove container/image and optionally Docker
|
||||
sudo ./docker/wallarm-ct-uninstall.sh
|
||||
|
||||
# Native: remove NGINX config, Wallarm packages, and node data
|
||||
sudo ./native/wallarm-ct-uninstall.sh
|
||||
```
|
||||
|
||||
## Artifact Sources (Priority Order)
|
||||
## Artifact Sources
|
||||
|
||||
The system uses a smart fallback approach for artifact retrieval:
|
||||
### Docker Deployment (Priority Order)
|
||||
|
||||
### 1. **Primary Source**: Git Repositorys
|
||||
The Docker deployment uses a smart fallback approach for artifact retrieval:
|
||||
|
||||
1. **Primary Source**: Git Repositorys
|
||||
- URL: `https://git.sechpoint.app/customer-engineering/wallarm`
|
||||
- Contains: Docker binaries and Wallarm images with SHA256 checksums
|
||||
- Contains: `docker/binaries/` (Docker static binaries) and `docker/images/` (Wallarm images) with SHA256 checksums
|
||||
- Benefits: Version control, access control, audit trail
|
||||
|
||||
### 2. **Secondary Source**: Local Directories
|
||||
- `./binaries/` – Docker static binaries (`docker-29.2.1.tgz`)
|
||||
- `./images/` – Wallarm Docker images (`wallarm-node-6.11.0-rc1.tar.gz`)
|
||||
2. **Secondary Source**: Local Directories
|
||||
- `docker/binaries/` – Docker static binaries (`docker-29.2.1.tgz`)
|
||||
- `docker/images/` – Wallarm Docker images (`wallarm-node-6.11.0-rc1.tar.gz`)
|
||||
- Benefits: Air‑gapped environments, faster deployment
|
||||
|
||||
### 3. **Tertiary Source**: Current Directory
|
||||
3. **Tertiary Source**: Current Directory
|
||||
- Any `docker-*.tgz` or `wallarm-node-*.tar.gz` files in script location
|
||||
- Benefits: Ad‑hoc deployments, testing scenarios
|
||||
|
||||
### 4. **Fallback Source**: Internal Proxy Servers
|
||||
- Original infrastructure URLs (with embedded credentials)
|
||||
- Used only when other sources are unavailable
|
||||
### Native Deployment (Source)
|
||||
|
||||
The native deployment downloads the Wallarm **all-in-one installer** directly from `https://meganode.wallarm.com/`. No Docker artifacts are required. Current versions are listed at [node-artifact-versions](https://docs.wallarm.com/updating-migrating/node-artifact-versions/).
|
||||
|
||||
## Suggested Resources
|
||||
|
||||
|
|
@ -211,30 +294,42 @@ The system uses a smart fallback approach for artifact retrieval:
|
|||
|
||||
## Script Reference
|
||||
|
||||
### `wallarm-ct-check.sh`
|
||||
### `common/wallarm-lib.sh`
|
||||
**Purpose**: Shared library used by all deployment scripts (both types)
|
||||
|
||||
**Key Functions**:
|
||||
- Logging (`log_message`, `fail_with_remediation`)
|
||||
- System detection (OS, architecture, init system)
|
||||
- Network connectivity tests
|
||||
- Preflight `.env` parsing (`load_env_file`)
|
||||
- Cloud region selection (`select_cloud_region`)
|
||||
- Validation helpers (IP address, CIDR, port availability)
|
||||
- Artifact download and checksum verification
|
||||
|
||||
### `docker/wallarm-ct-check.sh` / `native/wallarm-ct-check.sh`
|
||||
**Purpose**: System validation and preflight checks
|
||||
|
||||
**Key Functions**:
|
||||
- OS compatibility verification (Ubuntu, CentOS, Debian)
|
||||
- OS compatibility verification (Ubuntu, CentOS, Debian, Alpine)
|
||||
- Network connectivity testing (US/EU cloud endpoints)
|
||||
- Resource availability assessment
|
||||
- Docker installation checking
|
||||
- Artifact source validation (Docker: binaries/images; Native: installer)
|
||||
- Environment file generation (`.env`)
|
||||
|
||||
**Usage**:
|
||||
```bash
|
||||
# Run check with default settings
|
||||
./wallarm-ct-check.sh
|
||||
./<type>/wallarm-ct-check.sh
|
||||
|
||||
# Enable debug output
|
||||
DEBUG=1 ./wallarm-ct-check.sh
|
||||
DEBUG=1 ./<type>/wallarm-ct-check.sh
|
||||
|
||||
# Disable SSL certificate validation (for self-signed certs)
|
||||
WALLARM_INSECURE_SSL=0 ./wallarm-ct-check.sh
|
||||
WALLARM_INSECURE_SSL=0 ./<type>/wallarm-ct-check.sh
|
||||
```
|
||||
|
||||
### `wallarm-ct-deploy.sh`
|
||||
**Purpose**: Wallarm node deployment and configuration
|
||||
### `docker/wallarm-ct-deploy.sh`
|
||||
**Purpose**: Wallarm node deployment and configuration (Docker)
|
||||
|
||||
**Key Functions**:
|
||||
- Interactive configuration wizard
|
||||
|
|
@ -247,10 +342,56 @@ WALLARM_INSECURE_SSL=0 ./wallarm-ct-check.sh
|
|||
**Usage**:
|
||||
```bash
|
||||
# Interactive deployment
|
||||
sudo ./wallarm-ct-deploy.sh
|
||||
sudo ./docker/wallarm-ct-deploy.sh
|
||||
|
||||
# Deployment with pre-filled environment (optional)
|
||||
WALLARM_TOKEN="your_token_here" sudo ./wallarm-ct-deploy.sh
|
||||
WALLARM_TOKEN="your_token_here" sudo ./docker/wallarm-ct-deploy.sh
|
||||
```
|
||||
|
||||
### `native/wallarm-ct-deploy.sh`
|
||||
**Purpose**: Wallarm node deployment and configuration (Native, no Docker)
|
||||
|
||||
**Key Functions**:
|
||||
- Interactive configuration wizard
|
||||
- Downloads and runs the Wallarm all-in-one installer (batch mode)
|
||||
- Node registration with your Wallarm token
|
||||
- NGINX server block configuration (proxy, wallarm_mode, trusted proxies, health endpoint)
|
||||
- NGINX test + reload
|
||||
- Health check and deployment verification
|
||||
|
||||
**Usage**:
|
||||
```bash
|
||||
# Interactive deployment
|
||||
sudo ./native/wallarm-ct-deploy.sh
|
||||
|
||||
# Pin a specific Wallarm version
|
||||
WALLARM_VERSION=6.12.7 sudo ./native/wallarm-ct-deploy.sh
|
||||
|
||||
# Add node labels (group)
|
||||
WALLARM_LABELS='group=prod' sudo ./native/wallarm-ct-deploy.sh
|
||||
```
|
||||
|
||||
### `native/wallarm-native.sh`
|
||||
**Purpose**: Unified single-script manager for the Wallarm Native Node (connector mode, no Docker/NGINX module)
|
||||
|
||||
**Key Functions**:
|
||||
- Preflight checks (root, systemd, architecture, commands, connectivity, resources, ports)
|
||||
- Interactive multi-node installation in parallel with per-node systemd template units
|
||||
- Configuration updates (address, token, labels) and node removal
|
||||
- Status reporting via systemd
|
||||
|
||||
**Usage**:
|
||||
```bash
|
||||
# Preflight only
|
||||
sudo ./native/wallarm-native.sh --preflight
|
||||
|
||||
# Interactive install
|
||||
sudo ./native/wallarm-native.sh --install
|
||||
|
||||
# Update config / remove / status
|
||||
sudo ./native/wallarm-native.sh --config --node node1 --address 0.0.0.0:9090
|
||||
sudo ./native/wallarm-native.sh --remove --node node2
|
||||
sudo ./native/wallarm-native.sh --status
|
||||
```
|
||||
|
||||
### `wallarm-ct-reconfigure.sh`
|
||||
|
|
@ -260,11 +401,11 @@ WALLARM_TOKEN="your_token_here" sudo ./wallarm-ct-deploy.sh
|
|||
- Update `set_real_ip_from` (trusted proxy IPs/CIDRs)
|
||||
- Change `wallarm_mode` (monitoring/block)
|
||||
- Create backup of current configuration
|
||||
- Restart container to apply changes
|
||||
- Apply changes (Docker: container restart; Native: NGINX reload)
|
||||
|
||||
**Usage**:
|
||||
```bash
|
||||
sudo ./wallarm-ct-reconfigure.sh
|
||||
sudo ./<type>/wallarm-ct-reconfigure.sh
|
||||
```
|
||||
|
||||
### `wallarm-ct-uninstall.sh`
|
||||
|
|
@ -272,21 +413,14 @@ sudo ./wallarm-ct-reconfigure.sh
|
|||
|
||||
**Key Functions**:
|
||||
- Interactive confirmation with safety checks
|
||||
- Container stopping and removal
|
||||
- Image cleanup
|
||||
- Docker: container/image removal, Docker cleanup; Native: NGINX config + package removal
|
||||
- Configuration directory removal
|
||||
- Optional Docker binary cleanup
|
||||
- Optional artifact cleanup
|
||||
|
||||
**Usage**:
|
||||
```bash
|
||||
# Interactive uninstallation
|
||||
sudo ./wallarm-ct-uninstall.sh
|
||||
|
||||
# Force removal without prompts (use with caution)
|
||||
FORCE=1 sudo ./wallarm-ct-uninstall.sh
|
||||
|
||||
# Remove Docker binaries (if no other containers exist)
|
||||
REMOVE_DOCKER=1 sudo ./wallarm-ct-uninstall.sh
|
||||
sudo ./<type>/wallarm-ct-uninstall.sh
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
|
@ -310,7 +444,7 @@ cat /etc/os-release
|
|||
#### 2. Deployment Fails – Port Conflicts
|
||||
```bash
|
||||
# Check for listening ports
|
||||
sudo ss -tlnp | grep ':80\|:90\|:8080'
|
||||
sudo ss -tlnp | grep ':80\|:8080'
|
||||
|
||||
# Find process using port
|
||||
sudo lsof -i :80
|
||||
|
|
@ -324,7 +458,7 @@ sudo lsof -i :80
|
|||
echo "your_token" | base64 -d 2>/dev/null | base64
|
||||
|
||||
# Get new token from Wallarm Console
|
||||
# https://docs.wallarm.com/admin-en/installation-docker-en/
|
||||
# https://docs.wallarm.com/
|
||||
```
|
||||
|
||||
#### 4. Docker Installation Problems
|
||||
|
|
@ -339,7 +473,19 @@ groups $USER
|
|||
docker run --rm hello-world
|
||||
```
|
||||
|
||||
#### 5. Header Configuration Warnings
|
||||
#### 5. Native Installer Fails
|
||||
```bash
|
||||
# The all-in-one installer logs its output to the terminal and to files
|
||||
# Check the current version at https://docs.wallarm.com/updating-migrating/node-artifact-versions/
|
||||
|
||||
# Verify node registration
|
||||
ls -la /opt/wallarm/etc/wallarm/node.yaml
|
||||
|
||||
# Check Wallarm module status
|
||||
curl http://127.0.0.8/wallarm-status
|
||||
```
|
||||
|
||||
#### 6. Header Configuration Warnings
|
||||
Ensure your upstream firewall/load balancer includes:
|
||||
- `X-Real-IP: "$remote_addr"`
|
||||
- `X-Forwarded-For: "$proxy_add_x_forwarded_for"`
|
||||
|
|
@ -347,42 +493,65 @@ Ensure your upstream firewall/load balancer includes:
|
|||
- `X-Forwarded-Host: "$host"`
|
||||
|
||||
### Log Files
|
||||
- **Preflight Check**: `~/logs/wallarm-check.log`
|
||||
- **Deployment**: `~/logs/wallarm-deployment.log`
|
||||
- **Container Logs**: `/opt/wallarm/<instance-name>/container.log`
|
||||
- **Preflight Check**: `~/logs/wallarm-check.log` (Docker) / `~/logs/wallarm-check-native.log` (Native)
|
||||
- **Deployment**: `~/logs/wallarm-deployment.log` (Docker) / `~/logs/wallarm-deployment-native.log` (Native)
|
||||
- **Docker Container Logs**: `/opt/wallarm-<instance-name>/container.log`
|
||||
- **NGINX Logs (Native)**: `/var/log/nginx/error.log`
|
||||
- **System Logs**: `/var/log/syslog` or `/var/log/messages`
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Network Security
|
||||
- Use firewall rules to restrict access to monitoring ports (default: 90, 190, 290, etc.)
|
||||
- Use firewall rules to restrict access to monitoring endpoints
|
||||
- Consider VPN or private networking for management interfaces
|
||||
- Implement rate limiting for ingress ports
|
||||
|
||||
### Access Control
|
||||
- Restrict `sudo` access to deployment scripts
|
||||
- Use separate service accounts for Wallarm containers
|
||||
- Use separate service accounts for Wallarm services
|
||||
- Implement proper secret management for Wallarm tokens
|
||||
|
||||
### Monitoring & Auditing
|
||||
- Enable Docker logging driver with rotation
|
||||
- Monitor container resource usage
|
||||
- Regular security updates for Docker and host OS
|
||||
- Enable logging with rotation
|
||||
- Monitor resource usage
|
||||
- Regular security updates for Docker/NGINX and host OS
|
||||
|
||||
## Maintenance
|
||||
|
||||
### Regular Tasks
|
||||
1. **Log Rotation**: Configure logrotate for container logs
|
||||
2. **Docker Updates**: Periodically update Docker engine
|
||||
3. **Image Updates**: Check for new Wallarm node versions
|
||||
1. **Log Rotation**: Configure logrotate for logs
|
||||
2. **Updates**: Periodically update Docker engine/NGINX and Wallarm node
|
||||
3. **Image/Version Updates**: Check for new Wallarm node versions
|
||||
4. **Backup**: Regular backup of configuration directories
|
||||
|
||||
### Version Updates
|
||||
When updating Wallarm node version:
|
||||
1. Pull new image from Git Repositorys or official registry
|
||||
2. Stop existing container
|
||||
3. Deploy new container with updated image
|
||||
4. Verify functionality before removing old container
|
||||
1. **Docker**: Pull new image from Git Repositorys or official registry, stop existing container, deploy new container with updated image, verify functionality before removing old container
|
||||
2. **Native**: Set `WALLARM_VERSION` to the new version and re-run the deploy script, or follow the [official upgrade guide](https://docs.wallarm.com/updating-migrating/)
|
||||
|
||||
## Repository Structure
|
||||
|
||||
```
|
||||
wallarm/
|
||||
├── README.md
|
||||
├── changelog.md
|
||||
├── setup.sh # Downloads scripts for a chosen deployment type
|
||||
├── common/
|
||||
│ └── wallarm-lib.sh # Shared library (both deployment types)
|
||||
├── docker/ # Docker deployment
|
||||
│ ├── wallarm-ct-check.sh
|
||||
│ ├── wallarm-ct-deploy.sh
|
||||
│ ├── wallarm-ct-reconfigure.sh
|
||||
│ ├── wallarm-ct-uninstall.sh
|
||||
│ ├── binaries/ # Docker static binaries
|
||||
│ └── images/ # Wallarm Docker images
|
||||
└── native/ # Native deployment (no Docker)
|
||||
├── wallarm-ct-check.sh
|
||||
├── wallarm-ct-deploy.sh
|
||||
├── wallarm-ct-reconfigure.sh
|
||||
├── wallarm-ct-uninstall.sh
|
||||
└── wallarm-native.sh # Unified single-script node manager (Native Node product)
|
||||
```
|
||||
|
||||
## Disclaimer
|
||||
|
||||
|
|
|
|||
35
changelog.md
35
changelog.md
|
|
@ -5,6 +5,41 @@ All notable changes to this project will be documented in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to date-based versioning (YYYY-MM.x).
|
||||
|
||||
## [2026-08.1] - 2026-08-01
|
||||
### Added
|
||||
- **Native deployment type**: Wallarm filtering node can now be deployed directly on the OS **without Docker**
|
||||
- `native/wallarm-ct-check.sh` – Preflight validation for native deployment (no Docker artifact checks)
|
||||
- `native/wallarm-ct-deploy.sh` – Downloads and runs the official Wallarm all-in-one installer (`meganode.wallarm.com`, version configurable via `WALLARM_VERSION`), configures the NGINX server block, reloads and verifies the node
|
||||
- `native/wallarm-ct-reconfigure.sh` – Update trusted proxies / `wallarm_mode` via NGINX test + reload
|
||||
- `native/wallarm-ct-uninstall.sh` – Remove NGINX config, Wallarm packages/repos, and `/opt/wallarm` data
|
||||
- **Unified node manager**: `native/wallarm-native.sh` – single-script manager for the Wallarm Native Node (go-node, connector-server mode)
|
||||
- `--preflight` checks (root, systemd, architecture, required commands, installer + Wallarm cloud connectivity, disk/memory, listen-port availability); auto-run before `--install`
|
||||
- Interactive parallel multi-node installation with per-node systemd template units (`wallarm-node@<name>.service`)
|
||||
- `--config` (address/token/labels, safe env rewrite), `--remove`, `--status [NODE]`
|
||||
- All-in-one installer from `repo.wallarm.com` (overridable via `WALLARM_INSTALLER_URL`/`WALLARM_INSTALLER_ARCH`)
|
||||
- **Shared library**: `common/wallarm-lib.sh` extracted and reused by both deployment types
|
||||
- Colors, logging (`log_message`, `fail_with_remediation`), early error handler
|
||||
- System detection (OS/arch/init), network connectivity tests
|
||||
- Preflight `.env` parsing (`load_env_file`), cloud region selection (`select_cloud_region`)
|
||||
- Validation helpers (IP, CIDR, port), artifact download + checksum verification
|
||||
|
||||
### Changed
|
||||
- **Repository structure** now separates deployment types:
|
||||
- `docker/` – all Docker-based scripts moved here (`git mv`, history preserved)
|
||||
- `docker/binaries/` and `docker/images/` – Docker artifacts moved into the Docker tree
|
||||
- `native/` – new native (no-Docker) deployment scripts
|
||||
- `common/` – shared library
|
||||
- **Artifact URLs** updated to the `docker/` prefix (`/docker/binaries/...`, `/docker/images/...`)
|
||||
- **Docker scripts** refactored to source `common/wallarm-lib.sh` (removed duplicated helper functions; behavior preserved)
|
||||
- **setup.sh** now prompts for a deployment type (`docker` or `native`), downloads the matching scripts into `docker/` or `native/` (native now includes `wallarm-native.sh`); supports `DEPLOYMENT_TYPE=native` for non-interactive use
|
||||
- **README.md** rewritten to document both deployment types, the new structure, the unified manager, and native-specific usage
|
||||
|
||||
### Notes
|
||||
- Native deployment supports one node per host (system NGINX); multi-node remains a Docker feature
|
||||
- Native installer version defaults to `6.12.7` and can be pinned via `WALLARM_VERSION`
|
||||
- Docker deployment behavior is unchanged apart from the new directory layout
|
||||
- The unified manager targets the Wallarm **Native Node** product; the `native/wallarm-ct-*.sh` scripts target the **NGINX-module** native deployment. Both are no-Docker options
|
||||
|
||||
## [2026-04.1] - 2026-04-21
|
||||
### Added
|
||||
- Initial changelog file with versioning schema
|
||||
|
|
|
|||
530
common/wallarm-lib.sh
Executable file
530
common/wallarm-lib.sh
Executable file
|
|
@ -0,0 +1,530 @@
|
|||
#!/bin/bash
|
||||
# ==============================================================================
|
||||
# WALLARM COMMON LIBRARY - shared functions for docker/ and native/ deployment
|
||||
# ==============================================================================
|
||||
# Purpose: Single source of truth for functionality shared by both deployment
|
||||
# types (Docker container vs native NGINX install).
|
||||
# Usage: Scripts source this file AFTER setting `set -euo pipefail` and before
|
||||
# defining their own functions:
|
||||
# source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/../common/wallarm-lib.sh"
|
||||
# The library does NOT set the error trap itself; each script owns its
|
||||
# error handling configuration.
|
||||
# ==============================================================================
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# COLOR DEFINITIONS (for better UX)
|
||||
# ------------------------------------------------------------------------------
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[1;34m'
|
||||
CYAN='\033[0;36m'
|
||||
MAGENTA='\033[0;35m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# SSL SECURITY SETTINGS
|
||||
# WALLARM_INSECURE_SSL=1 disables SSL certificate validation (for self-signed
|
||||
# certs). Kept as a default of 1 for backward compatibility with existing usage.
|
||||
# ------------------------------------------------------------------------------
|
||||
INSECURE_SSL="${WALLARM_INSECURE_SSL:-1}"
|
||||
if [ "$INSECURE_SSL" = "1" ]; then
|
||||
CURL_INSECURE_FLAG="-k"
|
||||
else
|
||||
CURL_INSECURE_FLAG=""
|
||||
fi
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# EARLY ERROR HANDLER
|
||||
# Use with: trap early_error_handler ERR
|
||||
# Handles failures before log_message is available (or when logging is not set).
|
||||
# ------------------------------------------------------------------------------
|
||||
early_error_handler() {
|
||||
echo -e "${RED}${BOLD}[ERROR]${NC} Script failed at line $LINENO. Command: $BASH_COMMAND" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# LOGGING
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Log a message to stderr (colored) and to $LOG_FILE (if set).
|
||||
log_message() {
|
||||
local level="$1"
|
||||
local message="$2"
|
||||
local timestamp
|
||||
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
|
||||
local color="$NC"
|
||||
case "$level" in
|
||||
"INFO") color="${BLUE}" ;;
|
||||
"SUCCESS") color="${GREEN}" ;;
|
||||
"WARNING") color="${YELLOW}" ;;
|
||||
"ERROR") color="${RED}" ;;
|
||||
"DEBUG") color="${CYAN}" ;;
|
||||
esac
|
||||
|
||||
echo -e "${color}[${timestamp}] ${level}: ${message}${NC}" >&2
|
||||
if [ -n "${LOG_FILE:-}" ]; then
|
||||
echo "[${timestamp}] ${level}: ${message}" >> "$LOG_FILE"
|
||||
fi
|
||||
}
|
||||
|
||||
# Log an ERROR, print a remediation banner, and exit non-zero.
|
||||
fail_with_remediation() {
|
||||
local error_msg="$1"
|
||||
local remediation="$2"
|
||||
|
||||
log_message "ERROR" "$error_msg"
|
||||
echo -e "\n${RED}${BOLD}╔══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${RED}${BOLD}║ DEPLOYMENT FAILED ║${NC}"
|
||||
echo -e "${RED}${BOLD}╚══════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo -e "\n${YELLOW}${BOLD}Root Cause:${NC} $error_msg"
|
||||
echo -e "\n${YELLOW}${BOLD}How to Fix:${NC}"
|
||||
echo -e "$remediation"
|
||||
echo -e "\n${YELLOW}Check the full log for details:${NC} ${LOG_FILE:-stdout}"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# MISC HELPERS
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Extract hostname from a URL, stripping protocol and credentials for safe logging.
|
||||
extract_hostname_from_url() {
|
||||
local url="$1"
|
||||
local hostpart="${url#*://}"
|
||||
hostpart="${hostpart#*@}"
|
||||
hostpart="${hostpart%%[:/]*}"
|
||||
echo "$hostpart"
|
||||
}
|
||||
|
||||
# Check whether a command exists (respects PATH + common system directories).
|
||||
command_exists() {
|
||||
local cmd="$1"
|
||||
if command -v "$cmd" >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
local system_dirs=("/usr/sbin" "/sbin" "/usr/local/sbin" "/usr/bin" "/bin" "/usr/local/bin")
|
||||
for dir in "${system_dirs[@]}"; do
|
||||
if [ -x "$dir/$cmd" ]; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
# Validate an IPv4 address (basic format + octet range check).
|
||||
validate_ip_address() {
|
||||
local ip="$1"
|
||||
|
||||
if [[ ! "$ip" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
IFS='.' read -r i1 i2 i3 i4 <<< "$ip"
|
||||
if [ "$i1" -gt 255 ] || [ "$i2" -gt 255 ] || [ "$i3" -gt 255 ] || [ "$i4" -gt 255 ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Validate an IP or CIDR entry (IPv4 with optional /prefix). Returns 0 if valid.
|
||||
validate_ip_or_cidr() {
|
||||
local entry="$1"
|
||||
|
||||
if [[ ! "$entry" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}(/[0-9]{1,2})?$ ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
IFS='/' read -r ip cidr <<< "$entry"
|
||||
IFS='.' read -r o1 o2 o3 o4 <<< "$ip"
|
||||
if [ "$o1" -gt 255 ] || [ "$o2" -gt 255 ] || [ "$o3" -gt 255 ] || [ "$o4" -gt 255 ]; then
|
||||
return 1
|
||||
fi
|
||||
if [ -n "$cidr" ] && { [ "$cidr" -lt 0 ] || [ "$cidr" -gt 32 ]; }; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Check if a TCP/UDP port is currently in use. Returns 0 when available.
|
||||
check_port_available() {
|
||||
local port="$1"
|
||||
local protocol="${2:-tcp}"
|
||||
|
||||
log_message "DEBUG" "Checking port $port/$protocol availability..."
|
||||
|
||||
if command -v ss >/dev/null 2>&1; then
|
||||
if ss -"${protocol:0:1}"ln | grep -q ":$port "; then
|
||||
return 1 # Port in use
|
||||
fi
|
||||
elif command -v netstat >/dev/null 2>&1; then
|
||||
if netstat -tulpn 2>/dev/null | grep -E ":$port\s" >/dev/null 2>&1; then
|
||||
return 1 # Port in use
|
||||
fi
|
||||
else
|
||||
log_message "WARNING" "Neither ss nor netstat available, cannot check port $port"
|
||||
fi
|
||||
|
||||
return 0 # Port available (or cannot check)
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# SYSTEM DETECTION
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Detect OS name and version. Prints "name:version".
|
||||
detect_os_and_version() {
|
||||
log_message "INFO" "Detecting OS and version..."
|
||||
|
||||
local os_name=""
|
||||
local os_version=""
|
||||
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
os_name="$ID"
|
||||
os_version="$VERSION_ID"
|
||||
elif [ -f /etc/redhat-release ]; then
|
||||
os_name="rhel"
|
||||
os_version=$(sed -e 's/.*release \([0-9]\+\)\..*/\1/' /etc/redhat-release)
|
||||
elif [ -f /etc/alpine-release ]; then
|
||||
os_name="alpine"
|
||||
os_version=$(cat /etc/alpine-release)
|
||||
else
|
||||
os_name=$(uname -s | tr '[:upper:]' '[:lower:]')
|
||||
os_version=$(uname -r)
|
||||
fi
|
||||
|
||||
os_name="${os_name//[$'\t\r\n']/}"
|
||||
os_version="${os_version//[$'\t\r\n']/}"
|
||||
|
||||
case "$os_name" in
|
||||
"ubuntu"|"debian"|"centos"|"rhel"|"alpine"|"amzn"|"ol"|"rocky"|"almalinux")
|
||||
log_message "SUCCESS" "OS detected: $os_name $os_version (supported)"
|
||||
;;
|
||||
*)
|
||||
log_message "WARNING" "OS '$os_name' not explicitly tested but may work"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "$os_name:$os_version"
|
||||
}
|
||||
|
||||
# Detect architecture. Prints a normalized value (x86_64/aarch64/armhf/unknown).
|
||||
detect_architecture() {
|
||||
log_message "INFO" "Detecting system architecture..."
|
||||
|
||||
local arch
|
||||
arch=$(uname -m)
|
||||
local docker_arch=""
|
||||
|
||||
case "$arch" in
|
||||
x86_64|x64|amd64)
|
||||
docker_arch="x86_64"
|
||||
log_message "SUCCESS" "Architecture: x86_64 (Intel/AMD 64-bit)"
|
||||
;;
|
||||
aarch64|arm64)
|
||||
docker_arch="aarch64"
|
||||
log_message "SUCCESS" "Architecture: aarch64 (ARM 64-bit)"
|
||||
;;
|
||||
armv7l|armhf)
|
||||
docker_arch="armhf"
|
||||
log_message "SUCCESS" "Architecture: armhf (ARM 32-bit)"
|
||||
;;
|
||||
*)
|
||||
log_message "ERROR" "Unsupported architecture: $arch"
|
||||
docker_arch="unknown"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "$docker_arch"
|
||||
}
|
||||
|
||||
# Detect the init system. Prints one of systemd/openrc/sysvinit/upstart/unknown.
|
||||
detect_init_system() {
|
||||
log_message "INFO" "Detecting init system..."
|
||||
|
||||
local init_system="unknown"
|
||||
|
||||
if [ "$(uname -s)" = "Darwin" ]; then
|
||||
init_system="darwin"
|
||||
log_message "SUCCESS" "Init system: darwin (macOS)"
|
||||
elif command -v systemctl >/dev/null 2>&1 && systemctl --version >/dev/null 2>&1; then
|
||||
init_system="systemd"
|
||||
log_message "SUCCESS" "Init system: systemd"
|
||||
elif { [ -d /etc/init.d ] && [ -x /sbin/initctl ]; } || [ -x /sbin/init ]; then
|
||||
init_system="sysvinit"
|
||||
log_message "SUCCESS" "Init system: sysvinit"
|
||||
elif [ -d /etc/rc.d ] && [ -x /sbin/rc-service ]; then
|
||||
init_system="openrc"
|
||||
log_message "SUCCESS" "Init system: openrc (Alpine)"
|
||||
elif [ -x /sbin/upstart ]; then
|
||||
init_system="upstart"
|
||||
log_message "SUCCESS" "Init system: upstart"
|
||||
else
|
||||
log_message "WARNING" "Could not determine init system"
|
||||
fi
|
||||
|
||||
echo "$init_system"
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# NETWORK CONNECTIVITY
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Test connectivity to a host/URL. Returns 0 when reachable.
|
||||
test_connectivity() {
|
||||
local host="$1"
|
||||
local description="$2"
|
||||
local timeout="${3:-10}"
|
||||
|
||||
local display_host
|
||||
display_host=$(extract_hostname_from_url "$host")
|
||||
log_message "INFO" "Testing connectivity to $description ($display_host)..."
|
||||
|
||||
local url="$host"
|
||||
if [[ ! "$host" =~ ^https?:// ]]; then
|
||||
url="https://$host"
|
||||
fi
|
||||
|
||||
if curl -sL $CURL_INSECURE_FLAG --connect-timeout "$timeout" "$url" >/dev/null 2>&1; then
|
||||
log_message "SUCCESS" "$description is reachable"
|
||||
return 0
|
||||
else
|
||||
log_message "ERROR" "$description is NOT reachable"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Test a set of cloud endpoints. Prints "true" if all reachable, else "false".
|
||||
test_cloud_endpoints() {
|
||||
local cloud_name="$1"
|
||||
shift
|
||||
local endpoints=("$@")
|
||||
|
||||
log_message "INFO" "Testing $cloud_name cloud endpoints..."
|
||||
|
||||
local all_reachable=true
|
||||
local endpoint
|
||||
for endpoint in "${endpoints[@]}"; do
|
||||
if ! test_connectivity "$endpoint" "$cloud_name cloud endpoint $endpoint"; then
|
||||
all_reachable=false
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$all_reachable" = "true" ]; then
|
||||
log_message "SUCCESS" "All $cloud_name cloud endpoints reachable"
|
||||
echo "true"
|
||||
else
|
||||
log_message "WARNING" "Some $cloud_name cloud endpoints unreachable"
|
||||
echo "false"
|
||||
fi
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ENVIRONMENT FILE HANDLING
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Load a preflight .env file into global variables. Returns 1 if file missing.
|
||||
load_env_file() {
|
||||
local env_file="${1:-$ENV_FILE}"
|
||||
|
||||
if [ ! -f "$env_file" ]; then
|
||||
log_message "ERROR" "Environment file not found: $env_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local key value
|
||||
while IFS='=' read -r key value; do
|
||||
[[ "$key" =~ ^#.*$ ]] && continue
|
||||
[[ -z "$key" ]] && continue
|
||||
|
||||
value="${value%\"}"
|
||||
value="${value#\"}"
|
||||
|
||||
case "$key" in
|
||||
result) CHECK_RESULT="$value" ;;
|
||||
os_name) OS_NAME="$value" ;;
|
||||
os_version) OS_VERSION="$value" ;;
|
||||
architecture) ARCHITECTURE="$value" ;;
|
||||
init_system) INIT_SYSTEM="$value" ;;
|
||||
us_cloud_reachable) US_CLOUD_REACHABLE="$value" ;;
|
||||
eu_cloud_reachable) EU_CLOUD_REACHABLE="$value" ;;
|
||||
registry_reachable) REGISTRY_REACHABLE="$value" ;;
|
||||
download_reachable) DOWNLOAD_REACHABLE="$value" ;;
|
||||
git_reachable) GIT_REACHABLE="$value" ;;
|
||||
installer_reachable) INSTALLER_REACHABLE="$value" ;;
|
||||
esac
|
||||
done < "$env_file"
|
||||
|
||||
log_message "SUCCESS" "Loaded preflight results from $env_file"
|
||||
return 0
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# CLOUD REGION SELECTION
|
||||
# Sets CLOUD_REGION and API_HOST based on reachability from the preflight check.
|
||||
# ------------------------------------------------------------------------------
|
||||
select_cloud_region() {
|
||||
log_message "INFO" "Selecting Wallarm Cloud region..."
|
||||
|
||||
echo -e "\n${CYAN}${BOLD}Wallarm Cloud Region Selection:${NC}"
|
||||
|
||||
local available_options=()
|
||||
|
||||
if [ "${US_CLOUD_REACHABLE:-false}" = "true" ]; then
|
||||
echo -e "1. ${YELLOW}US Cloud${NC} (us1.api.wallarm.com) - For US-based deployments"
|
||||
available_options+=("1" "US")
|
||||
fi
|
||||
|
||||
if [ "${EU_CLOUD_REACHABLE:-false}" = "true" ]; then
|
||||
echo -e "2. ${YELLOW}EU Cloud${NC} (api.wallarm.com) - For EU-based deployments"
|
||||
available_options+=("2" "EU")
|
||||
fi
|
||||
|
||||
if [ ${#available_options[@]} -eq 0 ]; then
|
||||
fail_with_remediation "No cloud regions available" \
|
||||
"Preflight check showed no reachable cloud regions.
|
||||
1. Check network connectivity to Wallarm endpoints
|
||||
2. Run the preflight check again
|
||||
3. Contact network administrator if behind firewall"
|
||||
fi
|
||||
|
||||
local pattern
|
||||
pattern="^($(IFS='|'; echo "${available_options[*]}"))$"
|
||||
|
||||
local cloud_choice=""
|
||||
while [[ ! "$cloud_choice" =~ $pattern ]]; do
|
||||
if [ ${#available_options[@]} -eq 2 ]; then
|
||||
if [ "${US_CLOUD_REACHABLE:-false}" = "true" ]; then
|
||||
cloud_choice="US"
|
||||
break
|
||||
else
|
||||
cloud_choice="EU"
|
||||
break
|
||||
fi
|
||||
fi
|
||||
|
||||
read -r -p "$(echo -e "${YELLOW}Enter choice [1/US or 2/EU]: ${NC}")" cloud_choice
|
||||
cloud_choice=$(echo "$cloud_choice" | tr '[:lower:]' '[:upper:]')
|
||||
|
||||
case "$cloud_choice" in
|
||||
1|"US")
|
||||
if [ "${US_CLOUD_REACHABLE:-false}" = "true" ]; then
|
||||
CLOUD_REGION="US"
|
||||
API_HOST="us1.api.wallarm.com"
|
||||
log_message "INFO" "Selected US Cloud"
|
||||
else
|
||||
echo -e "${RED}US Cloud is not reachable (per preflight check)${NC}"
|
||||
cloud_choice=""
|
||||
fi
|
||||
;;
|
||||
2|"EU")
|
||||
if [ "${EU_CLOUD_REACHABLE:-false}" = "true" ]; then
|
||||
CLOUD_REGION="EU"
|
||||
API_HOST="api.wallarm.com"
|
||||
log_message "INFO" "Selected EU Cloud"
|
||||
else
|
||||
echo -e "${RED}EU Cloud is not reachable (per preflight check)${NC}"
|
||||
cloud_choice=""
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if [ -n "$cloud_choice" ]; then
|
||||
echo -e "${RED}Invalid choice. Select from available options above.${NC}"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
log_message "SUCCESS" "Cloud region selected: $CLOUD_REGION ($API_HOST)"
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ARTIFACT DOWNLOAD (Git Repositorys primary source)
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Download a file from Git Repositorys. Returns 0 on success.
|
||||
download_from_git() {
|
||||
local url="$1"
|
||||
local output_path="$2"
|
||||
local description="$3"
|
||||
|
||||
log_message "INFO" "Attempting to download $description from Git Repositorys..."
|
||||
log_message "DEBUG" "URL: $url"
|
||||
log_message "DEBUG" "Output path: $output_path"
|
||||
|
||||
if curl -fL "$CURL_INSECURE_FLAG" --connect-timeout 30 --max-time 300 --progress-bar "$url" -o "$output_path"; then
|
||||
log_message "SUCCESS" "Downloaded $description to $output_path"
|
||||
return 0
|
||||
else
|
||||
local curl_exit=$?
|
||||
log_message "ERROR" "Failed to download $description from Git Repositorys (curl exit: $curl_exit)"
|
||||
if [ -f "$output_path" ]; then
|
||||
rm -f "$output_path"
|
||||
log_message "DEBUG" "Removed partial download: $output_path"
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Verify a file against a checksum file or URL. Returns 0 on success;
|
||||
# skips verification (returns 0) when the checksum cannot be obtained.
|
||||
verify_checksum() {
|
||||
local file_path="$1"
|
||||
local checksum_file_or_url="$2"
|
||||
local description="$3"
|
||||
|
||||
log_message "INFO" "Verifying $description checksum..."
|
||||
|
||||
local checksum_file=""
|
||||
if [[ "$checksum_file_or_url" =~ ^https?:// ]]; then
|
||||
checksum_file="/tmp/$(basename "$checksum_file_or_url")"
|
||||
log_message "DEBUG" "Downloading checksum from URL: $checksum_file_or_url"
|
||||
if ! curl -fL "$CURL_INSECURE_FLAG" --connect-timeout 10 --max-time 30 -s "$checksum_file_or_url" -o "$checksum_file"; then
|
||||
log_message "WARNING" "Could not download checksum file, skipping verification"
|
||||
return 0
|
||||
fi
|
||||
else
|
||||
checksum_file="$checksum_file_or_url"
|
||||
fi
|
||||
|
||||
if [ ! -f "$checksum_file" ]; then
|
||||
log_message "WARNING" "Checksum file not found: $checksum_file, skipping verification"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local expected_checksum
|
||||
expected_checksum=$(awk '{print $1}' "$checksum_file" 2>/dev/null)
|
||||
if [ -z "$expected_checksum" ]; then
|
||||
log_message "WARNING" "Could not read checksum from $checksum_file, skipping verification"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_message "DEBUG" "Computing SHA256 checksum of $file_path..."
|
||||
local actual_checksum
|
||||
if command -v sha256sum >/dev/null 2>&1; then
|
||||
actual_checksum=$(sha256sum "$file_path" | awk '{print $1}')
|
||||
elif command -v shasum >/dev/null 2>&1; then
|
||||
actual_checksum=$(shasum -a 256 "$file_path" | awk '{print $1}')
|
||||
else
|
||||
log_message "WARNING" "sha256sum or shasum not available, skipping checksum verification"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ "$expected_checksum" = "$actual_checksum" ]; then
|
||||
log_message "SUCCESS" "$description checksum verified successfully"
|
||||
return 0
|
||||
else
|
||||
log_message "ERROR" "$description checksum verification FAILED"
|
||||
log_message "DEBUG" "Expected: $expected_checksum"
|
||||
log_message "DEBUG" "Actual: $actual_checksum"
|
||||
rm -f "$file_path"
|
||||
log_message "INFO" "Removed corrupted file: $file_path"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
|
@ -1,72 +1,39 @@
|
|||
#!/bin/bash
|
||||
# ==============================================================================
|
||||
# WALLARM PREFLIGHT CHECK SCRIPT - V1.2
|
||||
# WALLARM PREFLIGHT CHECK SCRIPT - V1.3 (Docker deployment)
|
||||
# ==============================================================================
|
||||
# Purpose: Validate system readiness for Wallarm deployment
|
||||
# Purpose: Validate system readiness for Wallarm Docker deployment
|
||||
# Features:
|
||||
# - Non-interactive system validation (sudo, OS, architecture, init system)
|
||||
# - Network connectivity testing (US/EU cloud)
|
||||
# - Docker artifact source validation (Git Repositorys / local binaries/images)
|
||||
# - Outputs results to .env file for deployment script
|
||||
# - DAU-friendly error messages with remediation
|
||||
# ==============================================================================
|
||||
|
||||
# Color definitions for better UX
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[1;34m'
|
||||
CYAN='\033[0;36m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m' # No Color
|
||||
# Script location and shared library (colors, logging, validation, detection, connectivity)
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=../common/wallarm-lib.sh
|
||||
source "$SCRIPT_DIR/../common/wallarm-lib.sh"
|
||||
|
||||
# Strict error handling
|
||||
set -euo pipefail
|
||||
# Simple error handler for early failures (before log_message is defined)
|
||||
early_error_handler() {
|
||||
echo -e "${RED}${BOLD}[ERROR]${NC} Script failed at line $LINENO. Command: $BASH_COMMAND" >&2
|
||||
exit 1
|
||||
}
|
||||
trap early_error_handler ERR
|
||||
|
||||
# Extract hostname from URL (strip protocol and credentials for safe logging)
|
||||
extract_hostname_from_url() {
|
||||
local url="$1"
|
||||
# Remove protocol
|
||||
local hostpart="${url#*://}"
|
||||
# Remove credentials if present (username:password@)
|
||||
hostpart="${hostpart#*@}"
|
||||
# Remove port and path
|
||||
hostpart="${hostpart%%[:/]*}"
|
||||
echo "$hostpart"
|
||||
}
|
||||
|
||||
# Configuration
|
||||
ENV_FILE=".env"
|
||||
LOG_FILE="${HOME:-.}/logs/wallarm-check.log"
|
||||
|
||||
# SSL security settings
|
||||
# WALLARM_INSECURE_SSL=1 to disable SSL certificate validation (insecure, for self-signed certs)
|
||||
INSECURE_SSL="${WALLARM_INSECURE_SSL:-1}" # Default to insecure for backward compatibility
|
||||
if [ "$INSECURE_SSL" = "1" ]; then
|
||||
CURL_INSECURE_FLAG="-k"
|
||||
# Warning will be logged later when log_message is available
|
||||
else
|
||||
CURL_INSECURE_FLAG=""
|
||||
fi
|
||||
|
||||
# Git Repositorys artifact URLs (primary source) - same as deployment script
|
||||
# Git Repositorys artifact URLs (primary source) - Docker deployment artifacts
|
||||
GIT_BASE_URL="https://git.sechpoint.app/customer-engineering/wallarm"
|
||||
GIT_RAW_URL="https://git.sechpoint.app/customer-engineering/wallarm/raw/branch/main"
|
||||
GIT_DOCKER_BINARY_URL="${GIT_RAW_URL}/binaries/docker-29.2.1.tgz"
|
||||
GIT_WALLARM_IMAGE_URL="${GIT_RAW_URL}/images/wallarm-node-6.11.0-rc1.tar.gz"
|
||||
GIT_DOCKER_BINARY_URL="${GIT_RAW_URL}/docker/binaries/docker-29.2.1.tgz"
|
||||
GIT_WALLARM_IMAGE_URL="${GIT_RAW_URL}/docker/images/wallarm-node-6.11.0-rc1.tar.gz"
|
||||
|
||||
# Local artifact directories (relative to script location)
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
LOCAL_BINARY_DIR="${SCRIPT_DIR}/binaries"
|
||||
LOCAL_IMAGE_DIR="${SCRIPT_DIR}/images"
|
||||
|
||||
|
||||
|
||||
# Cloud endpoints (from Wallarm documentation)
|
||||
EU_DATA_NODES=("api.wallarm.com" "node-data0.eu1.wallarm.com" "node-data1.eu1.wallarm.com")
|
||||
US_DATA_NODES=("us1.api.wallarm.com" "node-data0.us1.wallarm.com" "node-data1.us1.wallarm.com")
|
||||
|
|
@ -77,28 +44,9 @@ CHECK_ERRORS=()
|
|||
GIT_REACHABLE="false"
|
||||
|
||||
# ==============================================================================
|
||||
# LOGGING & ERROR HANDLING FUNCTIONS
|
||||
# RESULT TRACKING & ENV FILE
|
||||
# ==============================================================================
|
||||
|
||||
log_message() {
|
||||
local level="$1"
|
||||
local message="$2"
|
||||
local timestamp
|
||||
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
|
||||
case "$level" in
|
||||
"INFO") color="${BLUE}" ;;
|
||||
"SUCCESS") color="${GREEN}" ;;
|
||||
"WARNING") color="${YELLOW}" ;;
|
||||
"ERROR") color="${RED}" ;;
|
||||
"DEBUG") color="${CYAN}" ;;
|
||||
*) color="${NC}" ;;
|
||||
esac
|
||||
|
||||
echo -e "${color}[${timestamp}] ${level}: ${message}${NC}" >&2
|
||||
echo "[${timestamp}] ${level}: ${message}" >> "$LOG_FILE"
|
||||
}
|
||||
|
||||
add_error() {
|
||||
local error_msg="$1"
|
||||
CHECK_ERRORS+=("$error_msg")
|
||||
|
|
@ -117,7 +65,6 @@ write_env_file() {
|
|||
local download_reachable="$8"
|
||||
local git_reachable="${9:-false}"
|
||||
|
||||
# Create .env file
|
||||
cat > "$ENV_FILE" << EOF
|
||||
# Wallarm Preflight Check Results
|
||||
# Generated: $(date '+%Y-%m-%d %H:%M:%S')
|
||||
|
|
@ -136,7 +83,6 @@ git_reachable=$git_reachable
|
|||
|
||||
EOF
|
||||
|
||||
# Add errors if any
|
||||
if [ ${#CHECK_ERRORS[@]} -gt 0 ]; then
|
||||
echo "# Errors:" >> "$ENV_FILE"
|
||||
for i in "${!CHECK_ERRORS[@]}"; do
|
||||
|
|
@ -154,25 +100,20 @@ EOF
|
|||
validate_sudo_access() {
|
||||
log_message "INFO" "Validating sudo access..."
|
||||
|
||||
# Detect OS
|
||||
local os_name
|
||||
os_name=$(uname -s | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
# Check if user can run sudo
|
||||
if ! command -v sudo >/dev/null 2>&1; then
|
||||
add_error "sudo command not found"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# On macOS, we can't reliably test sudo authentication without prompting
|
||||
# Skip the actual authentication test but warn
|
||||
if [ "$os_name" = "darwin" ]; then
|
||||
log_message "WARNING" "macOS detected: sudo authentication test skipped (may prompt during deployment)"
|
||||
log_message "INFO" "Note: macOS is not a supported deployment target. This check is for Linux servers."
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Test sudo with password prompt if needed
|
||||
if ! sudo -v; then
|
||||
add_error "sudo authentication failed"
|
||||
return 1
|
||||
|
|
@ -187,7 +128,6 @@ validate_required_commands() {
|
|||
|
||||
local missing_commands=()
|
||||
|
||||
# Detect OS
|
||||
local os_name
|
||||
os_name=$(uname -s | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
|
|
@ -221,24 +161,8 @@ validate_required_commands() {
|
|||
)
|
||||
fi
|
||||
|
||||
# Helper function to check if a command exists (including system directories)
|
||||
command_exists() {
|
||||
local cmd="$1"
|
||||
# First try command -v (respects PATH)
|
||||
if command -v "$cmd" >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
# Check common system directories (for commands that might be in sbin)
|
||||
local system_dirs=("/usr/sbin" "/sbin" "/usr/local/sbin" "/usr/bin" "/bin" "/usr/local/bin")
|
||||
for dir in "${system_dirs[@]}"; do
|
||||
if [ -x "$dir/$cmd" ]; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
# Check each core command
|
||||
# Check each core command (command_exists comes from common library)
|
||||
local cmd
|
||||
for cmd in "${core_commands[@]}"; do
|
||||
if ! command_exists "$cmd"; then
|
||||
missing_commands+=("$cmd")
|
||||
|
|
@ -246,7 +170,6 @@ validate_required_commands() {
|
|||
done
|
||||
|
||||
# Check for port checking utility (ss or netstat)
|
||||
# On macOS, netstat is available, ss is not
|
||||
if [ "$os_name" != "darwin" ]; then
|
||||
if ! command_exists ss && ! command_exists netstat; then
|
||||
missing_commands+=("ss or netstat")
|
||||
|
|
@ -254,7 +177,6 @@ validate_required_commands() {
|
|||
fi
|
||||
|
||||
# Detect init system and validate its control command
|
||||
# Skip on macOS as it's not a deployment target
|
||||
if [ "$os_name" != "darwin" ]; then
|
||||
local init_system
|
||||
init_system=$(detect_init_system)
|
||||
|
|
@ -288,7 +210,6 @@ validate_required_commands() {
|
|||
log_message "INFO" "Skipping init system validation on macOS (not a deployment target)"
|
||||
fi
|
||||
|
||||
# Report any missing commands
|
||||
if [ ${#missing_commands[@]} -gt 0 ]; then
|
||||
local missing_list
|
||||
missing_list=$(IFS=', '; echo "${missing_commands[*]}")
|
||||
|
|
@ -298,7 +219,6 @@ validate_required_commands() {
|
|||
fi
|
||||
|
||||
# Special check: iptables version must be 1.4 or higher for Docker static binaries
|
||||
# Skip on macOS as it's not a deployment target
|
||||
if [ "$os_name" != "darwin" ]; then
|
||||
log_message "INFO" "Checking iptables version (requires 1.4+ for Docker)..."
|
||||
if command_exists iptables; then
|
||||
|
|
@ -306,7 +226,6 @@ validate_required_commands() {
|
|||
iptables_version=$(iptables --version 2>/dev/null | head -1 | grep -o '[0-9]\+\.[0-9]\+' | head -1)
|
||||
if [ -n "$iptables_version" ]; then
|
||||
log_message "INFO" "Found iptables version $iptables_version"
|
||||
# Compare version numbers (basic check for 1.4 or higher)
|
||||
local major_version minor_version
|
||||
major_version=$(echo "$iptables_version" | cut -d. -f1)
|
||||
minor_version=$(echo "$iptables_version" | cut -d. -f2)
|
||||
|
|
@ -320,7 +239,6 @@ validate_required_commands() {
|
|||
log_message "WARNING" "Could not determine iptables version, continuing anyway"
|
||||
fi
|
||||
else
|
||||
# Should not happen since iptables is in required commands, but just in case
|
||||
add_error "iptables command not found (required for Docker network bridge)"
|
||||
return 1
|
||||
fi
|
||||
|
|
@ -332,205 +250,13 @@ validate_required_commands() {
|
|||
return 0
|
||||
}
|
||||
|
||||
detect_os_and_version() {
|
||||
log_message "INFO" "Detecting OS and version..."
|
||||
|
||||
local os_name=""
|
||||
local os_version=""
|
||||
|
||||
# Check for /etc/os-release first (modern systems)
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
os_name="$ID"
|
||||
os_version="$VERSION_ID"
|
||||
# Check for older RedHat/CentOS
|
||||
elif [ -f /etc/redhat-release ]; then
|
||||
os_name="rhel"
|
||||
os_version=$(sed -e 's/.*release \([0-9]\+\)\..*/\1/' /etc/redhat-release)
|
||||
# Check for Alpine
|
||||
elif [ -f /etc/alpine-release ]; then
|
||||
os_name="alpine"
|
||||
os_version=$(cat /etc/alpine-release)
|
||||
else
|
||||
os_name=$(uname -s | tr '[:upper:]' '[:lower:]')
|
||||
os_version=$(uname -r)
|
||||
fi
|
||||
|
||||
# Remove any carriage returns or newlines from variables
|
||||
os_name="${os_name//[$'\t\r\n']/}"
|
||||
os_version="${os_version//[$'\t\r\n']/}"
|
||||
|
||||
# Normalize OS names
|
||||
case "$os_name" in
|
||||
"ubuntu"|"debian"|"centos"|"rhel"|"alpine"|"amzn"|"ol"|"rocky"|"almalinux")
|
||||
# Valid supported OS
|
||||
log_message "SUCCESS" "OS detected: $os_name $os_version (supported)"
|
||||
;;
|
||||
*)
|
||||
log_message "WARNING" "OS '$os_name' not explicitly tested but may work"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "$os_name:$os_version"
|
||||
}
|
||||
|
||||
detect_architecture() {
|
||||
log_message "INFO" "Detecting system architecture..."
|
||||
|
||||
local arch
|
||||
arch=$(uname -m)
|
||||
local docker_arch=""
|
||||
|
||||
case "$arch" in
|
||||
x86_64|x64|amd64)
|
||||
docker_arch="x86_64"
|
||||
log_message "SUCCESS" "Architecture: x86_64 (Intel/AMD 64-bit)"
|
||||
;;
|
||||
aarch64|arm64)
|
||||
docker_arch="aarch64"
|
||||
log_message "SUCCESS" "Architecture: aarch64 (ARM 64-bit)"
|
||||
;;
|
||||
armv7l|armhf)
|
||||
docker_arch="armhf"
|
||||
log_message "SUCCESS" "Architecture: armhf (ARM 32-bit)"
|
||||
;;
|
||||
*)
|
||||
log_message "ERROR" "Unsupported architecture: $arch"
|
||||
docker_arch="unknown"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "$docker_arch"
|
||||
}
|
||||
|
||||
# Critical fix from review: Init system detection
|
||||
detect_init_system() {
|
||||
log_message "INFO" "Detecting init system..."
|
||||
|
||||
local init_system="unknown"
|
||||
|
||||
# Detect macOS/Darwin first
|
||||
if [ "$(uname -s)" = "Darwin" ]; then
|
||||
init_system="darwin"
|
||||
log_message "SUCCESS" "Init system: darwin (macOS)"
|
||||
elif command -v systemctl >/dev/null 2>&1 && systemctl --version >/dev/null 2>&1; then
|
||||
init_system="systemd"
|
||||
log_message "SUCCESS" "Init system: systemd"
|
||||
elif [ -d /etc/init.d ] && [ -x /sbin/initctl ] || [ -x /sbin/init ]; then
|
||||
init_system="sysvinit"
|
||||
log_message "SUCCESS" "Init system: sysvinit"
|
||||
elif [ -d /etc/rc.d ] && [ -x /sbin/rc-service ]; then
|
||||
init_system="openrc"
|
||||
log_message "SUCCESS" "Init system: openrc (Alpine)"
|
||||
elif [ -x /sbin/upstart ]; then
|
||||
init_system="upstart"
|
||||
log_message "SUCCESS" "Init system: upstart"
|
||||
else
|
||||
log_message "WARNING" "Could not determine init system"
|
||||
init_system="unknown"
|
||||
fi
|
||||
|
||||
echo "$init_system"
|
||||
}
|
||||
|
||||
# Critical fix from review: Proper IP validation
|
||||
validate_ip_address() {
|
||||
local ip="$1"
|
||||
|
||||
# Check basic format
|
||||
if [[ ! "$ip" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Check each octet is 0-255
|
||||
IFS='.' read -r i1 i2 i3 i4 <<< "$ip"
|
||||
if [ "$i1" -gt 255 ] || [ "$i2" -gt 255 ] || [ "$i3" -gt 255 ] || [ "$i4" -gt 255 ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Critical fix from review: Port conflict detection with fallback
|
||||
check_port_available() {
|
||||
local port="$1"
|
||||
local protocol="${2:-tcp}"
|
||||
|
||||
log_message "DEBUG" "Checking port $port/$protocol availability..."
|
||||
|
||||
# Try ss first (modern, usually available)
|
||||
if command -v ss >/dev/null 2>&1; then
|
||||
if ss -"${protocol:0:1}"ln | grep -q ":$port "; then
|
||||
return 1 # Port in use
|
||||
fi
|
||||
# Fallback to netstat
|
||||
elif command -v netstat >/dev/null 2>&1; then
|
||||
if netstat -tulpn 2>/dev/null | grep -E ":$port\s" >/dev/null 2>&1; then
|
||||
return 1 # Port in use
|
||||
fi
|
||||
else
|
||||
log_message "WARNING" "Neither ss nor netstat available, cannot check port $port"
|
||||
fi
|
||||
|
||||
return 0 # Port available (or cannot check)
|
||||
}
|
||||
|
||||
# Network connectivity testing
|
||||
|
||||
test_connectivity() {
|
||||
local host="$1"
|
||||
local description="$2"
|
||||
local timeout="${3:-10}"
|
||||
|
||||
# Extract hostname for safe logging (without credentials)
|
||||
local display_host
|
||||
display_host=$(extract_hostname_from_url "$host")
|
||||
log_message "INFO" "Testing connectivity to $description ($display_host)..."
|
||||
|
||||
local url="$host"
|
||||
if [[ ! "$host" =~ ^https?:// ]]; then
|
||||
url="https://$host"
|
||||
fi
|
||||
# Use -sL (GET + follow redirects) instead of -sI (HEAD only)
|
||||
# HEAD requests may not work reliably on all Forgejo/Gitea raw endpoints.
|
||||
# GET with -L follows redirects, and output goes to /dev/null.
|
||||
if curl -sL $CURL_INSECURE_FLAG --connect-timeout "$timeout" "$url" >/dev/null 2>&1; then
|
||||
log_message "SUCCESS" "$description is reachable"
|
||||
return 0
|
||||
else
|
||||
log_message "ERROR" "$description is NOT reachable"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
test_cloud_endpoints() {
|
||||
local cloud_name="$1"
|
||||
shift
|
||||
local endpoints=("$@")
|
||||
|
||||
log_message "INFO" "Testing $cloud_name cloud endpoints..."
|
||||
|
||||
local all_reachable=true
|
||||
for endpoint in "${endpoints[@]}"; do
|
||||
if ! test_connectivity "$endpoint" "$cloud_name endpoint $endpoint"; then
|
||||
all_reachable=false
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$all_reachable" = true ]; then
|
||||
log_message "SUCCESS" "All $cloud_name cloud endpoints reachable"
|
||||
echo "true"
|
||||
else
|
||||
log_message "WARNING" "Some $cloud_name cloud endpoints unreachable"
|
||||
echo "false"
|
||||
fi
|
||||
}
|
||||
# ==============================================================================
|
||||
# NETWORK CONNECTIVITY & ARTIFACT SOURCE TESTING
|
||||
# ==============================================================================
|
||||
|
||||
perform_network_tests() {
|
||||
log_message "INFO" "=== NETWORK CONNECTIVITY TESTING ==="
|
||||
|
||||
|
||||
|
||||
# Test US cloud endpoints
|
||||
local us_reachable
|
||||
us_reachable=$(test_cloud_endpoints "US" "${US_DATA_NODES[@]}")
|
||||
|
|
@ -549,27 +275,27 @@ perform_network_tests() {
|
|||
local has_local_docker=false
|
||||
local docker_sources=()
|
||||
|
||||
# Check local binaries directory
|
||||
if [ -d "$LOCAL_BINARY_DIR" ]; then
|
||||
log_message "INFO" "Checking local binaries directory: $LOCAL_BINARY_DIR"
|
||||
local binary_files=$(ls "$LOCAL_BINARY_DIR"/*.tgz 2>/dev/null | head -5)
|
||||
local binary_files
|
||||
binary_files=$(ls "$LOCAL_BINARY_DIR"/*.tgz 2>/dev/null | head -5)
|
||||
if [ -n "$binary_files" ]; then
|
||||
log_message "SUCCESS" "Found local Docker binaries in $LOCAL_BINARY_DIR:"
|
||||
for file in $binary_files; do
|
||||
while IFS= read -r file; do
|
||||
log_message "SUCCESS" " - $(basename "$file")"
|
||||
done
|
||||
done <<< "$binary_files"
|
||||
has_local_docker=true
|
||||
docker_sources+=("$LOCAL_BINARY_DIR/")
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check current directory
|
||||
local current_docker_files=$(ls docker-*.tgz 2>/dev/null | head -5)
|
||||
local current_docker_files
|
||||
current_docker_files=$(ls docker-*.tgz 2>/dev/null | head -5)
|
||||
if [ -n "$current_docker_files" ]; then
|
||||
log_message "SUCCESS" "Found local Docker binaries in current directory:"
|
||||
for file in $current_docker_files; do
|
||||
while IFS= read -r file; do
|
||||
log_message "SUCCESS" " - $file"
|
||||
done
|
||||
done <<< "$current_docker_files"
|
||||
has_local_docker=true
|
||||
docker_sources+=("current directory")
|
||||
fi
|
||||
|
|
@ -584,27 +310,27 @@ perform_network_tests() {
|
|||
local has_local_wallarm=false
|
||||
local wallarm_sources=()
|
||||
|
||||
# Check local images directory (prefers .tar.gz format)
|
||||
if [ -d "$LOCAL_IMAGE_DIR" ]; then
|
||||
log_message "INFO" "Checking local images directory: $LOCAL_IMAGE_DIR"
|
||||
local image_files=$(ls "$LOCAL_IMAGE_DIR"/*.tar.gz "$LOCAL_IMAGE_DIR"/*.tar 2>/dev/null | head -5)
|
||||
local image_files
|
||||
image_files=$(ls "$LOCAL_IMAGE_DIR"/*.tar.gz "$LOCAL_IMAGE_DIR"/*.tar 2>/dev/null | head -5)
|
||||
if [ -n "$image_files" ]; then
|
||||
log_message "SUCCESS" "Found local Wallarm images in $LOCAL_IMAGE_DIR:"
|
||||
for file in $image_files; do
|
||||
while IFS= read -r file; do
|
||||
log_message "SUCCESS" " - $(basename "$file")"
|
||||
done
|
||||
done <<< "$image_files"
|
||||
has_local_wallarm=true
|
||||
wallarm_sources+=("$LOCAL_IMAGE_DIR/")
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check current directory (.tar.gz and .tar formats)
|
||||
local current_image_files=$(ls wallarm-node-*.tar.gz wallarm-node-*.tar 2>/dev/null | head -5)
|
||||
local current_image_files
|
||||
current_image_files=$(ls wallarm-node-*.tar.gz wallarm-node-*.tar 2>/dev/null | head -5)
|
||||
if [ -n "$current_image_files" ]; then
|
||||
log_message "SUCCESS" "Found local Wallarm images in current directory:"
|
||||
for file in $current_image_files; do
|
||||
while IFS= read -r file; do
|
||||
log_message "SUCCESS" " - $file"
|
||||
done
|
||||
done <<< "$current_image_files"
|
||||
has_local_wallarm=true
|
||||
wallarm_sources+=("current directory")
|
||||
fi
|
||||
|
|
@ -626,13 +352,12 @@ main() {
|
|||
clear
|
||||
echo -e "${BLUE}${BOLD}"
|
||||
echo "╔══════════════════════════════════════════════════════════════╗"
|
||||
echo "║ WALLARM PREFLIGHT CHECK SCRIPT - V1.2 ║"
|
||||
echo "║ WALLARM PREFLIGHT CHECK SCRIPT (Docker) - V1.3 ║"
|
||||
echo "║ System Readiness Validation for Deployment ║"
|
||||
echo "╚══════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo -e "\n${YELLOW}Starting preflight check at: $(date)${NC}"
|
||||
|
||||
# Initialize logging
|
||||
# Create logs directory if it doesn't exist
|
||||
local log_dir="${HOME:-.}/logs"
|
||||
if [ ! -d "$log_dir" ]; then
|
||||
if ! mkdir -p "$log_dir"; then
|
||||
|
|
@ -654,7 +379,6 @@ main() {
|
|||
|
||||
log_message "INFO" "=== Wallarm Preflight Check Started ==="
|
||||
|
||||
# SSL security warning
|
||||
if [ "$INSECURE_SSL" = "1" ]; then
|
||||
log_message "WARNING" "SSL certificate validation is DISABLED (insecure). Set WALLARM_INSECURE_SSL=0 to enable validation."
|
||||
fi
|
||||
|
|
@ -694,7 +418,6 @@ main() {
|
|||
# Phase 2: Network connectivity testing
|
||||
log_message "INFO" "=== PHASE 2: NETWORK CONNECTIVITY TESTING ==="
|
||||
|
||||
# Test Git Repositorys connectivity (primary artifact source)
|
||||
log_message "INFO" "Testing connectivity to Git Repositorys artifact repository..."
|
||||
GIT_REACHABLE="false"
|
||||
if test_connectivity "$GIT_DOCKER_BINARY_URL" "Git Repositorys Docker artifact"; then
|
||||
|
|
@ -718,17 +441,14 @@ main() {
|
|||
# Critical check: Need at least one source for Docker and Wallarm
|
||||
# Priority: Git Repositorys (primary) -> local files
|
||||
|
||||
# If Git Repositorys is reachable, we have our primary source
|
||||
if [ "$GIT_REACHABLE" = "true" ]; then
|
||||
log_message "SUCCESS" "Git Repositorys artifact repository is reachable (primary source available)"
|
||||
else
|
||||
log_message "WARNING" "Git Repositorys artifact repository is not reachable - checking fallback sources"
|
||||
|
||||
# Check for local files in multiple locations
|
||||
local has_local_docker=false
|
||||
local has_local_wallarm=false
|
||||
|
||||
# Check Docker binary locations
|
||||
if [ -d "$LOCAL_BINARY_DIR" ] && [ -n "$(ls "$LOCAL_BINARY_DIR"/*.tgz 2>/dev/null)" ]; then
|
||||
has_local_docker=true
|
||||
log_message "INFO" "Found local Docker binaries in $LOCAL_BINARY_DIR/"
|
||||
|
|
@ -737,7 +457,6 @@ main() {
|
|||
log_message "INFO" "Found local Docker binaries in current directory"
|
||||
fi
|
||||
|
||||
# Check Wallarm image locations (support both .tar.gz and .tar)
|
||||
if [ -d "$LOCAL_IMAGE_DIR" ] && [ -n "$(ls "$LOCAL_IMAGE_DIR"/*.tar.gz "$LOCAL_IMAGE_DIR"/*.tar 2>/dev/null)" ]; then
|
||||
has_local_wallarm=true
|
||||
log_message "INFO" "Found local Wallarm images in $LOCAL_IMAGE_DIR/"
|
||||
|
|
@ -746,7 +465,6 @@ main() {
|
|||
log_message "INFO" "Found local Wallarm images in current directory"
|
||||
fi
|
||||
|
||||
# Determine if we have sufficient resources
|
||||
local has_sufficient_resources=true
|
||||
|
||||
if [ "$has_local_docker" = "false" ]; then
|
||||
|
|
@ -796,10 +514,10 @@ Possible sources:
|
|||
echo -e "\n${GREEN}${BOLD}╔══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${GREEN}${BOLD}║ PREFLIGHT CHECK PASSED - SYSTEM READY ║${NC}"
|
||||
echo -e "${GREEN}${BOLD}╚══════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo -e "\n${CYAN}System is ready for Wallarm deployment.${NC}"
|
||||
echo -e "\n${CYAN}System is ready for Wallarm Docker deployment.${NC}"
|
||||
echo -e "${YELLOW}Check results: $ENV_FILE${NC}"
|
||||
echo -e "${YELLOW}Full log: $LOG_FILE${NC}"
|
||||
echo -e "\n${GREEN}Next step: Run ./wallarm-ct-deploy.sh to proceed with deployment${NC}"
|
||||
echo -e "\n${GREEN}Next step: Run ./docker/wallarm-ct-deploy.sh to proceed with deployment${NC}"
|
||||
exit 0
|
||||
else
|
||||
log_message "ERROR" "=== PREFLIGHT CHECK FAILED ==="
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
#!/bin/bash
|
||||
# ==============================================================================
|
||||
# WALLARM DEPLOYMENT SCRIPT - V1.2
|
||||
# WALLARM DEPLOYMENT SCRIPT - V1.3 (Docker deployment)
|
||||
# ==============================================================================
|
||||
# Purpose: Deploy Wallarm filtering node after preflight check
|
||||
# Purpose: Deploy Wallarm filtering node (Docker container) after preflight check
|
||||
# Features:
|
||||
# - Reads preflight check results from .env file
|
||||
# - Interactive configuration (cloud region, ports, token, upstream)
|
||||
|
|
@ -12,61 +12,28 @@
|
|||
# - DAU-friendly error handling with remediation
|
||||
# ==============================================================================
|
||||
|
||||
# Color definitions for better UX
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[1;34m'
|
||||
CYAN='\033[0;36m'
|
||||
MAGENTA='\033[0;35m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m' # No Color
|
||||
# Script location and shared library (colors, logging, validation, detection, connectivity)
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=../common/wallarm-lib.sh
|
||||
source "$SCRIPT_DIR/../common/wallarm-lib.sh"
|
||||
|
||||
# Strict error handling
|
||||
set -euo pipefail
|
||||
# Simple error handler for early failures (before log_message is defined)
|
||||
early_error_handler() {
|
||||
echo -e "${RED}${BOLD}[ERROR]${NC} Script failed at line $LINENO. Command: $BASH_COMMAND" >&2
|
||||
exit 1
|
||||
}
|
||||
trap early_error_handler ERR
|
||||
|
||||
# Extract hostname from URL (strip protocol and credentials for safe logging)
|
||||
extract_hostname_from_url() {
|
||||
local url="$1"
|
||||
# Remove protocol
|
||||
local hostpart="${url#*://}"
|
||||
# Remove credentials if present (username:password@)
|
||||
hostpart="${hostpart#*@}"
|
||||
# Remove port and path
|
||||
hostpart="${hostpart%%[:/]*}"
|
||||
echo "$hostpart"
|
||||
}
|
||||
|
||||
# Configuration
|
||||
ENV_FILE=".env"
|
||||
LOG_FILE="${HOME:-.}/logs/wallarm-deployment.log"
|
||||
|
||||
# SSL security settings
|
||||
# WALLARM_INSECURE_SSL=1 to disable SSL certificate validation (insecure, for self-signed certs)
|
||||
INSECURE_SSL="${WALLARM_INSECURE_SSL:-1}" # Default to insecure for backward compatibility
|
||||
if [ "$INSECURE_SSL" = "1" ]; then
|
||||
CURL_INSECURE_FLAG="-k"
|
||||
# Warning will be logged later when log_message is available
|
||||
else
|
||||
CURL_INSECURE_FLAG=""
|
||||
fi
|
||||
|
||||
# Git Repositorys artifact URLs (primary source)
|
||||
# Git Repositorys artifact URLs (primary source) - Docker deployment artifacts
|
||||
GIT_BASE_URL="https://git.sechpoint.app/customer-engineering/wallarm"
|
||||
GIT_RAW_URL="https://git.sechpoint.app/customer-engineering/wallarm/raw/branch/main"
|
||||
GIT_DOCKER_BINARY_URL="${GIT_RAW_URL}/binaries/docker-29.2.1.tgz"
|
||||
GIT_DOCKER_CHECKSUM_URL="${GIT_RAW_URL}/binaries/docker-29.2.1.tgz.sha256"
|
||||
GIT_WALLARM_IMAGE_URL="${GIT_RAW_URL}/images/wallarm-node-6.11.0-rc1.tar.gz"
|
||||
GIT_WALLARM_CHECKSUM_URL="${GIT_RAW_URL}/images/wallarm-node-6.11.0-rc1.tar.gz.sha256"
|
||||
GIT_DOCKER_BINARY_URL="${GIT_RAW_URL}/docker/binaries/docker-29.2.1.tgz"
|
||||
GIT_DOCKER_CHECKSUM_URL="${GIT_RAW_URL}/docker/binaries/docker-29.2.1.tgz.sha256"
|
||||
GIT_WALLARM_IMAGE_URL="${GIT_RAW_URL}/docker/images/wallarm-node-6.11.0-rc1.tar.gz"
|
||||
GIT_WALLARM_CHECKSUM_URL="${GIT_RAW_URL}/docker/images/wallarm-node-6.11.0-rc1.tar.gz.sha256"
|
||||
|
||||
# Local artifact directories (relative to script location)
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
LOCAL_BINARY_DIR="${SCRIPT_DIR}/binaries"
|
||||
LOCAL_IMAGE_DIR="${SCRIPT_DIR}/images"
|
||||
|
||||
|
|
@ -93,134 +60,6 @@ REGISTRY_REACHABLE="false"
|
|||
DOWNLOAD_REACHABLE="false"
|
||||
GIT_REACHABLE="false"
|
||||
|
||||
# ==============================================================================
|
||||
# LOGGING & ERROR HANDLING FUNCTIONS
|
||||
# ==============================================================================
|
||||
|
||||
log_message() {
|
||||
local level="$1"
|
||||
local message="$2"
|
||||
local timestamp
|
||||
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
|
||||
case "$level" in
|
||||
"INFO") color="${BLUE}" ;;
|
||||
"SUCCESS") color="${GREEN}" ;;
|
||||
"WARNING") color="${YELLOW}" ;;
|
||||
"ERROR") color="${RED}" ;;
|
||||
"DEBUG") color="${CYAN}" ;;
|
||||
*) color="${NC}" ;;
|
||||
esac
|
||||
|
||||
echo -e "${color}[${timestamp}] ${level}: ${message}${NC}" >&2
|
||||
echo "[${timestamp}] ${level}: ${message}" >> "$LOG_FILE"
|
||||
}
|
||||
|
||||
fail_with_remediation() {
|
||||
local error_msg="$1"
|
||||
local remediation="$2"
|
||||
|
||||
log_message "ERROR" "$error_msg"
|
||||
echo -e "\n${RED}${BOLD}╔══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${RED}${BOLD}║ DEPLOYMENT FAILED ║${NC}"
|
||||
echo -e "${RED}${BOLD}╚══════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo -e "\n${YELLOW}${BOLD}Root Cause:${NC} $error_msg"
|
||||
echo -e "\n${YELLOW}${BOLD}How to Fix:${NC}"
|
||||
echo -e "$remediation"
|
||||
echo -e "\n${YELLOW}Check the full log for details:${NC} $LOG_FILE"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# GIT ARTIFACT FUNCTIONS
|
||||
# ==============================================================================
|
||||
|
||||
download_from_git() {
|
||||
local url="$1"
|
||||
local output_path="$2"
|
||||
local description="$3"
|
||||
|
||||
log_message "INFO" "Attempting to download $description from Git Repositorys..."
|
||||
log_message "DEBUG" "URL: $url"
|
||||
log_message "DEBUG" "Output path: $output_path"
|
||||
|
||||
# Use curl with follow redirects, fail on HTTP error, timeout settings
|
||||
if curl -fL "$CURL_INSECURE_FLAG" --connect-timeout 30 --max-time 300 --progress-bar "$url" -o "$output_path"; then
|
||||
log_message "SUCCESS" "Downloaded $description to $output_path"
|
||||
return 0
|
||||
else
|
||||
local curl_exit=$?
|
||||
log_message "ERROR" "Failed to download $description from Git Repositorys (curl exit: $curl_exit)"
|
||||
# Clean up partial download if it exists
|
||||
if [ -f "$output_path" ]; then
|
||||
rm -f "$output_path"
|
||||
log_message "DEBUG" "Removed partial download: $output_path"
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
verify_checksum() {
|
||||
local file_path="$1"
|
||||
local checksum_file_or_url="$2"
|
||||
local description="$3"
|
||||
|
||||
log_message "INFO" "Verifying $description checksum..."
|
||||
|
||||
local checksum_file=""
|
||||
# If checksum is a URL, download it first
|
||||
if [[ "$checksum_file_or_url" =~ ^https?:// ]]; then
|
||||
checksum_file="/tmp/$(basename "$checksum_file_or_url")"
|
||||
log_message "DEBUG" "Downloading checksum from URL: $checksum_file_or_url"
|
||||
if ! curl -fL "$CURL_INSECURE_FLAG" --connect-timeout 10 --max-time 30 -s "$checksum_file_or_url" -o "$checksum_file"; then
|
||||
log_message "WARNING" "Could not download checksum file, skipping verification"
|
||||
return 0 # Skip verification if checksum can't be downloaded
|
||||
fi
|
||||
else
|
||||
checksum_file="$checksum_file_or_url"
|
||||
fi
|
||||
|
||||
# Verify checksum file exists
|
||||
if [ ! -f "$checksum_file" ]; then
|
||||
log_message "WARNING" "Checksum file not found: $checksum_file, skipping verification"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Get expected checksum (first field from checksum file)
|
||||
local expected_checksum
|
||||
expected_checksum=$(awk '{print $1}' "$checksum_file" 2>/dev/null)
|
||||
if [ -z "$expected_checksum" ]; then
|
||||
log_message "WARNING" "Could not read checksum from $checksum_file, skipping verification"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Compute actual checksum
|
||||
log_message "DEBUG" "Computing SHA256 checksum of $file_path..."
|
||||
local actual_checksum
|
||||
if command -v sha256sum >/dev/null 2>&1; then
|
||||
actual_checksum=$(sha256sum "$file_path" | awk '{print $1}')
|
||||
elif command -v shasum >/dev/null 2>&1; then
|
||||
actual_checksum=$(shasum -a 256 "$file_path" | awk '{print $1}')
|
||||
else
|
||||
log_message "WARNING" "sha256sum or shasum not available, skipping checksum verification"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Compare checksums
|
||||
if [ "$expected_checksum" = "$actual_checksum" ]; then
|
||||
log_message "SUCCESS" "$description checksum verified successfully"
|
||||
return 0
|
||||
else
|
||||
log_message "ERROR" "$description checksum verification FAILED"
|
||||
log_message "DEBUG" "Expected: $expected_checksum"
|
||||
log_message "DEBUG" "Actual: $actual_checksum"
|
||||
# Clean up corrupted file
|
||||
rm -f "$file_path"
|
||||
log_message "INFO" "Removed corrupted file: $file_path"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# PREFLIGHT CHECK VERIFICATION
|
||||
# ==============================================================================
|
||||
|
|
@ -236,53 +75,36 @@ verify_preflight_check() {
|
|||
echo
|
||||
if [[ ! $REPLY =~ ^[Nn]$ ]]; then
|
||||
echo -e "${CYAN}Running preflight check...${NC}"
|
||||
if ! ./wallarm-ct-check.sh; then
|
||||
if ! "$SCRIPT_DIR/wallarm-ct-check.sh"; then
|
||||
fail_with_remediation "Preflight check failed" \
|
||||
"Run the preflight check manually and fix any issues:
|
||||
1. ./wallarm-ct-check.sh
|
||||
1. $SCRIPT_DIR/wallarm-ct-check.sh
|
||||
2. Review the errors in $ENV_FILE
|
||||
3. Fix the issues and run this script again"
|
||||
fi
|
||||
else
|
||||
fail_with_remediation "Preflight check required" \
|
||||
"Run the preflight check before deployment:
|
||||
1. ./wallarm-ct-check.sh
|
||||
1. $SCRIPT_DIR/wallarm-ct-check.sh
|
||||
2. Review results in $ENV_FILE
|
||||
3. Run this script again"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Load environment variables from .env file
|
||||
# Use a safer approach than sourcing (avoid code injection)
|
||||
while IFS='=' read -r key value; do
|
||||
# Remove comments and empty lines
|
||||
[[ "$key" =~ ^#.*$ ]] && continue
|
||||
[[ -z "$key" ]] && continue
|
||||
|
||||
# Remove quotes from value
|
||||
value="${value%\"}"
|
||||
value="${value#\"}"
|
||||
|
||||
# Export variable
|
||||
case "$key" in
|
||||
result) CHECK_RESULT="$value" ;;
|
||||
os_name) OS_NAME="$value" ;;
|
||||
os_version) OS_VERSION="$value" ;;
|
||||
architecture) ARCHITECTURE="$value" ;;
|
||||
init_system) INIT_SYSTEM="$value" ;;
|
||||
us_cloud_reachable) US_CLOUD_REACHABLE="$value" ;;
|
||||
eu_cloud_reachable) EU_CLOUD_REACHABLE="$value" ;;
|
||||
registry_reachable) REGISTRY_REACHABLE="$value" ;;
|
||||
download_reachable) DOWNLOAD_REACHABLE="$value" ;;
|
||||
git_reachable) GIT_REACHABLE="$value" ;;
|
||||
esac
|
||||
done < "$ENV_FILE"
|
||||
# Load environment variables from .env file (from shared library)
|
||||
if ! load_env_file "$ENV_FILE"; then
|
||||
fail_with_remediation "Cannot load preflight results" \
|
||||
"The preflight check results file could not be read.
|
||||
1. Run the preflight check: $SCRIPT_DIR/wallarm-ct-check.sh
|
||||
2. Verify $ENV_FILE exists and is readable
|
||||
3. Run this script again"
|
||||
fi
|
||||
|
||||
if [ "$CHECK_RESULT" != "pass" ]; then
|
||||
log_message "ERROR" "Preflight check failed (result: $CHECK_RESULT)"
|
||||
echo -e "\n${YELLOW}Preflight check found issues. Please review:${NC}"
|
||||
echo -e "${YELLOW}1. Check file: $ENV_FILE${NC}"
|
||||
echo -e "${YELLOW}2. Run: ./wallarm-ct-check.sh${NC}"
|
||||
echo -e "${YELLOW}2. Run: $SCRIPT_DIR/wallarm-ct-check.sh${NC}"
|
||||
echo -e "${YELLOW}3. Fix the issues and try again${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -324,7 +146,7 @@ verify_preflight_check() {
|
|||
"Network connectivity issues detected:
|
||||
1. Check firewall rules for Wallarm cloud endpoints
|
||||
2. Verify network connectivity
|
||||
3. Run preflight check again: ./wallarm-ct-check.sh"
|
||||
3. Run preflight check again: $SCRIPT_DIR/wallarm-ct-check.sh"
|
||||
fi
|
||||
|
||||
# Validate we have resources for Docker/Wallarm
|
||||
|
|
@ -365,126 +187,8 @@ verify_preflight_check() {
|
|||
# ==============================================================================
|
||||
# CONFIGURATION COLLECTION FUNCTIONS
|
||||
# ==============================================================================
|
||||
|
||||
select_cloud_region() {
|
||||
log_message "INFO" "Selecting Wallarm Cloud region..."
|
||||
|
||||
echo -e "\n${CYAN}${BOLD}Wallarm Cloud Region Selection:${NC}"
|
||||
|
||||
# Show available regions based on preflight check
|
||||
local available_options=()
|
||||
|
||||
if [ "$US_CLOUD_REACHABLE" = "true" ]; then
|
||||
echo -e "1. ${YELLOW}US Cloud${NC} (us1.api.wallarm.com) - For US-based deployments"
|
||||
available_options+=("1" "US")
|
||||
fi
|
||||
|
||||
if [ "$EU_CLOUD_REACHABLE" = "true" ]; then
|
||||
echo -e "2. ${YELLOW}EU Cloud${NC} (api.wallarm.com) - For EU-based deployments"
|
||||
available_options+=("2" "EU")
|
||||
fi
|
||||
|
||||
if [ ${#available_options[@]} -eq 0 ]; then
|
||||
fail_with_remediation "No cloud regions available" \
|
||||
"Preflight check showed no reachable cloud regions.
|
||||
1. Check network connectivity to Wallarm endpoints
|
||||
2. Run preflight check again: ./wallarm-ct-check.sh
|
||||
3. Contact network administrator if behind firewall"
|
||||
fi
|
||||
|
||||
# Build regex pattern for validation
|
||||
local pattern
|
||||
pattern="^($(IFS='|'; echo "${available_options[*]}"))$"
|
||||
|
||||
local cloud_choice=""
|
||||
while [[ ! "$cloud_choice" =~ $pattern ]]; do
|
||||
if [ ${#available_options[@]} -eq 2 ]; then
|
||||
# Only one region available
|
||||
if [ "$US_CLOUD_REACHABLE" = "true" ]; then
|
||||
cloud_choice="US"
|
||||
break
|
||||
else
|
||||
cloud_choice="EU"
|
||||
break
|
||||
fi
|
||||
fi
|
||||
|
||||
read -r -p "$(echo -e "${YELLOW}Enter choice [1/US or 2/EU]: ${NC}")" cloud_choice
|
||||
cloud_choice=$(echo "$cloud_choice" | tr '[:lower:]' '[:upper:]')
|
||||
|
||||
case "$cloud_choice" in
|
||||
1|"US")
|
||||
if [ "$US_CLOUD_REACHABLE" = "true" ]; then
|
||||
CLOUD_REGION="US"
|
||||
API_HOST="us1.api.wallarm.com"
|
||||
log_message "INFO" "Selected US Cloud"
|
||||
else
|
||||
echo -e "${RED}US Cloud is not reachable (per preflight check)${NC}"
|
||||
cloud_choice=""
|
||||
fi
|
||||
;;
|
||||
2|"EU")
|
||||
if [ "$EU_CLOUD_REACHABLE" = "true" ]; then
|
||||
CLOUD_REGION="EU"
|
||||
API_HOST="api.wallarm.com"
|
||||
log_message "INFO" "Selected EU Cloud"
|
||||
else
|
||||
echo -e "${RED}EU Cloud is not reachable (per preflight check)${NC}"
|
||||
cloud_choice=""
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if [ -n "$cloud_choice" ]; then
|
||||
echo -e "${RED}Invalid choice. Select from available options above.${NC}"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
log_message "SUCCESS" "Cloud region selected: $CLOUD_REGION ($API_HOST)"
|
||||
}
|
||||
|
||||
# Critical fix from review: Proper IP validation
|
||||
validate_ip_address() {
|
||||
local ip="$1"
|
||||
|
||||
# Check basic format
|
||||
if [[ ! "$ip" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Check each octet is 0-255
|
||||
IFS='.' read -r i1 i2 i3 i4 <<< "$ip"
|
||||
if [ "$i1" -gt 255 ] || [ "$i2" -gt 255 ] || [ "$i3" -gt 255 ] || [ "$i4" -gt 255 ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Critical fix from review: Port conflict detection with fallback
|
||||
check_port_available() {
|
||||
local port="$1"
|
||||
local protocol="${2:-tcp}"
|
||||
|
||||
log_message "DEBUG" "Checking port $port/$protocol availability..."
|
||||
|
||||
# Try ss first (modern, usually available)
|
||||
if command -v ss >/dev/null 2>&1; then
|
||||
if ss -"${protocol:0:1}"ln | grep -q ":$port "; then
|
||||
return 1 # Port in use
|
||||
fi
|
||||
# Fallback to netstat
|
||||
elif command -v netstat >/dev/null 2>&1; then
|
||||
if netstat -tulpn 2>/dev/null | grep -E ":$port\s" >/dev/null 2>&1; then
|
||||
return 1 # Port in use
|
||||
fi
|
||||
else
|
||||
log_message "WARNING" "Neither ss nor netstat available, cannot check port $port"
|
||||
fi
|
||||
|
||||
return 0 # Port available (or cannot check)
|
||||
}
|
||||
# select_cloud_region, validate_ip_address and check_port_available are provided
|
||||
# by the shared library (../common/wallarm-lib.sh).
|
||||
|
||||
collect_configuration() {
|
||||
log_message "INFO" "Collecting deployment configuration..."
|
||||
|
|
@ -1863,7 +1567,7 @@ main() {
|
|||
clear
|
||||
echo -e "${BLUE}${BOLD}"
|
||||
echo "╔══════════════════════════════════════════════════════════════╗"
|
||||
echo "║ WALLARM DEPLOYMENT SCRIPT - V1.2 ║"
|
||||
echo "║ WALLARM DEPLOYMENT SCRIPT (Docker) - V1.3 ║"
|
||||
echo "║ LXC-Optimized Filtering Node Deployment ║"
|
||||
echo "╚══════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo -e "\n${YELLOW}Starting deployment at: $(date)${NC}"
|
||||
19
wallarm-ct-reconfigure.sh → docker/wallarm-ct-reconfigure.sh
Normal file → Executable file
19
wallarm-ct-reconfigure.sh → docker/wallarm-ct-reconfigure.sh
Normal file → Executable file
|
|
@ -1,8 +1,8 @@
|
|||
#!/bin/bash
|
||||
# ==============================================================================
|
||||
# WALLARM RECONFIGURATION SCRIPT - V1.0
|
||||
# WALLARM RECONFIGURATION SCRIPT - V1.1 (Docker deployment)
|
||||
# ==============================================================================
|
||||
# Purpose: Modify nginx configuration of an existing Wallarm node
|
||||
# Purpose: Modify nginx configuration of an existing Wallarm Docker node
|
||||
# Features:
|
||||
# - Update set_real_ip_from (trusted proxy IPs/CIDRs)
|
||||
# - Change wallarm_mode (monitoring/block)
|
||||
|
|
@ -10,16 +10,13 @@
|
|||
# - Interactive prompts with validation
|
||||
# ==============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
# Script location and shared library (colors, logging, validation)
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=../common/wallarm-lib.sh
|
||||
source "$SCRIPT_DIR/../common/wallarm-lib.sh"
|
||||
|
||||
# Color definitions
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[1;34m'
|
||||
CYAN='\033[0;36m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m'
|
||||
set -euo pipefail
|
||||
trap early_error_handler ERR
|
||||
|
||||
# ==============================================================================
|
||||
# CHECK FOR SUDO / ROOT PRIVILEGES
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
#!/bin/bash
|
||||
# ==============================================================================
|
||||
# WALLARM UNINSTALL SCRIPT - V1.0
|
||||
# WALLARM UNINSTALL SCRIPT - V1.1 (Docker deployment)
|
||||
# ==============================================================================
|
||||
# Purpose: Safely remove Wallarm filtering node and cleanup Docker installation
|
||||
# Purpose: Safely remove a Wallarm Docker node and cleanup Docker installation
|
||||
# Features:
|
||||
# - Interactive confirmation with safety checks
|
||||
# - Stops and removes Wallarm container and image
|
||||
|
|
@ -12,43 +12,18 @@
|
|||
# - DAU-friendly warnings and confirmations
|
||||
# ==============================================================================
|
||||
|
||||
# Color definitions for better UX
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[1;34m'
|
||||
CYAN='\033[0;36m'
|
||||
MAGENTA='\033[0;35m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m' # No Color
|
||||
# Script location and shared library (colors, logging, validation)
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=../common/wallarm-lib.sh
|
||||
source "$SCRIPT_DIR/../common/wallarm-lib.sh"
|
||||
|
||||
# Strict error handling
|
||||
set -euo pipefail
|
||||
# Simple error handler for early failures (before log_message is defined)
|
||||
early_error_handler() {
|
||||
echo -e "${RED}${BOLD}[ERROR]${NC} Script failed at line $LINENO. Command: $BASH_COMMAND" >&2
|
||||
exit 1
|
||||
}
|
||||
trap early_error_handler ERR
|
||||
|
||||
# Logging function
|
||||
log_message() {
|
||||
local level="$1"
|
||||
local message="$2"
|
||||
local timestamp
|
||||
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
|
||||
case "$level" in
|
||||
"INFO") color="${BLUE}" ;;
|
||||
"SUCCESS") color="${GREEN}" ;;
|
||||
"WARNING") color="${YELLOW}" ;;
|
||||
"ERROR") color="${RED}" ;;
|
||||
"DEBUG") color="${CYAN}" ;;
|
||||
*) color="${NC}" ;;
|
||||
esac
|
||||
|
||||
echo -e "${color}[${timestamp}] ${level}: ${message}${NC}" >&2
|
||||
}
|
||||
# ==============================================================================
|
||||
# FUNCTIONS
|
||||
# ==============================================================================
|
||||
|
||||
# Ask for confirmation
|
||||
confirm() {
|
||||
364
native/wallarm-ct-check.sh
Executable file
364
native/wallarm-ct-check.sh
Executable file
|
|
@ -0,0 +1,364 @@
|
|||
#!/bin/bash
|
||||
# ==============================================================================
|
||||
# WALLARM PREFLIGHT CHECK SCRIPT - V1.0 (Native deployment)
|
||||
# ==============================================================================
|
||||
# Purpose: Validate system readiness for native (no-Docker) Wallarm deployment
|
||||
# Features:
|
||||
# - Non-interactive system validation (sudo, OS, architecture, init system)
|
||||
# - Network connectivity testing (US/EU cloud + Wallarm all-in-one installer)
|
||||
# - Resource availability assessment
|
||||
# - Outputs results to .env file for deployment script
|
||||
# - DAU-friendly error messages with remediation
|
||||
# ==============================================================================
|
||||
|
||||
# Script location and shared library (colors, logging, validation, detection, connectivity)
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=../common/wallarm-lib.sh
|
||||
source "$SCRIPT_DIR/../common/wallarm-lib.sh"
|
||||
|
||||
# Strict error handling
|
||||
set -euo pipefail
|
||||
trap early_error_handler ERR
|
||||
|
||||
# Configuration
|
||||
ENV_FILE=".env"
|
||||
LOG_FILE="${HOME:-.}/logs/wallarm-check-native.log"
|
||||
|
||||
# Native install artifacts (Wallarm all-in-one installer)
|
||||
WALLARM_VERSION="${WALLARM_VERSION:-6.12.7}"
|
||||
INSTALLER_BASE_URL="https://meganode.wallarm.com/${WALLARM_VERSION%.*}"
|
||||
INSTALLER_NAME="wallarm-${WALLARM_VERSION}.x86_64-glibc.sh"
|
||||
INSTALLER_URL="${INSTALLER_BASE_URL}/${INSTALLER_NAME}"
|
||||
|
||||
# Cloud endpoints (from Wallarm documentation)
|
||||
EU_DATA_NODES=("api.wallarm.com" "node-data0.eu1.wallarm.com" "node-data1.eu1.wallarm.com")
|
||||
US_DATA_NODES=("us1.api.wallarm.com" "node-data0.us1.wallarm.com" "node-data1.us1.wallarm.com")
|
||||
|
||||
# Global result tracking
|
||||
CHECK_RESULT="pass"
|
||||
CHECK_ERRORS=()
|
||||
INSTALLER_REACHABLE="false"
|
||||
|
||||
# ==============================================================================
|
||||
# RESULT TRACKING & ENV FILE
|
||||
# ==============================================================================
|
||||
|
||||
add_error() {
|
||||
local error_msg="$1"
|
||||
CHECK_ERRORS+=("$error_msg")
|
||||
CHECK_RESULT="fail"
|
||||
log_message "ERROR" "$error_msg"
|
||||
}
|
||||
|
||||
write_env_file() {
|
||||
local os_name="$1"
|
||||
local os_version="$2"
|
||||
local architecture="$3"
|
||||
local init_system="$4"
|
||||
local us_cloud_reachable="$5"
|
||||
local eu_cloud_reachable="$6"
|
||||
local installer_reachable="${7:-false}"
|
||||
|
||||
cat > "$ENV_FILE" << EOF
|
||||
# Wallarm Preflight Check Results (Native deployment)
|
||||
# Generated: $(date '+%Y-%m-%d %H:%M:%S')
|
||||
# Script: $0
|
||||
|
||||
result=$CHECK_RESULT
|
||||
os_name=$os_name
|
||||
os_version=$os_version
|
||||
architecture=$architecture
|
||||
init_system=$init_system
|
||||
us_cloud_reachable=$us_cloud_reachable
|
||||
eu_cloud_reachable=$eu_cloud_reachable
|
||||
installer_reachable=$installer_reachable
|
||||
|
||||
EOF
|
||||
|
||||
if [ ${#CHECK_ERRORS[@]} -gt 0 ]; then
|
||||
echo "# Errors:" >> "$ENV_FILE"
|
||||
for i in "${!CHECK_ERRORS[@]}"; do
|
||||
echo "error_$i=\"${CHECK_ERRORS[$i]}\"" >> "$ENV_FILE"
|
||||
done
|
||||
fi
|
||||
|
||||
log_message "SUCCESS" "Check results written to $ENV_FILE"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# PRE-FLIGHT VALIDATION FUNCTIONS
|
||||
# ==============================================================================
|
||||
|
||||
validate_sudo_access() {
|
||||
log_message "INFO" "Validating sudo access..."
|
||||
|
||||
local os_name
|
||||
os_name=$(uname -s | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
if ! command -v sudo >/dev/null 2>&1; then
|
||||
add_error "sudo command not found"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$os_name" = "darwin" ]; then
|
||||
log_message "WARNING" "macOS detected: sudo authentication test skipped (may prompt during deployment)"
|
||||
log_message "INFO" "Note: macOS is not a supported deployment target. This check is for Linux servers."
|
||||
return 0
|
||||
fi
|
||||
|
||||
if ! sudo -v; then
|
||||
add_error "sudo authentication failed"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log_message "SUCCESS" "Sudo access validated"
|
||||
return 0
|
||||
}
|
||||
|
||||
validate_required_commands() {
|
||||
log_message "INFO" "Validating required system commands..."
|
||||
|
||||
local missing_commands=()
|
||||
|
||||
local os_name
|
||||
os_name=$(uname -s | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
# Core commands required for native check and deployment scripts
|
||||
local core_commands=(
|
||||
"curl" # Required for downloading the all-in-one installer
|
||||
"grep" # Used extensively
|
||||
"cut" # Used for parsing output
|
||||
"tr" # Used for text transformations
|
||||
"sed" # Used for text processing
|
||||
"head" # Used for limiting output
|
||||
"tail" # Used for limiting output
|
||||
"ls" # Used for file listing
|
||||
"date" # Used for logging timestamps
|
||||
"mkdir" # Used for creating directories
|
||||
"chmod" # Used for permission changes
|
||||
"tee" # Required for writing configuration files
|
||||
"rm" # Required for cleanup operations
|
||||
)
|
||||
|
||||
# Check each core command (command_exists comes from common library)
|
||||
local cmd
|
||||
for cmd in "${core_commands[@]}"; do
|
||||
if ! command_exists "$cmd"; then
|
||||
missing_commands+=("$cmd")
|
||||
fi
|
||||
done
|
||||
|
||||
# Check for port checking utility (ss or netstat)
|
||||
if [ "$os_name" != "darwin" ]; then
|
||||
if ! command_exists ss && ! command_exists netstat; then
|
||||
missing_commands+=("ss or netstat")
|
||||
fi
|
||||
fi
|
||||
|
||||
# Detect init system and validate its control command
|
||||
if [ "$os_name" != "darwin" ]; then
|
||||
local init_system
|
||||
init_system=$(detect_init_system)
|
||||
|
||||
case "$init_system" in
|
||||
"systemd")
|
||||
if ! command_exists systemctl; then
|
||||
missing_commands+=("systemctl")
|
||||
fi
|
||||
;;
|
||||
"openrc")
|
||||
if ! command_exists rc-service; then
|
||||
missing_commands+=("rc-service")
|
||||
fi
|
||||
;;
|
||||
"sysvinit")
|
||||
if ! command_exists service; then
|
||||
missing_commands+=("service")
|
||||
fi
|
||||
;;
|
||||
"upstart")
|
||||
if ! command_exists initctl; then
|
||||
missing_commands+=("initctl")
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
log_message "WARNING" "Unknown init system '$init_system', cannot validate init command"
|
||||
;;
|
||||
esac
|
||||
else
|
||||
log_message "INFO" "Skipping init system validation on macOS (not a deployment target)"
|
||||
fi
|
||||
|
||||
if [ ${#missing_commands[@]} -gt 0 ]; then
|
||||
local missing_list
|
||||
missing_list=$(IFS=', '; echo "${missing_commands[*]}")
|
||||
add_error "Missing required commands: $missing_list"
|
||||
log_message "ERROR" "Please install missing commands and run the check again."
|
||||
return 1
|
||||
fi
|
||||
|
||||
log_message "SUCCESS" "All required system commands are available"
|
||||
return 0
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# NETWORK CONNECTIVITY TESTING
|
||||
# ==============================================================================
|
||||
|
||||
perform_network_tests() {
|
||||
log_message "INFO" "=== NETWORK CONNECTIVITY TESTING ==="
|
||||
|
||||
# Test US cloud endpoints
|
||||
local us_reachable
|
||||
us_reachable=$(test_cloud_endpoints "US" "${US_DATA_NODES[@]}")
|
||||
|
||||
# Test EU cloud endpoints
|
||||
local eu_reachable
|
||||
eu_reachable=$(test_cloud_endpoints "EU" "${EU_DATA_NODES[@]}")
|
||||
|
||||
# Test Wallarm all-in-one installer reachability (needed for native install)
|
||||
log_message "INFO" "Testing Wallarm all-in-one installer availability..."
|
||||
if test_connectivity "$INSTALLER_URL" "Wallarm all-in-one installer"; then
|
||||
INSTALLER_REACHABLE="true"
|
||||
log_message "SUCCESS" "Wallarm installer is reachable (version $WALLARM_VERSION)"
|
||||
else
|
||||
log_message "WARNING" "Wallarm installer is not reachable at $INSTALLER_URL"
|
||||
log_message "INFO" "Check https://docs.wallarm.com/updating-migrating/node-artifact-versions/ for the latest version."
|
||||
fi
|
||||
|
||||
echo "$us_reachable:$eu_reachable:$INSTALLER_REACHABLE"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# MAIN FUNCTION
|
||||
# ==============================================================================
|
||||
|
||||
main() {
|
||||
clear
|
||||
echo -e "${BLUE}${BOLD}"
|
||||
echo "╔══════════════════════════════════════════════════════════════╗"
|
||||
echo "║ WALLARM PREFLIGHT CHECK SCRIPT (Native) - V1.0 ║"
|
||||
echo "║ System Readiness Validation for Deployment ║"
|
||||
echo "╚══════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo -e "\n${YELLOW}Starting preflight check at: $(date)${NC}"
|
||||
|
||||
# Initialize logging
|
||||
local log_dir="${HOME:-.}/logs"
|
||||
if [ ! -d "$log_dir" ]; then
|
||||
if ! mkdir -p "$log_dir"; then
|
||||
echo -e "${YELLOW}Cannot create log directory $log_dir, falling back to current directory...${NC}"
|
||||
log_dir="."
|
||||
fi
|
||||
fi
|
||||
|
||||
LOG_FILE="$log_dir/wallarm-check-native.log"
|
||||
if ! : > "$LOG_FILE"; then
|
||||
echo -e "${RED}Cannot create log file at $LOG_FILE${NC}"
|
||||
echo -e "${YELLOW}Falling back to current directory...${NC}"
|
||||
LOG_FILE="./wallarm-check-native.log"
|
||||
: > "$LOG_FILE" 2>/dev/null || true
|
||||
fi
|
||||
if ! chmod 644 "$LOG_FILE" 2>/dev/null; then
|
||||
echo -e "${YELLOW}Warning: Could not set permissions on log file${NC}"
|
||||
fi
|
||||
|
||||
log_message "INFO" "=== Wallarm Preflight Check (Native) Started ==="
|
||||
|
||||
if [ "$INSECURE_SSL" = "1" ]; then
|
||||
log_message "WARNING" "SSL certificate validation is DISABLED (insecure). Set WALLARM_INSECURE_SSL=0 to enable validation."
|
||||
fi
|
||||
|
||||
# Phase 1: System validation
|
||||
log_message "INFO" "=== PHASE 1: SYSTEM VALIDATION ==="
|
||||
|
||||
if ! validate_required_commands; then
|
||||
add_error "Required system commands validation failed"
|
||||
fi
|
||||
|
||||
if ! validate_sudo_access; then
|
||||
add_error "Sudo access validation failed"
|
||||
fi
|
||||
|
||||
local os_info
|
||||
os_info=$(detect_os_and_version)
|
||||
local os_name
|
||||
os_name=$(echo "$os_info" | cut -d: -f1)
|
||||
local os_version
|
||||
os_version=$(echo "$os_info" | cut -d: -f2)
|
||||
|
||||
local architecture
|
||||
architecture=$(detect_architecture)
|
||||
if [ "$architecture" = "unknown" ]; then
|
||||
add_error "Unsupported architecture detected"
|
||||
fi
|
||||
|
||||
local init_system
|
||||
init_system=$(detect_init_system)
|
||||
|
||||
log_message "SUCCESS" "System validation completed:"
|
||||
log_message "SUCCESS" " OS: $os_name $os_version"
|
||||
log_message "SUCCESS" " Architecture: $architecture"
|
||||
log_message "SUCCESS" " Init System: $init_system"
|
||||
|
||||
# Phase 2: Network connectivity testing
|
||||
log_message "INFO" "=== PHASE 2: NETWORK CONNECTIVITY TESTING ==="
|
||||
|
||||
local network_results
|
||||
network_results=$(perform_network_tests)
|
||||
local us_reachable
|
||||
us_reachable=$(echo "$network_results" | cut -d: -f1)
|
||||
local eu_reachable
|
||||
eu_reachable=$(echo "$network_results" | cut -d: -f2)
|
||||
local installer_reachable
|
||||
installer_reachable=$(echo "$network_results" | cut -d: -f3)
|
||||
|
||||
log_message "SUCCESS" "Network testing completed:"
|
||||
log_message "SUCCESS" " US Cloud Reachable: $us_reachable"
|
||||
log_message "SUCCESS" " EU Cloud Reachable: $eu_reachable"
|
||||
log_message "SUCCESS" " Wallarm Installer Reachable: $installer_reachable"
|
||||
|
||||
# Phase 3: Write results
|
||||
log_message "INFO" "=== PHASE 3: WRITING RESULTS ==="
|
||||
|
||||
write_env_file "$os_name" "$os_version" "$architecture" "$init_system" \
|
||||
"$us_reachable" "$eu_reachable" "$installer_reachable"
|
||||
|
||||
# Final summary
|
||||
if [ "$CHECK_RESULT" = "pass" ]; then
|
||||
log_message "SUCCESS" "=== PREFLIGHT CHECK PASSED ==="
|
||||
echo -e "\n${GREEN}${BOLD}╔══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${GREEN}${BOLD}║ PREFLIGHT CHECK PASSED - SYSTEM READY ║${NC}"
|
||||
echo -e "${GREEN}${BOLD}╚══════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo -e "\n${CYAN}System is ready for native Wallarm deployment.${NC}"
|
||||
echo -e "${YELLOW}Check results: $ENV_FILE${NC}"
|
||||
echo -e "${YELLOW}Full log: $LOG_FILE${NC}"
|
||||
echo -e "\n${GREEN}Next step: Run ./native/wallarm-ct-deploy.sh to proceed with deployment${NC}"
|
||||
exit 0
|
||||
else
|
||||
log_message "ERROR" "=== PREFLIGHT CHECK FAILED ==="
|
||||
echo -e "\n${RED}${BOLD}╔══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${RED}${BOLD}║ PREFLIGHT CHECK FAILED - SYSTEM NOT READY ║${NC}"
|
||||
echo -e "${RED}${BOLD}╚══════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo -e "\n${YELLOW}${BOLD}Issues found:${NC}"
|
||||
for error in "${CHECK_ERRORS[@]}"; do
|
||||
echo -e " ${RED}•${NC} $error"
|
||||
done
|
||||
echo -e "\n${YELLOW}Check results: $ENV_FILE${NC}"
|
||||
echo -e "${YELLOW}Full log: $LOG_FILE${NC}"
|
||||
echo -e "\n${CYAN}Please fix the issues above and run the check again.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# SCRIPT EXECUTION
|
||||
# ==============================================================================
|
||||
|
||||
# Ensure we're in bash
|
||||
if [ -z "$BASH_VERSION" ]; then
|
||||
echo "Error: This script must be run with bash" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Run main function
|
||||
main "$@"
|
||||
673
native/wallarm-ct-deploy.sh
Executable file
673
native/wallarm-ct-deploy.sh
Executable file
|
|
@ -0,0 +1,673 @@
|
|||
#!/bin/bash
|
||||
# ==============================================================================
|
||||
# WALLARM DEPLOYMENT SCRIPT - V1.0 (Native deployment)
|
||||
# ==============================================================================
|
||||
# Purpose: Deploy Wallarm filtering node natively (NO Docker) after preflight
|
||||
# Features:
|
||||
# - Reads preflight check results from .env file
|
||||
# - Interactive configuration (cloud region, ports, token, upstream)
|
||||
# - Downloads and runs the official Wallarm all-in-one installer (meganode.wallarm.com)
|
||||
# - Configures NGINX server block (proxy, wallarm_mode, trusted proxies, health)
|
||||
# - Deployment verification (health endpoint, wallarm-status, node registration)
|
||||
# - DAU-friendly error handling with remediation
|
||||
# ==============================================================================
|
||||
|
||||
# Script location and shared library (colors, logging, validation, detection, connectivity)
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=../common/wallarm-lib.sh
|
||||
source "$SCRIPT_DIR/../common/wallarm-lib.sh"
|
||||
|
||||
# Strict error handling
|
||||
set -euo pipefail
|
||||
trap early_error_handler ERR
|
||||
|
||||
# Configuration
|
||||
ENV_FILE=".env"
|
||||
LOG_FILE="${HOME:-.}/logs/wallarm-deployment-native.log"
|
||||
|
||||
# Wallarm all-in-one installer (current recommended native install method)
|
||||
# Override WALLARM_VERSION to pin a different version.
|
||||
WALLARM_VERSION="${WALLARM_VERSION:-6.12.7}"
|
||||
INSTALLER_BASE_URL="https://meganode.wallarm.com/${WALLARM_VERSION%.*}"
|
||||
|
||||
# Optional node labels for the installer (e.g. 'group=prod')
|
||||
WALLARM_LABELS="${WALLARM_LABELS:-}"
|
||||
|
||||
# Deployment variables (set during execution)
|
||||
CLOUD_REGION=""
|
||||
API_HOST=""
|
||||
INGRESS_PORT=""
|
||||
UPSTREAM_IP=""
|
||||
UPSTREAM_PORT=""
|
||||
WALLARM_TOKEN=""
|
||||
INSTANCE_NAME=""
|
||||
INSTANCE_DIR=""
|
||||
NGINX_CONFIG=""
|
||||
|
||||
# Resource reachability from check script
|
||||
US_CLOUD_REACHABLE="false"
|
||||
EU_CLOUD_REACHABLE="false"
|
||||
INSTALLER_REACHABLE="false"
|
||||
|
||||
# ==============================================================================
|
||||
# PREFLIGHT CHECK VERIFICATION
|
||||
# ==============================================================================
|
||||
|
||||
verify_preflight_check() {
|
||||
log_message "INFO" "Verifying preflight check results..."
|
||||
|
||||
if [ ! -f "$ENV_FILE" ]; then
|
||||
log_message "ERROR" "Preflight check file not found: $ENV_FILE"
|
||||
echo -e "\n${YELLOW}Preflight check has not been run or .env file is missing.${NC}"
|
||||
echo -e "${YELLOW}Would you like to run the preflight check now?${NC}"
|
||||
read -r -p "$(echo -e "${YELLOW}Run preflight check? (Y/n): ${NC}")" -n 1
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Nn]$ ]]; then
|
||||
echo -e "${CYAN}Running preflight check...${NC}"
|
||||
if ! "$SCRIPT_DIR/wallarm-ct-check.sh"; then
|
||||
fail_with_remediation "Preflight check failed" \
|
||||
"Run the preflight check manually and fix any issues:
|
||||
1. $SCRIPT_DIR/wallarm-ct-check.sh
|
||||
2. Review the errors in $ENV_FILE
|
||||
3. Fix the issues and run this script again"
|
||||
fi
|
||||
else
|
||||
fail_with_remediation "Preflight check required" \
|
||||
"Run the preflight check before deployment:
|
||||
1. $SCRIPT_DIR/wallarm-ct-check.sh
|
||||
2. Review results in $ENV_FILE
|
||||
3. Run this script again"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Load environment variables from .env file (from shared library)
|
||||
if ! load_env_file "$ENV_FILE"; then
|
||||
fail_with_remediation "Cannot load preflight results" \
|
||||
"The preflight check results file could not be read.
|
||||
1. Run the preflight check: $SCRIPT_DIR/wallarm-ct-check.sh
|
||||
2. Verify $ENV_FILE exists and is readable
|
||||
3. Run this script again"
|
||||
fi
|
||||
|
||||
if [ "${CHECK_RESULT:-}" != "pass" ]; then
|
||||
log_message "ERROR" "Preflight check failed (result: $CHECK_RESULT)"
|
||||
echo -e "\n${YELLOW}Preflight check found issues. Please review:${NC}"
|
||||
echo -e "${YELLOW}1. Check file: $ENV_FILE${NC}"
|
||||
echo -e "${YELLOW}2. Run: $SCRIPT_DIR/wallarm-ct-check.sh${NC}"
|
||||
echo -e "${YELLOW}3. Fix the issues and try again${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_message "SUCCESS" "Preflight check verified:"
|
||||
log_message "SUCCESS" " OS: $OS_NAME $OS_VERSION"
|
||||
log_message "SUCCESS" " Architecture: $ARCHITECTURE"
|
||||
log_message "SUCCESS" " Init System: $INIT_SYSTEM"
|
||||
log_message "SUCCESS" " US Cloud Reachable: $US_CLOUD_REACHABLE"
|
||||
log_message "SUCCESS" " EU Cloud Reachable: $EU_CLOUD_REACHABLE"
|
||||
log_message "SUCCESS" " Wallarm Installer Reachable: $INSTALLER_REACHABLE"
|
||||
|
||||
# Validate we have at least one cloud region reachable
|
||||
if [ "$US_CLOUD_REACHABLE" = "false" ] && [ "$EU_CLOUD_REACHABLE" = "false" ]; then
|
||||
fail_with_remediation "No Wallarm cloud region reachable" \
|
||||
"Network connectivity issues detected:
|
||||
1. Check firewall rules for Wallarm cloud endpoints
|
||||
2. Verify network connectivity
|
||||
3. Run preflight check again: $SCRIPT_DIR/wallarm-ct-check.sh"
|
||||
fi
|
||||
|
||||
# The all-in-one installer must be reachable for a native deployment
|
||||
if [ "$INSTALLER_REACHABLE" != "true" ]; then
|
||||
fail_with_remediation "Wallarm all-in-one installer not reachable" \
|
||||
"Native deployment requires access to the Wallarm all-in-one installer:
|
||||
1. Verify network access to $INSTALLER_BASE_URL
|
||||
2. Check the current version at https://docs.wallarm.com/updating-migrating/node-artifact-versions/
|
||||
3. Pin the version with: WALLARM_VERSION=<version> sudo ./$0"
|
||||
fi
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# CONFIGURATION COLLECTION
|
||||
# ==============================================================================
|
||||
# select_cloud_region, validate_ip_address and check_port_available are provided
|
||||
# by the shared library (../common/wallarm-lib.sh).
|
||||
|
||||
collect_configuration() {
|
||||
log_message "INFO" "Collecting deployment configuration..."
|
||||
|
||||
# Get ingress port
|
||||
local default_port=80
|
||||
local ingress_port=""
|
||||
while [[ ! "$ingress_port" =~ ^[0-9]+$ ]] || [ "$ingress_port" -lt 1 ] || [ "$ingress_port" -gt 65535 ]; do
|
||||
read -r -p "$(echo -e "${YELLOW}Enter inbound port [${default_port}]: ${NC}")" ingress_port
|
||||
ingress_port="${ingress_port:-$default_port}"
|
||||
|
||||
if [[ ! "$ingress_port" =~ ^[0-9]+$ ]]; then
|
||||
echo -e "${RED}Port must be a number${NC}"
|
||||
elif [ "$ingress_port" -lt 1 ] || [ "$ingress_port" -gt 65535 ]; then
|
||||
echo -e "${RED}Port must be between 1 and 65535${NC}"
|
||||
elif ! check_port_available "$ingress_port"; then
|
||||
echo -e "${RED}Port $ingress_port is already in use${NC}"
|
||||
ingress_port=""
|
||||
fi
|
||||
done
|
||||
|
||||
# Get application server details
|
||||
local upstream_ip=""
|
||||
local upstream_port=""
|
||||
|
||||
echo -e "\n${CYAN}${BOLD}Application Server Configuration:${NC}"
|
||||
echo -e "${YELLOW}Enter the IP/hostname and port of your backend application${NC}"
|
||||
|
||||
while [[ -z "$upstream_ip" ]]; do
|
||||
read -r -p "$(echo -e "${YELLOW}Upstream App IP/Hostname [127.0.0.1]: ${NC}")" upstream_ip
|
||||
upstream_ip="${upstream_ip:-127.0.0.1}"
|
||||
|
||||
if ! validate_ip_address "$upstream_ip" && \
|
||||
! [[ "$upstream_ip" =~ ^[a-zA-Z0-9][a-zA-Z0-9.-]*[a-zA-Z0-9]$ ]]; then
|
||||
echo -e "${RED}Invalid IP/hostname format${NC}"
|
||||
upstream_ip=""
|
||||
fi
|
||||
done
|
||||
|
||||
while [[ ! "$upstream_port" =~ ^[0-9]+$ ]] || [ "$upstream_port" -lt 1 ] || [ "$upstream_port" -gt 65535 ]; do
|
||||
read -r -p "$(echo -e "${YELLOW}Upstream App Port [8080]: ${NC}")" upstream_port
|
||||
upstream_port="${upstream_port:-8080}"
|
||||
|
||||
if [[ ! "$upstream_port" =~ ^[0-9]+$ ]]; then
|
||||
echo -e "${RED}Port must be a number${NC}"
|
||||
elif [ "$upstream_port" -lt 1 ] || [ "$upstream_port" -gt 65535 ]; then
|
||||
echo -e "${RED}Port must be between 1 and 65535${NC}"
|
||||
fi
|
||||
done
|
||||
|
||||
# Verify application server reachability
|
||||
log_message "INFO" "Verifying application server reachability..."
|
||||
if timeout 5 bash -c "cat < /dev/null > /dev/tcp/$upstream_ip/$upstream_port" 2>/dev/null; then
|
||||
log_message "SUCCESS" "Application server $upstream_ip:$upstream_port is reachable"
|
||||
else
|
||||
log_message "WARNING" "Application server $upstream_ip:$upstream_port is not reachable"
|
||||
echo -e "${YELLOW}${BOLD}Warning:${NC} Cannot reach application server at $upstream_ip:$upstream_port"
|
||||
echo -e "${YELLOW}This may cause the Wallarm node to fail. Possible reasons:${NC}"
|
||||
echo -e "1. Application server is not running"
|
||||
echo -e "2. Firewall blocking port $upstream_port"
|
||||
echo -e "3. Wrong IP/hostname"
|
||||
echo -e "4. Application server not listening on that port"
|
||||
|
||||
read -r -p "$(echo -e "${YELLOW}Continue anyway? (y/N): ${NC}")" -n 1
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
fail_with_remediation "Application server unreachable" \
|
||||
"Ensure your application server is accessible:
|
||||
1. Start your application server
|
||||
2. Check it's listening: sudo ss -tlnp | grep :$upstream_port
|
||||
3. Verify firewall rules allow inbound connections
|
||||
4. Test connectivity: telnet $upstream_ip $upstream_port
|
||||
5. If using hostname, verify DNS resolution: nslookup $upstream_ip"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Get Wallarm node token
|
||||
local wallarm_token=""
|
||||
echo -e "\n${CYAN}${BOLD}Wallarm Node Token:${NC}"
|
||||
echo -e "${YELLOW}Get your token from Wallarm Console:${NC}"
|
||||
echo -e "Create a new 'Wallarm node' and copy the token (will be visible as you type)"
|
||||
while [[ -z "$wallarm_token" ]]; do
|
||||
read -r -p "$(echo -e "${YELLOW}Paste Wallarm Node Token: ${NC}")" wallarm_token
|
||||
wallarm_token=$(echo "$wallarm_token" | tr -d '[:space:]')
|
||||
|
||||
if [[ -z "$wallarm_token" ]]; then
|
||||
echo -e "${RED}Token cannot be empty${NC}"
|
||||
elif [[ ! "$wallarm_token" =~ ^[A-Za-z0-9_+/=\-]+$ ]]; then
|
||||
echo -e "${RED}Token contains invalid characters. Wallarm tokens are base64 strings (A-Z, a-z, 0-9, _, -, +, /, =)${NC}"
|
||||
echo -e "${YELLOW}First 20 chars of what you entered: '${wallarm_token:0:20}...'${NC}"
|
||||
wallarm_token=""
|
||||
else
|
||||
token_length=${#wallarm_token}
|
||||
echo -e "${GREEN}Token accepted (${token_length} characters).${NC}"
|
||||
echo -e "${YELLOW}First 8 chars for verification: ${wallarm_token:0:8}...${NC}"
|
||||
fi
|
||||
done
|
||||
|
||||
# Get trusted proxy IPs for real IP configuration
|
||||
local trusted_proxies=""
|
||||
echo -e "\n${CYAN}${BOLD}Real Client IP Configuration:${NC}"
|
||||
echo -e "${YELLOW}For Wallarm to see the real client IP, specify the IP address(es) of trusted proxies"
|
||||
echo -e "(e.g., load balancers, firewalls, CDNs) that forward traffic to this node.${NC}"
|
||||
echo -e "${YELLOW}You can enter:${NC}"
|
||||
echo -e " - Single IP: 10.0.0.10"
|
||||
echo -e " - CIDR range: 10.0.0.0/24"
|
||||
echo -e " - Multiple entries separated by spaces: 10.0.0.10 10.0.1.0/24 192.168.1.1"
|
||||
echo -e "${YELLOW}If unsure, you can leave empty and configure later${NC}"
|
||||
|
||||
read -r -p "$(echo -e "${YELLOW}Trusted proxy IPs/CIDRs (space-separated): ${NC}")" trusted_proxies_input
|
||||
|
||||
local validated_proxies=()
|
||||
if [[ -n "$trusted_proxies_input" ]]; then
|
||||
IFS=' ' read -ra proxy_array <<< "$trusted_proxies_input"
|
||||
|
||||
for proxy in "${proxy_array[@]}"; do
|
||||
proxy=$(echo "$proxy" | xargs)
|
||||
if [[ -n "$proxy" ]]; then
|
||||
if validate_ip_or_cidr "$proxy"; then
|
||||
validated_proxies+=("$proxy")
|
||||
else
|
||||
echo -e "${RED}Invalid IP/CIDR format: $proxy${NC}"
|
||||
echo -e "${YELLOW}Example valid formats: 10.0.0.10, 10.0.0.0/24, 192.168.1.1${NC}"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${#validated_proxies[@]} -eq 0 ]]; then
|
||||
echo -e "${YELLOW}No valid proxy IPs provided. Will skip set_real_ip_from configuration.${NC}"
|
||||
echo -e "${YELLOW}You can configure it later with the reconfigure script.${NC}"
|
||||
trusted_proxies=""
|
||||
else
|
||||
trusted_proxies="${validated_proxies[*]}"
|
||||
echo -e "${GREEN}Trusted proxies configured: $trusted_proxies${NC}"
|
||||
fi
|
||||
else
|
||||
echo -e "${YELLOW}No trusted proxies specified. The node will see the last hop IP only.${NC}"
|
||||
fi
|
||||
|
||||
# Generate instance name and directory
|
||||
local instance_name
|
||||
instance_name="wallarm-$(hostname -s | tr '[:upper:]' '[:lower:]')-$(date +%Y%m%d)"
|
||||
local instance_dir="/opt/wallarm/$instance_name"
|
||||
|
||||
sudo mkdir -p "$instance_dir"
|
||||
|
||||
log_message "SUCCESS" "Configuration collected:"
|
||||
log_message "SUCCESS" " Ingress Port: $ingress_port"
|
||||
log_message "SUCCESS" " Upstream: $upstream_ip:$upstream_port"
|
||||
if [[ -n "$trusted_proxies" ]]; then
|
||||
log_message "SUCCESS" " Trusted Proxies: $trusted_proxies"
|
||||
else
|
||||
log_message "INFO" " Trusted Proxies: Not configured (will need manual setup)"
|
||||
fi
|
||||
log_message "SUCCESS" " Instance: $instance_name"
|
||||
log_message "SUCCESS" " Directory: $instance_dir"
|
||||
|
||||
INGRESS_PORT="$ingress_port"
|
||||
UPSTREAM_IP="$upstream_ip"
|
||||
UPSTREAM_PORT="$upstream_port"
|
||||
WALLARM_TOKEN="$wallarm_token"
|
||||
INSTANCE_NAME="$instance_name"
|
||||
INSTANCE_DIR="$instance_dir"
|
||||
TRUSTED_PROXIES="$trusted_proxies"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# WALLARM NATIVE INSTALLATION (all-in-one installer)
|
||||
# ==============================================================================
|
||||
|
||||
install_wallarm_native() {
|
||||
log_message "INFO" "Installing Wallarm filtering node natively (all-in-one installer)..."
|
||||
|
||||
# Select the correct installer for the detected architecture
|
||||
local arch_suffix
|
||||
case "$ARCHITECTURE" in
|
||||
"x86_64") arch_suffix="x86_64-glibc" ;;
|
||||
"aarch64") arch_suffix="aarch64-glibc" ;;
|
||||
*)
|
||||
fail_with_remediation "Unsupported architecture for native install: $ARCHITECTURE" \
|
||||
"The Wallarm all-in-one installer supports x86_64 and aarch64.
|
||||
1. Check architecture: uname -m
|
||||
2. If you are on a 32-bit system, consider the Docker deployment instead.
|
||||
3. See https://docs.wallarm.com/installation/nginx/all-in-one/ for supported platforms."
|
||||
;;
|
||||
esac
|
||||
|
||||
local installer_name="wallarm-${WALLARM_VERSION}.${arch_suffix}.sh"
|
||||
local installer_url="${INSTALLER_BASE_URL}/${installer_name}"
|
||||
|
||||
log_message "INFO" "Downloading Wallarm installer: $installer_name"
|
||||
if ! download_from_git "$installer_url" "$installer_name" "Wallarm all-in-one installer"; then
|
||||
fail_with_remediation "Failed to download Wallarm installer" \
|
||||
"Could not download $installer_url
|
||||
1. Verify network access to meganode.wallarm.com
|
||||
2. Check the current version at https://docs.wallarm.com/updating-migrating/node-artifact-versions/
|
||||
3. Pin the version with: WALLARM_VERSION=<version> sudo ./$0"
|
||||
fi
|
||||
|
||||
chmod +x "$installer_name"
|
||||
|
||||
# Build installer arguments (batch mode)
|
||||
local install_args="-- --batch -t $WALLARM_TOKEN"
|
||||
if [ "$CLOUD_REGION" = "US" ]; then
|
||||
install_args="$install_args -c US"
|
||||
log_message "INFO" "Using US cloud (us1.api.wallarm.com)"
|
||||
else
|
||||
log_message "INFO" "Using EU cloud (api.wallarm.com)"
|
||||
fi
|
||||
|
||||
# Run the installer (batch mode). The installer registers the node with the
|
||||
# token and configures NGINX + the Wallarm module automatically.
|
||||
log_message "INFO" "Running Wallarm all-in-one installer (this may take several minutes)..."
|
||||
if [ -n "$WALLARM_LABELS" ]; then
|
||||
log_message "INFO" "Using node labels: $WALLARM_LABELS"
|
||||
if ! sudo env WALLARM_LABELS="$WALLARM_LABELS" sh "$installer_name" $install_args; then
|
||||
rm -f "$installer_name"
|
||||
fail_with_remediation "Wallarm installer failed" \
|
||||
"The all-in-one installer exited with an error. Check:
|
||||
1. The installer log output above for the exact error
|
||||
2. Token validity in the Wallarm Console
|
||||
3. Network access to Wallarm repositories (the installer adds them automatically)
|
||||
4. Disk space and memory: df -h / && free -h
|
||||
5. Retry with a higher log verbosity, or see https://docs.wallarm.com/installation/nginx/all-in-one/"
|
||||
fi
|
||||
else
|
||||
if ! sudo sh "$installer_name" $install_args; then
|
||||
rm -f "$installer_name"
|
||||
fail_with_remediation "Wallarm installer failed" \
|
||||
"The all-in-one installer exited with an error. Check:
|
||||
1. The installer log output above for the exact error
|
||||
2. Token validity in the Wallarm Console
|
||||
3. Network access to Wallarm repositories (the installer adds them automatically)
|
||||
4. Disk space and memory: df -h / && free -h
|
||||
5. Retry with a higher log verbosity, or see https://docs.wallarm.com/installation/nginx/all-in-one/"
|
||||
fi
|
||||
fi
|
||||
|
||||
rm -f "$installer_name"
|
||||
log_message "SUCCESS" "Wallarm all-in-one installer completed"
|
||||
|
||||
# Verify the node was registered
|
||||
if [ -f "/opt/wallarm/etc/wallarm/node.yaml" ]; then
|
||||
log_message "SUCCESS" "Wallarm node configuration found: /opt/wallarm/etc/wallarm/node.yaml"
|
||||
else
|
||||
log_message "WARNING" "Wallarm node configuration not found at /opt/wallarm/etc/wallarm/node.yaml"
|
||||
echo -e "${YELLOW}The node may not have been registered. Check the installer output.${NC}"
|
||||
fi
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# NGINX CONFIGURATION
|
||||
# ==============================================================================
|
||||
|
||||
# Detect existing NGINX server blocks that would conflict with our ingress port
|
||||
# and disable the default site if necessary.
|
||||
resolve_port_conflict() {
|
||||
local port="$1"
|
||||
|
||||
log_message "INFO" "Checking for NGINX config conflicts on port $port..."
|
||||
|
||||
# Only relevant for default port 80 where distro default sites listen
|
||||
if [ "$port" != "80" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Look for default server blocks listening on port 80
|
||||
local conflicting
|
||||
conflicting=$(grep -rl "listen.*80" /etc/nginx/sites-enabled/ /etc/nginx/conf.d/ 2>/dev/null | head -1 || true)
|
||||
|
||||
if [ -n "$conflicting" ]; then
|
||||
log_message "WARNING" "Default NGINX site found: $conflicting"
|
||||
echo -e "${YELLOW}The default site listens on port 80 and may conflict with the Wallarm node.${NC}"
|
||||
read -r -p "$(echo -e "${YELLOW}Disable it (backup to .bak)? (Y/n): ${NC}")" -n 1
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Nn]$ ]]; then
|
||||
sudo mv "$conflicting" "${conflicting}.bak"
|
||||
log_message "SUCCESS" "Disabled $conflicting (backup: ${conflicting}.bak)"
|
||||
else
|
||||
log_message "WARNING" "Keeping default site. The Wallarm node may not receive traffic on port 80."
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
create_nginx_config() {
|
||||
NGINX_CONFIG="/etc/nginx/conf.d/wallarm-${INSTANCE_NAME}.conf"
|
||||
|
||||
log_message "INFO" "Creating NGINX configuration: $NGINX_CONFIG"
|
||||
|
||||
# Also keep a copy in the instance directory for reference/backup
|
||||
sudo tee "$NGINX_CONFIG" > /dev/null <<EOF
|
||||
# Wallarm filtering node: $INSTANCE_NAME
|
||||
# Generated: $(date)
|
||||
server {
|
||||
listen $INGRESS_PORT;
|
||||
server_name _;
|
||||
EOF
|
||||
|
||||
# Add set_real_ip_from directives if trusted proxies are configured
|
||||
if [[ -n "$TRUSTED_PROXIES" ]]; then
|
||||
for proxy in $TRUSTED_PROXIES; do
|
||||
sudo tee -a "$NGINX_CONFIG" > /dev/null <<EOF
|
||||
set_real_ip_from $proxy;
|
||||
EOF
|
||||
done
|
||||
sudo tee -a "$NGINX_CONFIG" > /dev/null <<EOF
|
||||
real_ip_header X-Real-IP;
|
||||
real_ip_recursive on;
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Add the rest of the configuration
|
||||
sudo tee -a "$NGINX_CONFIG" > /dev/null <<EOF
|
||||
|
||||
location / {
|
||||
proxy_pass http://$UPSTREAM_IP:$UPSTREAM_PORT;
|
||||
proxy_set_header Host \$host;
|
||||
proxy_set_header X-Real-IP \$remote_addr;
|
||||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto \$scheme;
|
||||
proxy_set_header X-Forwarded-Server \$http_x_forwarded_server;
|
||||
|
||||
# Wallarm directives
|
||||
wallarm_mode monitoring;
|
||||
}
|
||||
|
||||
# Health check endpoint
|
||||
location /health {
|
||||
access_log off;
|
||||
return 200 "healthy\n";
|
||||
add_header Content-Type text/plain;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# Keep a reference copy in the instance directory
|
||||
sudo cp "$NGINX_CONFIG" "$INSTANCE_DIR/nginx.conf"
|
||||
log_message "SUCCESS" "NGINX configuration created: $NGINX_CONFIG"
|
||||
if [[ -n "$TRUSTED_PROXIES" ]]; then
|
||||
log_message "INFO" " Configured trusted proxies: $TRUSTED_PROXIES"
|
||||
else
|
||||
log_message "INFO" " No trusted proxies configured - real client IP detection may be limited"
|
||||
fi
|
||||
}
|
||||
|
||||
reload_nginx() {
|
||||
log_message "INFO" "Testing and reloading NGINX..."
|
||||
|
||||
if ! sudo nginx -t 2>&1 | tee "$INSTANCE_DIR/nginx-test.log"; then
|
||||
fail_with_remediation "NGINX configuration test failed" \
|
||||
"NGINX rejected the configuration. Check the test output above.
|
||||
1. Review the generated config: $NGINX_CONFIG
|
||||
2. Look for port conflicts or syntax errors
|
||||
3. Restore the backup if the default site was disabled
|
||||
4. Manual test: sudo nginx -t"
|
||||
fi
|
||||
|
||||
# Reload according to init system
|
||||
case "${INIT_SYSTEM:-systemd}" in
|
||||
"systemd")
|
||||
sudo systemctl reload nginx 2>/dev/null || sudo systemctl restart nginx
|
||||
;;
|
||||
"openrc")
|
||||
sudo rc-service nginx reload 2>/dev/null || sudo rc-service nginx restart
|
||||
;;
|
||||
"sysvinit")
|
||||
sudo service nginx reload 2>/dev/null || sudo service nginx restart
|
||||
;;
|
||||
*)
|
||||
sudo nginx -s reload 2>/dev/null || true
|
||||
;;
|
||||
esac
|
||||
|
||||
log_message "SUCCESS" "NGINX reloaded with Wallarm configuration"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# DEPLOYMENT VERIFICATION
|
||||
# ==============================================================================
|
||||
|
||||
verify_deployment() {
|
||||
log_message "INFO" "Verifying native Wallarm deployment..."
|
||||
|
||||
# Test ingress port
|
||||
log_message "INFO" "Testing ingress port $INGRESS_PORT..."
|
||||
if ! check_port_available "$INGRESS_PORT"; then
|
||||
log_message "SUCCESS" "Ingress port $INGRESS_PORT is in use (as expected)"
|
||||
else
|
||||
log_message "WARNING" "Ingress port $INGRESS_PORT appears available (NGINX may not be listening)"
|
||||
fi
|
||||
|
||||
# Test health check endpoint
|
||||
log_message "INFO" "Testing health check endpoint..."
|
||||
local health_check_url="http://localhost:$INGRESS_PORT/health"
|
||||
if curl -sf --connect-timeout 5 "$health_check_url" >/dev/null 2>&1; then
|
||||
log_message "SUCCESS" "Health check endpoint responsive"
|
||||
else
|
||||
log_message "WARNING" "Health check endpoint not responsive (may need time to start)"
|
||||
sleep 5
|
||||
if curl -sf --connect-timeout 5 "$health_check_url" >/dev/null 2>&1; then
|
||||
log_message "SUCCESS" "Health check endpoint now responsive"
|
||||
else
|
||||
log_message "WARNING" "Health check endpoint still not responsive (check nginx config)"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Test handshake through filtering node
|
||||
log_message "INFO" "Testing handshake through filtering node to upstream..."
|
||||
local test_url="http://localhost:$INGRESS_PORT/"
|
||||
if curl -sfI --connect-timeout 10 "$test_url" >/dev/null 2>&1; then
|
||||
log_message "SUCCESS" "Handshake successful: filtering node can reach upstream"
|
||||
else
|
||||
log_message "WARNING" "Handshake failed (upstream may not be responding)"
|
||||
log_message "INFO" "Checking if upstream is directly reachable..."
|
||||
if timeout 5 bash -c "cat < /dev/null > /dev/tcp/$UPSTREAM_IP/$UPSTREAM_PORT" 2>/dev/null; then
|
||||
log_message "ERROR" "Upstream is reachable but filtering node cannot proxy"
|
||||
echo -e "${YELLOW}Possible NGINX configuration issue. Check:${NC}"
|
||||
echo -e "1. NGINX error log: sudo tail -50 /var/log/nginx/error.log"
|
||||
echo -e "2. NGINX config: $NGINX_CONFIG"
|
||||
else
|
||||
log_message "WARNING" "Upstream server is not reachable (as previously warned)"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check Wallarm module status endpoint
|
||||
log_message "INFO" "Checking Wallarm module status..."
|
||||
if curl -sf --connect-timeout 5 "http://127.0.0.8/wallarm-status" >/dev/null 2>&1; then
|
||||
log_message "SUCCESS" "Wallarm module is active (wallarm-status responsive)"
|
||||
else
|
||||
log_message "WARNING" "wallarm-status not responsive (module may need more time or a restart)"
|
||||
fi
|
||||
|
||||
# Check node registration file
|
||||
if [ -f "/opt/wallarm/etc/wallarm/node.yaml" ]; then
|
||||
log_message "SUCCESS" "Node is registered (node.yaml present)"
|
||||
else
|
||||
log_message "WARNING" "node.yaml not found - node may not be registered with the cloud"
|
||||
fi
|
||||
|
||||
log_message "SUCCESS" "Deployment verification completed"
|
||||
echo -e "\n${GREEN}${BOLD}Verification Summary:${NC}"
|
||||
echo -e " ${GREEN}✓${NC} NGINX + Wallarm module installed"
|
||||
echo -e " ${GREEN}✓${NC} Ingress port: $INGRESS_PORT"
|
||||
echo -e " ${GREEN}✓${NC} Upstream: $UPSTREAM_IP:$UPSTREAM_PORT"
|
||||
echo -e " ${GREEN}✓${NC} Cloud region: $CLOUD_REGION ($API_HOST)"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# MAIN FUNCTION
|
||||
# ==============================================================================
|
||||
|
||||
main() {
|
||||
clear
|
||||
echo -e "${BLUE}${BOLD}"
|
||||
echo "╔══════════════════════════════════════════════════════════════╗"
|
||||
echo "║ WALLARM DEPLOYMENT SCRIPT (Native) - V1.0 ║"
|
||||
echo "║ Filtering Node Deployment Without Docker ║"
|
||||
echo "╚══════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo -e "\n${YELLOW}Starting deployment at: $(date)${NC}"
|
||||
|
||||
# Initialize logging
|
||||
local log_dir="${HOME:-.}/logs"
|
||||
if [ ! -d "$log_dir" ]; then
|
||||
if ! mkdir -p "$log_dir"; then
|
||||
echo -e "${YELLOW}Cannot create log directory $log_dir, falling back to current directory...${NC}"
|
||||
log_dir="."
|
||||
fi
|
||||
fi
|
||||
|
||||
LOG_FILE="$log_dir/wallarm-deployment-native.log"
|
||||
if ! : > "$LOG_FILE"; then
|
||||
echo -e "${RED}Cannot create log file at $LOG_FILE${NC}"
|
||||
echo -e "${YELLOW}Falling back to current directory...${NC}"
|
||||
LOG_FILE="./wallarm-deployment-native.log"
|
||||
: > "$LOG_FILE" 2>/dev/null || true
|
||||
fi
|
||||
if ! chmod 644 "$LOG_FILE" 2>/dev/null; then
|
||||
echo -e "${YELLOW}Warning: Could not set permissions on log file${NC}"
|
||||
fi
|
||||
|
||||
log_message "INFO" "=== Wallarm Native Deployment Started ==="
|
||||
|
||||
if [ "$INSECURE_SSL" = "1" ]; then
|
||||
log_message "WARNING" "SSL certificate validation is DISABLED (insecure). Set WALLARM_INSECURE_SSL=0 to enable validation."
|
||||
fi
|
||||
|
||||
# Phase 1: Verify preflight check
|
||||
log_message "INFO" "=== PHASE 1: PREFLIGHT CHECK VERIFICATION ==="
|
||||
verify_preflight_check
|
||||
|
||||
# Phase 2: Configuration collection
|
||||
log_message "INFO" "=== PHASE 2: CONFIGURATION COLLECTION ==="
|
||||
select_cloud_region
|
||||
collect_configuration
|
||||
|
||||
# Phase 3: Native installation (all-in-one installer)
|
||||
log_message "INFO" "=== PHASE 3: WALLARM NATIVE INSTALLATION ==="
|
||||
install_wallarm_native
|
||||
|
||||
# Phase 4: NGINX configuration
|
||||
log_message "INFO" "=== PHASE 4: NGINX CONFIGURATION ==="
|
||||
resolve_port_conflict "$INGRESS_PORT"
|
||||
create_nginx_config
|
||||
reload_nginx
|
||||
|
||||
# Phase 5: Verification
|
||||
log_message "INFO" "=== PHASE 5: VERIFICATION ==="
|
||||
verify_deployment
|
||||
|
||||
# Success message
|
||||
log_message "SUCCESS" "=== WALLARM NATIVE DEPLOYMENT COMPLETED SUCCESSFULLY ==="
|
||||
echo -e "\n${GREEN}${BOLD}╔══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${GREEN}${BOLD}║ WALLARM FILTERING NODE DEPLOYMENT SUCCESSFUL ║${NC}"
|
||||
echo -e "${GREEN}${BOLD}╚══════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo -e "\n${CYAN}The Wallarm filtering node is now active and protecting your application.${NC}"
|
||||
echo -e "${YELLOW}Full deployment log: $LOG_FILE${NC}"
|
||||
echo -e "${YELLOW}Instance directory: $INSTANCE_DIR${NC}"
|
||||
echo -e "\n${GREEN}To stop the node:${NC} sudo systemctl stop nginx"
|
||||
echo -e "${GREEN}To restart:${NC} sudo systemctl restart nginx"
|
||||
echo -e "${GREEN}To view logs:${NC} sudo tail -f /var/log/nginx/error.log"
|
||||
echo -e "${GREEN}Node status:${NC} curl http://127.0.0.8/wallarm-status"
|
||||
echo -e "\n${MAGENTA}${BOLD}Deployment completed successfully!${NC}"
|
||||
echo -e "\n${YELLOW}Important next steps:${NC}"
|
||||
echo -e "1. Monitor sync status in Wallarm Console"
|
||||
echo -e "2. Test attack detection with safe test: curl http://localhost:$INGRESS_PORT/?wallarm_test=1"
|
||||
echo -e "3. Review logs periodically: sudo tail -50 /var/log/nginx/error.log"
|
||||
echo -e "4. Switch to block mode after validation: sudo ./native/wallarm-ct-reconfigure.sh"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# SCRIPT EXECUTION
|
||||
# ==============================================================================
|
||||
|
||||
# Ensure we're in bash
|
||||
if [ -z "$BASH_VERSION" ]; then
|
||||
echo "Error: This script must be run with bash" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Run main function
|
||||
main "$@"
|
||||
227
native/wallarm-ct-reconfigure.sh
Executable file
227
native/wallarm-ct-reconfigure.sh
Executable file
|
|
@ -0,0 +1,227 @@
|
|||
#!/bin/bash
|
||||
# ==============================================================================
|
||||
# WALLARM RECONFIGURATION SCRIPT - V1.0 (Native deployment)
|
||||
# ==============================================================================
|
||||
# Purpose: Modify NGINX configuration of an existing native Wallarm node
|
||||
# Features:
|
||||
# - Update set_real_ip_from (trusted proxy IPs/CIDRs)
|
||||
# - Change wallarm_mode (monitoring/block)
|
||||
# - Backup current config before changes
|
||||
# - NGINX test + reload instead of container restart
|
||||
# - Interactive prompts with validation
|
||||
# ==============================================================================
|
||||
|
||||
# Script location and shared library (colors, logging, validation)
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=../common/wallarm-lib.sh
|
||||
source "$SCRIPT_DIR/../common/wallarm-lib.sh"
|
||||
|
||||
set -euo pipefail
|
||||
trap early_error_handler ERR
|
||||
|
||||
# ==============================================================================
|
||||
# CHECK FOR SUDO / ROOT PRIVILEGES
|
||||
# ==============================================================================
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo -e "${RED}${BOLD}ERROR:${NC} This script must be run with sudo or as root."
|
||||
echo -e "${YELLOW}Please run: sudo $0${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ==============================================================================
|
||||
# CONFIGURATION
|
||||
# ==============================================================================
|
||||
CONFIG_GLOB="/etc/nginx/conf.d/wallarm-*.conf"
|
||||
CONFIG_FILE=""
|
||||
INSTANCE_NAME=""
|
||||
|
||||
# ==============================================================================
|
||||
# FUNCTIONS
|
||||
# ==============================================================================
|
||||
|
||||
# Find the Wallarm NGINX config file(s)
|
||||
find_wallarm_config() {
|
||||
local configs=()
|
||||
while IFS= read -r file; do
|
||||
configs+=("$file")
|
||||
done < <(ls $CONFIG_GLOB 2>/dev/null)
|
||||
|
||||
if [ ${#configs[@]} -eq 0 ]; then
|
||||
echo -e "${RED}No Wallarm NGINX configuration found ($CONFIG_GLOB).${NC}"
|
||||
echo -e "${YELLOW}Has the native deployment been run? Check /etc/nginx/conf.d/wallarm-*.conf${NC}"
|
||||
exit 1
|
||||
elif [ ${#configs[@]} -eq 1 ]; then
|
||||
CONFIG_FILE="${configs[0]}"
|
||||
INSTANCE_NAME=$(basename "$CONFIG_FILE" | sed 's/^wallarm-//; s/\.conf$//')
|
||||
echo -e "${GREEN}Found Wallarm config: $CONFIG_FILE${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}Multiple Wallarm NGINX configs found:${NC}"
|
||||
for i in "${!configs[@]}"; do
|
||||
echo "$((i+1)). ${configs[$i]}"
|
||||
done
|
||||
read -r -p "Select config number: " choice
|
||||
if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le ${#configs[@]} ]; then
|
||||
CONFIG_FILE="${configs[$((choice-1))]}"
|
||||
INSTANCE_NAME=$(basename "$CONFIG_FILE" | sed 's/^wallarm-//; s/\.conf$//')
|
||||
else
|
||||
echo -e "${RED}Invalid selection.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Parse current configuration to get existing values
|
||||
parse_current_config() {
|
||||
local config_file="$1"
|
||||
current_mode=$(grep -oP 'wallarm_mode\s+\K\S+' "$config_file" | head -1)
|
||||
current_proxies=$(grep -oP 'set_real_ip_from\s+\K\S+' "$config_file")
|
||||
}
|
||||
|
||||
# Update configuration
|
||||
update_config() {
|
||||
local config_file="$1"
|
||||
local backup_file="$config_file.backup.$(date +%Y%m%d_%H%M%S)"
|
||||
|
||||
echo -e "${YELLOW}Backing up current config to $backup_file${NC}"
|
||||
cp "$config_file" "$backup_file"
|
||||
|
||||
echo -e "\n${CYAN}${BOLD}Current set_real_ip_from entries:${NC}"
|
||||
if [ -n "$current_proxies" ]; then
|
||||
while read -r proxy; do
|
||||
echo " $proxy"
|
||||
done <<< "$current_proxies"
|
||||
else
|
||||
echo " (none)"
|
||||
fi
|
||||
|
||||
echo -e "\n${YELLOW}Do you want to change the trusted proxy IPs/CIDRs? (y/N)${NC}"
|
||||
read -r change_proxy
|
||||
new_proxies=()
|
||||
if [[ "$change_proxy" =~ ^[Yy]$ ]]; then
|
||||
echo -e "${YELLOW}Enter new trusted proxy IPs/CIDRs (space-separated, or empty to remove all):${NC}"
|
||||
read -r new_proxies_input
|
||||
if [[ -n "$new_proxies_input" ]]; then
|
||||
IFS=' ' read -ra proxy_array <<< "$new_proxies_input"
|
||||
for proxy in "${proxy_array[@]}"; do
|
||||
proxy=$(echo "$proxy" | xargs)
|
||||
if validate_ip_or_cidr "$proxy"; then
|
||||
new_proxies+=("$proxy")
|
||||
else
|
||||
echo -e "${RED}Invalid format: $proxy. Skipping.${NC}"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
else
|
||||
# Keep existing
|
||||
while read -r proxy; do
|
||||
new_proxies+=("$proxy")
|
||||
done <<< "$current_proxies"
|
||||
fi
|
||||
|
||||
echo -e "\n${CYAN}${BOLD}Current wallarm_mode:${NC} ${current_mode:-not set}"
|
||||
echo -e "${YELLOW}Do you want to change the wallarm_mode? (y/N)${NC}"
|
||||
read -r change_mode
|
||||
if [[ "$change_mode" =~ ^[Yy]$ ]]; then
|
||||
echo -e "${YELLOW}Select new mode:${NC}"
|
||||
echo "1. monitoring"
|
||||
echo "2. block"
|
||||
read -r mode_choice
|
||||
case "$mode_choice" in
|
||||
1) new_mode="monitoring" ;;
|
||||
2) new_mode="block" ;;
|
||||
*) echo -e "${RED}Invalid choice, keeping current mode.${NC}"; new_mode="$current_mode" ;;
|
||||
esac
|
||||
else
|
||||
new_mode="$current_mode"
|
||||
fi
|
||||
|
||||
# Rebuild the config file
|
||||
temp_config=$(mktemp)
|
||||
|
||||
in_server_block=false
|
||||
while IFS= read -r line; do
|
||||
if [[ "$line" =~ ^[[:space:]]*server[[:space:]]*{ ]]; then
|
||||
in_server_block=true
|
||||
fi
|
||||
|
||||
if $in_server_block; then
|
||||
if [[ "$line" =~ ^[[:space:]]*set_real_ip_from[[:space:]]+ ]]; then
|
||||
continue
|
||||
fi
|
||||
if [[ "$line" =~ ^[[:space:]]*wallarm_mode[[:space:]]+ ]]; then
|
||||
continue
|
||||
fi
|
||||
if [[ "$line" =~ ^[[:space:]]*real_ip_header[[:space:]]+ ]]; then
|
||||
continue
|
||||
fi
|
||||
if [[ "$line" =~ ^[[:space:]]*real_ip_recursive[[:space:]]+ ]]; then
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "$line" >> "$temp_config"
|
||||
|
||||
if $in_server_block && [[ "$line" =~ ^[[:space:]]*}$ ]]; then
|
||||
in_server_block=false
|
||||
if [ ${#new_proxies[@]} -gt 0 ]; then
|
||||
for proxy in "${new_proxies[@]}"; do
|
||||
echo " set_real_ip_from $proxy;" >> "$temp_config"
|
||||
done
|
||||
echo " real_ip_header X-Real-IP;" >> "$temp_config"
|
||||
echo " real_ip_recursive on;" >> "$temp_config"
|
||||
fi
|
||||
if [ -n "$new_mode" ]; then
|
||||
echo " wallarm_mode $new_mode;" >> "$temp_config"
|
||||
fi
|
||||
fi
|
||||
done < "$config_file"
|
||||
|
||||
mv "$temp_config" "$config_file"
|
||||
chmod 644 "$config_file"
|
||||
|
||||
echo -e "${GREEN}Configuration updated.${NC}"
|
||||
}
|
||||
|
||||
reload_nginx() {
|
||||
echo -e "${YELLOW}Testing NGINX configuration...${NC}"
|
||||
if ! sudo nginx -t; then
|
||||
echo -e "${RED}NGINX configuration test failed. Restoring backup...${NC}"
|
||||
cp "$CONFIG_FILE.backup."*. "$CONFIG_FILE" 2>/dev/null || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${YELLOW}Reloading NGINX to apply changes...${NC}"
|
||||
sudo systemctl reload nginx 2>/dev/null || sudo nginx -s reload 2>/dev/null || {
|
||||
sudo systemctl restart nginx 2>/dev/null || {
|
||||
echo -e "${RED}Could not reload NGINX. Please do it manually: sudo systemctl reload nginx${NC}"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
echo -e "${GREEN}NGINX reloaded.${NC}"
|
||||
}
|
||||
|
||||
main() {
|
||||
echo -e "${BLUE}${BOLD}"
|
||||
echo "╔══════════════════════════════════════════════════════════════╗"
|
||||
echo "║ WALLARM RECONFIGURATION SCRIPT (Native) - V1.0 ║"
|
||||
echo "║ Modify NGINX config (trusted proxies / mode) ║"
|
||||
echo "╚══════════════════════════════════════════════════════════════╝${NC}"
|
||||
|
||||
find_wallarm_config
|
||||
|
||||
parse_current_config "$CONFIG_FILE"
|
||||
update_config "$CONFIG_FILE"
|
||||
|
||||
echo -e "${YELLOW}Do you want to reload NGINX now? (Y/n)${NC}"
|
||||
read -r reload_choice
|
||||
if [[ ! "$reload_choice" =~ ^[Nn]$ ]]; then
|
||||
reload_nginx
|
||||
else
|
||||
echo -e "${YELLOW}Changes will take effect after NGINX reload.${NC}"
|
||||
echo -e "You can reload later with: sudo systemctl reload nginx"
|
||||
fi
|
||||
|
||||
echo -e "\n${GREEN}${BOLD}Reconfiguration completed.${NC}"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
299
native/wallarm-ct-uninstall.sh
Executable file
299
native/wallarm-ct-uninstall.sh
Executable file
|
|
@ -0,0 +1,299 @@
|
|||
#!/bin/bash
|
||||
# ==============================================================================
|
||||
# WALLARM UNINSTALL SCRIPT - V1.0 (Native deployment)
|
||||
# ==============================================================================
|
||||
# Purpose: Safely remove a native (no-Docker) Wallarm filtering node
|
||||
# Features:
|
||||
# - Interactive confirmation with safety checks
|
||||
# - Removes Wallarm NGINX configuration (with backup)
|
||||
# - Restores disabled default NGINX sites
|
||||
# - Uninstalls Wallarm packages and repository definitions
|
||||
# - Removes /opt/wallarm node data
|
||||
# - Preserves user data and logs (with option to remove)
|
||||
# - DAU-friendly warnings and confirmations
|
||||
# ==============================================================================
|
||||
|
||||
# Script location and shared library (colors, logging, validation)
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=../common/wallarm-lib.sh
|
||||
source "$SCRIPT_DIR/../common/wallarm-lib.sh"
|
||||
|
||||
# Strict error handling
|
||||
set -euo pipefail
|
||||
trap early_error_handler ERR
|
||||
|
||||
# ==============================================================================
|
||||
# CONFIGURATION
|
||||
# ==============================================================================
|
||||
CONFIG_GLOB="/etc/nginx/conf.d/wallarm-*.conf"
|
||||
DEFAULT_BACKUP_GLOB="/etc/nginx/sites-enabled/*.bak"
|
||||
WALLARM_NODE_DIR="/opt/wallarm"
|
||||
|
||||
# ==============================================================================
|
||||
# FUNCTIONS
|
||||
# ==============================================================================
|
||||
|
||||
# Ask for confirmation
|
||||
confirm() {
|
||||
local prompt="$1"
|
||||
local default="${2:-n}"
|
||||
local options="[y/N]"
|
||||
|
||||
if [ "$default" = "y" ]; then
|
||||
options="[Y/n]"
|
||||
fi
|
||||
|
||||
echo -e -n "${YELLOW}${prompt} ${options}${NC} "
|
||||
read -r response
|
||||
|
||||
case "$response" in
|
||||
[yY][eE][sS]|[yY]) return 0 ;;
|
||||
[nN][oO]|[nN]) return 1 ;;
|
||||
"")
|
||||
if [ "$default" = "y" ]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Detect the package manager in use
|
||||
detect_package_manager() {
|
||||
if command -v apt-get >/dev/null 2>&1; then
|
||||
echo "apt"
|
||||
elif command -v yum >/dev/null 2>&1; then
|
||||
echo "yum"
|
||||
elif command -v dnf >/dev/null 2>&1; then
|
||||
echo "dnf"
|
||||
elif command -v apk >/dev/null 2>&1; then
|
||||
echo "apk"
|
||||
else
|
||||
echo "unknown"
|
||||
fi
|
||||
}
|
||||
|
||||
# Remove Wallarm NGINX configuration files
|
||||
remove_nginx_configs() {
|
||||
log_message "INFO" "Looking for Wallarm NGINX configurations..."
|
||||
|
||||
local configs=()
|
||||
while IFS= read -r file; do
|
||||
configs+=("$file")
|
||||
done < <(ls $CONFIG_GLOB 2>/dev/null)
|
||||
|
||||
if [ ${#configs[@]} -eq 0 ]; then
|
||||
log_message "INFO" "No Wallarm NGINX configurations found"
|
||||
return
|
||||
fi
|
||||
|
||||
log_message "INFO" "Found ${#configs[@]} Wallarm NGINX configuration(s)"
|
||||
for file in "${configs[@]}"; do
|
||||
if confirm "Remove $file? (backup created)" "y"; then
|
||||
cp "$file" "$file.uninstall-$(date +%Y%m%d_%H%M%S).bak"
|
||||
rm -f "$file"
|
||||
log_message "SUCCESS" "Removed $file (backup created)"
|
||||
else
|
||||
log_message "INFO" "Skipping $file"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Restore any default NGINX sites we disabled during deployment
|
||||
restore_default_sites() {
|
||||
log_message "INFO" "Looking for disabled default NGINX sites..."
|
||||
|
||||
local restored=0
|
||||
while IFS= read -r backup; do
|
||||
if [ -f "$backup" ]; then
|
||||
local target="${backup%.bak}"
|
||||
log_message "INFO" "Restoring $target from $backup"
|
||||
if confirm "Restore $target?" "y"; then
|
||||
cp "$backup" "$target"
|
||||
rm -f "$backup"
|
||||
restored=$((restored + 1))
|
||||
fi
|
||||
fi
|
||||
done < <(ls $DEFAULT_BACKUP_GLOB 2>/dev/null)
|
||||
|
||||
if [ "$restored" -gt 0 ]; then
|
||||
log_message "SUCCESS" "Restored $restored default site(s)"
|
||||
else
|
||||
log_message "INFO" "No disabled default sites found"
|
||||
fi
|
||||
}
|
||||
|
||||
# Reload NGINX to drop the removed configurations
|
||||
reload_nginx() {
|
||||
log_message "INFO" "Testing and reloading NGINX..."
|
||||
|
||||
if sudo nginx -t 2>/dev/null; then
|
||||
sudo systemctl reload nginx 2>/dev/null || sudo nginx -s reload 2>/dev/null || true
|
||||
log_message "SUCCESS" "NGINX reloaded"
|
||||
else
|
||||
log_message "WARNING" "NGINX configuration test failed - reload skipped"
|
||||
echo -e "${YELLOW}Run 'sudo nginx -t' manually to diagnose the issue.${NC}"
|
||||
fi
|
||||
}
|
||||
|
||||
# Uninstall Wallarm packages via the system package manager
|
||||
remove_wallarm_packages() {
|
||||
local pkg_manager
|
||||
pkg_manager=$(detect_package_manager)
|
||||
|
||||
log_message "INFO" "Detected package manager: $pkg_manager"
|
||||
|
||||
if ! confirm "Uninstall Wallarm packages? (wallarm-node, wallarm modules)" "y"; then
|
||||
log_message "INFO" "Skipping Wallarm package removal"
|
||||
return
|
||||
fi
|
||||
|
||||
case "$pkg_manager" in
|
||||
"apt")
|
||||
log_message "INFO" "Removing Wallarm packages (apt)..."
|
||||
sudo apt-get purge -y "wallarm-node" "wallarm-node-nginx" "nginx-module-wallarm*" 2>/dev/null || true
|
||||
sudo apt-get autoremove -y 2>/dev/null || true
|
||||
;;
|
||||
"yum")
|
||||
log_message "INFO" "Removing Wallarm packages (yum)..."
|
||||
sudo yum remove -y "wallarm-node" "nginx-module-wallarm*" 2>/dev/null || true
|
||||
;;
|
||||
"dnf")
|
||||
log_message "INFO" "Removing Wallarm packages (dnf)..."
|
||||
sudo dnf remove -y "wallarm-node" "nginx-module-wallarm*" 2>/dev/null || true
|
||||
;;
|
||||
"apk")
|
||||
log_message "INFO" "Removing Wallarm packages (apk)..."
|
||||
sudo apk del "wallarm-node" "nginx-module-wallarm" 2>/dev/null || true
|
||||
;;
|
||||
*)
|
||||
log_message "WARNING" "Unknown package manager. Please remove Wallarm packages manually."
|
||||
echo -e "${YELLOW}Relevant packages usually include: wallarm-node, nginx-module-wallarm${NC}"
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
||||
log_message "SUCCESS" "Wallarm packages removed"
|
||||
}
|
||||
|
||||
# Remove Wallarm repository definitions added by the installer
|
||||
remove_wallarm_repos() {
|
||||
log_message "INFO" "Removing Wallarm repository definitions..."
|
||||
|
||||
local removed=0
|
||||
while IFS= read -r file; do
|
||||
if [ -f "$file" ]; then
|
||||
sudo rm -f "$file"
|
||||
log_message "SUCCESS" "Removed repo file: $file"
|
||||
removed=$((removed + 1))
|
||||
fi
|
||||
done < <(ls /etc/apt/sources.list.d/*wallarm* /etc/yum.repos.d/*wallarm* 2>/dev/null)
|
||||
|
||||
if [ "$removed" -eq 0 ]; then
|
||||
log_message "INFO" "No Wallarm repository files found"
|
||||
fi
|
||||
}
|
||||
|
||||
# Remove Wallarm node data directory
|
||||
remove_wallarm_data() {
|
||||
if [ -d "$WALLARM_NODE_DIR" ]; then
|
||||
log_message "WARNING" "Found Wallarm data directory: $WALLARM_NODE_DIR"
|
||||
log_message "WARNING" "This contains node registration and local data."
|
||||
if confirm "Remove $WALLARM_NODE_DIR? (node will need re-registration)" "n"; then
|
||||
sudo rm -rf "$WALLARM_NODE_DIR"
|
||||
log_message "SUCCESS" "Removed $WALLARM_NODE_DIR"
|
||||
else
|
||||
log_message "INFO" "Skipping removal of $WALLARM_NODE_DIR"
|
||||
fi
|
||||
else
|
||||
log_message "INFO" "No Wallarm data directory found"
|
||||
fi
|
||||
}
|
||||
|
||||
# Remove Wallarm log files (optional)
|
||||
remove_wallarm_logs() {
|
||||
local log_dir="$HOME/logs"
|
||||
if [ -d "$log_dir" ]; then
|
||||
log_message "INFO" "Found log directory: $log_dir"
|
||||
if [ -z "$(ls -A "$log_dir" 2>/dev/null)" ]; then
|
||||
log_message "INFO" "Log directory is empty, removing..."
|
||||
sudo rmdir "$log_dir" 2>/dev/null || true
|
||||
else
|
||||
log_message "INFO" "Log directory contains files, preserving..."
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -f ".env" ]; then
|
||||
if confirm "Remove .env preflight file?" "n"; then
|
||||
rm -f ".env"
|
||||
log_message "SUCCESS" "Removed .env file"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# MAIN
|
||||
# ==============================================================================
|
||||
|
||||
main() {
|
||||
echo -e "${CYAN}${BOLD}"
|
||||
echo "╔══════════════════════════════════════════════════════════════╗"
|
||||
echo "║ WALLARM UNINSTALLATION (Native) ║"
|
||||
echo "╚══════════════════════════════════════════════════════════════╝"
|
||||
echo -e "${NC}"
|
||||
|
||||
echo -e "${YELLOW}This script will remove the native Wallarm filtering node.${NC}"
|
||||
echo -e "${YELLOW}You will be asked for confirmation before each destructive operation.${NC}"
|
||||
echo ""
|
||||
|
||||
if ! confirm "Do you want to continue with the uninstallation?" "n"; then
|
||||
log_message "INFO" "Uninstallation cancelled by user"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Step 1: Remove Wallarm NGINX configurations
|
||||
echo ""
|
||||
echo -e "${CYAN}${BOLD}Step 1: Remove Wallarm NGINX configurations${NC}"
|
||||
remove_nginx_configs
|
||||
restore_default_sites
|
||||
reload_nginx
|
||||
|
||||
# Step 2: Uninstall Wallarm packages
|
||||
echo ""
|
||||
echo -e "${CYAN}${BOLD}Step 2: Uninstall Wallarm packages${NC}"
|
||||
remove_wallarm_packages
|
||||
remove_wallarm_repos
|
||||
|
||||
# Step 3: Remove Wallarm data
|
||||
echo ""
|
||||
echo -e "${CYAN}${BOLD}Step 3: Remove Wallarm data${NC}"
|
||||
remove_wallarm_data
|
||||
|
||||
# Step 4: Cleanup
|
||||
echo ""
|
||||
echo -e "${CYAN}${BOLD}Step 4: Logs and files cleanup${NC}"
|
||||
if confirm "Remove Wallarm log files and .env?" "n"; then
|
||||
remove_wallarm_logs
|
||||
else
|
||||
log_message "INFO" "Skipping log/file cleanup"
|
||||
fi
|
||||
|
||||
# Final message
|
||||
echo ""
|
||||
echo -e "${GREEN}${BOLD}╔══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${GREEN}${BOLD}║ UNINSTALLATION COMPLETE ║${NC}"
|
||||
echo -e "${GREEN}${BOLD}╚══════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
echo -e "${GREEN}The native Wallarm filtering node has been removed.${NC}"
|
||||
echo ""
|
||||
echo -e "${YELLOW}Note:${NC}"
|
||||
echo -e " • NGINX itself was kept installed (may be used by other applications)"
|
||||
echo -e " • The Wallarm module may remain in NGINX's modules directory"
|
||||
echo -e " • Wallarm repositories were removed from your package sources"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Run main function
|
||||
main "$@"
|
||||
483
native/wallarm-native.sh
Executable file
483
native/wallarm-native.sh
Executable file
|
|
@ -0,0 +1,483 @@
|
|||
#!/bin/bash
|
||||
# ==============================================================================
|
||||
# Wallarm Native Node Manager - Install, Configure, Remove, and Control
|
||||
# ==============================================================================
|
||||
# Unified single-script manager for the Wallarm Native Node (connector mode,
|
||||
# NO Docker). Manages multiple isolated nodes under ${BASE_DIR}/nodes with a
|
||||
# systemd template unit (wallarm-node@<name>.service).
|
||||
#
|
||||
# NOTE: This targets the Wallarm Native Node product (go-node, connector-server
|
||||
# mode, all-in-one installer) - distinct from the NGINX-module based native
|
||||
# deployment in ./wallarm-ct-deploy.sh.
|
||||
#
|
||||
# Commands:
|
||||
# --preflight Run preflight checks only (no installation).
|
||||
# --install Interactive installation of one or more nodes (parallel).
|
||||
# --config Update an existing node's configuration.
|
||||
# Options: --node NAME --address IP:PORT [--token TOKEN] [--labels LABELS]
|
||||
# --remove Remove a node completely.
|
||||
# Options: --node NAME
|
||||
# --status [NODE] Show systemd status for a node, or all nodes.
|
||||
# --help|-h Show help.
|
||||
# ==============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Script location and shared library (logging, detection, connectivity, validation)
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=../common/wallarm-lib.sh
|
||||
source "$SCRIPT_DIR/../common/wallarm-lib.sh"
|
||||
|
||||
# --- Constants ---
|
||||
BASE_DIR="/opt/wallarm"
|
||||
NODES_DIR="${BASE_DIR}/nodes"
|
||||
SYSTEMD_TEMPLATE="/etc/systemd/system/wallarm-node@.service"
|
||||
|
||||
# Wallarm Native Node all-in-one installer (latest, x86_64 by default)
|
||||
# Override WALLARM_INSTALLER_URL to pin a version; WALLARM_INSTALLER_ARCH to
|
||||
# select the architecture suffix.
|
||||
INSTALLER_BASE_URL="https://repo.wallarm.com/linux/wallarm-native-node/latest/all-in-one"
|
||||
INSTALLER_ARCH="${WALLARM_INSTALLER_ARCH:-x86_64}"
|
||||
INSTALLER_URL="${WALLARM_INSTALLER_URL:-${INSTALLER_BASE_URL}/wallarm-native-node-aio-${INSTALLER_ARCH}-latest.sh}"
|
||||
|
||||
# Wallarm cloud endpoints (for connectivity checks)
|
||||
EU_DATA_NODES=("api.wallarm.com" "node-data0.eu1.wallarm.com" "node-data1.eu1.wallarm.com")
|
||||
US_DATA_NODES=("us1.api.wallarm.com" "node-data0.us1.wallarm.com" "node-data1.us1.wallarm.com")
|
||||
|
||||
# --- Helper functions ---
|
||||
log() { echo ">>> $*"; }
|
||||
err() { echo "!!! $*" >&2; }
|
||||
|
||||
check_root() {
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
err "This script must be run as root (for systemd and /opt write access)."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_dirs() {
|
||||
mkdir -p "${NODES_DIR}"
|
||||
}
|
||||
|
||||
generate_systemd_template() {
|
||||
if [[ ! -f "${SYSTEMD_TEMPLATE}" ]]; then
|
||||
log "Creating systemd template: ${SYSTEMD_TEMPLATE}"
|
||||
cat > "${SYSTEMD_TEMPLATE}" <<EOF
|
||||
[Unit]
|
||||
Description=Wallarm Native Node - %I
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
WorkingDirectory=${NODES_DIR}/%i
|
||||
EnvironmentFile=${NODES_DIR}/%i/env
|
||||
ExecStart=${NODES_DIR}/%i/wallarm-native-node-aio.sh start
|
||||
ExecStop=${NODES_DIR}/%i/wallarm-native-node-aio.sh stop
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
User=root
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl daemon-reload
|
||||
fi
|
||||
}
|
||||
|
||||
write_env_file() {
|
||||
local node_name="$1"
|
||||
local api_token="$2"
|
||||
local labels="$3"
|
||||
local config_path="${NODES_DIR}/${node_name}/etc/go-node.yaml"
|
||||
local env_file="${NODES_DIR}/${node_name}/env"
|
||||
|
||||
cat > "${env_file}" <<EOF
|
||||
WALLARM_API_TOKEN=${api_token}
|
||||
WALLARM_LABELS=${labels}
|
||||
WALLARM_CONFIG_PATH=${config_path}
|
||||
EOF
|
||||
chmod 600 "${env_file}" # token is sensitive
|
||||
}
|
||||
|
||||
# --- Preflight checks ---
|
||||
run_preflight() {
|
||||
local failed=0
|
||||
|
||||
log "Running preflight checks..."
|
||||
|
||||
# 1. Root privileges
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
err "Preflight failed: must be run as root."
|
||||
failed=1
|
||||
fi
|
||||
|
||||
# 2. Init system must be systemd (template unit management)
|
||||
local init_system
|
||||
init_system=$(detect_init_system)
|
||||
if [[ "$init_system" != "systemd" ]]; then
|
||||
err "Preflight failed: this manager requires systemd (detected: $init_system)."
|
||||
failed=1
|
||||
fi
|
||||
|
||||
# 3. Architecture
|
||||
local arch
|
||||
arch=$(detect_architecture)
|
||||
if [[ "$arch" != "x86_64" && "$arch" != "aarch64" ]]; then
|
||||
err "Preflight failed: unsupported architecture '$arch' for the native node installer."
|
||||
failed=1
|
||||
fi
|
||||
log "Architecture: ${arch} (installer suffix: ${INSTALLER_ARCH})"
|
||||
|
||||
# 4. Required commands
|
||||
local required_cmds=(curl systemctl sed mkdir rm sleep)
|
||||
local missing=()
|
||||
local cmd
|
||||
for cmd in "${required_cmds[@]}"; do
|
||||
if ! command_exists "$cmd"; then
|
||||
missing+=("$cmd")
|
||||
fi
|
||||
done
|
||||
if [[ ${#missing[@]} -gt 0 ]]; then
|
||||
err "Preflight failed: missing required commands: ${missing[*]}"
|
||||
failed=1
|
||||
fi
|
||||
|
||||
# 5. Installer reachability
|
||||
if ! test_connectivity "$INSTALLER_URL" "Wallarm native node installer"; then
|
||||
err "Preflight failed: installer not reachable: $INSTALLER_URL"
|
||||
failed=1
|
||||
fi
|
||||
|
||||
# 6. Wallarm cloud reachability (must have at least one reachable region)
|
||||
local us eu
|
||||
us=$(test_cloud_endpoints "US" "${US_DATA_NODES[@]}")
|
||||
eu=$(test_cloud_endpoints "EU" "${EU_DATA_NODES[@]}")
|
||||
if [[ "$us" != "true" && "$eu" != "true" ]]; then
|
||||
err "Preflight failed: no Wallarm cloud region reachable (US/EU)."
|
||||
failed=1
|
||||
fi
|
||||
|
||||
# 7. Disk space (>= 2GB free on the nodes volume)
|
||||
local avail_kb
|
||||
avail_kb=$(df -k "$BASE_DIR" 2>/dev/null | awk 'NR==2 {print $4}' || true)
|
||||
if [[ -n "$avail_kb" ]] && (( avail_kb < 2097152 )); then
|
||||
err "Preflight failed: insufficient disk space on $BASE_DIR (need >= 2GB free)."
|
||||
failed=1
|
||||
fi
|
||||
|
||||
# 8. Memory (>= 2GB recommended; warning only)
|
||||
if command_exists free; then
|
||||
local mem_mb
|
||||
mem_mb=$(free -m 2>/dev/null | awk '/Mem:/ {print $2}')
|
||||
if [[ -n "$mem_mb" ]] && (( mem_mb < 2048 )); then
|
||||
err "Warning: only ${mem_mb}MB RAM detected (2GB+ recommended)."
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $failed -ne 0 ]]; then
|
||||
err "Preflight check FAILED. Resolve the issues above and re-run."
|
||||
return 1
|
||||
fi
|
||||
|
||||
log "Preflight checks passed."
|
||||
return 0
|
||||
}
|
||||
|
||||
# Validate a listen address (IP:PORT) and check its port is free
|
||||
check_listen_port() {
|
||||
local address="$1"
|
||||
local port="${address##*:}"
|
||||
if [[ ! "$port" =~ ^[0-9]+$ ]] || (( port < 1 || port > 65535 )); then
|
||||
err "Invalid listen address (expected IP:PORT): $address"
|
||||
return 1
|
||||
fi
|
||||
if ! check_port_available "$port"; then
|
||||
err "Listen port $port (for $address) is already in use."
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# --- Core actions ---
|
||||
install_single_node() {
|
||||
local node_name="$1"
|
||||
local listen_address="$2"
|
||||
local api_token="$3"
|
||||
local labels="${4:-group=${node_name}}"
|
||||
|
||||
local work_dir="${NODES_DIR}/${node_name}"
|
||||
local installer_path="${work_dir}/wallarm-native-node-aio.sh"
|
||||
|
||||
log "[${node_name}] Installing (listening on ${listen_address})..."
|
||||
|
||||
mkdir -p "${work_dir}/etc" "${work_dir}/var/log" "${work_dir}/var/run"
|
||||
|
||||
# 1. Write config
|
||||
cat > "${work_dir}/etc/go-node.yaml" <<EOF
|
||||
mode: connector-server
|
||||
connector:
|
||||
address: "${listen_address}"
|
||||
EOF
|
||||
|
||||
# 2. Download installer if missing
|
||||
if [[ ! -f "${installer_path}" ]]; then
|
||||
log "[${node_name}] Downloading installer..."
|
||||
curl -fsSL -o "${installer_path}" "${INSTALLER_URL}" || {
|
||||
err "[${node_name}] Download failed"
|
||||
return 1
|
||||
}
|
||||
chmod +x "${installer_path}"
|
||||
fi
|
||||
|
||||
# 3. Write environment file (used by systemd and manual scripts)
|
||||
write_env_file "${node_name}" "${api_token}" "${labels}"
|
||||
|
||||
# 4. Run installer
|
||||
cd "${work_dir}" || return 1
|
||||
if WALLARM_API_TOKEN="${api_token}" \
|
||||
WALLARM_LABELS="${labels}" \
|
||||
WALLARM_CONFIG_PATH="${work_dir}/etc/go-node.yaml" \
|
||||
./wallarm-native-node-aio.sh install \
|
||||
-- --config-dir "${work_dir}/etc" \
|
||||
-- --log-dir "${work_dir}/var/log" \
|
||||
-- --pid-dir "${work_dir}/var/run" \
|
||||
> "${work_dir}/install.log" 2>&1; then
|
||||
log "[${node_name}] Installation successful."
|
||||
# Enable and start the systemd service
|
||||
systemctl enable "wallarm-node@${node_name}" 2>/dev/null || true
|
||||
systemctl start "wallarm-node@${node_name}"
|
||||
log "[${node_name}] Service started (systemctl status wallarm-node@${node_name})"
|
||||
else
|
||||
err "[${node_name}] Installation failed. Check ${work_dir}/install.log"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
cmd_preflight() {
|
||||
check_root
|
||||
echo ""
|
||||
if run_preflight; then
|
||||
log "Preflight passed - system ready for --install."
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
cmd_install() {
|
||||
check_root
|
||||
if ! run_preflight; then
|
||||
exit 1
|
||||
fi
|
||||
ensure_dirs
|
||||
generate_systemd_template
|
||||
|
||||
read -p "Enter Wallarm API Token (with Deploy role): " WALLARM_API_TOKEN
|
||||
if [[ -z "$WALLARM_API_TOKEN" ]]; then
|
||||
err "API Token cannot be empty."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Enter each node's name and listening address (format: name IP:Port)"
|
||||
echo "Example: node1 0.0.0.0:8081"
|
||||
echo "Leave name blank to finish."
|
||||
|
||||
declare -a NODE_NAMES
|
||||
declare -a NODE_ADDRESSES
|
||||
|
||||
while true; do
|
||||
read -p "Node name (blank to stop): " name
|
||||
[[ -z "$name" ]] && break
|
||||
read -p "Listening address (e.g., 0.0.0.0:8081): " address
|
||||
if [[ -z "$address" ]]; then
|
||||
err "Address cannot be empty, skipping."
|
||||
continue
|
||||
fi
|
||||
NODE_NAMES+=("$name")
|
||||
NODE_ADDRESSES+=("$address")
|
||||
done
|
||||
|
||||
if [[ ${#NODE_NAMES[@]} -eq 0 ]]; then
|
||||
err "No nodes provided."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Validate listen ports before installing anything
|
||||
local address
|
||||
for address in "${NODE_ADDRESSES[@]}"; do
|
||||
if ! check_listen_port "$address"; then
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Will install ${#NODE_NAMES[@]} nodes in parallel:"
|
||||
for i in "${!NODE_NAMES[@]}"; do
|
||||
echo " - ${NODE_NAMES[$i]} -> ${NODE_ADDRESSES[$i]}"
|
||||
done
|
||||
read -p "Proceed? (y/N): " confirm
|
||||
[[ ! "$confirm" =~ ^[Yy]$ ]] && { echo "Cancelled."; exit 0; }
|
||||
|
||||
echo ""
|
||||
log "Starting parallel installations..."
|
||||
|
||||
declare -a INSTALL_PIDS
|
||||
for i in "${!NODE_NAMES[@]}"; do
|
||||
install_single_node "${NODE_NAMES[$i]}" "${NODE_ADDRESSES[$i]}" "$WALLARM_API_TOKEN" &
|
||||
INSTALL_PIDS+=($!)
|
||||
done
|
||||
|
||||
FAILED=0
|
||||
local pid
|
||||
for pid in "${INSTALL_PIDS[@]}"; do
|
||||
wait "$pid" || ((FAILED++))
|
||||
done
|
||||
|
||||
if [[ $FAILED -eq 0 ]]; then
|
||||
log "All nodes installed and started via systemd."
|
||||
else
|
||||
err "$FAILED node(s) failed. Check individual install.log files."
|
||||
fi
|
||||
}
|
||||
|
||||
cmd_config() {
|
||||
# Usage: --config --node NAME --address IP:PORT [--token TOKEN] [--labels LABELS]
|
||||
check_root
|
||||
local node_name="" address="" token="" labels=""
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--node) [[ $# -ge 2 ]] || { err "--node requires a value"; exit 1; }; node_name="$2"; shift 2 ;;
|
||||
--address) [[ $# -ge 2 ]] || { err "--address requires a value"; exit 1; }; address="$2"; shift 2 ;;
|
||||
--token) [[ $# -ge 2 ]] || { err "--token requires a value"; exit 1; }; token="$2"; shift 2 ;;
|
||||
--labels) [[ $# -ge 2 ]] || { err "--labels requires a value"; exit 1; }; labels="$2"; shift 2 ;;
|
||||
*) err "Unknown config option: $1"; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "$node_name" ]]; then
|
||||
err "Missing --node"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local work_dir="${NODES_DIR}/${node_name}"
|
||||
if [[ ! -d "$work_dir" ]]; then
|
||||
err "Node '$node_name' does not exist in ${NODES_DIR}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Update config file
|
||||
if [[ -n "$address" ]]; then
|
||||
if ! check_listen_port "$address"; then
|
||||
exit 1
|
||||
fi
|
||||
log "Updating listening address to $address"
|
||||
sed -i "s|^\([[:space:]]*address: \).*|\1\"${address}\"|" "${work_dir}/etc/go-node.yaml"
|
||||
fi
|
||||
|
||||
# Update env file if token or labels provided (rewrite to avoid sed escaping issues)
|
||||
if [[ -n "$token" || -n "$labels" ]]; then
|
||||
local env_file="${work_dir}/env"
|
||||
[[ -f "$env_file" ]] || { err "env file not found"; exit 1; }
|
||||
local current_token current_labels
|
||||
current_token=$(grep '^WALLARM_API_TOKEN=' "$env_file" | cut -d= -f2-)
|
||||
current_labels=$(grep '^WALLARM_LABELS=' "$env_file" | cut -d= -f2-)
|
||||
write_env_file "$node_name" "${token:-$current_token}" "${labels:-$current_labels}"
|
||||
log "Token/labels updated for $node_name."
|
||||
fi
|
||||
|
||||
log "Configuration updated for $node_name. Restart with: systemctl restart wallarm-node@${node_name}"
|
||||
}
|
||||
|
||||
cmd_remove() {
|
||||
check_root
|
||||
local node_name=""
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--node) [[ $# -ge 2 ]] || { err "--node requires a value"; exit 1; }; node_name="$2"; shift 2 ;;
|
||||
*) err "Unknown remove option: $1"; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "$node_name" ]]; then
|
||||
err "Missing --node"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local work_dir="${NODES_DIR}/${node_name}"
|
||||
if [[ ! -d "$work_dir" ]]; then
|
||||
err "Node '$node_name' does not exist."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "Stopping and disabling service..."
|
||||
systemctl stop "wallarm-node@${node_name}" 2>/dev/null || true
|
||||
systemctl disable "wallarm-node@${node_name}" 2>/dev/null || true
|
||||
|
||||
log "Removing directory ${work_dir}..."
|
||||
rm -rf "$work_dir"
|
||||
log "Node $node_name removed."
|
||||
}
|
||||
|
||||
cmd_status() {
|
||||
# Show systemd status for all found nodes or a specific one
|
||||
local node_name="${1:-}"
|
||||
if [[ -n "$node_name" ]]; then
|
||||
systemctl status "wallarm-node@${node_name}" --no-pager
|
||||
else
|
||||
echo "Wallarm Nodes status:"
|
||||
local dir name
|
||||
for dir in "${NODES_DIR}"/*/; do
|
||||
if [[ -d "$dir" ]]; then
|
||||
name=$(basename "$dir")
|
||||
echo "--- $name ---"
|
||||
systemctl status "wallarm-node@${name}" --no-pager | head -5
|
||||
echo ""
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
# --- Help ---
|
||||
show_help() {
|
||||
cat <<EOF
|
||||
Usage: $0 [COMMAND] [OPTIONS]
|
||||
|
||||
Commands:
|
||||
--preflight Run preflight checks only (no installation).
|
||||
--install Interactive installation of one or more nodes (parallel).
|
||||
--config Update an existing node's configuration.
|
||||
Options: --node NAME --address IP:PORT [--token TOKEN] [--labels LABELS]
|
||||
--remove Remove a node completely.
|
||||
Options: --node NAME
|
||||
--status [NODE] Show systemd status for a node, or all nodes.
|
||||
|
||||
Environment:
|
||||
WALLARM_INSTALLER_URL Override the all-in-one installer URL (default: repo.wallarm.com latest).
|
||||
WALLARM_INSTALLER_ARCH Installer architecture suffix (default: x86_64).
|
||||
|
||||
Examples:
|
||||
$0 --preflight
|
||||
$0 --install
|
||||
$0 --config --node node1 --address 0.0.0.0:9090
|
||||
$0 --remove --node node2
|
||||
$0 --status
|
||||
EOF
|
||||
}
|
||||
|
||||
# --- Main argument parsing ---
|
||||
if [[ $# -eq 0 ]]; then
|
||||
show_help
|
||||
exit 0
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
--preflight) shift; cmd_preflight "$@" ;;
|
||||
--install) shift; cmd_install "$@" ;;
|
||||
--config) shift; cmd_config "$@" ;;
|
||||
--remove) shift; cmd_remove "$@" ;;
|
||||
--status) shift; cmd_status "$@" ;;
|
||||
--help|-h) show_help ;;
|
||||
*) err "Unknown command: $1"; show_help; exit 1 ;;
|
||||
esac
|
||||
112
setup.sh
Normal file → Executable file
112
setup.sh
Normal file → Executable file
|
|
@ -4,6 +4,13 @@
|
|||
# ==============================================================================
|
||||
# Downloads all necessary Wallarm deployment scripts from the Git repository
|
||||
# and makes them executable.
|
||||
#
|
||||
# The repository supports two deployment types:
|
||||
# 1. docker - Wallarm filtering node as a Docker container
|
||||
# 2. native - Wallarm filtering node installed directly on the OS (no Docker)
|
||||
#
|
||||
# Usage: curl -fsSL "https://git.sechpoint.app/customer-engineering/wallarm/raw/branch/main/setup.sh" | bash
|
||||
# DEPLOYMENT_TYPE=native curl -fsSL ".../setup.sh" | bash (non-interactive)
|
||||
# ==============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
|
@ -19,13 +26,23 @@ NC='\033[0m'
|
|||
|
||||
# Git repository URL base
|
||||
GIT_BASE="https://git.sechpoint.app/customer-engineering/wallarm/raw/branch/main/"
|
||||
SCRIPTS=(
|
||||
|
||||
# Per-deployment-type scripts
|
||||
DOCKER_SCRIPTS=(
|
||||
"wallarm-ct-check.sh"
|
||||
"wallarm-ct-deploy.sh"
|
||||
"wallarm-ct-reconfigure.sh"
|
||||
"wallarm-ct-uninstall.sh"
|
||||
)
|
||||
|
||||
NATIVE_SCRIPTS=(
|
||||
"wallarm-ct-check.sh"
|
||||
"wallarm-ct-deploy.sh"
|
||||
"wallarm-ct-reconfigure.sh"
|
||||
"wallarm-ct-uninstall.sh"
|
||||
"wallarm-native.sh"
|
||||
)
|
||||
|
||||
# Detect download command
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
DOWNLOAD_CMD="curl -fL -O"
|
||||
|
|
@ -39,31 +56,43 @@ else
|
|||
exit 1
|
||||
fi
|
||||
|
||||
download_script() {
|
||||
local script="$1"
|
||||
local url="${GIT_BASE}/${script}"
|
||||
echo -e "${YELLOW}Downloading ${script}...${NC}"
|
||||
if [ -f "$script" ]; then
|
||||
echo -e "${YELLOW} File already exists. Overwrite? (y/N)${NC}"
|
||||
read -r answer
|
||||
if [[ ! "$answer" =~ ^[Yy]$ ]]; then
|
||||
echo -e "${BLUE} Skipping.${NC}"
|
||||
# Select the deployment type (interactive or via DEPLOYMENT_TYPE env var)
|
||||
select_deployment_type() {
|
||||
if [[ "${DEPLOYMENT_TYPE:-}" =~ ^(docker|native)$ ]]; then
|
||||
DEPLOY_TYPE="$DEPLOYMENT_TYPE"
|
||||
echo -e "${GREEN}Deployment type: $DEPLOY_TYPE${NC}"
|
||||
return 0
|
||||
fi
|
||||
rm -f "$script"
|
||||
fi
|
||||
|
||||
echo -e "${CYAN}${BOLD}Select the deployment type:${NC}"
|
||||
echo -e " 1. ${YELLOW}docker${NC} - Wallarm filtering node as a Docker container (LXC-optimized)"
|
||||
echo -e " 2. ${YELLOW}native${NC} - Wallarm filtering node installed directly on the OS (no Docker)"
|
||||
read -r -p "$(echo -e "${YELLOW}Enter choice [1/2] (default: docker): ${NC}")" choice
|
||||
case "${choice:-1}" in
|
||||
1|docker) DEPLOY_TYPE="docker" ;;
|
||||
2|native) DEPLOY_TYPE="native" ;;
|
||||
*) DEPLOY_TYPE="docker" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
download_file() {
|
||||
local url="$1"
|
||||
local dest="$2"
|
||||
local description="$3"
|
||||
|
||||
echo -e "${YELLOW}Downloading ${description}...${NC}"
|
||||
if [ "$DOWNLOAD_NAME" = "curl" ]; then
|
||||
curl -fL "$url" -o "$script"
|
||||
curl -fL "$url" -o "$dest"
|
||||
else
|
||||
wget -q "$url" -O "$script"
|
||||
wget -q "$url" -O "$dest"
|
||||
fi
|
||||
|
||||
if [ $? -eq 0 ] && [ -s "$script" ]; then
|
||||
chmod +x "$script"
|
||||
echo -e "${GREEN} Success: ${script} downloaded and made executable.${NC}"
|
||||
if [ -s "$dest" ]; then
|
||||
chmod +x "$dest"
|
||||
echo -e "${GREEN} Success: ${description} downloaded to ${dest}${NC}"
|
||||
else
|
||||
echo -e "${RED} Failed to download ${script}. Check network connectivity.${NC}"
|
||||
rm -f "$dest"
|
||||
echo -e "${RED} Failed to download ${description}. Check network connectivity.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
|
@ -77,9 +106,17 @@ echo "║ Downloads all necessary deployment tools ║"
|
|||
echo "╚══════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo
|
||||
|
||||
# Select deployment type
|
||||
select_deployment_type
|
||||
|
||||
# Determine target directories
|
||||
COMMON_DIR="common"
|
||||
TARGET_DIR="$DEPLOY_TYPE"
|
||||
echo -e "${BLUE}Target directory: ${TARGET_DIR}/${NC}"
|
||||
|
||||
# Check for existing scripts
|
||||
if ls wallarm-ct-*.sh 2>/dev/null | grep -q .; then
|
||||
echo -e "${YELLOW}Existing Wallarm scripts found.${NC}"
|
||||
if ls "$TARGET_DIR"/wallarm-ct-*.sh 2>/dev/null | grep -q .; then
|
||||
echo -e "${YELLOW}Existing $DEPLOY_TYPE Wallarm scripts found.${NC}"
|
||||
echo -e "${YELLOW}Do you want to re-download all? (y/N)${NC}"
|
||||
read -r answer
|
||||
if [[ ! "$answer" =~ ^[Yy]$ ]]; then
|
||||
|
|
@ -88,19 +125,40 @@ if ls wallarm-ct-*.sh 2>/dev/null | grep -q .; then
|
|||
fi
|
||||
fi
|
||||
|
||||
# Download each script
|
||||
# Select the script list for the chosen deployment type
|
||||
case "$DEPLOY_TYPE" in
|
||||
native) SCRIPTS=("${NATIVE_SCRIPTS[@]}") ;;
|
||||
*) SCRIPTS=("${DOCKER_SCRIPTS[@]}") ;;
|
||||
esac
|
||||
|
||||
# Create target directories
|
||||
mkdir -p "$TARGET_DIR" "$COMMON_DIR"
|
||||
|
||||
# Download shared library
|
||||
download_file "${GIT_BASE}common/wallarm-lib.sh" "${COMMON_DIR}/wallarm-lib.sh" "shared library (${COMMON_DIR}/wallarm-lib.sh)"
|
||||
|
||||
# Download the deployment type scripts
|
||||
for script in "${SCRIPTS[@]}"; do
|
||||
download_script "$script"
|
||||
download_file "${GIT_BASE}${TARGET_DIR}/${script}" "${TARGET_DIR}/${script}" "$DEPLOY_TYPE/$script"
|
||||
done
|
||||
|
||||
echo
|
||||
echo -e "${GREEN}${BOLD}All scripts downloaded successfully!${NC}"
|
||||
echo -e "${GREEN}${BOLD}All $DEPLOY_TYPE scripts downloaded successfully!${NC}"
|
||||
echo
|
||||
if [ "$DEPLOY_TYPE" = "native" ]; then
|
||||
echo -e "${CYAN}Next steps:${NC}"
|
||||
echo -e " 1. Run the preflight check: ${YELLOW}./wallarm-ct-check.sh${NC}"
|
||||
echo -e " 2. Deploy a Wallarm node: ${YELLOW}./wallarm-ct-deploy.sh${NC}"
|
||||
echo -e " 3. Reconfigure existing node: ${YELLOW}./wallarm-ct-reconfigure.sh${NC}"
|
||||
echo -e " 4. Uninstall a node: ${YELLOW}./wallarm-ct-uninstall.sh${NC}"
|
||||
echo -e " 1. Run the preflight check: ${YELLOW}./native/wallarm-ct-check.sh${NC}"
|
||||
echo -e " 2. Deploy a Wallarm node: ${YELLOW}./native/wallarm-ct-deploy.sh${NC}"
|
||||
echo -e " 3. Unified node manager: ${YELLOW}./native/wallarm-native.sh --preflight${NC} (then --install)"
|
||||
echo -e " 4. Reconfigure existing node: ${YELLOW}./native/wallarm-ct-reconfigure.sh${NC}"
|
||||
echo -e " 5. Uninstall a node: ${YELLOW}./native/wallarm-ct-uninstall.sh${NC}"
|
||||
else
|
||||
echo -e "${CYAN}Next steps:${NC}"
|
||||
echo -e " 1. Run the preflight check: ${YELLOW}./docker/wallarm-ct-check.sh${NC}"
|
||||
echo -e " 2. Deploy a Wallarm node: ${YELLOW}./docker/wallarm-ct-deploy.sh${NC}"
|
||||
echo -e " 3. Reconfigure existing node: ${YELLOW}./docker/wallarm-ct-reconfigure.sh${NC}"
|
||||
echo -e " 4. Uninstall a node: ${YELLOW}./docker/wallarm-ct-uninstall.sh${NC}"
|
||||
fi
|
||||
echo
|
||||
echo -e "${YELLOW}Note: Some scripts require sudo. Run them with: sudo ./<script>${NC}"
|
||||
echo -e "${YELLOW}Make sure you have the required information ready (see documentation).${NC}"
|
||||
Loading…
Reference in a new issue