spinny:~/writing $ less devsecops-shift-left-security-guide.md
12ช่องโหว่ที่พบระหว่างเขียนโค้ดใช้เวลาเพียงไม่กี่นาทีในการแก้ไข ช่องโหว่เดียวกันที่ถูกพบใน production จะเสียเวลาถึงหนึ่ง sprint และหากผู้โจมตีเป็นคนพบก่อน ค่าใช้จ่ายจะสูงถึงหลายล้านดอลลาร์ นี่คือเหตุผลหลักของ **shift-left security** - การย้ายการตรวจสอบความปลอดภัยให้เร็วที่สุดเท่าที่เป็นไปได้ในวงจรการพัฒนา34DevSecOps นำแนวคิดนี้มาเปลี่ยนเป็นแนวปฏิบัติ: ความปลอดภัยไม่ใช่ขั้นตอนแยกต่างหากในตอนท้าย แต่เป็นกระบวนการต่อเนื่องที่สอดแทรกอยู่ในทุกขั้นตอนของการพัฒนา ตั้งแต่โค้ดบรรทัดแรกไปจนถึงการ deploy สู่ production56## ต้นทุนของการทำ Security ล่าช้า78รายงาน Cost of a Data Breach ของ IBM แสดงให้เห็นอย่างต่อเนื่องว่าต้นทุนในการแก้ไขปัญหาความปลอดภัยเพิ่มขึ้นแบบทวีคูณเมื่อค้นพบช้าลง:910| ขั้นตอน | ต้นทุนการแก้ไข | เวลาในการแก้ไข |11|-------|------------|-------------|12| **IDE / Local Dev** | นาที | วินาทีถึงนาที |13| **Code Review / PR** | ชั่วโมง | นาทีถึงชั่วโมง |14| **CI/CD Pipeline** | วัน | ชั่วโมงถึงวัน |15| **Staging / QA** | สัปดาห์ | วัน |16| **Production** | เดือน | สัปดาห์ถึงเดือน |17| **หลังถูกเจาะระบบ** | หลายล้านดอลลาร์ | เดือนถึงปี |1819บทสรุปชัดเจน: ทุกขั้นตอนที่คุณเลื่อนความปลอดภัยให้เร็วขึ้น จะช่วยประหยัดต้นทุนและเวลาได้อย่างมหาศาล2021## DevSecOps Pipeline2223DevSecOps pipeline ที่สมบูรณ์จะรวมการตรวจสอบความปลอดภัยไว้ในทุกขั้นตอน:2425```mermaid26graph LR27 IDE[IDE / Editor] --> PC[Pre-commit Hooks]28 PC --> PR[Pull Request]29 PR --> CI[CI Pipeline]30 CI --> Build[Build / Package]31 Build --> Deploy[Deploy]32 Deploy --> Runtime[Runtime / Production]3334 IDE -.- S1[SAST\nSecret Detection\nLinting]35 PC -.- S2[Secrets Scan\nFormat Check]36 PR -.- S3[Code Review\nDependency Audit]37 CI -.- S4[SAST\nSCA\nContainer Scan\nSBOM]38 Build -.- S5[Image Signing\nArtifact Verification]39 Deploy -.- S6[Policy Enforcement\nAdmission Control]40 Runtime -.- S7[DAST\nWAF\nMonitoring]41```4243มาดูรายละเอียดของแต่ละขั้นตอนพร้อมเครื่องมือและการตั้งค่าที่เป็นรูปธรรม4445## ขั้นตอนที่ 1: ความปลอดภัยใน IDE4647feedback loop ที่เร็วที่สุด จับช่องโหว่ได้ก่อนที่คุณจะบันทึกไฟล์4849### เครื่องมือที่แนะนำ5051- **Semgrep**: เครื่องมือ static analysis น้ำหนักเบาพร้อม community rules สำหรับช่องโหว่ OWASP52- **Snyk IDE Extension**: สแกนช่องโหว่ของ dependency แบบ real-time53- **GitLens + GitLeaks**: ตรวจจับ secret ในเอดิเตอร์54- **ESLint Security Plugins**: `eslint-plugin-security` สำหรับ Node.js, `eslint-plugin-no-unsanitized` สำหรับ DOM XSS5556### ตัวอย่าง: การตั้งค่า ESLint Security5758```json59{60 "extends": ["eslint:recommended"],61 "plugins": ["security", "no-unsanitized"],62 "rules": {63 "security/detect-object-injection": "warn",64 "security/detect-non-literal-regexp": "warn",65 "security/detect-unsafe-regex": "error",66 "security/detect-buffer-noassert": "error",67 "security/detect-eval-with-expression": "error",68 "security/detect-no-csrf-before-method-override": "error",69 "security/detect-possible-timing-attacks": "warn",70 "no-unsanitized/method": "error",71 "no-unsanitized/property": "error"72 }73}74```7576## ขั้นตอนที่ 2: Pre-commit Hooks7778แนวป้องกันที่สอง ทำงานอัตโนมัติก่อนทุก commit เพื่อบล็อกโค้ดอันตรายไม่ให้เข้า repository7980### Gitleaks: จับ Secret ก่อนที่จะเข้าสู่ Git8182ข้อผิดพลาดด้านความปลอดภัยที่พบบ่อยที่สุดในโค้ดเบสคือการ commit secret - API key, รหัสผ่านฐานข้อมูล, token เมื่อ secret เข้าสู่ git history แล้ว จะลบออกอย่างสมบูรณ์ได้ยากมาก (แม้จะใช้ force push แต่ fork และ cache อาจยังเก็บข้อมูลไว้)8384```yaml85# .pre-commit-config.yaml86repos:87 - repo: https://github.com/gitleaks/gitleaks88 rev: v8.21.089 hooks:90 - id: gitleaks9192 - repo: https://github.com/semgrep/semgrep93 rev: v1.90.094 hooks:95 - id: semgrep96 args: ['--config', 'auto']97```9899ติดตั้งและเปิดใช้งาน:100101```bash102pip install pre-commit103pre-commit install104```105106ตอนนี้ทุกครั้งที่ `git commit` จะสแกน secret ที่รั่วไหลและช่องโหว่ทั่วไปโดยอัตโนมัติ หากพบสิ่งใด commit จะถูกบล็อก107108### กฎ Gitleaks ที่กำหนดเอง109110คุณสามารถเพิ่ม pattern ที่กำหนดเองสำหรับ secret ขององค์กร:111112```toml113# .gitleaks.toml114title = "Custom Gitleaks Config"115116[[rules]]117id = "internal-api-key"118description = "Internal API key detected"119regex = '''INTERNAL_KEY_[A-Za-z0-9]{32}'''120tags = ["key", "internal"]121```122123## ขั้นตอนที่ 3: ความปลอดภัยของ CI/CD Pipeline124125นี่คือจุดที่งานหนักเกิดขึ้น CI pipeline ของคุณควรรันการสแกนความปลอดภัยหลายตัวในทุก pull request126127### SAST (Static Application Security Testing)128129เครื่องมือ SAST วิเคราะห์ซอร์สโค้ดโดยไม่ต้องรัน เพื่อค้นหา pattern ที่บ่งชี้ช่องโหว่130131```yaml132# .github/workflows/security.yml133name: Security Scan134on:135 pull_request:136 branches: [main]137138jobs:139 sast:140 name: Static Analysis141 runs-on: ubuntu-latest142 steps:143 - uses: actions/checkout@v4144145 - name: Run Semgrep146 uses: semgrep/semgrep-action@v1147 with:148 config: >-149 p/owasp-top-ten150 p/typescript151 p/nodejs152 p/react153 generateSarif: true154155 - name: Upload SARIF156 uses: github/codeql-action/upload-sarif@v3157 with:158 sarif_file: semgrep.sarif159```160161ruleset `p/owasp-top-ten` ของ Semgrep จับช่องโหว่ที่พบบ่อยที่สุด: SQL injection, XSS, SSRF, path traversal, insecure deserialization และอื่น ๆ162163### SCA (Software Composition Analysis)164165SCA สแกน dependency ของคุณเพื่อหาช่องโหว่ที่รู้จัก สิ่งนี้สำคัญมาก - โค้ดแอปพลิเคชันสมัยใหม่กว่า 80% มาจาก dependency โอเพนซอร์ส166167```yaml168 dependency-scan:169 name: Dependency Audit170 runs-on: ubuntu-latest171 steps:172 - uses: actions/checkout@v4173174 - name: Run Snyk175 uses: snyk/actions/node@master176 env:177 SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}178 with:179 args: --severity-threshold=high180181 - name: npm audit182 run: npm audit --audit-level=high183```184185### ความปลอดภัยของ Container ด้วย Trivy186187หากคุณ build Docker image การสแกนช่องโหว่เป็นสิ่งจำเป็น **Trivy** เป็น container scanner โอเพนซอร์สที่ได้รับความนิยมสูงสุด188189```yaml190 container-scan:191 name: Container Security192 runs-on: ubuntu-latest193 steps:194 - uses: actions/checkout@v4195196 - name: Build image197 run: docker build -t my-app:${{ github.sha }} .198199 - name: Run Trivy200 uses: aquasecurity/trivy-action@master201 with:202 image-ref: my-app:${{ github.sha }}203 format: 'sarif'204 output: 'trivy-results.sarif'205 severity: 'CRITICAL,HIGH'206 exit-code: '1'207208 - name: Upload Trivy SARIF209 uses: github/codeql-action/upload-sarif@v3210 with:211 sarif_file: trivy-results.sarif212```213214### การสร้าง SBOM215216**Software Bill of Materials (SBOM)** คือรายการที่สมบูรณ์ของทุก component ในแอปพลิเคชันของคุณ ถูกกำหนดให้ต้องมีมากขึ้นเรื่อย ๆ โดย compliance framework และกฎระเบียบของรัฐบาล (คำสั่งฝ่ายบริหารของสหรัฐฯ เรื่อง Cybersecurity กำหนดให้ซอฟต์แวร์ของรัฐบาลกลางต้องมี SBOM)217218```yaml219 sbom:220 name: Generate SBOM221 runs-on: ubuntu-latest222 steps:223 - uses: actions/checkout@v4224225 - name: Generate SBOM with Syft226 uses: anchore/sbom-action@v0227 with:228 format: spdx-json229 output-file: sbom.spdx.json230231 - name: Upload SBOM232 uses: actions/upload-artifact@v4233 with:234 name: sbom235 path: sbom.spdx.json236```237238## ขั้นตอนที่ 4: Docker Image ที่ปลอดภัย239240Docker image สำหรับ production ควรปฏิบัติตามหลักการให้สิทธิ์น้อยที่สุด นี่คือตัวอย่าง Dockerfile ที่ได้รับการเสริมความแข็งแกร่ง:241242```dockerfile243# Build stage244FROM node:22-alpine AS builder245WORKDIR /app246COPY package.json package-lock.json ./247RUN npm ci248COPY . .249RUN npm run build250251# Production stage252FROM node:22-alpine AS runner253WORKDIR /app254255# Install dumb-init before dropping root256RUN apk add --no-cache dumb-init257258# Don't run as root259RUN addgroup -S app && adduser -S app -G app260261# Copy only what's needed262COPY --from=builder --chown=app:app /app/dist ./dist263COPY --from=builder --chown=app:app /app/node_modules ./node_modules264COPY --from=builder --chown=app:app /app/package.json ./265266# Drop to non-root user267USER app268ENTRYPOINT ["dumb-init", "--"]269270# Health check271HEALTHCHECK --interval=30s --timeout=3s --retries=3 \272 CMD wget -qO- http://localhost:3000/health || exit 1273274EXPOSE 3000275CMD ["node", "dist/server.js"]276```277278แนวปฏิบัติสำคัญ:2792801. **ใช้ multi-stage build**: ขั้นตอน builder มี dev dependency ส่วนขั้นตอน runner มีเฉพาะโค้ด production2812. **อย่ารันด้วย root**: สร้าง non-root user แล้วสลับไปใช้2823. **ใช้ Alpine image**: พื้นผิวการโจมตีเล็กลง (package ที่ติดตั้งเริ่มต้นน้อยลง)2834. **ล็อกเวอร์ชัน image**: ใช้ `node:22-alpine` แทน `node:latest` เพื่อหลีกเลี่ยง supply chain attack2845. **ใช้ `npm ci`**: ติดตั้งแบบ deterministic จาก lock file ไม่ใช่ `npm install`285286## ขั้นตอนที่ 5: การจัดการ Secret287288Secret ที่ฝังในโค้ดเป็นสาเหตุอันดับหนึ่งของการถูกเจาะระบบที่เกิดจากนักพัฒนา289290### สิ่งที่ไม่ควรทำ291292```typescript293// NEVER do this294const API_KEY = "sk-1234567890abcdef";295const DB_PASSWORD = "supersecret123";296297const client = new Client({298 connectionString: `postgres://admin:${DB_PASSWORD}@db.example.com/prod`299});300```301302### สิ่งที่ควรทำแทน303304```typescript305// Use environment variables306const client = new Client({307 connectionString: process.env.DATABASE_URL308});309310// Or use a secret manager311import { SecretManagerServiceClient } from '@google-cloud/secret-manager';312313const client = new SecretManagerServiceClient();314const [version] = await client.accessSecretVersion({315 name: 'projects/my-project/secrets/db-password/versions/latest',316});317const dbPassword = version.payload?.data?.toString();318```319320### ลำดับชั้นการจัดการ Secret321322```mermaid323graph TD324 A[Secret Manager\nAWS Secrets Manager\nGCP Secret Manager\nHashiCorp Vault] --> B[Best: Rotated, audited, centralized]325 C[Environment Variables\nInjected at deploy time] --> D[Good: Not in code, but static]326 E[.env files\nWith .gitignore] --> F[Acceptable: Local development only]327 G[Hard-coded in source] --> H[NEVER: Instant breach risk]328329 style A fill:#d4edda330 style C fill:#fff3cd331 style E fill:#ffeeba332 style G fill:#f8d7da333```334335## OWASP Top 10: คู่มืออ้างอิงด่วน336337นักพัฒนาทุกคนควรรู้จัก OWASP Top 10 เวอร์ชันย่อ:338339| # | ช่องโหว่ | คำอธิบาย | การป้องกัน |340|---|--------------|-----------|------------|341| 1 | **Broken Access Control** | ผู้ใช้เข้าถึงทรัพยากรที่ไม่ควรเข้าถึง | ปฏิเสธเป็นค่าเริ่มต้น ตรวจสอบฝั่ง server |342| 2 | **Cryptographic Failures** | การเข้ารหัสอ่อนแอ ข้อมูลแบบ plaintext | ใช้อัลกอริทึมที่แข็งแกร่ง (AES-256, bcrypt) ใช้ TLS ทุกที่ |343| 3 | **Injection** | SQL, NoSQL, OS command injection | ใช้ parameterized query ตรวจสอบ input |344| 4 | **Insecure Design** | สถาปัตยกรรมที่มีข้อบกพร่อง | threat modeling, secure design pattern |345| 5 | **Security Misconfiguration** | credential เริ่มต้น, cloud bucket ที่เปิดอยู่ | ค่าเริ่มต้นที่เข้มงวด การตรวจสอบ config อัตโนมัติ |346| 6 | **Vulnerable Components** | CVE ที่รู้จักใน dependency | SCA scanning อัปเดตเป็นประจำ |347| 7 | **Auth Failures** | รหัสผ่านอ่อนแอ session เสียหาย | MFA rate limiting การจัดการ session ที่ปลอดภัย |348| 8 | **Data Integrity Failures** | อัปเดตที่ไม่ได้ลงนาม CI/CD ที่ไม่น่าเชื่อถือ | code signing, SBOM, pipeline integrity |349| 9 | **Logging Failures** | ไม่มี audit trail | structured logging แจ้งเตือนเมื่อพบความผิดปกติ |350| 10 | **SSRF** | Server-side request forgery | allowlist URL ขาออก ตรวจสอบ input |351352## Workflow ความปลอดภัยของ GitHub Actions ที่สมบูรณ์353354workflow ที่พร้อมใช้งาน production ซึ่งรวมทุกอย่างข้างต้น:355356```yaml357# .github/workflows/security.yml358name: Security Pipeline359on:360 pull_request:361 branches: [main]362 push:363 branches: [main]364365permissions:366 contents: read367 security-events: write368369jobs:370 secrets-scan:371 name: Secret Detection372 runs-on: ubuntu-latest373 steps:374 - uses: actions/checkout@v4375 with:376 fetch-depth: 0377 - uses: gitleaks/gitleaks-action@v2378 env:379 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}380381 sast:382 name: Static Analysis (SAST)383 runs-on: ubuntu-latest384 steps:385 - uses: actions/checkout@v4386 - uses: semgrep/semgrep-action@v1387 with:388 config: p/owasp-top-ten p/typescript p/nodejs389390 dependency-audit:391 name: Dependency Scan (SCA)392 runs-on: ubuntu-latest393 steps:394 - uses: actions/checkout@v4395 - uses: actions/setup-node@v4396 with:397 node-version: 22398 - run: npm ci399 - run: npm audit --audit-level=high400 - uses: snyk/actions/node@master401 env:402 SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}403 with:404 args: --severity-threshold=high405 continue-on-error: true406407 container-scan:408 name: Container Scan409 runs-on: ubuntu-latest410 needs: [sast, dependency-audit]411 steps:412 - uses: actions/checkout@v4413 - run: docker build -t app:${{ github.sha }} .414 - uses: aquasecurity/trivy-action@master415 with:416 image-ref: app:${{ github.sha }}417 severity: CRITICAL,HIGH418 exit-code: '1'419420 sbom:421 name: SBOM Generation422 runs-on: ubuntu-latest423 needs: [container-scan]424 steps:425 - uses: actions/checkout@v4426 - uses: anchore/sbom-action@v0427 with:428 format: spdx-json429 output-file: sbom.spdx.json430```431432```mermaid433graph TD434 PR[Pull Request] --> S1[Secret Detection]435 PR --> S2[SAST - Semgrep]436 PR --> S3[SCA - Snyk + npm audit]437 S2 --> S4[Container Scan - Trivy]438 S3 --> S4439 S4 --> S5[SBOM Generation]440 S5 --> Deploy[Deploy]441442 S1 -.- F1[Block if secrets found]443 S2 -.- F2[Block on critical vulns]444 S3 -.- F3[Block on high severity]445 S4 -.- F4[Block on critical CVEs]446```447448## ตัวชี้วัดที่ควรติดตาม449450คุณจะรู้ได้อย่างไรว่าโปรแกรม DevSecOps ของคุณทำงานได้ผล? ติดตามตัวชี้วัดเหล่านี้:451452- **เวลาเฉลี่ยในการแก้ไข (MTTR)**: ความเร็วในการแก้ไขช่องโหว่หลังตรวจพบ453- **อัตราการหลุดรอดของช่องโหว่**: เปอร์เซ็นต์ของช่องโหว่ที่ไปถึง production454- **อัตรา false positive**: false positive มากเกินไปจะนำไปสู่ความเหนื่อยล้าจากการแจ้งเตือนและการเพิกเฉยคำเตือน455- **ความใหม่ของ dependency**: อายุเฉลี่ยของ dependency (ยิ่งเก่ายิ่งมีโอกาสมี CVE ที่รู้จัก)456- **ความครอบคลุมของ SBOM**: เปอร์เซ็นต์ของโปรเจกต์ที่มี SBOM ล่าสุด457458## เริ่มต้น: แผนงานเชิงปฏิบัติ459460อย่าพยายามทำทุกอย่างพร้อมกัน การดำเนินการเป็นขั้นตอนจะได้ผลดีกว่า:461462```mermaid463flowchart TD464 A[Week 1-2: Foundations] --> B[Week 3-4: CI/CD Integration]465 B --> C[Month 2: Container Security]466 C --> D[Month 3+: Advanced]467468 A --> A1[Add Gitleaks pre-commit hooks]469 A --> A2[Enable npm audit in CI]470 A --> A3[Add .gitignore for .env files]471472 B --> B1[Add Semgrep to GitHub Actions]473 B --> B2[Add Snyk dependency scanning]474 B --> B3[Set up SARIF upload to GitHub]475476 C --> C1[Add Trivy container scanning]477 C --> C2[Harden Dockerfiles]478 C --> C3[Generate SBOMs]479480 D --> D1[Secret manager integration]481 D --> D2[Runtime protection - DAST]482 D --> D3[Policy as code - OPA]483```484485## บทสรุป486487DevSecOps ไม่ใช่การเพิ่มเครื่องมือมากขึ้นใน pipeline - แต่เป็นการทำให้ความปลอดภัยเป็นส่วนหนึ่งตามธรรมชาติของการสร้างซอฟต์แวร์ เป้าหมายไม่ใช่การบล็อกทุก PR ด้วยคำเตือนด้านความปลอดภัย แต่เป็นการให้ feedback ที่รวดเร็วแก่นักพัฒนาเพื่อให้สามารถแก้ไขปัญหาได้ขณะที่โค้ดยังสดใหม่ในหัว488489เริ่มจากพื้นฐาน: pre-commit hooks สำหรับ secret, dependency scanning ใน CI และ container scanning สำหรับ Docker image จากนั้นปรับปรุงตามความต้องการของทีม490491ความปลอดภัยไม่ใช่ฟีเจอร์ที่ส่งมอบครั้งเดียว แต่เป็นแนวปฏิบัติที่คุณสร้างไว้ในทุก commit492493> **รายการตรวจสอบเริ่มต้น DevSecOps:**494>495> - [x] ติดตั้ง Gitleaks pre-commit hooks496> - [x] เพิ่ม .env และไฟล์ secret ใน .gitignore497> - [x] รวม Semgrep SAST ใน CI pipeline498> - [x] ใช้ Snyk หรือ npm audit สำหรับ dependency scanning499> - [x] ใช้ Trivy สำหรับ container image scanning500> - [x] ใช้ non-root user ใน Dockerfile501> - [x] เก็บ secret ใน environment variable หรือ secret manager502> - [x] สร้าง SBOM ในทุกการ release503> - [x] ทุกคนในทีมเข้าใจ OWASP Top 10504
:DevSecOps สำหรับนักพัฒนา: คู่มือปฏิบัติ Shift-Left Securitylines 1-504 (END) — press q to close