Шифрование облачных функций с помощью ключей шифрования, управляемых клиентом (CMEK)

1. Введение

Обзор

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

Вы можете использовать управляемые клиентом ключи шифрования Cloud Key Management Service (CMEK) для защиты облачных функций и связанных с ними данных в состоянии покоя. Развертывание функции с помощью CMEK защищает связанные с ней данные с помощью ключа шифрования, который находится под вашим полным контролем. Этот тип шифрования позволяет удовлетворить требования соответствия в определенных отраслях, например финансовых услугах. Поскольку ключ принадлежит вам и не контролируется Google, никто (включая вас) не сможет получить доступ к данным, защищенным этими ключами шифрования, когда ключи отключены или уничтожены.

Для облачных функций CMEK шифрует следующее:

  • Исходный код функции, загруженный для развертывания и сохраненный Google в облачном хранилище, используется в процессе сборки.
  • Результаты процесса сборки функции, включая образ контейнера, созданный на основе исходного кода функции, каждый развернутый экземпляр функции.
  • Неактивные данные для внутренних каналов передачи событий (только 1-го поколения).

Более подробную информацию о том, какие данные шифруются, вы можете найти в документации Cloud Function CMEK .

Что ты построишь

В этой лаборатории кода показано, как развернуть облачную функцию (1-го или 2-го поколения), зашифрованную с помощью CMEK. В этой лаборатории кода для демонстрационных целей используется общедоступная облачная функция, то есть функция, не требующая аутентификации. Вы можете вызвать функцию с поддержкой CMEK, прошедшую проверку подлинности, как и любую другую облачную функцию, требующую аутентификации.

Что вы узнаете

  • Как создать ключ CMEK на существующей симметричной связке ключей
  • Как создать репозиторий реестра артефактов
  • Как настроить CMEK в облачной функции как для 1-го, так и для 2-го поколения

2. Настройка и требования

Предварительные условия

  • Вы вошли в облачную консоль
  • Ранее вы развернули облачную функцию, активируемую HTTP (чтобы убедиться, что у вас включены соответствующие роли и API).

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

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

55efc1aaa7a4d3ad.png

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

9c92662c6a846a5c.png

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

9f0e51b578fecce5.png

Эта виртуальная машина загружена всеми необходимыми инструментами разработки. Он предлагает постоянный домашний каталог объемом 5 ГБ и работает в Google Cloud, что значительно повышает производительность сети и аутентификацию. Большую часть, если не всю, работу в этой лаборатории кода можно выполнить с помощью браузера.

После подключения к 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 KMS API включен, выполнив следующую команду:

gcloud services enable cloudkms.googleapis.com

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

KEYRING_NAME="keyring-functions"
REGION="us-central1"
KEY_NAME="key-encrypted-function"
PROJECT_ID=$(gcloud config get-value project)
PROJECT_NUMBER="$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')"
USER_EMAIL="$(gcloud config list account --format "value(core.account)")"

Затем создайте связку ключей , которая будет корневым ресурсом для ключей и версий ключей Cloud KMS.

gcloud kms keyrings create $KEYRING_NAME --location $REGION

Наконец, теперь вы можете создать симметричный ключ в новом наборе ключей в Cloud KMS.

gcloud kms keys create $KEY_NAME --keyring $KEYRING_NAME --location $REGION --purpose "encryption"

4. Создайте репозиторий реестра артефактов в формате Docker с поддержкой CMEK.

В этом разделе вы создадите репозиторий в формате Docker в реестре артефактов с поддержкой CMEK . Этот ключ будет тем же ключом, который использовался для развертывания вашей облачной функции.

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

gcloud beta services identity create --service=artifactregistry.googleapis.com --project=$PROJECT_ID

Используйте следующую команду, чтобы предоставить роль IAM CryptoKey Encrypter/Decrypter ( roles/cloudkms.cryptoKeyEncrypterDecrypter ) учетной записи службы реестра артефактов, чтобы иметь разрешения на доступ к ключу:

gcloud kms keys add-iam-policy-binding \
  $KEY_NAME --location $REGION --keyring=$KEYRING_NAME \
  --member serviceAccount:service-$PROJECT_NUMBER@gcp-sa-artifactregistry.iam.gserviceaccount.com \
  --role roles/cloudkms.cryptoKeyEncrypterDecrypter

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

gcloud kms keys add-iam-policy-binding \
       $KEY_NAME --location $REGION --keyring=$KEYRING_NAME \
       --member user:$USER_EMAIL \
       --role roles/cloudkms.cryptoKeyEncrypterDecrypter

Теперь вы можете создать репозиторий в формате Docker с поддержкой CMEK.

Примечание. Регион должен быть тем же регионом, что и ключ CMEK.

REPO_NAME=my-cmek-encrypted-repo 

KEY_FULLPATH=projects/"$PROJECT_ID"/locations/"$REGION"/keyRings/"$KEYRING_NAME"/cryptoKeys/"$KEY_NAME" 

gcloud artifacts repositories create $REPO_NAME \
    --repository-format=docker \
    --location=$REGION \
    --kms-key=$KEY_FULLPATH \
    --async

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

gcloud artifacts repositories describe $REPO_NAME --location=$REGION

5. Предоставьте сервисным учетным записям доступ к ключу (2-го поколения).

В этом разделе описано создание учетных записей служб для функций 2-го поколения. Если вы создаете функцию 1-го поколения, перейдите к следующему разделу.

Вы должны предоставить нескольким агентам службы доступ к ключу, предоставив роль IAM CryptoKey Encrypter/Decrypter ( roles/cloudkms.cryptoKeyEncrypterDecrypter ). Эти сервисные агенты используются для получения доступа к исходному коду, хранящемуся в облачном хранилище, хранения изображений функций в репозитории, защищенном CMEK, в реестре артефактов, а также для развертывания облачной функции, зашифрованной CMEK.

Шаги для функций второго поколения

  1. Предоставьте агенту службы Cloud Run доступ к ключу:
CLOUDRUN_SA=service-$PROJECT_NUMBER@serverless-robot-prod.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$CLOUDRUN_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter
  1. Предоставьте сервисному агенту Eventarc доступ к ключу:
EVENTARC_SA=service-$PROJECT_NUMBER@gcp-sa-eventarc.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$EVENTARC_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter
  1. Предоставьте агенту службы реестра артефактов доступ к ключу:
AR_SA=service-$PROJECT_NUMBER@gcp-sa-artifactregistry.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$AR_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter
  1. Предоставьте агентам службы Cloud Storage доступ к ключу:
STORAGE_SA=service-$PROJECT_NUMBER@gs-project-accounts.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$STORAGE_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter

В следующем разделе вы увидите, как создать и развернуть функцию, зашифрованную CMEK.

6. Предоставьте сервисным учетным записям доступ к ключу (1-го поколения).

В этом разделе описано создание учетных записей служб для функций 1-го поколения. Если вы ранее создали учетные записи служб для функции 2-го поколения, перейдите к следующему разделу.

Вы должны предоставить нескольким сервисным агентам доступ к ключу, предоставив роль IAM CryptoKey Encrypter/Decrypter ( roles/cloudkms.cryptoKeyEncrypterDecrypter ). Эти сервисные агенты используются для получения доступа к исходному коду, хранящемуся в облачном хранилище, хранения изображений функций в репозитории, защищенном CMEK, в реестре артефактов, а также для развертывания облачной функции, зашифрованной CMEK.

Шаги для функций 1-го поколения

  1. Предоставьте агенту службы Cloud Functions доступ к ключу:
FUNCTION_SA=service-$PROJECT_NUMBER@gcf-admin-robot.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$FUNCTION_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter
  1. Предоставьте агенту службы реестра артефактов доступ к ключу:
AR_SA=service-$PROJECT_NUMBER@gcp-sa-artifactregistry.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$AR_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter
  1. Предоставьте агентам службы Cloud Storage доступ к ключу:
STORAGE_SA=service-$PROJECT_NUMBER@gs-project-accounts.iam.gserviceaccount.com

gcloud kms keys add-iam-policy-binding $KEY_NAME \
--keyring=$KEYRING_NAME \
--location=$REGION \
--member=serviceAccount:$STORAGE_SA \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter

В следующем разделе вы увидите, как создать и развернуть функцию, зашифрованную CMEK.

7. Создайте функцию, зашифрованную CMEK (2-го поколения).

В этом разделе рассматривается создание функций второго поколения. Вы можете перейти к следующему разделу для инструкций 1-го поколения.

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

Шаги для функций 2-го поколения:

Создайте исходный код для функции

Хотя в этой лаборатории кода используется Node.js, вы можете использовать любую поддерживаемую среду выполнения .

Сначала создайте каталог и перейдите в него.

mkdir ~/cmek-function-2ndgen && cd $_

Затем создайте файл package.json.

touch package.json

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

Затем создайте исходный файл 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

Развертывание облачной функции 2-го поколения с использованием шифрования CMEK

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

FUNCTION_NAME=protect-me-cmek-2ndgen
ENTRY_POINT=helloWorld

REPO_FULLPATH=projects/"$PROJECT_ID"/locations/"$REGION"/repositories/$REPO_NAME

gcloud beta functions deploy $FUNCTION_NAME  \
--gen2 \
--region $REGION \
--kms-key $KEY_FULLPATH \
--docker-repository $REPO_FULLPATH \
--source . \
--trigger-http \
--allow-unauthenticated \
--runtime nodejs16 \
--entry-point $ENTRY_POINT

Вы можете увидеть ключ CMEK в полученном выводе, выполнив эту команду

Функции gcloud описывают $FUNCTION_NAME –регион $REGION | grep kmsKeyName

Проверьте функцию 2-го поколения

Вы можете проверить свою функцию, свернув ее:

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

curl $FUNCTION_URL

что приводит к следующему:

Hello World!

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

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

8. Создайте функцию, зашифрованную CMEK (1-го поколения).

В этом разделе рассматривается создание функций первого поколения. Если вы ранее создали функцию 2-го поколения, перейдите к следующему разделу.

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

Шаги для функций 1-го поколения:

Создайте исходный код для функции 1-го поколения.

Хотя в этой лаборатории кода используется Node.js, вы можете использовать любую поддерживаемую среду выполнения .

Сначала создайте каталог и перейдите в него.

mkdir ~/cmek-function-1stgen && cd $_

Затем создайте файл package.json.

touch package.json

echo '{
    "name": "function-cmek-codelab",
    "version": "0.0.1"
}' > package.json

Затем создайте исходный файл index.js.

touch index.js

echo "exports.helloWorld = (req, res) => {
    let message = req.query.message || req.body.message || 'Hello World!';
    res.status(200).send(message);
};" > index.js

Развертывание облачной функции 1-го поколения с использованием шифрования CMEK

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

FUNCTION_NAME=protect-me-cmek-1stgen
ENTRY_POINT=helloWorld

REPO_FULLPATH=projects/"$PROJECT_ID"/locations/"$REGION"/repositories/$REPO_NAME

gcloud functions deploy $FUNCTION_NAME  \
--region $REGION \
--kms-key $KEY_FULLPATH \
--docker-repository $REPO_FULLPATH \
--source . \
--trigger-http \
--allow-unauthenticated \
--runtime nodejs16 \
--entry-point $ENTRY_POINT

Вы можете увидеть ключ CMEK в полученном выводе, выполнив эту команду

Функции gcloud описывают $FUNCTION_NAME –регион $REGION | grep kmsKeyName

Проверьте функцию 1-го поколения

Вы можете проверить свою функцию, свернув ее:

FUNCTION_URL="$(gcloud functions describe $FUNCTION_NAME --region $REGION --format='get(httpsTrigger.url)')"

curl $FUNCTION_URL

что приводит к следующему:

Hello World!

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

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

9. Вызовите функцию, зашифрованную CMEK, где ключ шифрования отключен.

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

Отключить ключ шифрования

Вы можете запустить эту команду, чтобы отключить ключ . Поскольку эта лаборатория кода создает только одну версию ключа, вы отключите версию 1.

gcloud kms keys versions disable 1 \
    --key=$KEY_NAME \
    --keyring=$KEYRING_NAME \
    --location=$REGION

и вы должны увидеть полученную информацию:

algorithm: GOOGLE_SYMMETRIC_ENCRYPTION
createTime: '2023-04-11T03:30:49.111832653Z'
generateTime: '2023-04-11T03:30:49.111832653Z'
name: projects/dogfood-gcf-saraford/locations/us-central1/keyRings/myKeyRing/cryptoKeys/encrypted-function/cryptoKeyVersions/1
protectionLevel: SOFTWARE
state: DISABLED

Вызов функции с отключенной клавишей

Теперь снова curl функцию.

curl $FUNCTION_URL

и на этот раз вы не получите ответа Hello World.

В журналах облачной функции вы увидите

User's CMEK key has been disabled. CMEK key: projects/<PROJECT-NAME>/locations/us-central1/keyRings/myKeyRing/cryptoKeys/encrypted-function

Попытка просмотра ресурсов, когда ключ CMEK отключен.

В этом разделе вы увидите, что следующие ресурсы становятся недоступными, когда ключ CMEK отключен:

  • Исходный код функции
  • Создайте образ контейнера из исходного кода.

Например, при посещении вкладки «Источник» для функции «Облако» отображается ошибка при получении архива. Вы получите аналогичную ошибку, если попытаетесь просмотреть ZIP-файл, содержащий исходный код, непосредственно в Cloud Storage.

ac3307bb05d30e19.png

Кроме того, у вас не будет доступа к использованию образа контейнера для функции из реестра артефактов. Например, если вы попытаетесь развернуть этот образ контейнера в Cloud Run, вы получите сообщение об ошибке, сообщающее, что образ не найден.

Полный список зашифрованных ресурсов см. в документации по функциям CMEK.

10. Поздравления

Поздравляем, вы завершили работу над кодом!

Что мы рассмотрели

  • Как создать ключ CMEK на существующей симметричной связке ключей
  • Как создать репозиторий реестра артефактов
  • Как настроить CMEK в облачной функции

Для дополнительной информации

Дополнительную информацию об облачных функциях и CMEK можно найти по следующим ссылкам: