Tối ưu quản lý secrets, API key và credentials an toàn trên Linux với HashiCorp Vault

Security tutorial - IT technology blog
Security tutorial - IT technology blog

Bối cảnh: Tại sao quản lý secrets hiệu quả lại cần thiết?

Khi làm việc với các hệ thống IT, mình nhận ra một vấn đề phổ biến nhưng đầy rủi ro: quản lý thông tin nhạy cảm, hay còn gọi là secrets. Các secrets này có thể là API keys của bên thứ ba, database credentials, chứng chỉ SSL, token truy cập, hoặc thậm chí là mật khẩu root server. Thông thường, anh em lập trình viên thường lưu trữ chúng trong các file cấu hình (.env), biến môi trường, hoặc tệ hơn là hardcode thẳng vào mã nguồn.

Server của mình từng bị tấn công brute-force SSH và mình đã phải xử lý khẩn cấp vào nửa đêm. Từ đó, mình luôn ưu tiên thiết lập bảo mật ngay từ đầu.

Bảo mật không chỉ là hardening hệ thống hay dùng mật khẩu mạnh, mà còn là cách chúng ta quản lý các thông tin nhạy cảm như API keys, database credentials hay token. Chỉ cần một lỗ hổng nhỏ trong việc lưu trữ hoặc truyền tải secrets, hậu quả có thể rất nghiêm trọng. Điều này có thể dẫn đến lộ dữ liệu khách hàng hoặc thậm chí mất quyền kiểm soát toàn bộ hệ thống.

Việc quản lý secrets thủ công không chỉ kém an toàn mà còn gây khó khăn khi mở rộng hoặc thay đổi. Chẳng hạn, nếu bạn có hàng chục dịch vụ cùng dùng chung một database, việc cập nhật mật khẩu database sẽ trở thành một cơn ác mộng. Chính vì vậy, mình đã tìm đến các giải pháp chuyên nghiệp, và HashiCorp Vault là một trong những lựa chọn nổi bật.

Để tạo mật khẩu đủ mạnh và duy nhất, mình thường dùng các công cụ online như Password Generator trên ToolCraft.app. Công cụ này chạy hoàn toàn trên trình duyệt, không gửi dữ liệu lên server, nên mình rất yên tâm khi dùng để tạo mật khẩu cho nhiều dịch vụ. Tuy nhiên, mật khẩu mạnh thôi là chưa đủ. Quan trọng hơn là cách chúng ta lưu trữ và sử dụng chúng một cách an toàn, có kiểm soát.

HashiCorp Vault là một công cụ mã nguồn mở, được thiết kế để quản lý vòng đời của secrets một cách an toàn. Nó cung cấp kho lưu trữ tập trung, khả năng mã hóa, kiểm soát truy cập dựa trên chính sách, và đặc biệt là khả năng tạo secrets động theo yêu cầu. Nhờ đó, Vault giúp giảm thiểu rủi ro lộ thông tin nhạy cảm, đơn giản hóa việc quản lý và tự động hóa các tác vụ bảo mật.

Cài đặt HashiCorp Vault trên Linux

Trong phần này, mình sẽ hướng dẫn cài đặt HashiCorp Vault trên một server Linux cụ thể là Ubuntu Server 22.04 LTS. Quy trình này khá đơn giản và rất phù hợp cho việc triển khai bước đầu.

1. Tải và cài đặt Vault

Đầu tiên, chúng ta cần tải Vault. Bạn có thể truy cập trang web chính thức của HashiCorp Vault để lấy link phiên bản mới nhất, hoặc sử dụng wget như sau:

wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install vault

Sau khi cài đặt, bạn hãy kiểm tra phiên bản Vault để xác nhận mọi thứ đã sẵn sàng:

vault --version

Kết quả hiển thị sẽ tương tự Vault v1.X.X ('X.X.X+ent' for enterprise).

2. Cấu hình Vault Server

Để Vault có thể hoạt động, chúng ta cần tạo một file cấu hình. Mình sẽ thiết lập một cấu hình cơ bản với backend lưu trữ là filesystem, rất phù hợp cho môi trường phát triển hoặc thử nghiệm. Đối với môi trường production, bạn nên cân nhắc sử dụng các backend mạnh mẽ hơn như Consul, Raft hoặc PostgreSQL để đảm bảo tính sẵn sàng cao (High Availability).

Tạo người dùng, nhóm và thư mục cần thiết

sudo useradd --system --home /etc/vault.d --shell /bin/false vault
sudo mkdir -p /etc/vault.d
sudo mkdir -p /var/lib/vault
sudo chown -R vault:vault /var/lib/vault
sudo chmod 755 /var/lib/vault

Tạo file cấu hình /etc/vault.d/vault.hcl

Sử dụng lệnh sudo nano /etc/vault.d/vault.hcl rồi dán nội dung sau:

storage "file" {
  path = "/var/lib/vault"
}

listener "tcp" {
  address     = "0.0.0.0:8200"
  tls_disable = "true" # Tắt TLS cho môi trường dev/test. Cần bật TLS cho production!
}

# UI cho phép truy cập Vault qua trình duyệt (tùy chọn)
ui = true

disable_mlock = true

Lưu ý quan trọng: tls_disable = "true" chỉ dùng cho môi trường phát triển. Trong môi trường production, BẮT BUỘC phải bật TLS để mã hóa mọi giao tiếp với Vault. Mình cũng bật ui = true để sau này có thể truy cập giao diện web của Vault một cách dễ dàng.

3. Tạo Systemd Service

Để Vault tự động khởi động cùng hệ thống và giúp việc quản lý thuận tiện, mình sẽ tạo một service Systemd.

Tạo file /etc/systemd/system/vault.service:

sudo nano /etc/systemd/system/vault.service

Tiếp theo, dán nội dung sau:

[Unit]
Description="HashiCorp Vault - A tool for managing secrets"
Documentation=https://www.vaultproject.io/docs/
Requires=network-online.target
After=network-online.target

[Service]
User=vault
Group=vault
ProtectSystem=full
ProtectHome=read-only
PrivateTmp=yes
PrivateDevices=yes
SecureBits=keep capabilities
AmbientCapabilities=CAP_IPC_LOCK
Capabilities=CAP_IPC_LOCK+ep
CapabilityBoundingSet=CAP_IPC_LOCK
NoNewPrivileges=yes
ExecStart=/usr/bin/vault server -config=/etc/vault.d/vault.hcl
ExecReload=/bin/kill --signal HUP $MAINPID
KillMode=process
KillSignal=SIGINT
Restart=on-failure
RestartSec=5
TimeoutStopSec=30
StartLimitInterval=60s
StartLimitBurst=3
LimitNOFILE=65536
LimitMEMLOCK=infinity

[Install]
WantedBy=multi-user.target

Lưu file và thoát. Sau đó, bạn cần reload Systemd, enable và khởi động Vault service:

sudo systemctl daemon-reload
sudo systemctl enable vault
sudo systemctl start vault

Để kiểm tra trạng thái service, dùng lệnh:

sudo systemctl status vault

Bạn sẽ thấy Vault đang hiển thị trạng thái active (running).

Cấu hình Vault chi tiết

Khi Vault server đã khởi động, bước tiếp theo là khởi tạo và cấu hình nó để bắt đầu lưu trữ cũng như quản lý secrets.

1. Khởi tạo (Initialize) Vault

Khi Vault mới khởi động, nó sẽ ở trạng thái sealed (niêm phong). Điều này có nghĩa là Vault chưa thể truy cập vào các dữ liệu đã được mã hóa. Để mở khóa (unseal) Vault, chúng ta cần thực hiện khởi tạo. Quá trình này sẽ tạo ra các Unseal Keys và một Root Token.

Chạy lệnh sau:

vault operator init

Bạn sẽ nhận được kết quả tương tự như sau:

Unseal Key 1: Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Unseal Key 2: Yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
Unseal Key 3: Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
Unseal Key 4: Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Unseal Key 5: Bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

Initial Root Token: hvs.Cccccccccccccccccccccccccccccccccccccccc

Vault initialized with 5 key shares and a key threshold of 3. Please
safely distribute the key shares you see above. When the Vault is re-sealed,
restarted, or stopped, you must provide at least 3 of these key shares
to unseal it again.

Cực kỳ quan trọng: Bạn phải lưu trữ cẩn thận các Unseal Keys và Root Token này ở một nơi thật an toàn. Root Token có toàn quyền truy cập vào Vault và chỉ nên được sử dụng một lần duy nhất cho cấu hình ban đầu. Sau đó, hãy thu hồi nó và chuyển sang dùng các phương thức xác thực có quyền hạn thấp hơn. Unseal Keys rất cần thiết để mở khóa Vault mỗi khi nó khởi động lại hoặc bị niêm phong.

2. Giải niêm phong (Unseal) Vault

Với key_threshold là 3, mình cần cung cấp ít nhất 3 trong số 5 Unseal Keys đã nhận được để giải niêm phong Vault.

vault operator unseal
# Dán Unseal Key 1 vào đây

vault operator unseal
# Dán Unseal Key 2 vào đây

vault operator unseal
# Dán Unseal Key 3 vào đây

Khi đã cung cấp đủ số lượng key, Vault sẽ chuyển sang trạng thái unsealed.

3. Đăng nhập (Login)

Để tương tác với Vault, chúng ta cần đăng nhập. Trước tiên, hãy thiết lập biến môi trường VAULT_ADDR:

export VAULT_ADDR='http://127.0.0.1:8200'

Bây giờ, đăng nhập bằng Root Token:

vault login hvs.Cccccccccccccccccccccccccccccccccccccccc

Bạn sẽ thấy thông báo Success! You are now authenticated.

4. Kích hoạt và cấu hình Secret Engines (KV Secret Engine v2)

Secret Engines là các thành phần của Vault để lưu trữ, tạo hoặc mã hóa secrets. KV (Key-Value) Secret Engine là loại phổ biến nhất, cho phép bạn lưu trữ secrets dưới dạng cặp key-value.

Kích hoạt KV Secret Engine v2 (phiên bản 2 hỗ trợ versioning cho secrets):

vault secrets enable -version=2 kv

Ghi một secret:

vault kv put kv/my-app/config username=devuser password="supersecretpassword123"

Đọc secret:

vault kv get kv/my-app/config

Output sẽ hiển thị các secret đã lưu. Khi làm việc với output JSON từ Vault, đôi khi chuỗi JSON khá dài và khó đọc. Mình thường copy output đó vào JSON Formatter & Validator trên ToolCraft.app để định dạng lại, giúp phân tích dễ dàng hơn. Cần nhớ, các thông tin nhạy cảm (secrets) phải được xử lý cẩn thận. Đừng dán chúng vào các công cụ online nếu không chắc chắn về bảo mật. Riêng ToolCraft, vì mọi xử lý đều trên trình duyệt, mình an tâm hơn khi dùng.

5. Chính sách (Policies)

Policies trong Vault định nghĩa quyền mà một token hoặc AppRole có thể truy cập. Mình sẽ tạo một policy mẫu dành cho ứng dụng phát triển.

Tạo file dev-policy.hcl:

path "kv/data/my-app/config" {
  capabilities = ["read"]
}

path "kv/metadata/my-app/config" {
  capabilities = ["list"]
}

Policy này cho phép đọc secret tại đường dẫn kv/my-app/config và liệt kê metadata của secret đó.

Ghi policy vào Vault:

vault policy write dev dev-policy.hcl

6. Phương thức xác thực (Auth Methods – AppRole)

AppRole là một phương thức xác thực phổ biến cho các ứng dụng. Nó cho phép ứng dụng tự động lấy token từ Vault mà không cần hardcode credentials.

Kích hoạt AppRole Auth Method:

vault auth enable approle

Tạo một role tên dev-app và gán policy dev vừa tạo:

vault write auth/approle/role/dev-app token_policies="dev" token_ttl="1h" token_max_ttl="24h"

Đọc role_id cho role dev-app (role_id là public và có thể phân phối cho ứng dụng):

vault read auth/approle/role/dev-app/role-id

Tạo secret_id cho role dev-app (secret_id là private, cần được bảo mật tuyệt đối và chỉ cấp cho ứng dụng):

vault write -f auth/approle/role/dev-app/secret-id

Ứng dụng của bạn sẽ dùng role_idsecret_id này để gửi yêu cầu tới Vault. Từ đó, nó sẽ nhận về một Vault Token với quyền hạn theo policy dev. Token này sau đó sẽ được sử dụng để đọc các secrets cần thiết.

Ví dụ một đoạn code Python để lấy secret từ Vault:

import os
import hvac # pip install hvac

VAULT_ADDR = os.environ.get('VAULT_ADDR', 'http://127.0.0.1:8200')
APPROLE_ROLE_ID = "your_role_id_here"
APPROLE_SECRET_ID = "your_secret_id_here"

client = hvac.Client(url=VAULT_ADDR)

try:
    # Login using AppRole
    login_response = client.auth.approle.login(role_id=APPROLE_ROLE_ID, secret_id=APPROLE_SECRET_ID)
    client.token = login_response['auth']['client_token']

    # Read secret
    read_response = client.secrets.kv.v2.read_secret_version(path='my-app/config', mount_point='kv')
    
    username = read_response['data']['data']['username']
    password = read_response['data']['data']['password']

    print(f"Username: {username}")
    print(f"Password: {password}")

except hvac.exceptions.VaultError as e:
    print(f"Lỗi khi tương tác với Vault: {e}")
except Exception as e:
    print(f"Lỗi không xác định: {e}")

Trên thực tế, bạn sẽ không hardcode role_idsecret_id trực tiếp vào code. Thay vào đó, hãy cung cấp chúng qua biến môi trường hoặc một cơ chế bảo mật khác khi triển khai.

Kiểm tra và giám sát Vault

Sau khi thiết lập Vault, việc kiểm tra và giám sát là bước vô cùng quan trọng. Nó giúp đảm bảo hệ thống hoạt động ổn định và an toàn.

1. Kiểm tra trạng thái Vault

Bạn có thể kiểm tra trạng thái tổng quan của Vault bằng lệnh:

vault status

Lệnh này sẽ hiển thị thông tin về trạng thái niêm phong, tính sẵn sàng cao (High Availability, nếu có), và địa chỉ của Vault.

2. Audit Logging

Vault có khả năng ghi lại mọi yêu cầu và phản hồi, cung cấp cho bạn một bản ghi chi tiết về ai đã truy cập gì và vào thời điểm nào. Đây là tính năng không thể thiếu cho mục đích kiểm toán và nâng cao bảo mật.

Kích hoạt audit log ra file:

vault audit enable file file_path=/var/log/vault_audit.log

Sau khi kích hoạt, mọi tương tác với Vault sẽ được ghi lại vào file /var/log/vault_audit.log. Bạn cần đảm bảo file log này được bảo vệ và chỉ người dùng có quyền mới được truy cập.

3. Backup và Restore

Dù mình dùng filesystem backend cho ví dụ này, nhưng trong môi trường production, bạn CẦN có chiến lược backup rõ ràng cho backend storage (như Consul, Raft, PostgreSQL,…). Quan trọng hơn cả là phải bảo vệ các Unseal Keys. Nếu không có Unseal Keys, bạn sẽ không thể truy cập lại dữ liệu khi Vault khởi động lại và trở về trạng thái niêm phong.

4. Lưu ý bảo mật quan trọng

  • Bảo mật Unseal Keys: Tuyệt đối không lưu trữ tất cả Unseal Keys tại cùng một vị trí. Hãy phân phối chúng cho những người thực sự đáng tin cậy.
  • Sử dụng TLS: Luôn bật TLS cho mọi giao tiếp với Vault trong môi trường production. Điều này giúp bảo vệ dữ liệu trong quá trình truyền tải.
  • Nguyên tắc quyền hạn tối thiểu (Least Privilege): Chỉ cấp cho người dùng hoặc ứng dụng những quyền hạn cần thiết, không bao giờ nhiều hơn mức đó.
  • Kiểm toán định kỳ: Thường xuyên kiểm tra audit logs để kịp thời phát hiện các hoạt động bất thường.
  • Xoay vòng secrets và token: Tận dụng khả năng tạo secrets động của Vault và định kỳ xoay vòng các token, secrets. Việc này giúp giảm thiểu đáng kể rủi ro.

Kết luận

HashiCorp Vault là giải pháp linh hoạt và hiệu quả để quản lý secrets một cách an toàn. Việc đầu tư thời gian tìm hiểu và triển khai Vault sẽ mang lại lợi ích lâu dài cho hệ thống, giúp bạn yên tâm hơn về bảo mật. Với những kiến thức cơ bản về cài đặt và cấu hình này, mình hy vọng bạn có thể bắt đầu hành trình bảo vệ thông tin nhạy cảm một cách chủ động và chuyên nghiệp hơn.

Share: