Docker Socket Permissions and Security

Historical / retired. This document describes Docker socket access for the legacy Zastava Agent. The StellaOps.Zastava.* source tree was archived on 2026-05-12 and the standalone agent no longer ships; runtime evidence is now collected through the RuntimeInstrumentation host-agent / deployment-agent model. See the Zastava retirement record and Host-agent strategy. The socket-hardening guidance below (proxy, ACLs, SELinux/AppArmor, rootless Docker) remains a useful reference for any future host-agent that reads the Docker socket.

This document covers the security considerations and configuration options for Docker socket access in Zastava Agent deployments.

Overview

The Zastava Agent requires read access to the Docker socket (/var/run/docker.sock) to:

  1. Monitor container lifecycle events - Start, stop, pause, die, etc.
  2. Inspect running containers - Image digest, labels, environment variables
  3. Collect runtime evidence - Loaded libraries, process information

Default Configuration

By default, the agent runs as:

# systemd service configuration
User=zastava-agent
Group=docker
ReadWritePaths=/var/run/docker.sock

Security Considerations

Docker Socket Exposure Risks

The Docker socket provides significant privileges:

CapabilityRisk LevelMitigation
List containersLowRequired for operation
Inspect containersLowRequired for operation
Read container logsMediumAgent does not use this
Create containersHighAgent does not use this
Execute in containersCriticalAgent does not use this
Pull imagesHighAgent does not use this
Remove containersHighAgent does not use this

Agent Behavior

The Zastava Agent performs read-only operations:

// Operations used by agent
docker.ContainerList(...)     // List running containers
docker.ContainerInspect(...)  // Get container details
docker.Events(...)            // Subscribe to lifecycle events

The agent does not perform write operations such as creating, starting, stopping, or removing containers.

Alternative Configurations

Option 1: Docker API Proxy (Recommended for High-Security)

Deploy a Docker API proxy that restricts available operations:

# docker-proxy configuration example
allowed_endpoints:
  - "GET /containers/json"        # List containers
  - "GET /containers/*/json"      # Inspect container
  - "GET /events"                 # Subscribe to events
  - "GET /_ping"                  # Health check

Example proxy: Tecnativa/docker-socket-proxy

# Deploy proxy
docker run -d \
  --name docker-proxy \
  -v /var/run/docker.sock:/var/run/docker.sock:ro \
  -e CONTAINERS=1 \
  -e EVENTS=1 \
  -p 2375:2375 \
  tecnativa/docker-socket-proxy

Configure agent to use proxy:

ZASTAVA_AGENT__DockerEndpoint=tcp://localhost:2375

Option 2: Unix Socket with ACLs

Use filesystem ACLs for fine-grained access:

# Install ACL support
sudo apt-get install acl

# Set ACL for zastava-agent user
sudo setfacl -m u:zastava-agent:rw /var/run/docker.sock

# Verify ACL
getfacl /var/run/docker.sock

This allows removing the user from the docker group while maintaining socket access.

Option 3: SELinux/AppArmor Policies

SELinux Policy

# zastava-agent.te
module zastava_agent 1.0;

require {
    type docker_var_run_t;
    type zastava_agent_t;
    class sock_file { read write };
}

# Allow read/write to Docker socket
allow zastava_agent_t docker_var_run_t:sock_file { read write getattr };

AppArmor Profile

# /etc/apparmor.d/zastava-agent
profile zastava-agent /opt/stellaops/zastava-agent/StellaOps.Zastava.Agent {
  # Docker socket access
  /var/run/docker.sock rw,

  # Network access (restrict to the scanner backend via egress firewall rules)
  network inet stream,
  network inet6 stream,

  # Read-only system access
  /etc/stellaops/* r,
  /opt/stellaops/zastava-agent/** mr,

  # Data directory
  /var/lib/zastava-agent/** rw,
}

Option 4: Rootless Docker

For maximum isolation, use rootless Docker:

# Install rootless Docker
dockerd-rootless-setuptool.sh install

# Configure agent to use rootless socket
export ZASTAVA_AGENT__DockerEndpoint=unix:///run/user/1000/docker.sock

Note: Rootless Docker has some limitations with networking and storage drivers.

Log Paths

Agent Logs

ComponentLog Location
Agent stdout/stderrjournalctl -u zastava-agent
Runtime events/var/lib/zastava-agent/runtime-events/*.ndjson
Health checkAgent stdout (structured JSON)

Log Configuration

# Set log level
Serilog__MinimumLevel__Default=Information

# Available levels: Verbose, Debug, Information, Warning, Error, Fatal

Log Rotation

Event buffer files are automatically rotated:

# Default settings
event_buffer:
  max_file_size_mb: 10
  max_total_size_mb: 100
  retention_hours: 24

Health Check Configuration

The agent exposes HTTP health endpoints:

EndpointPortDescription
/healthz8080Liveness probe
/readyz8080Readiness probe
/livez8080Alias for liveness

Health Check Port

Configure via environment variable:

ZASTAVA_AGENT__HealthCheck__Port=8080

Health Check Behavior

Liveness (/healthz):

Readiness (/readyz):

Prometheus Metrics

Health metrics are exposed at /metrics:

# HELP zastava_agent_docker_connected Docker connectivity status
# TYPE zastava_agent_docker_connected gauge
zastava_agent_docker_connected 1

# HELP zastava_agent_buffer_writable Event buffer writability
# TYPE zastava_agent_buffer_writable gauge
zastava_agent_buffer_writable 1

# HELP zastava_agent_events_buffered Number of events in buffer
# TYPE zastava_agent_events_buffered gauge
zastava_agent_events_buffered 42

Monitoring Recommendations

Alerting Rules

groups:
  - name: zastava-agent
    rules:
      - alert: ZastavaAgentDown
        expr: up{job="zastava-agent"} == 0
        for: 5m
        annotations:
          summary: "Zastava Agent is down on {{ $labels.instance }}"

      - alert: ZastavaDockerDisconnected
        expr: zastava_agent_docker_connected == 0
        for: 1m
        annotations:
          summary: "Zastava Agent lost Docker connectivity"

      - alert: ZastavaBufferNotWritable
        expr: zastava_agent_buffer_writable == 0
        for: 1m
        severity: critical
        annotations:
          summary: "Zastava event buffer is not writable"

Grafana Dashboard

Import the Zastava monitoring dashboard from dashboards/zastava-observability.json.

Troubleshooting

Cannot Access Docker Socket

# Check socket exists
ls -la /var/run/docker.sock

# Check agent user groups
id zastava-agent

# Check Docker daemon is running
systemctl status docker

# Test socket access manually
sudo -u zastava-agent docker ps

Permission Denied Errors

# Add user to docker group (if not using ACLs)
sudo usermod -aG docker zastava-agent

# Restart agent
sudo systemctl restart zastava-agent

Events Not Being Received

# Check Docker events stream
docker events --since 1m

# Verify agent can see events
journalctl -u zastava-agent | grep -i "event"

# Check event buffer
ls -la /var/lib/zastava-agent/runtime-events/

References