diff --git a/modules/integration/traefik/module.yaml b/modules/integration/traefik/module.yaml new file mode 100644 index 0000000..37d91cd --- /dev/null +++ b/modules/integration/traefik/module.yaml @@ -0,0 +1,201 @@ +# modules/integration/traefik/module.yaml +# yaml-language-server: $schema=../../../cli/resources/module.schema.json +apiVersion: cds/v1alpha1 +kind: Module + +metadata: + name: traefik + category: integration + version: "3.0.0" + displayName: Traefik + description: > + Traefik reverse proxy with TLS 1.2+ enforcement for secure ingress, + service discovery, and centralized certificate management. + +spec: + runtime: + type: container + service: + name: traefik + ports: + - name: http + containerPort: 80 + protocol: TCP + - name: https + containerPort: 443 + protocol: TCP + - name: dashboard + containerPort: 8080 + protocol: TCP + networks: + - default + + configSchema: + type: object + additionalProperties: false + properties: + log: + type: object + default: {} + properties: + level: + type: string + enum: [DEBUG, INFO, WARN, ERROR] + default: INFO + + accessLog: + type: object + default: {} + properties: + enabled: + type: boolean + default: true + + api: + type: object + default: {} + properties: + dashboard: + type: boolean + default: true + debug: + type: boolean + default: false + insecure: + type: boolean + default: false + + entryPoints: + type: object + default: {} + properties: + web: + type: object + properties: + address: + type: string + default: ":80" + websecure: + type: object + properties: + address: + type: string + default: ":443" + + tls: + type: object + default: {} + properties: + minVersion: + type: string + default: VersionTLS12 + maxVersion: + type: string + default: VersionTLS13 + preferServerCipherSuites: + type: boolean + default: true + sniStrict: + type: boolean + default: true + + docker: + type: object + default: {} + properties: + enabled: + type: boolean + default: false + description: > + Enables Traefik's Docker provider for label-based dynamic + routing. Disabled by default: this module does not mount + /var/run/docker.sock (doing so grants root-equivalent access + to the Docker host, negating the container's cap_drop/ + no-new-privileges/read_only hardening). Enabling this option + alone has no effect unless the profile also supplies the + socket (e.g. via a socket proxy) through a Compose override; + prefer fileProvider for dynamic configuration instead. + exposedByDefault: + type: boolean + default: false + + fileProvider: + type: object + default: {} + properties: + directory: + type: string + default: "/etc/traefik/dynamic" + watch: + type: boolean + default: true + + provides: + - name: reverse-proxy + contract: + kind: reverse-proxy + spec: + host: ${service.host} + port: 443 + protocol: https + connectionUri: "https://${service.host}:443" + + implementation: + kind: docker-compose + compose: + services: + traefik: + image: traefik:v3.0@sha256:a208c74fd80a566d4ea376053bff73d31616d7af3f1465a7747b8b89ee34d97e + user: "65532:65532" + init: true + read_only: true + cap_drop: + - ALL + security_opt: + - no-new-privileges:true + pids_limit: 512 + tmpfs: + - /tmp:rw,noexec,nosuid,nodev + + ports: + - "${config.entryPoints.web.address}:80" + - "${config.entryPoints.websecure.address}:443" + - "127.0.0.1:8080:8080" + + networks: + - default + + # No /var/run/docker.sock mount: the Docker provider is disabled + # by default (see docker.enabled above), and mounting the socket + # even read-only would grant root-equivalent host access, + # undermining cap_drop/no-new-privileges/read_only hardening. + volumes: + - ./traefik/dynamic:/etc/traefik/dynamic:ro + - ./certs/traefik:/etc/traefik/certs:ro + - ./data:/data:rw + + environment: + TRAEFIK_LOG_LEVEL: "${config.log.level}" + TRAEFIK_LOG_FILEPATH: "/data/traefik.log" + TRAEFIK_ACCESSLOG: "${config.accessLog.enabled}" + TRAEFIK_ACCESSLOG_FILEPATH: "/data/access.log" + TRAEFIK_API_DASHBOARD: "${config.api.dashboard}" + TRAEFIK_API_DEBUG: "${config.api.debug}" + TRAEFIK_API_INSECURE: "${config.api.insecure}" + TRAEFIK_ENTRYPOINTS_WEB_ADDRESS: "${config.entryPoints.web.address}" + TRAEFIK_ENTRYPOINTS_WEBSECURE_ADDRESS: "${config.entryPoints.websecure.address}" + TRAEFIK_ENTRYPOINTS_WEBSECURE_HTTP_TLS_MINVERSION: "${config.tls.minVersion}" + TRAEFIK_ENTRYPOINTS_WEBSECURE_HTTP_TLS_MAXVERSION: "${config.tls.maxVersion}" + TRAEFIK_ENTRYPOINTS_WEBSECURE_HTTP_TLS_SNISTRICT: "${config.tls.sniStrict}" + TRAEFIK_ENTRYPOINTS_WEBSECURE_HTTP_TLS_PREFERSERVERCIPHERSUITES: "${config.tls.preferServerCipherSuites}" + TRAEFIK_PROVIDERS_DOCKER: "${config.docker.enabled}" + TRAEFIK_PROVIDERS_DOCKER_EXPOSEDBYDEFAULT: "${config.docker.exposedByDefault}" + TRAEFIK_PROVIDERS_DOCKER_NETWORK: "default" + TRAEFIK_PROVIDERS_FILE_DIRECTORY: "${config.fileProvider.directory}" + TRAEFIK_PROVIDERS_FILE_WATCH: "${config.fileProvider.watch}" + + healthcheck: + test: ["CMD", "traefik", "healthcheck", "--ping"] + interval: 10s + timeout: 5s + retries: 3