Statische Code-Analyse für Terraform
Statische Code-Analyse ist ein wichtiger Bestandteil der Qualitätssicherung von Software-Projekten. Durch sie können Fehler bereits frühzeitig in einer kurzen Feedback-Schleife erkannt und behoben werden. Der Quellcode wird anhand von definierten Regeln auf Fehler und potenzielle Schwachstellen hin überprüft und je nach verwendetem Tool wird direkt eine mögliche Lösung angeboten.
Mit dem aufkommen von Infrastructure As Code
-Ansätzen werden nun auch zunehmend Infrastruktur-Beschreibungen in Form von Code- oder zumindest von strukturierten Textdateien hinterlegt. Damit lassen sich die Vorteile der statischen Code-Analyse auch auf Infrastruktur-Definitionen anwenden.
Analyse von Terraform-Dateien
Für die Analyse von Terraform-Definitionsdateien existiert das CLI-Tool tfsec an. Es steht unter der MIT-Lizenz als ausführbare Datei für Windows, Linux und macOS oder als Docker-Image zum Download bereit.
tfsec
kommt mit einem umfangreichen Set an Regeln für die großen Hyperscaler wie AWS, Azure und Google Cloud daher. Für eine selbst-gehostete Kubernetes Umgebung oder einen OpenStack-Cluster sind es allerdings bereits deutlich weniger. Zwar lassen sich über Custom Checks eigene Regel definieren, am sinnvollsten lässt sich tfsec
aber vermutlich in einer managed Umgebung einsetzen.
tfsec
Im einfachsten Fall führt man tfsec
im Ordner mit den Terraform-Dateien aus bzw. übergibt den Pfad als erstes Aufrufargument. tfsec
durchsucht rekursiv alle Dateien mit der Endung .tf
und .tfvars
und gibt die Ergebnisse in der Konsole aus.
./tfsec ./terraform
Werden keine Regelverletzungen entdeckt, werden ein paar Statistiken ausgegeben und tfsec
gibt Entwarnung.
timings
──────────────────────────────────────────
disk i/o 5.3983ms
parsing 0s
adaptation 610.2µs
checks 3.2634ms
total 9.2719ms
counts
──────────────────────────────────────────
modules downloaded 0
modules processed 1
blocks processed 11
files read 1
results
──────────────────────────────────────────
passed 6
ignored 0
critical 0
high 0
medium 0
low 0
No problems detected!
Werden Probleme festgestellt, folgen Details zur beanstandeten Datei und der genauen Position des Problems sowie Hinweise und Links zu weiteren Informationen. Der Parameter --concise-output
reduziert die Ausgabe auf die wichtigsten Informationen.
> ./tfsec ./terraform --concise-output
Result #1 CRITICAL Storage account uses an insecure TLS version.
────────────────────────────────────────────────────────────────────────────────
./Terraform/main.tf:55
────────────────────────────────────────────────────────────────────────────────
ID azure-storage-use-secure-tls-policy
Impact The TLS version being outdated and has known vulnerabilities
Resolution Use a more recent TLS/SSL policy for the load balancer
More Information
- https://aquasecurity.github.io/tfsec/v1.28.1/checks/azure/storage/use-secure-tls-policy/
- https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_account#min_tls_version
────────────────────────────────────────────────────────────────────────────────
5 passed, 1 potential problem(s) detected.
In dem Beispiel bemängelt tfsec
eine veraltete TLS-Version für einen Azure-Storage-Account.
Möchte man einzelne Regeln nicht zur Anwendung bringen, schließt man sie über den Parameter --exclude [RULE-ID]
von der Prüfung aus. Auch lassen sich Beanstandungen einzelner Ressourcen oder Optionen innerhalb der Terraform-Definitionen per Kommentar ignorieren.
resource "azurerm_storage_account" "storage_account" {
account_kind = "StorageV2"
account_tier = "Standard"
min_tls_version = "TLS1_1" #tfsec:ignore:azure-storage-use-secure-tls-policy
...
}
CI-Pipeline
Ein nützliches Feature von tfsec
ist, dass es das Ergebnis einer Analyse in unterschiedlichen Formaten ausgeben kann. Über den Parameter --format
wählt man die gewünschten Formate, darunter auch Markdown, HTML und JUnit. Mit --out
legt man den Order (dieser muss existieren) und das Dateiprefix der Ausgabedateien fest. Das erste Format wird zusätzlich auf der Konsole ausgegeben.
Der folgende Aufruf erzeugt in dem Ordner ./terraform/tfsec-results
die Dateien results.lovely
, results.junit
und results.markdown
.
./tfsec ./terraform --concise-output \
--format lovely,junit,markdown \
--out ./terraform/tfsec-results/results
Die Ergebnisse lassen sich nun in einer CI-Pipeline weiterverarbeiten und der Build kann bei Regelverletzungen fehlschlagen.
Azure DevOps Pipeline
Nutzt man Azure DevOps Pipelines, kann man die JUnit-Datei als Test-Results veröffentlichen. So kann man tfsec
einfach in vorhandene Test- und Build-Workflows integrieren und Fehler direkt in der Pipeline visualisieren.
Ich zeige hier für eine einfachere Adaption an andere CI-Systeme, wie man tfsec
als Shell-Command nutzt. Daneben existiert auch eine Pipeline Extension im Visual Studio Marketplace und eine GitHub Action.
Zuerst lädt man das passende Binary für sein System herunter, setzt ggf. das Execute-Bit und legt den Ausgabe-Ordner an. Danach führt man tfsec
aus. Möchte man das Ergebnis im Markdown-Format als Ergebnis des Pipeline-Laufs in der Weboberfläche sehen, kann man es über ein Logging-Command echo "##vso[task.uploadsummary]...
hochladen.
In einem zweiten Task veröffentlicht man dann die JUnit-Datei als Test-Result.
- task: CmdLine@2
displayName: "Run tfsec"
inputs:
workingDirectory: "$(System.DefaultWorkingDirectory)/Infrastructure/Terraform"
script: |
echo "Download tfsec v1.28.1 ..."
wget -q https://github.com/aquasecurity/tfsec/releases/download/v1.28.1/tfsec-linux-amd64 -O tfsec
chmod +x tfsec
mkdir ./tfsec-results
./tfsec . --concise-output \
--format lovely,junit,markdown \
--out ./tfsec-results/results
echo "##vso[task.uploadsummary]$(System.DefaultWorkingDirectory)/Infrastructure/Terraform/tfsec-results/results.markdown"
- task: PublishTestResults@2
displayName: "Publish tfsec results"
condition: succeededOrFailed()
inputs:
testResultsFormat: JUnit
searchFolder: $(System.DefaultWorkingDirectory)/Infrastructure/Terraform/tfsec-results
testResultsFiles: "results.junit"
failTaskOnFailedTests: true
testRunTitle: tfsec
Die tfsec
-Results gehen mit in die Teststatistik ein.
Im Extensions
-Tab wird das Ergebnis der Markdown-Datei angezeigt.
Damit hat man eine automatische und kontinuierliche Überprüfung der Terraform-Dateien in seine CI-Pipeline integriert.