Feuille de chaleur TFSec
Aperçu général
TFSec est un scanner de sécurité d'analyse statique pour le code Terraform qui identifie les problèmes de sécurité potentiels dans Infrastructure comme code avant le déploiement. Il fournit des vérifications de sécurité exhaustives entre plusieurs fournisseurs de cloud avec des directives détaillées d'assainissement et s'intègre parfaitement aux pipelines CI/CD.
C'est pas vrai. Note: Outil libre et open-source. Maintenant partie de Trivy à partir de 2023.
Installation
Installation binaire
# Linux/macOS
curl -s https://raw.githubusercontent.com/aquasecurity/tfsec/master/scripts/install_linux.sh | bash
# macOS with Homebrew
brew install tfsec
# Windows with Chocolatey
choco install tfsec
# Windows with Scoop
scoop install tfsec
# Direct download
# Visit: https://github.com/aquasecurity/tfsec/releases
# Download appropriate binary for your platform
Installation Docker
# Pull Docker image
docker pull aquasec/tfsec:latest
# Run with Docker
docker run --rm -it \
-v $(pwd):/src \
aquasec/tfsec:latest /src
# Docker alias for convenience
alias tfsec='docker run --rm -it -v $(pwd):/src aquasec/tfsec:latest'
```_
### Gestionnaires de paquets
```bash
# Alpine Linux
apk add tfsec
# Arch Linux
yay -S tfsec
# Ubuntu/Debian (via snap)
sudo snap install tfsec
# Go install
go install github.com/aquasecurity/tfsec/cmd/tfsec@latest
```_
## Utilisation de base
### Analyse simple
```bash
# Scan current directory
tfsec
# Scan specific directory
tfsec /path/to/terraform/code
# Scan with verbose output
tfsec --verbose
# Scan and show passed checks
tfsec --include-passed
Formats de sortie
# JSON output
tfsec --format json
# SARIF output
tfsec --format sarif
# JUnit XML output
tfsec --format junit
# CSV output
tfsec --format csv
# Checkstyle XML output
tfsec --format checkstyle
# GitHub output
tfsec --format github
# Save output to file
tfsec --format json --out results.json
Résultats de filtrage
# Show only high severity issues
tfsec --minimum-severity HIGH
# Show critical and high severity
tfsec --minimum-severity CRITICAL
# Include specific checks
tfsec --include-checks AWS001,AWS002
# Exclude specific checks
tfsec --exclude-checks AWS001,AWS002
# Exclude by severity
tfsec --exclude-severity LOW,MEDIUM
Configuration
Fichier de configuration
# .tfsec.yml or tfsec.yml
severity_overrides:
AWS001: ERROR
AWS002: WARNING
exclude_checks:
- AWS001
- AWS002
include_checks:
- AWS003
- AWS004
minimum_severity: MEDIUM
exclude_paths:
- "**/.terraform/**"
- "**/node_modules/**"
- "examples/**"
include_paths:
- "modules/**"
- "environments/**"
Variables d'environnement
# Set configuration via environment variables
export TFSEC_MINIMUM_SEVERITY=HIGH
export TFSEC_EXCLUDE_CHECKS=AWS001,AWS002
export TFSEC_FORMAT=json
export TFSEC_OUT=results.json
# Run with environment configuration
tfsec
Répertoire des vérifications personnalisées
# Specify custom checks directory
tfsec --custom-check-dir ./custom-checks
# Multiple custom check directories
tfsec --custom-check-dir ./custom-checks --custom-check-dir ./team-checks
Fournisseur de cloud Couverture
Vérifications de sécurité AWS
# AWS-specific scan
tfsec --include-checks AWS*
# Common AWS security issues:
# - S3 bucket encryption
# - IAM policy issues
# - Security group misconfigurations
# - RDS encryption
# - EBS encryption
# - CloudTrail configuration
# - VPC security
Exemples AWS
# ❌ Insecure S3 bucket
resource "aws_s3_bucket" "bad_example" {
bucket = "my-bucket"
# Missing encryption configuration
}
# ✅ Secure S3 bucket
resource "aws_s3_bucket" "good_example" {
bucket = "my-bucket"
}
resource "aws_s3_bucket_server_side_encryption_configuration" "example" {
bucket = aws_s3_bucket.good_example.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
# ❌ Overly permissive security group
resource "aws_security_group" "bad_example" {
ingress {
from_port = 0
to_port = 65535
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
# ✅ Restrictive security group
resource "aws_security_group" "good_example" {
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["10.0.0.0/16"]
}
}
Vérifications de sécurité Azure
# Azure-specific scan
tfsec --include-checks AZURE*
# Common Azure security issues:
# - Storage account encryption
# - Network security groups
# - Key Vault configuration
# - SQL Database security
# - Virtual machine security
Exemples d'azur
# ❌ Insecure storage account
resource "azurerm_storage_account" "bad_example" {
name = "storageaccountname"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
account_tier = "Standard"
account_replication_type = "GRS"
# Missing encryption configuration
}
# ✅ Secure storage account
resource "azurerm_storage_account" "good_example" {
name = "storageaccountname"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
account_tier = "Standard"
account_replication_type = "GRS"
enable_https_traffic_only = true
min_tls_version = "TLS1_2"
encryption {
services {
blob {
enabled = true
}
file {
enabled = true
}
}
source = "Microsoft.Storage"
}
}
Vérifications de sécurité Google Cloud
# GCP-specific scan
tfsec --include-checks GCP*
# Common GCP security issues:
# - Storage bucket permissions
# - Compute instance security
# - IAM bindings
# - Network security
# - Encryption settings
Exemples de GCP
# ❌ Public storage bucket
resource "google_storage_bucket" "bad_example" {
name = "my-bucket"
location = "US"
uniform_bucket_level_access = false
}
resource "google_storage_bucket_iam_member" "bad_example" {
bucket = google_storage_bucket.bad_example.name
role = "roles/storage.objectViewer"
member = "allUsers"
}
# ✅ Secure storage bucket
resource "google_storage_bucket" "good_example" {
name = "my-bucket"
location = "US"
uniform_bucket_level_access = true
encryption {
default_kms_key_name = google_kms_crypto_key.example.id
}
}
resource "google_storage_bucket_iam_member" "good_example" {
bucket = google_storage_bucket.good_example.name
role = "roles/storage.objectViewer"
member = "serviceAccount:${google_service_account.example.email}"
}
Suppressions inline
Suppression Commentaires
# Suppress specific check
resource "aws_s3_bucket" "example" {
#tfsec:ignore:AWS002
bucket = "my-bucket"
# Bucket encryption handled by separate resource
}
# Suppress multiple checks
resource "aws_security_group" "example" {
#tfsec:ignore:AWS007,AWS008
name_prefix = "example"
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
# Suppress with explanation
resource "aws_instance" "example" {
#tfsec:ignore:AWS012:This instance needs public IP for external access
ami = "ami-12345678"
instance_type = "t2.micro"
associate_public_ip_address = true
}
Suppressions au niveau des blocs
# Suppress entire resource block
#tfsec:ignore:*
resource "aws_s3_bucket" "legacy" {
bucket = "legacy-bucket"
# Legacy bucket with known issues
# Will be migrated in next sprint
}
# Suppress specific attribute
resource "aws_db_instance" "example" {
allocated_storage = 20
engine = "mysql"
#tfsec:ignore:AWS017
storage_encrypted = false # Encryption handled at application level
}
Suppressions conditionnelles
# Suppress based on condition
resource "aws_s3_bucket" "example" {
bucket = var.bucket_name
# Only ignore in development environment
#tfsec:ignore:AWS002:exp:2024-12-31
# Temporary suppression with expiration
}
Intégration CI/CD
Actions GitHub
# .github/workflows/tfsec.yml
name: TFSec Security Scan
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
tfsec:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Run TFSec
uses: aquasecurity/tfsec-action@v1.0.3
with:
soft_fail: true
format: sarif
output: tfsec.sarif
- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@v2
if: always()
with:
sarif_file: tfsec.sarif
- name: TFSec Report
uses: aquasecurity/tfsec-pr-commenter-action@v1.3.1
with:
github_token: ${{ github.token }}
GitLab CI
# .gitlab-ci.yml
tfsec:
stage: security
image: aquasec/tfsec:latest
script:
- tfsec --format gitlab-sast --out gl-sast-report.json .
artifacts:
reports:
sast: gl-sast-report.json
paths:
- gl-sast-report.json
expire_in: 1 week
only:
- merge_requests
- main
Jenkins Pipeline
pipeline {
agent any
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('TFSec Scan') {
steps {
script {
docker.image('aquasec/tfsec:latest').inside {
sh '''
tfsec --format junit --out tfsec-results.xml .
tfsec --format json --out tfsec-results.json .
'''
}
}
}
post {
always {
publishTestResults testResultsPattern: 'tfsec-results.xml'
archiveArtifacts artifacts: 'tfsec-results.json', fingerprint: true
}
}
}
}
}
Azure DevOps
# azure-pipelines.yml
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
steps:
- task: Docker@2
displayName: 'Run TFSec Security Scan'
inputs:
command: 'run'
arguments: >
--rm
-v $(Build.SourcesDirectory):/src
aquasec/tfsec:latest
--format junit --out /src/tfsec-results.xml /src
- task: PublishTestResults@2
displayName: 'Publish TFSec Results'
inputs:
testResultsFormat: 'JUnit'
testResultsFiles: 'tfsec-results.xml'
testRunTitle: 'TFSec Security Scan'
condition: always()
Vérifications personnalisées
Écrire des vérifications personnalisées
// custom-check.go
package main
import (
"github.com/aquasecurity/tfsec/pkg/provider"
"github.com/aquasecurity/tfsec/pkg/result"
"github.com/aquasecurity/tfsec/pkg/rule"
"github.com/aquasecurity/tfsec/pkg/scanner"
)
func init() {
scanner.RegisterCheckRule(rule.Rule{
Provider: provider.AWSProvider,
Service: "s3",
ShortCode: "custom-bucket-naming",
Summary: "S3 bucket names should follow company naming convention",
Impact: "Non-standard bucket names may cause confusion",
Resolution: "Use company naming convention: company-env-purpose-random",
Explanation: "All S3 buckets should follow the company naming convention",
Links: []string{
"https://company.com/docs/naming-conventions",
},
Terraform: &rule.EngineMetadata{
GoodExamples: []string{`
resource "aws_s3_bucket" "good_example" {
bucket = "mycompany-prod-data-abc123"
}
`},
BadExamples: []string{`
resource "aws_s3_bucket" "bad_example" {
bucket = "my-random-bucket-name"
}
`},
Links: []string{
"https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket",
},
RemediationMarkdown: `
Ensure S3 bucket names follow the company naming convention:
- Format: company-environment-purpose-randomstring
- Use lowercase letters and hyphens only
- Keep names descriptive but concise
`,
},
Severity: rule.SeverityMedium,
}, func(s *scanner.Scanner, rule *rule.Rule) (results []result.Result) {
// Custom check logic here
return results
})
}
Vérification personnalisée de la configuration
# custom-checks.yml
checks:
- id: CUSTOM001
name: "Company S3 Naming Convention"
description: "S3 buckets must follow company naming convention"
severity: MEDIUM
provider: aws
service: s3
resource_type: aws_s3_bucket
attribute: bucket
pattern: "^mycompany-(dev|staging|prod)-[a-z]+-[a-z0-9]{6}$"
message: "Bucket name must follow format: mycompany-{env}-{purpose}-{random}"
Chargement des vérifications personnalisées
# Load custom checks from directory
tfsec --custom-check-dir ./custom-checks
# Load custom checks from multiple directories
tfsec --custom-check-dir ./custom-checks --custom-check-dir ./team-checks
# Use custom configuration file
tfsec --config-file ./custom-tfsec-config.yml
Caractéristiques avancées
Analyse du plan Terraform
# Analyze Terraform plan file
terraform plan -out=tfplan
terraform show -json tfplan > tfplan.json
tfsec --tfplan tfplan.json
# Analyze plan with specific format
tfsec --tfplan tfplan.json --format json --out plan-results.json
Analyse des modules
# Scan Terraform modules
tfsec ./modules/
# Scan specific module
tfsec ./modules/vpc/
# Scan with module path context
tfsec --include-paths "modules/**" --exclude-paths "examples/**"
Analyse de l'espace de travail
# Analyze specific Terraform workspace
terraform workspace select production
terraform plan -out=prod-plan
terraform show -json prod-plan > prod-plan.json
tfsec --tfplan prod-plan.json --out prod-security-report.json
Intégration avec Terraform Cloud
# Download plan from Terraform Cloud
# (requires API token and run ID)
curl -H "Authorization: Bearer $TFC_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
"https://app.terraform.io/api/v2/runs/$RUN_ID/plan" \
| jq -r '.data.attributes.log-read-url' \
| xargs curl -o plan.json
tfsec --tfplan plan.json
Rapports et statistiques
Rapports détaillés
# Generate comprehensive report
tfsec --format json --include-passed --out detailed-report.json
# Generate SARIF report for security tools
tfsec --format sarif --out security-report.sarif
# Generate multiple formats
tfsec --format json --out results.json
tfsec --format html --out report.html
tfsec --format csv --out metrics.csv
Collecte de données
# Extract metrics from JSON report
jq '.results | group_by(.severity) | map({severity: .[0].severity, count: length})' results.json
# Count issues by provider
jq '.results | group_by(.rule.provider) | map({provider: .[0].rule.provider, count: length})' results.json
# Get top failing checks
jq '.results | group_by(.rule.id) | map({check: .[0].rule.id, count: length}) | sort_by(.count) | reverse | .[0:10]' results.json
Intégration des tableaux de bord
# Python script to parse TFSec results
import json
import matplotlib.pyplot as plt
def analyze_tfsec_results(results_file):
with open(results_file, 'r') as f:
data = json.load(f)
# Count by severity
severity_counts = {}
for result in data['results']:
severity = result['severity']
severity_counts[severity] = severity_counts.get(severity, 0) + 1
# Create visualization
plt.figure(figsize=(10, 6))
plt.bar(severity_counts.keys(), severity_counts.values())
plt.title('Security Issues by Severity')
plt.xlabel('Severity')
plt.ylabel('Count')
plt.savefig('tfsec-dashboard.png')
return severity_counts
# Usage
results = analyze_tfsec_results('results.json')
print(f"Security issues found: {results}")
Optimisation des performances
Optimisation des grandes bases de codes
# Optimize for large codebases
tfsec --concurrency-limit 10 --exclude-paths "**/.terraform/**"
# Scan specific directories only
tfsec ./environments/production/
# Use include patterns for focused scanning
tfsec --include-paths "**/*.tf" --exclude-paths "**/examples/**"
Analyses de cache et d'accroissement
# Cache results for faster subsequent scans
export TFSEC_CACHE_DIR=~/.tfsec-cache
tfsec --cache-dir ~/.tfsec-cache
# Incremental scanning (scan only changed files)
# Get changed files from git
CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD | grep '\.tf$' | tr '\n' ' ')
if [ -n "$CHANGED_FILES" ]; then
tfsec $CHANGED_FILES
fi
Traitement parallèle
# Run multiple TFSec instances in parallel
find . -name "*.tf" -type d | \
xargs -I {} -P 4 tfsec --format json --out {}/tfsec-results.json {}
# Combine results
jq -s 'add' **/tfsec-results.json > combined-results.json
Dépannage
Questions communes
# Debug mode for troubleshooting
tfsec --debug
# Verbose output
tfsec --verbose
# Check version and supported providers
tfsec --version
# Validate configuration file
tfsec --config-file tfsec.yml --debug
Problèmes de mémoire et de performance
# Increase memory limit for large projects
export GOMAXPROCS=4
export GOGC=100
# Reduce memory usage
tfsec --concurrency-limit 2 --exclude-paths "**/.terraform/**"
# Profile memory usage
tfsec --profile-memory --out memory-profile.prof
Faux positifs
# Handle false positives with suppressions
# Use inline comments for specific cases
#tfsec:ignore:AWS001:This is a false positive because...
# Update configuration to exclude problematic checks
# .tfsec.yml
exclude_checks:
- AWS001 # False positive in our use case
# Report false positives to TFSec team
# Create issue at: https://github.com/aquasecurity/tfsec/issues
Migration vers Trivy
Intégration trivy
# TFSec is now part of Trivy
# Install Trivy
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
# Scan with Trivy (includes TFSec functionality)
trivy config .
# Use TFSec-compatible options
trivy config --format json --output results.json .
Commandements de migration
# Old TFSec command
tfsec --format json --out results.json
# New Trivy equivalent
trivy config --format json --output results.json .
# Migrate configuration
# .tfsec.yml becomes .trivyignore or trivy.yaml
Meilleures pratiques
Stratégie de numérisation de la sécurité
# 1. Start with baseline scan
tfsec --format json --out baseline.json
# 2. Implement in CI/CD with soft fail initially
tfsec --soft-fail
# 3. Gradually reduce acceptable risk levels
tfsec --minimum-severity HIGH
# 4. Regular security reviews
tfsec --format html --out weekly-report.html
Adoption par l'équipe
# Developer workflow:
# 1. Pre-commit hooks
echo '#!/bin/bash
tfsec --minimum-severity HIGH
' > .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
# 2. IDE integration
# Install TFSec extension for VS Code or other IDEs
# 3. Regular training
# Schedule security awareness sessions
# Share common vulnerability patterns
# Review security findings in team meetings
Gestion de la configuration
# Version control all configuration
git add .tfsec.yml
git commit -m "Add TFSec security scanning configuration"
# Environment-specific configurations
# .tfsec-dev.yml - Development environment
# .tfsec-prod.yml - Production environment
# Use appropriate config per environment
tfsec --config-file .tfsec-${ENVIRONMENT}.yml
Ressources
Documentation
- [Documentation TFSec] (LINK_9)
- [Répertoire GitHub] (LINK_9)
- Cochez la référence
Communauté
- [Débats de GitHub] (LINK_9)
- [Communauté Slack] (LINK_9)
- [Débordement de la pile] (LINK_9)
Formation
- Pratiques exemplaires en matière de sécurité de la terrasse
- [Sécurité des infrastructures] (LINK_9)
- [Guide DevSecOps] (LINK_9)