Skip to main content

Como usar o Pulumi para automatizar a integração do Snyk Kubernetes para contêineres

Escrito por

Pas Apicella

feature snyk container purple

9 de fevereiro de 2022

0 minutos de leitura

Todos já ouvimos falar do termo infraestrutura como código (IaC), mas código, nesse contexto, não é exatamente código no sentido de uma linguagem de programação. IaC geralmente se refere à configuração da infraestrutura por meio de ferramentas como Terraform, CloudFormation, YAML do Kubernetes ou modelos do Azure Resource Manager — que, na prática, definem como a infraestrutura será criada. Essas configurações não oferecem a flexibilidade e o poder de uma linguagem de programação moderna. Portanto, IaC é código, mas geralmente não é esse tipo de código.

Nesta postagem, vamos mostrar como usar o Pulumi, uma nova ferramenta de código aberto que permite aos desenvolvedores escrever código em várias linguagens, como JavaScript, TypeScript, Python e Go, para criar tudo o que é necessário para configurar a integração do Kubernetes no Snyk Container.

Visão geral da integração do Snyk com Kubernetes

A Snyk se integra ao Kubernetes, permitindo que você importe e teste suas cargas de trabalho em execução e identifique vulnerabilidades nas imagens e configurações associadas que possam comprometer a segurança dessas cargas. Após a importação, a Snyk continua monitorando essas cargas de trabalho e identificando novos problemas de segurança à medida que novas imagens são implantadas e a configuração muda.

O que é Pulumi?

Pulumi é uma ferramenta de IaC de código aberto que usa as linguagens de programação mais populares para simplificar o provisionamento e o gerenciamento de recursos na nuvem.

Fundada em 2017, a Pulumi mudou profundamente a forma como as equipes de DevOps abordam o conceito de infraestrutura como código. Em vez de depender de linguagens específicas de domínio, a Pulumi permite que as organizações usem linguagens de programação de verdade para provisionar e desativar infraestrutura nativa da nuvem.

O Pulumi oferece suporte às seguintes linguagens de programação:

  • Python

  • JavaScript

  • Go

  • TypeScript

  • Linguagens .NET (C#, F# e VB)

Como instalar a integração do Snyk com Kubernetes usando o Pulumi

Agora vem a parte divertida! Vamos configurar o Pulumi passo a passo e iniciar nossas automações. Estas são as etapas:

  1. Crie um ID de integração com Kubernetes no app da Snyk

  2. Clone o repositório de exemplo

  3. Faça a autenticação no Google Cloud

  4. Crie uma nova stack do Pulumi

  5. Defina as variáveis de configuração necessárias do Pulumi

  6. Implante tudo com pulumi up

  7. Recupere a configuração do Kubernetes

  8. Destrua toda a configuração

Pré-requisitos

  1. Para usar a integração com Kubernetes, você precisa ter uma conta Business ou Enterprise da Snyk. Se ainda não tiver uma, você pode se inscrever para um teste gratuito de 14 dias do plano Business.

  2. Vamos implantar no Google Cloud, então você precisará de uma conta. Se ainda não tiver uma, inscreva-se gratuitamente aqui. Em ambos os casos, siga estas instruções para conectar o Pulumi à sua conta do Google Cloud.

  3. Este exemplo pressupõe que a CLI gcloud esteja no seu PATH. Ela é instalada como parte do Google Cloud SDK.

  4. Verifique se você tem o Python 3, uma conta do Pulumi e a CLI do Pulumi.

  5. Observe que o Pulumi exige que o Python 3 seja a versão padrão no seu ambiente. Se você tiver o Python 2 e o Python 3 instalados, talvez seja necessário criar um alias. Para verificar, execute o comando a seguir e confirme que está usando a versão mais recente do 3.x:

❯ python --version
Python 3.9.9

Etapa 1: Crie um ID de integração com Kubernetes no app da Snyk

Entre na Snyk e selecione a organização em que deseja configurar automaticamente a integração com Kubernetes. Pode ser uma organização vazia ou uma já existente com projetos. Neste exemplo, verifique se a integração com Kubernetes ainda não está configurada na organização escolhida.

Em seguida, clique em Integrações > Kubernetes > Conectar. Se você não tiver uma conta Business ou Enterprise da Snyk, não poderá concluir esta etapa.

Anote o ID da integração, pois vamos precisar dele em breve.

Configurações do projeto Snyk mostrando a integração com o Kubernetes como desconectada, com o botão Conectar em destaque.

Pronto! Agora você pode configurar a demonstração da integração do Snyk com Kubernetes usando infraestrutura como código com o Pulumi. O Pulumi fará o seguinte:

  • Criar um cluster GKE

  • Implantar o controlador da Snyk no cluster0

  • Configurar a integração do Snyk com Kubernetes para importar automaticamente as cargas de trabalho do K8s para a Snyk

  • Implantar uma carga de trabalho de exemplo no namespace apples, de acordo com nosso arquivo de política Rego

Etapa 2: Clone o repositório de exemplo

Clone o repositório de demonstração no GitHub a seguir, como mostrado abaixo:

$ git clone https://github.com/papicella/snyk-kubernetes-integration
Cloning into 'snyk-kubernetes-integration'...
remote: Enumerating objects: 18, done.
remote: Counting objects: 100% (18/18), done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 18 (delta 8), reused 14 (delta 4), pack-reused 0
Receiving objects: 100% (18/18), 8.76 KiB | 4.38 MiB/s, done.
Resolving deltas: 100% (8/8), done.

Depois de clonar o repositório, acesse-o com cd e execute os próximos comandos…

Etapa 3: Faça a autenticação no Google Cloud

Para implantar esta demonstração, autentique-se no Google Cloud usando a autenticação local. Há outras maneiras de configurar o Pulumi com o Google Cloud, mas esta é a mais simples para a demonstração:

$ gcloud auth login

Etapa 4: Crie uma nova stack do Pulumi

Crie uma nova stack, que será um destino de implantação isolado para este exemplo. Use dev como exemplo:

$ pulumi stack init dev

Etapa 5: Defina as variáveis de configuração necessárias do Pulumi

Em muitos casos, stacks diferentes de um mesmo projeto precisam de valores distintos. Por exemplo, talvez você queira usar um tamanho diferente para sua instância do Google Cloud ou uma quantidade diferente de servidores no cluster do Kubernetes nas stacks de desenvolvimento e produção.

Os pares de chave e valor de cada stack ficam armazenados no arquivo de configurações da stack do seu projeto, cujo nome padrão é Pulumi.<stack-name>.yaml. Em geral, você pode ignorar esse arquivo, embora seja possível adicioná-lo ao controle de versão junto com o código-fonte do projeto.

Adicione as seguintes variáveis de configuração à nossa stack, como mostrado abaixo:

$ pulumi config set gcp:project [your-gcp-project-here] # Eg: snyk-cx-se-demo
$ pulumi config set gcp:zone us-central1-c # any valid GCP zone here
$ pulumi config set password --secret [your-cluster-password-here] # password for the cluster
$ pulumi config set master_version 1.21.6-gke.1500 # any valid K8s master version on GKE

Por padrão, seu cluster terá 3 nós do tipo n1-standard-1. Essa configuração pode ser alterada. Para escolher 5 nós do tipo n1-standard-2, por exemplo, você pode executar estes comandos:

$ pulumi config set node_count 5
$ pulumi config set node_machine_type n1-standard-2

Por fim, precisamos configurar as definições necessárias da integração do Snyk com Kubernetes, que serão usadas para adicionar automaticamente essa integração ao nosso cluster. Precisamos do ID da integração com Kubernetes e do ID da organização da Snyk. Neste exemplo, eles são iguais:

$ pulumi config set snyk_K8s_integration_id K8S_INTEGRATION_ID #same as ORG_ID at the moment
$ pulumi config set snyk_org_id ORG_ID # your Snyk ORG ID under settings

Isso mostra como você pode configurar stacks de maneiras úteis. Você pode até alterar essas configurações depois do provisionamento.

Depois de concluir esta etapa, você terá um arquivo Pulumi.dev.yaml com o seguinte conteúdo:

config:
gcp-K8s-integration-demo:master_version: 1.21.5-gke.1302
gcp-K8s-integration-demo:node_count: "3"
gcp-K8s-integration-demo:node_machine_type: n1-standard-2
gcp-K8s-integration-demo:password:
    secure: AAABsomesecret+EnF1p4w==
gcp-K8s-integration-demo:snyk_K8s_integration_id: yyyy1234
gcp-K8s-integration-demo:snyk_org_id: yyyy1234
gcp:project: snyk-cx-se-demo
gcp:zone: us-central1-c

Etapa 6: Implante tudo com pulumi up

A implantação de tudo com o comando pulumi up provisiona todos os recursos do Google Cloud necessários para a integração do Kubernetes com a Snyk, incluindo o próprio cluster GKE e o gráfico Helm do controlador da Snyk. Em seguida, implanta um deployment do Kubernetes que executa uma aplicação Spring Boot:

$ pulumi up

Será exibida uma prévia, você precisará confirmar e, em seguida, começará o provisionamento da demonstração da integração do Snyk com Kubernetes:

$ pulumi up
Previewing update (dev)

View Live: https://app.pulumi.com/papicella/gcp-K8s-integration-demo/dev/previews/1db6492c-ae23-4e87-abf0-41e09fb62177

    Type                                                              Name                          Plan
+   pulumi:pulumi:Stack                                               gcp-K8s-integration-demo-dev  create
+   ├─ kubernetes:helm.sh/v3:Chart                                    snyk-monitor                  create
+   │  ├─ kubernetes:core/v1:ServiceAccount                           snyk-monitor/snyk-monitor     create
+   │  ├─ kubernetes:networking.k8s.io/v1:NetworkPolicy               snyk-monitor/snyk-monitor     create
+   │  ├─ kubernetes:rbac.authorization.k8s.io/v1:ClusterRole         snyk-monitor                  create
+   │  ├─ kubernetes:rbac.authorization.k8s.io/v1:ClusterRoleBinding  snyk-monitor                  create
+   │  └─ kubernetes:apps/v1:Deployment                               snyk-monitor/snyk-monitor     create
+   ├─ gcp:container:Cluster                                          pulumi-gke-cluster            create
+   ├─ pulumi:providers:kubernetes                                    gke_k8s                       create
+   ├─ kubernetes:core/v1:Namespace                                   snyk-monitor                  create
+   ├─ kubernetes:core/v1:Namespace                                   apples                        create
+   ├─ kubernetes:core/v1:ConfigMap                                   snyk-monitor-custom-policies  create
+   ├─ kubernetes:core/v1:Service                                     springboot-employee-api       create
+   ├─ kubernetes:core/v1:Secret                                      snyk-monitor                  create
+   └─ kubernetes:apps/v1:Deployment                                  springboot-employee-api       create

Resources:
    + 15 to create

Após cerca de cinco minutos, seu cluster estará pronto, com o controlador da Snyk instalado e uma carga de trabalho de exemplo importada automaticamente para sua organização da Snyk:

Do you want to perform this update? yes
Updating (dev)

View Live: https://app.pulumi.com/papicella/gcp-K8s-integration-demo/dev/updates/1

    Type                                                              Name                          Status
+   pulumi:pulumi:Stack                                               gcp-K8s-integration-demo-dev  created
+   ├─ kubernetes:helm.sh/v3:Chart                                    snyk-monitor                  created
+   │  ├─ kubernetes:core/v1:ServiceAccount                           snyk-monitor/snyk-monitor     created
+   │  ├─ kubernetes:networking.k8s.io/v1:NetworkPolicy               snyk-monitor/snyk-monitor     created
+   │  ├─ kubernetes:rbac.authorization.k8s.io/v1:ClusterRole         snyk-monitor                  created
+   │  ├─ kubernetes:rbac.authorization.k8s.io/v1:ClusterRoleBinding  snyk-monitor                  created
+   │  └─ kubernetes:apps/v1:Deployment                               snyk-monitor/snyk-monitor     created
+   ├─ gcp:container:Cluster                                          pulumi-gke-cluster            created
+   ├─ pulumi:providers:kubernetes                                    gke_k8s                       created
+   ├─ kubernetes:core/v1:Namespace                                   snyk-monitor                  created
+   ├─ kubernetes:core/v1:Namespace                                   apples                        created
+   ├─ kubernetes:core/v1:Service                                     springboot-employee-api       created
+   ├─ kubernetes:core/v1:ConfigMap                                   snyk-monitor-custom-policies  created
+   ├─ kubernetes:core/v1:Secret                                      snyk-monitor                  created
+   └─ kubernetes:apps/v1:Deployment                                  springboot-employee-api       created

Outputs:
    kubeconfig: "[secret]"

Resources:
    + 15 created

Duration: 6m28s

Confira algumas capturas de tela para verificar se tudo foi criado como esperado.

O cluster GKE criado no Google Cloud:

Console do Google Kubernetes Engine mostrando detalhes do cluster pulumi-gke-cluster-008049b.

A integração do Snyk com Kubernetes configurada automaticamente:

Página de configurações do Snyk mostrando a integração com Kubernetes conectada, com uma opção para adicionar cargas de trabalho do Kubernetes e detalhes da integração.

A carga de trabalho de exemplo importada automaticamente do namespace apples:

Painel do Snyk Projects que mostra projetos do Kubernetes, a quantidade de problemas de segurança por nível de gravidade e a opção de adicionar outro projeto
Painel do Snyk mostrando uma implantação do Kubernetes com 52 vulnerabilidades e verificações de configuração segura reprovadas

Explorando a configuração

Vamos analisar o arquivo Python __main__.py e entender como a integração do Snyk com Kubernetes foi instalada e configurada para nós.

Atualmente, o arquivo de política Rego usado pelo controlador da Snyk está codificado para importar apenas cargas de trabalho do namespace apples, desde que não sejam do tipo CronJob nem Service. Você pode alterar isso em __main__.py e usar um arquivo externo, em vez de deixar a política codificada no código Python:

snyk_monitor_custom_policies_str = """package snyk
orgs := ["%s"]
default workload_events = false
workload_events {
input.metadata.namespace == "apples"
    input.kind != "CronJob"
    input.kind != "Service"
}""" % (SNYK_ORG_ID)

Este é o código Python que instala o controlador da Snyk usando seu gráfico Helm. Observe que especificamos o repositório de onde buscar o gráfico Helm, fornecemos o ID da organização da Snyk e incluímos o arquivo de política personalizado mencionado acima. Tudo isso é necessário para instalar o controlador da Snyk no cluster GKE e integrá-lo à Snyk.

# Deploy the snyk controller using it's helm chart
snyk_monitor_chart = Chart(
    "snyk-monitor",
    ChartOpts(
        chart="snyk-monitor",
        version="1.79.0",
        namespace="snyk-monitor",
        fetch_opts=FetchOpts(
            repo="https://snyk.github.io/kubernetes-monitor",
        ),
        values={
          "clusterName": "K8s-integration-demo-cluster",
          "policyOrgs": "{%s}" % (SNYK_ORG_ID),
          "workloadPoliciesMap": "snyk-monitor-custom-policies"
        }
    ),
    opts=ResourceOptions(provider=k8s_provider)
)

O código Python também implantou uma aplicação de exemplo Spring Boot no nosso namespace apples, que foi importada automaticamente pelo controlador da Snyk para o app da Snyk. Veja a seguir o código Python usado para fazer essa implantação:

# deploy spring boot employee app

"""springboot employee api container, replicated 1 time."""
app_name = "springboot-employee-api"
app_labels = { "app": app_name }

springboot_employee_api = k8s.apps.v1.Deployment(
            app_name,
            metadata={
              "namespace": "apples",
            },
            spec=k8s.apps.v1.DeploymentSpecArgs(
                replicas=1,
                selector=k8s.meta.v1.LabelSelectorArgs(match_labels=app_labels),
                template=k8s.core.v1.PodTemplateSpecArgs(
                    metadata=k8s.meta.v1.ObjectMetaArgs(labels=app_labels),
                    spec=k8s.core.v1.PodSpecArgs(
                        containers=[
                            k8s.core.v1.ContainerArgs(
                                name=app_name,
                                image="pasapples/springbootemployee:cnb",
                                ports=[k8s.core.v1.ContainerPortArgs(
                                  container_port=8080
                                )]
                            )
                        ]
                    ),
                ),
            ),
            opts=ResourceOptions(provider=k8s_provider)
)

Etapa 7: Recupere a configuração do Kubernetes

Agora, você pode usar essa configuração no arquivo ~/.kube/config ou salvá-la localmente e defini-la na variável de ambiente KUBECONFIG. Naturalmente, todos os seus comandos habituais do Google Cloud também funcionarão.

Por exemplo:

$ pulumi stack output kubeconfig --show-secrets > kubeconfig.yaml
$ KUBECONFIG=./kubeconfig.yaml kubectl get po -n apples
NAME                                                READY   STATUS    RESTARTS   AGE
springboot-employee-api-fyrj9hr2-66d8456f5f-hqqhx   1/1     Running   0          17m

O controlador da Snyk instalado no namespace snyk-monitor, além do mapa de configuração e do segredo agora gerenciados pelo Pulumi, exibidos com alguns comandos kubectl:

$ kubectl get all -n snyk-monitor
NAME                              READY   STATUS    RESTARTS   AGE
pod/snyk-monitor-db67744d-szl79   1/1     Running   0          8m52s

NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/snyk-monitor   1/1     1            1           8m53s

NAME                                    DESIRED   CURRENT   READY   AGE
replicaset.apps/snyk-monitor-db67744d   1         1         1       8m53s

$ kubectl get secret -n snyk-monitor -l app.kubernetes.io/managed-by=pulumi
NAME           TYPE     DATA   AGE
snyk-monitor   Opaque   2      42m

$ kubectl get configmap -n snyk-monitor -l app.kubernetes.io/managed-by=pulumi
NAME                           DATA   AGE
snyk-monitor-custom-policies   1      42m

Etapa 8: Destrua toda a configuração

Quando terminar, você poderá destruir todos os recursos e a stack:

$ pulumi destroy
$ pulumi stack rm

Em resumo, você aprendeu como usar o Pulumi para instalar e configurar a integração do Snyk com Kubernetes. Essa integração permite que você importe e teste suas cargas de trabalho em execução e identifique vulnerabilidades nas imagens e configurações associadas que possam comprometer a segurança delas.

Mais recursos

Agora que você viu como é fácil configurar a integração do Snyk com Kubernetes usando a linguagem de programação Python e o Pulumi, confira alguns links úteis para começar sua jornada de segurança de contêineres.

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.