Na parte anterior deste ciclo, estabelecemos as bases para nosso pipeline de desenvolvimento seguro (РБПО): configuramos máquinas virtuais, o servidor Ubuntu, a rede, o firewall e o Docker. Essencialmente, criamos a plataforma onde a construção do pipeline de desenvolvimento seguro pode começar. Agora, é hora de povoar nossas máquinas virtuais com os componentes necessários. Continuando a analogia, vamos adicionar os primeiros habitantes ao nosso reino de desenvolvimento seguro: um guardião de segredos, um supervisor de artefatos, um cronista de vulnerabilidades e outros personagens úteis. Isso significa instalar e configurar GitLab, Nexus, HashiCorp Vault, DefectDojo e Dependency-Track, além de preparar uma máquina virtual separada com um conjunto de ferramentas CLI para análise de segurança. A maioria desses serviços será executada em contêineres Docker, então também abordaremos a configuração de armazenamento persistente, Docker Compose e algumas particularidades de configuração de componentes individuais.
Aviso Importante: Este ciclo de artigos não substitui os requisitos de metodologias sérias de desenvolvimento seguro como GOST, OWASP SAMM ou BSIMM. É um exemplo prático de como organizar um pipeline de desenvolvimento seguro de software com investimento mínimo. Toda a experiência descrita é pessoal e não representa a posição oficial de empregadores atuais ou anteriores. Não copie cegamente; teste em ambientes de laboratório, faça backups e aborde os experimentos com cautela. Erros são possíveis e devem ser vistos como oportunidades de aprendizado para construir processos mais robustos.
GitLab: Decidimos instalar o GitLab Community Edition (CE) devido a restrições orçamentárias. A instalação é simples, geralmente com um único comando. Primeiro, adicionamos o repositório oficial do GitLab para que nosso gerenciador de pacotes saiba de onde baixar:
bashcurl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash
Em seguida, instalamos o pacote:
bashsudo apt install -y gitlab-ce
Após a instalação, é crucial configurar o URL externo pelo qual o GitLab será acessível. Edite o arquivo /etc/gitlab/gitlab.rb e localize a linha external_url, substituindo-a pelo IP ou domínio desejado (neste exemplo, http://192.168.0.201:9090). Evite a porta 8080, pois ela já está em uso pelo servidor Puma interno.
bashsudo nano /etc/gitlab/gitlab.rb external_url ‘http:// 192.168.0.201:9090’;
Aplique a configuração:
bashsudo gitlab-ctl reconfigure
Verifique o status dos serviços:
bashsudo gitlab-ctl status
O GitLab estará acessível em http://192.168.0.201:9090. O login padrão é root, e a senha inicial é gerada durante a instalação e pode ser encontrada em /etc/gitlab/initial_root_password.
Nexus: Em vez de baixar o Nexus diretamente, optamos por implantá-lo via Docker para contornar possíveis bloqueios. Para garantir a persistência dos dados, configuraremos um volume no host. Embora alguns possam considerar isso inseguro, em um ambiente de laboratório, é uma abordagem justificável. Criaremos um diretório para os dados do Nexus, definiremos as permissões corretas para o usuário interno do contêiner (UID 200) e, em seguida, usaremos o Docker Compose para configurar o volume e o mapeamento de portas (8081).
Criamos o diretório de dados:
bashsudo mkdir -p /opt/nexus-data
Definimos as permissões:
bashsudo chown -R 200:200 /opt/nexus-data
Criamos o arquivo docker-compose.yml:
yamlversion: '3' services: nexus: image: sonatype/nexus3:latest container_name: nexus restart: unless-stopped ports: - "8081:8081" volumes: - nexus-data:/nexus-data volumes: nexus-data: driver_opts: type: none device: /opt/nexus-data o: bind
Iniciamos o Nexus:
bashdocker-compose up -d
O Nexus estará acessível em http://192.168.0.202:8081/. A senha inicial do administrador pode ser obtida com docker exec nexus cat /nexus-data/admin.password. Para testar a persistência, pare, remova o contêiner e reinicie-o via Docker Compose. Se o login com a senha alterada funcionar, o armazenamento está correto.
HashiCorp Vault: Para gerenciar segredos como senhas e tokens, implantaremos o HashiCorp Vault, também via Docker Compose e com armazenamento persistente. Para um ambiente de laboratório, o modo file é suficiente, mas para produção, o modo raft é recomendado para alta disponibilidade e escalabilidade. Para este exemplo, usaremos o modo file.
Criamos a estrutura de diretórios e o arquivo de configuração /vault/config/config.hcl:
hclstorage "file" { path = "/vault/data" } listener "tcp" { address = "0.0.0.0:8200" tls_disable = true } ui = true disable_mlock = true # Necessário para rodar em contêiner
O docker-compose.yml para o Vault:
yamlversion: '3.8' services: vault: image: hashicorp/vault:latest container_name: vault restart: unless-stopped ports: - "8200:8200" volumes: - ./data:/vault/data:rw - ./config/config.hcl:/vault/config/config.hcl:ro cap_add: - IPC_LOCK environment: - VAULT_ADDR=http://127.0.0.1:8200 command: vault server -config=/vault/config/config.hcl
Iniciamos o Vault:
bashdocker-compose up -d
Em seguida, inicializamos o Vault dentro do contêiner. É crucial salvar as chaves de deslacração (unseal keys) e o token root gerados:
bashdocker exec -it vault sh export VAULT_ADDR=http://127.0.0.1:8200 vault operator init
Verifique o status com vault status. Para testar a persistência, deslacre o Vault usando uma das chaves (vault operator unseal <KEY>), faça login com o token root, crie um segredo (vault kv put secret/test message="Hello Persistent Storage") e, após reiniciar o contêiner, verifique se o segredo ainda existe.
DefectDojo e Dependency-Track: Instalaremos ambos em uma única máquina virtual, cada um em sua porta. Usaremos Docker Compose com volumes persistentes. O DefectDojo requer vários componentes (PostgreSQL, Redis, Nginx, uWSGI, Celery), enquanto o Dependency-Track é mais direto (API Server, Frontend, PostgreSQL).
Para o DefectDojo, criamos diretórios e clonamos o repositório oficial. Configuramos o docker-compose.yml para usar volumes persistentes para PostgreSQL (/opt/defectdojo/postgres) e arquivos de mídia (/opt/defectdojo/media). Ajustamos a porta para 9090 para evitar conflitos com o Dependency-Track. Um arquivo de configuração Nginx customizado (nginx/conf.d/dojo.conf) é necessário para o correto roteamento.
nginxupstream django { server uwsgi:9090; } server { listen 8080; server_name _; client_max_body_size 100M; location / { uwsgi_pass django; include /etc/nginx/uwsgi_params; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location /static/ { alias /app/static/; } location /media/ { alias /app/media/; } }
Executamos as migrações do banco de dados e criamos um superusuário:
bashdocker compose exec uwsgi /bin/bash -c "python manage.py migrate" docker compose exec uwsgi /bin/bash -c "python manage.py createsuperuser"
O DefectDojo estará acessível em http://192.168.0.204:9090/.
Para o Dependency-Track, editamos o docker-compose.yml padrão para mapear os volumes do Docker para diretórios específicos no host (e.g., /opt/dependency-track/data para o API Server e /opt/dependency-track/tmp para os arquivos temporários). A configuração do ambiente API_BASE_URL deve ser ajustada para o IP correto (e.g., http://localhost:8081).
yamlservices: apiserver: image: dependencytrack/apiserver depends_on: postgres: condition: service_healthy environment: EXTRA_JAVA_OPTIONS: "-Xmx4G -Xms2G -Djava.io.tmpdir=/data/tmp" ALPINE_DATABASE_MODE: "external" ALPINE_DATABASE_URL: "jdbc:postgresql://postgres:5432/dtrack" ALPINE_DATABASE_DRIVER: "org.postgresql.Driver" ALPINE_DATABASE_USERNAME: "dtrack" ALPINE_DATABASE_PASSWORD: "dtrack" deploy: resources: limits: memory: 6g restart_policy: condition: on-failure ports: - '8081:8080' volumes: - "/opt/dependency-track/data:/data" - "/opt/dependency-track/tmp:/data/tmp" restart: unless-stopped frontend: image: dependencytrack/frontend depends_on: apiserver: condition: service_healthy environment: API_BASE_URL: "http://localhost:8081" ports: - "8080:8080" restart: unless-stopped postgres: image: postgres:17-alpine environment: POSTGRES_DB: "dtrack" POSTGRES_USER: "dtrack" POSTGRES_PASSWORD: "dtrack" POSTGRES_SHARED_BUFFERS: 256MB POSTGRES_EFFECTIVE_CACHE_SIZE: 512MB healthcheck: test: [ "CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}" ] interval: 5s timeout: 3s retries: 3 volumes: - "postgres-data:/var/lib/postgresql/data" restart: unless-stopped volumes: dtrack-data: {} postgres-data: {}
Iniciamos o Dependency-Track:
bashdocker compose up -d
O frontend estará acessível em http://ip_servidor:8080/ com login admin/admin (a senha será solicitada para alteração no primeiro acesso).
Ferramentas CLI: Em uma quinta máquina virtual, reuniremos um conjunto de utilitários para análise de segurança, incluindo ferramentas para DAST, análise de código-fonte e verificação de segredos. Instalaremos Checkov, Trivy, Gitleaks, OpenGrep, Nuclei e outros. A instalação varia entre APT, downloads diretos do GitHub e scripts.
Instalamos Node.js e npm, seguidos por Checkov (via pip) e Trivy (via repositório oficial). Para Gitleaks, baixamos o binário do GitHub. OpenGrep requer um script de instalação e a adição do diretório ao PATH. Nuclei é baixado e descompactado do GitHub.
Conclusão: Estabelecemos a infraestrutura básica para um ambiente de desenvolvimento seguro, com GitLab, Nexus, HashiCorp Vault, DefectDojo e Dependency-Track, além de uma VM com ferramentas CLI de segurança. Este é o fundamento; na próxima parte, integraremos esses componentes para criar um pipeline DevSecOps completo, configurando repositórios, runners, autenticação e projetos.
