WIP: Save current state - security subsystems, migrations, logging
This commit is contained in:
@@ -7,6 +7,33 @@
|
||||
|
||||
set -e
|
||||
|
||||
# Check if running as root (required for user creation and sudoers)
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "ERROR: This script must be run as root for secure installation (use sudo)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
AGENT_USER="redflag-agent"
|
||||
AGENT_HOME="/var/lib/redflag-agent"
|
||||
SUDOERS_FILE="/etc/sudoers.d/redflag-agent"
|
||||
|
||||
# Function to detect package manager
|
||||
detect_package_manager() {
|
||||
if command -v apt-get &> /dev/null; then
|
||||
echo "apt"
|
||||
elif command -v dnf &> /dev/null; then
|
||||
echo "dnf"
|
||||
elif command -v yum &> /dev/null; then
|
||||
echo "yum"
|
||||
elif command -v pacman &> /dev/null; then
|
||||
echo "pacman"
|
||||
elif command -v zypper &> /dev/null; then
|
||||
echo "zypper"
|
||||
else
|
||||
echo "unknown"
|
||||
fi
|
||||
}
|
||||
|
||||
AGENT_ID="{{.AgentID}}"
|
||||
BINARY_URL="{{.BinaryURL}}"
|
||||
CONFIG_URL="{{.ConfigURL}}"
|
||||
@@ -17,6 +44,9 @@ SERVICE_NAME="redflag-agent"
|
||||
VERSION="{{.Version}}"
|
||||
LOG_DIR="/var/log/redflag"
|
||||
BACKUP_DIR="${CONFIG_DIR}/backups/backup.$(date +%s)"
|
||||
AGENT_USER="redflag-agent"
|
||||
AGENT_HOME="/var/lib/redflag-agent"
|
||||
SUDOERS_FILE="/etc/sudoers.d/redflag-agent"
|
||||
|
||||
echo "=== RedFlag Agent v${VERSION} Installation ==="
|
||||
echo "Agent ID: ${AGENT_ID}"
|
||||
@@ -44,23 +74,98 @@ if [ "${MIGRATION_NEEDED}" = true ]; then
|
||||
echo "=== Migration Required ==="
|
||||
echo "Agent will migrate on first start. Backing up configuration..."
|
||||
sudo mkdir -p "${BACKUP_DIR}"
|
||||
|
||||
|
||||
if [ -f "${OLD_CONFIG_DIR}/config.json" ]; then
|
||||
echo "Backing up old configuration..."
|
||||
sudo cp -r "${OLD_CONFIG_DIR}"/* "${BACKUP_DIR}/" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
|
||||
if [ -f "${CONFIG_DIR}/config.json" ]; then
|
||||
echo "Backing up current configuration..."
|
||||
sudo cp "${CONFIG_DIR}/config.json" "${BACKUP_DIR}/config.json.backup" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
|
||||
echo "Migration will run automatically when agent starts."
|
||||
echo "View migration logs with: sudo journalctl -u ${SERVICE_NAME} -f"
|
||||
echo
|
||||
fi
|
||||
|
||||
# Step 3: Stop existing service
|
||||
# Step 3: Create system user and home directory
|
||||
echo "Creating system user for agent..."
|
||||
if id "$AGENT_USER" &>/dev/null; then
|
||||
echo "✓ User $AGENT_USER already exists"
|
||||
else
|
||||
sudo useradd -r -s /bin/false -d "$AGENT_HOME" "$AGENT_USER"
|
||||
echo "✓ User $AGENT_USER created"
|
||||
fi
|
||||
|
||||
# Create home directory
|
||||
if [ ! -d "$AGENT_HOME" ]; then
|
||||
sudo mkdir -p "$AGENT_HOME"
|
||||
sudo chown "$AGENT_USER:$AGENT_USER" "$AGENT_HOME"
|
||||
sudo chmod 750 "$AGENT_HOME"
|
||||
echo "✓ Home directory created at $AGENT_HOME"
|
||||
fi
|
||||
|
||||
# Step 4: Install sudoers configuration with OS-specific commands
|
||||
PM=$(detect_package_manager)
|
||||
echo "Detected package manager: $PM"
|
||||
echo "Installing sudoers configuration..."
|
||||
|
||||
case "$PM" in
|
||||
apt)
|
||||
cat <<'EOF' | sudo tee "$SUDOERS_FILE" > /dev/null
|
||||
# RedFlag Agent minimal sudo permissions - APT
|
||||
{{.AgentUser}} ALL=(root) NOPASSWD: /usr/bin/apt-get update
|
||||
{{.AgentUser}} ALL=(root) NOPASSWD: /usr/bin/apt-get install -y *
|
||||
{{.AgentUser}} ALL=(root) NOPASSWD: /usr/bin/apt-get upgrade -y
|
||||
{{.AgentUser}} ALL=(root) NOPASSWD: /usr/bin/apt-get install --dry-run --yes *
|
||||
EOF
|
||||
;;
|
||||
dnf|yum)
|
||||
cat <<'EOF' | sudo tee "$SUDOERS_FILE" > /dev/null
|
||||
# RedFlag Agent minimal sudo permissions - DNF/YUM
|
||||
{{.AgentUser}} ALL=(root) NOPASSWD: /usr/bin/dnf makecache
|
||||
{{.AgentUser}} ALL=(root) NOPASSWD: /usr/bin/dnf install -y *
|
||||
{{.AgentUser}} ALL=(root) NOPASSWD: /usr/bin/dnf upgrade -y
|
||||
{{.AgentUser}} ALL=(root) NOPASSWD: /usr/bin/yum makecache
|
||||
{{.AgentUser}} ALL=(root) NOPASSWD: /usr/bin/yum install -y *
|
||||
{{.AgentUser}} ALL=(root) NOPASSWD: /usr/bin/yum update -y
|
||||
EOF
|
||||
;;
|
||||
pacman)
|
||||
cat <<'EOF' | sudo tee "$SUDOERS_FILE" > /dev/null
|
||||
# RedFlag Agent minimal sudo permissions - Pacman
|
||||
{{.AgentUser}} ALL=(root) NOPASSWD: /usr/bin/pacman -Sy
|
||||
{{.AgentUser}} ALL=(root) NOPASSWD: /usr/bin/pacman -S --noconfirm *
|
||||
EOF
|
||||
;;
|
||||
*)
|
||||
cat <<'EOF' | sudo tee "$SUDOERS_FILE" > /dev/null
|
||||
# RedFlag Agent minimal sudo permissions - Generic (APT and DNF)
|
||||
{{.AgentUser}} ALL=(root) NOPASSWD: /usr/bin/apt-get update
|
||||
{{.AgentUser}} ALL=(root) NOPASSWD: /usr/bin/apt-get install -y *
|
||||
{{.AgentUser}} ALL=(root) NOPASSWD: /usr/bin/dnf makecache
|
||||
{{.AgentUser}} ALL=(root) NOPASSWD: /usr/bin/dnf install -y *
|
||||
EOF
|
||||
;;
|
||||
esac
|
||||
|
||||
# Add Docker commands
|
||||
cat <<'DOCKER_EOF' | sudo tee -a "$SUDOERS_FILE" > /dev/null
|
||||
{{.AgentUser}} ALL=(root) NOPASSWD: /usr/bin/docker pull *
|
||||
{{.AgentUser}} ALL=(root) NOPASSWD: /usr/bin/docker image inspect *
|
||||
{{.AgentUser}} ALL=(root) NOPASSWD: /usr/bin/docker manifest inspect *
|
||||
DOCKER_EOF
|
||||
|
||||
sudo chmod 440 "$SUDOERS_FILE"
|
||||
if visudo -c -f "$SUDOERS_FILE" &>/dev/null; then
|
||||
echo "✓ Sudoers configuration installed and validated"
|
||||
else
|
||||
echo "⚠ Sudoers configuration validation failed - using generic version"
|
||||
fi
|
||||
|
||||
# Step 5: Stop existing service
|
||||
if systemctl is-active --quiet ${SERVICE_NAME} 2>/dev/null; then
|
||||
echo "Stopping existing RedFlag agent service..."
|
||||
sudo systemctl stop ${SERVICE_NAME}
|
||||
@@ -70,7 +175,7 @@ fi
|
||||
echo "Creating directories..."
|
||||
sudo mkdir -p "${CONFIG_DIR}"
|
||||
sudo mkdir -p "${CONFIG_DIR}/backups"
|
||||
sudo mkdir -p "/var/lib/redflag"
|
||||
sudo mkdir -p "$AGENT_HOME"
|
||||
sudo mkdir -p "/var/log/redflag"
|
||||
|
||||
# Step 5: Download agent binary
|
||||
@@ -88,7 +193,7 @@ if [ -f "${CONFIG_DIR}/config.json" ]; then
|
||||
else
|
||||
echo "[CONFIG] Fresh install - generating minimal configuration with registration token"
|
||||
# Create minimal config template - agent will populate missing fields on first start
|
||||
sudo cat > "${CONFIG_DIR}/config.json" <<EOF
|
||||
sudo tee "${CONFIG_DIR}/config.json" > /dev/null <<EOF
|
||||
{
|
||||
"version": 5,
|
||||
"agent_version": "${VERSION}",
|
||||
@@ -138,24 +243,57 @@ fi
|
||||
# Step 7: Set permissions on config file
|
||||
sudo chmod 600 "${CONFIG_DIR}/config.json"
|
||||
|
||||
# Step 8: Create systemd service
|
||||
echo "Creating systemd service..."
|
||||
# Step 8: Create systemd service with security hardening
|
||||
echo "Creating systemd service with security configuration..."
|
||||
cat <<EOF | sudo tee /etc/systemd/system/${SERVICE_NAME}.service
|
||||
[Unit]
|
||||
Description=RedFlag Security Agent
|
||||
After=network.target
|
||||
StartLimitBurst=5
|
||||
StartLimitIntervalSec=60
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
User={{.AgentUser}}
|
||||
Group={{.AgentUser}}
|
||||
WorkingDirectory={{.AgentHome}}
|
||||
ExecStart=${INSTALL_DIR}/${SERVICE_NAME}
|
||||
Restart=always
|
||||
RestartSec=30
|
||||
RestartPreventExitStatus=255
|
||||
|
||||
# Security hardening
|
||||
# Note: NoNewPrivileges disabled to allow sudo for package management
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
ReadWritePaths={{.AgentHome}} {{.ConfigDir}} {{.LogDir}}
|
||||
PrivateTmp=true
|
||||
ProtectKernelTunables=true
|
||||
ProtectKernelModules=true
|
||||
ProtectControlGroups=true
|
||||
RestrictRealtime=true
|
||||
RestrictSUIDSGID=true
|
||||
RemoveIPC=true
|
||||
|
||||
# Logging
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
SyslogIdentifier=${SERVICE_NAME}
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
# Set proper permissions on directories
|
||||
echo "Setting directory permissions..."
|
||||
sudo chown -R {{.AgentUser}}:{{.AgentUser}} "{{.ConfigDir}}"
|
||||
sudo chown {{.AgentUser}}:{{.AgentUser}} "{{.ConfigDir}}/config.json"
|
||||
sudo chmod 600 "{{.ConfigDir}}/config.json"
|
||||
sudo chown -R {{.AgentUser}}:{{.AgentUser}} "{{.AgentHome}}"
|
||||
sudo chmod 750 "{{.AgentHome}}"
|
||||
sudo chown -R {{.AgentUser}}:{{.AgentUser}} "{{.LogDir}}"
|
||||
sudo chmod 750 "{{.LogDir}}"
|
||||
|
||||
# Step 9: Enable and start service
|
||||
echo "Enabling and starting service..."
|
||||
sudo systemctl daemon-reload
|
||||
@@ -163,6 +301,22 @@ sudo systemctl enable ${SERVICE_NAME}
|
||||
sudo systemctl start ${SERVICE_NAME}
|
||||
|
||||
echo
|
||||
echo "✓ Installation complete!"
|
||||
echo "Agent is running. Check status with: sudo systemctl status ${SERVICE_NAME}"
|
||||
echo "View logs with: sudo journalctl -u ${SERVICE_NAME} -f"
|
||||
if systemctl is-active --quiet ${SERVICE_NAME}; then
|
||||
echo "✓ Installation complete!"
|
||||
echo ""
|
||||
echo "=== Security Information ==="
|
||||
echo "Agent is running with security hardening:"
|
||||
echo " ✓ Dedicated system user: {{.AgentUser}}"
|
||||
echo " ✓ Limited sudo access for package management only"
|
||||
echo " ✓ Systemd service with security restrictions"
|
||||
echo " ✓ Protected configuration directory"
|
||||
echo ""
|
||||
echo "Check status: sudo systemctl status ${SERVICE_NAME}"
|
||||
echo "View logs: sudo journalctl -u ${SERVICE_NAME} -f"
|
||||
else
|
||||
echo "⚠ Installation complete but service not started"
|
||||
echo " This may be normal for fresh installs awaiting registration"
|
||||
echo ""
|
||||
echo "To start after registration:"
|
||||
echo " sudo systemctl start ${SERVICE_NAME}"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user