# Docker Socket Permissions and Security 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: - **User:** `zastava-agent` (system user) - **Group:** `docker` (grants socket access) - **Socket:** `/var/run/docker.sock` ```yaml # 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: | Capability | Risk Level | Mitigation | |------------|-----------|------------| | List containers | Low | Required for operation | | Inspect containers | Low | Required for operation | | Read container logs | Medium | Agent does not use this | | Create containers | High | Agent does not use this | | Execute in containers | Critical | Agent does not use this | | Pull images | High | Agent does not use this | | Remove containers | High | Agent does not use this | ### Agent Behavior The Zastava Agent performs **read-only operations**: ```go // 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: ```yaml # 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](https://github.com/Tecnativa/docker-socket-proxy) ```bash # 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: ```env ZASTAVA_AGENT__DockerEndpoint=tcp://localhost:2375 ``` ### Option 2: Unix Socket with ACLs Use filesystem ACLs for fine-grained access: ```bash # 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 ```te # 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 ```apparmor # /etc/apparmor.d/zastava-agent profile zastava-agent /opt/stellaops/zastava-agent/StellaOps.Zastava.Agent { # Docker socket access /var/run/docker.sock rw, # Deny network access except to scanner backend 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: ```bash # 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 | Component | Log Location | |-----------|--------------| | Agent stdout/stderr | `journalctl -u zastava-agent` | | Runtime events | `/var/lib/zastava-agent/runtime-events/*.ndjson` | | Health check | Agent stdout (structured JSON) | ### Log Configuration ```env # Set log level Serilog__MinimumLevel__Default=Information # Available levels: Verbose, Debug, Information, Warning, Error, Fatal ``` ### Log Rotation Event buffer files are automatically rotated: ```yaml # 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: | Endpoint | Port | Description | |----------|------|-------------| | `/healthz` | 8080 | Liveness probe | | `/readyz` | 8080 | Readiness probe | | `/livez` | 8080 | Alias for liveness | ### Health Check Port Configure via environment variable: ```env ZASTAVA_AGENT__HealthCheck__Port=8080 ``` ### Health Check Behavior **Liveness (`/healthz`):** - Returns 200 if agent process is running - Returns 503 if critical subsystems failed **Readiness (`/readyz`):** - Returns 200 if agent can process events - Returns 503 if: - Docker socket is unreachable - Event buffer is not writable - Backend connection failed ### 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 ```yaml 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: `docs/modules/zastava/operations/dashboards/zastava-observability.json` ## Troubleshooting ### Cannot Access Docker Socket ```bash # 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 ```bash # 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 ```bash # 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 - [Docker Engine Security](https://docs.docker.com/engine/security/) - [Docker Socket Security](https://docs.docker.com/engine/security/protect-access/) - [Rootless Docker](https://docs.docker.com/engine/security/rootless/) - [docker-socket-proxy](https://github.com/Tecnativa/docker-socket-proxy)