Pipeline DevSecOps completo com CI/CD, SAST, DAST e Monitoramento
Projeto de conclusão da Especialização em DevSecOps — Hackers do Bem (SENAI/RNP/Softex)
Este projeto implementa um pipeline DevSecOps completo sobre uma aplicação web de gerenciamento de tarefas pessoais desenvolvida em Flask. O objetivo foi aplicar na prática os conceitos de segurança integrada ao ciclo de desenvolvimento, desde o primeiro commit até o deploy em staging.
O projeto parte do repositório base corrigido pelo professor Jaime Neto, com ajustes de ambiente, integração de ferramentas de segurança e automação completa via pipeline GitLab CI/CD.
COMMIT
│
▼
┌─────────────┐
│ TEST │ 47 testes unitários · Cobertura 100%
└──────┬──────┘
│
▼
┌─────────────┐
│ SAST │ Bandit · No issues identified
└──────┬──────┘
│
▼
┌─────────────┐
│ BUILD │ Docker build · python:3.11-slim
└──────┬──────┘
│
▼
┌─────────────┐
│ DAST │ OWASP ZAP · High: 0 · Medium: 3 · Low: 7
└──────┬──────┘
│
▼
┌─────────────┐
│ STAGING │ Deploy automático · porta 5001
└─────────────┘
| Camada | Tecnologia |
|---|---|
| Aplicação | Python 3.11 · Flask 3.0.3 · SQLAlchemy · Flask-Login · Flask-Bcrypt · Flask-WTF |
| Testes | pytest 9.0.3 · pytest-cov · Cobertura 100% |
| Container | Docker · python:3.11-slim |
| CI/CD | GitLab CE · GitLab Runner 19.0.1 |
| SAST | Bandit 1.9.4 |
| DAST | OWASP ZAP 2.17.0 |
| Monitoramento | Prometheus · Grafana · prometheus-flask-exporter |
- ✅ 47 testes passando
- ✅ 100% de cobertura em todos os módulos
- ✅ Cobertura mínima exigida (90%) superada
- ✅ No issues identified
- ✅ 197 linhas de código analisadas
- ✅ Zero ocorrências em todos os níveis de severidade
- ✅ High: 0 vulnerabilidades críticas
⚠️ Medium: 3 (CSP Header, Anti-clickjacking, JS library)⚠️ Low: 7 (headers de segurança, SameSite, versão exposta)- ✅ 54 testes aprovados
- Docker
- Python 3.11+
- Git
git clone https://github.com/luciano-veiga/devsecops-task-manager.git
cd devsecops-task-manager
# Ambiente virtual
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt -r requirements-dev.txt
# Rodar testes
pytest
# Rodar aplicação
cd todo_project
python run.pyAcesse: http://localhost:5000
docker build -t task-manager:v1 .
docker run -d -p 5000:5000 --name taskmanager task-manager:v1Acesse: http://localhost:5000
stages:
- test
- sast
- build
- dast
- staging
variables:
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
cache:
paths:
- .cache/pip
build-and-test:
stage: test
image: python:3.11-slim
before_script:
- pip install --upgrade pip
- pip install -r requirements.txt -r requirements-dev.txt
script:
- pytest --cov-report=xml --cov-report=term
coverage: '/TOTAL.*\s+(\d+%)$/'
sast-bandit:
stage: sast
image: python:3.11-slim
before_script:
- pip install bandit[toml]
script:
- bandit -r todo_project/todo_project/ -f json -o bandit-report.json || true
- bandit -r todo_project/todo_project/ -f txt
allow_failure: true
docker-build:
stage: build
image: docker:24
variables:
DOCKER_HOST: unix:///var/run/docker.sock
script:
- docker build -t task-manager:$CI_COMMIT_SHORT_SHA .
- docker tag task-manager:$CI_COMMIT_SHORT_SHA task-manager:staging
allow_failure: true
dast-zap:
stage: dast
image: docker:24
variables:
DOCKER_HOST: unix:///var/run/docker.sock
script:
- mkdir -p zap-reports
- docker run --rm --network host
-v $(pwd)/zap-reports:/zap/wrk/:rw
ghcr.io/zaproxy/zaproxy:stable
zap-baseline.py
-t http://host.docker.internal:5000
-r zap-report.html -I || true
allow_failure: true
deploy-staging:
stage: staging
image: docker:24
variables:
DOCKER_HOST: unix:///var/run/docker.sock
script:
- docker stop taskmanager-staging || true
- docker rm taskmanager-staging || true
- docker run -d -p 5001:5000 --name taskmanager-staging task-manager:staging
- docker ps | grep taskmanager-staging
environment:
name: staging
url: http://localhost:5001
allow_failure: true
only:
- develop
- stagingA aplicação expõe métricas no endpoint /metrics via prometheus-flask-exporter.
# Prometheus
docker run -d --name prometheus -p 9090:9090 \
-v ~/monitoring/prometheus.yml:/etc/prometheus/prometheus.yml \
prom/prometheus:latest
# Grafana (já existente no ambiente)
# Acesse: http://localhost:3000
# Datasource: http://host.docker.internal:9090
# Métrica: flask_http_request_totalDesafios técnicos resolvidos:
- Configuração do
clone_urlno GitLab Runner para comunicação entre containers Docker Desktop e WSL2 - Flask em modo debug impedindo o endpoint
/metricsdo Prometheus de funcionar corretamente - Mapeamento correto de portas entre Docker Desktop Windows e WSL2
Conceitos aplicados:
- Shift Left Security: segurança verificada desde o primeiro commit
- Pipeline como código: toda a configuração versionada no
.gitlab-ci.yml - Containers imutáveis: cada build gera uma imagem nova com o SHA do commit
- Observabilidade: métricas expostas e coletadas automaticamente
Luciano Veiga
Gerente de Infraestrutura de Redes e Cloud · Allg Connect
AWS Certified Cloud Practitioner · Solutions Architect Associate
Especializando em DevSecOps — Hackers do Bem
Este projeto é baseado no trabalho original de Aditya Bagad com contribuições de Jaime F. L. Neto e adaptações para fins acadêmicos.





