Ir para o conteúdo

Lab 1.2: Utilizando linters e ferramenta de segurança

Analisando código com ruff

Agora que já temos um pacote Python pronto para ser distribuído, é fundamental adotar práticas de qualidade de código que garantam a legibilidade, consistência e segurança do seu código. Uma ferramenta poderosa para ajudar nesse processo é o Ruff.

Ruff

Ruff é um linter rápido e eficiente para Python. Ele foi projetado para ser altamente configurável e rápido, realizando verificações de estilo e erros de código. Ele é mais rápido que outros linters populares (como o pylint e flake8) devido ao seu design otimizado e ao uso de técnicas de compilação.

Benefícios do Ruff:

  • Desempenho: O Ruff é significativamente mais rápido do que linters tradicionais como o - pylint e flake8.
  • Facilidade de Uso: Requer pouca configuração e é fácil de integrar em seu fluxo de trabalho.
  • Alta Configuração: Você pode configurar quais regras deseja aplicar, ou até mesmo desativar certas verificações.
  • Compatibilidade: O Ruff oferece compatibilidade com diversas regras de linters populares, como flake8, black, isort, etc.
  • Análise de Segurança: Além de verificar o estilo do código, ele também verifica problemas de segurança, como importações não utilizadas e práticas arriscadas.

Como Integrar o Ruff no Seu Pacote Python localmente?

1 - Instalando o Ruff o primeiro passo é instalar o Ruff no seu ambiente de desenvolvimento. Você pode instalá-lo com o pip:

pip install ruff

2 - Rodando o Ruff no Código: Para rodar o Ruff em um diretório (onde seu pacote Python está localizado, por exemplo), rode o seguinte comando:

ruff check .

Isso irá verificar todo o código no diretório atual e subdiretórios. O Ruff então irá mostrar qualquer problema encontrado, como problemas de formatação ou uso incorreto de importações. Como podemos ver abaixo:

Erros Ruff

O Ruff identificou 3 erros, onde:

  • Na linha 14 do arquivo csv_functions erro de indentação, em decorrência do avanço da doc string.
  • Na linha 16 do arquivo csv_functions erro de indentação, em decorrência do avanço da doc string.
  • Na linha 6 do arquivo email_functions erro gerado por estar usando uma classe sem o devido import.

Após corrigir esses erros, ao rodar novamente ruff check . todas as verificações finalizaram sem problemas.

Buscando vulnerabilidades de dependências com Snyk

O Snyk é uma ferramenta de segurança para desenvolvedores, focada principalmente em detectar e corrigir vulnerabilidades de segurança em dependências de código, infraestrutura e pipelines de CI/CD.

O Snyk ajuda a proteger as aplicações contra problemas de segurança que podem ser introduzidos por pacotes e bibliotecas externas, além de oferecer monitoramento contínuo da segurança.

Como o Snyk atua na segurança de dependências

Análise de Dependências

  • O Snyk realiza a análise automática das dependências de um projeto. Ele escaneia tanto as dependências diretas (pacotes explicitamente incluídos no projeto) quanto as dependências transitivas (pacotes que essas dependências diretas exigem).
  • Ao escanear o projeto, o Snyk identifica as bibliotecas e versões usadas, e compara essas versões com uma base de dados de vulnerabilidades conhecidas, que contém informações sobre falhas de segurança já documentadas em várias bibliotecas populares.

Identificação de Vulnerabilidades:

  • Após realizar a análise, o Snyk identifica vulnerabilidades conhecidas nas dependências do projeto. Ele pode detectar problemas como:
    • CVE (Common Vulnerabilities and Exposures): O Snyk utiliza bancos de dados de CVEs para identificar falhas já publicadas na segurança de software.
    • Vulnerabilidades específicas de pacotes: O Snyk não se limita apenas a problemas CVE, ele também verifica por falhas específicas em pacotes e versões populares.
  • O Snyk também considera vulnerabilidades em tempo de execução e problemas relacionados a permissões de pacotes, garantindo que não haja riscos durante a execução do software.

Recomendações de Correção:

  • Para cada vulnerabilidade detectada, o Snyk fornece recomendações claras de como corrigi-las. Isso pode incluir:
    • Atualizar para uma versão segura da dependência.
    • Substituir uma dependência vulnerável por uma alternativa mais segura.
    • Aplicar patches (em alguns casos, se disponível).

Integrando o Ruff no CI/CD

Agora, vamos configurar o Ruff para ser executado automaticamente em um pipeline de CI/CD. Vou exemplificar o processo usando o GitHub Actions, mas o conceito é semelhante em outras ferramentas de CI/CD.

1 - Criar o arquivo de configuração do GitHub Actions

Na raiz do seu repositório, crie o arquivo .github/workflows/ruff.yml com o seguinte conteúdo:

name: Lint with Ruff

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  lint:
    runs-on: ubuntu-latest

    steps:
    - name: Check out repository
      uses: actions/checkout@v3

    - name: Set up Python
      uses: actions/setup-python@v3
      with:
        python-version: '3.x'

    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt
        pip install ruff  # Instala o Ruff

    - name: Run Ruff Linting
      run: ruff check .

Onde:

  • on: Define os eventos que acionam o workflow. Neste caso, ele será executado em:
    • push: Aciona o pipeline quando houver um push na branch main.
    • pull_request: Aciona o pipeline quando houver um pull request para a branch main.
  • jobs: Define os jobs do CI. O job lint será executado em um runner Ubuntu:
    • steps: Cada etapa do job:
      • Check out repository: Faz o checkout do código do repositório.
      • Set up Python: Configura o ambiente Python com a versão 3.x.
      • Install dependencies: Atualiza o pip e instala as dependências do projeto (definidas no requirements.txt), além de instalar o Ruff.
      • Run Ruff Linting: Executa o Ruff para verificar todos os arquivos Python do projeto.

2 - Adicionar o arquivo de configuração ao repositório

Use os comandos do Git para adicionar esse arquivo ao repositório remoto:

git add .github/workflows/ruff.yml
git commit -m "Adiciona pipeline de linting com Ruff"
git push origin main

3 - Verificar a execução do pipeline

Após configurar o GitHub Actions, sempre que houver um push ou pull_request para a branch main, o GitHub acionará o pipeline e executará a análise de linting do Ruff, ela pode ser visualizada na aba Actions do repositório:

Abas Action

Se houver problemas no código, eles serão exibidos nos logs do pipeline como abaixo:

Erros Ruff

Mas, caso contrário retornará sucesso em todas as etapas:

Erros Ruff

Pre-commit

O Pre-commit é uma ferramenta que configura verificações de qualidade de código e vulnerabilidades antes de um commit ser feito e publicar um código no repositório. Sua vantagem consiste em configuração simplificada e mitigação de riscos ao apontar falhas e problemas no seu código antes mesmo dele ser publicado.

Abaixo, veja como configurar o Pre-commit e realizar as verificações de qualidade e segurança no código:

Pré-requisitos:

Para utilizar a ferramenta, é necessário ter:

  • Git instalado no ambiente
  • Uma conta no Github
  • Recomendamos também a utilização de um projeto Python para inicializar um repositório Git e checar os recursos do pre-commit.

Projeto de exemplo

Você pode utilizar o projeto de exemplo que disponibilizamos clicando aqui

Setup do Pre-commit

Inicialmente, o Pre-commit pode ser instalado no seu ambiente como um pacote Python. Execute o comando abaixo no seu terminal:

Inicialize o git na pasta raíz do seu projeto:

git init
A seguir, iremos configurar o arquivo e ativar o pre-commit:

Configuração das verificações executadas no pre-commit:

Iremos indicar as verificações a serem feitas no código a partir de um arquivo chamado .pre-commit-config.yaml

Crie este arquivo na pasta-raíz de seu projeto, e em seguida, iremos configurar as seguintes verificações no arquivo:

  • Checagem de espaços em branco desnecessários
  • Checagem da ordem dos imports seguindo as práticas recomendadas do PEP
  • Indicador de linhas de código fora do padrão de formatação Python
  • Checagem de código vulnerável com bandit

O arquivo configurado ficará assim:

repos:
-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.5.0
    hooks:
    -   id: trailing-whitespace
    -   id: end-of-file-fixer
    -   id: check-yaml
-   repo: https://github.com/pycqa/isort
    rev: 5.13.2
    hooks:
    -   id: isort
-   repo: https://github.com/pycqa/flake8
    rev: 7.0.0
    hooks:
    -   id: flake8

-   repo: https://github.com/pycqa/bandit
    rev: 1.7.7
    hooks:
    -   id: bandit
        args: [ "-ll" ]
        files: .py$

Entendendo o arquivo .pre-commit-config.yaml

Este arquivo é a "receita" que o pre-commit utiliza para garantir que o seu código siga padrões de qualidade e segurança antes mesmo de ser enviado ao repositório (Git).

Aqui está o que cada parte faz:

1. pre-commit-hooks (Ferramentas de Limpeza Básica)

  • trailing-whitespace: Remove automaticamente espaços em branco inúteis no final das linhas de texto.

  • end-of-file-fixer: Garante que todos os arquivos terminem com uma linha vazia (padrão de sistemas Unix para evitar problemas de leitura de arquivos).

  • check-yaml: Verifica se a sintaxe de todos os arquivos .yaml ou .yml do projeto está correta.

2. isort (Organização de Importações)

  • isort: Organiza os seus imports no Python de forma alfabética e separada por seções (bibliotecas padrão, bibliotecas de terceiros e módulos locais). Isso evita bagunça no topo do código.

3. flake8 (Guia de Estilo e Erros)

  • flake8: É um linter que verifica se o seu código segue a PEP 8 (o manual de estilo do Python). Ele aponta variáveis não utilizadas, linhas muito longas e outros erros de formatação.

4. Bandit (Análise de Segurança)

Este é um ponto crítico para projetos profissionais e de IA:

  • bandit: Faz uma análise estática focada em segurança.

    • args: [ "-ll" ]: Configura o Bandit para reportar apenas problemas de nível de severidade Médio e Alto (ignorando os Baixos para evitar ruído).

    • files: .py$: Garante que o Bandit analise especificamente arquivos com extensão .py.

Por que isso é importante?

Ao rodar o git commit, o pre-commit executará todas essas ferramentas. Se o Bandit encontrar uma vulnerabilidade ou o Flake8 encontrar um erro de estilo, o commit será bloqueado, forçando você a corrigir o problema antes de seguir adiante.

Configurando o Ruff para rodar antes de um Commit (opcional)

Se você quiser garantir que o código seja verificado antes de ser comitado, pode usar uma ferramenta como pre-commit para integrar o Ruff diretamente ao processo de commit.

Aplicando verificações na prática com pre-commit:

Com o arquivo .pre-commit-config.yaml devidamente configurado, iremos testar e acompanhar as verificações retornadas pelo pre-commit:

Siga estes passos para instalar e ativar os hooks no seu repositório local.

Passo 1: Instalação da Ferramenta

Instale a ferramenta no seu ambiente virtual (é crucial instalá-la no seu venv ou conda).

# Garanta que seu ambiente virtual esteja ativo
pip install pre-commit

Passo 2: Configuração e Download dos Hooks

Certifique-se de que o arquivo .pre-commit-config.yaml (gerado acima) esteja na raiz do seu projeto.

Ao rodar este comando, o pre-commit lê o arquivo YAML e baixa todas as ferramentas (black, isort, etc.) para o ambiente de cache local:

pre-commit install

Você deve ver uma mensagem de sucesso como: pre-commit installed at .git/hooks/pre-commit.

Passo 3: Uso e Teste

O pre-commit agora está ativo. Não é necessário fazer mais nada; ele será acionado automaticamente em cada git commit.

  1. Faça uma alteração de teste: Deixe um import fora de ordem ou insira um espaço em branco no final de uma linha.
  2. Adicione e Comite:

    git add .
    git commit -m "feat: configurando pre-commit"
    

O que vai acontecer no commit?

  • Se houver correção automática (Black/isort): O pre-commit corrigirá o arquivo e o commit falhará com uma mensagem dizendo: Files were modified by the hooks. Re-run commit..
    • Você deve rodar git add . novamente (para incluir as correções) e, em seguida, git commit de novo.
  • Se houver erro de linting (Flake8): O commit falhará e você verá a linha exata do erro. Você deve corrigir o código manualmente