Использование Secret Manager с Python

1. Обзор

В этом практическом занятии вы сосредоточитесь на использовании Secret Manager в Python.

Secret Manager позволяет хранить, управлять и получать доступ к секретам в виде двоичных данных или текстовых строк. При наличии соответствующих прав доступа вы можете просматривать содержимое секрета.

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

  • Название проекта — это отображаемое имя участников данного проекта. Это строка символов, не используемая API Google. Вы можете изменить её в любое время.
  • Идентификатор проекта должен быть уникальным для всех проектов Google Cloud и неизменяемым (его нельзя изменить после установки). Консоль Cloud автоматически генерирует уникальную строку; обычно вам неважно, какая она. В большинстве практических заданий вам потребуется указать идентификатор проекта (обычно он обозначается как PROJECT_ID ). Если сгенерированный идентификатор вас не устраивает, вы можете сгенерировать другой случайный идентификатор. В качестве альтернативы вы можете попробовать свой собственный и посмотреть, доступен ли он. После этого шага его нельзя изменить, и он останется неизменным на протяжении всего проекта.
  • К вашему сведению, существует третье значение — номер проекта , который используется некоторыми API. Подробнее обо всех трех значениях можно узнать в документации .
  1. Далее вам потребуется включить оплату в консоли Cloud для использования ресурсов/API Cloud. Выполнение этого практического задания не должно стоить дорого, если вообще что-либо. Чтобы отключить ресурсы и избежать дополнительных расходов после завершения этого урока, вы можете удалить созданные ресурсы или удалить весь проект. Новые пользователи Google Cloud имеют право на бесплатную пробную версию стоимостью 300 долларов США .

Запустить Cloud Shell

Хотя Google Cloud можно управлять удаленно с ноутбука, в этом практическом занятии вы будете использовать Google Cloud Shell — среду командной строки, работающую в облаке.

Активировать Cloud Shell

  1. В консоли Cloud нажмите «Активировать Cloud Shell» . 853e55310c205094.png .

55efc1aaa7a4d3ad.png

Если вы никогда раньше не запускали Cloud Shell, вам будет показан промежуточный экран (внизу), описывающий его назначение. В этом случае нажмите «Продолжить» (и вы больше никогда его не увидите). Вот как выглядит этот одноразовый экран:

9c92662c6a846a5c.png

Подготовка и подключение к Cloud Shell займут всего несколько минут.

9f0e51b578fecce5.png

Эта виртуальная машина оснащена всеми необходимыми инструментами разработки. Она предоставляет постоянный домашний каталог размером 5 ГБ и работает в облаке Google, что значительно повышает производительность сети и аутентификацию. Большая часть, если не вся, работа в этом практическом задании может быть выполнена с помощью обычного браузера или вашего 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. Включите API менеджера секретов.

Прежде чем начать использовать API Secret Manager, необходимо его включить. В Cloud Shell это можно сделать с помощью следующей команды:

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. Получение доступа к секретам

При доступе к секретной версии возвращается её содержимое, а также дополнительные метаданные о ней. При доступе к секретной версии вы можете либо указать конкретную версию, либо запросить последнюю версию, указав "latest".

Секреты следует хранить в секрете. Храните учетные данные базы данных в качестве секретов, а затем используйте их для аутентификации, или храните сертификаты и используйте их; но не распечатывайте свои секреты напрямую, так как это противоречит цели их сохранения в секрете.

Вы будете выполнять операции над нашими секретами, оценивая их значение, не выводя его напрямую на экран. Вместо этого вы будете выводить хеш значения секрета.

Скопируйте следующий код в свою сессию 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 с облачными функциями

В Google Cloud можно использовать секретные данные во многих его частях. В этом разделе вы сосредоточитесь на Cloud Functions, бессерверном вычислительном решении от Google, основанном на событиях.

Если вас интересует использование Python в Cloud Functions, вы можете ознакомиться с инструкцией по применению HTTP Google Cloud Functions в Python на Codelab .

Закройте IPython, вызвав функцию exit :

exit

Вы должны вернуться в свою оболочку Cloud Shell:

yourname@cloudshell:~ (<PROJECT_ID>)$

Прежде чем начать использовать API Cloud Functions, необходимо его включить. В Cloud Shell это можно сделать с помощью следующей команды:

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. Написание облачной функции для доступа к секретам.

Хотя хранение и извлечение секретных значений из командной строки или терминала IPython полезно, гораздо удобнее иметь возможность получать доступ к этим секретам внутри функции.

Используя созданную ранее функцию access_secret_version , вы можете использовать её в качестве основы для вашей облачной функции.

Скопируйте следующий код в файл 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. Развертывание вашей облачной функции

Учитывая настройки, выполненные в предыдущих разделах, теперь вы можете развернуть и протестировать свою облачную функцию.

В папке, содержащей только два созданных вами файла, разверните функцию:

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. Поздравляем!

Вы научились использовать API Secret Manager с помощью Python!

Уборка

Чтобы избежать списания средств с вашего аккаунта Google Cloud за ресурсы, использованные в этом руководстве:

  • В консоли Cloud перейдите на страницу «Управление ресурсами» .
  • В списке проектов выберите свой проект и нажмите «Удалить» .
  • В диалоговом окне введите идентификатор проекта, а затем нажмите «Завершить» , чтобы удалить проект.

Узнать больше

Лицензия

Данная работа распространяется под лицензией Creative Commons Attribution 2.0 Generic.