feat(infra): auto-commit con 86 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
---
|
||||
name: docker_container_exec
|
||||
kind: function
|
||||
lang: go
|
||||
domain: infra
|
||||
version: "1.0.0"
|
||||
purity: impure
|
||||
signature: "func DockerContainerExec(opts DockerExecOpts) (DockerExecResult, error)"
|
||||
description: "Exec comando dentro de container Docker con whitelist obligatoria de binarios. SIN shell expansion. Stream demuxado stdout/stderr. Timeout context-cancellable. Capability docker.container.exec del device_agent."
|
||||
tags: [docker, docker-agent, exec, security, infra]
|
||||
uses_functions: []
|
||||
uses_types: [docker_exec_result_go_infra, error_go_core]
|
||||
returns: [docker_exec_result_go_infra]
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: [bytes, context, encoding/json, fmt, io, net/http, strings, time]
|
||||
params:
|
||||
- name: opts.ContainerID
|
||||
desc: "ID o nombre del container destino. Obligatorio."
|
||||
- name: opts.Cmd
|
||||
desc: "argv del comando. Cmd[0] es el binario a ejecutar; debe estar en BinariesAllowed. Sin shell expansion."
|
||||
- name: opts.BinariesAllowed
|
||||
desc: "Whitelist exacta de binarios permitidos. EMPTY = rechaza todo sin contactar el engine. Security-critical."
|
||||
- name: opts.User
|
||||
desc: "Usuario/grupo en formato UID:GID (ej: '1000:1000'). Vacio = default del container."
|
||||
- name: opts.WorkingDir
|
||||
desc: "Directorio de trabajo dentro del container. Vacio = default del container."
|
||||
- name: opts.Env
|
||||
desc: "Variables de entorno adicionales en formato KEY=VAL. Combinadas con las del container."
|
||||
- name: opts.TimeoutSeconds
|
||||
desc: "Timeout de la operacion completa en segundos. Default 30 si es 0 o negativo."
|
||||
- name: opts.DockerHost
|
||||
desc: "Socket Docker. Default 'unix:///var/run/docker.sock'. Soporta 'unix://', 'tcp://', 'http://'."
|
||||
output: "DockerExecResult{ExitCode, Stdout, Stderr, Duration} con el resultado completo del comando ejecutado."
|
||||
tested: true
|
||||
tests:
|
||||
- "binario en whitelist exitcode 0 stdout stderr capturados"
|
||||
- "binario NO en whitelist error sin contactar engine"
|
||||
- "whitelist vacia rechaza todo"
|
||||
- "timeout simulado"
|
||||
test_file_path: "functions/infra/docker_container_exec_test.go"
|
||||
file_path: "functions/infra/docker_container_exec.go"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```go
|
||||
result, err := infra.DockerContainerExec(infra.DockerExecOpts{
|
||||
ContainerID: "my-app-container",
|
||||
Cmd: []string{"cat", "/etc/hostname"},
|
||||
BinariesAllowed: []string{"cat", "ls", "id", "env"},
|
||||
User: "1000:1000",
|
||||
TimeoutSeconds: 10,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("exec failed: %v", err)
|
||||
}
|
||||
fmt.Printf("exit=%d stdout=%q stderr=%q duration=%dms\n",
|
||||
result.ExitCode, result.Stdout, result.Stderr, result.Duration)
|
||||
```
|
||||
|
||||
## Cuando usarla
|
||||
|
||||
Cuando necesitas ejecutar un comando dentro de un container en ejecucion desde Go, con control de seguridad sobre que binarios pueden invocarse. Indispensable para el capability group `docker-agent` (flow 0009 A2): health-checks, introspection, file reads, reconfigurations controladas. Usar antes de cualquier operacion que requiera acceso al filesystem o procesos del container sin montar volumenes adicionales.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **NUNCA usar `BinariesAllowed` vacio en produccion**: la funcion rechaza por diseno. Cualquier lista vacia es un error de configuracion, no un "permitir todo".
|
||||
- **Sin shell expansion**: no puedes hacer pipes, redirects ni `$VAR` desde `Cmd`. Para eso el manifest del agent debe usar un binario que implemente esa logica (ej. `python3 -c "..."` si python3 esta en la whitelist).
|
||||
- **Stream demux 8-byte header**: el protocolo Docker multiplexado (Tty=false) prefixa cada frame con 8 bytes. Esta funcion lo demux correctamente; si cambias a Tty=true el stream es raw y el demux falla.
|
||||
- **Timeout incluye overhead de red**: el `TimeoutSeconds` aplica al flujo completo (create + start + stream + inspect). En containers locales el overhead es <10ms; en TCP remoto puede ser mas alto.
|
||||
- **ExitCode -1**: solo aparece si falla la llamada a `/exec/{id}/json` (error de red/timeout), no como exit code real del proceso.
|
||||
- **DockerHost en TCP**: usar `tcp://host:2375` para daemons remotos sin TLS. Para TLS, el cliente HTTP necesitaria cert/key — no soportado en esta version (ver Gotchas de produccion).
|
||||
Reference in New Issue
Block a user