CodeBuild Nâng Cao: Biến Môi Trường, Secret và Cache
Build của bài trước chỉ in ra vài dòng. Build thật cần nhiều hơn: một URL API tùy môi trường, một khóa để gọi dịch vụ, mật khẩu để chạy migration database. Câu hỏi là truyền những giá trị đó vào build thế nào cho an toàn — không hardcode vào source, không in ra log. Bài này làm đúng việc đó, phân biệt rõ biến thường và secret, rồi bật cache để build nhanh hơn.
Mục tiêu
Truyền biến môi trường và secret vào CodeBuild đúng cách (biến thường vs SSM vs Secrets Manager), thấy CodeBuild che secret trong log ra sao, và bật cache.
Ba nguồn biến môi trường
Khối env trong buildspec.yml nhận giá trị từ ba nguồn, mỗi nguồn cho một mục đích:
env:
variables:
APP_ENV: "production"
parameter-store:
GREETING: /cicddemo/greeting
API_KEY: /cicddemo/api-key
secrets-manager:
DB_PASSWORD: awscicd/demo/db:password
variables là giá trị thường, ghi thẳng vào buildspec — dùng cho config không nhạy cảm (môi trường, cờ tính năng). parameter-store lấy giá trị từ SSM Parameter Store theo tên tham số. secrets-manager lấy từ Secrets Manager, cú pháp tên-secret:khóa-json. Khác biệt cốt lõi: hai nguồn sau giữ giá trị ngoài source code; buildspec chỉ ghi tên tham chiếu, giá trị thật được CodeBuild đọc lúc build.
Tạo tham số và secret
SSM Parameter Store — một tham số thường và một dạng SecureString (mã hóa):
$ aws ssm put-parameter --name /cicddemo/greeting --value "hello-from-ssm" --type String
$ aws ssm put-parameter --name /cicddemo/api-key --value "s3cr3t-ssm-value" --type SecureString
(Lưu ý: tên tham số SSM không được bắt đầu bằng aws — đó là tiền tố dành riêng, sẽ bị từ chối; dùng tên khác như /cicddemo/.)
Secrets Manager — một secret dạng JSON:
$ aws secretsmanager create-secret --name awscicd/demo/db \
--secret-string '{"password":"p@ss-from-secretsmanager"}'
Service role CodeBuild (bài 2) chưa có quyền đọc hai thứ này, nên cấp thêm — giới hạn đúng vào đường dẫn của ta, không mở rộng:
{
"Version": "2012-10-17",
"Statement": [
{ "Effect": "Allow", "Action": ["ssm:GetParameters","ssm:GetParameter"],
"Resource": "arn:aws:ssm:*:*:parameter/cicddemo/*" },
{ "Effect": "Allow", "Action": ["secretsmanager:GetSecretValue"],
"Resource": "arn:aws:secretsmanager:*:*:secret:awscicd/*" }
]
}
$ aws iam put-role-policy --role-name awscicd-codebuild-role \
--policy-name awscicd-codebuild-secrets --policy-document file://cb-secrets.json
CodeBuild tự che secret trong log
Đây là điểm quan trọng nhất của bài. Sửa buildspec để in các biến ra (cố tình, để xem), rồi chạy build và đọc log:
$ aws logs get-log-events --log-group-name /aws/codebuild/awscicd-demo-build ...
Install phase — APP_ENV=production
GREETING from SSM = ***
API_KEY present? yes
DB_PASSWORD present? yes
Đọc kỹ từng dòng. APP_ENV=production hiện nguyên — nó là variables, không nhạy cảm. Nhưng GREETING (lấy từ Parameter Store) bị thay bằng ***, dù giá trị của nó chỉ là "hello-from-ssm" vô hại. CodeBuild tự động che mọi giá trị đến từ parameter-store và secrets-manager trong log, bất kể nó có thật sự bí mật hay không. Còn API_KEY và DB_PASSWORD ta chỉ in "present? yes" để không lộ, và chúng đã được bơm vào môi trường đúng như mong đợi.
Hệ quả thực hành rút ra: đặt secret vào parameter-store/secrets-manager thì được CodeBuild che giúp; đặt secret vào variables thì nó hiện nguyên trong log và nằm trong source code — đừng bao giờ làm vậy.
buildspec env:
variables: APP_ENV=production ──────────▶ hiện trong log
parameter-store: GREETING = /cicddemo/... ──┐
secrets-manager: DB_PASSWORD = awscicd/... ──┤ CodeBuild đọc lúc build
▼
bơm vào biến môi trường, giá trị BỊ CHE (***) trong log
Bật cache để build nhanh hơn
Mỗi build dựng container mới, sạch — tốt cho tính tái lập nhưng chậm nếu phải tải lại dependency mỗi lần. Cache giữ lại một số thứ giữa các build. Bật cache LOCAL cho project:
$ aws codebuild update-project --name awscicd-demo-build \
--cache '{"type":"LOCAL","modes":["LOCAL_SOURCE_CACHE","LOCAL_CUSTOM_CACHE"]}' \
--query 'project.cache.type' --output text
LOCAL
Có ba chế độ cache LOCAL: LOCAL_SOURCE_CACHE giữ lại git metadata (clone nhanh hơn ở lần sau), LOCAL_DOCKER_LAYER_CACHE giữ layer Docker (cho build image), LOCAL_CUSTOM_CACHE giữ các thư mục bạn khai trong cache.paths của buildspec (ví dụ node_modules, ~/.m2). Cache LOCAL gắn với máy chạy build nên chỉ giúp khi cùng máy được tái dùng; với cache bền hơn qua mọi build, dùng type: S3 trỏ vào một bucket. Với app có nhiều dependency, cache cắt được phần lớn thời gian install.
🧹 Dọn dẹp
SSM param và secret giữ tới cuối series (build ở các bài sau vẫn tham chiếu chúng). Khi dọn:
$ aws ssm delete-parameter --name /cicddemo/greeting
$ aws ssm delete-parameter --name /cicddemo/api-key
$ aws secretsmanager delete-secret --secret-id awscicd/demo/db --force-delete-without-recovery
SSM Parameter Store (standard) miễn phí; Secrets Manager tính khoảng 0,40 USD/secret/tháng theo tỉ lệ, nên giữ vài ngày chỉ vài cent. --force-delete-without-recovery xóa ngay thay vì chờ cửa sổ khôi phục.
Tổng kết
CodeBuild nhận biến môi trường từ ba nguồn: variables cho config thường (hiện trong log), parameter-store (SSM) và secrets-manager cho giá trị nhạy cảm — hai nguồn sau giữ giá trị ngoài source và được CodeBuild tự che (***) trong log. Cấp quyền đọc cho role theo least-privilege, giới hạn đúng đường dẫn tham số. Cache (LOCAL với các mode source/docker-layer/custom, hoặc S3) giữ lại dependency giữa các build để chạy nhanh hơn. Quy tắc vàng: secret không bao giờ nằm trong variables hay source.
Bài tới khép Part II: cho CodeBuild chạy test và xuất test report — gom kết quả test (JUnit, v.v.) thành báo cáo xem được trong CodeBuild, để biết build không chỉ chạy mà còn đúng.