Skip to content

XDR Podman Quadlets for User Session - Enhanced Container Security

Published: at 11:45 AM

XDR Podman Quadlets for User Session: Enhanced Container Security

This guide demonstrates how to deploy XDR (Extended Detection and Response) agents as Podman Quadlets in user sessions, providing rootless container-based security monitoring with seamless systemd integration. This approach enhances security by running XDR agents without root privileges while maintaining full monitoring capabilities.

Overview

Podman Quadlets represent a modern approach to container management, combining the security benefits of rootless containers with the reliability of systemd service management. When applied to XDR deployment, this creates a robust security monitoring solution that:

Prerequisites

System Requirements

  1. Operating System: Linux with systemd 250+ (RHEL 9, Ubuntu 22.04, Fedora 36+)
  2. Podman: Version 4.4+ with quadlet support
  3. User Account: Regular user account (non-root)
  4. XDR Agent: Container image for your XDR solution

Initial Setup

# Verify Podman version
podman --version

# Check systemd user instance
systemctl --user status

# Enable lingering for user (allows services to run without login)
sudo loginctl enable-linger $USER

# Create quadlet directory structure
mkdir -p ~/.config/containers/systemd/

Understanding Quadlets

Quadlets are systemd unit files that define how Podman containers should run. They’re automatically converted to proper systemd services by the podman-systemd-generator.

Key Benefits

  1. Declarative Configuration: Define containers as systemd units
  2. Automatic Management: Systemd handles lifecycle, restarts, and dependencies
  3. User Session Support: Run containers in user context without root
  4. Native Integration: Leverage systemd features like timers and dependencies

XDR Agent Quadlet Configuration

Basic XDR Container Quadlet

Create ~/.config/containers/systemd/xdr-agent.container:

[Unit]
Description=XDR Security Agent
Documentation=https://docs.example.com/xdr-agent
Wants=network-online.target
After=network-online.target
StartLimitIntervalSec=60
StartLimitBurst=3

[Container]
# Container image
Image=registry.example.com/security/xdr-agent:latest
ContainerName=xdr-agent

# Security options
SecurityLabelDisable=false
ReadOnly=true
NoNewPrivileges=true

# Resource limits
CpuLimit=2
MemoryLimit=2G
MemoryReservation=1G

# Environment variables
Environment="XDR_SERVER=xdr.example.com"
Environment="XDR_PORT=8443"
Environment="LOG_LEVEL=info"
EnvironmentFile=/home/%u/.config/xdr/agent.env

# Volume mounts
Volume=/home/%u/.config/xdr/certs:/etc/xdr/certs:ro,Z
Volume=/var/log/journal:/var/log/journal:ro
Volume=/proc:/host/proc:ro
Volume=/sys:/host/sys:ro
Volume=/etc/os-release:/host/etc/os-release:ro

# Tmpfs for temporary data
Tmpfs=/tmp:size=512M,mode=1777
Tmpfs=/var/tmp:size=512M,mode=1777

# Network configuration
Network=host
Hostname=xdr-%H

# Health check
HealthCmd="/usr/bin/xdr-agent healthcheck"
HealthInterval=30s
HealthRetries=3
HealthTimeout=10s
HealthStartPeriod=60s

# Labels for management
Label="io.containers.autoupdate=registry"
Label="com.example.component=security"
Label="com.example.managed-by=quadlet"

[Service]
# Restart policy
Restart=always
RestartSec=30

# Systemd integration
Type=notify
NotifyAccess=all

# Security hardening
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=read-only
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
LockPersonality=yes

# Timeouts
TimeoutStartSec=120
TimeoutStopSec=30

[Install]
WantedBy=default.target

Advanced XDR Configuration with Secrets

Create ~/.config/containers/systemd/xdr-agent-advanced.container:

[Unit]
Description=Advanced XDR Security Agent with Secret Management
Documentation=https://docs.example.com/xdr-agent
Requires=podman-secret-xdr-token.service
After=podman-secret-xdr-token.service

[Container]
Image=registry.example.com/security/xdr-agent:latest
ContainerName=xdr-agent-advanced

# Pull policy
Pull=newer
PullRetryCount=3
PullRetryDelay=10s

# User and group mapping
UserNS=keep-id
User=1000
Group=1000

# Capabilities (minimal required set)
DropCapability=all
AddCapability=CAP_SYS_PTRACE,CAP_DAC_READ_SEARCH,CAP_NET_RAW

# Secret management
Secret=xdr-token,type=env,target=XDR_AUTH_TOKEN
Secret=xdr-cert,type=mount,target=/etc/xdr/cert.pem
Secret=xdr-key,type=mount,target=/etc/xdr/key.pem,mode=0600

# Advanced volumes with specific options
Volume=/home/%u/.config/xdr/config.yaml:/etc/xdr/config.yaml:ro,Z
Volume=xdr-data:/var/lib/xdr:Z
Volume=/run/user/%U/podman/podman.sock:/var/run/docker.sock:ro

# Environment with interpolation
Environment="HOSTNAME=%H"
Environment="XDR_NODE_ID=%H-%u"
Environment="XDR_CLUSTER_NAME=production"

# Entrypoint override
Entrypoint=/usr/bin/xdr-agent
Cmd="--config=/etc/xdr/config.yaml" "--node-id=$XDR_NODE_ID"

# Logging configuration
LogDriver=journald
LogOpt="tag=xdr-agent"
LogOpt="labels=com.example.component"

[Service]
Type=notify
Restart=on-failure
RestartSec=30
RestartPreventExitStatus=0 2

# Dependency ordering
RequiresMountsFor=/home/%u/.config/xdr

# Resource accounting
CPUAccounting=yes
MemoryAccounting=yes
TasksAccounting=yes
IOAccounting=yes

# Watchdog
WatchdogSec=60

[Install]
WantedBy=default.target

Supporting Services

Secret Creation Service

Create ~/.config/containers/systemd/podman-secret-xdr-token.service:

[Unit]
Description=Create Podman Secret for XDR Token
ConditionPathExists=!/run/user/%U/containers/secrets/xdr-token
Before=xdr-agent-advanced.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/bash -c 'podman secret create xdr-token /home/%u/.config/xdr/token'
ExecStop=podman secret rm xdr-token

[Install]
WantedBy=default.target

Auto-Update Timer

Create ~/.config/containers/systemd/podman-auto-update-xdr.timer:

[Unit]
Description=Auto-update XDR containers
Documentation=man:podman-auto-update(1)

[Timer]
OnCalendar=daily
RandomizedDelaySec=900
Persistent=true

[Install]
WantedBy=timers.target

Create ~/.config/containers/systemd/podman-auto-update-xdr.service:

[Unit]
Description=Auto-update XDR containers
Documentation=man:podman-auto-update(1)
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/bin/podman auto-update --label "io.containers.autoupdate=registry"
ExecStartPost=/usr/bin/systemctl --user try-restart xdr-agent.service

[Install]
WantedBy=default.target

Configuration Files

XDR Agent Configuration

Create ~/.config/xdr/config.yaml:

# XDR Agent Configuration
version: 2

agent:
  id: ${XDR_NODE_ID}
  name: ${HOSTNAME}-xdr
  type: endpoint

server:
  url: https://${XDR_SERVER}:${XDR_PORT}
  tls:
    cert: /etc/xdr/cert.pem
    key: /etc/xdr/key.pem
    ca: /etc/xdr/ca.pem
    verify: true

collectors:
  system:
    enabled: true
    interval: 60s
    metrics:
      - cpu
      - memory
      - disk
      - network

  process:
    enabled: true
    interval: 30s
    include_cmdline: true

  file_integrity:
    enabled: true
    paths:
      - /etc
      - /usr/bin
      - /usr/sbin
      - /home/%u/.ssh
    exclude:
      - "*.log"
      - "*.tmp"

  network:
    enabled: true
    capture_packets: false
    connection_tracking: true

  container:
    enabled: true
    runtime: podman
    socket: /var/run/docker.sock

logging:
  level: ${LOG_LEVEL}
  format: json
  outputs:
    - type: file
      path: /var/lib/xdr/agent.log
      rotate:
        max_size: 100M
        max_age: 7d
        max_backups: 5
    - type: syslog
      facility: local0
      tag: xdr-agent

response:
  enabled: true
  actions:
    - quarantine
    - kill_process
    - block_network
  require_approval: true

performance:
  max_cpu_percent: 20
  max_memory_mb: 2048
  rate_limit:
    events_per_second: 1000
    burst: 5000

Environment File

Create ~/.config/xdr/agent.env:

# XDR Agent Environment Variables
# This file should be protected with appropriate permissions

# Server Configuration
XDR_SERVER=xdr.example.com
XDR_PORT=8443

# Agent Settings
XDR_DEPLOYMENT_TYPE=production
XDR_REGION=us-east-1
XDR_TENANT_ID=tenant-123

# Features
XDR_FEATURE_EDR=true
XDR_FEATURE_DLP=false
XDR_FEATURE_COMPLIANCE=true

# Performance Tuning
XDR_WORKER_THREADS=4
XDR_BUFFER_SIZE=65536
XDR_BATCH_SIZE=100

# Logging
LOG_LEVEL=info
LOG_FORMAT=json

Deployment Process

Initial Deployment

#!/bin/bash
# deploy-xdr.sh - XDR Deployment Script

set -euo pipefail

XDR_USER="${USER}"
XDR_HOME="/home/${XDR_USER}"
XDR_CONFIG="${XDR_HOME}/.config/xdr"

echo "Deploying XDR Agent for user: ${XDR_USER}"

# Create directories
echo "Creating configuration directories..."
mkdir -p "${XDR_CONFIG}/certs"
mkdir -p "${XDR_HOME}/.config/containers/systemd"

# Set permissions
chmod 700 "${XDR_CONFIG}"
chmod 700 "${XDR_CONFIG}/certs"

# Generate or copy certificates
echo "Setting up certificates..."
# Copy your certificates to ${XDR_CONFIG}/certs/
# Ensure proper permissions (600 for keys, 644 for certs)

# Create secrets
echo "Creating secrets..."
if [ -f "${XDR_CONFIG}/token" ]; then
    podman secret create xdr-token "${XDR_CONFIG}/token" || true
fi

# Reload systemd
echo "Reloading systemd configuration..."
systemctl --user daemon-reload

# Enable and start services
echo "Enabling XDR services..."
systemctl --user enable --now podman-secret-xdr-token.service
systemctl --user enable --now xdr-agent.service
systemctl --user enable --now podman-auto-update-xdr.timer

# Verify deployment
echo "Verifying deployment..."
systemctl --user status xdr-agent.service --no-pager
podman ps --filter "name=xdr-agent"

echo "XDR Agent deployment complete!"

Health Monitoring Script

Create ~/.local/bin/xdr-health-check.sh:

#!/bin/bash
# XDR Health Monitoring Script

set -euo pipefail

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

echo "XDR Agent Health Check"
echo "====================="

# Check service status
echo -n "Service Status: "
if systemctl --user is-active --quiet xdr-agent.service; then
    echo -e "${GREEN}ACTIVE${NC}"
else
    echo -e "${RED}INACTIVE${NC}"
    exit 1
fi

# Check container status
echo -n "Container Status: "
if podman ps --format "{{.Names}}" | grep -q "xdr-agent"; then
    echo -e "${GREEN}RUNNING${NC}"
else
    echo -e "${RED}NOT RUNNING${NC}"
    exit 1
fi

# Check container health
echo -n "Container Health: "
HEALTH=$(podman inspect xdr-agent --format '{{.State.Health.Status}}' 2>/dev/null || echo "unknown")
case $HEALTH in
    healthy)
        echo -e "${GREEN}HEALTHY${NC}"
        ;;
    starting)
        echo -e "${YELLOW}STARTING${NC}"
        ;;
    unhealthy)
        echo -e "${RED}UNHEALTHY${NC}"
        exit 1
        ;;
    *)
        echo -e "${YELLOW}UNKNOWN${NC}"
        ;;
esac

# Check resource usage
echo -e "\nResource Usage:"
podman stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}" xdr-agent

# Check recent logs for errors
echo -e "\nRecent Errors (last 10 minutes):"
journalctl --user -u xdr-agent.service --since "10 minutes ago" -p err --no-pager || echo "No errors found"

# Check auto-update status
echo -e "\nAuto-Update Status:"
systemctl --user status podman-auto-update-xdr.timer --no-pager | grep -E "Loaded:|Active:|Trigger:"

echo -e "\nHealth check complete!"

Troubleshooting

Common Issues and Solutions

Service Won’t Start

# Check service status
systemctl --user status xdr-agent.service

# View detailed logs
journalctl --user -u xdr-agent.service -f

# Check quadlet generation
/usr/lib/systemd/system-generators/podman-system-generator --user --dryrun

# Verify quadlet syntax
systemd-analyze --user verify xdr-agent.service

Permission Issues

# Fix SELinux contexts
restorecon -Rv ~/.config/xdr/

# Check volume permissions
podman unshare ls -la /var/lib/containers/storage/volumes/xdr-data/_data

# Reset user namespace
podman system migrate

Network Connectivity

# Test from container
podman run --rm -it --network host \
    registry.example.com/security/xdr-agent:latest \
    curl -v https://xdr.example.com:8443/health

# Check firewall rules
firewall-cmd --list-all

Debug Mode

Create ~/.config/containers/systemd/xdr-agent-debug.container for debugging:

[Unit]
Description=XDR Agent Debug Mode
Conflicts=xdr-agent.service

[Container]
Image=registry.example.com/security/xdr-agent:latest
ContainerName=xdr-agent-debug

# Debug settings
Environment="LOG_LEVEL=debug"
Environment="XDR_DEBUG=true"

# Interactive mode
Interactive=true
TTY=true

# Override entrypoint for debugging
Entrypoint=/bin/bash

# Mount source code for debugging (if available)
Volume=/home/%u/src/xdr-agent:/src:ro,Z

# Same mounts as production
Volume=/home/%u/.config/xdr/certs:/etc/xdr/certs:ro,Z
Volume=/var/log/journal:/var/log/journal:ro

[Service]
Type=simple
Restart=no

[Install]
WantedBy=default.target

Performance Optimization

Resource Tuning

Create ~/.config/containers/systemd/xdr-agent.resource:

[Unit]
Description=Resource limits for XDR Agent

[Slice]
# CPU allocation
CPUWeight=50
CPUQuota=200%

# Memory limits
MemoryMax=2G
MemoryHigh=1500M

# IO limits
IOWeight=50
IOReadBandwidthMax=/var/lib/containers 50M
IOWriteBandwidthMax=/var/lib/containers 20M

# Task limits
TasksMax=100

Monitoring Dashboard

Create a monitoring script ~/.local/bin/xdr-monitor.sh:

#!/bin/bash
# Real-time XDR monitoring dashboard

watch -n 5 '
echo "=== XDR Agent Monitor ==="
echo
echo "Service Status:"
systemctl --user is-active xdr-agent.service
echo
echo "Container Stats:"
podman stats --no-stream xdr-agent
echo
echo "Recent Logs:"
journalctl --user -u xdr-agent.service -n 5 --no-pager
echo
echo "Network Connections:"
podman exec xdr-agent ss -tunap 2>/dev/null | head -10
'

Security Best Practices

1. Rootless Operation

2. Secret Management

# Use Podman secrets for sensitive data
podman secret create xdr-api-key api-key.txt
rm api-key.txt

# Rotate secrets regularly
podman secret rm xdr-api-key
podman secret create xdr-api-key new-api-key.txt

3. Network Isolation

# For enhanced security, use custom networks
[Container]
Network=xdr-network
IP=10.88.0.10

4. Audit Logging

# Enable audit logging for XDR activities
auditctl -w /home/$USER/.config/xdr/ -p wa -k xdr_config_change
auditctl -w /var/lib/containers/storage/volumes/xdr-data/ -p wa -k xdr_data_access

Integration with XDR Platforms

Wazuh Integration

# Add to config.yaml for Wazuh XDR
integrations:
  wazuh:
    enabled: true
    manager: wazuh.example.com
    port: 1514
    protocol: tcp
    agent_name: ${HOSTNAME}-podman
    groups:
      - linux
      - containers
      - xdr

Elastic Security Integration

# Add to config.yaml for Elastic
integrations:
  elastic:
    enabled: true
    hosts:
      - https://elastic1.example.com:9200
      - https://elastic2.example.com:9200
    username: xdr_agent
    api_key: ${ELASTIC_API_KEY}
    index: xdr-events

Conclusion

Deploying XDR agents as Podman Quadlets in user sessions provides a secure, maintainable, and scalable approach to endpoint security monitoring. This configuration offers:

By following this guide, organizations can implement enterprise-grade security monitoring while adhering to the principle of least privilege and modern container best practices.

Additional Resources