Snyk คืออะไรและทำไมต้องใช้
Snyk เป็น developer security platform ที่ช่วยค้นหาและแก้ไขช่องโหว่ใน code, dependencies, containers และ infrastructure as code แบบอัตโนมัติ Snyk ออกแบบมาสำหรับ developers ทำให้ security เป็นส่วนหนึ่งของ development workflow ไม่ใช่ขั้นตอนแยกที่ทำทีหลัง
Snyk มี 4 products หลักคือ Snyk Open Source ที่ scan dependencies สำหรับ known vulnerabilities (SCA), Snyk Code ที่เป็น SAST tool สำหรับ scan source code, Snyk Container ที่ scan Docker images สำหรับ OS vulnerabilities และ Snyk IaC ที่ scan Terraform, CloudFormation, Kubernetes configs
Compliance Automation หมายถึงการทำให้กระบวนการตรวจสอบ security compliance เป็นอัตโนมัติ แทนที่จะตรวจสอบด้วยมือทุกครั้ง ให้ CI/CD pipeline ตรวจสอบให้โดยอัตโนมัติ ปฏิเสธ code ที่ไม่ผ่าน security standards และสร้าง compliance reports อัตโนมัติ
Standards ที่ Snyk ช่วย comply ได้แก่ SOC 2 Type II, ISO 27001, PCI DSS, HIPAA, GDPR, OWASP Top 10 และ CIS Benchmarks
ติดตั้ง Snyk CLI และ Scan โปรเจกต์
เริ่มต้นใช้งาน Snyk
# ติดตั้ง Snyk CLI
npm install -g snyk
# หรือใช้ standalone binary
# Linux
curl -sL https://static.snyk.io/cli/latest/snyk-linux -o snyk
chmod +x snyk
sudo mv snyk /usr/local/bin/
# macOS
brew install snyk
# Windows
scoop install snyk
# Authenticate
snyk auth
# หรือใช้ API token
export SNYK_TOKEN="your-api-token-here"
snyk auth $SNYK_TOKEN
# === Open Source Scan (SCA) ===
# Scan dependencies
snyk test
# Scan และดู details
snyk test --severity-threshold=high
# Scan specific file
snyk test --file=requirements.txt
snyk test --file=package.json
snyk test --file=go.mod
# Monitor (track ใน Snyk dashboard)
snyk monitor --project-name="my-project"
# === Code Scan (SAST) ===
snyk code test
# Scan specific directory
snyk code test ./src
# Output as JSON
snyk code test --json > code_results.json
# === Container Scan ===
# Scan Docker image
snyk container test nginx:latest
snyk container test my-app:v1.0 --file=Dockerfile
# Scan และ monitor
snyk container monitor my-app:v1.0
# === IaC Scan ===
# Scan Terraform
snyk iac test terraform/
# Scan Kubernetes manifests
snyk iac test k8s/deployment.yaml
# Scan CloudFormation
snyk iac test cloudformation/template.yaml
# Custom severity threshold
snyk iac test --severity-threshold=medium
# === Output Formats ===
# JSON output
snyk test --json > results.json
# SARIF output (for GitHub Code Scanning)
snyk test --sarif > results.sarif
# HTML report
snyk test --json | snyk-to-html -o report.html
# === Fix vulnerabilities ===
# Auto-fix (upgrade dependencies)
snyk fix
# ดู fix suggestions
snyk test --show-vulnerable-paths=all
รวม Snyk กับ CI/CD Pipeline
GitHub Actions workflow สำหรับ Snyk scanning
# .github/workflows/snyk-security.yml
name: Snyk Security Scan
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
schedule:
- cron: '0 6 * * 1' # Weekly Monday 06:00
permissions:
security-events: write
contents: read
jobs:
snyk-open-source:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install Dependencies
run: npm ci
- name: Snyk Open Source Scan
uses: snyk/actions/node@master
env:
SNYK_TOKEN: }
with:
args: >
--severity-threshold=high
--fail-on=all
--sarif-file-output=snyk-oss.sarif
continue-on-error: true
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: snyk-oss.sarif
snyk-code:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Snyk Code Scan
uses: snyk/actions/node@master
env:
SNYK_TOKEN: }
with:
command: code test
args: --sarif-file-output=snyk-code.sarif
continue-on-error: true
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: snyk-code.sarif
snyk-container:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build Docker Image
run: docker build -t my-app:} .
- name: Snyk Container Scan
uses: snyk/actions/docker@master
env:
SNYK_TOKEN: }
with:
image: my-app:}
args: >
--severity-threshold=high
--file=Dockerfile
--sarif-file-output=snyk-container.sarif
continue-on-error: true
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: snyk-container.sarif
snyk-iac:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Snyk IaC Scan
uses: snyk/actions/iac@master
env:
SNYK_TOKEN: }
with:
args: >
--severity-threshold=medium
--sarif-file-output=snyk-iac.sarif
continue-on-error: true
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: snyk-iac.sarif
security-gate:
needs: [snyk-open-source, snyk-code, snyk-container, snyk-iac]
runs-on: ubuntu-latest
steps:
- name: Security Gate Check
run: |
echo "All security scans completed"
echo "Check GitHub Security tab for results"
Compliance Automation ด้วย Snyk API
ใช้ Snyk API สร้างระบบ compliance อัตโนมัติ
#!/usr/bin/env python3
# snyk_compliance.py — Automated Compliance with Snyk API
import requests
import json
import logging
from datetime import datetime
from typing import Dict, List, Optional
from dataclasses import dataclass
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("snyk_compliance")
@dataclass
class ComplianceResult:
project_name: str
scan_type: str
critical: int
high: int
medium: int
low: int
compliant: bool
violations: List[str]
class SnykComplianceChecker:
def __init__(self, api_token, org_id):
self.base_url = "https://api.snyk.io/v1"
self.headers = {
"Authorization": f"token {api_token}",
"Content-Type": "application/json",
}
self.org_id = org_id
def get_projects(self) -> List[Dict]:
resp = requests.get(
f"{self.base_url}/org/{self.org_id}/projects",
headers=self.headers,
)
resp.raise_for_status()
return resp.json().get("projects", [])
def get_project_issues(self, project_id) -> Dict:
resp = requests.post(
f"{self.base_url}/org/{self.org_id}/project/{project_id}/aggregated-issues",
headers=self.headers,
json={"includeDescription": False, "includeIntroducedThrough": False},
)
resp.raise_for_status()
return resp.json()
def check_compliance(self, policy: Dict) -> List[ComplianceResult]:
projects = self.get_projects()
results = []
for project in projects:
issues = self.get_project_issues(project["id"])
critical = 0
high = 0
medium = 0
low = 0
for issue in issues.get("issues", []):
severity = issue.get("issueData", {}).get("severity", "low")
if severity == "critical":
critical += 1
elif severity == "high":
high += 1
elif severity == "medium":
medium += 1
else:
low += 1
violations = []
compliant = True
if critical > policy.get("max_critical", 0):
violations.append(f"Critical: {critical} (max: {policy['max_critical']})")
compliant = False
if high > policy.get("max_high", 0):
violations.append(f"High: {high} (max: {policy['max_high']})")
compliant = False
results.append(ComplianceResult(
project_name=project["name"],
scan_type=project.get("type", "unknown"),
critical=critical, high=high, medium=medium, low=low,
compliant=compliant, violations=violations,
))
return results
def generate_compliance_report(self, results: List[ComplianceResult]):
total = len(results)
compliant = sum(1 for r in results if r.compliant)
report = {
"report_date": datetime.utcnow().isoformat(),
"organization": self.org_id,
"summary": {
"total_projects": total,
"compliant": compliant,
"non_compliant": total - compliant,
"compliance_rate": f"{compliant/total*100:.1f}%" if total > 0 else "N/A",
},
"total_vulnerabilities": {
"critical": sum(r.critical for r in results),
"high": sum(r.high for r in results),
"medium": sum(r.medium for r in results),
"low": sum(r.low for r in results),
},
"projects": [
{
"name": r.project_name,
"type": r.scan_type,
"compliant": r.compliant,
"violations": r.violations,
"vulnerabilities": {
"critical": r.critical,
"high": r.high,
"medium": r.medium,
"low": r.low,
},
}
for r in results
],
}
return report
# ใช้งาน
# checker = SnykComplianceChecker("snyk-api-token", "org-id")
#
# policy = {
# "max_critical": 0,
# "max_high": 5,
# "max_medium": 20,
# }
#
# results = checker.check_compliance(policy)
# report = checker.generate_compliance_report(results)
# print(json.dumps(report, indent=2))
สร้าง Security Dashboard และ Reports
Dashboard สำหรับ security overview
#!/usr/bin/env python3
# security_dashboard.py — Security Compliance Dashboard
import json
from datetime import datetime
from pathlib import Path
class SecurityDashboard:
def __init__(self):
self.reports = []
def add_snyk_report(self, report_data):
self.reports.append({
"source": "snyk",
"data": report_data,
"timestamp": datetime.utcnow().isoformat(),
})
def generate_html_dashboard(self, output_path="dashboard.html"):
total_critical = sum(
r["data"]["total_vulnerabilities"]["critical"]
for r in self.reports if r["source"] == "snyk"
)
total_high = sum(
r["data"]["total_vulnerabilities"]["high"]
for r in self.reports if r["source"] == "snyk"
)
compliance_rates = []
for r in self.reports:
if r["source"] == "snyk":
s = r["data"]["summary"]
if s["total_projects"] > 0:
rate = s["compliant"] / s["total_projects"] * 100
compliance_rates.append(rate)
avg_compliance = sum(compliance_rates) / len(compliance_rates) if compliance_rates else 0
html = f"""
Snyk Code Security Compliance Automation — | SiamCafe
Generated: {datetime.utcnow().strftime('%Y-%m-%d %H:%M UTC')}
{total_critical}
Critical Vulnerabilities
{total_high}
High Vulnerabilities
{avg_compliance:.0f}%
Compliance Rate
{len(self.reports)}
Scans Completed
Project Details
Project Type Critical High Medium Status """
for r in self.reports:
if r["source"] == "snyk":
for p in r["data"].get("projects", []):
badge = "badge-pass" if p["compliant"] else "badge-fail"
status = "PASS" if p["compliant"] else "FAIL"
v = p["vulnerabilities"]
html += f"""
{p['name']}
{p['type']}
{v['critical']}
{v['high']}
{v['medium']}
{status}
"""
html += """
"""
Path(output_path).write_text(html)
print(f"Dashboard saved to {output_path}")
def export_csv(self, output_path="compliance_report.csv"):
lines = ["Project, Type, Critical, High, Medium, Low, Compliant, Violations"]
for r in self.reports:
if r["source"] == "snyk":
for p in r["data"].get("projects", []):
v = p["vulnerabilities"]
violations = "; ".join(p.get("violations", []))
lines.append(
f"{p['name']},{p['type']},{v['critical']},{v['high']},"
f"{v['medium']},{v['low']},{p['compliant']},{violations}"
)
Path(output_path).write_text("\n".join(lines))
print(f"CSV exported to {output_path}")
# dashboard = SecurityDashboard()
# dashboard.add_snyk_report(report)
# dashboard.generate_html_dashboard()
# dashboard.export_csv()
Policy as Code และ Custom Rules
กำหนด security policies แบบ code
# === Snyk Policy File (.snyk) ===
# วางที่ root ของ project
# .snyk
# version: v1.25.0
# ignore:
# SNYK-JS-LODASH-567746:
# - '*':
# reason: 'Not exploitable in our context'
# expires: 2025-06-01T00:00:00.000Z
# SNYK-PYTHON-REQUESTS-5595532:
# - '*':
# reason: 'Will fix in next sprint'
# expires: 2025-03-01T00:00:00.000Z
# patch: {}
# === Custom Policy (Python) ===
#!/usr/bin/env python3
# security_policy.py — Security Policy as Code
import json
import sys
from datetime import datetime
class SecurityPolicy:
"""Define and enforce security policies"""
def __init__(self, policy_file="security_policy.json"):
self.policy = self._load_policy(policy_file)
def _load_policy(self, filepath):
default_policy = {
"name": "Production Security Policy",
"version": "1.0",
"rules": {
"max_critical_vulns": 0,
"max_high_vulns": 0,
"max_medium_vulns": 10,
"max_days_unfixed_critical": 1,
"max_days_unfixed_high": 7,
"max_days_unfixed_medium": 30,
"required_scans": ["sca", "sast", "container", "iac"],
"blocked_licenses": ["GPL-3.0", "AGPL-3.0"],
"minimum_test_coverage": 80,
"required_code_review": True,
"branch_protection": True,
},
"exceptions": [],
"compliance_frameworks": ["soc2", "iso27001", "owasp"],
}
try:
with open(filepath) as f:
return json.load(f)
except FileNotFoundError:
return default_policy
def evaluate(self, scan_results):
rules = self.policy["rules"]
violations = []
warnings = []
# Check vulnerability counts
critical = scan_results.get("critical", 0)
high = scan_results.get("high", 0)
medium = scan_results.get("medium", 0)
if critical > rules["max_critical_vulns"]:
violations.append(
f"CRITICAL: {critical} critical vulns (max: {rules['max_critical_vulns']})"
)
if high > rules["max_high_vulns"]:
violations.append(
f"HIGH: {high} high vulns (max: {rules['max_high_vulns']})"
)
if medium > rules["max_medium_vulns"]:
warnings.append(
f"MEDIUM: {medium} medium vulns (max: {rules['max_medium_vulns']})"
)
# Check blocked licenses
for dep in scan_results.get("dependencies", []):
if dep.get("license") in rules["blocked_licenses"]:
violations.append(
f"LICENSE: {dep['name']} uses blocked license {dep['license']}"
)
# Check required scans
completed_scans = scan_results.get("completed_scans", [])
for required in rules["required_scans"]:
if required not in completed_scans:
violations.append(f"MISSING SCAN: {required} scan not completed")
passed = len(violations) == 0
result = {
"policy": self.policy["name"],
"evaluated_at": datetime.utcnow().isoformat(),
"passed": passed,
"violations": violations,
"warnings": warnings,
"exit_code": 0 if passed else 1,
}
return result
# CI/CD integration
policy = SecurityPolicy()
# scan_data = json.loads(sys.stdin.read()) # pipe from snyk
scan_data = {"critical": 0, "high": 2, "medium": 5, "completed_scans": ["sca", "sast"]}
result = policy.evaluate(scan_data)
print(json.dumps(result, indent=2))
# sys.exit(result["exit_code"])
FAQ คำถามที่พบบ่อย
Q: Snyk ฟรีไหม?
A: Snyk มี Free plan ที่รองรับ 200 open source tests ต่อเดือน, 100 container tests และ 300 IaC tests เพียงพอสำหรับ small projects และ individual developers Team plan เริ่มต้นที่ $25/developer/month Business plan สำหรับองค์กรใหญ่ สำหรับ open source projects Snyk ให้ใช้ฟรีไม่จำกัด
Q: Snyk กับ SonarQube ต่างกันอย่างไร?
A: Snyk เน้น security (vulnerabilities, license compliance) ครอบคลุม dependencies, containers และ IaC SonarQube เน้น code quality (bugs, code smells, technical debt) และ security hotspots องค์กรส่วนใหญ่ใช้ทั้งสองร่วมกัน Snyk สำหรับ security scanning และ SonarQube สำหรับ code quality Snyk มี developer experience ที่ดีกว่าและ fix suggestions ที่ดีกว่า
Q: Compliance automation ช่วยลด audit time ได้จริงไหม?
A: ได้มาก จากประสบการณ์ลด SOC 2 audit preparation จาก 2-3 เดือนเหลือ 2-3 สัปดาห์ เพราะ evidence collection อัตโนมัติ (scan results, reports, fix history), policy enforcement อัตโนมัติ (CI/CD blocks non-compliant code), continuous monitoring แทน point-in-time checks และ audit trail ที่ครบถ้วนและ traceable
Q: จะ handle false positives อย่างไร?
A: ใช้ .snyk file เพื่อ ignore vulnerabilities ที่ไม่เกี่ยวข้อง (ต้องระบุเหตุผลและ expiry date) ตั้ง severity threshold ที่เหมาะสม (อาจเริ่มที่ high แล้วค่อยลดเป็น medium) ใช้ Snyk UI เพื่อ mark false positives Review ignored vulnerabilities เป็นประจำ (ทุก quarter) อย่า ignore ทุกอย่าง ควร fix ให้ได้มากที่สุด
