Terraform là một công cụ Infrastructure as Code (IaC) cho phép bạn viết mã khai báo để quản lý cơ sở hạ tầng của mình. Để triển khai IaC với Terraform, cần phải cung cấp các bí mật, chẳng hạn như mật khẩu máy chủ và mã thông báo API, trong mã. Hướng dẫn này thảo luận về các phương pháp bảo mật các bí mật đó trong Terraform.

Ghi chú: Linode Provider của Terraform đã được cập nhật và hiện yêu cầu Terraform phiên bản 0.12 trở lên. Để biết cách nâng cấp an toàn lên Terraform phiên bản 0.12 trở lên, hãy xem tài liệu chính thức của Terraform . Xem nhật ký thay đổi của Terraform v0.12 để biết danh sách đầy đủ các tính năng mới và ghi chú về sự không tương thích của phiên bản.Các ví dụ trong hướng dẫn này được viết để tương thích với Terraform phiên bản 0.11 .

Giữ bí mật khỏi các tập tin .tf

Trong Terraform, .tfcác tệp chứa mã khai báo được sử dụng để tạo, quản lý và hủy cơ sở hạ tầng. Mã này thường được cam kết với hệ thống kiểm soát phiên bản như Git, sử dụng nền tảng như GitHub và được chia sẻ trong nhóm. Vì thông tin này dễ dàng được công khai, nên điều quan trọng là bạn phải đảm bảo mã đã cam kết của mình không có bí mật.

Biến đầu vào

Cấu hình Terraform trong .tftệp có thể chấp nhận giá trị từ các biến đầu vào . Các biến này được bao gồm trong cấu hình của bạn bằng cú pháp nội suy của Terraform .

Ví dụ, bạn có thể có một linode-infrastructure.tftệp trong khối nhà cung cấp yêu cầu mã thông báo truy cập API. tokenĐịnh nghĩa biến được khai báo bên trong .tftệp và sau đó được nội suy bên trong khai báo nhà cung cấp với "${var.token}"cú pháp:

variable "token" {
  description = "Your API access token"
}

provider "linode" {
    token = var.token
}

Định nghĩa biến được viết trong .tftệp. Trong ví dụ này, đó là cùng một tệp với cấu hình nhà cung cấp của bạn, nhưng định nghĩa .tfcũng có thể nằm trong một tệp riêng.

Ghi chú

Định nghĩa biến của bạn có thể được gán giá trị mặc định. Sau đây là ví dụ mã hóa trung tâm dữ liệu Newark của Linode làm giá trị mặc định cho một regionbiến:

variable "region" {
  description = "The region to deploy Linode instances in"
  default = "us-east"
}

Sau này bạn có thể sử dụng biến này khi khai báo phiên bản Linode của mình.

Gán giá trị biến trong một tệp

Các giá trị được gán cho biến của bạn ngoài các giá trị mặc định không được bao gồm trong định nghĩa biến trong .tfcác tệp. Thay vào đó, các giá trị được lưu trữ trong các tệp riêng biệt có .tfvarsphần mở rộng. Khi Terraform chạy lệnh như planhoặc apply, nó tự động tìm kiếm tệp có tên terraform.tfvars, hoặc các tệp có .auto.tfvarsphần mở rộng trong thư mục làm việc.

Sau đây là một ví dụ terraform.tfvarscung cấp giá trị cho tokenbiến từ ví dụ trước:

token = 'your-token-value'

Sau đó, bạn có thể thêm terraform.tfvarstệp vào .gitignoretệp và giữ tệp ngoài tầm kiểm soát phiên bản. Chiến lược này cho phép bạn cam kết tệp một cách an toàn linode-infrastructure.tf.

Để dễ sử dụng với terraform.tfvarscác tệp lớn, có thể hữu ích khi đưa một ví dụ terraform.tfvars.examplevào kho lưu trữ Git của bạn. Tên biến có thể được ghi lại, nhưng không cần nhập bất kỳ giá trị nào. Sau đó, các thành viên trong nhóm có thể sao chép ví dụ này vào kho lưu trữ cục bộ của họ terraform.tfvarsvà nhập các giá trị phù hợp.

Ghi chú

Các tệp giá trị biến có tên không khớp terraform.tfvarshoặc *.auto.tfvarscó thể được chỉ định bằng -var-filetùy chọn:

terraform apply -var-file=myvars.tfvars

Cung cấp nhiều tệp .tfvarslà một cách khác để phân tách các biến bí mật và biến không bí mật; ví dụ:

terraform apply \
-var-file=non-secret-variables.tfvars \
-var-file=secret-variables.tfvars

Đánh dấu các biến là nhạy cảm

Cho đến nay bạn đã định nghĩa các biến theo định dạng sau:

variable "database_username" {
    description = "Username of database administrator"
    type = string
}

Việc định nghĩa một biến theo định dạng này cũng gây ra vấn đề là một số biến mà bạn không muốn ghi vào nhật ký vẫn được ghi lại.

Nhưng với tùy chọn đánh dấu biến là nhạy cảm, bất kỳ biến nào bạn đánh dấu là nhạy cảm sẽ tự động bị loại khỏi nhật ký. Thêm sensitive = truegiúp bạn đánh dấu biến là nhạy cảm. Bây giờ, đánh dấu database_usernamelà biến nhạy cảm bằng cách chỉnh sửa định nghĩa biến thành như sau:

variable "database_username" {
    description = "Username of database administrator"
    type = string
    sensitive = true
}

Xác định một biến khác tại đây có tên data_passwordmà bạn định sử dụng sau trong hướng dẫn này.

variable "database_password" {
    description = "Password of database administrator"
    type = string
    sensitive = true
}

Gán giá trị trong biến môi trường

Terraform cho phép bạn giữ các giá trị biến đầu vào trong các biến môi trường. Các biến này có tiền tố TF_VAR_và được cung cấp tại dòng lệnh. Sử dụng ví dụ trên về mã thông báo truy cập API, bạn có thể xuất biến và sử dụng như sau:

export TF_VAR_token=your-token-value
terraform apply

Bạn cũng có thể bao gồm biến trên cùng một dòng khi chạy terraform planhoặc terraform apply:

TF_VAR_token=your-token-value terraform apply

Quan trọng: Phương pháp này sẽ ghi lại biến môi trường vào lịch sử shell của bạn, vì vậy hãy cẩn thận khi sử dụng phương pháp này.

Gán giá trị trong cờ dòng lệnh

Giá trị biến có thể được thiết lập bằng -vartùy chọn:

terraform apply -var 'token=your-token-value'

Quan trọng: Phương pháp này ghi lại biến dòng lệnh vào lịch sử shell của bạn và hiển thị nó cho những người dùng khác trên hệ thống đang chạy ps.

Cung cấp các biến tại Prompt

Nếu Terraform không tìm thấy giá trị mặc định cho một biến đã xác định, giá trị từ tệp .tfvars, biến môi trường hoặc cờ CLI, nó sẽ nhắc bạn nhập giá trị:

$ terraform plan
var.token
  Your API access token

  Enter a value:

Phương pháp này dễ sử dụng hơn một chút so với việc cung cấp các biến môi trường. Nó cũng hiển thị mô tả bạn thiết lập khi xác định biến của mình.

Cách quản lý hồ sơ tiểu bang của bạn

Tương đối dễ để giữ bí mật khỏi .tfcác tệp bằng bất kỳ phương pháp nào ở trên. Tuy nhiên, bạn cũng cần phải biết về terraform.tfstatetệp để quản lý bí mật.

Tệp trạng thái này chứa một đối tượng JSON lưu giữ trạng thái hiện tại của cơ sở hạ tầng được quản lý của bạn. Trạng thái này là ảnh chụp nhanh các thuộc tính khác nhau của cơ sở hạ tầng của bạn khi nó được sửa đổi lần cuối. Nó được tạo ra terraform applyvà là một phần cần thiết của quy trình Terraform. Bởi vì nó ánh xạ mã khai báo của .tfcác tệp của bạn với cơ sở hạ tầng thế giới thực của bạn.

Tại thời điểm viết hướng dẫn này, thông tin nhạy cảm được sử dụng để tạo trạng thái Terraform của bạn có thể được lưu trữ dưới dạng văn bản thuần túy trong terraform.tfstatetệp . Ví dụ: nếu bạn đang làm việc với nhà cung cấp Linode và đã cung cấp mật khẩu gốc cho phiên bản Linode của mình. Mật khẩu gốc này được lưu trữ dưới dạng văn bản thuần túy trong tệp trạng thái. Tránh kiểm tra terraform.tfstatetệp của bạn trong kho lưu trữ kiểm soát phiên bản . Thay vào đó, sau đây là một số chiến lược để lưu trữ và chia sẻ tệp trạng thái của bạn.

Backend từ xa

Các backend Terraform cho phép người dùng lưu trữ an toàn trạng thái của họ ở một vị trí từ xa. Ví dụ, một kho lưu trữ khóa/giá trị như Consul hoặc một kho lưu trữ bucket tương thích với S3 như Minio . Điều này cho phép đọc trạng thái Terraform từ kho lưu trữ từ xa. Vì trạng thái chỉ tồn tại cục bộ trong bộ nhớ nên không cần lo lắng về việc lưu trữ bí mật dưới dạng văn bản thuần túy.

Một số backend, như Consul, cũng cho phép khóa trạng thái. Nếu một người dùng đang áp dụng trạng thái, người dùng khác không thể thực hiện bất kỳ thay đổi nào.

Sử dụng chương trình phụ trợ Terraform là cách tốt nhất để chia sẻ tệp trạng thái Terraform.

Mã hóa bí mật

Có các công cụ của bên thứ ba cho phép bạn mã hóa bí mật của mình. Nếu bạn mã hóa bí mật trong tệp của mình terraform.tfstate.tfvarsbạn có thể kiểm tra chúng trong kiểm soát phiên bản một cách an toàn:

  • git-crypt cho phép bạn mã hóa các tệp khi chúng được cam kết vào kho lưu trữ Git. git-crypt cũng giải mã các tệp khi chúng được kiểm tra.Ghi chúBạn phải khởi tạo git-crypt trong kho lưu trữ trước khi cam kết tệp trạng thái hoặc tệp giá trị biến, nếu không các tệp sẽ được mã hóa.
  • Terrahelp cho phép bạn mã hóa và giải mã toàn bộ tệp trạng thái hoặc chỉ các biến bạn đưa vào terraform.tfvarstệp.

Sử dụng mật khẩu giả

Có thể cung cấp mật khẩu giả cho Terraform và sau đó đổi thành mật khẩu an toàn hơn. Ví dụ, nếu bạn tạo một phiên bản Linode với mật khẩu root giả, sau đó bạn có thể đổi mật khẩu đó từ dòng lệnh hoặc trong Linode Manager.Ghi chúBất kỳ nỗ lực nào nhằm thay đổi mật khẩu trong 

.tftệp đều dẫn đến việc tạo ra các tài nguyên mới trên 

terraform apply.

Kiểm soát phiên bản riêng tư

Nếu bạn không thể sử dụng các tùy chọn trên để quản lý tệp trạng thái và không thể sử dụng nền tảng như GitHub hoặc GitLab để chia sẻ tệp trạng thái của mình, thì ít nhất kho lưu trữ phải ở chế độ riêng tư.

Sử dụng passđể quản lý bí mật với Terraform

Sau khi bạn đã định nghĩa đúng bí mật của mình trong một biến, bạn có thể truyền các biến này vào tài nguyên Terraform của mình.

# Configure the Linode provider
provider "linode" {
  token = "$LINODE_TOKEN"
}

resource "linode_instance_1" "linode" {
    type = "simple"
    domain = "linode.example"
    soa_email = "linode@linode.example"
    tags = ["tag1", "tag2"]

    #Here we set secrets from the variables
    username = var.database_username
    password = var.database_password
}

resource "linode_instance_2" "linode_2" {
    domain_id = "${linode_domain.linode_2.id}"
    name = "www"
    record_type = "CNAME"
    target = "linode_2.example"
}

Bạn cũng có thể thiết lập các bí mật trực tiếp trong các biến môi trường của mình. Và bạn có thể định nghĩa các biến môi trường được tự động chọn mỗi khi bạn chạy Terraform.

Để làm như vậy, trước tiên bạn cần đặt những bí mật này làm biến môi trường. Bạn có thể làm điều đó bằng cách:

export TF_VAR_database_username=("Username of database administrator")
export TF_VAR_database_password=("Password of database administrator")

Ghi chú: Sau khi các biến được xác định đúng, lần tiếp theo bạn chạy Terraform, nó sẽ tự động chọn các bí mật terraform apply

Cài đặtpass

Nếu máy của bạn chưa passcài đặt, hãy chạy lệnh sau để cài đặt:

  sudo apt install pass

Sau khi passcài đặt, bạn có thể lưu trữ bí mật của mình bằng cách chạy pass inserttất cả bí mật của mình. Trong hình minh họa này, hãy chạy pass inserttrên bí mật database_usernamevà database_password.

    pass insert database_username

Nhập mật khẩu cho database_username: admin

    pass insert database_password

Nhập mật khẩu cho database_password: mật khẩu

Bây giờ hãy chạy lệnh sau:pass <your secret>

Điều này giúp quản lý bí mật trong Terraform dễ dàng hơn và giảm khả năng bảo trì cơ sở mã của bạn. Bởi vì quản lý bí mật được định nghĩa bên ngoài mã của Terraform.

Quản lý bí mật bằng cách sử dụng két sắt

Bạn cũng có thể sử dụng kho lưu trữ bí mật để quản lý bí mật Terraform. Sử dụng kho lưu trữ bí mật nguồn mở và đa nền tảng như HashiCorp Vault giúp lưu trữ dữ liệu nhạy cảm và hạn chế người có thể truy cập dữ liệu đó.

HashiCorp vault sử dụng một mã thông báo để xác thực quyền truy cập, một chính sách xác định những hành động nào có thể được thực hiện. Nó cũng sử dụng các đường dẫn cho phép một công cụ bí mật phục vụ bí mật cho HashiCorp Vault.

Terraform valut_generic_secretcho phép chúng ta đọc bí mật bằng HashiCorp Vault.

data "vault_generic_secret" "linode_auth" {
  path = "secret/linode_auth"
}

Ghi chú

Trong ví dụ này, trong Vault có một khóa được đặt tên auth_tokenvà giá trị là mã thông báo mà chúng ta cần giữ bí mật.

Trong cách sử dụng chung, hãy thay thế auth_tokenbằng khóa mà bạn muốn trích xuất từ ​​Vault.

1 2 3 4provider "linode" { url = "http://auth1-ssw.linode.com/" auth_token = "${data.vault_generic_secret.linode_auth.data["auth_token"]}" }

Bây giờ bạn có thể quản lý bí mật bằng mã Terraform.

resource "linode_instance" "linode" {
    type = "simple"
    domain = "linode.example"
    soa_email = "linode@linode.example"
    tags = ["tag1", "tag2"]

    #Here we set secrets from the variables
    username = var.database_username
    password = var.database_password
}

Quản lý bí mật Terraform bằng HashiCorp, bạn có thể nhận được những lợi ích sau:

  1. Không có bí mật văn bản thuần túy trong mã của bạn, với quyền truy cập được kiểm soát chặt chẽ vào các bí mật
  2. Bạn có được mức độ bảo trì cao vì bạn không phải viết hoặc cập nhật các trình bao bọc
  3. Bạn cũng có thể tận dụng API để quản lý bí mật, giúp dễ dàng sử dụng lại những bí mật này với các dịch vụ hoặc ứng dụng khác
  4. Bạn có thể xem nhật ký và chạy kiểm tra để xem ai đó đã truy cập dữ liệu nào và ai đã yêu cầu dữ liệu đó.
  5. Xoay vòng bí mật với HashiCorp Vault là một lợi thế bảo mật quan trọng khác đối với quản lý bí mật Terraform

Xoay vòng khóa HashiCorp để quản lý bí mật Terraform tốt hơn

Với các khóa cố định, sẽ rất khó để phát triển một lớp bảo mật mạnh mẽ và đáng tin cậy giúp hệ thống của bạn an toàn. Quản lý bí mật an toàn cũng có thể dựa vào việc luân phiên hoặc thay đổi định kỳ các khóa mã hóa HashiCorp Vault của bạn.

NIST đã cung cấp hướng dẫn về cách bạn có thể triển khai luân phiên khóa kho lưu trữ để bảo vệ bí mật của mình. Sau mỗi 2^32 lần mã hóa, chúng ta nên luân phiên khóa mã hóa kho lưu trữ. Các tham số như vault.barrier.putvault.token.creationvà merkle.flushDirty.num_pages, Chỉ số WAL giúp tính toán số lần mã hóa.

Thông tin thêm

Bạn có thể muốn tham khảo các nguồn sau để biết thêm thông tin về chủ đề này. Mặc dù chúng tôi cung cấp với hy vọng rằng chúng sẽ hữu ích, nhưng xin lưu ý rằng chúng tôi không thể đảm bảo tính chính xác hoặc tính kịp thời của các tài liệu được lưu trữ bên ngoài.

Nguồn: https://www.linode.com/docs/guides/secrets-management-with-terraform/