DevSecOps: melhores práticas para garantir a segurança em todo o processo de desenvolvimento

DevSecOps: melhores práticas para garantir a segurança em todo o processo de desenvolvimento

O Devops é uma abordagem que visa integrar e automatizar as atividades de desenvolvimento, teste, implantação e operação de software, com o objetivo de entregar produtos de qualidade com mais rapidez e eficiência. No entanto, a segurança nem sempre é considerada uma prioridade no Devops, o que pode resultar em vulnerabilidades, riscos e incidentes que comprometem a confiabilidade, a disponibilidade e a integridade dos sistemas e dos dados.

A segurança Devops, ou DevSecOps, é uma forma de incorporar a segurança em todo o ciclo de vida do Devops, desde o planejamento até a operação, passando pelo design, codificação, teste e implantação. A segurança Devops visa criar uma cultura de colaboração entre as equipes de desenvolvimento, operação e segurança, bem como aplicar ferramentas e práticas que garantam a proteção do software e dos dados em todas as fases do processo.

Neste artigo, vamos apresentar algumas das melhores práticas para implementar a segurança Devops, bem como exemplos de código que ilustram como aplicá-las. As práticas são:

  • Definir requisitos e padrões de segurança;
  • Realizar análises estáticas e dinâmicas do código;
  • Utilizar contêineres e orquestradores seguros;
  • Implementar pipelines de integração e entrega contínua com segurança;
  • Monitorar e responder a incidentes de segurança.

Definir requisitos e padrões de segurança

A primeira prática para garantir a segurança Devops é definir os requisitos e os padrões de segurança que devem ser seguidos pelas equipes envolvidas no processo. Esses requisitos e padrões devem estar alinhados com as políticas, as normas e as regulamentações da organização, bem como com as boas práticas do mercado.

Os requisitos e os padrões de segurança devem abranger aspectos como:

  • A identificação e a classificação dos ativos críticos (sistemas, dados, serviços, etc);
  • A definição dos níveis de confidencialidade, integridade e disponibilidade esperados para cada ativo;
  • A especificação dos controles de segurança necessários para cada ativo (criptografia, autenticação, autorização, auditoria, etc);
  • A definição das responsabilidades e dos papéis das equipes de desenvolvimento, operação e segurança;
  • A documentação das políticas e dos procedimentos de segurança (como gerenciar senhas, chaves, certificados, logs, backups, etc).

Um exemplo de código que pode ser usado para definir requisitos e padrões de segurança é o uso de arquivos YAML (Yet Another Markup Language) para descrever as configurações de segurança dos sistemas. O YAML é um formato simples e legível para representar dados estruturados. Por exemplo, o seguinte arquivo YAML define alguns requisitos e padrões de segurança para um sistema web:

# Requisitos e padrões de segurança para o sistema web
assets:
  - name: web_server
    description: Servidor web que hospeda o aplicativo
    criticality: high
    security_level: 3
    security_controls:
      - encryption: TLS 1.3
      - authentication: Basic Auth
      - authorization: RBAC
      - auditing: Syslog
  - name: database
    description: Banco de dados que armazena os dados do aplicativo
    criticality: high
    security_level: 3
    security_controls:
      - encryption: AES 256
      - authentication: PostgreSQL Auth
      - authorization: SQL GRANT/REVOKE
      - auditing: PostgreSQL Audit Extension
roles:
  - name: developer
    description: Pessoa responsável pelo desenvolvimento do aplicativo
    permissions:
      - web_server: read/write/execute
      - database: read/write
  - name: operator
    description: Pessoa responsável pela operação do sistema
    permissions:
      - web_server: read/execute
      - database: read
  - name: security
    description: Pessoa responsável pela segurança do sistema
    permissions:
      - web_server: read
      - database: read

Realizar análises estáticas e dinâmicas do código

A segunda prática para garantir a segurança Devops é realizar análises estáticas e dinâmicas do código, com o objetivo de identificar e corrigir vulnerabilidades, erros e más práticas que possam comprometer a segurança do software. As análises estáticas e dinâmicas devem ser realizadas de forma contínua, integradas ao processo de desenvolvimento e teste.

As análises estáticas são aquelas que examinam o código-fonte do software sem executá-lo, verificando aspectos como:

  • A conformidade com os padrões de codificação e de segurança;
  • A presença de códigos maliciosos, obsoletos ou desnecessários;
  • A existência de falhas de lógica, de design ou de implementação;
  • A qualidade, a complexidade e a manutenibilidade do código.

As análises dinâmicas são aquelas que testam o comportamento do software em execução, simulando cenários reais e ataques potenciais, verificando aspectos como:

  • A robustez, a performance e a escalabilidade do software;
  • A validação, a sanitização e a codificação dos dados de entrada e saída;
  • A proteção contra ataques comuns, como injeção de código, cross-site scripting, quebra de sessão, etc;
  • A detecção e o tratamento de exceções, erros e falhas.

Um exemplo de código que pode ser usado para realizar análises estáticas e dinâmicas do código é o uso de ferramentas automatizadas que integram com as plataformas de desenvolvimento e teste. Por exemplo, o SonarQube é uma ferramenta que realiza análises estáticas do código, verificando a qualidade e a segurança do código em diversas linguagens. O OWASP ZAP é uma ferramenta que realiza análises dinâmicas do código, testando a segurança das aplicações web contra ataques. Ambas as ferramentas podem ser integradas com o Jenkins, uma plataforma de integração e entrega contínua. Por exemplo, o seguinte arquivo Jenkinsfile define um pipeline que realiza análises estáticas e dinâmicas do código de um aplicativo web:

// Pipeline para realizar análises estáticas e dinâmicas do código
pipeline {
  agent any
  stages {
    stage('Checkout') {
      steps {
        // Obtém o código-fonte do repositório Git
        git 'https://github.com/example/web-app.git'
      }
    }
    stage('Build') {
      steps {
        // Compila o código-fonte usando Maven
        sh 'mvn clean package'
      }
    }
    stage('Static Analysis') {
      steps {
        // Realiza a análise estática do código usando SonarQube
        withSonarQubeEnv('SonarQube') {
          sh 'mvn sonar:sonar'
        }
      }
    }
    stage('Deploy') {
      steps {
        // Implanta o aplicativo web em um servidor Tomcat
        deploy adapters: [tomcat8(credentialsId: 'tomcat', path: '', url: 'http://localhost:8080/')], contextPath: 'web-app', war: '**/*.war'
      }
    }
    stage('Dynamic Analysis') {
      steps {
        // Realiza a análise dinâmica do código usando OWASP ZAP
        withZap() {
          zapCrawler(target: 'http://localhost:8080/web-app')
          zapScanner(failAllAlerts: true)
          zapAlerts()
          zapReport()
        }
      }
    }
  }
}

Utilizar contêineres e orquestradores seguros

A terceira prática para garantir a segurança Devops é utilizar contêineres e orquestradores seguros para empacotar, distribuir e executar o software. Os contêineres são unidades isoladas que contêm o software e todas as suas dependências, facilitando a portabilidade, a escalabilidade e a atualização do software. Os orquestradores são sistemas que gerenciam o ciclo de vida dos contêineres, automatizando tarefas como provisionamento, configuração, balanceamento de carga e recuperação.

A utilização de contêineres e orquestradores seguros é uma prática que visa garantir a segurança do software em ambientes distribuídos e dinâmicos, onde o software pode ser executado em diferentes plataformas, redes e nuvens. Para utilizar contêineres e orquestradores seguros, é preciso considerar aspectos como:

  • A escolha de imagens de contêineres confiáveis e atualizadas, que contenham apenas os componentes necessários para o software e que não apresentem vulnerabilidades conhecidas;
  • A configuração dos contêineres com os parâmetros de segurança adequados, como limites de recursos, privilégios mínimos, redes isoladas, montagens somente leitura, etc;
  • A verificação da integridade e da autenticidade dos contêineres, usando assinaturas digitais, hashes ou selos de tempo;
  • A proteção dos dados dos contêineres, usando criptografia, backups e políticas de retenção;
  • A monitoração do comportamento dos contêineres, usando ferramentas de observabilidade, detecção de anomalias e resposta a incidentes.

Um exemplo de código que pode ser usado para utilizar contêineres e orquestradores seguros é o uso do Docker e do Kubernetes. O Docker é uma plataforma que permite criar, executar e gerenciar contêineres. O Kubernetes é um sistema que permite orquestrar contêineres em clusters de servidores. Por exemplo, o seguinte arquivo Dockerfile define uma imagem de contêiner para um aplicativo web em Python:

# Imagem base do Python 3.9
FROM python:3.9

# Diretório de trabalho do contêiner
WORKDIR /app

# Copia os arquivos do aplicativo para o contêiner
COPY . .

# Instala as dependências do aplicativo
RUN pip install -r requirements.txt

# Expõe a porta 5000 do contêiner
EXPOSE 5000

# Executa o aplicativo quando o contêiner iniciar
CMD ["python", "app.py"]

O seguinte arquivo YAML define um deployment do Kubernetes para executar o aplicativo web em três réplicas de contêineres:

# Deployment do Kubernetes para o aplicativo web
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 3 # Número de réplicas do contêiner
  selector:
    matchLabels:
      app: web-app # Rótulo que identifica o contêiner
  template:
    metadata:
      labels:
        app: web-app # Rótulo que identifica o contêiner
    spec:
      containers:
      - name: web-app # Nome do contêiner
        image: web-app # Nome da imagem do contêiner
        ports:
        - containerPort: 5000 # Porta do contêiner
        resources:
          limits: # Limites de recursos do contêiner
            cpu: "1" # Limite de CPU
            memory: "512Mi" # Limite de memória
        securityContext: # Contexto de segurança do contêiner
          runAsUser: 1000 # Usuário com privilégios mínimos
          readOnlyRootFilesystem: true # Sistema de arquivos somente leitura

Implementar pipelines de integração e entrega contínua com segurança

A quarta prática para garantir a segurança Devops é implementar pipelines de integração e entrega contínua com segurança, ou seja, processos automatizados que permitem integrar, testar, implantar e entregar o software com rapidez e qualidade, incorporando a segurança em cada etapa. Os pipelines de integração e entrega contínua com segurança devem considerar aspectos como:

  • A utilização de ferramentas e plataformas confiáveis e atualizadas para gerenciar os pipelines, como Jenkins, GitLab CI/CD, GitHub Actions, etc.
  • A proteção dos repositórios de código-fonte, das imagens de contêineres, dos artefatos gerados e dos dados sensíveis usados nos pipelines, usando criptografia, controle de acesso, monitoração e auditoria.
  • A realização de testes automatizados de unidade, integração, funcionalidade e segurança em cada etapa dos pipelines, usando ferramentas como JUnit, Selenium, SonarQube, OWASP ZAP, etc;
  • A implantação automatizada do software em ambientes controlados e segregados, como desenvolvimento, teste, homologação e produção, usando ferramentas como Ansible, Terraform, Helm, etc;
  • A entrega automatizada do software aos usuários finais, usando técnicas como implantação contínua, implantação azul-verde, implantação canário, etc.

Um exemplo de código que pode ser usado para implementar pipelines de integração e entrega contínua com segurança é o uso do Jenkins e do Helm. O Jenkins é uma plataforma de integração e entrega contínua que permite criar e executar pipelines automatizados. O Helm é uma ferramenta que permite gerenciar aplicações Kubernetes usando gráficos, que são pacotes que contêm as configurações e os recursos necessários para implantar uma aplicação. Por exemplo, o seguinte arquivo Jenkinsfile define um pipeline que realiza a integração e a entrega contínua de um aplicativo web em Kubernetes:

// Pipeline para realizar a integração e a entrega contínua de um aplicativo web em Kubernetes
pipeline {
  agent any
  stages {
    stage('Checkout') {
      steps {
        // Obtém o código-fonte do repositório Git
        git 'https://github.com/example/web-app.git'
      }
    }
    stage('Build') {
      steps {
        // Compila o código-fonte usando Maven
        sh 'mvn clean package'
      }
    }
    stage('Static Analysis') {
      steps {
        // Realiza a análise estática do código usando SonarQube
        withSonarQubeEnv('SonarQube') {
          sh 'mvn sonar:sonar'
        }
      }
    }
    stage('Docker Build') {
      steps {
        // Constrói a imagem do contêiner usando Docker
        sh 'docker build -t web-app .'
      }
    }
    stage('Docker Push') {
      steps {
        // Envia a imagem do contêiner para o Docker Hub
        withCredentials([usernamePassword(credentialsId: 'dockerhub', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) {
          sh 'docker login -u $USERNAME -p $PASSWORD'
          sh 'docker push web-app'
        }
      }
    }
    stage('Helm Deploy') {
      steps {
        // Implanta o aplicativo web em Kubernetes usando Helm
        withKubeConfig([credentialsId: 'kubernetes']) {
          sh 'helm upgrade --install web-app ./helm-chart'
        }
      }
    }
    stage('Dynamic Analysis') {
      steps {
        // Realiza a análise dinâmica do código usando OWASP ZAP
        withZap() {
          zapCrawler(target: 'http://web-app')
          zapScanner(failAllAlerts: true)
          zapAlerts()
          zapReport()
        }
      }
    }
  }
}

Monitorar e responder a incidentes de segurança

A quinta e última prática para garantir a segurança Devops é monitorar e responder a incidentes de segurança, ou seja, coletar, analisar e agir sobre as informações relacionadas à segurança do software em operação, com o objetivo de prevenir, detectar e mitigar ameaças e ataques. O monitoramento e a resposta a incidentes de segurança devem considerar aspectos como:

  • A coleta de dados de segurança provenientes de diversas fontes, como logs, métricas, alertas, eventos, etc, usando ferramentas como ELK Stack, Prometheus, Grafana, etc;
  • A análise dos dados de segurança usando técnicas de inteligência artificial, aprendizado de máquina e big data, para identificar padrões, tendências e anomalias que indiquem possíveis incidentes de segurança;
  • A atuação sobre os incidentes de segurança usando procedimentos padronizados e automatizados, como notificação, escalonamento, contenção, erradicação, recuperação e lições aprendidas.

O monitoramento e a resposta a incidentes de segurança são práticas essenciais para garantir a segurança Devops, pois permitem prevenir, detectar e mitigar ameaças e ataques que possam comprometer o software em operação. Para monitorar e responder a incidentes de segurança, é preciso coletar, analisar e agir sobre as informações relacionadas à segurança do software, usando ferramentas e procedimentos adequados.

Um exemplo de código que pode ser usado para monitorar e responder a incidentes de segurança é o uso do ELK Stack e do TheHive. O ELK Stack é uma plataforma que permite coletar, armazenar, pesquisar e visualizar dados de logs. O TheHive é uma plataforma que permite gerenciar casos de incidentes de segurança. Por exemplo, o seguinte arquivo Logstash.conf define uma configuração para coletar os logs do aplicativo web e enviá-los para o Elasticsearch:

# Configuração do Logstash para coletar os logs do aplicativo web
input {
  # Coleta os logs do arquivo app.log
  file {
    path => "/var/log/app.log"
    start_position => "beginning"
    sincedb_path => "/dev/null"
  }
}
filter {
  # Filtra os logs usando expressões regulares
  grok {
    match => { "message" => "%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:level} %{DATA:class} - %{GREEDYDATA:message}" }
  }
  # Converte o campo timestamp para o formato ISO8601
  date {
    match => [ "timestamp", "ISO8601" ]
  }
}
output {
  # Envia os logs para o Elasticsearch
  elasticsearch {
    hosts => ["http://localhost:9200"]
    index => "web-app-%{+YYYY.MM.dd}"
  }
}

O seguinte arquivo TheHive.conf define uma configuração para integrar o TheHive com o Elasticsearch:

# Configuração do TheHive para integrar com o Elasticsearch
play.modules.enabled += org.thp.thehive.connector.elastic.ElasticModule

elastic.uri = "http://localhost:9200"

elastic.index = "the_hive_23"

elastic.audit.index = "the_hive_audit_23"

elastic.metrics.index = "the_hive_metrics_23"

elastic.alert.index = "the_hive_alert_23"

elastic.case.template.index = "the_hive_case_template_23"

elastic.attachment.index = "the_hive_attachment_23"

elastic.datastore.attachment.name = "the_hive_attachment_23"

elastic.datastore.attachment.hash = true

elastic.datastore.attachment.chunkSize = 1m

elastic.datastore.attachment.concurrentUpload = 5

elastic.datastore.attachment.endRetry = 3

elastic.datastore.attachment.retryDelay = 1s

elastic.search.scroll.keepalive = 1m

elastic.search.scroll.pageSize = 50

# Configuração para importar alertas do Elasticsearch
alerting.providers += local-elasticsearch

alerting.local-elasticsearch.name = "Local Elasticsearch"

alerting.local-elasticsearch.description = "Import alerts from local Elasticsearch index"

alerting.local-elasticsearch.endpoint = "http://localhost:9200/web-app-*"

alerting.local-elasticsearch.interval = 5 minutes

alerting.local-elasticsearch.filter.level = ERROR

alerting.local-elasticsearch.filter.class = SecurityException

alerting.local-elasticsearch.sourceRefPattern = %{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:level} %{DATA:class} - %{GREEDYDATA:message}

alerting.local-elasticsearch.titlePattern = Alert from web-app: %{message}

alerting.local-elasticsearch.descriptionPattern = An error occurred in the web-app at %{timestamp}: %{message}

alerting.local-elasticsearch.tags += web-app

alerting.local-elasticsearch.tags += elasticsearch

Com essas configurações, é possível monitorar os logs do aplicativo web no Elasticsearch usando o Kibana, uma ferramenta de visualização de dados. Além disso, é possível importar alertas de segurança do Elasticsearch para o TheHive, uma ferramenta de gerenciamento de casos. Assim, é possível responder aos incidentes de segurança usando procedimentos padronizados e automatizados, como notificação, escalonamento, contenção, erradicação, recuperação e lições aprendidas.

Conclusão

A segurança Devops é uma forma de incorporar a segurança em todo o ciclo de vida do Devops, desde o planejamento até a operação, passando pelo design, codificação, teste e implantação. A segurança Devops visa criar uma cultura de colaboração entre as equipes de desenvolvimento, operação e segurança, bem como aplicar ferramentas e práticas que garantam a proteção do software e dos dados em todas as fases do processo.

Neste artigo, apresentamos algumas das melhores práticas para implementar a segurança Devops, bem como exemplos de código que ilustram como aplicá-las. As práticas são:

  • Definir requisitos e padrões de segurança;
  • Realizar análises estáticas e dinâmicas do código;
  • Utilizar contêineres e orquestradores seguros;
  • Implementar pipelines de integração e entrega contínua com segurança;
  • Monitorar e responder a incidentes de segurança.

Esperamos que este artigo tenha sido útil e interessante para você, e que você possa aplicar as práticas apresentadas em seus projetos de Devops. Lembre-se que a segurança não é um custo, mas um investimento que pode trazer benefícios como confiança, qualidade e competitividade.

Referências Bibliográficas

BASS, L.; WEBER, I.; ZHU, L. DevOps: A Software Architect’s Perspective. Boston: Addison-Wesley Professional, 2015.

HUMBLE, J.; MOLESKY, J.; O’REILLY, B. Lean Enterprise: How High Performance Organizations Innovate at Scale. Sebastopol: O’Reilly Media, 2015.

KIM, G.; DEBOIS, P.; WILLIS, J.; HUMBLE, J. The DevOps Handbook: How to Create World-Class Agility, Reliability, and Security in Technology Organizations. Portland: IT Revolution Press, 2016.

OWASP. OWASP Top 10 - 2021: The Ten Most Critical Web Application Security Risks.

💡
As opiniões e comentários expressos neste artigo são de propriedade exclusiva de seu autor e não representam necessariamente o ponto de vista da Revelo.

A Revelo Content Network acolhe todas as raças, etnias, nacionalidades, credos, gêneros, orientações, pontos de vista e ideologias, desde que promovam diversidade, equidade, inclusão e crescimento na carreira dos profissionais de tecnologia.