DevSecOps (Phần 7): Đừng Hard-code Password! Vì sao cấu hình phải tách khỏi Source Code?
Bạn mở một dự án trên GitHub và nhìn thấy đoạn mã như thế này:
DB_HOST = "10.10.10.5"
DB_USER = "admin"
DB_PASSWORD = "Cisco@123"
Ứng dụng vẫn chạy bình thường.
Developer cũng không thấy có gì bất thường.
Nhưng với DevSecOps, đây là một trong những lỗi thiết kế nghiêm trọng nhất.
Đó là lý do Yếu tố thứ 3 trong phương pháp 12-Factor App yêu cầu:
Configuration là gì?
Configuration là tất cả những giá trị có thể thay đổi giữa các môi trường triển khai.
Ví dụ:
Điểm quan trọng là:
Code phải giữ nguyên.
Chỉ Configuration mới thay đổi giữa:
Đó là nguyên tắc cốt lõi của 12-Factor App.
Vì sao không nên lưu cấu hình trong Source Code?
Nhiều dự án vẫn khai báo:
DATABASE = "prod-db.company.com"
PASSWORD = "Password123"
Hoặc đưa toàn bộ thông tin này vào:
rồi commit cùng source code.
Đây không phải là giải pháp an toàn.
Bởi vì những file này vẫn nằm trong repository. Bất kỳ ai có quyền truy cập mã nguồn đều có thể đọc được toàn bộ credentials.
Theo 12-Factor App, một phép thử rất đơn giản là:
Environment Variables – Cách làm được khuyến nghị
12-Factor App khuyến nghị lưu cấu hình trong Environment Variables (Biến môi trường).
Ví dụ:
DB_HOST=10.10.10.5
DB_USER=admin
DB_PASSWORD=********
REDIS_HOST=redis.internal
SMTP_SERVER=mail.company.com
Ứng dụng chỉ việc đọc:
os.getenv("DB_HOST")
thay vì hard-code.
Ưu điểm:
Đây cũng là lý do Environment Variables trở thành tiêu chuẩn chung trong các hệ thống Cloud Native.
Vì sao không nên dùng web.config hoặc Java Properties?
Nhiều nền tảng có cơ chế cấu hình riêng:
Mặc dù tiện lợi, nhưng nếu các tệp này được đóng gói cùng ứng dụng thì chúng vẫn trở thành một phần của codebase.
Điều đó khiến việc triển khai cùng một ứng dụng lên nhiều môi trường trở nên khó khăn hơn và tăng nguy cơ lộ thông tin nhạy cảm.
Cloud còn có những lựa chọn tốt hơn
Ngày nay, rất nhiều doanh nghiệp không chỉ dùng Environment Variables.
Họ sử dụng các dịch vụ chuyên quản lý cấu hình và bí mật như:
CI/CD Pipeline sẽ lấy cấu hình hoặc secrets từ các dịch vụ này trong quá trình triển khai mà không cần lưu trực tiếp trong source code.
Nhờ vậy:
Bạn mở một dự án trên GitHub và nhìn thấy đoạn mã như thế này:
DB_HOST = "10.10.10.5"
DB_USER = "admin"
DB_PASSWORD = "Cisco@123"
Ứng dụng vẫn chạy bình thường.
Developer cũng không thấy có gì bất thường.
Nhưng với DevSecOps, đây là một trong những lỗi thiết kế nghiêm trọng nhất.
Đó là lý do Yếu tố thứ 3 trong phương pháp 12-Factor App yêu cầu:
Store Configuration in the Environment – Tách toàn bộ cấu hình ra khỏi mã nguồn.
Configuration là gì?
Configuration là tất cả những giá trị có thể thay đổi giữa các môi trường triển khai.
Ví dụ:
- Địa chỉ Database
- API Endpoint
- Username
- Password
- API Key
- Secret Key
- Token
- SMTP Server
- Redis Server
- RabbitMQ Address
- Kafka Broker
- Logging Level
Điểm quan trọng là:
Code phải giữ nguyên.
Chỉ Configuration mới thay đổi giữa:
- Development
- Testing
- Staging
- Production
Đó là nguyên tắc cốt lõi của 12-Factor App.
Vì sao không nên lưu cấu hình trong Source Code?
Nhiều dự án vẫn khai báo:
DATABASE = "prod-db.company.com"
PASSWORD = "Password123"
Hoặc đưa toàn bộ thông tin này vào:
- config.json
- settings.xml
- appsettings.json
- web.config
rồi commit cùng source code.
Đây không phải là giải pháp an toàn.
Bởi vì những file này vẫn nằm trong repository. Bất kỳ ai có quyền truy cập mã nguồn đều có thể đọc được toàn bộ credentials.
Theo 12-Factor App, một phép thử rất đơn giản là:
Nếu ngày mai bạn chuyển toàn bộ repository sang Open Source mà không cần xóa bất kỳ thông tin nhạy cảm nào, nghĩa là bạn đã tách Configuration khỏi Code đúng cách.
Environment Variables – Cách làm được khuyến nghị
12-Factor App khuyến nghị lưu cấu hình trong Environment Variables (Biến môi trường).
Ví dụ:
DB_HOST=10.10.10.5
DB_USER=admin
DB_PASSWORD=********
REDIS_HOST=redis.internal
SMTP_SERVER=mail.company.com
Ứng dụng chỉ việc đọc:
os.getenv("DB_HOST")
thay vì hard-code.
Ưu điểm:
- Không xuất hiện trong Git Repository.
- Có thể thay đổi mà không sửa mã nguồn.
- Hoạt động trên mọi ngôn ngữ lập trình.
- Rất phù hợp với Docker và Kubernetes.
- Dễ tích hợp với CI/CD Pipeline.
Đây cũng là lý do Environment Variables trở thành tiêu chuẩn chung trong các hệ thống Cloud Native.
Vì sao không nên dùng web.config hoặc Java Properties?
Nhiều nền tảng có cơ chế cấu hình riêng:
- Java → Properties File
- .NET → web.config
- XML
- JSON
Mặc dù tiện lợi, nhưng nếu các tệp này được đóng gói cùng ứng dụng thì chúng vẫn trở thành một phần của codebase.
Điều đó khiến việc triển khai cùng một ứng dụng lên nhiều môi trường trở nên khó khăn hơn và tăng nguy cơ lộ thông tin nhạy cảm.
Cloud còn có những lựa chọn tốt hơn
Ngày nay, rất nhiều doanh nghiệp không chỉ dùng Environment Variables.
Họ sử dụng các dịch vụ chuyên quản lý cấu hình và bí mật như:
- AWS Systems Manager Parameter Store
- AWS Secrets Manager
- Azure Key Vault
- Google Secret Manager
- HashiCorp Vault
CI/CD Pipeline sẽ lấy cấu hình hoặc secrets từ các dịch vụ này trong quá trình triển khai mà không cần lưu trực tiếp trong source code.
Nhờ vậy:
- Secrets được mã hóa.
- Có thể phân quyền truy cập.
- Dễ xoay vòng (Rotate) mật khẩu và khóa truy cập.
- Đáp ứng tốt các yêu cầu kiểm toán và tuân thủ.