Skip to main content

Mit Pulumi die Snyk-Kubernetes-Integration für Container automatisieren

Artikel von

Pas Apicella

feature snyk container purple

9. Februar 2022

0 Min. Lesezeit

Der Begriff Infrastructure as Code (IaC) ist uns allen bekannt. Doch Code bedeutet in diesem Zusammenhang nicht wirklich Code im Sinne einer Programmiersprache. IaC bezeichnet in der Regel die Konfiguration von Infrastruktur mithilfe von Tools wie Terraform, CloudFormation, Kubernetes-YAML oder Azure Resource Manager-Vorlagen. Dabei wird festgelegt, wie die Infrastruktur erstellt wird. Diese Konfigurationen bieten nicht die Flexibilität und Leistungsfähigkeit moderner Programmiersprachen. IaC ist also Code, aber normalerweise nicht diese Art von Code.

In diesem Blogbeitrag zeigen wir Ihnen Schritt für Schritt, wie Sie mit Pulumi, einem neuen Open-Source-Tool, mit dem Entwickler Code in mehreren Sprachen wie JavaScript, Typescript, Python und Go erstellen können, alles Notwendige für die Konfiguration der Kubernetes-Integration in Snyk Container einrichten.

Überblick über die Snyk-Kubernetes-Integration

Snyk lässt sich in Kubernetes integrieren. So können Sie Ihre laufenden Workloads importieren und testen sowie Schwachstellen in den zugehörigen Images und Konfigurationen erkennen, die die Sicherheit dieser Workloads beeinträchtigen könnten. Nach dem Import überwacht Snyk diese Workloads weiterhin und erkennt zusätzliche Sicherheitsprobleme, wenn neue Images bereitgestellt werden oder sich die Workload-Konfiguration ändert.

Was ist Pulumi?

Pulumi ist ein Open-Source-IaC-Tool, das die beliebtesten Programmiersprachen nutzt, um die Bereitstellung und Verwaltung von Cloud-Ressourcen zu vereinfachen.

Pulumi wurde 2017 gegründet und hat grundlegend verändert, wie DevOps-Teams das Konzept von Infrastructure as Code angehen. Anstatt auf domänenspezifische Sprachen zu setzen, können Unternehmen mit Pulumi echte Programmiersprachen verwenden, um Cloud-native Infrastruktur bereitzustellen und wieder abzubauen.

Pulumi unterstützt die folgenden Programmiersprachen:

  • Python

  • JavaScript

  • Go

  • TypeScript

  • .NET-Sprachen (C#, F# und VB)

So installieren Sie die Snyk-Kubernetes-Integration mit Pulumi

Jetzt wird es spannend! Wir gehen Schritt für Schritt durch die Einrichtung von Pulumi und starten unsere Automatisierungen. Dabei gehen wir wie folgt vor:

  1. Richten Sie in der Snyk-App eine Kubernetes-Integrations-ID ein

  2. Klonen Sie das Beispiel-Repository

  3. Authentifizieren Sie sich bei Google Cloud

  4. Erstellen Sie einen neuen Pulumi-Stack

  5. Legen Sie die erforderlichen Pulumi-Konfigurationsvariablen fest

  6. Stellen Sie alles mit pulumi up bereit

  7. Rufen Sie die Kubernetes-Konfiguration ab

  8. Entfernen Sie die gesamte Einrichtung

Voraussetzungen

  1. Für die Kubernetes-Integration benötigen Sie ein Business- oder Enterprise-Konto bei Snyk. Falls Sie noch keines haben, können Sie sich für eine kostenlose 14-tägige Business-Testversion anmelden.

  2. Wir stellen die Ressourcen in Google Cloud bereit, daher benötigen Sie ein Konto. Falls Sie noch kein Konto haben, melden Sie sich hier kostenlos an. Folgen Sie anschließend in jedem Fall diesen Anweisungen, um Pulumi mit Ihrem Google-Cloud-Konto zu verbinden.

  3. In diesem Beispiel wird vorausgesetzt, dass sich die gcloud-CLI in Ihrem Pfad befindet. Sie wird als Teil des Google Cloud SDK installiert.

  4. Stellen Sie sicher, dass Sie über Python 3, ein Pulumi-Konto und die Pulumi-CLI verfügen.

  5. Beachten Sie, dass Pulumi voraussetzt, dass Python 3 in Ihrer Umgebung die Standardversion ist. Falls neben Python 3 auch Python 2 installiert ist, müssen Sie möglicherweise einen Alias erstellen. Führen Sie den folgenden Befehl aus, um dies zu überprüfen und sicherzustellen, dass Sie die neueste Version von 3.x verwenden:

❯ python --version
Python 3.9.9

Schritt 1: Richten Sie in der Snyk-App eine Kubernetes-Integrations-ID ein

Melden Sie sich bei Snyk an und wählen Sie die Organisation aus, in der Sie die Kubernetes-Integration automatisch einrichten möchten. Sie können eine leere Organisation oder eine bestehende Organisation mit Projekten verwenden. Stellen Sie für dieses Beispiel sicher, dass die Kubernetes-Integration in der ausgewählten Organisation noch nicht konfiguriert ist.

Klicken Sie anschließend auf Integrationen > Kubernetes > Verbinden. Wenn Sie kein Snyk-Business- oder Enterprise-Konto haben, können Sie diesen Schritt nicht ausführen.

Notieren Sie sich die Integrations-ID, da wir sie gleich benötigen.

Snyk-Projekteinstellungen, die zeigen, dass die Kubernetes-Integration nicht verbunden ist; die Schaltfläche „Verbinden“ ist hervorgehoben.

Das war’s! Jetzt können Sie unsere Snyk-Kubernetes-Integrationsdemo mit Pulumi Infrastructure as Code einrichten. Pulumi erledigt Folgendes:

  • Einen GKE-Cluster erstellen

  • Den Snyk-Controller im Cluster bereitstellen0

  • Die Snyk-Kubernetes-Integration für den automatischen Import von K8s-Workloads in Snyk einrichten

  • Einen Beispiel-Workload gemäß unserer Rego-Richtliniendatei im Namespace apples bereitstellen

Schritt 2: Klonen Sie das Beispiel-Repository

Klonen Sie das folgende GitHub-Demo-Repository wie unten gezeigt:

$ 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.

Wechseln Sie nach dem Klonen dieses Repositorys mit cd in das Verzeichnis und führen Sie die nächsten Befehle aus …

Schritt 3: Authentifizieren Sie sich bei Google Cloud

Authentifizieren Sie sich mit der lokalen Authentifizierung bei Google Cloud, um diese Demo bereitzustellen. Es gibt weitere Möglichkeiten, Pulumi mit Google Cloud zu konfigurieren, aber für diese Demo ist dies der einfachste Weg:

$ gcloud auth login

Schritt 4: Erstellen Sie einen neuen Pulumi-Stack

Erstellen Sie einen neuen Stack, der für dieses Beispiel als isoliertes Bereitstellungsziel dient. Verwenden Sie als Beispiel dev:

$ pulumi stack init dev

Schritt 5: Legen Sie die erforderlichen Pulumi-Konfigurationsvariablen fest

Häufig benötigen verschiedene Stacks innerhalb eines Projekts unterschiedliche Werte. Beispielsweise möchten Sie möglicherweise für Ihre Google-Cloud-Compute-Instanz eine andere Größe oder für Ihren Kubernetes-Cluster in Entwicklungs- und Produktions-Stacks eine andere Anzahl von Servern verwenden.

Die Schlüssel-Wert-Paare eines Stacks werden in der Stack-Einstellungsdatei Ihres Projekts gespeichert. Ihr Name lautet automatisch Pulumi.<stack-name>.yaml. In der Regel können Sie diese Datei ignorieren. Möglicherweise möchten Sie sie jedoch einchecken und zusammen mit dem Quellcode Ihres Projekts versionieren.

Fügen Sie Ihrem Stack die folgenden Konfigurationsvariablen hinzu, wie unten gezeigt:

$ 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

Standardmäßig hat Ihr Cluster 3 Knoten vom Typ n1-standard-1. Diese Einstellung lässt sich ändern. Wenn Sie beispielsweise 5 Knoten vom Typ n1-standard-2 auswählen möchten, können Sie folgende Befehle ausführen:

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

Abschließend müssen wir die erforderlichen Einstellungen für die Snyk-Kubernetes-Integration konfigurieren, damit die Integration automatisch in unserem Cluster eingerichtet wird. Dazu benötigen wir die ID unserer Kubernetes-Integration und die ID unserer Snyk-Organisation. In diesem Beispiel sind beide identisch:

$ 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

Dieses Beispiel zeigt, wie Sie Stacks sinnvoll konfigurieren können. Sie können diese Einstellungen sogar nach der Bereitstellung ändern.

Anschließend enthält die Datei Pulumi.dev.yaml Folgendes:

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

Schritt 6: Stellen Sie alles mit pulumi up bereit

Mit dem Befehl pulumi up werden alle für die Kubernetes-Integration mit Snyk erforderlichen Google-Cloud-Ressourcen bereitgestellt, darunter der GKE-Cluster selbst und das Helm-Chart des Snyk-Controllers. Anschließend wird ein Kubernetes-Deployment mit einer Spring-Boot-Anwendung bereitgestellt:

$ pulumi up

Daraufhin wird eine Vorschau angezeigt und Sie werden um Bestätigung gebeten. Anschließend beginnt die Bereitstellung der Snyk-Kubernetes-Integrationsdemo:

$ 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

Nach etwa fünf Minuten ist Ihr Cluster bereit. Der Snyk-Controller ist installiert und ein Beispiel-Workload-Deployment wurde automatisch in Ihre Snyk-Organisation importiert:

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

Die folgenden Screenshots zeigen, dass alles wie erwartet erstellt wurde.

Der in Google Cloud erstellte GKE-Cluster:

Google-Kubernetes-Engine-Konsole mit Details zum Cluster pulumi-gke-cluster-008049b.

Die automatisch konfigurierte Snyk-Kubernetes-Integration:

Snyk-Einstellungsseite mit verbundener Kubernetes-Integration sowie einer Option zum Hinzufügen von Kubernetes-Workloads und Integrationsdetails.

Der automatisch aus dem Namespace apples importierte Beispiel-Workload:

Snyk-Projekt-Dashboard mit Kubernetes-Projekten, Schweregraden der Sicherheitsprobleme und einer Option zum Hinzufügen eines weiteren Projekts
Snyk-Dashboard mit einer Kubernetes-Bereitstellung mit 52 Schwachstellen und fehlgeschlagenen Prüfungen der sicheren Konfiguration

Konfiguration im Detail

Sehen wir uns die Python-Datei __main__.py genauer an und erfahren wir, wie die Snyk-Kubernetes-Integration für uns installiert und konfiguriert wurde.

Die vom Snyk-Controller verwendete Rego-Richtliniendatei ist derzeit fest so eingestellt, dass nur Workloads aus dem Namespace apples importiert werden, sofern sie nicht vom Typ CronJob oder Service sind. Sie können dies in __main__.py ändern und die Richtliniendatei extern statt als fest codierten Bestandteil des Python-Codes verwenden:

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)

Hier sehen Sie den Python-Code, mit dem der Snyk-Controller über sein Helm-Chart installiert wird. Beachten Sie, dass wir das Repository zum Abrufen des Helm-Charts angegeben und sowohl die Snyk-Organisations-ID als auch die oben beschriebene benutzerdefinierte Richtliniendatei bereitgestellt haben. All dies ist erforderlich, um den Snyk-Controller im GKE-Cluster zu installieren und in Snyk zu integrieren.

# 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)
)

Mit dem Python-Code wurde außerdem eine Spring-Boot-Beispielanwendung im Namespace apples bereitgestellt. Diese wurde vom Snyk-Controller automatisch in die Snyk-App importiert. Der Python-Code für dieses Deployment lautet:

# 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)
)

Schritt 7: Rufen Sie die Kubernetes-Konfiguration ab

Sie können diese Konfiguration nun entweder in Ihrer Datei ~/.kube/config verwenden oder lokal speichern und in die Umgebungsvariable KUBECONFIG eintragen. Natürlich funktionieren auch alle Ihre gewohnten Google-Cloud-Befehle.

Zum Beispiel:

$ 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

Der im Namespace snyk-monitor installierte Snyk-Controller sowie die jetzt von Pulumi verwaltete ConfigMap und das Secret, angezeigt mit einigen kubectl-Befehlen:

$ 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

Schritt 8: Entfernen Sie die gesamte Einrichtung

Wenn Sie fertig sind, können Sie alle Ressourcen und den Stack entfernen:

$ pulumi destroy
$ pulumi stack rm

Zusammenfassend haben Sie erfahren, wie Sie mit Pulumi die Snyk-Kubernetes-Integration installieren und konfigurieren können. Damit können Sie Ihre laufenden Workloads importieren und testen sowie Schwachstellen in den zugehörigen Images und Konfigurationen erkennen, die die Sicherheit dieser Workloads beeinträchtigen könnten.

Weitere Ressourcen

Sie wissen nun, wie einfach sich die Kubernetes-Integration mit Snyk mithilfe der Programmiersprache Python und Pulumi einrichten lässt. Die folgenden Links helfen Ihnen bei den ersten Schritten auf Ihrem Weg zur Container-Sicherheit.

Sichern Sie Ihre Infrastruktur an der Quelle

Snyk automatisiert die IaC-Sicherheit und Compliance in Workflows und erkennt abweichende sowie fehlende Ressourcen.