Skip to main content

Melhorar a cobertura de recursos de nuvem para reduzir desvios da infraestrutura

Escrito por:
Stephane Jourdan
Stephane Jourdan
wordpress-sync/feature-iac-drift-purple

23 de março de 2022

0 minutos de leitura

Aviso de descontinuidade Detecção de desvios em recursos gerenciados

A detecção de desvios em recursos gerenciados, incluindo snyk iac describe --only-managed and snyk iac describe --drift, foi descontinudada. A data de fim de vida útil da detecção de desvios de recursos gerenciados foi 30 de setembro de 2023.

A equipe de desenvolvimento precisa de visibilidade máxima do que está execução nos nossos ambientes de nuvem para mantê-los seguros. A infraestrutura como código (IaC) ajuda os desenvolvedores a automatizar as infraestruturas de nuvem, de modo que o que for implantado na nuvem fique sob controle e possa ser facilmente auditado, mas alcançar e manter 100% de cobertura de IaC da sua infraestrutura apresenta muitos desafios.

A segurança é diretamente proporcional aos recursos implantados e em execução nos ambientes de nuvem. Na maioria das vezes, muitas ações manuais ainda são realizadas regularmente, por nós, outras equipes ou alguns serviços autenticados. Essas alterações ficam ocultas para IaC e auditorias, o que gera problemas como configurações incorretas e preocupações de segurança. É nesse momento que o gerenciamento de desvios mostra seu valor: queremos relatórios de recursos que ainda não estão sob o controle da IaC ou que foram alterados por algum motivo.

Neste artigo, vamos mostrar como o Snyk IaC ajuda os desenvolvedores a descobrir recursos de nuvem que não estão sob controle da infraestrutura como código (IaC) (recursos não gerenciados) ou que se descompassaram dos estados esperados (recursos gerenciados).

Configurar o ambiente

O Snyk IaC ajuda a listar os recursos encontrados como recursos do Terraform para que você determine com facilidade qual parte do serviço de nuvem é o alvo da descoberta. Por exemplo, um único serviço do Amazon API Gateway v2 é composto de pelo menos 12 recursos do Terraform. Com as informações de descoberta fornecidas pela Snyk, você poderá decidir imediatamente se deseja reverter a modificação, importar um novo recurso ou simplesmente excluir essa nova alteração.

Para acompanhar o exemplo, use o arquivo do Terraform abaixo para criar dois recursos da AWS que usaremos nas instruções. Ele cria um usuário do IAM chamado “user1” com um sufixo aleatório, uma chave de acesso e uma política anexada para acesso somente leitura.

Na redação do artigo, usamos o Terraform v1.1.7 com o provedor da AWS v3.74.2

Reutilize a seguinte configuração de HCL:

main.tf

1resource "random_string" "prefix" {
2  length  = 6
3  upper   = false
4  special = false
5}
6
7resource "aws_iam_user" "user1" {
8  name = "user1-${random_string.prefix.result}"
9
10  tags = {
11    Name = "user1-${random_string.prefix.result}"
12    manual = "true"
13  }
14}
15
16resource "aws_iam_access_key" "user1" {
17  user = aws_iam_user.user1.name
18}
19
20resource "aws_iam_user_policy_attachment" "user1" {
21  user       = aws_iam_user.user1.name
22  policy_arn = "arn:aws:iam::aws:policy/ReadOnlyAccess"
23}

Aplique esta configuração do Terraform:

1$ terraform init
2[...]
3$ terraform apply
4[...]

Confirme se você tem um terraform.tfstate na raiz do diretório:

1$ ls -al terraform.tfstate
2-rw-r--r--  1 sjourdan  staff  5049 Mar 16 18:31 terraform.tfstate

Confirme também se o usuário do IAM foi criado com sucesso na AWS.

Começando do zero

Para começar, vamos listar todos os recursos da nuvem que não estão sob o controle do Terraform:

1$ snyk iac describe --only-unmanaged

Você provavelmente acabará com uma lista imensa de recursos que não estão sob o controle do Terraform. Essas informações são ótimas, mas não são muito úteis para o nosso caso. O Snyk IaC tem uma maneira integrada de ignorar recursos em massa, adicionando todos os recursos encontrados ao arquivo de política .snyk.

Vamos ignorar todos esses recursos não gerenciados existentes para trabalhar com mais precisão em um ambiente controlado só com os dois que criamos acima:

1$ snyk iac describe --only-unmanaged --json  | snyk iac update-exclude-policy

Repita a verificação para confirmar se seu ambiente está ignorando ativamente os desvios descobertos (você terá todo o tempo do mundo mais tarde para agendar a importação deles). 

1$ snyk iac describe --only-unmanaged
2
3Scanned states (1)
4Found 3 resource(s)
5 - 100% coverage
6Congrats! Your infrastructure is fully in sync.

Agora estamos com tudo pronto para começar do zero.

Exploração dos desvios com o IAM!

Agora vamos criar três tipos de desvios para simular situações reais:

  1. Uma modificação no usuário do IAM existente (a ser removida)

  2. Um anexo manual de uma nova política do IAM (a ser removida)

  3. Um novo usuário do IAM (a ser aprimorado)

Navegue até o console da AWS para o IAM.

Modifique o usuário do IAM existente adicionando uma tag

  1. Na página de usuários do IAM, clique em “user1”

  2. Clique na guia Tags

  3. Clique no botão Edit Tags (Editar tags)

  4. Adicione uma nova chave (“environment”) e um novo valor (“production”)

  5. Clique em Save (Salvar)

Anexe uma política poderosa ao usuário do IAM existente

  1. Na página de usuários do IAM, clique em “user1”

  2. Clique na guia Permissions (Permissões)

  3. Clique no botão Add permissions (Adicionar permissões)

  4. Clique em Attach existing policies directly (Anexar políticas existentes diretamente)

  5. Selecione Administrator Access (Acesso de administrador)

  6. Clique em Next: Review (Avançar: revisão)

  7. Valide clicando em Add permissions (Adicionar permissões)

Crie outro usuário do IAM manualmente

  1. Na página de usuários do IAM, clique no botão Add Users (Adicionar usuários)

  2. Insira “user2” no campo User name: (Nome de usuário:)

  3. Selecione Access key (Chave de acesso)

  4. Clique no botão Next: Permissions (Avançar: permissões)

  5. Não defina permissões nem tags

  6. Clique em Create user (Criar usuário) (as credenciais exibidas não importam, então você pode descartá-las)

Agora já cuidamos dos preparativos para lidar com esses tipos de alterações manuais usando a detecção de desvios do Snyk IaC.

desvios de infraestrutura gerenciados e não gerenciados

Agora vamos descobrir como as alterações são detectadas pelo Snyk IaC, começando com recursos não gerenciados pelo Terraform.

1$ snyk iac describe --only-unmanaged
2
3Scanned states (1)
4Found resources not covered by IaC:
5  aws_iam_access_key:
6    - AKIASBXWQ3AYQETE6OFR
7        User: user2
8  aws_iam_policy_attachment:
9    - user1-84i30k-arn:aws:iam::aws:policy/AdministratorAccess
10  aws_iam_user:
11    - user2
12Found 6 resource(s)
13 - 50% coverage
14 - 3 resource(s) managed by Terraform
15 - 3 resource(s) not managed by Terraform
16 - 0 resource(s) found in a Terraform state but missing on the cloud provider

Usando os termos de recursos do Terraform, a verificação relatou o seguinte:

  • O usuário do IAM “user2” criado manualmente, com sua chave de acesso do IAM

  • A política do IAM anexada manualmente ao usuário do IAM “user1” gerenciado pelo Terraform

Vamos conferir se há alterações apenas nos recursos gerenciados pelo Terraform que estão nos vários estados do Terraform:

1$ snyk iac describe –only-managed
2Scanned states (1)
3Found changed resources:
4  From tfstate://terraform.tfstate
5    - user1-84i30k (aws_iam_user.user1):
6        + tags.environment: <nil> => "production"
7Found 5 resource(s)
8 - 100% coverage
9 - 5 resource(s) managed by Terraform
10     - 1/5 resource(s) out of sync with Terraform state
11 - 0 resource(s) found in a Terraform state but missing on the cloud provider

Essa verificação gerou um resultado muito diferente e foi bem mais demorada (36 segundos em vez de 9 do modo de verificação “não gerenciado”).

Usando esse resultado, descobrimos que o usuário do IAM chamado “user1-84i30k”, que podemos encontrar na HCL (como um recurso) sob o nome “user1”, tem uma tag chamada “environment” definida como “production”.

Plano de ação

A ferramenta de detecção de desvios da Snyk nos ajudou a descobrir quatro diferenças inesperadas entre nossas expectativas e a realidade. Para os fins deste artigo, digamos que a equipe decida o seguinte:

  • O usuário do IAM “user2” é usado em produção e deve ser importado no Terraform.

  • A chave de acesso do IAM “user2” deve ser alternada por motivos de segurança.

  • “user1” não deve, sob nenhuma circunstância, ser um administrador.

  • A nova tag “user1” é exigida por alguns requisitos e deve ser importada no Terraform.

O que

Tipo de recurso

Nome

Tipo de descompasso

Ação

Um usuário do IAM

aws_iam_user

user2

Não gerenciado

IMPORTAR

Uma chave de acesso do IAM

aws_iam_access_key

AKIASBXWQ3AYQETE6OFR

Não gerenciado

ALTERNAR

Uma política do IAM anexada

aws_iam_policy_attachment

arn:aws:iam::aws:policy/AdministratorAccess

Não gerenciado

EXCLUIR

Uma tag em um usuário do IAM

aws_iam_user

tags.environment

Gerenciado

IMPORTAR

Pipelines de implantação não são remediação

Temos um ótimo pipeline de implantação do Terraform e, da próxima vez que o comando terraform apply for acionado, poderemos esperar que as coisas voltem ao normal.

Nesse caso, o que o Terraform fará? Um trabalho de implantação:

1$ terraform apply
2Terraform will perform the following actions:
3
4  # aws_iam_user.user1 will be updated in-place
5  ~ resource "aws_iam_user" "user1" {
6        id            = "user1-84i30k"
7        name          = "user1-84i30k"
8      ~ tags          = {
9          - "environment" = "production" -> null
10            # (1 unchanged element hidden)
11        }
12[...]
13
14Plan: 0 to add, 1 to change, 0 to destroy.

O Terraform não tem o objetivo de descobrir recursos criados ou anexados manualmente, então ele reverterá os que foram modificados para o estado original (mas não é isso que queremos neste caso).

O que

Tipo de recurso

Nome

Tipo de descompasso

Ação

Um usuário do IAM

aws_iam_user

user2

Não gerenciado

NENHUMA

Uma chave de acesso do IAM

aws_iam_access_key

AKIASBXWQ3AYQETE6OFR

Não gerenciado

NENHUMA

Uma política do IAM anexada

aws_iam_policy_attachment

arn:aws:iam::aws:policy/AdministratorAccess

Não gerenciado

NENHUMA

Uma tag em um usuário do IAM

aws_iam_user

tags.environment

Gerenciado

REVERTER

Não é a ajuda que esperamos em nenhum dos casos:

  • O usuário do IAM criado manualmente e sua chave de acesso não são relatados (inútil)

  • A política de administrador anexada manualmente a um usuário gerenciado não é relatada (inútil)

  • A tag importante adicionada manualmente a um usuário gerenciado será revertida (prejudicial)

Um tipo diferente de ferramenta é necessário para esse tipo de detecção e trabalho.

Melhorar nossa cobertura

Começamos a jornada com 50% de cobertura para os recursos não gerenciados:

1$ snyk iac describe --only-unmanaged
2
3Scanned states (1)
4Found resources not covered by IaC:
5  aws_iam_access_key:
6    - AKIASBXWQ3AYQETE6OFR
7        User: user2
8  aws_iam_policy_attachment:
9    - user1-84i30k-arn:aws:iam::aws:policy/AdministratorAccess
10  aws_iam_user:
11    - user2
12Found 6 resource(s)
13 - 50% coverage
14 - 3 resource(s) managed by Terraform
15 - 3 resource(s) not managed by Terraform
16 - 0 resource(s) found in a Terraform state but missing on the cloud provider

Vamos melhorar isso com base no plano da equipe.

Excluir a política do IAM de “user1”

Vamos começar com o mais urgente e fácil: remover a política de administrador do usuário do IAM gerenciado “user1”:

  • Acesse IAM > Users (Usuários) > “user1”

  • Clique em Permissions (Permissões) e exclua “AdministratorAccess”

1$ snyk iac describe --only-unmanaged
2Scanned states (1)
3Found resources not covered by IaC:
4  aws_iam_access_key:
5    - AKIASBXWQ3AYQETE6OFR
6        User: user2
7  aws_iam_user:
8    - user2
9Found 5 resource(s)
10 - 60% coverage
11 - 3 resource(s) managed by Terraform
12 - 2 resource(s) not managed by Terraform

Agora aumentamos de 50% para 60% a cobertura dos recursos da AWS.

O que

Tipo de recurso

Nome

Tipo de descompasso

Ação

Status

Um usuário do IAM

aws_iam_user

user2

Não gerenciado

IMPORTAR

Uma chave de acesso do IAM

aws_iam_access_key

AKIASBXWQ3AYQETE6OFR

Não gerenciado

ALTERNAR

Uma política do IAM anexada

aws_iam_policy_attachment

arn:aws:iam::aws:policy/AdministratorAccess

Não gerenciado

EXCLUIR

*

Uma tag em um usuário do IAM

aws_iam_user

tags.environment

Gerenciado

ADICIONAR

Vamos continuar.

Desbloqueie o pipeline de implantação do Terraform

O pipeline está bloqueado pela alteração manual nas tags para aws_iam_user.user1. Se ocorrer alguma implantação, as tags serão revertidas para o que está na HCL. Então qual é a solução? Usar o resultado de desvios do Snyk IaC para adaptar a configuração do Terraform.

As informações que temos são as seguintes:

1Found changed resources:
2  From tfstate://terraform.tfstate
3    - user1-84i30k (aws_iam_user.user1):
4        + tags.environment: <nil> => "production"

Sabemos a partir do resultado que:

  • Estamos procurando um recurso aws_iam_user chamado “user1”

  • Esse recurso é encontrado em terraform.tfstate (muito útil quando existem dezenas ou centenas de estados)

  • Há uma nova chave de tag chamada environment com um valor de “production”

Vamos adicionar environment = “production” para atualizar o recurso de usuário do IAM. Agora o recurso agora fica assim:

1resource "aws_iam_user" "user1" {
2 name = "user1-${random_string.prefix.result}"
3
4 tags = {
5   Name = "user1-${random_string.prefix.result}"
6   environment = "production"
7 }
8}

Agora podemos desbloquear o pipeline de implantação do Terraform com segurança:

1$ terraform apply
2No changes. Your infrastructure matches the configuration.
3Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Corrigimos nossos desvios “gerenciados” por enquanto:

1$ snyk iac describe --only-managed
2Scanned states (1)
3Found 3 resource(s)
4 - 100% coverage
5Congrats! Your infrastructure is fully in sync.

O que

Tipo de recurso

Nome

Tipo de descompasso

Ação

Status

Um usuário do IAM

aws_iam_user

user2

Não gerenciado

IMPORTAR

Uma chave de acesso do IAM

aws_iam_access_key

AKIASBXWQ3AYQETE6OFR

Não gerenciado

ALTERNAR

Uma política do IAM anexada

aws_iam_policy_attachment

arn:aws:iam::aws:policy/AdministratorAccess

Não gerenciado

EXCLUIR

*

Uma tag em um usuário do IAM

aws_iam_user

tags.environment

Gerenciado

ADICIONAR

*

Importar e alternar o usuário do IAM user2

Agora vamos lidar com o caso de “user2”. O que queremos:

  • Importá-lo para o Terraform

  • Alternar a chave

Vamos começar importando o usuário do IAM para o Terraform. Confira a seguir uma maneira simples de fazer isso.

Comece coletando as informações do Snyk IaC:

Tipo de recurso

Nome

aws_iam_user

user2

Como importamos um recurso aws_iam_user? De acordo com a documentação oficial do TerraformOs usuários do IAM podem ser importados usando o atributoname, como $ terraform import aws_iam_user.lb loadbalancer.

Também podemos ler que o único argumento necessário é name. Então vamos adicionar esta estrutura básica ao arquivo HCL:

1resource "aws_iam_user" "user2" {
2 name = "user2" # required
3}

Agora vamos importar este usuário para o Terraform:

1$ terraform import aws_iam_user.user2 user2
2aws_iam_user.user2: Importing from ID "user2"...
3aws_iam_user.user2: Import prepared!
4  Prepared aws_iam_user for import
5aws_iam_user.user2: Refreshing state... [id=user2]
6
7Import successful!

Como nossa cobertura evoluiu? Vamos descobrir:

1$ snyk iac describe --only-unmanaged
2Scanned states (1)
3Found resources not covered by IaC:
4  aws_iam_access_key:
5    - AKIASBXWQ3AYQETE6OFR
6        User: user2
7Found 5 resource(s)
8 - 80% coverage
9 - 4 resource(s) managed by Terraform
10 - 1 resource(s) not managed by Terraform

Agora estamos com 80% de cobertura (antes era 60%) e resta apenas um recurso.

O que

Tipo de recurso

Nome

Tipo de descompasso

Ação

Status

Um usuário do IAM

aws_iam_user

user2

Não gerenciado

IMPORTAR

*

Uma chave de acesso do IAM

aws_iam_access_key

AKIASBXWQ3AYQETE6OFR

Não gerenciado

ALTERNAR

Uma política do IAM anexada

aws_iam_policy_attachment

arn:aws:iam::aws:policy/AdministratorAccess

Não gerenciado

EXCLUIR

*

Uma tag em um usuário do IAM

aws_iam_user

tags.environment

Gerenciado

ADICIONAR

*

Alternar a chave

Chegou a hora de lidar com a chave. Sabemos que o objetivo é alternar a chave enquanto a adicionamos ao Terraform. Vamos começar adicionando a nova chave à HCL para criar outra (para a fornecermos à equipe relevante, por exemplo) e depois excluir a chave antiga da AWS.

A documentação do Terraform sobre aws_iam_access_key é bastante direta, então podemos criar um recurso que usa o nome user2 como argumento:

1resource "aws_iam_access_key" "user2" {
2 user = aws_iam_user.user2.name
3}

Como o pipeline de implantação foi desbloqueado antes, podemos aplicar isso de maneira segura usando o Terraform para criar uma nova chave:

1$ terraform apply 
2[...]
3Terraform will perform the following actions:
4
5  # aws_iam_access_key.user2 will be created
6  + resource "aws_iam_access_key" "user2" {
7      + create_date          = (known after apply)
8      + encrypted_secret     = (known after apply)
9      + id                   = (known after apply)
10      + key_fingerprint      = (known after apply)
11      + secret               = (sensitive value)
12      + ses_smtp_password_v4 = (sensitive value)
13      + status               = "Active"
14      + user                 = "user2"
15    }
16
17Plan: 1 to add, 0 to change, 0 to destroy.
18
19aws_iam_access_key.user2: Creating...
20aws_iam_access_key.user2: Creation complete after 1s [id=AKIASBXWQ3AY4KPUNIHZ]
21
22Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Ainda temos a chave antiga para remover. Usando as informações do resultado gerada pelo Snyk IaC, sabemos que o nome da chave é AKIASBXWQ3AYQETE6OFR.

A maneira mais simples de remover essa chave é:

  • Acesse IAM > Users (Usuários) > user2 > Security Credentials (Credenciais de segurança)

  • Remova a chave AKIASBXWQ3AYQETE6OFR conforme informado pelo Snyk IaC. Para fazer isso, primeiro desative-a e depois a exclua.

Como ficou a cobertura agora?

1$ snyk iac describe --only-unmanaged
2Scanned states (1)
3Found 5 resource(s)
4 - 100% coverage
5Congrats! Your infrastructure is fully in sync.

Parabéns! Agora está sob controle de novo, graças à detecção de desvios do Snyk IaC!

O que

Tipo de recurso

Nome

Tipo de descompasso

Ação

Status

Um usuário do IAM

aws_iam_user

user2

Não gerenciado

IMPORTAR

*

Uma chave de acesso do IAM

aws_iam_access_key

AKIASBXWQ3AYQETE6OFR

Não gerenciado

ALTERNAR

*

Uma política do IAM anexada

aws_iam_policy_attachment

arn:aws:iam::aws:policy/AdministratorAccess

Não gerenciado

EXCLUIR

*

Uma tag em um usuário do IAM

aws_iam_user

tags.environment

Gerenciado

ADICIONAR

*

Conclusão

Neste artigo, mostramos como a detecção de desvios do Snyk IaC pode ajudar a descobrir recursos da AWS criados manualmente e como ele relata tudo em termos do Terraform com as informações corretas para ajudar os desenvolvedores a importar esses recursos para o código Terraform HCL. Também vimos brevemente que a reversão automática das alterações nem sempre é o resultado desejado e que um sistema leve de alertas de detecção de desvios é necessário em conjunto com esse pipeline de implantação.

Temos a forte convicção de que toda a infraestrutura deve estar no código, pois assim os engenheiros podem ter feedback sobre a segurança e visibilidade dos problemas o mais rápido possível.

É por isso que o Snyk IaC pode ajudar as equipes a reintegrar rapidamente ao código do Terraform todos os recursos em execução na conta da AWS para aumentar a cobertura geral da IaC e reduzir os problemas de segurança em geral. O Snyk IaC promove correções mais rápidas, fechando o ciclo de feedback entre as equipes de engenharia e de segurança na nuvem e informando correções acionáveis diretamente ao engenheiro, usando termos com os quais ele já está familiarizado.