Cubre la implementación en AWS EKS y OpenShift (ROSA). El flujo de trabajo es
el mismo para ambos: configurar la infraestructura, crear los secretos e
instalar el chart.
Omítala si la autenticación está deshabilitada (solo VPC). Verifique con: aws elasticache describe-replication-groups --query 'ReplicationGroups[].AuthTokenEnabled'
Debe coincidir con el contexto de seguridad del contenedor (vea la nota siguiente)
Nombre de dominio (FQDN)
dojo.example.com
Su administrador de DNS (vea las notas específicas de la plataforma más abajo)
ARN del certificado ACM (EKS con HTTPS)
arn:aws:acm:...
aws acm list-certificates --region <region>
Dominio de apps de OpenShift (solo ROSA)
apps.abc123.p1.openshiftapps.com
oc get ingresses.config.openshift.io cluster -o jsonpath='{.spec.domain}'
fsGroup del namespace de OpenShift (solo ROSA)
1001070000
oc get namespace <ns> -o jsonpath='{.metadata.annotations.openshift\.io/sa\.scc\.supplemental-groups}': use el valor inicial
Archivo de licencia
onprem-dojopro.lic
Proporcionado por el soporte de DefectDojo
Cree las bases de datos antes de instalar. El chart no crea bases de
datos en un servidor PostgreSQL externo. Cree ambas bases de datos
siguientes en su servidor de base de datos, con el usuario de la
aplicación como propietario, antes de ejecutar helm install:
dojodb: la base de datos principal de DefectDojo
dojodb-ddorch: la base de datos del orquestador (ddorch), siempre
nombrada como la base de datos principal con el sufijo -ddorch. Como
alternativa, otorgue al rol de la aplicación el privilegio CREATEDB y
ddorch la creará por sí mismo en el primer arranque.
UID/GID del punto de acceso de EFS: Si su sistema de archivos EFS usa
un punto de acceso, su configuración de usuario POSIX debe usar UID
1001 y GID 1337 para coincidir con el contexto de seguridad del
contenedor de DefectDojo. Una discrepancia provoca errores de Permission denied durante la inicialización, cuando los contenedores intentan crear
los subdirectorios de medios. Verifíquelo con:
FQDN de OpenShift/ROSA: En ROSA, las Routes generan automáticamente
nombres de host con el patrón <release-name>-<namespace>.apps.<cluster-domain>.
Por ejemplo, si su release es dojopro en el namespace dojopro, el nombre
de host de la Route será dojopro-dojopro.apps.abc123.p1.openshiftapps.com.
Determine el dominio de apps de su clúster con:
oc get ingresses.config.openshift.io cluster -o jsonpath='{.spec.domain}'
Use el FQDN resultante para dojo.fqdn, dojo.url y dojo.hosts.main.
fsGroup de OpenShift/ROSA: Necesitará el valor inicial de
supplemental-groups de su namespace para securityContext.openshift.fsGroup.
Búsquelo ahora para evitar tener que editar su archivo de valores más
adelante:
oc get namespace <your-namespace> \
-o jsonpath='{.metadata.annotations.openshift\.io/sa\.scc\.supplemental-groups}'# Output example: 1001070000/10000 — use 1001070000 as fsGroup
Los siguientes secretos deben generarse de forma nueva para su
implementación. Use los comandos indicados para crear valores
criptográficamente aleatorios:
Consejo: copie secrets-template.yaml y complete los valores
anteriores. Consulte Generar secretos para obtener
instrucciones detalladas sobre cómo crear el Secret de Kubernetes.
En entornos de red restringidos, deben permitirse las siguientes conexiones
salientes antes de la instalación. Las reglas de firewall pueden requerir
solicitudes de cambio con antelación; verifique que estén implementadas antes
de continuar.
Registro de contenedores (obligatorio)
Todos los nodos del clúster deben poder alcanzar el registro de contenedores
de DefectDojo por el puerto 443:
host us-south1-docker.pkg.dev
# us-south1-docker.pkg.dev is an alias for googlecode.l.googleusercontent.com
Nodos del clúster hacia su instancia de PostgreSQL, normalmente por el
puerto 5432.
RDS en la misma VPC: asegúrese de que el grupo de seguridad de los nodos de
EKS tenga permitido el tráfico entrante por el puerto 5432
RDS en una VPC o cuenta diferente: se requiere VPC peering o Transit
Gateway
Externo/local: la ruta de VPN o Direct Connect debe permitir el puerto
5432
Actualizaciones de EPSS (recomendado)
host api.first.org
# api.first.org has address 151.101.1.91
# api.first.org has address 151.101.193.91
# api.first.org has address 151.101.129.91
# api.first.org has address 151.101.65.91
# Port 443
Fuente de KEV (recomendado)
https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json
host www.cisa.gov
# www.cisa.gov is an alias for www.cisa.gov.edgekey.net (Akamai CDN — IPs vary)
# Port 443
Servicios de AWS (solo EKS, obligatorio)
El controlador EBS CSI y el ALB Controller requieren acceso a los endpoints
de la API de AWS por el puerto 443:
Controlador EFS CSI (obligatorio si usa almacenamiento EFS, el backend de
almacenamiento recomendado para implementaciones EKS con múltiples
réplicas):
El chart se distribuye como un zip que contiene un paquete Helm .tgz.
Extraiga ambos antes de continuar. Use una ruta de extracción con versión
para evitar sobrescribir silenciosamente los presets cuando extraiga una
versión más reciente del chart más adelante:
unzip helm-chart-<version>.zip -d /tmp/dojopro-extract
cd /tmp/dojopro-extract
mkdir -p dojopro-<version>
tar -xzf dojopro-<version>.tgz -C dojopro-<version>/
Defina una variable CHART que apunte al directorio del chart extraído.
Todos los comandos helm posteriores en esta guía usan $CHART:
CHART="dojopro-<version>/dojopro"# e.g. CHART="dojopro-2.55.4/dojopro"
Por qué la extracción es necesaria para los usuarios de la CLI: los
archivos de presets (presets/platforms/*.yaml, presets/profiles/*.yaml)
vienen incluidos dentro del paquete .tgz. helm install -f requiere
archivos en el sistema de archivos local: no puede leer archivos desde
dentro de un .tgz empaquetado. Debe extraer el chart para acceder a los
presets.
Los usuarios de ArgoCD no necesitan extraer nada. ArgoCD lee
valueFiles directamente desde dentro del paquete del chart. Consulte
Implementar con ArgoCD.
La plantilla de configuración del cliente (template.yaml) y la plantilla de
secretos (secrets-template.yaml) están disponibles por separado en el
portal de soporte de DefectDojo, o solicitándolas a support@defectdojo.com.
No se incluyen en el .tgz del chart. Una vez que tenga la plantilla,
cópiela y complete sus datos:
cp template.yaml my-company.yaml
Como mínimo, configure lo siguiente:
Configuración
Descripción
dojo.fqdn
Su nombre de dominio (ROSA: consulte la nota sobre FQDN anterior)
dojo.url
URL completa, incluido el protocolo (por ejemplo, https://dojo.example.com)
dojo.hosts.main
Debe coincidir con su FQDN
dojo.secureCookies
Configúrelo como false en OpenShift/ROSA (vea la advertencia siguiente)
dojo.admin.*
user, email, firstName, lastName: cuenta de administrador
database.host, .port, .name, .user
Datos de conexión de PostgreSQL (la contraseña va en los secretos)
celery.broker.host
Su endpoint de Redis/ElastiCache
redis.enabled
Debe ser false si usa un Redis externo (vea la advertencia siguiente)
storage.type
Backend de almacenamiento; consulte las notas específicas de la plataforma
certificates.*
Configuración de certificados TLS
django.ingress.* o django.route.*
Ingress (EKS) o Route (OpenShift); el preset define los valores predeterminados
securityContext.openshift.fsGroup
Solo ROSA: valor inicial de supplemental-groups del namespace
ADVERTENCIA:redis.enabled debe configurarse explícitamente como
false cuando se usa un Redis/ElastiCache externo. Los presets de perfil
standard y performance configuran redis.enabled: true de forma
predeterminada. Si su archivo de valores no anula esto, el chart
implementará un Redis dentro del clúster junto con su broker externo,
lo que da como resultado una configuración incorrecta. Agregue esto a su
archivo de valores:
redis:enabled:false
ADVERTENCIA:dojo.secureCookies debe ser false en OpenShift/ROSA.
Al usar Routes de OpenShift con terminación TLS en el borde (edge),
secureCookies: true (el valor predeterminado en template.yaml) provoca
bucles de redirección y fallos de inicio de sesión. Esto no es opcional:
las Routes con terminación en el borde requieren:
dojo:secureCookies:false
Notas sobre almacenamiento:
EKS: use EFS, no EBS. Los volúmenes EBS no se pueden compartir entre
nodos, lo que provoca errores de Multi-Attach. Consulte Problemas
conocidos. Si su EFS usa un punto de
acceso, configure también storage.efs.accessPointId; consulte Puntos de
acceso de EFS.
OpenShift/ROSA: el preset de la plataforma usa de forma predeterminada
storage.type: "pvc" con createNew: true, lo que utiliza el
StorageClass predeterminado del clúster. Para implementaciones con varios
nodos, use NFS a través de EFS (storage.type: "nfs").
De manera opcional, configure el nivel de detalle de los registros:
config.logLevel: nivel de registro de la aplicación Django (valor
predeterminado: "INFO")
celery.logLevel: nivel de registro del worker/beat de Celery (valor
predeterminado: "INFO")
Configure cualquiera de los dos como "DEBUG" para solucionar problemas.
Consulte Nivel de detalle de los registros para saber cómo
activarlo en tiempo de ejecución sin editar su archivo de valores.
No coloque secretos ni el contenido de la licencia en este archivo. Estos se
tratan en las dos secciones siguientes.
Consulte template.yaml para ver la lista completa de opciones.
Verificación previa: comprobar la conectividad de la base de datos#
Confirme que su base de datos sea accesible antes de continuar; esto
ahorrará bastante tiempo de resolución de problemas más adelante. Cree un
pod temporal con psql:
version
--------------------------------------------------------------------------------------------------------
PostgreSQL 16.x on x86_64-pc-linux-gnu, compiled by gcc ...
(1 row)
pod "psql-test" deleted
Si esto falla con database "dojodb" does not exist, su instancia de RDS es
accesible, pero la base de datos aún no se ha creado. Créela:
Luego vuelva a ejecutar la comprobación de conectividad anterior para
confirmarlo.
Si falla por otros motivos, revise lo siguiente:
Reglas de grupo de seguridad/firewall: el puerto 5432 debe estar
abierto desde el clúster hacia el host de la base de datos
Privilegios del usuario de la base de datos: el usuario debe tener
permisos CREATE, ALTER y SELECT en la base de datos de destino, además de
CREATEDB o una base de datos del orquestador creada previamente (vea la
siguiente sección)
El chart también incluye comprobaciones integradas: un init container que
espera la conectividad TCP con la base de datos, y helm test, que valida
una conexión completa a PostgreSQL después de la implementación. Este paso
de verificación previa detecta problemas antes de que invierta tiempo
creando secretos y ejecutando helm install.
Verificación previa: base de datos del orquestador (ddorch)#
El orquestador (ddorch, habilitado de forma predeterminada) almacena su
estado de flujo de trabajo en una segunda base de datos, junto a la base
de datos principal de DefectDojo. Al iniciar, toma el nombre de la base de
datos de DD_DATABASE_URL, le agrega -ddorch y crea esa base de datos si
no existe; si la base de datos principal es dojodb, el orquestador usa
dojodb-ddorch.
Si al rol de la aplicación no se le permite crear bases de datos, el pod de
ddorch falla al iniciar con:
ERROR: permission denied to create database (SQLSTATE 42501)
Cumpla con una de las siguientes opciones antes de instalar:
Opción A: otorgue CREATEDB al rol de la aplicación y deje que ddorch
cree su base de datos en el primer arranque:
ALTERROLEdefectdojoCREATEDB;
Opción B: cree previamente la base de datos del orquestador, con el
nombre de su base de datos principal más el sufijo -ddorch, y con el mismo
usuario de la aplicación como propietario. El guion en el nombre requiere
comillas dobles en SQL:
CREATEDATABASE"dojodb-ddorch"OWNERdefectdojo;
Usando el mismo enfoque de pod temporal que en la comprobación de
conectividad anterior:
Opción A: Secret externo (recomendado para GitOps)#
Cree un Secret de Kubernetes con las 12 claves requeridas antes de instalar
el chart. Use secrets-template.yaml, proporcionado por el soporte de
DefectDojo, como punto de partida (consulte Prepare su archivo de
valores para saber cómo obtenerlo):
El secret también puede administrarse con External Secrets Operator, Sealed
Secrets o cualquier otra herramienta que cree Secrets de Kubernetes. Al
chart no le importa cómo llegó el secret; solo configure dojo.existingSecret
con su nombre.
En el momento de la instalación:
--set dojo.existingSecret=dojopro-secrets
El chart omite automáticamente la generación de su Secret integrado cuando
se configura dojo.existingSecret; no se necesitan indicadores adicionales.
Si su Redis externo requiere autenticación, secrets-template.yaml también
incluye un Secret dojopro-redis independiente. El chart lee las
credenciales de Redis desde redis.auth.existingSecret (valor
predeterminado: dojopro-redis). Si su Redis no tiene contraseña (por
ejemplo, un ElastiCache solo de VPC), puede omitirlo.
Opción B: secretos en línea (más simple, no apto para GitOps)#
Pase los valores de los secretos directamente en un archivo de valores:
dojo:secretKey:""# openssl rand -hex 25credentialAES256Key:""# openssl rand -hex 16cloudPortalSecretKey:""# openssl rand -hex 25connectorsSharedSecret:""# openssl rand -hex 25 (or reuse cloudPortalSecretKey)admin:password:""# openssl rand -base64 16emailUrl:"consolemail://"proEnhancementsEpssBucketKey:""# leave empty if not using EPSSdatabase:password:""# your PostgreSQL passwordredis:auth:password:""# your Redis password (omit if Redis has no auth)monitoring:password:""# openssl rand -hex 16
Guarde esto como my-secrets.yaml y páselo con -f en el momento de la
instalación.
No incluya archivos de secretos en el control de versiones.
El chart necesita certificados TLS internos para la comunicación entre
servicios.
Cree dos secrets TLS de Kubernetes en su namespace antes de instalar:
dojopro-internal-tls: un secret TLS con tls.crt y tls.key para el
cifrado entre servicios (nginx ↔ connectors, etc.)
dojopro-internal-ca: un secret que contiene el certificado de la CA
bajo la clave ca.crt, usado por los connectors para validar el
certificado TLS interno
Puede generar una CA y un certificado de servidor autofirmados con
openssl, o usar la CA interna de su organización. El CN/SAN del
certificado del servidor debe cubrir el nombre del servicio nginx
interno usado por el release de Helm. De forma predeterminada, este es
<release-name>-nginx (por ejemplo, dojopro-nginx si su release se llama
dojopro).
Ejemplo de generación de una CA y un certificado de servidor autofirmados:
RELEASE_NAME="dojopro"NAMESPACE="dojopro"# Generate CA# basicConstraints + keyUsage MUST be set explicitly. Without them the CA may# be rejected as not a valid CA (e.g. "x509: certificate signed by unknown# authority" / missing keyUsage) depending on your local openssl defaults.openssl req -x509 -newkey rsa:2048 -keyout ca.key -out ca.crt \
-days 365 -nodes -subj "/CN=${RELEASE_NAME}-internal-ca"\
-addext "basicConstraints=critical,CA:TRUE"\
-addext "keyUsage=critical,digitalSignature,keyCertSign,cRLSign"# Generate server cert with correct SANs and usage extensionsopenssl req -newkey rsa:2048 -keyout server.key -out server.csr -nodes \
-subj "/CN=${RELEASE_NAME}-nginx"\
-addext "subjectAltName=DNS:${RELEASE_NAME}-nginx,DNS:${RELEASE_NAME}-nginx.${NAMESPACE}.svc.cluster.local"\
-addext "basicConstraints=critical,CA:FALSE"\
-addext "keyUsage=critical,digitalSignature,keyEncipherment"\
-addext "extendedKeyUsage=serverAuth,clientAuth"openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out server.crt -days 365 -copy_extensions copyall
# Create the Kubernetes secretskubectl create secret tls dojopro-internal-tls \
--cert=server.crt --key=server.key \
-n $NAMESPACEkubectl create secret generic dojopro-internal-ca \
--from-file=ca.crt=ca.crt \
-n $NAMESPACE
Error común: usar nginx-internal como CN/SAN en lugar de
<release-name>-nginx. El pod de connectors valida el certificado TLS
contra el nombre de servicio real
(<release-name>-nginx.<namespace>.svc.cluster.local), y fallará con un
error x509: certificate is valid for ... not ... si el SAN no coincide.
Además de los secrets TLS internos anteriores, el orquestador ddorch
requiere un trío de certificados mTLS independiente, usado por el servidor
ddorch y por cada worker que se comunica con él (ddorch-workers,
integrators). Estos se entregan al chart en el momento de la instalación
mediante --set-file (no se leen de un secret de Kubernetes
preexistente):
orch_tls_root.ca: certificado de la CA
orch_tls.crt: certificado del servidor
orch_tls.key: clave privada del servidor
Sin estos tres archivos, helm install falla con
ddorch.tls.rootCa is required.
El SAN del certificado del servidor debe incluir todos los nombres de
host que los workers usan para llegar a ddorch:
ddorch: nombre corto del servicio dentro del clúster
<release-name>-ddorch: nombre de servicio completo (por ejemplo,
dojopro-ddorch)
<release-name>-ddorch.<namespace>.svc.cluster.local: FQDN del clúster
nginx: el SERVER_TLS_SERVER_NAME predeterminado usado por los workers
de tipo hatchet
localhost, 127.0.0.1: workers en el mismo pod que llegan a ddorch a
través del loopback de hostAlias
Ejemplo de generación del trío:
RELEASE_NAME="dojopro"NAMESPACE="dojopro"# ddorch CA# As with the internal CA, set basicConstraints + keyUsage explicitly so the# generated cert is a valid signing CA regardless of local openssl defaults.openssl req -x509 -newkey rsa:2048 -keyout orch_ca.key -out orch_ca.crt \
-days 365 -nodes -subj "/CN=${RELEASE_NAME}-ddorch-ca"\
-addext "basicConstraints=critical,CA:TRUE"\
-addext "keyUsage=critical,digitalSignature,keyCertSign,cRLSign"# ddorch server certopenssl req -newkey rsa:2048 -keyout orch_server.key -out orch_server.csr -nodes \
-subj "/CN=ddorch"\
-addext "subjectAltName=DNS:ddorch,DNS:${RELEASE_NAME}-ddorch,DNS:${RELEASE_NAME}-ddorch.${NAMESPACE}.svc.cluster.local,DNS:nginx,DNS:localhost,IP:127.0.0.1"\
-addext "basicConstraints=critical,CA:FALSE"\
-addext "keyUsage=critical,digitalSignature,keyEncipherment"\
-addext "extendedKeyUsage=serverAuth,clientAuth"openssl x509 -req -in orch_server.csr -CA orch_ca.crt -CAkey orch_ca.key \
-CAcreateserial -out orch_server.crt -days 365 -copy_extensions copyall
El script auxiliar scripts/bootstrap-aws-eks.sh genera y reutiliza estos
certificados automáticamente mediante dojopro-orch-certs-configmap; si
usa ese script, no necesita crearlos manualmente.
Antes de implementar, verifique que su licencia sea válida y no haya
expirado:
sed -n '/^[[:space:]]*ey/,/-----END/p' license.lic \
| sed '$d'| tr -d ' '| base64 -d | jq .
Esto muestra los metadatos de la licencia, incluidos:
not_after: fecha de vencimiento de la licencia
license_package: confirma su nivel
Secretos de extracción de imágenes: cuando se configura
images.pullSecrets.extractFromLicense: true (el valor predeterminado en
los presets de plataforma), el chart extrae automáticamente la cuenta de
servicio de GCP incrustada en su archivo de licencia y crea el secret de
extracción de imágenes necesario para obtener las imágenes de DefectDojo
del registro de contenedores. No se requiere extracción ni decodificación
manual. Si en cambio usa un registro privado, configure
extractFromLicense: false y proporcione su propio secret de extracción;
consulte Registro privado/entornos aislados.
Opción 1: –set-file (instalación estándar de Helm)#
Pase el archivo de licencia en el momento de la instalación:
Cree un Secret de Kubernetes que contenga la licencia y luego indíquele al
chart que lo use. Esto evita tener que usar --set-file o almacenar la
licencia en git.
Luego, en su archivo de valores o en las opciones de helm:
license:existingSecret:"dojopro-license"
El secret puede administrarse con External Secrets Operator, Sealed
Secrets o kubectl simple.
Importante:license.existingSecretno es compatible con la
configuración predeterminada images.pullSecrets.extractFromLicense: true.
El chart necesita que el contenido de la licencia esté disponible en el
momento de la generación (render) para extraer las credenciales del
registro de contenedores incrustadas. Si usa license.existingSecret,
también debe deshabilitar la extracción automática del secret de
extracción de imágenes y proporcionar el suyo propio:
Si desea que el chart extraiga automáticamente los secretos de extracción
a partir de la licencia (el valor predeterminado), use en su lugar la
Opción 1 (--set-file license.contents=).
Para entornos sujetos a FedRAMP SC-13 o similares, el chart puede
implementar las variantes de imagen -fips, cuya criptografía se realiza
mediante el OpenSSL FIPS Provider 3.1.2 (certificado CMVP del NIST
n.º 4985) y, para los servicios en Go, el Go Cryptographic Module
v1.0.0 (CMVP n.º 5247).
La aplicación de esta política ocurre dentro del contenedor, por lo que no
se requiere un kernel de host habilitado para FIPS; esto es lo que hace que
sea viable en runtimes administrados donde el sistema operativo del host no
está bajo su control.
Deshabilitado de forma predeterminada; la salida generada no cambia cuando
está desactivado.
fips:enabled:truevalidate:true# refuse to render a partly-FIPS deployment (see below)
Las imágenes con la etiqueta -fips deben estar disponibles en su
registro. Póngase en contacto con hello@defectdojo.com para obtener acceso.
Sensei y el PostgreSQL/Redis integrados no tienen una compilación FIPS:
la imagen de valkey incluida está basada en Alpine, que no cuenta con
OpenSSL validado para FIPS. Por lo tanto, una instalación FIPS debe usar
almacenes de datos externos y dejar Sensei deshabilitado:
fips:enabled:truesensei:enabled:falsepostgresql:enabled:false# point at an external FIPS-compliant databaseredis:enabled:false# point at an external FIPS-compliant cache
Con fips.validate: true (el valor predeterminado), el chart falla al
generarse si habilita FIPS junto con cualquiera de ellos, indicando los
componentes responsables:
Error: fips.enabled is true but these services have no FIPS image variant:
sensei, redis (embedded). Disable them, or set fips.validate=false to accept
that they run non-validated cryptography.
Esto es intencional. Una implementación en la que la mayoría de los
servicios usan criptografía validada, y uno o dos no lo hacen de forma
silenciosa, es peor que un fallo evidente: parece conforme y solo se
descubre durante una evaluación. Configure fips.validate: false únicamente
si ha aceptado ese riesgo de forma explícita.
Cada pod ejecuta una comprobación de inicio de tipo fail-closed: si el
proveedor validado no está activo, el contenedor se cierra en lugar de
servir tráfico. La evidencia que imprime suele ser lo que un evaluador
necesita:
Los cambios de comportamiento a tener en cuenta (el hash de contraseñas pasa
a PBKDF2, ChaCha20 se elimina de la lista de cifrados TLS) se describen en
la página del Modo FIPS 140-3 de la documentación del producto.
Antes de instalar, ejecute helm template para renderizar y validar todos los manifiestos
sin tocar el clúster. Esto detecta errores de valores, campos obligatorios
faltantes y problemas de YAML antes de comprometerse con helm install:
Use las mismas opciones que planea pasar a helm install. Si esto finaliza sin errores,
sus valores son válidos. Si falla, el mensaje de error identificará el campo faltante
o inválido; corrija su archivo de valores y vuelva a ejecutarlo hasta que pase.
Se recomienda encarecidamente usar HTTPS para el acceso desde el navegador en EKS.
Cuando el TLS de ingress está activo, el chart habilita automáticamente
SECURE_SSL_REDIRECT y establece las cookies de CSRF/sesión como Secure, lo que
significa que el inicio de sesión desde el navegador fallará sin un listener HTTPS en el ALB.
Configure un certificado ACM antes de implementar para obtener la mejor experiencia.
Consistencia del namespace: el valor del namespace debe coincidir en todos los
recursos: su YAML de secretos (metadata.namespace), kubectl create namespace
y helm install -n. Si usa un namespace personalizado en lugar de dojopro,
reemplácelo de forma consistente en todos los comandos y manifiestos de secretos.
Secretos externos + secreto de licencia (GitOps):
Aplique sus secretos si aún no lo ha hecho (consulte Generar secretos),
luego instale:
Advertencia: ejecutar sin HTTPS significa que las cookies de sesión se envían en
texto plano y la protección CSRF mediante cookies seguras queda deshabilitada. No use
esta configuración en producción.
Si necesita implementar sin HTTPS temporalmente (por ejemplo, para pruebas iniciales sin
un certificado ACM), aplique todos los siguientes cambios en su archivo de valores:
dojo:url:"http://dojo.example.com"# must be http://, not https://secureCookies:false# disable Secure flag on session/CSRF cookiesdjango:ingress:tls:enabled:falseannotations:# HTTP-only listener — remove the HTTPS listener entirelyalb.ingress.kubernetes.io/listen-ports:'[{"HTTP": 80}]'# Do NOT include the ssl-redirect annotation — it causes a redirect# loop when no HTTPS listener exists (see BUG-17 in Known Issues)# alb.ingress.kubernetes.io/ssl-redirect: "443" # REMOVE this line
Los cuatro cambios son obligatorios. Si falta alguno, se producirán bucles de
redirección o fallos en el inicio de sesión. Cuando esté listo para habilitar HTTPS,
revierta estos cambios y configure un certificado ACM.
oc get namespace $NAMESPACE\
-o jsonpath='{.metadata.annotations.openshift\.io/sa\.scc\.supplemental-groups}'# Use the start value (e.g., 1001070000) as securityContext.openshift.fsGroup
Secretos externos + secreto de licencia (GitOps):
Aplique sus secretos si aún no lo ha hecho (consulte Generar secretos),
luego instale:
DefectDojo Pro es totalmente compatible con ArgoCD. El chart incluye presets de
plataforma y de perfil que ArgoCD puede referenciar directamente como valueFiles.
El material de mTLS de ddorch (consulte Certificados mTLS de ddorch). ArgoCD no tiene un equivalente de --set-file, así que pase el contenido de los tres PEM mediante parámetros de la Application (ddorch.tls.rootCa / ddorch.tls.cert / ddorch.tls.key). Use un plugin de gestión de secretos de ArgoCD (Sealed Secrets, External Secrets o un plugin de ConfigMap) en lugar de confirmar la clave en texto plano.
ArgoCD referencia los archivos de preset de forma relativa a la raíz del chart. Su
especificación de Application necesita tres cosas:
Los presets de plataforma y de perfil como valueFiles
Su configuración específica del entorno (mediante valueFiles, values en línea, o ambos)
Las referencias de secreto y licencia como parameters
helm:valueFiles:- presets/platforms/aws-eks.yaml # or openshift- presets/profiles/standard.yaml # or minimal, performancevalues:| # Your environment-specific configuration goes here.
# This is applied last and overrides the presets above.
dojo:
fqdn: dojo.example.com
admin:
user: admin
email: admin@example.com
database:
host: your-db-host.example.com
# ... see template.yaml for all optionsparameters:- name:dojo.existingSecretvalue:dojopro-secrets- name:license.existingSecretvalue:dojopro-license
Hay varias formas de proporcionar sus valores específicos del entorno a ArgoCD:
values en línea en la especificación de la Application: el enfoque más simple, sin
necesidad de archivos ni repositorios adicionales. Funciona bien cuando su configuración
es sencilla.
Un archivo de valores en un repositorio git separado: use la función multi-source de
ArgoCD (v2.6+) con una variable $ref para extraer su archivo de valores junto con el chart.
Recomendado cuando se usa un chart publicado en OCI.
Un archivo de valores en el mismo repositorio git que el chart: referéncielo en
valueFiles con una ruta relativa al directorio del chart
(por ejemplo, ../../overrides/customers/my-company.yaml).
Los tres enfoques siguen la misma estratificación: preset de plataforma → preset de
perfil → su configuración. Los valores posteriores anulan a los anteriores.
Cuando el chart se publica en un registro OCI, actualizar es un único cambio en
targetRevision dentro de su especificación de Application. Los presets de plataforma y
de perfil están versionados junto con el chart, por lo que se actualizan automáticamente.
Para obtener información completa sobre la compatibilidad de ArgoCD con Helm, consulte la
documentación de ArgoCD Helm.
# Check the initializer job completed successfully (required for first install)kubectl get jobs -n $NAMESPACE# The initializer job must show 1/1 COMPLETIONS. If it shows 0/1, the# database migrations did not run and the application will not work.# Check its logs:# kubectl logs -n $NAMESPACE -l app.kubernetes.io/component=initializer# To retry: delete the failed job and run helm upgrade with the same flags:# kubectl delete job -n $NAMESPACE -l app.kubernetes.io/component=initializer# helm upgrade dojopro <chart> ... (same flags as install)# Check all pods are runningkubectl get pods -n $NAMESPACE# Expected components (chart 2.57+): django, celery-worker, celery-beat,# connectors, nginx, ddorch, ddorch-workers, integrators, mcp-server, plus# redis and postgresql if you are using the bundled copies, plus psirt and# sensei if you enabled them (psirt.enabled, sensei.enabled).# Note: ddorch-workers replaces the legacy kairos, rulesengine, and# hatchet-integrators workers.# Check ingress (EKS) or route (OpenShift)kubectl get ingress -n $NAMESPACE# EKSoc get route -n $NAMESPACE# OpenShift# Run built-in helm testshelm test dojopro -n $NAMESPACE --logs --timeout 5m
# Health check# EKS (use https:// if TLS is configured, http:// otherwise):ALB=$(kubectl get ingress -n $NAMESPACE -o jsonpath='{.items[0].status.loadBalancer.ingress[0].hostname}')curl -sk "https://${ALB}/api/v2/health_check/light/"# or for HTTP-only deployments:# curl -s "http://${ALB}/api/v2/health_check/light/"# OpenShift:ROUTE=$(oc get route -n $NAMESPACE -o jsonpath='{.items[0].spec.host}')curl -sk "https://${ROUTE}/api/v2/health_check/light/"
El chart incluye cuatro tests que se ejecutan como pods de Kubernetes al ejecutar
helm test. Validan los puntos de integración críticos entre DefectDojo
y sus servicios de respaldo:
Test
Qué verifica
test-database
Se conecta a PostgreSQL usando las credenciales configuradas, ejecuta SELECT version(), y confirma que la base de datos acepta consultas. Reintenta durante hasta 60 segundos.
test-redis-broker
Se conecta al broker Redis/Valkey, envía un PING, y luego realiza un ciclo de set/get/delete para verificar el acceso de lectura y escritura.
test-django-health
Consulta el endpoint /api/v2/health_check/light/ en el servicio nginx interno y confirma una respuesta HTTP 2xx/3xx. Se ejecuta después de los tests de base de datos y broker (hook-weight 10).
test-storage
Monta el volumen de medios y realiza un ciclo de escritura/lectura/eliminación para confirmar que el backend de almacenamiento es accesible y que la aplicación puede escribir en él. Se ejecuta al final (hook-weight 15).
Los tests se ejecutan en orden según hook-weight: primero los tests de
infraestructura (base de datos, broker), luego los tests a nivel de aplicación
(salud, almacenamiento). Si un test anterior falla, los tests posteriores pueden
seguir ejecutándose, pero es probable que también fallen.
Para volver a ejecutar los tests después de una implementación fallida o un cambio de
configuración:
helm test dojopro -n $NAMESPACE --logs --timeout 5m
Los pods de test se limpian automáticamente antes de cada ejecución
(política de eliminación before-hook-creation). Para inspeccionar manualmente los
logs de un pod de test fallido:
Inicie sesión en su URL configurada con el nombre de usuario administrador
(predeterminado: admin) y esta contraseña. Cambie la contraseña después del
primer inicio de sesión.
El chart expone dos ajustes de nivel de log, ambos con valor predeterminado INFO:
Ajuste
Controla
Variable de entorno
config.logLevel
Logging de la aplicación Django
DD_LOG_LEVEL
celery.logLevel
Logging del worker y del beat de Celery
DD_CELERY_LOG_LEVEL
Para aumentar el nivel de detalle con fines de resolución de problemas, establezca
uno o ambos en DEBUG en su archivo de valores y ejecute helm upgrade:
Las opciones --set anulan la configuración del archivo de valores, por lo que
puede activar y desactivar el logging de depuración sin editar archivos. Una vez
resuelto el problema, ejecute helm upgrade nuevamente sin las opciones --set
para volver a sus valores predeterminados configurados.
El deployment de Django también admite django.uwsgi.enableDebug: true, que
establece DD_DEBUG=True para depuración de bajo nivel del framework. Esto produce
una cantidad de salida significativamente mayor y solo debe usarse para
investigaciones breves.
Las importaciones de escaneos (/api/v2/import-scan/ y /api/v2/reimport-scan/) se
analizan de forma síncrona y pueden consumir grandes cantidades de memoria del worker.
De forma predeterminada, el chart ejecuta un deployment dedicado django-import
(uwsgi en el puerto 3032 detrás de su propio Service) y el nginx del pod de Django
enruta los endpoints de importación hacia él.
Una importación pesada no puede agotar (ni causar un OOM en) los workers web
interactivos, y el pool de importadores (escritores) escala de forma independiente
de los pods web (lectores).
Parámetros ajustables bajo django.uwsgiImport:
django:uwsgiImport:enabled:true# false routes imports back to the main uwsgi poolreplicas:2# importer pods (ignored when autoscaling is on)maxBodySizeMb:null# client_max_body_size on the import routes; null# derives dojo.scanMaxFileSize + 5 (multipart# overhead), so raising scanMaxFileSize just works.# Set an integer to override.performance:processes:2# concurrent imports per pod = processes x threadsthreads:4resources:requests:cpu:"100m"memory:"512Mi"limits:memory:"4Gi"terminationGracePeriodSeconds:60# raise toward 1800 to let in-flight# imports finish on rollouts/drainsautoscaling:enabled:false# scale importers on their own CPU signalhorizontalpodautoscaler:minReplicas:2maxReplicas:5averageUtilization:60
Notas operativas:
Los pods importadores montan el volumen de medios compartido, por lo que necesitan
almacenamiento con capacidad ReadWriteMany para poder programarse libremente entre
nodos. Los backends de almacenamiento del chart (efs, filestore, gcsfuse,
nfs, y el PVC de medios RWX predeterminado) cumplen este requisito; un PVC
ReadWriteOnce no lo cumple.
El autoescalado de importadores está desactivado de forma predeterminada porque un
escalado hacia abajo desaloja la importación que ese pod esté ejecutando en cuanto
vence terminationGracePeriodSeconds.
Si lo habilita, aumente el período de gracia para que las importaciones en curso
puedan finalizar.
Un PodDisruptionBudget (podDisruptionBudget.djangoImport) protege el pool de
importadores durante interrupciones voluntarias siempre que se ejecute más de un
importador.
El perfil minimal deshabilita el deployment de importadores para mantener la huella
reducida; en ese caso, las importaciones comparten el pool uwsgi único como antes.
El chart puede implementar el PSIRT Advisory Engine, un servicio para redactar y
publicar asesorías de seguridad a partir de los hallazgos de DefectDojo. Está
desactivado de forma predeterminada.
Cuando está habilitado, aparece bajo /psirt/ en su host principal de DefectDojo;
el sidecar de nginx lo expone mediante proxy, por lo que no se necesita ingress
ni entrada DNS adicional.
psirt:enabled:true# REQUIRED: full async connection URL. Use a dedicated database (its# migrations must not share DefectDojo's database).databaseUrl:"postgresql+asyncpg://pae:<password>@<host>:5432/pae"# Pre-shared secret for autonomous advisory publishing. The scheduler sends# it to DefectDojo as an X-Psirt-Secret header (no minted token, no UI step);# the chart injects the SAME value into the DefectDojo pods so they accept it.# Optional — omit to disable autonomous publishing (the pod still boots).psirtSharedSecret:"<high-entropy secret>"# Strongly recommended: pin both secrets. Left empty they are re-generated# on every helm upgrade, which logs out active sessions and invalidates# stored DefectDojo tokens.sessionSecretKey:""# any 64-character stringfernetSaltB64:""# python -c "import secrets; print(secrets.token_urlsafe(32))"
psirtSharedSecret es un valor simple que usted elige; no interviene ningún usuario
de DefectDojo ni token generado. Establezca una cadena de alta entropía (por ejemplo,
python -c "import secrets; print(secrets.token_urlsafe(48))"). El chart la integra
tanto en el Secret del motor psirt como en los pods de DefectDojo, de modo que un
solo valor habilita la publicación autónoma en una instalación nueva sin ningún paso
posterior al arranque. Rotación: cámbielo y ejecute helm upgrade.
Configuración de la base de datos: apunte databaseUrl al mismo host de PostgreSQL
que usa DefectDojo (o a cualquier otro host accesible) con un nombre de base de
datos de su elección. El pod crea la base de datos en el primer inicio si no
existe, lo cual requiere una concesión única como superusuario de postgres:
ALTERROLEpaeCREATEDB;
Notas operativas:
Mantenga psirt.replicas en 1. El servicio ejecuta su propio planificador de
tareas interno, y una segunda réplica ejecutaría cada tarea programada dos veces.
El pod monta el volumen de medios compartido (los adjuntos de asesorías se
guardan bajo <media>/pae/uploads), por lo que aplican las mismas indicaciones
de almacenamiento ReadWriteMany que para el pool de importadores.
Se requiere HTTPS saliente para los feeds de asesorías y las consultas a NVD.
Con networkPolicy.profile=aggressive, la lista de CIDR permitidos
(networkPolicy.externalAPIs.allowedCidrs) debe cubrir esos endpoints.
Un psirt.nvdApiKey opcional eleva el límite de tasa de NVD de 5 a 50
solicitudes por 30 segundos.
El chart puede implementar el motor Sensei, el servicio detrás de las tareas de
escaneo del lado del servidor y de corrección automática (fix). Está desactivado
de forma predeterminada y no necesita configuración adicional para arrancar:
sensei:enabled:true
El motor no conserva secretos de larga duración. Las credenciales de escaneo/corrección
y las URL de endpoint viajan con cada tarea, despachadas desde la configuración cifrada
de workers de DefectDojo.
django y celery alcanzan al motor dentro del clúster (SENSEI_ENGINE_URL se integra
automáticamente en el configmap compartido), por lo que no se necesita ingress ni
entrada DNS.
Notas operativas:
El motor llama de vuelta a DefectDojo en la URL pública de su sitio (dojo.url)
de forma predeterminada. Establezca sensei.ddCallbackUrl para anularlo; para
tráfico puramente dentro del clúster, apúntelo al listener interno de nginx, pero
entonces el motor debe confiar en la CA interna de DefectDojo.
Las credenciales de LLM para las tareas de corrección normalmente se configuran
dentro de la aplicación (Configuración de modelo de IA) y se transportan por cada
tarea. Establezca sensei.llm.* solo cuando el motor deba leer la clave desde su
propio entorno; prefiera sensei.llm.existingSecret en lugar del texto plano
sensei.llm.apiKey.
Para ejecutar el motor contra Google Vertex AI en lugar de una clave de API de
proveedor, establezca sensei.llm.provider: vertex y sensei.llm.vertexProject
con el proyecto de GCP que aloja Vertex (sensei.llm.vertexRegion suele ser
global). El pod se autentica con Application Default Credentials, así que
asígnele una cuenta de servicio de GCP mediante sensei.serviceAccountName +
Workload Identity, o monte un archivo de clave con sensei.extraVolumesRaw y
sensei.extraVolumeMounts, y luego apunte GOOGLE_APPLICATION_CREDENTIALS a él
mediante sensei.extraEnv.
sensei.llm.fallbackChain toma una lista separada por comas de entradas
provider o provider:model a las que recurre el motor cuando el proveedor
principal devuelve un fallo reintentable. Terminar la cadena en un proveedor
distinto (por ejemplo, vertex-gemini:gemini-2.5-pro) mantiene las tareas de
corrección funcionando durante una interrupción del proveedor principal.
La imagen del escáner es pesada. sensei.maxConcurrentJobs (predeterminado 3)
limita las tareas paralelas por pod, y los recursos predeterminados
(solicitud de 1Gi / límite de 4Gi) están dimensionados para ese límite; aumente
ambos juntos.
Un HPA basado en CPU (de 1 a 4 réplicas) está activado de forma predeterminada.
Establezca sensei.hpa.maxReplicas igual a sensei.hpa.minReplicas para fijar
el número en sensei.replicas en su lugar.
Se requiere HTTPS saliente para clones de repositorios, API de alojamiento de git
y API de proveedores de LLM. Con networkPolicy.profile=aggressive, la lista de
CIDR permitidos (networkPolicy.externalAPIs.allowedCidrs) debe cubrir esos
endpoints.
La rotación depende de cómo haya configurado el TLS:
Gestionado por ACM (EKS): la renovación es automática; no se requiere ninguna acción.
cert-manager: la renovación es automática según los ajustes duration y
renewBefore (predeterminados: 2160h / 720h).
Certificados gestionados de GKE: la renovación es automática; no se requiere
ninguna acción.
Certificado manual mediante secreto de Kubernetes: actualice el secreto al que
hace referencia el ingress usando el mismo patrón kubectl create secret tls ... --dry-run=client mostrado anteriormente.
Certificados internos autogenerados: el chart puede regenerarlos con
helm upgrade si certificates.generation.enabled: true.
En Kubernetes, la fuente de verdad es el objeto Secret; actualizar el secreto
y reiniciar el deployment es cómo funciona la rotación de certificados.
Si usa External Secrets Operator o Sealed Secrets para gestionar los secretos TLS,
la rotación se maneja en esa capa y los secretos de Kubernetes se actualizan
automáticamente; no se necesitan pasos manuales con kubectl.
Los presets de plataforma y de perfil se incluyen dentro del chart
(dojopro/presets/). Están incluidos en el .tgz empaquetado y versionados junto
con el chart. Los clientes no necesitan modificarlos.
Al usar helm install desde el chart extraído, referéncielos usando la variable
$CHART establecida durante la extracción:
-f $CHART/presets/platforms/aws-eks.yaml
Al usar ArgoCD, referéncielos de forma relativa a la raíz del chart:
valueFiles:
- presets/platforms/aws-eks.yaml
No coloque límites de recursos en los archivos del cliente ni configuración de
plataforma en los archivos de perfil. Mantenga cada capa enfocada en una sola cosa.
Versionado de presets: ArgoCD vs. CLI: ArgoCD referencia los presets desde
dentro del paquete del chart, por lo que se actualizan automáticamente cuando
cambia targetRevision. Los usuarios de la CLI deben volver a extraer los
presets al actualizar a una nueva versión del chart para incorporar cualquier
cambio en los valores predeterminados de plataforma o perfil. Use una ruta de
extracción versionada (por ejemplo, dojopro-2.55.4/) para evitar confusión
entre versiones del chart; consulte Extraer el paquete del chart.
Más allá de los archivos de valores de plataforma/perfil/cliente, el chart
proporciona puntos de extensión de primera clase para conectar su propia
infraestructura: sidecars, init containers, variables de entorno, volúmenes,
cuentas de servicio, restricciones de programación y manifiestos adicionales
arbitrarios, sin necesidad de bifurcar el chart:
Hooks por componente: extraEnv, extraEnvFrom, extraVolumesRaw,
extraVolumeMounts, extraInitContainers, extraContainers, hostAliases,
priorityClassName, topologySpreadConstraints, dnsConfig, y
serviceAccountName en cada workload (django, celery worker/beat,
connectors, ddorch, ddorch-workers, integrators, mcp-server, psirt).
extraManifests de nivel superior: renderiza YAML arbitrario proporcionado
por el usuario (ConfigMaps, Secrets, NetworkPolicies, etc.) junto con el chart,
pasado a través de tpl de Helm con el contexto raíz del chart.
Consumo como umbrella chart: dojopro puede incrustarse como subchart
mediante una dependencia file:// u OCI, útil para distribuir paquetes de
cliente que agregan recursos adicionales alrededor del chart.
Validación consciente del esquema: values.schema.json cubre cada hook,
de modo que los editores obtienen autocompletado y helm lint/helm install
validan sus overrides.
Consulte la guía de extensibilidad BYO, incluida como Apéndice: Traiga su propia
infraestructura (BYO) en la edición en PDF, para conocer patrones, ejemplos y
garantías de estabilidad de actualización.
El chart incluye NetworkPolicies para cada componente, habilitadas de forma
predeterminada (networkPolicy.enabled: true). Una línea base de denegación por
defecto se limita a los pods de este release (mediante las etiquetas
app.kubernetes.io/name + app.kubernetes.io/instance), por lo que nunca
afecta a otros workloads que compartan el namespace.
El nivel de rigor de las reglas se controla mediante networkPolicy.profile:
Perfil
Egress
Ingress entre pods
Ingress externo
standard (predeterminado)
Todo el egress permitido (0.0.0.0/0)
Todo el tráfico entre los propios pods de este release está permitido
Restringido al controlador de ingress / balanceador de carga
aggressive
Lista de permitidos granular por componente (DNS, base de datos/broker, servicios específicos dentro del clúster, solo API externas explícitamente permitidas)
Lista de permitidos granular por componente
Restringido al controlador de ingress / balanceador de carga
standard se recomienda para la mayoría de los clústeres. Evita fallos
causados por dependencias de egress específicas del clúster (el servidor de
metadatos de GKE, NodeLocal DNSCache, endpoints de almacenamiento/API en la
nube) y por llamadas de servicio internas de la aplicación, a la vez que
mantiene el ingress externo restringido a la ruta de ingress: el release
confía en sus propios pods, pero lo externo sigue entrando por la puerta
principal.
aggressive aplica una lista de permitidos estricta en ambas direcciones.
Si la usa, es posible que deba ajustar las excepciones bajo networkPolicy
para su clúster:
nodeLocalDns: permite el resolutor NodeLocal DNSCache (link-local
169.254.20.10 de forma predeterminada, en el puerto 53). Necesario en
clústeres que ejecutan NodeLocal DNSCache (por ejemplo, el addon de GKE);
de lo contrario, la resolución DNS falla.
dnsSelectors: anula el destino de egress de DNS para una configuración
de DNS personalizada.
allowExternalAPIs / externalAPIs: controlan el egress hacia API HTTPS
externas y qué CIDR se bloquean (por ejemplo, metadatos en la nube).
Establezca el perfil en cualquier archivo de valores, por ejemplo:
networkPolicy:profile:aggressive
Las comprobaciones de salud de GKE se manejan en ambos perfiles: los rangos
de sondeo del balanceador de carga de GCE (130.211.0.0/22, 35.191.0.0/16)
siempre pueden acceder al backend de django en GKE. Consulte GCP GKE.
Acceso del controlador de ingress (502 Bad Gateway)#
En clústeres que no son GKE ni OpenShift, la NetworkPolicy de django permite
la entrada del controlador de ingress seleccionando su namespace mediante la
etiqueta kubernetes.io/metadata.name que Kubernetes aplica automáticamente a
cada namespace. De forma predeterminada, esto espera que el controlador esté en
un namespace llamado ingress-nginx, con los pods del controlador con la
etiqueta app.kubernetes.io/name: ingress-nginx (el valor predeterminado del
chart ingress-nginx).
Si su controlador de ingress reside en un namespace con un nombre distinto, usa
etiquetas de pod diferentes, o es un controlador completamente distinto
(Traefik, un ALB, etc.), la política descartará silenciosamente su tráfico y
las solicitudes devolverán 502 Bad Gateway (connect() failed (110: Operation timed out) en los logs del controlador). Apunte la política a su origen real de
ingress con networkPolicy.ingressSource:
O ajuste networkPolicy.ingressNamespace / networkPolicy.ingressControllerLabel
si solo difieren los nombres. Consulte los comentarios bajo networkPolicy en
values.yaml para ver más ejemplos de ingressSource (Traefik, router de
OpenShift, ALB de AWS).
El flujo de trabajo de zip empaquetado usado en la instalación también funciona
para las actualizaciones: sustituya helm install por helm upgrade contra la
ruta extraída $CHART.
Consulte la Guía de actualización — incluida como Apéndice: Actualización de
DefectDojo Pro en la edición en PDF — para conocer la autenticación, las
actualizaciones con ArgoCD, la verificación, la reversión y la resolución de
problemas.
Los PersistentVolumes con una política de reclamación Retain tienen alcance
de clúster — no se eliminan con helm uninstall ni al eliminar el
namespace. Si reinstala DefectDojo en un namespace distinto, los metadatos de
propiedad del PV huérfano entrarán en conflicto con la nueva instalación y
bloquearán helm install.
Compruebe si quedan PV huérfanos después de desinstalar:
kubectl get pv | grep dojopro
Si queda alguno, elimínelo:
kubectl delete pv dojopro-media-pv
Nota: Eliminar el PV quita la referencia del volumen en Kubernetes, pero
los datos subyacentes persisten en el backend de almacenamiento (por
ejemplo, un sistema de archivos EFS). Esto es seguro si piensa reinstalar,
pero debe hacerse de forma intencionada.
Esta configuración es solo para pruebas locales y evaluación. No use
PostgreSQL ni Redis embebidos en producción. Los despliegues de producción
deben usar servicios gestionados (por ejemplo, RDS, ElastiCache) para
garantizar fiabilidad, copias de seguridad y escalado. El soporte de
DefectDojo no cubre incidencias con bases de datos embebidas en entornos de
producción.
El chart puede desplegar su propio PostgreSQL y Redis para pruebas locales
rápidas usando el perfil minimal. Esto evita la necesidad de infraestructura
externa de base de datos y broker.
Agregue lo siguiente a su archivo de values:
# Enable embedded PostgreSQL (instead of external RDS)postgresql:enabled:truedatabase:password:"your-password"# required — must match DD_DATABASE_PASSWORD in your secretsdatabase:external:false# Enable embedded Redis (instead of external ElastiCache)redis:enabled:truecelery:broker:external:false
Importante: postgresql.database.password es obligatorio cuando
postgresql.enabled es true y database.existingSecret no está definido.
El chart no se podrá renderizar sin él. Esta contraseña debe coincidir con
el valor DD_DATABASE_PASSWORD de los secretos de la aplicación.
Credenciales predeterminadas de PostgreSQL embebido: los valores por
defecto del chart para el PostgreSQL embebido son el usuario dojodbusr y
la base de datos dojodb (definidos en el values.yaml del chart). Su
DD_DATABASE_URL en los secretos de la aplicación debe usar estos valores,
no los marcadores de posición de base de datos externa de
secrets-template.yaml. Por ejemplo:
El perfil minimal (dojopro/presets/profiles/minimal.yaml) establece
solicitudes de recursos reducidas apropiadas para un clúster de prueba de un
solo nodo, pero no activa estos indicadores de base de datos/broker — debe
configurarlos usted mismo.
Nota sobre privilegios de contenedor: los contenedores embebidos de
PostgreSQL y Redis no se ejecutan como root — PostgreSQL se ejecuta con
el UID 999 y Redis con el UID 1001. La única excepción es el init
container de PostgreSQL (init-chmod-data), que se ejecuta como root
(UID 0) para establecer la propiedad del directorio en el volumen de datos
antes de que arranque el proceso principal. Este es un patrón habitual en
StatefulSets con almacenamiento persistente. Si su clúster aplica un Pod
Security Standard restricted o una SCC de OpenShift que prohíbe los init
containers como root, desactívelo con
postgresql.initContainer.enabled: false (consulte Problemas conocidos).
Si usa PostgreSQL embebido en EKS, también necesitará el driver CSI de EBS
(consulte Requisitos previos de AWS EKS) y es
posible que deba ajustar los valores predeterminados de almacenamiento
(consulte Problemas conocidos).
Valide sus values antes de instalar — la ruta minimal requiere más overrides
y es más propensa a errores de renderizado:
Si esto finaliza sin errores, continúe con helm install usando las mismas
opciones.
Use --timeout 30m para instalaciones minimal o con base de datos
nueva. El PostgreSQL embebido tiene recursos reducidos, y el
initializer debe ejecutar todas las migraciones de base de datos desde cero
en una base de datos nueva. En pruebas, esto tardó unos 23 minutos, lo que
supera el --timeout 15m usado en los ejemplos de instalación estándar. Un
timeout hace que helm install informe INSTALLATION FAILED aunque el
despliegue se complete correctamente en segundo plano. Usar
--timeout 30m evita este fallo falso y el estado failed de release que
resulta de él.
Si su clúster no puede descargar imágenes del registro predeterminado de
DefectDojo, replique las imágenes en su propio registro y configure el chart
para usarlo.
Establezca global.imageRegistry para redirigir todas las descargas de
imágenes. El chart elimina el registro original de images.prefix y
antepone el suyo:
global:imageRegistry:"my-registry.example.com"
Esto afecta a todas las imágenes (django, nginx, celery, connectors, redis,
etc.).
Para un control más preciso, establezca images.registry (afecta a las
imágenes principales de la aplicación) y sobrescriba imágenes individuales:
images:registry:"my-registry.example.com"prefix:"defectdojo/"# path within your registrytag:"2.53.0"connectors:registry:"my-registry.example.com"repository:"defectdojo/connectors"tag:"2.53.0"redis:registry:"my-registry.example.com"repository:"defectdojo/redis"tag:"7.2.4"
Secretos de pull de imagen para registros privados#
Si su registro requiere autenticación, cree un secreto de pull y hágale
referencia:
O deje que el chart cree uno a partir de credenciales explícitas:
images:pullSecrets:create:trueregistry:"my-registry.example.com"# Provide credentials via a Kubernetes docker-registry secret
El comportamiento predeterminado (extractFromLicense: true) extrae
credenciales de cuenta de servicio de GCP desde el archivo de licencia para
descargar imágenes del registro de DefectDojo. Desactive esto cuando use su
propio registro:
El chart inyecta automáticamente anotaciones específicas de plataforma en el
Ingress y el Service según cloudProvider (por ejemplo, anotaciones ALB para
EKS, anotaciones GCE para GKE). Si necesita control total sobre las
anotaciones — por ejemplo, usar un controlador de ingress nginx en EKS en
lugar de ALB — establezca platformAnnotations.enabled: false y proporcione
las suyas:
Cuando platformAnnotations.enabled es true (el valor predeterminado), el
chart combina las anotaciones de plataforma con sus anotaciones
personalizadas. Sus anotaciones tienen prioridad en caso de conflicto de
claves, pero no puede eliminar una anotación de plataforma sin este
interruptor.
De forma predeterminada, el chart establece
nginx.ingress.kubernetes.io/proxy-body-size: "2400m" en el Ingress para que
las subidas grandes de resultados de escaneo y los informes PDF pasen por
nginx-ingress sin un 413 Request Entity Too Large. Puede sobrescribirlo así:
django:ingress:maxBodySize:"100m"# set "" to omit the annotation entirely
Esto se aplica siempre que nginx-ingress sea el controlador — incluido
nginx-ingress ejecutándose sobre EKS, GKE o AKS. Los controladores que no son
nginx ignoran la anotación y deben ajustarse mediante sus propios mecanismos
(límites de inspección del cuerpo en AWS WAF, request-body-limit de AppGW,
tuningOptions de HAProxy en OpenShift Route).
Si su sistema de archivos EFS está configurado con un access point
(recomendado para forzar la propiedad UID/GID en el mount), debe
establecer storage.efs.accessPointId en su archivo de values. Sin esto, el
PV monta la raíz de EFS con propiedad de root, y los contenedores de
DefectDojo (que se ejecutan como UID 1001) no pueden crear subdirectorios de
media — lo que provoca que el initializer falle con errores de
Permission denied.
Importante: el campo volumeHandle del PersistentVolume es
inmutable tras su creación. Si inicialmente instala sin un access
point y más adelante necesita agregar uno, debe eliminar el PV y el PVC
existentes antes de ejecutar helm upgrade:
Esto es seguro — eliminar el PV solo quita la referencia de Kubernetes; los
datos en el sistema de archivos EFS no se ven afectados.
Storage Classes en clústeres endurecidos o gobernados por GitOps#
Hay dos supuestos sobre storage classes que causan problemas en clústeres con
nombres de StorageClass personalizados o donde los recursos de alcance de
clúster se gestionan fuera del chart de la aplicación.
Los PVC de aprovisionamiento dinámico usan gp3 por defecto en EKS.
Cualquier PVC que el chart aprovisione dinámicamente — el volumen de Redis
embebido (redis.enabled: true) y el volumen de media
storage.type: "pvc" — resuelve su StorageClass al valor predeterminado de
la plataforma, que es gp3 en EKS. Si su clúster no tiene una StorageClass
llamada gp3 (algo común en clústeres endurecidos con nomenclatura
personalizada), el PVC queda en estado Pending con un evento
storageclass.storage.k8s.io "gp3" not found y los pods nunca arrancan.
Sobrescríbalo de una de estas dos maneras:
Globalmente (recomendado) — una sola palanca para todos los PVC
aprovisionados por el chart:
storage:defaultStorageClass:"your-ebs-storageclass"# or "" for the cluster default
Por componente, si necesita clases distintas:
redis:redisVolume:pvc:storageClassName:"your-ebs-storageclass"storage:pvc:storageClassName:"your-ebs-storageclass"# only for storage.type: "pvc"
El orden de resolución es: valor por componente → storage.defaultStorageClass
→ valor predeterminado de la plataforma (gp3). Establezca un valor en
"" para volver a la StorageClass predeterminada del clúster. Esto no
se aplica a la ruta de media EFS predeterminada (ver más abajo), que no usa
ninguna StorageClass.
El volumen de media EFS predeterminado no necesita StorageClass. Cuando
storage.type: "efs", el chart enlaza el PV de media de forma estática
mediante el volumeHandle del sistema de archivos EFS y un claimRef —
tanto el PV como el PVC usan un storageClassName vacío. La StorageClass
efs-scno necesita existir para que el PVC de media se enlace.
El chart solo crea una StorageClass efs-sc de alcance de clúster si opta
explícitamente por el aprovisionamiento dinámico de EFS con
storageClasses.efs.enabled: true (valor predeterminado: false). En
clústeres donde los recursos de alcance de clúster se gobiernan fuera del
chart de la aplicación (GitOps), déjelo en el valor predeterminado false —
la ruta estática de EFS descrita arriba no requiere ninguna StorageClass ni
objetos de alcance de clúster de este chart. Si desea aprovisionamiento
dinámico de EFS bajo GitOps, cree la StorageClass fuera de banda y mantenga
storageClasses.efs.enabled: false.
Usa el controlador de ingress GCE (className: "gce") con TLS terminando
en el balanceador de carga de Google Cloud
El preset gcp-gke.yaml adjunta automáticamente un FrontendConfig
(redirección HTTP→HTTPS + política SSL) y un BackendConfig al ingress
El balanceador de carga GCE comprueba el estado del backend de django
directamente desde los rangos de Google (130.211.0.0/22,
35.191.0.0/16). Las NetworkPolicies del chart permiten esto
automáticamente en GKE bajo ambos valores de networkPolicy.profile, de
modo que el probe /nginx_health tiene éxito y el backend se reporta como
saludable — consulte Políticas de red
El preset gcp-gke.yaml usa por defecto certificados gestionados por
Google. Elija uno de estos dos enfoques:
Gestionado por Google (predeterminado): GCP aprovisiona y renueva el
certificado. Simplemente indique sus dominios — no se necesita ningún
secreto TLS de Kubernetes:
Esto genera spec.tls[].secretName en el ingress y omite la anotación
networking.gke.io/managed-certificates.
Soporte del script de bootstrap:scripts/bootstrap/bootstrap-gcp-gke.sh
solo cubre los flujos de certificados nativos de GCP (google-managed y
pre-shared). Para la ruta BYO con secret, instale directamente con
helm (cree primero el secreto TLS, luego pase
certificates.ingress.source=secret y
certificates.ingress.secretName=<your-secret>).
Usa Routes de forma predeterminada (django.route.enabled: true), pero
también se admite Ingress
Para usar Ingress en su lugar: establezca django.ingress.enabled: true y
django.route.enabled: false
Solo se puede habilitar uno a la vez (el chart valida la exclusividad mutua)
dojo.secureCookies debe ser false cuando se usan Routes con
terminación edge (el valor predeterminado). Esto es obligatorio, no
opcional. Consulte la advertencia en Preparar su archivo de values.
securityContext.openshift.fsGroup debe coincidir con el rango de grupos
suplementarios de su namespace (consulte la
Lista de verificación previa a la instalación
para saber cómo consultarlo)
NFS a través de EFS funciona bien — use storage.type: "nfs" con el nombre
DNS de EFS como servidor
OpenShift incluye un controlador de ingress basado en HAProxy por defecto. Si
prefiere Ingress en lugar de Routes (por ejemplo, para mantener coherencia
con otros clústeres o para usar un controlador de ingress personalizado),
configure sus values así:
django:ingress:enabled:trueclassName:"openshift-default"# or your custom ingress classplatformAnnotations:enabled:false# recommended — provide your own annotationspathType:"Prefix"path:"/"tls:enabled:trueannotations:{}# add your ingress controller annotations hereroute:enabled:falsenginx:tls:enabled:falsegenerateCertificate:false
Los helpers de plataforma del chart seguirán gestionando correctamente los
contextos de seguridad, el resolvedor DNS y los valores predeterminados de
almacenamiento para OpenShift, sea cual sea el método de exposición que
elija.
Estos son errores confirmados en la versión actual del chart. Las soluciones
temporales se documentan aquí hasta que se publique una versión corregida.
Instalación minimal solo con PostgreSQL o Redis locales#
Los siguientes problemas solo se aplican si usa el PostgreSQL o Redis
integrados del chart (postgresql.enabled: true o broker.external: false).
No afectan a los despliegues de producción que usan bases de datos y brokers
externos.
No use EBS para el volumen de media (BUG-14, BUG-15)
Los volúmenes EBS solo admiten ReadWriteOnce — solo pueden conectarse a un
nodo a la vez. DefectDojo requiere que el volumen de media se comparta entre
varios pods (django, celery-worker, initializer, connectors), que pueden
programarse en nodos distintos. Cuando esto ocurre, los pods quedan atascados
en ContainerCreating con un error Multi-Attach error porque EBS no puede
montar el volumen en más de un nodo simultáneamente. Esto también afecta a
helm test, donde el pod de test-storage puede programarse en un nodo
distinto al de los pods de la aplicación.
Use EFS (u otro backend de almacenamiento compatible con
ReadWriteMany) en lugar de EBS para el volumen de media. EFS admite
acceso concurrente desde todos los nodos del clúster y es el backend de
almacenamiento recomendado para despliegues en EKS.
Si debe usar EBS para pruebas en un clúster de un solo nodo, sobrescriba los
valores predeterminados:
Tenga en cuenta que incluso con este override, EBS fallará en cuanto los
pods se programen en varios nodos (por ejemplo, durante el escalado, el
reemplazo de nodos o helm test). EFS evita esto por completo.
El init container de PostgreSQL entra en conflicto con el contexto de
seguridad sin root (BUG-16)
Desactívelo si se encuentra con CreateContainerConfigError:
El pod de connectors entra en crashloop mientras se ejecuta el
initializer (comportamiento esperado)
Durante la primera instalación, el pod de connectors entrará en
CrashLoopBackOff mientras el job del initializer ejecuta las migraciones de
base de datos. Esto es esperado — el pod de connectors intenta llamar a la
API de Django (/api/connectors/v1/config/), que devuelve un 500 porque el
esquema de la base de datos aún no está completamente migrado. Una vez que el
job del initializer se completa correctamente (muestra 1/1 COMPLETIONS en
kubectl get jobs), el pod de connectors se recuperará en su siguiente ciclo
de reinicio. No se requiere intervención manual.
El fallo del initializer tras las migraciones deja un estado de base de
datos irrecuperable (BUG-18)
Si el job del initializer falla después de ejecutar las migraciones de
base de datos pero antes de sembrar los datos iniciales (por ejemplo,
debido a errores de permisos de almacenamiento o límites de recursos), la
base de datos queda en un estado parcialmente inicializado — las tablas
existen pero la tabla dojo_system_settings está vacía. En reinicios
posteriores, el initializer falla de inmediato con:
CommandError: Failed to read system settings from database: 'NoneType' object is not iterable
Esto crea un bucle de fallos sin recuperación automática. Solución
temporal: restablezca el esquema de la base de datos y vuelva a ejecutar el
initializer:
# Drop and recreate the public schemakubectl run psql-reset --rm -i --tty=false --restart=Never \
--image=postgres:16 \
-n $NAMESPACE\
--env="PGPASSWORD=<your-db-password>"\
-- psql -h <your-db-host> -p 5432 -d <your-db-name> -U <your-db-user> \
-c "DROP SCHEMA public CASCADE; CREATE SCHEMA public; GRANT ALL ON SCHEMA public TO <your-db-user>;"# Delete the failed initializer job and trigger a new onekubectl delete job -n $NAMESPACE -l app.kubernetes.io/component=initializer
helm upgrade dojopro $CHART ... (same flags as install)
Prevención: asegúrese de que los permisos de almacenamiento
(especialmente los access points de EFS — consulte
Access Points de EFS) y los límites de recursos estén
correctamente configurados antes de la primera instalación. Ejecute
helm template para validar sus values, y verifique los permisos de
montaje de EFS con un pod de prueba si es posible.
Advertencia de token de Hatchet en los logs (informativo)
Cuando hatchet.enabled: false (el valor predeterminado), los pods
registrarán la siguiente advertencia al arrancar:
Could not create Hatchet handle; all future Hatchet invocations will fail.
Error: ... Token must be set
Esto es esperado e inofensivo. A partir del chart 2.57, la ejecución de
flujos de trabajo en segundo plano se ha consolidado en ddorch +
ddorch-workers, que sustituyen a los workers heredados basados en Hatchet
(kairos, rulesengine, hatchet-integrators). El código cliente de
Hatchet aún se inicializa al arrancar, por lo que la advertencia sigue
apareciendo cuando Hatchet está desactivado, pero nada depende de ella. La
advertencia puede ignorarse con seguridad.
La anotación ssl-redirect del ALB requiere un listener HTTPS (BUG-17)
El preset de EKS incluye una anotación ssl-redirect que asume que existe un
listener HTTPS en el ALB. Si no ha configurado un certificado ACM ni un
listener HTTPS, esta anotación provoca un bucle de redirección. Configure
HTTPS (recomendado) o consulte
Desplegar sin HTTPS (no recomendado)
para conocer el conjunto completo de cambios necesarios.
Habitualmente se debe a: secretos faltantes o incorrectos (compruebe las 12
claves), base de datos inaccesible (compruebe database.host y los grupos
de seguridad), o falta el certificado TLS interno (compruebe que existe el
secreto dojopro-internal-tls).
dojo.existingSecret is set to 'X', but the following inline secret values are also provided: [...]
Elija un solo enfoque. Si usa dojo.existingSecret, elimine todos los
valores de secretos inline (dojo.secretKey, dojo.admin.password,
monitoring.password, etc.) de sus archivos de values.
El esquema indica que admin.password es obligatorio#
Establezca dojo.existingSecret — el esquema elimina el requisito de
contraseña cuando se configura un secreto externo.
Si los pods fallan con errores de permisos en volúmenes NFS, compruebe que
securityContext.openshift.fsGroup está dentro del rango de grupos
suplementarios de su namespace. Consulte la búsqueda de fsGroup en
Despliegue → OpenShift / ROSA.
La plantilla completa (template.yaml) está disponible en el portal de
soporte de DefectDojo o solicitándola a support@defectdojo.com. Cópiela,
reemplace los marcadores REPLACE_* y elimine las secciones que no se
apliquen a su plataforma. La plantilla incluye ejemplos comentados para:
Identificación de plataforma (cloudProvider)
Configuración de secretos de pull de imagen
Configuración de Ingress y Route (Ingress para EKS/GKE/OpenShift, Route
para OpenShift)
Opciones de almacenamiento EFS y NFS
Configuración de certificados y TLS
Contextos de seguridad (uwsgi, nginx, fsGroup de OpenShift)
Políticas de red
Opciones de entrega de licencia (archivo, secreto, inline)
Se agrega el PSIRT Advisory Engine opcional (psirt.enabled): se sirve bajo /psirt/ a través del sidecar de nginx, base de datos dedicada mediante psirt.databaseUrl, guía de fijación de secretos, reglas de política de red, hooks BYO
2026-04-17
2.57.1
Se documentan ddorch + ddorch-workers (nuevo par de orquestador que sustituye a kairos/rulesengine/hatchet-integrators); se agregan las opciones --set-fileddorch.tls.rootCa/cert/key a los comandos de pre-flight y despliegue; nueva sección de certificados mTLS de ddorch con requisitos de SAN; mcp-server incluido en los pods esperados; se agregan PDB para ddorch (singleton) y ddorch-workers; nota de requisitos previos de ArgoCD sobre la entrega de certificados de ddorch; se actualiza la advertencia de Hatchet para reflejar la consolidación de workers
2026-03-25
2.55.4
Se agrega documentación y campo de plantilla para access points de EFS; se documenta la recuperación de fallos del initializer (BUG-18); se documenta el crashloop de connectors durante la inicialización como comportamiento esperado; se aclara que la advertencia de token de Hatchet es inofensiva; se corrige un anclaje obsoleto de problemas conocidos; ruta de extracción del chart versionada; se consolida la guía sin HTTPS; limpieza de PV en la desinstalación; nota de coherencia de namespace; aviso sobre versionado de presets ArgoCD frente a CLI
2026-03-11
2.53.0
Se corrigen las rutas de los comandos helm; se agregan la extracción del chart, los requisitos previos de EKS, la comprobación de BD previa al vuelo, el aviso de HTTPS, la rotación de TLS y la sección de problemas conocidos