Cách sử dụng phổ biến

  1. Bạn có một project Google Cloud Platform (GCP)
  2. Bạn có Terraform scripts
  3. Bạn có JSON Key của serviceaccount trong script Terraform của mình
  4. 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.

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments