שימוש ב-Secret Manager עם Python

1. סקירה כללית

ב-Codelab הזה, אתם נתמקד בשימוש ב-Secret Manager ב-Python.

בעזרת Secret Manager אפשר לאחסן סודות, לנהל אותם ולגשת אליהם כ-blobs בינאריים או כמחרוזות טקסט. אם יש לכם את ההרשאות המתאימות, תוכלו לראות את תוכן הסוד.

Secret Manager מתאים לאחסון פרטי הגדרות כמו סיסמאות למסדי נתונים, מפתחות API או אישורי TLS שנדרשים על ידי אפליקציה בזמן ריצה.

מה תלמדו

  • איך משתמשים ב-Cloud Shell?
  • איך מתקינים את ספריית הלקוח של Secret Manager ל-Python
  • איך יוצרים סודות ולגשת אליהם באמצעות ספריית הלקוח של Python
  • איך ניגשים לסודות ב-Cloud Functions באמצעות ספריית הלקוח של Python

מה צריך להכין

  • פרויקט ב-Google Cloud
  • דפדפן, כמו Chrome או Firefox
  • היכרות עם Python 3

סקר

איך תשתמשו במדריך הזה?

לקריאה בלבד לקרוא אותו ולבצע את התרגילים

איזה דירוג מגיע לדעתך לחוויה שלך עם Python?

מתחילים בינונית בקיאים

איזה דירוג מגיע לדעתך לחוויית השימוש שלך בשירותי Google Cloud?

מתחילים בינונית בקיאים

2. הגדרה ודרישות

הגדרת סביבה בקצב עצמאי

  1. נכנסים למסוף Google Cloud ויוצרים פרויקט חדש או עושים שימוש חוזר בפרויקט קיים. אם אין לכם עדיין חשבון Gmail או חשבון Google Workspace, עליכם ליצור חשבון.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Project name הוא השם המוצג של המשתתפים בפרויקט. זו מחרוזת תווים שלא משמשת את Google APIs. אפשר לעדכן אותו בכל שלב.
  • Project ID חייב להיות ייחודי בכל הפרויקטים ב-Google Cloud ואי אפשר לשנות אותו (אי אפשר לשנות אותו אחרי שמגדירים אותו). מסוף Cloud יוצר מחרוזת ייחודית באופן אוטומטי; בדרך כלל לא מעניין אותך מה זה. ברוב ה-Codelabs תצטרכו להפנות אל מזהה הפרויקט (בדרך כלל הוא מזוהה כ-PROJECT_ID). אם המזהה שנוצר לא מוצא חן בעיניך, יש לך אפשרות ליצור מזהה אקראי אחר. לחלופין, אפשר לנסות תבנית משלך ולבדוק אם היא זמינה. לא ניתן לשנות אותו אחרי השלב הזה, והוא יישאר למשך הפרויקט.
  • לידיעתך, יש ערך שלישי – Project Number (מספר פרויקט), שחלק מממשקי ה-API משתמשים בו. מידע נוסף על כל שלושת הערכים האלה זמין במסמכי התיעוד.
  1. בשלב הבא צריך להפעיל את החיוב במסוף Cloud כדי להשתמש במשאבים או בממשקי API של Cloud. מעבר ב-Codelab הזה לא אמור לעלות הרבה, אם בכלל. כדי להשבית את המשאבים ולא לצבור חיובים מעבר למדריך הזה, אתם יכולים למחוק את המשאבים שיצרתם או למחוק את הפרויקט כולו. משתמשים חדשים ב-Google Cloud זכאים להצטרף לתוכנית תקופת ניסיון בחינם בשווי 1,200 ש"ח.

הפעלת Cloud Shell

אומנם אפשר להפעיל את Google Cloud מרחוק מהמחשב הנייד, אבל ב-Codelab הזה משתמשים ב-Google Cloud Shell, סביבת שורת הפקודה שפועלת ב-Cloud.

הפעלת Cloud Shell

  1. במסוף Cloud, לוחצים על Activate Cloud Shell 853e55310c205094.png.

55efc1aaa7a4d3ad.png

אם לא הפעלתם את Cloud Shell בעבר, יוצג לכם מסך ביניים (בחלק הנגלל) שמתאר מהו. במקרה כזה, לוחצים על המשך (וזה לא יקרה שוב). כך נראה המסך החד-פעמי:

9c92662c6a846a5c.png

ההקצאה וההתחברות ל-Cloud Shell נמשכת כמה דקות.

9f0e51b578fecce5.png

במכונה הווירטואלית הזו משולבת כל כלי הפיתוח שדרושים לכם. יש בה ספריית בית בנפח מתמיד של 5GB והיא פועלת ב-Google Cloud, מה שמשפר משמעותית את ביצועי הרשת והאימות. אם לא את כולן, ניתן לבצע חלק גדול מהעבודה ב-Codelab הזה באמצעות דפדפן או Chromebook.

אחרי ההתחברות ל-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. הפעלת Secret Manager API

לפני שמתחילים להשתמש ב-Secret Manager API, צריך להפעיל את ה-API. ב-Cloud Shell, אפשר להפעיל את ה-API באמצעות הפקודה הבאה:

gcloud services enable secretmanager.googleapis.com

הפלט אמור להיראות כך:

Operation "operations/acf.cc11852d-40af-47ad-9d59-477a12847c9e" finished successfully.

4. התקנת ספריית הלקוח של Secret Manager ל-Python

מתקינים את ספריית הלקוח של Secret Manager:

pip3 install --user google-cloud-secret-manager==2.10.0

5. התחלת השימוש ב-Python אינטראקטיבי

כחלק מהמדריך הזה נשתמש במפענח אינטראקטיבי של Python בשם IPython, שמותקן מראש ב-Cloud Shell. כדי להתחיל סשן מריצים את ipython ב-Cloud Shell:

ipython

אתם אמורים לראות משהו כזה:

Python 3.9.2 (default, Feb 28 2021, 17:03:44)
Type 'copyright', 'credits' or 'license' for more information
IPython 8.3.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]:

6. יצירת סודות

סוד מכיל גרסה סודית אחת או יותר. אפשר ליצור אותם באמצעות שורת הפקודה gcloud, אבל אפשר ליצור אותם גם באמצעות Python.

כדי להשתמש בסוד, צריך קודם ליצור את הסוד ולציין בו את השם שלו. לאחר מכן מוסיפים גרסה של הסוד, שתהיה הערך שלו.

מגדירים את מזהה הפרויקט ב-IPython:

PROJECT_ID = "<PROJECT_ID>"

יצירת סוד

מעתיקים את הקוד הבא לסשן IPython:

from google.cloud import secretmanager

def create_secret(secret_id):
    # Create the Secret Manager client.
    client = secretmanager.SecretManagerServiceClient()

    # Build the resource name of the parent project.
    parent = f"projects/{PROJECT_ID}"

    # Build a dict of settings for the secret
    secret = {'replication': {'automatic': {}}}

    # Create the secret
    response = client.create_secret(secret_id=secret_id, parent=parent, secret=secret)

    # Print the new secret name.
    print(f'Created secret: {response.name}')   

קוראים לפונקציה כדי ליצור סוד חדש בשם my_secret_value:

create_secret("my_secret_value")

הפלט הבא אמור להתקבל:

Created secret: projects/<PROJECT_NUM>/secrets/my_secret_value

הוספת גרסה סודית

עכשיו, כשהסוד קיים, אפשר ליצור גרסה כדי להקצות לו ערך.

מעתיקים את הקוד הבא לסשן IPython:

def add_secret_version(secret_id, payload):
    # Create the Secret Manager client.
    client = secretmanager.SecretManagerServiceClient()

    # Build the resource name of the parent secret.
    parent = f"projects/{PROJECT_ID}/secrets/{secret_id}"

    # Convert the string payload into a bytes. This step can be omitted if you
    # pass in bytes instead of a str for the payload argument.
    payload = payload.encode('UTF-8')

    # Add the secret version.
    response = client.add_secret_version(parent=parent, payload={'data': payload})

    # Print the new secret version name.
    print(f'Added secret version: {response.name}')   

קוראים לפונקציה כדי ליצור גרסה חדשה של סוד:

add_secret_version("my_secret_value", "Hello Secret Manager")

הפלט הבא אמור להתקבל:

Added secret version: projects/<PROJECT_NUM>/secrets/my_secret_value/versions/1

לסודות יכולות להיות כמה גרסאות. קוראים לפונקציה שוב עם ערך אחר:

add_secret_version("my_secret_value", "Hello Again, Secret Manager")

הפלט הבא אמור להתקבל:

Added secret version: projects/<PROJECT_NUM>/secrets/my_secret_value/versions/2

שים לב שהגרסה החדשה של הסוד שלנו ארוכה משמעותית מזו של הגרסה המקורית. המאפיין הזה יוזכר מאוחר יותר.

7. גישה לסודות

גישה לגרסה סודית מחזירה את התוכן של הסוד, וגם מטא-נתונים נוספים לגבי גרסת הסוד. כשאתם ניגשים לגרסה סודית, תוכלו לציין גרסה ספציפית או לבקש את הגרסה העדכנית ביותר על ידי ציון הגרסה העדכנית ביותר.

יש לשמור על סודות. לאחסן פרטי כניסה למסד הנתונים כסודות ולאחר מכן להשתמש בהם כדי לאמת או לאחסן אישורים ולהשתמש בהם. אבל אל תדפיסו את הסודות שלכם ישירות, כי כך הם נוגדים את המטרה של שמירת הסודות.

אתם עומדים לבצע פעולות על הסודות שלנו, להעריך את הערך שלו בלי להדפיס אותו ישירות. במקום זאת, מדפיסים גיבוב של ערך הסוד.

מעתיקים את הקוד הבא לסשן IPython:

def access_secret_version(secret_id, version_id="latest"):
    # Create the Secret Manager client.
    client = secretmanager.SecretManagerServiceClient()

    # Build the resource name of the secret version.
    name = f"projects/{PROJECT_ID}/secrets/{secret_id}/versions/{version_id}"

    # Access the secret version.
    response = client.access_secret_version(name=name)

    # Return the decoded payload.
    return response.payload.data.decode('UTF-8')
    
import hashlib

def secret_hash(secret_value): 
  # return the sha224 hash of the secret value
  return hashlib.sha224(bytes(secret_value, "utf-8")).hexdigest()

קוראים לפונקציה כדי לאחזר את הסוד כגיבוב של הערך:

secret_hash(access_secret_version("my_secret_value"))

הפלט אמור להיראות כך:

83f8a4edb555cde4271029354395c9f4b7d79706ffa90c746e021d11

מכיוון שלא ציינת גרסה, הערך האחרון אוחזר.

קוראים לפונקציה ומוסיפה את מספר הגרסה הצפוי כדי לוודא:

secret_hash(access_secret_version("my_secret_value", version_id=2))

הפלט אמור להיראות כמו הפקודה האחרונה:

83f8a4edb555cde4271029354395c9f4b7d79706ffa90c746e021d11

קוראים לפונקציה שוב, אך הפעם מציינים את הגרסה הראשונה:

secret_hash(access_secret_version("my_secret_value", version_id=1))

הפעם אמור להופיע גיבוב שונה, שמציין פלט שונה:

9a3fc8b809ddc611c82aee950c636c7557e220893560ec2c1eeeb177

8. שימוש ב-Secret Manager עם Cloud Functions

אתם יכולים להשתמש בסודות בהרבה חלקים ב-Google Cloud. בחלק הזה נתמקד ב-Cloud Functions, שירות המחשוב ללא שרת (serverless) של Google שמבוסס על אירועים.

אם אתם רוצים להשתמש ב-Python ב-Cloud Functions, תוכלו להיעזר ב-HTTP Google Cloud Functions ב-Python Codelab.

סוגרים את IPython על ידי שליחת קריאה לפונקציה exit:

exit

אתם אמורים לחזור ל-Cloud Shell:

yourname@cloudshell:~ (<PROJECT_ID>)$

כדי להתחיל להשתמש ב-Cloud Functions API, צריך להפעיל את ה-API. ב-Cloud Shell, אפשר להפעיל את ה-API באמצעות הפקודה הבאה:

gcloud services enable cloudfunctions.googleapis.com cloudbuild.googleapis.com

יוצרים תיקייה חדשה כדי ליצור את הפונקציה, ויוצרים קבצים ריקים שאפשר לכתוב בהם:

mkdir secret-manager-api-demo
cd secret-manager-api-demo
touch main.py
touch requirements.txt

פותחים את עורך הקוד מהצד השמאלי העליון של Cloud Shell:

7651a97c51e11a24.png

עוברים לקובץ main.py שבתוך התיקייה secret-manager-api-demo. זה המקום שבו מוסיפים את כל הקוד.

9. כתיבת פונקציה של Cloud Functions כדי לגשת לסודות

אמנם אחסון ואחזור של ערכים סודיים משורת הפקודה או מטרמינל IPython הם שימושיים, אבל הרבה יותר שימושי לגשת לסודות האלה בתוך פונקציה.

באמצעות הפונקציה access_secret_version שיצרתם קודם, תוכלו להשתמש בה כבסיס לפונקציה של Cloud Functions.

מעתיקים את הקוד הבא לקובץ main.py:

main.py

import os

from google.cloud import secretmanager

project_id = os.environ["PROJECT_ID"]

client = secretmanager.SecretManagerServiceClient()
name = f"projects/{project_id}/secrets/my_secret_value/versions/latest"
response = client.access_secret_version(name=name)
my_secret_value = response.payload.data.decode("UTF-8")


def secret_hello(request):
    if "Again" in my_secret_value:
        return "We meet again!\n"

    return "Hello there.\n"

לפני שתוכלו לפרוס את הפונקציה, עליכם להשלים את הגדרת הסביבה. לשם כך צריך להגדיר את יחסי התלות של הפונקציה.

יוצרים קובץ חדש בשם requirements.txt ומוסיפים אליו את החבילה google-cloud-secret-manager:

requirements.txt

google-cloud-secret-manager==2.10.0

עכשיו אמורה להיות לך תיקייה שמכילה רק main.py ו-requirements.txt.

מתן גישה לסוד

כדי לפרוס את הפונקציה, עליכם לאפשר ל-Cloud Functions לגשת לסוד שלכם.

חוזרים אל הטרמינל:

c5b686edf94b5222.png

כדי לגשת לסוד, מעניקים גישה לחשבון השירות של Cloud Functions:

export PROJECT_ID=$(gcloud config get-value core/project)

gcloud secrets add-iam-policy-binding my_secret_value \
    --role roles/secretmanager.secretAccessor \
    --member serviceAccount:${PROJECT_ID}@appspot.gserviceaccount.com

הפלט הבא אמור להתקבל:

Updated IAM policy for secret [my_secret_value].
bindings:
- members:
  - serviceAccount:<PROJECT_ID>@appspot.gserviceaccount.com
  role: roles/secretmanager.secretAccessor
etag: BwWiRUt2oB4=
version: 1

10. פריסת הפונקציה של Cloud Functions

בהתאם להגדרות בקטעים הקודמים, עכשיו תוכלו לפרוס ולבדוק את הפונקציה של Cloud Functions.

בתוך התיקייה שמכילה רק את שני הקבצים שיצרתם, פורסים את הפונקציה:

gcloud functions deploy secret_hello \
    --runtime python39 \
    --set-env-vars PROJECT_ID=${PROJECT_ID} \
    --trigger-http \
    --allow-unauthenticated

הפלט הבא אמור להופיע (קטוע):

Deploying function (may take a while - up to 2 minutes)...done.

...

entryPoint: secret_hello
httpsTrigger:
  url: https://<REGION>-<PROJECT_ID>.cloudfunctions.net/secret_hello
...
status: ACTIVE
...

מאחזרים את כתובת ה-URL של הפונקציה (מטא-נתונים של httpsTrigger.url) באמצעות הפקודה הבאה:

FUNCTION_URL=$(gcloud functions describe secret_hello --format 'value(httpsTrigger.url)')

עכשיו אפשר לבדוק את הפונקציה עם הערך המוחזר הצפוי. כדי לעשות את זה, שולחים קריאה לפונקציה:

curl $FUNCTION_URL

הפלט הבא אמור להתקבל:

We meet again!

הפונקציה הזו מפנה לגרסה העדכנית ביותר של הסוד, שהוגדרה להכיל את המחרוזת 'Again', ולכן הפונקציה פועלת כצפוי.

11. מעולה!

למדת איך להשתמש ב-Secret Manager API באמצעות Python!

הסרת המשאבים

כדי להימנע מצבירת חיובים בחשבון Google Cloud על המשאבים שבהם השתמשתם במדריך הזה:

  • במסוף Cloud, עוברים לדף Manage resources.
  • ברשימת הפרויקטים, בוחרים את הפרויקט הרלוונטי ולוחצים על מחיקה.
  • כדי למחוק את הפרויקט, כותבים את מזהה הפרויקט בתיבת הדו-שיח ולוחצים על Shut down.

מידע נוסף

רישיון

היצירה הזו בשימוש ברישיון Creative Commons Attribution 2.0 גנרי.