Image Scanning - protegendo suas imagens e sua organização


No primeiro cápitulo da nossa série sobre segurança de contêineres, vamos falar sobre Image Scanning, um assunto de extrema necessidade, muito considerado por empresas que levam segurança a sério mas que se apresenta com fragilidades frequentes!
O que é?
Sabemos que ao construirmos uma aplicação contêinerizada, temos que começar com algo. Nossa aplicação e suas dependências devem ser instaladas e configuradas em alguma coisa. Esse alguma coisa é uma Imagem Base.
Como o próprio nome já diz, nosso contêiner será inicializado com essa imagem, que por sua vez receberá todas as instruções declaradas posteriormente no arquivo de configuração (como um Dockerfile, por exemplo).
Abaixo temos um exemplo do início da configuração de um Dockerfile que mostra exatamente onde declaramos a imagem base da nossa aplicação.
FROM alpine:latest AS base
Após inicializarmos o contêiner com essa imagem base, vamos passar para todos os outros passos.
Copiar os arquivos da aplicação.
Instalar dependências.
Passar argumentos e variáveis de ambiente.
Todo esse processo tornará a imagem final do contêiner muito mais complexa, visto que a mesma terá uma série de outros componentes dentro de si.
Conforme vamos adicionando essas “camadas”, não é apenas a complexidade da nossa aplicação que vai crescendo, mas também sua superfície de exposição, visto que a versão do framework que você está utilizando também tem vulnerabilidades já conhecidas, somadas as libs e outros componentes instalados para que sua aplicação funcione, no final da construção do arquivo teremos uma lista imensa de vulnerabilidades e de preocupações, que precisarão ser direcionadas.
Para garantir as aplicações executadas em seu ambiente estejam bem mapeadas e que não apresentem nenhum grande risco ao contexto maior da sua plataforma, integramos em nossos workflows uma ferramenta de Image Scanning, como o Docker Scout e Aqua Trivy.
Por quê utilizar?
Se pensarmos em todo o ciclo de desenvolvimento de software e como hoje em dia as empresas trabalham em um modelo distribuído, as capacidades de segurança também tiveram que se modernizar e passaram a ser construídas de forma decentralizada. Os times de segurança e plataforma ainda as controlam e parametrizam porém o primeiro contato do desenvolvedor/engenheiro com um recurso PRECISA ser um contato seguro, caso contrário temos mais uma demonstração de abertura de brecha no ambiente.
Acima temos um desenho simples sobre como funciona uma pipeline CI/CD. No terceiro passo, que é de fato onde o build da aplicação se inicia, a pipeline buscará no arquivo de configuração os recursos apontados.
Dentro de uma organização, é importante deixar claro que JAMAIS deve-se buscar imagens diretamente da internet. Os requisitos de segurança são variados de acordo com a criticidade dos serviços que sua empresa presta e acima de tudo devem ser modificados pelos times de segurança, compliance, auditoria e jurídico. Dito isso, as imagens utilizadas de forma corporativa devem passar por um extenso processo de análise, que visa garantir a qualidade do artefato inicialmente utilizado.
E essa é um dos momentos que entra o nosso image scanning.
Acima, um print retirado diretamente da console do Docker Desktop rodando o Docker Scout. Podemos visualizar na esquerda as duas camadas que essa imagem contém e à direita todas as dependências dela, bem como suas vulnerabilidades.
Essa visão nos permite entender o estado em que aquele recurso se apresenta e à partir do apetite a risco da sua organização, qual será a origem dele.
Mesmo podendo ser utilizado dessa maneira, o image scanning não costuma estar “na mão” dos engenheiros de software, mas sim nos times de Plataform Engineering e Segurança, isso sem falar das integrações através das pipelines, que falaremos sobre agora!
CI/CD Integration
O primeiro scanning que falamos é extremamente necessário para criarmos a base da nossa pipeline, que é: fornecer imagens base seguras e com vulnerabilidades controladas/aceitas pela empresa em questão.
Ao longo do processo de build, as dependências serão instaladas no contêiner e no final da execução, um “pacotinho” será gerado, que contém a aplicação autossuficiente (com tudo que ela precisa para ser executada). Esse pacotinho deve mais uma vez ser analizado pelo nosso image scanner para avaliar algum problema de configuração que possa ter passado em branco.
No final do ciclo, sua imagem conterá tudo que precisa para ser executada e esse é o motivo da segunda validação.
Nós passamos de uma image base, que já continha algumas dependências e possivelmente vulnerabilidades, para uma imagem “carregada” e com vários outros componentes adicionados. A única forma de garantirmos a boa proteção das nossas imagens é realizar essa validação em camadas, garantindo sempre que pelo menos uma validação tenha sido feita nas novas adições daquele componente.
Dentro de uma pipeline, a análise da imagem estará próxima do final do ciclo de execução da mesma, fornecendo em grande parte das vezes um score que nos permite determinar se aquele insumo está seguro ou não para ser utilizado.
Container security é crucial para que sua estratégia de cloud security seja efetiva. Visto que hoje tudo é contêinerizado, é de extrema importância que você proteja bem sua plataforma.
Espero que tenha gostado do texto. Nos vemos no próximo!! :)
Subscribe to my newsletter
Read articles from Pedro Ignácio directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Pedro Ignácio
Pedro Ignácio
Engenheiro DevOps especialista em Cloud Security e IAM. Gosto de pizza, open source e tudo que traz a comunidade junto!