Tìm hiểu cách gọi các hàm Cloud Run đã xác thực

1. Giới thiệu

Tổng quan

Hàm Cloud Run là một giải pháp điện toán đơn giản để nhà phát triển tạo các hàm độc lập, có mục đích duy nhất có thể được kích hoạt bằng HTTPS hoặc phản hồi CloudEvents mà không cần quản lý máy chủ hoặc môi trường thời gian chạy. Tìm hiểu thêm về các hàm Cloud Run trong bài đăng trên blog của chúng tôi.

Có hai phương pháp chính để kiểm soát lệnh gọi đến các hàm Cloud Run: bảo mật quyền truy cập dựa trên danh tính và bảo mật quyền truy cập bằng các chế độ kiểm soát quyền truy cập dựa trên mạng. Lớp học lập trình này tập trung vào phương pháp đầu tiên và hướng dẫn bạn 3 trường hợp để bảo mật quyền truy cập dựa trên danh tính nhằm gọi một hàm:

  1. Sử dụng mã thông báo nhận dạng gcloud để gọi một hàm cho mục đích phát triển và kiểm thử cục bộ
  2. Mạo danh một tài khoản dịch vụ khi phát triển và kiểm thử cục bộ để sử dụng cùng thông tin đăng nhập như trong quá trình sản xuất
  3. Sử dụng các thư viện ứng dụng Google để xử lý việc xác thực đối với các Cloud APIs của Google, chẳng hạn như khi một dịch vụ cần gọi một hàm

Kiến thức bạn sẽ học được

  • Cách định cấu hình quy trình xác thực trên một hàm Cloud Run và xác minh rằng quy trình xác thực đã được định cấu hình đúng cách
  • Gọi một hàm đã xác thực từ môi trường phát triển cục bộ bằng cách cung cấp mã thông báo cho danh tính gcloud của bạn
  • Cách tạo tài khoản dịch vụ và cấp cho tài khoản đó vai trò phù hợp để gọi một hàm
  • Cách mạo danh một dịch vụ từ môi trường phát triển cục bộ có các vai trò thích hợp để gọi một hàm

2. Thiết lập và yêu cầu

Điều kiện tiên quyết

  • Bạn đã đăng nhập vào Cloud Console
  • Trước đây, bạn đã triển khai một hàm Cloud Run được kích hoạt bằng HTTP. Xem ví dụ bắt đầu nhanh.
  • (không bắt buộc) Đối với trường hợp thứ 3, lớp học lập trình này sử dụng Node.jsnpm làm ví dụ, nhưng bạn có thể sử dụng bất kỳ thời gian chạy nào được thư viện ứng dụng Google Auth hỗ trợ.

Kích hoạt Cloud Shell

  1. Trong Cloud Console, hãy nhấp vào Kích hoạt Cloud Shell d1264ca30785e435.png.

84688aa223b1c3a2.png

Nếu đây là lần đầu tiên bạn khởi động Cloud Shell, bạn sẽ thấy một màn hình trung gian mô tả về Cloud Shell. Nếu bạn thấy màn hình trung gian, hãy nhấp vào Tiếp tục.

d95252b003979716.png

Quá trình cung cấp và kết nối với Cloud Shell chỉ mất vài giây.

7833d5e1c5d18f54.png

Máy ảo này được trang bị tất cả các công cụ phát triển cần thiết. Nền tảng này cung cấp một thư mục chính có dung lượng 5 GB và chạy trong Google Cloud, giúp tăng cường đáng kể hiệu suất mạng và hoạt động xác thực. Bạn có thể thực hiện hầu hết, nếu không muốn nói là tất cả, công việc của mình trong lớp học lập trình này bằng trình duyệt.

Sau khi kết nối với Cloud Shell, bạn sẽ thấy rằng mình đã được xác thực và dự án được đặt thành mã dự án của bạn.

  1. Chạy lệnh sau trong Cloud Shell để xác nhận rằng bạn đã được xác thực:
gcloud auth list

Đầu ra của lệnh

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Chạy lệnh sau trong Cloud Shell để xác nhận rằng lệnh gcloud biết về dự án của bạn:
gcloud config list project

Đầu ra của lệnh

[core]
project = <PROJECT_ID>

Nếu không, bạn có thể đặt nó bằng lệnh sau:

gcloud config set project <PROJECT_ID>

Đầu ra của lệnh

Updated property [core/project].

3. Tạo và kiểm thử một hàm Cloud Run đã xác thực

Việc yêu cầu xác thực có nghĩa là nguyên tắc gọi hàm phải có vai trò Cloud Run Invoker; nếu không, hàm sẽ trả về lỗi 403 Bị cấm. Lớp học lập trình này sẽ hướng dẫn bạn cách cấp vai trò Người gọi phù hợp cho một nguyên tắc.

Thiết lập các biến môi trường cục bộ để đơn giản hoá các lệnh gcloud

Trước tiên, bạn sẽ tạo một số biến môi trường để cải thiện khả năng đọc của các lệnh gcloud được dùng trong lớp học lập trình này.

REGION=us-central1
PROJECT_ID=$(gcloud config get-value project)

Tạo mã nguồn cho hàm

Mặc dù lớp học lập trình này sử dụng Node.js, nhưng bạn có thể sử dụng bất kỳ thời gian chạy nào được các thư viện ứng dụng Google Auth hỗ trợ.

Trước tiên, hãy tạo một thư mục rồi chuyển đến thư mục đó.

mkdir auth-function-codelab && cd $_

Sau đó, hãy tạo tệp package.json.

touch package.json

echo '{
  "dependencies": {
    "@google-cloud/functions-framework": "^3.0.0"
  }
}
' > package.json

Tiếp theo, hãy tạo tệp nguồn index.js.

touch index.js

echo 'const functions = require("@google-cloud/functions-framework");

functions.http("helloWorld", (req, res) => {
 res.send(`Hello ${req.query.name || req.body.name || "World"}!`);
});' > index.js

Tạo hàm đã xác thực

Sau đây là các bước tạo một hàm đã xác thực cho thời gian chạy nodejs20. Tuy nhiên, bạn có thể sử dụng bất kỳ thời gian chạy nào được thư viện ứng dụng Google Auth hỗ trợ.

FUNCTION_NAME=authenticated-function-codelab
ENTRY_POINT=helloWorld

Để triển khai một hàm Cloud Run trực tiếp lên Cloud Run, hãy chạy lệnh sau:

gcloud beta run deploy $FUNCTION_NAME \
      --source . \
      --function helloWorld \
      --region $REGION \
      --no-allow-unauthenticated

sau đó, bạn có thể lưu URL của hàm dưới dạng một biến môi trường để sử dụng sau này.

FUNCTION_URL="$(gcloud run services describe $FUNCTION_NAME --region $REGION --format 'value(status.url)')"

Nếu bạn muốn triển khai dưới dạng Cloud Functions thế hệ thứ 2, hãy dùng lệnh sau:

gcloud functions deploy nodejs-http-function \
  --gen2 \
  --runtime=nodejs20 \
  --region=$REGION \
  --source=. \
  --entry-point=helloWorld \
  --trigger-http \
  --no-allow-unauthenticated

sau đó, bạn có thể lưu URL của hàm dưới dạng một biến môi trường để sử dụng sau này.

FUNCTION_URL="$(gcloud functions describe $FUNCTION_NAME --gen2 --region us-central1 --format='get(serviceConfig.uri)')"

Xác minh rằng hàm yêu cầu xác thực bằng cách cố gắng gọi dưới dạng một người gọi ẩn danh

Bạn sẽ gọi hàm mà không cần xác thực để xác minh rằng bạn nhận được lỗi 403 như dự kiến.

Từ dòng lệnh, hãy chạy lệnh curl sau:

curl -i $FUNCTION_URL

Bạn sẽ thấy kết quả sau:

<html><head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>403 Forbidden</title>
</head>
<body text=#000000 bgcolor=#ffffff>
<h1>Error: Forbidden</h1>
<h2>Your client does not have permission to get URL <code>/</code> from this server.</h2>
<h2></h2>
</body></html>

Giờ đây, bạn đã sẵn sàng xem xét 3 trường hợp mà bạn có thể gọi Hàm bằng cách cung cấp thông tin xác thực.

4. Trường hợp 1: Sử dụng mã nhận dạng gcloud

Là một nhà phát triển, bạn sẽ muốn có cách để kiểm thử hàm trong khi đang phát triển hàm đó trên máy cục bộ. Trong phần này, bạn sẽ thực hiện một bài kiểm thử nhanh để xác minh rằng hàm đã được xác thực đúng cách bằng danh tính của riêng bạn.

Xác minh rằng bạn đã được xác thực bằng gcloud bằng cách chạy lệnh sau:

gcloud auth list

Bạn sẽ thấy một dấu hoa thị bên cạnh danh tính đang hoạt động, ví dụ:

Credentialed Accounts
ACTIVE  ACCOUNT

*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`

Bạn có thể tìm thêm thông tin về cách thiết lập gcloud initgcloud auth login trong tài liệu.

Tiếp theo, hãy gọi Hàm và truyền mã thông báo nhận dạng của bạn vào đó.

curl $FUNCTION_URL -H "Authorization: bearer $(gcloud auth print-identity-token)"

Bây giờ, bạn sẽ thấy kết quả:

Hello World!

Khắc phục sự cố

Nếu bạn nhận được lỗi 403 Bị cấm, hãy đảm bảo rằng danh tính của bạn có vai trò Cloud Run Invoker. Bạn có thể sử dụng bảng điều khiển IAM để xác minh các vai trò được chỉ định cho một thực thể.

Mặc dù việc sử dụng mã thông báo nhận dạng của riêng bạn là một cách nhanh chóng để kiểm thử hàm trong quá trình phát triển, nhưng người gọi hàm đã xác thực của bạn sẽ cần có các vai trò thích hợp; nếu không, người gọi sẽ nhận được lỗi 403 Bị cấm.

Bạn nên tuân theo nguyên tắc về đặc quyền tối thiểu bằng cách giới hạn số lượng danh tính và tài khoản dịch vụ có vai trò gọi hàm. Trong trường hợp tiếp theo, bạn sẽ tìm hiểu cách tạo tài khoản dịch vụ mới và cấp cho tài khoản đó các vai trò thích hợp để gọi hàm.

5. Tình huống 2: Mạo danh tài khoản dịch vụ

Trong trường hợp này, bạn sẽ mạo danh (tức là giả định các quyền của) một tài khoản dịch vụ để gọi một hàm khi phát triển và kiểm thử cục bộ. Bằng cách mạo danh một tài khoản dịch vụ, bạn có thể kiểm thử chức năng của mình bằng thông tin đăng nhập giống như trong quá trình sản xuất.

Bằng cách này, bạn không chỉ xác minh các vai trò mà còn tuân theo nguyên tắc về đặc quyền tối thiểu bằng cách không phải cấp vai trò Người gọi Cloud Functions cho các danh tính khác chỉ cho mục đích kiểm thử cục bộ.

Để phục vụ mục đích của lớp học lập trình này, bạn sẽ tạo một tài khoản dịch vụ mới chỉ có các vai trò để gọi hàm mà bạn đã tạo trong lớp học lập trình này.

Tạo tài khoản dịch vụ mới

Trước tiên, bạn sẽ tạo thêm một số biến môi trường để biểu thị các tài khoản dịch vụ được dùng trong các lệnh gcloud.

SERVICE_ACCOUNT_NAME="invoke-functions-codelab"
SERVICE_ACCOUNT_ADDRESS=$SERVICE_ACCOUNT_NAME@$PROJECT_ID.iam.gserviceaccount.com

Tiếp theo, bạn sẽ tạo tài khoản dịch vụ.

gcloud iam service-accounts create $SERVICE_ACCOUNT_NAME \
  --display-name="Cloud Run function Authentication codelab"

Và cấp cho tài khoản dịch vụ vai trò người gọi Cloud Run:

gcloud run services add-iam-policy-binding $FUNCTION_NAME \
  --region=us-central1  \
  --member serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
  --role='roles/run.invoker'

Gọi hàm bằng cách mạo danh tài khoản dịch vụ

Để làm việc này, bạn sẽ mạo danh tài khoản dịch vụ mới tạo bằng cách lấy mã thông báo nhận dạng của tài khoản đó.

Thêm các vai trò bắt buộc để mạo danh

Để mạo danh một tài khoản dịch vụ, tài khoản người dùng của bạn cần có vai trò Trình tạo mã thông báo tài khoản dịch vụ (roles/iam.serviceAccountTokenCreator) để tạo mã thông báo nhận dạng cho tài khoản dịch vụ.

Bạn có thể chạy các lệnh sau để cấp vai trò này cho tài khoản người dùng đang hoạt động của mình:

ACCOUNT_EMAIL=$(gcloud auth list --filter=status:ACTIVE --format="value(account)")

gcloud iam service-accounts add-iam-policy-binding $SERVICE_ACCOUNT_ADDRESS  \
  --member user:$ACCOUNT_EMAIL \
  --role='roles/iam.serviceAccountTokenCreator'

Sử dụng mã thông báo nhận dạng của tài khoản dịch vụ

Đợi một vài phút để quyền được áp dụng. Giờ đây, bạn có thể gọi Hàm bằng cách truyền mã nhận dạng (ID) của tài khoản dịch vụ.

curl $FUNCTION_URL -H "Authorization: bearer $(gcloud auth print-identity-token --impersonate-service-account $SERVICE_ACCOUNT_ADDRESS)" 

Bạn sẽ thấy những thông tin sau:

WARNING: This command is using service account impersonation. All API calls will be executed as [invoke-functions-codelab@<project-id>.iam.gserviceaccount.com].

Hello World!

6. Tình huống 3: Sử dụng thư viện ứng dụng Google

Trong phần cuối cùng của lớp học lập trình này, bạn sẽ chạy một dịch vụ nhỏ cục bộ để tạo mã thông báo nhận dạng (ID) cho một tài khoản dịch vụ, sau đó gọi Hàm theo phương thức lập trình bằng thư viện ứng dụng Google AuthThông tin xác thực mặc định của ứng dụng (ADC). Bạn có thể đọc thêm về thư viện ứng dụng Google trong phần giải thích về thư viện ứng dụng của tài liệu.

Việc sử dụng ADC đặc biệt quan trọng khi bạn muốn ghi và kiểm thử Hàm cục bộ (ví dụ: trên máy tính xách tay, trong Cloud Shell, v.v.) trong khi tương tác với các tài nguyên khác trên Google Cloud (ví dụ: Cloud Storage, Vision API, v.v.) Trong ví dụ này, bạn sẽ thấy cách để một dịch vụ gọi một Hàm khác yêu cầu xác thực. Để biết thêm thông tin về ADC và hoạt động phát triển cục bộ, hãy xem bài đăng trên blog Cách phát triển và kiểm thử cục bộ các Cloud Functions | Blog của Google Cloud

Chạy lệnh gcloud để mạo danh một tài khoản dịch vụ

ADC tự động tìm thông tin xác thực dựa trên môi trường ứng dụng và sử dụng thông tin xác thực đó để xác thực với các Cloud APIs của Google Cloud. Cờ –impersonate-service-account cho phép bạn mạo danh một tài khoản dịch vụ bằng cách sử dụng danh tính của tài khoản đó để xác thực với các Cloud API của Google.

Để mạo danh tài khoản dịch vụ, bạn có thể chạy lệnh sau:

gcloud auth application-default login --impersonate-service-account=$SERVICE_ACCOUNT_ADDRESS

Giờ đây, bạn đang chạy các lệnh gcloud dưới dạng tài khoản dịch vụ đó, thay vì danh tính của bạn.

Tạo và chạy một dịch vụ để gọi một hàm đã xác thực

Mỗi thời gian chạy đều có thư viện ứng dụng Google Auth riêng mà bạn có thể cài đặt. Lớp học lập trình này hướng dẫn bạn cách tạo và chạy một ứng dụng Node.js cục bộ.

Sau đây là các bước dành cho Node.js:

  1. Tạo thư mục mới
mkdir local-dev && cd $_
  1. Tạo ứng dụng Node.js mới
npm init -y
  1. Cài đặt thư viện ứng dụng Google Auth
npm install google-auth-library
  1. Tạo tệp index.js
  2. Truy xuất URL của hàm Cloud Run mà bạn sẽ thêm vào mã ở bước tiếp theo.
echo $FUNCTION_URL
  1. Thêm mã sau vào index.js. Hãy nhớ thay đổi biến targetAudience thành URL của hàm Cloud Run.

index.js

// Cloud Functions uses your function's url as the `targetAudience` value

const targetAudience = '<YOUR-CLOUD-RUN-FUNCTION-URL>';

// For Cloud Functions, endpoint(`url`) and `targetAudience` should be equal

const url = targetAudience;

const { GoogleAuth } = require('google-auth-library');
const auth = new GoogleAuth();

async function request() {
    console.info(`request ${url} with target audience ${targetAudience}`);

    // this call retrieves the ID token for the impersonated service account
    const client = await auth.getIdTokenClient(targetAudience);

    const res = await client.request({ url });
    console.info(res.data);
}

request().catch(err => {
    console.error(err.message);
    process.exitCode = 1;
});
  1. Chạy ứng dụng
node index.js

Bạn sẽ thấy kết quả là "Hello World!"

Khắc phục sự cố

Nếu bạn thấy lỗi Permission ‘iam.serviceAccounts.getOpenIdToken' denied on resource (hoặc lỗi này có thể không tồn tại), vui lòng đợi vài phút để vai trò Trình tạo mã thông báo tài khoản dịch vụ được truyền tải.

Nếu bạn nhận được lỗi Không thể tìm nạp mã nhận dạng trong môi trường này, hãy sử dụng GCE hoặc đặt biến môi trường GOOGLE_APPLICATION_CREDENTIALS thành tệp JSON thông tin đăng nhập tài khoản dịch vụ, có thể bạn đã quên chạy lệnh

gcloud auth application-default login --impersonate-service-account=$SERVICE_ACCOUNT_ADDRESS

7. Xin chúc mừng!

Chúc mừng bạn đã hoàn thành lớp học lập trình này!

Bạn nên xem tài liệu về cách bảo mật các hàm Cloud Run.

Bạn cũng nên đọc bài đăng này trên blog về phát triển cục bộ bằng các hàm của Cloud Run để tìm hiểu cách phát triển và kiểm thử hàm Cloud Run trong môi trường phát triển cục bộ.

Nội dung đã đề cập

  • Cách định cấu hình quy trình xác thực trên một hàm Cloud Run và xác minh rằng quy trình xác thực đã được định cấu hình đúng cách
  • Gọi một hàm đã xác thực từ môi trường phát triển cục bộ bằng cách cung cấp mã thông báo cho danh tính gcloud của bạn
  • Cách tạo tài khoản dịch vụ và cấp cho tài khoản đó vai trò phù hợp để gọi một hàm
  • Cách mạo danh một dịch vụ từ môi trường phát triển cục bộ có các vai trò thích hợp để gọi một hàm

8. Dọn dẹp

Để tránh bị tính phí ngoài ý muốn (ví dụ: Cloud Function này vô tình được gọi nhiều lần hơn hạn mức gọi hàm Cloud Run hằng tháng của bạn trong cấp miễn phí), bạn có thể xoá Cloud Function hoặc xoá dự án mà bạn đã tạo ở Bước 2.

Để ngừng mạo danh tài khoản dịch vụ, bạn có thể đăng nhập lại bằng danh tính của mình:

gcloud auth application-default login

Để xoá hàm Cloud Run, hãy chuyển đến Cloud Console của hàm Cloud Run tại https://console.cloud.google.com/functions/. Đảm bảo rằng dự án bạn đã tạo ở bước 2 là dự án hiện được chọn.

Chọn my-authenticated-function mà bạn đã triển khai trước đó. Sau đó, nhấn vào Xoá.

Nếu chọn xoá toàn bộ dự án, bạn có thể truy cập vào https://console.cloud.google.com/cloud-resource-manager, chọn dự án bạn đã tạo ở Bước 2 rồi chọn Xoá. Nếu xoá dự án, bạn sẽ cần thay đổi dự án trong Cloud SDK. Bạn có thể xem danh sách tất cả các dự án có sẵn bằng cách chạy gcloud projects list.