สวัสดีค่าา EP สุดท้ายของซีรี่ส์มาถึงแล้ว!
ก่อนจะจบ ขอเล่าให้ฟังก่อนนะ ตอนที่เตรียม HYROX ช่วงสุดท้ายก่อนแข่ง โค้ชทีนเตือนเรื่องนึงเสมอคือ "อย่าประมาทตรงที่คิดว่าตัวเองถนัด" เพราะ station ที่เราคิดว่าง่ายที่สุดอย่าง rowing มักเป็นจุดที่เสียเวลามากที่สุดเพราะไม่ได้เตรียมจริงจัง
Security ในโลก DevOps ก็เหมือนกันค่ะ คนมักมองข้ามเพราะคิดว่า "ยังเล็กอยู่ ยังไม่โดนหรอก" จนกว่าจะโดนจริงๆ แล้วก็สาย
DevSecOps คืออะไร
DevSecOps คือการนำ Security เข้ามาเป็นส่วนหนึ่งของ DevOps pipeline ตั้งแต่ต้น แทนที่จะเอา security มา check ตอนใกล้ release หรือหลัง incident เกิดขึ้นแล้ว
แนวคิดคือ Shift Left ขยับ security check ให้เร็วขึ้นในวงจรการพัฒนา เพราะยิ่ง detect ช้า ยิ่ง fix แพง
Secret Management ไม่มี credential ใน code
กฎข้อแรกของ security คือ ห้าม hardcode secret ใน code เด็ดขาด ไม่ว่าจะเป็น API key, database password, SSH key อะไรก็ตาม
# แบบนี้ ห้ามทำ!!!!
DB_PASSWORD = "super_secret_password_123"
AWS_SECRET_KEY = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
# แบบนี้ถูกต้อง อ่านจาก environment variable
DB_PASSWORD = os.environ.get("DB_PASSWORD")
AWS_SECRET_KEY = os.environ.get("AWS_SECRET_KEY")
HashiCorp Vault
Vault คือ secrets management tool ที่ให้ app ดึง secret มาใช้ตอน runtime แทนที่จะเก็บไว้ใน environment variable โดยตรง
# ดึง secret จาก Vault ใน Python
import hvac
client = hvac.Client(url='https://vault.example.com')
client.auth.approle.login(role_id=ROLE_ID, secret_id=SECRET_ID)
secret = client.secrets.kv.read_secret_version(
path='my-app/database'
)
db_password = secret['data']['data']['password']
AWS Secrets Manager
ถ้าอยู่บน AWS แล้ว AWS Secrets Manager เป็นทางเลือกที่ง่ายกว่าในการ rotate และ access secrets
import boto3
import json
client = boto3.client('secretsmanager', region_name='ap-southeast-1')
response = client.get_secret_value(SecretId='my-app/db-password')
secret = json.loads(response['SecretString'])
db_password = secret['password']
Security Scanning ใน CI/CD Pipeline
SAST (Static Application Security Testing)
Scan source code หา vulnerability โดยไม่ต้องรันโปรแกรม เหมือนอ่านโค้ดแล้ว flag สิ่งที่น่าสงสัย
# GitHub Actions ตัวอย่าง รัน Bandit สำหรับ Python
- name: Run SAST scan
run: |
pip install bandit
bandit -r ./src/ -f json -o bandit-report.json
- name: Upload scan results
uses: actions/upload-artifact@v4
with:
name: bandit-report
path: bandit-report.json
SCA (Software Composition Analysis)
Scan dependencies หา known vulnerabilities ใน library ที่เราใช้ เพราะ library ที่ใช้อยู่อาจมีช่องโหว่ที่ถูก discover ทีหลัง
# รัน Safety สำหรับ Python dependencies
pip install safety
safety check -r requirements.txt
# หรือใช้ GitHub Dependabot ซึ่ง built-in อยู่แล้ว
# แค่เปิด .github/dependabot.yml ก็พอ
Container Image Scanning
Scan Docker image หา vulnerability ก่อน push ขึ้น registry
# ใช้ Trivy scan image
trivy image my-app:1.0
# ใน GitHub Actions
- name: Scan Docker image
uses: aquasecurity/trivy-action@master
with:
image-ref: 'my-app:${{ github.sha }}'
exit-code: '1' # fail build ถ้าเจอ critical vulnerability
Principle of Least Privilege
ให้ permission เท่าที่จำเป็นจริงๆ เท่านั้น อย่าให้ admin access กับทุกอย่าง
เปรียบเหมือนยิมที่เราไป ไม่ใช่ทุกคนจะเข้าห้อง trainer ได้ คนที่เข้าได้มีแค่ trainer และ manager เท่านั้น member ทั่วไปเข้าได้แค่พื้นที่ออกกำลังกาย แบบนี้แหละที่ควรจะเป็น
# IAM Policy ที่ดี: ให้ read-only access แค่ S3 bucket เดียว
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:ListBucket"],
"Resource": [
"arn:aws:s3:::my-specific-bucket",
"arn:aws:s3:::my-specific-bucket/*"
]
}
]
}
# แบบนี้ไม่ดี: ให้ full access ทุกอย่าง
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
Network Security
Zero Trust Network
แนวคิด Zero Trust คือ "never trust, always verify" ไม่ว่าจะอยู่ใน network ไหน จะ internal หรือ external ก็ต้อง authenticate และ authorize ก่อนเสมอ ต่างจากแนวคิดเก่าที่ "ถ้าอยู่ใน network วงในแล้วเชื่อใจได้"
Security Groups และ Network Policies
ใน K8s ใช้ Network Policy ควบคุมว่า Pod ไหนคุยกับ Pod ไหนได้บ้าง แทนที่จะให้ทุก Pod คุยกันได้หมดโดย default
# k8s NetworkPolicy: อนุญาตเฉพาะ frontend คุยกับ backend
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-only
spec:
podSelector:
matchLabels:
app: backend
ingress:
- from:
- podSelector:
matchLabels:
app: frontend # แค่ frontend เท่านั้น
Security Checklist ก่อน Deploy Production
checklist นี้ไม่ครบ 100% แต่เป็นจุดเริ่มต้นที่ดี
| หมวด | รายการ |
|---|---|
| Secrets | ไม่มี secret hardcode ในโค้ดหรือ Dockerfile |
| Secrets | ใช้ secrets manager หรือ environment variables |
| Dependencies | scan dependencies หา known CVE ก่อน deploy |
| Container | ไม่ run container ด้วย root user |
| Container | ใช้ base image ที่ minimal และ updated |
| Network | เปิด port แค่ที่จำเป็น ปิดที่เหลือ |
| Access | ทุก IAM role ให้ least privilege เสมอ |
| Monitoring | มี alert สำหรับ suspicious activity |
| Audit | เปิด audit log ทุก API call ที่สำคัญ |
สรุป EP.10 และสรุปซีรี่ส์
- DevSecOps คือการ shift security check ให้เร็วขึ้นใน pipeline
- ห้าม hardcode secret ในโค้ดเด็ดขาด ใช้ secrets manager
- Scan code, dependencies, และ container image อัตโนมัติใน CI/CD
- Principle of least privilege ให้ permission เท่าที่จำเป็นเสมอ
- Network policy ควบคุม traffic ระหว่าง services
🎉 จบซีรี่ส์ DevOps พังแล้วพังอีกพังต่อ แล้ว!
ผ่านมาทั้ง 10 EP เราคุยกันมาเยอะมากนะ ตั้งแต่ DevOps คืออะไร ไปจนถึง Linux, Git, Networking, Cloud, Docker, CI/CD, Kubernetes, IaC, Monitoring และ Security
ถ้าถามว่าควรเรียนต่อยังไงหลังจากนี้ คำตอบคือ ลงมือทำ ค่ะ อ่านแค่ concept ไม่พอ ต้อง break ของด้วยตัวเองบ้าง ตั้ง server, deploy app, ดู log, แก้ error จริงๆ ถึงจะซึมซับเข้าไปจริงๆ
เหมือนการยกน้ำหนักเลย ไม่มีทางรู้ว่า 100kg หนักแค่ไหน จนกว่าจะจับบาร์แล้วรู้สึกด้วยตัวเอง 5555
ขอบคุณที่ติดตามมาจนถึง EP.10 นะคะ แล้วเจอกันในซีรี่ส์ต่อไปค่ะ 👋
ซีรี่ส์ DevOps พังแล้วพังอีกพังต่อ