d47d08ecab
Implements protocol v1.2.0. verifySignature() returned true when no public_key was configured, logging "skipping signature verification". The SSO installer never wrote a public_key, so a default install executed reboot, service_restart, configure_ldap, arbitrary_bash and update_binary UNVERIFIED from anything that could reach its socket. An agent that cannot verify now refuses. Canonicalization also disagreed with the server. Go's encoding/json escapes <, > and & by default; JSON.stringify does not. Any payload containing them hashed differently on each side and failed verification -- for arbitrary_bash that is most real scripts (`>` redirection, `&&`). Now uses json.Encoder with SetEscapeHTML(false), trailing newline trimmed. The SSO now rejects tokens it did not issue. Handles its close codes (4001/4002/4003/4004) and backs off 5 minutes on an enrollment failure instead of retrying every 5s forever. The connect log no longer prints the URL, which carried ?token=. install.sh gains --public-key and warns when none is configured. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
174 lines
5.2 KiB
Bash
174 lines
5.2 KiB
Bash
#!/bin/bash
|
|
set -e
|
|
|
|
# --- Configuration ---
|
|
# In a real environment, these would be derived from the script's download URL
|
|
# or passed as additional arguments. For now, we use the most recent release.
|
|
BINARY_URL="https://github.com/theta42/theta-agent/releases/latest/download/theta-agent-linux-amd64"
|
|
CONFIG_DIR="/etc/theta42"
|
|
CONFIG_FILE="$CONFIG_DIR/agent.yml"
|
|
BIN_PATH="/usr/local/bin/theta-agent"
|
|
SERVICE_FILE="/etc/systemd/system/theta-agent.service"
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
NC='\033[0m' # No Color
|
|
|
|
log() { echo -e "${GREEN}[+]${NC} $1"; }
|
|
error() { echo -e "${RED}[!]${NC} $1"; exit 1; }
|
|
|
|
# 1. Root check
|
|
if [ "$EUID" -ne 0 ]; then
|
|
error "This script must be run as root."
|
|
fi
|
|
|
|
# Install SSSD and PAM integration packages if missing
|
|
install_sssd_deps() {
|
|
if ! command -v sssd >/dev/null 2>&1; then
|
|
log "Installing SSSD and PAM integration dependencies..."
|
|
if command -v apt-get >/dev/null 2>&1; then
|
|
DEBIAN_FRONTEND=noninteractive apt-get update -qq || true
|
|
DEBIAN_FRONTEND=noninteractive apt-get install -y -qq sssd sssd-ldap libnss-sss libpam-sss libsss-sudo pam-auth-update || true
|
|
if command -v pam-auth-update >/dev/null 2>&1; then
|
|
pam-auth-update --enable mkhomedir || true
|
|
fi
|
|
elif command -v dnf >/dev/null 2>&1; then
|
|
dnf install -y sssd sssd-ldap sssd-tools || true
|
|
elif command -v yum >/dev/null 2>&1; then
|
|
yum install -y sssd sssd-ldap sssd-tools || true
|
|
elif command -v pacman >/dev/null 2>&1; then
|
|
pacman -S --noconfirm sssd || true
|
|
elif command -v zypper >/dev/null 2>&1; then
|
|
zypper in -y sssd || true
|
|
fi
|
|
else
|
|
log "SSSD is already installed."
|
|
fi
|
|
}
|
|
|
|
# 2. Argument Parsing
|
|
URL=""
|
|
TOKEN=""
|
|
PUBLIC_KEY=""
|
|
B64_CONFIG=""
|
|
INSTALL_SSSD=0
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
--url)
|
|
URL="$2"
|
|
shift 2
|
|
;;
|
|
--token)
|
|
TOKEN="$2"
|
|
shift 2
|
|
;;
|
|
# Base64 of the SSO's raw Ed25519 public key. The agent verifies high-risk
|
|
# commands (reboot, configure_ldap, arbitrary_bash, update_binary) against
|
|
# it and REFUSES them when it is absent, so an install without this key can
|
|
# stream telemetry but cannot be acted on.
|
|
--public-key)
|
|
PUBLIC_KEY="$2"
|
|
shift 2
|
|
;;
|
|
--install-sssd|--ldap)
|
|
INSTALL_SSSD=1
|
|
shift
|
|
;;
|
|
*)
|
|
B64_CONFIG="$1"
|
|
shift
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Validation
|
|
if [ -z "$B64_CONFIG" ] && [ -z "$URL" ] || [ -z "$B64_CONFIG" ] && [ -z "$TOKEN" ]; then
|
|
error "Missing required configuration. Either provide a base64 encoded config, or both --url and --token."
|
|
echo "Usage examples:"
|
|
echo " sh install.sh \"BASE64_CONFIG\""
|
|
echo " sh install.sh --url \"https://sso.local\" --token \"ISSUED_TOKEN\" --public-key \"BASE64_KEY\" --install-sssd"
|
|
echo ""
|
|
echo "The token must be issued by the SSO (Directory -> Install Agent enrolls"
|
|
echo "the host and mints it). Tokens the server did not issue are rejected."
|
|
exit 1
|
|
fi
|
|
|
|
log "Starting Theta Agent installation..."
|
|
|
|
# 3. Install binary
|
|
log "Downloading binary from $BINARY_URL..."
|
|
curl -fsSL "$BINARY_URL" -o "$BIN_PATH" || error "Failed to download binary."
|
|
chmod +x "$BIN_PATH"
|
|
|
|
# 4. Setup configuration
|
|
log "Preparing configuration directory $CONFIG_DIR..."
|
|
mkdir -p "$CONFIG_DIR"
|
|
chmod 755 "$CONFIG_DIR"
|
|
|
|
if [ -n "$B64_CONFIG" ]; then
|
|
log "Decoding and writing configuration from base64..."
|
|
echo "$B64_CONFIG" | base64 -d > "$CONFIG_FILE" || error "Failed to decode base64 configuration."
|
|
else
|
|
log "Generating minimal configuration from arguments..."
|
|
# Create a minimal yaml with the provided URL and Token
|
|
cat <<EOF > "$CONFIG_FILE"
|
|
server_url: "$URL"
|
|
auth_token: "$TOKEN"
|
|
public_key: "$PUBLIC_KEY"
|
|
location: "unknown"
|
|
capabilities:
|
|
telemetry: true
|
|
configure_ldap: false
|
|
reboot: false
|
|
service_control: []
|
|
arbitrary_bash: false
|
|
EOF
|
|
fi
|
|
chmod 600 "$CONFIG_FILE"
|
|
|
|
# An agent with no public_key cannot verify signed commands and will refuse
|
|
# every one of them. That is the safe default, but it is silent at run time, so
|
|
# say it plainly here where the operator is watching.
|
|
if ! grep -qE '^public_key:[[:space:]]*"[^"]+"' "$CONFIG_FILE" 2>/dev/null; then
|
|
log "WARNING: no public_key configured — this agent will report telemetry but"
|
|
log " REFUSE reboot / configure_ldap / arbitrary_bash / update_binary."
|
|
log " Re-run with --public-key \"<base64 key>\" (shown at enrollment)."
|
|
fi
|
|
|
|
# 4b. Ensure SSSD dependencies are installed if configure_ldap is enabled
|
|
if [ "$INSTALL_SSSD" -eq 1 ] || grep -q -i "configure_ldap:\s*true" "$CONFIG_FILE" 2>/dev/null; then
|
|
install_sssd_deps
|
|
fi
|
|
|
|
# 5. Setup systemd service
|
|
log "Creating systemd service unit..."
|
|
cat <<EOF > "$SERVICE_FILE"
|
|
[Unit]
|
|
Description=Theta Agent Unified Endpoint Management
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
ExecStart=$BIN_PATH
|
|
Restart=always
|
|
RestartSec=5
|
|
StandardOutput=syslog
|
|
StandardError=syslog
|
|
SyslogIdentifier=theta-agent
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOF
|
|
|
|
# 6. Start the agent
|
|
log "Enabling and starting Theta Agent..."
|
|
systemctl daemon-reload
|
|
systemctl enable theta-agent
|
|
systemctl start theta-agent
|
|
|
|
log "Theta Agent installation complete!"
|
|
log "Verify status with: systemctl status theta-agent"
|
|
log "Check logs with: journalctl -u theta-agent -f"
|