Skip to main content

Desenvolvendo regras personalizadas de IaC com a Snyk

Escrito por
Headshot of Teodora Sandu

Teodora Sandu

blog feature snyk iac magenta

18 de novembro de 2021

0 minutos de leitura

Em um mundo cada vez mais nativo da nuvem, a infraestrutura como código (IaC) costuma ser o primeiro ponto de entrada em uma aplicação. E, com tecnologias como Kubernetes e Terraform se tornando cada vez mais populares, a maioria dos desenvolvedores de aplicações vai atualizar pelo menos um recurso de Kubernetes ou Terraform em algum momento da carreira.

Embora atualizar e manter a infraestrutura possa ser tão simples quanto gerenciar alguns arquivos de configuração — ou tão complexo quanto orquestrar uma arquitetura com várias stacks nativas da nuvem —, uma coisa não muda: a segurança da infraestrutura é essencial para a segurança das aplicações. E, embora muitos provedores de nuvem e ferramentas de análise de IaC ofereçam conjuntos de regras de configuração e segurança integrados ou criados pela comunidade, a infraestrutura costuma ser diversa e complexa demais para uma abordagem única que proteja tudo.

Neste artigo, vou mostrar como proteger seu ambiente de infraestrutura com regras personalizadas do Snyk IaC. Com o SDK de regras do Snyk IaC (snyk-iac-rules), você pode criar, testar e empacotar regras de infraestrutura personalizadas para a Snyk CLI.

Ganhe flexibilidade com o Open Policy Agent (OPA)

Nos bastidores, o Snyk IaC usa o Open Policy Agent (OPA), um agente geral de políticas de código aberto, e sua linguagem Rego para definir regras personalizadas. Como agente independente de frameworks, o OPA facilita a adaptação e a aplicação de políticas em toda a stack nativa da nuvem, seja para infraestrutura, autorização de aplicações ou controle de admissão do Kubernetes.

Como as regras são escritas na linguagem de consulta nativa do OPA, elas também podem ser exportadas e reutilizadas fora da Snyk. Isso significa que todo o investimento feito aqui pode ser aproveitado em todo o ecossistema de integrações do OPA.

Para acompanhar este passo a passo, você precisa ter conhecimentos básicos de OPA, além de WebAssembly (Wasm) e artefatos OCI, que usamos para empacotar e distribuir as regras.

Proteja melhor com regras personalizadas

As regras personalizadas permitem atender a cada caso de uso específico e são uma ferramenta poderosa quando combinadas com conjuntos de regras pré-criados e modelados contra ameaças por especialistas em segurança.

Como exemplo de regra personalizada, imagine que sou arquiteto de segurança e tenho um requisito interno específico: todos os recursos Terraform aws_iam_role da nossa aplicação precisam ter tags de proprietário, descrição e tipo.

Isso significa que eu precisaria executar uma regra que:

  • Garanta que todos os recursos de função do IAM, existentes ou futuros, tenham tags de proprietário, descrição e tipo

  • Notifique os desenvolvedores de aplicações quando esquecerem de adicionar as tags.

Também quero configurar nosso CI/CD para falhar quando uma alteração no código não seguir esse padrão, evitando que ela chegue aos ambientes de produção.

Como fazer isso? Configurando a Snyk CLI para ser executada no meu CI/CD com um conjunto personalizado de regras, que vou criar, empacotar e publicar em um local seguro à minha escolha.

Desenvolvendo uma regra personalizada de IaC com a Snyk

Com o novo SDK de regras do Snyk IaC, posso fazer exatamente isso. Instalo o SDK na minha máquina e, com a ajuda da documentação sobre regras personalizadas, posso aplicar rapidamente meu novo padrão de tags na Snyk CLI.

Veja como exemplo o recurso Terraform a seguir, que quero incluir as tags owner, description e type:

resource "aws_iam_role" "denied" {
  name = "denied"
  assume_role_policy = jsonencode({
      Version   = "2012-10-17"
      Statement = [
        {
          Action    = "sts:AssumeRole"
          Effect    = "Allow"
          Sid       = ""
          Principal = {
            Service = "ec2.amazonaws.com"
          }
        },
      ]
  })
  tags = {
    description = "a tag that describes something"
  }
}

Seguindo as instruções para começar na documentação sobre regras personalizadas, executo o comando template para gerar uma regra básica:

$ snyk-iac-rules template --rule CUSTOM-RULE-8

Quero que o padrão de tags seja uma regra de severidade média. Então, ajusto o template e personalizo o título e a mensagem:

package rules

aws_iam_role_tags_missing(resource) {
    not resource.tags.owner
}

aws_iam_role_tags_missing(resource) {
    not resource.tags.description
}

aws_iam_role_tags_missing(resource) {
    not resource.tags.type
}

deny[msg] {
    resource := input.resource.aws_iam_role[name]
    aws_iam_role_tags_missing(resource)

    msg := {
        "publicId": "CUSTOM-RULE-8",
        "title": "IAM Role missing one of the required tags: owner, description or type",
        "severity": "medium",
        "msg": sprintf("input.resource.aws_iam_role[%s].tags", [name]),
        "issue": "",
        "impact": "",
        "remediation": "",
        "references": [],
    }
}

Antes de empacotar e publicar a regra, escrevo alguns testes unitários para verificar seu comportamento e adiciono meu arquivo Terraform de exemplo ao arquivo ./rules/CUSTOM-RULE-8/fixtures/denied2.tf gerado:

package rules

import data.lib
import data.lib.testing

test_CUSTOM_RULE_8 {
        # array containing test cases where the rule is allowed
        allowed_test_cases := []

        # array containing cases where the rule is denied
        denied_test_cases := [{
            "want_msgs": ["input.resource.aws_iam_role[denied].tags"],
            "fixture": "denied2.tf",
        }]

        test_cases := array.concat(allowed_test_cases, denied_test_cases)
        testing.evaluate_test_cases("CUSTOM-RULE-8", "./rules/CUSTOM-RULE-8/fixtures", test_cases)
}

Você encontra esta regra e outras no nosso repositório público no GitHub.

$ snyk-iac-rules test
PASS: 1/1

Depois de executar os testes e confirmar que foram aprovados, empacoto a regra usando o SDK e também posso testá-la localmente com a Snyk CLI, usando a flag --rules. Primeiro, confirmo que estou autenticado em uma organização test-org, onde pretendo fazer todos os meus testes com regras personalizadas daqui em diante:

$ snyk auth

Em seguida, crio o pacote das minhas regras personalizadas e o passo para a flag --rules para confirmar que os problemas de IaC são sinalizados:

$ snyk-iac-rules build .
Generated bundle: bundle.tar.gz

$ snyk iac test --rules=bundle.tar.gz ./fixtures/custom-rules/rules/CUSTOM-RULE-8/fixtures/denied2.tf

Testing ./fixtures/custom-rules/rules/CUSTOM-RULE-8/fixtures/denied2.tf...

Infrastructure as code issues:
  ✗ IAM Role missing one of the required tags: owner, description or type [Medium Severity] [CUSTOM-RULE-8]
    introduced by input > resource > aws_iam_role[denied] > tags

Organization:      test-org
Type:              Terraform
Target file:       ./fixtures/custom-rules/rules/CUSTOM-RULE-8/fixtures/denied2.tf
Project name:      fixtures
Open source:       no
Project path:      ./fixtures/custom-rules/rules/CUSTOM-RULE-8/fixtures/denied2.tf

Tested ./fixtures/custom-rules/rules/CUSTOM-RULE-8/fixtures/denied2.tf for known issues, found 1 issues

Depois de confirmar que a Snyk CLI consegue interpretar minha regra, envio-a para um registro OCI — neste caso, o DockerHub — e identifico-a como a primeira versão das minhas regras personalizadas. Assim, se eu fizer alterações incompatíveis no futuro, poderei implementá-las gradualmente usando uma nova tag:

$ snyk-iac-rules push --r docker.io/snykgoof/oci-example:v1 bundle.tar.gz

Por fim, aplico a nova regra personalizada a todas as equipes do meu departamento, configurando as definições de IaC do meu grupo Snyk pela API pública de configurações de IaC do grupo.

curl --location --request PATCH 'https://api.snyk.io/v3/groups/<group_id>/settings/iac/?version=2021-11-03~beta' \
--header 'Content-Type: application/vnd.api+json' \
--header 'Authorization: token <API key from Snyk>' \
--data-raw '{
   "data": {
         "type": "iac_settings",
         "attributes": {
           "custom_rules": {
             "oci_registry_url": "https://registry-1.docker.io/snykgoof/oci-example",
             "oci_registry_tag": "v1",
             "is_enabled": true
           }
       }
   }
}'

Automatizei todas essas etapas usando um workflow de GitHub Actions, como você pode ver no nosso repositório público no GitHub. Agora, qualquer desenvolvedor de aplicações ou pipeline de CI/CD autenticado em uma organização do meu grupo usará minha regra personalizada. Para saber mais sobre como integrar a Snyk CLI e o SDK de regras do Snyk IaC ao GitHub, consulte nossa documentação.

Se decidirmos aplicar regras personalizadas diferentes em partes distintas da empresa, também podemos substituir as configurações de regras personalizadas no nível da organização e executar um conjunto diferente de regras somente para ela. Por exemplo, para continuar usando a flag --rules e testar minhas regras personalizadas com a Snyk CLI, configurei minha organização test-org para desativar as configurações de regras personalizadas. Assim, posso fornecer minhas próprias regras personalizadas localmente:

Configurações do Snyk Infrastructure as Code mostrando a detecção de arquivos de configuração ativada e as regras personalizadas desativadas

No futuro, posso decidir que a equipe de Plataforma precisa de um conjunto de regras personalizadas mais restritivo. Nesse caso, vou configurar a organização dela para usar outro pacote de regras personalizadas, armazenado em um artefato OCI diferente.

Aproveitando os benefícios das regras personalizadas do Snyk IaC

Vimos como eu, na função de arquiteto de segurança, usei o SDK de regras do Snyk IaC para configurar novos padrões de segurança para meu departamento. Agora, vamos ver como eu, como desenvolvedor de aplicações, me beneficio desse recurso durante o desenvolvimento.

Imagine que estou adicionando um novo recurso aws_iam_role à infraestrutura Terraform da nossa aplicação para configurar uma nova função do IAM:

resource "aws_iam_role" "new_role" {
  name               = "new_role"
  assume_role_policy = jsonencode({
    Version   = "2021-11-18"
    Statement = [
      {
        Action    = "sts:AssumeRole"
        Effect    = "Allow"
        Sid       = ""
        Principal = {
          Service = "ec2.amazonaws.com"
        }
      },
    ]
  })
}

Testei tudo localmente e confirmei que minha função do IAM foi configurada corretamente. Porém, esqueci que meu departamento exige tags muito rigorosas para todos os recursos. Quando vou abrir um PR, percebo que o repositório para o qual estou enviando as alterações foi configurado para executar a GitHub Action do Snyk IaC e que ela está falhando.

Status de pull request do GitHub mostrando que é necessária uma revisão, uma verificação de segurança personalizada de IaC reprovada, cinco verificações aprovadas e a mesclagem bloqueada.

Analiso os resultados e percebo que meu novo arquivo está fazendo a verificação do PR falhar. Mais especificamente, está faltando a tag owner, description e type no meu recurso.

Log do GitHub Actions mostrando uma verificação do Snyk Infrastructure as Code com falha, que detectou a ausência de uma tag obrigatória de função do IAM pela regra personalizada CUSTOM-RULE-8

Volto ao código e adiciono as tags que faltavam. Agora, depois que envio minha alteração e a verificação do PR é executada novamente, posso enviar o novo recurso ao nosso ambiente de produção com segurança e confiança!

Proteja suas aplicações com o Snyk IaC

O Snyk Infrastructure as Code (Snyk IaC) ajuda você a desenvolver com rapidez e segurança, oferecendo aos desenvolvedores inteligência de segurança e correções em linha para Terraform, CloudFormation, configurações de Kubernetes e modelos ARM, que podem ser incorporadas diretamente ao código.

O Snyk IaC se integra às ferramentas que os desenvolvedores já usam, como Terraform Cloud e ferramentas de CI/CD, além de ferramentas para desenvolvedores, como sistemas de gerenciamento de código-fonte (GitHub, GitLab, Bitbucket) e IDEs.

Comece agora gratuitamente a usar o Snyk IaC na nossa plataforma ou baixe a versão mais recente da Snyk CLI.

Proteja a infraestrutura desde a origem

A Snyk automatiza a segurança e a conformidade de IaC nos fluxos de trabalho e detecta recursos com configurações divergentes ou ausentes.