Cách sử dụng phổ biến
- Bạn có một project Google Cloud Platform (GCP)
- Bạn có Terraform scripts
- Bạn có JSON Key của serviceaccount trong script Terraform của mình
- ServiceAccount của bạn có quyền truy cập đầy đủ (owner) vào GCP của bạn – để có thể tạo và phá hủy mọi thứ trên GCP.
Vấn đề phát sinh
Điểm số 4 ở trên là vấn đề chúng ta sẽ để mắt tới. Bạn có một JSON key bên ngoài trên thế giới có toàn quyền truy cập để làm bất cứ điều gì với GCP của bạn. Nếu file JSON key đó được lấy bởi ai đó (mặc dù có tất cả các loại mã hóa / bảo vệ / v.v.), bạn có nguy cơ bị thiệt hại rất nhiều. Đó là một rủi ro lớn trong quan điểm bảo mật và chúng ta có thể làm tốt hơn thế.
Bạn cần gì trước khi bắt đầu?
Để làm theo hướng dẫn này, bạn nên làm quen với Google Cloud Console và có một số hiểu biết cơ bản về các dịch vụ GCP như IAM và Cloud Storage. Bạn cần có quyền tạo cloud storage và IAM role.
Sử dụng terraform ở local
1. Cài đặt Google cloud cli
Cài đặt Google cloud cli trên máy tính của bạn theo hướng dẫn tại đây.
2. Cấu hình Google cloud project
Thiết lập Cấu hình GCP của bạn để sử dụng dự án mà bạn sẽ làm việc cùng.
gcloud config set project PROJECT_ID
Bước tiếp theo là đặt thông tin đăng nhập người dùng của riêng bạn cho Terraform để truy cập các API:
gcloud auth application-default login
Giả sử user của bạn có email là user_name@hocdevops.com. Chúng ta sẽ sử dụng email này cho các bước tiếp theo.
3. Tạo service account
Bạn có thể sử dụng quy ước đặt tên sau: sa-{short_project_name}-tf-{Environment}.
Mẹo: Tên ngắn có thể là tên liên quan đến tên dự án bạn đang sử dụng.
Ví dụ:
Tên tài khoản dịch vụ của tôi là sa-demo-tf-sbx
- Demo: dự án của tôi được gọi là demo-playground
- Sbx: môi trường tôi đang sử dụng được gọi là sandbox
gcloud iam service-accounts create sa-demo-tf-sbx \ --description="Terraform Service account Demo Sandbox Environment" \ --display-name="Terraform Service Account"
4. Cung cấp cho service account mới role và permission cần thiết
Bây giờ chúng ta sẽ cung cấp cho service account mới role và permission cần thiết. Chúng ta sẽ cấp quyền editor, danh sách đầy đủ các role có thể có mà bạn có thể tìm thấy nhấn vào đây. Hãy thay PROJECT_ID bằng project id của bạn.
gcloud projects add-iam-policy-binding PROJECT_ID \ --member="serviceAccount:sa-demo-tf- sbx@PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/editor"
Chúng ta sẽ sử dụng account này để thực hiện tất cả các thay đổi của chúng ta. Để làm điều này, chúng ta cần cấp cho mình những quyền cần thiết. Bạn có thể làm điều đó như thế này:
3.1. Lấy các policy của service account và lưu nó trong policy.json
gcloud iam service-accounts get-iam-policy sa-demo-tf-sbx@PROJECT_ID.iam.gserviceaccount.com --format=json > policy.json
3.2. Sửa đổi policy.json để thêm chính bạn làm thành viên với role là iam.serviceAccountTokenCreator. Hãy nhớ giữ các policy đã tồn tại:
{ "bindings": [ { "members": [ "user:user_name@hocdevops.com" ], "role": "roles/iam.serviceAccountTokenCreator" } ], ... }
3.3. Cập nhật các policy mới bằng file policy.json
gcloud iam service-accounts set-iam-policy sa-demo-tf-sbx@PROJECT_ID.gserviceaccount.com policy.json
5. Tạo một bucket sẽ giữ Terraform Stat của bạn
Bây giờ chọn tên của bucket. Bạn có thể sử dụng quy ước đặt tên này:
{short_project_name}-{Environment}-tf-state
Ví dụ: trong trường hợp này nó sẽ là demo-sbx-tf-state
Nơi lưu trữ này sẽ giúp bạn giữ trạng thái Terraform ở một vị trí được chia sẻ trên tất cả các nhà phát triển. Đó là một nơi lư trữ tốt để giữ trạng thái của Terraform với các thay đổi.
gsutil mb -l gs://demo-sbx-tf-state gsutil versioning set on gs://demo-sbx-tf-state
6. Viết Terraform Main
Bây giờ, chúng ta hãy viết Terraform Main. Để làm điều này, chúng ta sẽ cần:
- Terraform Main
- Backend
- Version
Thông thường khi bạn viết code thì bạn sẽ tạo file và folder theo một template nào đó. Bạn có thể sử dụng kiểu thiết kế dưới đây:
Bây giờ hãy tập trung vào main.tf, backend.tf và version.tf.
tf-code │ main.tf │ backend.tf │ variables.tf │ version.tf │ └───module1 │ │ main.tf │ │ outputs.tf │ │ variables.tf │ └───module2 │ │ main.tf │ │ outputs.tf │ │ variables.tf │ ...
6.1. Main.tf
Đây là code chính của Terraform của chúng ta. Chúng ta sẽ sử dụng Google cloud provider. Sử dụng đoạn code sau làm điểm bắt đầu:
provider "google" { alias = "impersonation" scopes = [ "https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/userinfo.email", ] } data "google_service_account_access_token" "default" { provider = google.impersonation # vì chúng ta đang config ở local nên target_service_account sẽ là local # hoặc bạn có thể đổi sang email của bạn: user_name@hocdevops.com target_service_account = local.terraform_service_account scopes = ["userinfo-email", "cloud-platform"] lifetime = "1200s" } provider "google" { project = var.project_id region = var.gcp_location access_token = data.google_service_account_access_token.default.access_token } provider "google-beta" { project = var.project_id region = var.gcp_location access_token = data.google_service_account_access_token.default.access_token }
6.3. Config backend
File này chứa config liên quan đến backend:
terraform { backend "gcs" { bucket = "demo-sbx-tf-state" prefix = "static.tfstate.d" } }
6.4. Version.tf
Điều này sẽ cho phép bạn theo dõi chính xác phiên bản Terraform nào bạn đang sử dụng và từng nhà cung cấp được yêu cầu.
terraform { required_version = ">= 0.12.26" }
7. Khởi tạo code Terraform
Bước tiếp theo là khởi tạo Terraform backend bằng lệnh sau:
terraform init -backend-config=backend.tf
8. Terraform plan và apply
Bây giờ bạn có thể plan và apply thay đổi để tiến hành thực hiện việc tạo các resource trên cloud.
terraform plan terraform apply
Tích hợp CI/CD với terraform và impersonated service account
Để sử dụng impersonated service account vào CI/CD process, chúng ta sẽ cần phải tạo ra một service account mới và tạo service account key để sử dụng trong pipeline của chúng ta. Điều đặc biệt là service account này cũng sẽ đc impersonated.
1. Tạo service account cho việc CI/CD
Chúng ta sẽ tạo ra một service account mới tên là tf-executor với role:
roles/storage.admin
– để có thể truy vấn GCS nếu đó là những gì bạn đang sử dụng để lưu trữ TFStates của chúng ta. Điều này là bắt buộc ngay cả trước khi được “impersonate” .Bạn có thể thắt chặt hơn nữa role này bằng cách thêm một điều kiện vào role này để nó chỉ có thể truy cập vào bucket GCS cụ thể đang xử lý TFStates (trong bài viết này thì là demo-sbx-tf-state).roles/iam.serviceAccountTokenCreator
— để có thể thực hiện các data block — yêu cầu token access thay mặt cho một ServiceAccount khác.- Đó là tất cả – không cần nhiều permission hơn nữa.
2. Cung cấp cho service account mới role và permission cần thiết
Để service account mới có thể hoạt động, chúng ta sẽ thêm service account mới tạo vào policy của service account gốc.
3.1. Lấy các policy của service account gốc và lưu nó trong policy.json
gcloud iam service-accounts get-iam-policy sa-demo-tf-sbx@PROJECT_ID.iam.gserviceaccount.com --format=json > policy.json
3.2. Sửa đổi policy.json để thêm chính bạn làm thành viên với role là iam.serviceAccountTokenCreator. Hãy nhớ giữ các policy đã tồn tại:
{ "bindings": [ { "members": [ "serviceAccount:tf-executor@PROJECT_ID.iam.gserviceaccount" ], "role": "roles/iam.serviceAccountTokenCreator" } ], ... }
3.3. Cập nhật các policy mới bằng file policy.json
gcloud iam service-accounts set-iam-policy sa-demo-tf-sbx@PROJECT_ID.gserviceaccount.com policy.json
3. Config CI/CD
Việc cuối cùng chúng ta cần làm là config CI/CD sử dụng file service account key đã tạo riêng cho việc này. Chúng ta có thể lưu trữ key này trong gitlab env, github secret hoặc bất cứ đâu an toàn.
Dưới đây là ví dụ pipeline với gitlab. 2 biến được config bao gồm:
- SERVICEACCOUNT : chứ thông tin service account key.
- TF_OWNER_SA_EMAIL: chứa thông tin email của service account đang sử dụng (tf-executor@PROJECT_ID.iam.gserviceaccount)
image: name: hashicorp/terraform:1.1.7 entrypoint: - '/usr/bin/env' - 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' before_script - rm -rf .terraform - terraform --version - mkdir -p ./creds - echo $SERVICEACCOUNT | base64 -d > ./creds/serviceaccount.json - gcloud auth activate-service-account --key-file=./creds/serviceaccount.json - gcloud config set auth/impersonate_service_account ${TF_OWNER_SA_EMAIL} - terraform init stages: - validate - plan - apply validate: stage: validate script: - terraform validate plan: stage: plan script: - terraform plan -out "planfile" dependencies: - validate artifacts: paths: - planfile apply: stage: apply script: - terraform apply -input=false "planfile" dependencies: - plan when: manual
Tổng kết
Việc sử dụng Service Account impersonation sẽ giúp giảm thiểu được rủi do khi làm việc với terraform, đồng thời cũng giúp cho việc quản lý cũng dễ dàng hơn. Nếu bạn có góp ý hay bất kì câu hỏi gì, xin để lại bình luận.