Quản lý và bảo mật khoá API

1. Giới thiệu

Trước đây, khoá API Google được dùng để truy cập vào các API của Google khi không có phương thức nào khác hoặc khi các phương thức khác được coi là bất tiện. Các trường hợp sử dụng phổ biến là quyền truy cập vào API Google Maps và Google API do Firebase cung cấp. Với sự ra đời của các mô hình AI, các tác nhân AI như Gemini, cũng như AI Studio và các khung phát triển tác nhân AI như Agent Development Kit, khoá API đã trở thành phương thức chính để truy cập vào các Mô hình ngôn ngữ lớn của Google.

Khoá API có mức độ bảo vệ thấp. Mặc dù Google Cloud cung cấp một số phương thức để ngăn chặn hành vi sử dụng sai khoá, nhưng việc sở hữu một khoá API đang hoạt động cho phép truy cập vào các API của Google mà không cần xác thực hoặc xác thực uỷ quyền bổ sung. Các phương thức hạn chế việc sử dụng khoá API được mô tả trong tài liệu. Bài đăng Bảo mật khoá Gemini và Google API trên Cloud Blog đưa ra thêm đề xuất về việc duy trì khoá API. Trong Lớp học lập trình này, bạn sẽ áp dụng những đề xuất này vào thực tế.

Bạn sẽ thực hiện

  • Xem các quy tắc hạn chế bắt buộc khi tạo khoá API mới trên Google Cloud
  • Lập danh mục tất cả khoá API và tìm những khoá không có biện pháp bảo mật
  • Thực thi các quy tắc hạn chế đối với khoá API hiện có dựa trên mức sử dụng
  • Xác định quy trình tự động hoá sẽ xoá khoá trong trường hợp sử dụng bất thường

Bạn cần có

  • Một trình duyệt web hiện đại (chẳng hạn như Chrome).
  • Tài khoản Google

2. Thiết lập

Hướng dẫn trong Lớp học lập trình này giả định rằng bạn chạy các lệnh trong Cloud Shell trong Cloud Console của Google Cloud. Nếu có gcloud CLI trong môi trường cục bộ, bạn có thể chạy các lệnh tại đó.

Mặc dù bạn có thể thực hiện các thao tác trong các bước bằng giao diện người dùng của Cloud Console, nhưng các phương thức sẽ khác nhau. Lớp học lập trình này sử dụng giao diện dòng lệnh để đơn giản hoá các hoạt động tương tác và giúp việc tích hợp với các tác nhân AI hiện đại (như Antigravity CLI) trở nên dễ dàng hơn.

Khởi động một cửa sổ dòng lệnh Cloud Shell

  1. Mở Google Cloud Console bằng cách truy cập vào https://console.cloud.google.com/ trong một cửa sổ trình duyệt mới. Bạn nên sử dụng Chrome để có trải nghiệm người dùng tốt nhất.
  2. Đăng nhập vào Tài khoản Google của bạn trong Google Cloud.
  3. Nhấp vào Kích hoạt Cloud Shell Biểu tượng Kích hoạt Cloud Shell ở đầu Cloud Console.
    Nếu thấy, hãy nhấp vào các cửa sổ sau:
    • Tiếp tục qua cửa sổ thông tin Cloud Shell.
    • Cho phép Cloud Shell sử dụng thông tin đăng nhập của bạn để thực hiện các lệnh gọi API Google Cloud.

Chọn một dự án trong Google Cloud

Sau khi mở Cloud Console, bạn sẽ được xác thực và thường có một lựa chọn dự án cho công việc của bạn. Mã dự án là một chuỗi gồm 6 đến 30 ký tự bao gồm chữ cái viết thường, số và dấu gạch ngang, ví dụ: qwiklabs-gcp-04-3075fc9fd77f. Thiết bị đầu cuối Cloud Shell sẽ định cấu hình gcloud CLI bằng dự án đã chọn. Bạn sẽ thấy kết quả tương tự như sau:

Your Cloud Platform project in this session is set to qwiklabs-gcp-04-3075fc9fd77f

Điều này có nghĩa là các lệnh tiếp theo của bạn đối với gcloud sẽ sử dụng mã dự án qwiklabs-gcp-04-3075fc9fd77f.

Đặt mã dự án làm biến môi trường PROJECT_ID. Bạn có thể xem danh sách tất cả các dự án của mình bằng lệnh sau:

gcloud projects list
  • Thay thế your-project-id và chạy lệnh nếu bạn muốn sử dụng một mã dự án khác với mã được định cấu hình trong gcloud.
    export PROJECT_ID="your-project-id"
    
    Ví dụ:
    export PROJECT_ID="qwiklabs-gcp-04-3075fc9fd77f"
    
  • Chạy lệnh sau nếu bạn muốn sử dụng mã dự án đã chọn:
    export PROJECT_ID=$(gcloud config get project)
    

3. Hạn chế khoá API mới

Trước đây, người dùng có thể tạo khoá API hoàn toàn không bị hạn chế. Bạn có thể dùng khoá không bị hạn chế để gọi BẤT KỲ API nào của Google được bật trong dự án mà bạn đã tạo khoá. Mặc dù Google Cloud Console ngăn người dùng tạo khoá không hạn chế, nhưng bạn vẫn có thể tạo khoá bằng cách sử dụng gcloud CLI hoặc sử dụng các lệnh gọi API trực tiếp.

Các bước sau đây cho biết cách tạo một khoá API bị hạn chế, chỉ cho phép sử dụng API cụ thể và trang web được chỉ định.

  1. Để tạo một khoá API mới chỉ được dùng với API vị trí địa lý của Google Maps, hãy chạy lệnh sau trong thiết bị đầu cuối shell:
    gcloud services api-keys create --key-id=restricted-api-key \
      --display-name="restricted api key" \
      --api-target=service=geolocation.googleapis.com \
      --project=${PROJECT_ID}
    
    Lệnh này tạo một khoá API mới và CHỈ có thể dùng để gọi dịch vụ định vị địa lý của Google Maps.
  2. Tăng cường bảo mật khoá bằng cách thêm một hạn chế về ứng dụng. Giới hạn việc sử dụng khoá cho tất cả các đường dẫn trong trang web example.com. Chạy lệnh sau để thêm hạn chế về ứng dụng vào khoá:
    gcloud services api-keys update restricted-api-key \
      --location=global \
      --allowed-referrers="example.com/*" \
      --project=${PROJECT_ID}
    
    Thay vì cho phép sử dụng khoá cho(các) trang web cụ thể, bạn có thể dùng --allowed-application để xác định ứng dụng Android được phép hoặcallowed-ips để xác định địa chỉ IP được phép. Hãy tham khảo tài liệu đầy đủ để biết tất cả các lựa chọn.

Dọn dẹp

Xoá khoá API mà bạn đã tạo, trừ phi bạn dự định sử dụng khoá đó:

gcloud services api-keys delete --key-id=restricted-api-key \
  --project=${PROJECT_ID}

4. Lập danh mục khoá API

Ở bước này, bạn sẽ sử dụng CLI gcloud để lấy danh sách khoá API. Danh sách kết quả cho thấy tất cả các khoá API đang hoạt động (chưa bị xoá) mà bạn có quyền truy cập.

  1. Chạy lệnh sau để xem tất cả tên khoá, mã nhận dạng và ngày tạo:
    gcloud services api-keys list --project=${PROJECT_ID} \
      --format='value(displayName,name.basename(),createTime.date())'
    
    Kết quả sẽ cho thấy tên dễ đọc của khoá, mã khoá và ngày tạo khoá. Nội dung sẽ tương tự như sau:
    api key 1	api-key-1	2024-05-10T07:53:24
    api key 2	api-key-2	2025-06-12T14:47:57
    
  2. Chọn một trong các mã nhận dạng khoá rồi dán lệnh sau để kiểm tra xem khoá có hạn chế nào không. Thay thế your-key-id bằng giá trị của mã khoá đã chọn:
    gcloud services api-keys describe "your-key-id" --project=${PROJECT_ID}
    

Đầu ra (ở định dạng YAML) sẽ chứa danh sách các quy định hạn chế trong restrictions.

createTime: '2024-05-10T07:53:24.986528Z'
displayName: api key 1
etag: W/"u1WuY41K2tPKUZd7cfLoKg=="
name: projects/123456789012/locations/global/keys/api-key-1
restrictions:
  apiTargets:
  - service: geolocation.googleapis.com
  browserKeyRestrictions:
    allowedReferrers:
    - https://example.com/*
uid: 1a2b3c4d-1234-abcd-1234-a1b2c3d4e5f6
updateTime: '2024-05-10T07:53:24.071228Z'

Xin lưu ý rằng nếu khoá chưa bao giờ được cập nhật, thì các trường createTime và updateTime sẽ có cùng dấu thời gian.

  1. Tải xuống và chạy tập lệnh này để xem tất cả dự án của bạn và in ra tất cả khoá API KHÔNG có quy tắc hạn chế:
    curl -fsSL -o unrestricted_api_keys.sh \
      "https://github.com/GoogleCloudPlatform/devrel-demos/blob/main/security/api-key-audit/unrestricted_api_keys.sh"
    chmod +x unrestricted_api_keys.sh
    ./unrestricted_api_keys.sh
    
    Sau khi chạy tập lệnh, bạn sẽ thấy kết quả có dạng:
    DISPLAY NAME    KEY ID    PROJECT ID    CREATION DATE
    Key 1    1a2b3c4d-1234-abcd-1234-a1b2c3d4e5f6    my-project-1    2024-05-10T07:53:24.071228Z
    
    Bạn có thể tìm thấy tất cả các tập lệnh được dùng trong Lớp học lập trình này tại thư mục Security trong kho lưu trữ devrel-demos trên GitHub.

5. Khám phá mức sử dụng của khoá API

Trong bước này, bạn sẽ truy vấn các chỉ số của Google Cloud để tìm ra những API đã được gọi bằng khoá API của bạn. Dựa vào thông tin này, bạn có thể xem xét việc sử dụng khoá hiện tại và áp dụng các quy tắc hạn chế API cho khoá dựa trên thông tin thực tế thay vì đoán chừng.

  1. Sử dụng cùng một mã khoá mà bạn đã dùng ở bước trước hoặc chọn một mã khoá khác. Thay thế your-key-id bằng mã khoá đã chọn trong lệnh sau:
    export KEY_UID=$(
       gcloud services api-keys describe "your-key-id" \
       --format='value(uid)' \
       --project=${PROJECT_ID})
    
  2. Đặt phạm vi tìm kiếm là nhật ký sử dụng trong một năm. Nếu bạn muốn tìm kiếm trong khoảng thời gian dài hơn hoặc ngắn hơn, hãy thay thế 365 (số ngày) bằng một số dương khác.
    export DAYS=365
    
  3. Làm mới Thông tin xác thực mặc định của ứng dụng (ADC) để cho phép gọi trực tiếp đến Cloud Monitoring API. Chạy lệnh sau và làm theo hướng dẫn trong cửa sổ dòng lệnh:
    gcloud auth application-default login
    
  4. Chạy lệnh sau để gửi yêu cầu về dữ liệu chỉ số sử dụng dịch vụ đến Cloud Monitoring API:
curl -s -G -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  --data-urlencode "filter=metric.type=\"serviceruntime.googleapis.com/api/request_count\" AND resource.labels.credential_id=\"apikey:${KEY_UID}\"" \
  --data-urlencode "interval.startTime=$(date -u -d "${DAYS} days ago" +%Y-%m-%dT%H:%M:%SZ)" \
  --data-urlencode "interval.endTime=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
  "https://monitoring.googleapis.com/v3/projects/${PROJECT_ID}/timeSeries" \
  | jq -r '.timeSeries[]?.resource.labels.service' | sort -u

Lệnh này truy vấn chỉ số tích hợp sẵn serviceruntime/api/request_count cho các điểm dữ liệu có nhãn credential_id khớp với mã nhận dạng duy nhất của khoá API đã chọn. Sau đó, nó sẽ truy xuất các giá trị cho nhãn service và in các giá trị đó trong khi loại bỏ các giá trị lặp lại.

Tăng cường bảo mật khoá API

Ở bước này, bạn sẽ sử dụng thông tin thu thập được ở các bước trước để cập nhật cấu hình hạn chế của khoá API dựa trên thông tin sử dụng.

Bạn sẽ sử dụng cùng một khoá API đã dùng ở bước trước. Nếu cần, hãy chạy lại hướng dẫn từ các bước trước để đảm bảo rằng các biến môi trường PROJECT_ID, KEY_UID và DAYS được đặt.

  1. Chạy lệnh sau để truy xuất danh sách các API của Google được gọi bằng khoá API:

SERVICES=$(curl -s -G -H "Authorization: Bearer $(gcloud auth application-default print-access-token)"
–data-urlencode "filter=metric.type="serviceruntime.googleapis.com/api/request_count" AND resource.labels.credential_id="apikey:${KEY_UID}""
–data-urlencode "interval.startTime=$(date -u -d "${DAYS} days ago" +%Y-%m-%dT%H:%M:%SZ)"
–data-urlencode "interval.endTime=$(date -u +%Y-%m-%dT%H:%M:%SZ)"
"https://monitoring.googleapis.com/v3/projects/${PROJECT_ID}/timeSeries"
| jq -r ‘.timeSeries[]?.resource.labels.service' | sort -u)

1. Build the list of arguments to restrict the API usage for the API key based
on the retrieved list.

```shell
API_TARGET_ARGS=()
for SERVICE in $SERVICES; do
  API_TARGET_ARGS+=("--api-target=service=${SERVICE}")
done
  1. Thay thế danh sách API bị hạn chế cho danh sách không trống:
    if [ ${#API_TARGET_ARGS[@]} -gt 0 ]; then
        gcloud services api-keys update "projects/${PROJECT_ID}/locations/global/keys/${KEY_UID}" \
        ${API_TARGET_ARGS}
    fi
    

6. Xác định tính năng phát hiện mức sử dụng bất thường

Các bước trước đó cho thấy cách khám phá và tăng cường bảo mật khoá API. Bước này cho biết cách tự động hoá phản hồi đối với mức sử dụng khoá tăng đột biến không mong muốn bằng sự trợ giúp của Cảnh báo giám sát.

Hướng dẫn sau đây sẽ tạo một cảnh báo được kích hoạt khi tốc độ của các lệnh gọi API sử dụng khoá API tăng hơn 10% trong 5 phút qua. Cảnh báo được định cấu hình để kích hoạt một tập lệnh Cloud Build nhằm xoá khoá API để ngăn chặn việc sử dụng thêm. Bạn có thể khôi phục khoá trong vòng 30 ngày tới. Hãy xem tài liệu để tìm hiểu cách khôi phục khoá.

Các hướng dẫn này sẽ sử dụng lại các biến PROJECT_ID và KEY_UID mà bạn đã dùng ở các bước trước. Nếu bạn muốn chọn một khoá và/hoặc dự án khác, hãy đặt các giá trị mới cho những biến này như mô tả trong các bước Thiết lập và khám phá cách sử dụng khoá API.

  1. Chạy tập lệnh sau để tạo tệp chính sách cảnh báo:
    cat <<EOF > alert_policy.json
    {
      "displayName": "Credential API Request Count Increase Alert (Project: ${PROJECT_ID})",
      "combiner": "OR",
      "conditions": [
        {
          "displayName": "API Request Count Increase > 10% in 5m with Min Volume",
          "conditionPrometheusQueryLanguage": {
            "query": "(sum(increase(serviceruntime_googleapis_com:api_request_count{metric_label_credential_id=\\"apikey:${KEY_UID}\\"}[5m])) / (sum(increase(serviceruntime_googleapis_com:api_request_count{metric_label_credential_id=\\"apikey:${KEY_UID}\\"}[5m] offset 5m)) or on() vector(1)) > 1.10) and (sum(increase(serviceruntime_googleapis_com:api_request_count{metric_label_credential_id=\\"apikey:${KEY_UID}\\"}[5m])) > 50)",
            "duration": "0s",
            "evaluationInterval": "60s"
          }
        }
      ],
      "enabled": true
    }
    EOF
    
    Chính sách cảnh báo sử dụng bộ lọc PromQL sau đây để kích hoạt cảnh báo:
     (sum(
       increase(
         serviceruntime_googleapis_com:api_request_count{metric_label_credential_id="API_KEY_UID"}[5m])
     ) /
     (sum(
       increase(
         serviceruntime_googleapis_com:api_request_count{metric_label_credential_id="API_KEY_UID"}[5m] offset 5m)
     ) or on() vector(1)) > 1.10)
    and
     (sum(
       increase(
         serviceruntime_googleapis_com:api_request_count{metric_label_credential_id=\"YOUR_CREDENTIAL_ID_HERE\"}[5m])) > 50)
    
    Chỉ số này tính toán tốc độ tăng và so sánh với một khoảng thời gian trước đó. Và chỉ kích hoạt cảnh báo nếu mức tăng lớn hơn 10%. Để tránh kích hoạt cảnh báo khi tổng số lệnh gọi không đáng kể, hệ thống sẽ đặt điều kiện kích hoạt là phải có hơn 50 lệnh gọi API trong khoảng thời gian đó. Để tránh tính toán NaN (xoá theo số 0) khi tốc độ 5 phút trước đó là 0, hệ thống sẽ thay thế mẫu số bằng 1 nếu tốc độ của cửa sổ trước đó là 0.Bạn có thể thay đổi các thông số cảnh báo như độ dài cửa sổ (5m), ngưỡng tối thiểu (50) hoặc ngưỡng tăng 10% (1.10).Các thông số chính sách bổ sung xác định rằng khi đạt đến điều kiện, cảnh báo sẽ được kích hoạt (duration) và điều kiện sẽ được kiểm tra sau mỗi 60 giây (evaluationInterval).
  2. Chạy lệnh sau để tạo một chủ đề PubSub sẽ được dùng để đăng thông báo cảnh báo:
    gcloud pubsub topics create api-key-alert-notifications --project=$PROJECT_ID
    
  3. Chạy lệnh sau để tạo một kênh thông báo cho các cảnh báo sử dụng PubSub.
    CHANNEL_NAME=$(gcloud beta monitoring channels create \
      --display-name="Pub/Sub Alert Channel" \
      --type="pubsub" \
      --channel-labels="topic=projects/$PROJECT_ID/topics/api-key-alert-notifications" \
      --format='value(name)' \
      --project=$PROJECT_ID)
    
    Bạn sẽ sử dụng biến môi trường CHANNEL_NAME trong bước Dọn dẹp.
  4. Chạy lệnh sau để tạo một cảnh báo giám sát mới:
    gcloud monitoring policies create --policy-from-file=alert_policy.json \
      --project=$PROJECT_ID
    
  5. Chạy lệnh sau để cấp cho dịch vụ Cloud Build quyền xoá khoá API trong dự án.
    PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
    gcloud projects add-iam-policy-binding $PROJECT_ID \
      --member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
      --role="roles/apikeys.admin"
    
    Bạn có thể giới hạn vai trò apikeys.admin để chỉ thao tác với một phiên bản cụ thể của khoá API. Hãy xem Điều kiện IAM để biết thêm thông tin.
  6. Chạy tập lệnh sau để tạo một trình kích hoạt Cloud Build giúp xoá khoá API.
    cat <<EOF > trigger_config.yaml
    name: "delete-compromised-api-key"
    description: "Triggered by Pub/Sub alert to automatically delete the leaking API Key"
    pubsubConfig:
      topic: "projects/${PROJECT_ID}/topics/api-key-alert-notifications"
    build:
      steps:
      - name: "gcr.io/google.com/cloudsdktool/cloud-sdk:slim"
        args:
        - "gcloud"
        - "services"
        - "api-keys"
        - "delete"
        - "${KEY_UID}"
        - "--quiet"
    EOF
    
  7. Chạy lệnh sau để tạo điều kiện kích hoạt Cảnh báo giám sát mới:
    gcloud builds triggers create pubsub \
      --trigger-config=trigger_config.yaml \
      --project=$PROJECT_ID
    

Giờ đây, bạn có thể xoá tệp cấu hình chính sách cảnh báo và trình kích hoạt Cloud Build:

rm alert_policy.json trigger_config.yaml

Ngoài ra, bạn có thể thiết lập quy trình tự động hoá này bằng kế hoạch Terraform. Tải các tệp Terraform xuống từ thư mục abnormal-usage-detection trong kho lưu trữ Google Cloud DevRel. Kế hoạch này chấp nhận mã dự án và mã nhận dạng duy nhất của khoá API làm thông số đầu vào, đồng thời thiết lập các tài nguyên và cấu hình mà bạn thấy trong bước này.

7. Dọn dẹp

Để tránh phát sinh các khoản phí không mong muốn trong tài khoản Google Cloud của bạn, hãy nhớ xoá chủ đề Pub/Sub, trình kích hoạt Cloud Build và các chính sách cảnh báo đã tạo trong bài tập này.

Chạy các lệnh sau để xoá tất cả tài nguyên mà bạn đã tạo:

gcloud builds triggers delete delete-compromised-api-key \
  --project=$PROJECT_ID
gcloud beta monitoring channels delete $CHANNEL_NAME \
  --project=$PROJECT_ID \
  --quiet
gcloud pubsub topics delete api-key-alert-notifications \
  --project=$PROJECT_ID
gcloud projects remove-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
  --role="roles/apikeys.admin"

8. Tóm tắt

Trong lớp học lập trình này, bạn đã triển khai một khung bảo mật và tự động hoá toàn diện cho khoá API của Google Cloud:

  1. Cấu hình mặc định được tăng cường: Bạn đã tạo và hạn chế khoá API để chỉ cho phép truy cập vào các API cần thiết và nền tảng đáng tin cậy (chẳng hạn như các giới thiệu HTTP cụ thể).
  2. Kiểm tra Khoá dự phòng: Bạn đã quét các môi trường dự án để phát hiện và cô lập các khoá không bị hạn chế có nguy cơ bảo mật tức thì.
  3. Dữ liệu sử dụng đã phân tích: Bạn đã truy vấn dữ liệu chỉ số Cloud Monitoring theo phương thức lập trình để lập hồ sơ mức sử dụng khoá chính trong quá khứ, cho phép bạn hạn chế các khoá dựa trên dấu vết sử dụng đã xác minh.
  4. Giảm thiểu mối đe doạ tự động: Bạn đã thiết lập một "cầu dao" phản ứng bằng cách kết nối chính sách cảnh báo Cloud Monitoring với một chủ đề Pub/Sub và một trình kích hoạt Cloud Build, cho phép bạn tự động xoá các khoá bị xâm nhập trong thời gian lưu lượng truy cập tăng đột biến bất thường.

Các bước tiếp theo

  • Áp dụng các quy tắc hạn chế cho tất cả khoá API: Sử dụng những gì bạn đã học được trong phòng thí nghiệm này để phát hiện tất cả khoá API bị hạn chế một phần hoặc không bị hạn chế, đồng thời áp dụng các quy tắc hạn chế về API và ứng dụng,
  • Thiết lập "cầu dao" cho khoá API: Bảo vệ khoá API khỏi việc sử dụng ngoài ý muốn bằng cách thiết lập tính năng tự động xoá khoá trong trường hợp mức tiêu thụ tăng đột ngột. Sử dụng các lệnh gcloud hoặc Terraform có trong phòng thí nghiệm. Cân nhắc việc thắt chặt các quyền bằng cách sử dụng điều kiện IAM
  • Khám phá tính năng Cảnh báo của dịch vụ Giám sát: Tìm hiểu thêm về cách thiết lập cảnh báo bằng dịch vụ Giám sát của Google Cloud.
  • Tìm hiểu thêm về chế độ kiểm soát quyền truy cập có trên Google Cloud: Xem Chính sách ranh giới truy cập và quy trình truyền tải thay đổi về quyền truy cập.