ดูวิธีเรียกใช้ Cloud Functions ที่ตรวจสอบสิทธิ์แล้ว

1. บทนำ

ภาพรวม

Cloud Functions เป็นโซลูชันประมวลผลที่ใช้งานง่ายสำหรับนักพัฒนาแอปในการสร้างฟังก์ชันแบบสแตนด์อโลนวัตถุประสงค์เดียวที่จะทริกเกอร์โดยใช้ HTTPS หรือตอบสนองต่อ CloudEvents ได้โดยไม่ต้องจัดการเซิร์ฟเวอร์หรือสภาพแวดล้อมรันไทม์

วิธีหลักในการควบคุมคำขอไปยัง Cloud Functions มี 2 วิธี ได้แก่ การรักษาการเข้าถึงตามข้อมูลระบุตัวตนและการรักษาความปลอดภัยการเข้าถึงโดยใช้การควบคุมการเข้าถึงตามเครือข่าย Codelab นี้มุ่งเน้นไปที่วิธีการแรกและอธิบายสถานการณ์ต่างๆ 3 อย่างสำหรับการรักษาความปลอดภัยการเข้าถึงตามข้อมูลระบุตัวตนเพื่อเรียกใช้ฟังก์ชัน ดังนี้

  1. ใช้โทเค็นข้อมูลประจำตัว gcloud เพื่อเรียกใช้ฟังก์ชันสำหรับการพัฒนาภายในและ วัตถุประสงค์ในการทดสอบ
  2. แอบอ้างเป็นบัญชีบริการเมื่อพัฒนาและทดสอบภายในเพื่อใช้ข้อมูลเข้าสู่ระบบเหมือนกับเวอร์ชันที่ใช้งานจริง
  3. ใช้ไลบรารีของไคลเอ็นต์ Google เพื่อจัดการการตรวจสอบสิทธิ์กับ Google Cloud APIs เช่น เมื่อบริการจำเป็นต้องเรียกใช้ฟังก์ชัน

สิ่งที่คุณจะได้เรียนรู้

  • วิธีกำหนดค่าการตรวจสอบสิทธิ์ใน Cloud Function และยืนยันว่ามีการกำหนดค่าการตรวจสอบสิทธิ์อย่างถูกต้องแล้ว
  • เรียกใช้ฟังก์ชันที่ตรวจสอบสิทธิ์แล้วจากสภาพแวดล้อมการพัฒนาในเครื่องโดยมอบโทเค็นสำหรับข้อมูลประจำตัว gcloud ของคุณ
  • วิธีสร้างบัญชีบริการและมอบบทบาทที่เหมาะสมในการเรียกใช้ฟังก์ชัน
  • วิธีเลียนแบบบริการจากสภาพแวดล้อมการพัฒนาในเครื่องที่มีบทบาทที่เหมาะสมในการเรียกใช้ฟังก์ชัน

2. การตั้งค่าและข้อกำหนด

ข้อกำหนดเบื้องต้น

  • คุณเข้าสู่ระบบ Cloud Console แล้ว
  • ก่อนหน้านี้คุณได้ทำให้ Cloud Function รุ่นที่ 2 ทริกเกอร์ HTTP ใช้งานได้
  • (ไม่บังคับ) สำหรับสถานการณ์ที่ 3 Codelab นี้ใช้ Node.js และ npm เป็นตัวอย่าง แต่คุณสามารถใช้รันไทม์ใดก็ได้ที่ไลบรารีของไคลเอ็นต์ Google Auth รองรับ

เปิดใช้งาน Cloud Shell

  1. คลิกเปิดใช้งาน Cloud Shell 853e55310c205094.png จาก Cloud Console

55efc1aaa7a4d3ad.png

หากเริ่มต้นใช้งาน Cloud Shell เป็นครั้งแรก คุณจะเห็นหน้าจอตรงกลางที่อธิบายว่านี่คืออะไร หากระบบแสดงหน้าจอตรงกลาง ให้คลิกต่อไป

9c92662c6a846a5c.png

การจัดสรรและเชื่อมต่อกับ Cloud Shell ใช้เวลาเพียงไม่กี่นาที

9f0e51b578fecce5.png

เครื่องเสมือนนี้โหลดด้วยเครื่องมือการพัฒนาทั้งหมดที่จำเป็น โดยมีไดเรกทอรีหลักขนาด 5 GB ถาวรและทำงานใน Google Cloud ซึ่งช่วยเพิ่มประสิทธิภาพของเครือข่ายและการตรวจสอบสิทธิ์ได้อย่างมาก งานส่วนใหญ่ใน Codelab นี้สามารถทำได้โดยใช้เบราว์เซอร์

เมื่อเชื่อมต่อกับ Cloud Shell แล้ว คุณควรเห็นข้อความตรวจสอบสิทธิ์และโปรเจ็กต์ได้รับการตั้งค่าเป็นรหัสโปรเจ็กต์แล้ว

  1. เรียกใช้คำสั่งต่อไปนี้ใน Cloud Shell เพื่อยืนยันว่าคุณได้รับการตรวจสอบสิทธิ์แล้ว
gcloud auth list

เอาต์พุตจากคำสั่ง

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

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. เรียกใช้คำสั่งต่อไปนี้ใน Cloud Shell เพื่อยืนยันว่าคำสั่ง gcloud รู้เกี่ยวกับโปรเจ็กต์ของคุณ
gcloud config list project

เอาต์พุตจากคำสั่ง

[core]
project = <PROJECT_ID>

หากไม่ใช่ ให้ตั้งคำสั่งด้วยคำสั่งนี้

gcloud config set project <PROJECT_ID>

เอาต์พุตจากคำสั่ง

Updated property [core/project].

3. สร้างและทดสอบ Cloud Function ที่ตรวจสอบสิทธิ์แล้ว

Codelab นี้ทำตามวิธีการเดียวกันกับการเริ่มต้นใช้งานคอนโซลอย่างรวดเร็วสำหรับ Cloud Functions โดยมีข้อยกเว้นที่สำคัญข้อเดียวคือ ฟังก์ชันจะต้องมีการตรวจสอบสิทธิ์

การต้องมีการตรวจสอบสิทธิ์หมายความว่าหลักการเรียกใช้ฟังก์ชันต้องมีบทบาทผู้เรียกใช้ Cloud Functions (และผู้เรียกใช้ Cloud Run สำหรับรุ่นที่ 2) ไม่เช่นนั้น ฟังก์ชันจะแสดงข้อผิดพลาด 403 Forbidden Codelab นี้จะแสดงวิธีมอบบทบาทผู้เรียกใช้ที่เหมาะสมให้กับหลักการ

สร้างฟังก์ชันที่ตรวจสอบสิทธิ์แล้ว

ขั้นตอนการใช้ Cloud Console มีดังนี้

  1. ไปที่หน้าภาพรวมฟังก์ชันระบบคลาวด์ แล้วคลิกสร้างฟังก์ชัน
  2. ในส่วนตัวเลือกสภาพแวดล้อม ให้เลือกรุ่นที่ 2
  3. ตั้งชื่อฟังก์ชัน my-authenticated-function
  4. ในช่องการตรวจสอบสิทธิ์ ให้ใช้ค่าเริ่มต้นเป็นต้องมีการตรวจสอบสิทธิ์

936eee0d5930d12b.png

  1. คลิกถัดไป
  2. คุณเลือกภาษาสำหรับ Codelab นี้ได้
  3. จากนั้นคลิกทำให้ใช้งานได้

การทำให้ฟังก์ชันใช้งานได้จะใช้เวลาประมาณ 1 นาที

ตั้งค่าตัวแปรสภาพแวดล้อมภายในสำหรับคำสั่ง gcloud แบบง่าย

ก่อนอื่น คุณจะต้องสร้างตัวแปรสภาพแวดล้อม 2-3 รายการเพื่อให้คำสั่ง gcloud ที่ใช้ใน Codelab นี้อ่านได้ง่ายขึ้น

คุณจะต้องระบุภูมิภาคสำหรับ Function ของคุณ ตัวอย่างนี้ใช้ us-central1

REGION="us-central1"

จากนั้นคุณจะบันทึก URL ฟังก์ชันเป็นตัวแปรสภาพแวดล้อมไว้ใช้ในภายหลังได้

PROJECT_ID=$(gcloud config get-value project)
FUNCTION_URL="$(gcloud functions describe my-authenticated-function --gen2 --region us-central1 --format='get(serviceConfig.uri)')"

ยืนยันว่าฟังก์ชันต้องมีการตรวจสอบสิทธิ์โดยพยายามเรียกใช้เป็นผู้โทรที่ไม่ระบุตัวตน

คุณจะเรียกใช้ฟังก์ชันโดยไม่มีการตรวจสอบสิทธิ์เพื่อยืนยันว่าคุณได้รับข้อผิดพลาด 403 ที่คาดไว้

จากบรรทัดคำสั่ง ให้เรียกใช้คำสั่ง curl ต่อไปนี้

curl $FUNCTION_URL

คุณจะเห็นผลลัพธ์ต่อไปนี้

<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>

ตอนนี้คุณพร้อมที่จะดูสถานการณ์ 3 อย่างที่สามารถเรียกใช้ฟังก์ชันด้วยการระบุการตรวจสอบสิทธิ์

4. สถานการณ์ที่ 1: ใช้โทเค็นข้อมูลประจำตัว gcloud

ในฐานะนักพัฒนาซอฟต์แวร์ คุณจะต้องหาวิธีทดสอบฟังก์ชันขณะพัฒนาฟังก์ชันในเครื่อง ในส่วนนี้ คุณจะต้องทำการทดสอบอย่างรวดเร็วเพื่อยืนยันว่าฟังก์ชันนั้นได้รับการตรวจสอบสิทธิ์อย่างถูกต้องโดยใช้ข้อมูลประจำตัวของคุณเอง

ยืนยันว่าคุณได้รับการตรวจสอบสิทธิ์โดยใช้ gcloud โดยเรียกใช้คำสั่งต่อไปนี้

gcloud auth list

คุณจะเห็นเครื่องหมายดอกจันอยู่ข้างข้อมูลประจำตัวที่ใช้งานอยู่ ตัวอย่างเช่น

Credentialed Accounts
ACTIVE  ACCOUNT

*       <my_account>@<my_domain.com>

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

เมื่อยืนยันแล้วว่าคุณใช้ข้อมูลประจำตัวที่ถูกต้อง คุณจะบันทึกอีเมลของบัญชีลงในตัวแปรสภาพแวดล้อม

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

ดูข้อมูลเพิ่มเติมเกี่ยวกับการตั้งค่า gcloud init และ gcloud authlogin ได้ในเอกสาร

ถัดไป ให้เรียกใช้ฟังก์ชันแล้วส่งโทเค็นข้อมูลประจำตัวของคุณ

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

ตอนนี้คุณจะเห็นผลลัพธ์:

Hello World!

การแก้ปัญหา

หากได้รับข้อผิดพลาด 403 Forbidden โปรดตรวจสอบว่าตัวตนของคุณมีบทบาทผู้เรียกใช้ Cloud Functions หรือบทบาทผู้เรียกใช้ Cloud Run สำหรับฟังก์ชันรุ่นที่ 2 คุณใช้คอนโซล IAM เพื่อยืนยันบทบาทที่กำหนดให้กับผู้ใช้หลักได้

แม้ว่าการใช้โทเค็นข้อมูลประจำตัวของคุณเองจะช่วยให้ทดสอบฟังก์ชันในระหว่างการพัฒนาได้อย่างรวดเร็ว แต่ผู้เรียกใช้ฟังก์ชันที่ได้รับการตรวจสอบสิทธิ์จะต้องมีบทบาทที่เหมาะสม ไม่เช่นนั้น ผู้โทรจะได้รับข้อผิดพลาด 403 Forbidden

คุณจะต้องปฏิบัติตามหลักของสิทธิ์ขั้นต่ำโดยการจำกัดจำนวนข้อมูลประจำตัวและบัญชีบริการที่มีบทบาทที่จะเรียกใช้ฟังก์ชัน

สร้างบัญชีบริการใหม่และมอบบทบาทที่จำเป็น

5. สถานการณ์ที่ 2: แอบอ้างบัญชีบริการ

ในสถานการณ์นี้ คุณจะแอบอ้างเป็นบุคคลอื่น (เช่น อ้างสิทธิ์ใน) บัญชีบริการเพื่อเรียกใช้ฟังก์ชันเมื่อพัฒนาและทดสอบภายใน เมื่อแอบอ้างเป็นบัญชีบริการ คุณจะทดสอบฟังก์ชันได้เหมือนกับที่ใช้ในเวอร์ชันที่ใช้งานจริง

การทำเช่นนี้จะไม่เพียงไม่เพียงยืนยันบทบาท แต่ยังทำตามหลักการให้สิทธิ์ขั้นต่ำโดยไม่ต้องมอบบทบาทผู้เรียกใช้ Cloud Function ให้กับข้อมูลประจำตัวอื่นๆ เพื่อการทดสอบภายในโดยเฉพาะด้วย

เพื่อจุดประสงค์ของ Codelab นี้ คุณจะสร้างบัญชีบริการใหม่ที่มีเฉพาะบทบาทในการเรียกใช้ฟังก์ชันที่คุณสร้างไว้ใน Codelab นี้

สร้างบัญชีบริการใหม่

ก่อนอื่น คุณจะต้องสร้างตัวแปรสภาพแวดล้อมเพิ่มเติม 2 รายการเพื่อแสดงบัญชีบริการที่ใช้ในคำสั่ง gcloud

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

ถัดไป คุณจะสร้างบัญชีบริการ

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

และมอบบทบาทผู้เรียกใช้ Cloud Function ให้กับบัญชีบริการ

gcloud functions add-iam-policy-binding my-authenticated-function \
  --region=us-central1 --gen2 \
  --member serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
  --role='roles/cloudfunctions.invoker'

เรียกใช้ฟังก์ชันโดยการแอบอ้างบัญชีบริการ

สำหรับกรณีนี้ คุณจะสวมบทบาทเป็นบัญชีบริการที่สร้างขึ้นใหม่ด้วยการรับโทเค็นรหัสของบัญชีดังกล่าว

เพิ่มบทบาทที่จำเป็นสำหรับการแอบอ้างเป็นบุคคลอื่น

สำหรับการแอบอ้างบัญชีบริการ บัญชีผู้ใช้ของคุณต้องมีบทบาทผู้สร้างโทเค็นบัญชีบริการ (roles/iam.serviceAccountTokenCreator) เพื่อสร้างโทเค็นรหัสสำหรับบัญชีบริการ

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

ใช้โทเค็นรหัสของบัญชีบริการ

ตอนนี้คุณจะเรียกใช้ฟังก์ชันได้โดยการส่งโทเค็นรหัสของบัญชีบริการ

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

และคุณจะเห็นข้อมูลต่อไปนี้

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. สถานการณ์ที่ 3: ใช้ไลบรารีของไคลเอ็นต์ Google

สำหรับส่วนสุดท้ายของ Codelab คุณจะต้องเรียกใช้บริการขนาดเล็กในเครื่องเพื่อสร้างโทเค็นรหัสสำหรับบัญชีบริการ จากนั้นเรียกใช้ฟังก์ชันแบบเป็นโปรแกรมโดยใช้ไลบรารีของไคลเอ็นต์ Google Auth และข้อมูลเข้าสู่ระบบเริ่มต้นของแอปพลิเคชัน (ADC) คุณสามารถอ่านเพิ่มเติมเกี่ยวกับไลบรารีของไคลเอ็นต์ Google ได้ในส่วนคำอธิบายไลบรารีของไคลเอ็นต์ของเอกสาร

การใช้ ADC มีความสำคัญอย่างยิ่งเมื่อคุณต้องการเขียนและทดสอบฟังก์ชันภายในเครื่อง (เช่น บนแล็ปท็อป ใน Cloud Shell ฯลฯ) ขณะโต้ตอบกับทรัพยากรอื่นๆ ของ Google Cloud (เช่น Cloud Storage, Vision API ฯลฯ) ในตัวอย่างนี้ คุณจะเห็นวิธีที่บริการหนึ่งๆ จะเรียกใช้ฟังก์ชันอื่นที่ต้องมีการตรวจสอบสิทธิ์ ดูข้อมูลเพิ่มเติมเกี่ยวกับ ADC และการพัฒนาภายในได้ที่บล็อกโพสต์วิธีพัฒนาและทดสอบ Cloud Functions ในเครื่อง | บล็อก Google Cloud

เรียกใช้คำสั่ง gcloud เพื่อแอบอ้างบัญชีบริการ

ADC จะค้นหาข้อมูลเข้าสู่ระบบโดยอัตโนมัติตามสภาพแวดล้อมของแอปพลิเคชัน และจะใช้ข้อมูลเข้าสู่ระบบเหล่านั้นเพื่อตรวจสอบสิทธิ์ Google Cloud API แฟล็ก –impersonate-service-account ช่วยให้คุณแอบอ้างเป็นบัญชีบริการได้ โดยใช้ข้อมูลระบุตัวตนของบัญชีนั้นในการตรวจสอบสิทธิ์กับ Google Cloud APIs

หากต้องการแอบอ้างเป็นบัญชีบริการ ให้เรียกใช้คำสั่งต่อไปนี้

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

ตอนนี้คุณกำลังเรียกใช้คำสั่ง gcloud เป็นบัญชีบริการนั้น แทนที่จะเป็นข้อมูลระบุตัวตนของคุณ

สร้างและเรียกใช้บริการเพื่อเรียกใช้ฟังก์ชันที่ตรวจสอบสิทธิ์แล้ว

รันไทม์แต่ละรายการจะมีไลบรารีของไคลเอ็นต์ Google Auth ของตนเองซึ่งคุณติดตั้งได้ Codelab นี้จะแนะนำวิธีสร้างและเรียกใช้แอป Node.js ในเครื่อง

ขั้นตอนสำหรับ Node.js มีดังนี้

  1. สร้างแอป Node.js ใหม่
npm init
  1. ติดตั้งไลบรารีของไคลเอ็นต์ Google Auth
npm install google-auth-library
  1. สร้างไฟล์ index.js
  2. ดึงข้อมูล URL ของ Cloud Function ซึ่งจะเพิ่มลงในโค้ดในขั้นตอนต่อไปนี้
echo $FUNCTION_URL
  1. เพิ่มโค้ดต่อไปนี้ลงในindex.js อย่าลืมเปลี่ยนตัวแปร targetAudience เป็น URL ของ Cloud Function

index.js

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

const targetAudience = '<YOUR-CLOUD-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. เรียกใช้แอป
node index.js

และคุณควรจะเห็นผลลัพธ์ " Hello World!"

การแก้ปัญหา

หากคุณเห็นข้อผิดพลาด Permissions "iam.serviceAccounts.getOpenIdToken" ถูกปฏิเสธในทรัพยากร (หรืออาจไม่มีอยู่) โปรดรอสักครู่เพื่อให้บทบาทผู้สร้างโทเค็นบัญชีบริการมีผล

หากคุณได้รับข้อผิดพลาด ไม่สามารถดึงข้อมูลโทเค็นรหัสในสภาพแวดล้อมนี้ ให้ใช้ GCE หรือตั้งค่าตัวแปรสภาพแวดล้อม GOOGLE_APPLICATION_CREDENTIALS เป็นไฟล์ JSON ของข้อมูลเข้าสู่ระบบของบัญชีบริการ คุณอาจลืมเรียกใช้คำสั่ง

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

7. ยินดีด้วย

ขอแสดงความยินดีที่เรียน Codelab จนจบ

เราขอแนะนำให้อ่านเอกสารเกี่ยวกับวิธีรักษาความปลอดภัยของ Cloud Functions

นอกจากนี้ เราขอแนะนำบล็อกโพสต์นี้เกี่ยวกับการพัฒนาภายในด้วยฟังก์ชันระบบคลาวด์ เพื่อดูวิธีพัฒนาและทดสอบ Cloud Function ในสภาพแวดล้อมของนักพัฒนาซอฟต์แวร์ภายใน

หัวข้อที่ครอบคลุม

  • วิธีกำหนดค่าการตรวจสอบสิทธิ์ใน Cloud Function และยืนยันว่ามีการกำหนดค่าการตรวจสอบสิทธิ์อย่างถูกต้องแล้ว
  • เรียกใช้ฟังก์ชันที่ตรวจสอบสิทธิ์แล้วจากสภาพแวดล้อมการพัฒนาในเครื่องโดยมอบโทเค็นสำหรับข้อมูลประจำตัว gcloud ของคุณ
  • วิธีสร้างบัญชีบริการและมอบบทบาทที่เหมาะสมในการเรียกใช้ฟังก์ชัน
  • วิธีเลียนแบบบริการจากสภาพแวดล้อมการพัฒนาในเครื่องที่มีบทบาทที่เหมาะสมในการเรียกใช้ฟังก์ชัน

8. ล้างข้อมูล

เพื่อหลีกเลี่ยงการเรียกเก็บเงินที่ไม่ตั้งใจ (เช่น มีการเรียกใช้ Cloud Function โดยไม่ได้ตั้งใจมากกว่าการจัดสรรการเรียกใช้ Cloud Function รายเดือนในรุ่นฟรี) คุณจะลบ Cloud Function หรือลบโปรเจ็กต์ที่สร้างไว้ในขั้นตอนที่ 2 ก็ได้

หากต้องการหยุดแอบอ้างบัญชีบริการ ให้เข้าสู่ระบบอีกครั้งโดยใช้ข้อมูลประจำตัวโดยทำดังนี้

gcloud auth application-default login

หากต้องการลบ Cloud Function ให้ไปที่ Cloud Function ใน Cloud Console ที่ https://console.cloud.google.com/functions/ ตรวจสอบว่าโปรเจ็กต์ที่คุณสร้างในขั้นตอนที่ 2 เป็นโปรเจ็กต์ที่เลือกไว้ในปัจจุบัน

เลือก my-authd-Function ที่คุณทำให้ใช้งานได้ก่อนหน้านี้ จากนั้นกดลบ

หากคุณเลือกที่จะลบทั้งโปรเจ็กต์ ให้ไปที่ https://console.cloud.google.com/cloud-resource-manager เลือกโปรเจ็กต์ที่คุณสร้างในขั้นตอนที่ 2 แล้วเลือกลบ หากลบโปรเจ็กต์ คุณจะต้องเปลี่ยนโปรเจ็กต์ใน Cloud SDK คุณสามารถดูรายการโปรเจ็กต์ที่ใช้ได้ทั้งหมดโดยเรียกใช้ gcloud projects list