diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index adb5aa9..48dc6d6 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -1,410 +1,9 @@ # Boundary Architecture -This document describes the architecture and components of boundary, a network isolation tool for monitoring and restricting HTTP/HTTPS requests. +Boundary -## High-Level Architecture +# Alternative Architectures +## Anthropic SRT +https://github.com/anthropic-experimental/sandbox-runtime -``` -┌─────────────────────────────────────────────────────────────────────────────┐ -│ BOUNDARY SYSTEM │ -├─────────────────────────────────────────────────────────────────────────────┤ -│ │ -│ User Command: boundary --allow "*.github.com" -- npm install │ -│ │ │ -│ ▼ │ -│ ┌─────────────────────────────────────────────────────────────────────────┐ │ -│ │ CLI LAYER │ │ -│ │ • Parse --allow rules │ │ -│ │ • Configure log level │ │ -│ │ • Setup components │ │ -│ │ • Handle signals │ │ -│ └─────────────────────────────────────────────────────────────────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌─────────────────────────────────────────────────────────────────────────┐ │ -│ │ BOUNDARY CORE │ │ -│ │ │ │ -│ │ ┌───────────────────┐ ┌─────────────────────┐ │ │ -│ │ │ JAILER │ │ PROXY SERVER │ │ │ -│ │ │ │ │ │ │ │ -│ │ │ Network Isolation │◄───┤ HTTP/HTTPS Handler │ │ │ -│ │ │ Process Control │ │ TLS Termination │ │ │ -│ │ │ │ │ Request Filtering │ │ │ -│ │ └───────────────────┘ └─────────────────────┘ │ │ -│ │ │ │ │ │ -│ │ │ ▼ │ │ -│ │ │ ┌─────────────────────────────────────────────────┐ │ │ -│ │ │ │ SUPPORT COMPONENTS │ │ │ -│ │ │ │ │ │ │ -│ │ │ │ Rules Engine │ Auditor │ TLS Manager │ │ │ -│ │ │ │ • Pattern │ • Log │ • CA Certificate │ │ │ -│ │ │ │ Matching │ Reqs │ • Certificate │ │ │ -│ │ │ │ • Method │ • Allow/ │ Generation │ │ │ -│ │ │ │ Filtering │ Deny │ • TLS Config │ │ │ -│ │ │ └─────────────────────────────────────────────────┘ │ │ -│ │ │ │ │ -│ │ ▼ │ │ -│ │ ┌─────────────────────┐ │ │ -│ │ │ TARGET COMMAND │ │ │ -│ │ │ │ │ │ -│ │ │ npm install │ ◄── HTTP_PROXY/HTTPS_PROXY env vars │ │ -│ │ │ curl https://... │ ◄── Network isolation (Linux) │ │ -│ │ │ git clone │ ◄── DNS redirection │ │ -│ │ │ │ │ │ -│ │ └─────────────────────┘ │ │ -│ │ │ │ -│ └─────────────────────────────────────────────────────────────────────────┘ │ -│ │ -└─────────────────────────────────────────────────────────────────────────────┘ -``` - -## Component Details - -### 1. CLI Layer -**Input**: Command line arguments (`--allow`, `--log-level`, target command) -**Output**: Configured boundary instance and executed target command - -**Responsibilities**: -- Parse and validate command line arguments -- Create rule engine from `--allow` specifications -- Setup logging configuration -- Initialize and coordinate all components -- Handle graceful shutdown on signals - -### 2. Jailer Component -**Input**: Target command, proxy configuration -**Output**: Isolated process with network restrictions - -Platform-specific implementations: - -#### Linux Jailer -``` -┌─────────────────────────────────────────────┐ -│ LINUX JAILER │ -├─────────────────────────────────────────────┤ -│ │ -│ Network Namespace Creation │ -│ │ │ -│ ├─ Create veth pair (host ↔ namespace) │ -│ ├─ Configure IP addresses │ -│ ├─ Setup routing │ -│ └─ Configure DNS resolution │ -│ │ -│ iptables Rules │ -│ │ │ -│ ├─ REDIRECT all HTTP → proxy (8080) │ -│ ├─ REDIRECT all HTTPS → proxy (8080) │ -│ └─ Allow localhost traffic │ -│ │ -│ Process Execution │ -│ │ │ -│ ├─ Set HTTP_PROXY env var │ -│ ├─ Set HTTPS_PROXY env var │ -│ ├─ Set SSL_CERT_FILE (custom CA) │ -│ └─ Execute in network namespace │ -│ │ -└─────────────────────────────────────────────┘ -``` - - - -### 3. Proxy Server Component -**Input**: HTTP/HTTPS requests from jailed processes -**Output**: Allowed requests forwarded to internet, denied requests blocked - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ PROXY SERVER │ -├─────────────────────────────────────────────────────────────────┤ -│ │ -│ Connection Handler │ -│ │ │ -│ ├─ Listen on port 8080 │ -│ ├─ Detect HTTP vs HTTPS (peek first byte) │ -│ ├─ Route to appropriate handler │ -│ └─ Handle connection errors │ -│ │ -│ ┌─────────────────────┐ ┌───────────────────────────────────┐ │ -│ │ HTTP HANDLER │ │ HTTPS HANDLER │ │ -│ │ │ │ │ │ -│ │ • Direct requests │ │ • CONNECT tunneling │ │ -│ │ • Apply rules │ │ • TLS termination │ │ -│ │ • Forward allowed │ │ • Certificate generation │ │ -│ │ • Block denied │ │ • Decrypt → HTTP → Re-encrypt │ │ -│ │ │ │ • Apply rules to decrypted │ │ -│ └─────────────────────┘ └───────────────────────────────────┘ │ -│ │ │ │ -│ └────────────────┬───────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌────────────────────────────────────────────────────────────┐ │ -│ │ REQUEST PROCESSING │ │ -│ │ │ │ -│ │ 1. Extract method (GET, POST, etc.) │ │ -│ │ 2. Extract URL (https://github.com/user/repo) │ │ -│ │ 3. Evaluate against rules │ │ -│ │ 4. Audit request (log allow/deny decision) │ │ -│ │ 5. Forward if allowed, block if denied │ │ -│ │ │ │ -│ └────────────────────────────────────────────────────────────┘ │ -│ │ -└─────────────────────────────────────────────────────────────────┘ -``` - -### 4. Rules Engine -**Input**: HTTP method, URL, configured allow rules -**Output**: Allow/Deny decision with matching rule - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ RULES ENGINE │ -├─────────────────────────────────────────────────────────────────┤ -│ │ -│ Rule Structure │ -│ │ │ -│ ├─ Pattern: "*.github.com", "api.*", "exact.com" │ -│ ├─ Methods: ["GET", "POST"] or nil (all methods) │ -│ └─ Raw: "allow GET,POST *.github.com" (for logging) │ -│ │ -│ Pattern Matching │ -│ │ │ -│ ├─ Wildcard support: * matches any characters │ -│ ├─ Case-insensitive matching │ -│ ├─ Protocol-agnostic: pattern "github.com" matches │ -│ │ both "http://github.com" and "https://github.com" │ -│ └─ Domain-only matching: "github.com" matches any path │ -│ │ -│ Evaluation Process │ -│ │ │ -│ ├─ 1. Check each rule in order │ -│ ├─ 2. Verify method matches (if specified) │ -│ ├─ 3. Apply wildcard pattern matching to URL │ -│ ├─ 4. Return ALLOW + rule on first match │ -│ └─ 5. Return DENY if no rules match (default deny-all) │ -│ │ -│ Examples: │ -│ • "*.github.com" → matches "api.github.com" │ -│ • "GET github.com" → matches "GET https://github.com/user" │ -│ • "api.*" → matches "api.example.com" │ -│ │ -└─────────────────────────────────────────────────────────────────┘ -``` - -### 5. Auditor Component -**Input**: Request details and allow/deny decision -**Output**: Structured logs - -``` -┌──────────────────────────────────────────────────────────────────┐ -│ AUDITOR │ -├──────────────────────────────────────────────────────────────────┤ -│ │ -│ Request Information │ -│ │ │ -│ ├─ Method: GET, POST, PUT, DELETE, etc. │ -│ ├─ URL: Full URL of the request │ -│ ├─ Allowed: boolean (true/false) │ -│ └─ Rule: Matching rule string (if allowed) │ -│ │ -│ Log Output │ -│ │ │ -│ ├─ ALLOW requests: INFO level │ -│ │ "ALLOW method=GET url=https://github.com rule=*.github.com" │ -│ │ │ -│ └─ DENY requests: WARN level │ -│ "DENY method=GET url=https://example.com" │ -│ │ -│ Structured Logging │ -│ │ │ -│ ├─ Uses slog for structured output │ -│ ├─ Machine-readable format │ -│ ├─ Filterable by log level │ -│ └─ Includes contextual information │ -│ │ -└──────────────────────────────────────────────────────────────────┘ -``` - -### 6. TLS Manager -**Input**: Hostname from HTTPS requests -**Output**: Valid TLS certificates, CA certificate file - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ TLS MANAGER │ -├─────────────────────────────────────────────────────────────────┤ -│ │ -│ Certificate Authority (CA) │ -│ │ │ -│ ├─ Generate root CA private key │ -│ ├─ Create root CA certificate │ -│ ├─ Write CA cert to file system │ -│ └─ Configure system to trust CA (via SSL_CERT_FILE) │ -│ │ -│ Dynamic Certificate Generation │ -│ │ │ -│ ├─ On-demand cert creation per hostname │ -│ ├─ Sign certificates with CA private key │ -│ ├─ Cache certificates for reuse │ -│ ├─ Include Subject Alternative Names (SAN) │ -│ └─ Set appropriate validity periods │ -│ │ -│ TLS Termination │ -│ │ │ -│ ├─ Accept HTTPS connections │ -│ ├─ Present generated certificate │ -│ ├─ Decrypt TLS traffic │ -│ ├─ Process as HTTP internally │ -│ └─ Re-encrypt for upstream connections │ -│ │ -│ Certificate Cache │ -│ │ │ -│ ├─ In-memory storage for performance │ -│ ├─ Thread-safe access with mutex │ -│ ├─ Key: hostname │ -│ └─ Value: *tls.Certificate │ -│ │ -└─────────────────────────────────────────────────────────────────┘ -``` - -## Request Flow Examples - -### HTTP Request Flow -``` -1. Target Process (npm install) - ├─ Makes HTTP request to registry.npmjs.org - ├─ HTTP_PROXY env var points to localhost:8080 - └─ Request sent to boundary proxy - -2. Jailer (Network Isolation) - ├─ iptables/PF rules intercept request - ├─ Redirect to proxy server (port 8080) - └─ Process isolated in namespace/group - -3. Proxy Server - ├─ Receive HTTP request - ├─ Extract method=GET, url=http://registry.npmjs.org/package - └─ Route to HTTP handler - -4. Rules Engine - ├─ Evaluate "GET http://registry.npmjs.org/package" - ├─ Check against rules: ["*.npmjs.org"] - ├─ Pattern "*.npmjs.org" matches "registry.npmjs.org" - └─ Return: ALLOW + rule="*.npmjs.org" - -5. Auditor - ├─ Log: "ALLOW method=GET url=http://registry.npmjs.org/package rule=*.npmjs.org" - └─ Output to structured log - -6. Request Forwarding - ├─ Create upstream HTTP request - ├─ Forward to registry.npmjs.org - ├─ Receive response - └─ Return response to target process -``` - -### HTTPS Request Flow -``` -1. Target Process (curl https://github.com) - ├─ Makes HTTPS request to github.com - ├─ HTTPS_PROXY env var points to localhost:8080 - └─ Sends CONNECT request to proxy - -2. Jailer (Network Isolation) - ├─ iptables/PF rules intercept CONNECT - ├─ Redirect to proxy server (port 8080) - └─ Process sees custom CA certificate - -3. Proxy Server (CONNECT Handler) - ├─ Receive "CONNECT github.com:443" - ├─ Accept connection - └─ Wait for TLS handshake - -4. TLS Manager - ├─ Generate certificate for "github.com" - ├─ Sign with boundary CA - ├─ Present certificate to client - └─ Establish TLS connection - -5. HTTPS Handler - ├─ Decrypt TLS traffic - ├─ Parse HTTP request: "GET / HTTP/1.1 Host: github.com" - └─ Route to request processing - -6. Rules Engine - ├─ Evaluate "GET https://github.com/" - ├─ Check against rules: ["*.github.com"] - ├─ Pattern "*.github.com" matches "github.com" - └─ Return: ALLOW + rule="*.github.com" - -7. Auditor - ├─ Log: "ALLOW method=GET url=https://github.com/ rule=*.github.com" - └─ Output to structured log - -8. Request Forwarding - ├─ Create upstream HTTPS request - ├─ Connect to real github.com:443 - ├─ Forward decrypted HTTP request - ├─ Receive response - ├─ Encrypt response with boundary TLS - └─ Return to target process -``` - -### Denied Request Flow -``` -1. Target Process (curl https://malicious.com) - ├─ Makes HTTPS request to malicious.com - └─ Request intercepted by boundary - -2. Proxy Server Processing - ├─ Extract method=GET, url=https://malicious.com/ - └─ Route to rules engine - -3. Rules Engine - ├─ Evaluate "GET https://malicious.com/" - ├─ Check against rules: ["*.github.com", "*.npmjs.org"] - ├─ No patterns match "malicious.com" - └─ Return: DENY (default deny-all) - -4. Auditor - ├─ Log: "DENY method=GET url=https://malicious.com/" - └─ Output to structured log - -5. Request Blocking - ├─ Return HTTP 403 Forbidden - ├─ Include boundary error message - └─ Close connection -``` - -## Platform Differences - -| Aspect | Linux | -|--------|-------| -| **Isolation** | Network namespaces | -| **Traffic Interception** | iptables REDIRECT | -| **DNS** | Custom resolv.conf | -| **Privileges** | Requires network capabilities (e.g., CAP_NET_ADMIN) | -| **Security** | Strong isolation | -| **Compatibility** | Linux kernel 3.8+ | -| **Process Control** | Network namespace | - -## Security Model - -### Default Deny-All -- All network requests are blocked by default -- Only explicitly allowed patterns are permitted -- Fail-safe behavior: unknown requests are denied - -### Network Isolation -- Process cannot bypass boundary -- All traffic routed through proxy server -- TLS interception prevents encrypted bypass - -### Certificate Authority -- Boundary acts as trusted CA for intercepted HTTPS -- Generated certificates signed by boundary CA -- Target processes trust boundary CA via SSL_CERT_FILE - -### Audit Trail -- All requests (allowed and denied) are logged -- Structured logging for analysis -- Rule attribution for allowed requests +SRT diff --git a/README.md b/README.md index 15c176b..62a0abc 100644 --- a/README.md +++ b/README.md @@ -15,26 +15,82 @@ boundary creates an isolated network environment for target processes, intercept ## Installation +### Quick Install (Recommended) + ```bash curl -fsSL https://raw.githubusercontent.com/coder/boundary/main/install.sh | bash ``` > For installation options, manual installation, and release details, see [RELEASES.md](RELEASES.md). +### From Source + +Build `boundary` from source: + +```bash +# Clone the repository +git clone https://github.com/coder/boundary.git +cd boundary + +# Build the binary +make build + +# Install binary and wrapper script (optional) +sudo cp boundary /usr/local/bin/ +sudo cp scripts/boundary-wrapper.sh /usr/local/bin/boundary-run +sudo chmod +x /usr/local/bin/boundary-run +``` + +**Requirements:** +- Go 1.24 or later +- Linux + ## Usage +### Quick Start with Shortcut + +The recommended way to run `boundary` is using the `boundary-run` shortcut, which handles privilege escalation automatically. The `boundary-run` wrapper is installed automatically when you use the installation script: + +```bash +# After installation, use the shortcut: +boundary-run --allow "domain=github.com" -- curl https://github.com +boundary-run -- bash +``` + +> **Note:** If you installed `boundary` manually, you can install the wrapper script separately: +> ```bash +> sudo cp scripts/boundary-wrapper.sh /usr/local/bin/boundary-run +> sudo chmod +x /usr/local/bin/boundary-run +> ``` + +### Direct Usage + +If you prefer to run `boundary` directly, you'll need to handle privilege escalation: + +```bash +sudo -E env PATH=$PATH setpriv \ + --reuid=$(id -u) \ + --regid=$(id -g) \ + --clear-groups \ + --inh-caps=+net_admin \ + --ambient-caps=+net_admin \ + boundary --allow "domain=github.com" -- curl https://github.com +``` + +### Examples + ```bash # Allow only requests to github.com -boundary --allow "domain=github.com" -- curl https://github.com +boundary-run --allow "domain=github.com" -- curl https://github.com # Allow full access to GitHub issues API, but only GET/HEAD elsewhere on GitHub -boundary \ +boundary-run \ --allow "domain=github.com path=/api/issues/*" \ --allow "method=GET,HEAD domain=github.com" \ -- npm install # Default deny-all: everything is blocked unless explicitly allowed -boundary -- curl https://example.com +boundary-run -- curl https://example.com ``` ## Allow Rules @@ -51,11 +107,11 @@ boundary -- curl https://example.com ### Examples ```bash -boundary --allow "domain=github.com" -- git pull -boundary --allow "domain=*.github.com" -- npm install # GitHub subdomains -boundary --allow "method=GET,HEAD domain=api.github.com" -- curl https://api.github.com -boundary --allow "method=POST domain=api.example.com path=/users,/posts" -- ./app # Multiple paths -boundary --allow "path=/api/v1/*,/api/v2/*" -- curl https://api.example.com/api/v1/users +boundary-run --allow "domain=github.com" -- git pull +boundary-run --allow "domain=*.github.com" -- npm install # GitHub subdomains +boundary-run --allow "method=GET,HEAD domain=api.github.com" -- curl https://api.github.com +boundary-run --allow "method=POST domain=api.example.com path=/users,/posts" -- ./app # Multiple paths +boundary-run --allow "path=/api/v1/*,/api/v2/*" -- curl https://api.example.com/api/v1/users ``` Wildcards: `*` matches any characters. All traffic is denied unless explicitly allowed. @@ -63,8 +119,9 @@ Wildcards: `*` matches any characters. All traffic is denied unless explicitly a ## Logging ```bash -boundary --log-level info --allow "method=*" -- npm install # Show all requests -boundary --log-level debug --allow "domain=github.com" -- git pull # Debug info +boundary-run --log-level warn --allow "domain=github.com" -- git pull # Default: only logs denied requests +boundary-run --log-level info --allow "method=*" -- npm install # Show all requests +boundary-run --log-level debug --allow "domain=github.com" -- git pull # Debug info ``` **Log Levels:** `error`, `warn` (default), `info`, `debug` @@ -80,13 +137,20 @@ boundary --log-level debug --allow "domain=github.com" -- git pull # Debug info ## Command-Line Options ```text -boundary [flags] -- command [args...] - - --allow Allow rule (repeatable) - --log-level Set log level (error, warn, info, debug) - -h, --help Print help +boundary-run [flags] -- command [args...] + + --config Path to YAML config file (default: ~/.config/coder_boundary/config.yaml) + --allow Allow rule (repeatable). Merged with allowlist from config file + --log-level Set log level (error, warn, info, debug). Default: warn + --log-dir Directory to write logs to (default: stderr) + --proxy-port HTTP proxy port (default: 8080) + --pprof Enable pprof profiling server + --pprof-port pprof server port (default: 6060) + -h, --help Print help ``` +Environment variables: `BOUNDARY_CONFIG`, `BOUNDARY_ALLOW`, `BOUNDARY_LOG_LEVEL`, `BOUNDARY_LOG_DIR`, `PROXY_PORT`, `BOUNDARY_PPROF`, `BOUNDARY_PPROF_PORT` + ## Development ```bash @@ -99,6 +163,10 @@ make fmt # Format code make lint # Lint code ``` +## Architecture + +For detailed information about how `boundary` works internally, see [ARCHITECTURE.md](ARCHITECTURE.md). + ## License MIT License - see LICENSE file for details. \ No newline at end of file diff --git a/install.sh b/install.sh index 0309c03..9dfac3c 100755 --- a/install.sh +++ b/install.sh @@ -163,6 +163,35 @@ download_binary() { log_success "Binary extracted and made executable" } +# Download wrapper script +download_wrapper() { + local wrapper_url="https://raw.githubusercontent.com/$REPO/main/scripts/boundary-wrapper.sh" + WRAPPER_PATH="$TMP_DIR/boundary-wrapper.sh" + + log_info "Downloading boundary-run wrapper script..." + + if command -v curl &> /dev/null; then + if ! curl -fsSL "$wrapper_url" -o "$WRAPPER_PATH"; then + log_warning "Failed to download wrapper script. You can install it manually later." + WRAPPER_PATH="" + return + fi + elif command -v wget &> /dev/null; then + if ! wget -q "$wrapper_url" -O "$WRAPPER_PATH"; then + log_warning "Failed to download wrapper script. You can install it manually later." + WRAPPER_PATH="" + return + fi + else + log_warning "Cannot download wrapper script (neither curl nor wget available)." + WRAPPER_PATH="" + return + fi + + chmod +x "$WRAPPER_PATH" + log_success "Wrapper script downloaded" +} + # Install binary install_binary() { local target_path="$INSTALL_DIR/$BINARY_NAME" @@ -181,6 +210,22 @@ install_binary() { fi log_success "boundary installed successfully!" + + # Install wrapper script if available + if [[ -n "$WRAPPER_PATH" && -f "$WRAPPER_PATH" ]]; then + local wrapper_target="$INSTALL_DIR/boundary-run" + log_info "Installing boundary-run wrapper to $wrapper_target..." + + if [[ "$NEED_SUDO" == "true" ]]; then + sudo cp "$WRAPPER_PATH" "$wrapper_target" + sudo chmod +x "$wrapper_target" + else + cp "$WRAPPER_PATH" "$wrapper_target" + chmod +x "$wrapper_target" + fi + + log_success "boundary-run wrapper installed successfully!" + fi } # Verify installation @@ -196,6 +241,13 @@ verify_installation() { log_warning "boundary is not in PATH. You may need to add $INSTALL_DIR to your PATH." log_info "You can run boundary using the full path: $INSTALL_DIR/$BINARY_NAME" fi + + if command -v "boundary-run" &> /dev/null; then + log_success "boundary-run wrapper is available in PATH" + elif [[ -f "$INSTALL_DIR/boundary-run" ]]; then + log_info "boundary-run is installed at $INSTALL_DIR/boundary-run" + log_info "You can use it directly: $INSTALL_DIR/boundary-run" + fi } # Print usage examples @@ -204,9 +256,16 @@ print_usage() { echo -e "${GREEN}🎉 Installation complete!${NC}" echo echo -e "${BLUE}Quick Start:${NC}" - echo " boundary --help" - echo " boundary --allow 'github.com' -- curl https://github.com" - echo " boundary --allow '*.npmjs.org' -- npm install" + if command -v "boundary-run" &> /dev/null; then + echo " boundary-run --help" + echo " boundary-run --allow 'github.com' -- curl https://github.com" + echo " boundary-run --allow '*.npmjs.org' -- npm install" + echo " boundary-run -- bash" + else + echo " boundary --help" + echo " boundary --allow 'github.com' -- curl https://github.com" + echo " boundary --allow '*.npmjs.org' -- npm install" + fi echo echo -e "${BLUE}Documentation:${NC}" echo " https://github.com/$REPO" @@ -293,6 +352,7 @@ main() { fi download_binary + download_wrapper install_binary verify_installation print_usage diff --git a/scripts/boundary-wrapper.sh b/scripts/boundary-wrapper.sh new file mode 100644 index 0000000..22fc9ac --- /dev/null +++ b/scripts/boundary-wrapper.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# Wrapper script for boundary that handles privilege escalation +# This makes it convenient to run boundary without typing the long sudo+setpriv command + +# Find boundary binary +BOUNDARY_BIN="" +if [ -n "$BOUNDARY_BIN_PATH" ]; then + BOUNDARY_BIN="$BOUNDARY_BIN_PATH" +elif command -v boundary >/dev/null 2>&1; then + BOUNDARY_BIN="$(command -v boundary)" +else + echo "Error: boundary binary not found. Please install boundary or set BOUNDARY_BIN_PATH." >&2 + exit 1 +fi + +# Check if we're already running as the target user (not root) +if [ "$(id -u)" -eq 0 ]; then + echo "Error: This wrapper should not be run as root. It will handle privilege escalation automatically." >&2 + exit 1 +fi + +# Run boundary with proper privilege handling +exec sudo -E env PATH="$PATH" setpriv \ + --reuid="$(id -u)" \ + --regid="$(id -g)" \ + --clear-groups \ + --inh-caps=+net_admin \ + --ambient-caps=+net_admin \ + "$BOUNDARY_BIN" "$@" +