Referencia de egress.yml y de las entradas

Ver en Markdown

Cada clave del fichero de política de Egress CI, cada entrada y salida de la acción, las variables que deja al job y el informe que escribe.

En esta página

egress.yml

La política es un fichero YAML del repositorio, .github/egress.yml salvo que la entrada policy indique otro.

.github/egress.yml
version: 1
mode: enforce
presets: [github-actions]
allow:
  - proxy.golang.org
  - "*.npmjs.org"
  - registry.example.com:5000
  - ci-cache.example.com:*
inspect:
  - api.staging.example.com
ClavePor defectoSignificado
version1Versión del formato. Solo existe la 1.
modeauditaudit: todo pasa y se informa de lo que enforce rechazaría. enforce: se rechaza lo que no está en allow. La entrada mode manda sobre ella.
presetsningunoListas con nombre que se mantienen con la acción. La única es github-actions.
allowningunoDestinos a los que pueden llegar el job y sus contenedores.
inspectningunoHosts cuyo TLS termina el proxy para revisar los cuerpos de las peticiones en busca de secretos. Ver Inspección y DLP.

Una clave desconocida es un error: una errata como alow: hace fallar el paso de la acción en vez de no permitir nada sin avisar. La acción comprueba el fichero antes de arrancar nada.

Reglas de allow

ReglaCoincide con
proxy.golang.orgEse nombre, puertos 80 y 443
*.npmjs.orgCualquier nombre por debajo de npmjs.org (registry.npmjs.org, a.b.npmjs.org), no npmjs.org en sí; puertos 80 y 443
registry.example.com:5000Ese nombre, solo el puerto 5000
registry.example.com:80,5000Ese nombre, puertos 80 y 5000
ci-cache.example.com:*Ese nombre, cualquier puerto
203.0.113.10Esa dirección IPv4, puertos 80 y 443

Los nombres no distinguen mayúsculas y el punto final se ignora. El comodín solo vale como primera etiqueta (*.example.com).

El job recibe las respuestas DNS de un nombre permitido; el bloqueo solo deja pasar los flujos que no son TCP (UDP como QUIC) hacia las direcciones de esas respuestas. Los pulls de imágenes se comprueban contra el nombre del registry en cualquier puerto.

El preset github-actions

github-actions es la lista que GitHub publica para los runners de Actions en el campo domains.actions de api.github.com/meta (enlace externo): el servicio del runner, el checkout, la API, la caché de Actions, los artefactos y los logs, con cada cuenta de almacenamiento de Azure por su nombre exacto (nunca *.blob.core.windows.net, donde cualquiera puede crear una cuenta). La acción añade raw.githubusercontent.com, donde las acciones setup-* leen sus manifiestos de versiones.

La acción descarga la lista al empezar con la entrada token y la guarda 6 horas en ~/.cache/egress-ci/ del usuario del runner. Si la descarga falla, usa una copia incluida en la acción. El resumen del job dice cuál se usó.

Entradas

EntradaPor defectoSignificado
policy.github/egress.ymlRuta del fichero de política.
modevacíoaudit o enforce; manda sobre el mode del fichero. Sirve para probar un fichero en audit en las pull requests y aplicarlo en main.
lockautoEl bloqueo nftables para las conexiones que ignoran el proxy. auto: activo si el job llega a root con sudo o Docker, inactivo si no. on: como auto, pero el paso falla si no se llega a root. off: solo se usa HTTPS_PROXY. En enforce, un bloqueo que no se puede instalar hace fallar el paso.
containerstracktrack: el Docker del job pasa por su propio socket y sus contenedores y builds cumplen la política. lock-all: además rechaza en enforce el tráfico fuera de la política de cualquier otro contenedor (runners que ejecutan un job cada vez). off: Docker se deja como está. Ver Docker y builds.
no-proxyvacíoEntradas extra de NO_PROXY, separadas por comas, para hosts a los que las herramientas con proxy deben ir directas. Con el bloqueo activo, esas conexiones pasan igualmente por el proxy transparente y por la política.
token${{ github.token }}Token con el que se lee api.github.com/meta. Se le pasa a curl por la entrada estándar, nunca en la línea de órdenes.
send-eventsoffon: envía los destinos, bloqueos y detecciones del job a los eventos de Egress de tu organización. Ver Enviar los eventos a OpenWAF.
openwaf-apihttps://dash.openwaf.devAPI de OpenWAF que usa send-events. Tiene que ser https://.
SalidaSignificado
proxyLa URL del proxy, http://127.0.0.1:PUERTO.

Lo que la acción deja al job

VariableValor
HTTPS_PROXY, HTTP_PROXY, https_proxy, http_proxyLa URL del proxy.
NO_PROXY, no_proxylocalhost,127.0.0.1,::1,172.16.0.0/12,.local,.localhost,.test, tu no-proxy y .blob.core.windows.net cuando el bloqueo está activo (la caché de Actions pasa entonces por el proxy transparente, limitada igualmente a las cuentas exactas de GitHub).
EGRESS_CI_STATEEl directorio de estado del sidecar, $RUNNER_TEMP/egress-ci (ahí está el registro de eventos, events.jsonl).
DOCKER_HOST, BUILDX_BUILDERCon el seguimiento de Docker: el socket de Docker del job y el builder del job.
NODE_EXTRA_CA_CERTS, SSL_CERT_FILE, REQUESTS_CA_BUNDLE, CURL_CA_BUNDLE, GIT_SSL_CAINFOCon inspect: la CA de la ejecución, sola o añadida al bundle del sistema.

El sidecar escucha en 127.0.0.1 (y en la dirección del bridge de Docker para los contenedores) en tres puertos por debajo del rango efímero, fijos por usuario del runner: el proxy, el forwarder DNS (el puerto siguiente) y el proxy transparente (el de después).

Decisiones y motivos

Cada conexión, consulta DNS y pull de imagen recibe una decisión: allow, audit (fuera de la política, se deja pasar porque el modo es audit) o block. Una rechazada lleva un motivo:

MotivoPor qué
not_allowedEl nombre, o el puerto para ese nombre, no está en allow.
sni_mismatchUn CONNECT a un nombre permitido llevaba un SNI de TLS de un nombre fuera de la política.
name_ip_mismatchUna conexión nombraba un host permitido pero iba a una dirección que ese nombre no resuelve (domain fronting).
dlpLa petición llevaba un secreto (ver Inspección y DLP).
registry_not_allowedUn pull de imagen de un registry fuera de la política.
private_destinationLoopback, link-local (como la dirección de metadatos de la nube) o multicast, rechazados en los dos modos.

En enforce, el proxy responde 403 con la cabecera X-OpenWAF-Egress: blocked (o dlp), el DNS responde NXDOMAIN, el socket de Docker responde 403 y el resto de conexiones recibe un reset.

El informe

El paso posterior añade el informe al resumen del job e imprime report.json en un grupo del log llamado egress-ci report.json. Contiene nombres, puertos, contadores e ids de detección, nunca cuerpos de peticiones.

Campo de report.jsonSignificado
metaVersión, modo, fichero de política y su SHA-256, estado del bloqueo y de Docker, de dónde salió la lista de GitHub, horas de inicio y fin, los contenedores del job.
destinationsUna entrada por host: ports, via, containers, connections, bytes_up, bytes_down, allowed, blocked, audited, dns_refused, reasons, detections.
blocked, would_block, dns_refused, detections, dns_queriesTotales.
suggested_allowNombres fuera de la política, listos para allow.
image_pullsPulls por el socket del job, con su decisión.
other_containersFlujos de contenedores del runner que no son de este job.
unattributed_addressesFlujos que no son TCP hacia direcciones que ninguna respuesta DNS nombró.

Última actualización:

↑↓ para moverte↵ para abriresc para cerrar