Управление ключами API и безопасность

1. Введение

Исторически ключи API Google использовались для доступа к API Google, когда другие методы были недоступны или считались неудобными. Наиболее распространенными примерами использования были доступ к API Google Maps и API Google, предоставляемым Firebase. С появлением моделей искусственного интеллекта, агентов ИИ, таких как Gemini, а также фреймворков для разработки AI Studio и агентов, таких как Agent Development Kit, ключи API стали основным методом доступа к большим языковым моделям Google.

Ключи API обеспечивают низкий уровень защиты. Хотя Google Cloud предоставляет несколько методов предотвращения неправомерного использования ключей, наличие активного ключа API позволяет получить доступ к API Google без дополнительной аутентификации или проверки авторизации. Методы ограничения использования ключей API описаны в документации . В статье «Защита ваших ключей Gemini и Google API» в блоге Cloud Blog даются дополнительные рекомендации по обслуживанию ключей API. В этом практическом занятии вы примените эти рекомендации на практике.

Что вы будете делать

  • Ознакомьтесь с действующими ограничениями при создании новых ключей API в Google Cloud.
  • Составьте каталог всех ваших API-ключей и найдите ключи, не защищенные никакими средствами безопасности.
  • Вводить ограничения на использование существующих ключей API в зависимости от их назначения.
  • Настройте автоматизацию, которая удаляет ключ в случае его некорректного использования.

Что вам понадобится

  • Современный веб-браузер (например, Chrome).
  • Аккаунт Google

2. Настройка

Инструкции в этом практическом занятии предполагают, что вы выполняете команды в Cloud Shell в консоли Google Cloud. Если у вас локально установлена ​​утилита gcloud CLI , вы можете выполнить команды там.

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

Запустите терминал Cloud Shell.

  1. Откройте консоль Google Cloud по адресу https://console.cloud.google.com/ в новом окне браузера. Для наилучшего пользовательского опыта рекомендуется использовать Chrome.
  2. Войдите в свою учетную запись Google в Google Cloud.
  3. Нажмите «Активировать облачную оболочку» . Активировать значок Cloud Shell в верхней части консоли Google Cloud.
    Если отображается, перейдите по ссылкам в следующих окнах:
    • Продолжите просмотр информационного окна Cloud Shell.
    • Разрешите Cloud Shell использовать ваши учетные данные для выполнения вызовов к API Google Cloud.

Выберите проект Google Cloud

После открытия консоли Cloud вы проходите аутентификацию, и обычно появляется возможность выбрать проект для вашей работы. Идентификатор проекта представляет собой последовательность из 6–30 символов, состоящую из строчных букв, цифр и дефисов, например qwiklabs-gcp-04-3075fc9fd77f . Терминал Cloud Shell настраивает интерфейс командной строки gcloud с выбранным проектом. Вы увидите вывод, похожий на следующий:

Your Cloud Platform project in this session is set to qwiklabs-gcp-04-3075fc9fd77f

Это означает, что ваши дальнейшие команды для gcloud будут использовать идентификатор проекта qwiklabs-gcp-04-3075fc9fd77f .

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

gcloud projects list
  • Замените your-project-id и выполните команду, если хотите использовать идентификатор проекта, отличный от настроенного в gcloud .
    export PROJECT_ID="your-project-id"
    
    Например:
    export PROJECT_ID="qwiklabs-gcp-04-3075fc9fd77f"
    
  • Выполните следующую команду, если хотите использовать выбранный идентификатор проекта:
    export PROJECT_ID=$(gcloud config get project)
    

3. Ограничение доступа для нового ключа API

Раньше пользователи могли создавать совершенно неограниченные API-ключи. Неограниченные ключи можно было использовать для вызова ЛЮБОГО API Google, включенного в проекте, где был создан ключ. Хотя консоль Google Cloud не позволяет пользователям создавать неограниченные ключи, это все еще возможно с помощью gcloud CLI или прямых вызовов API.

Следующие шаги показывают, как создать ключ API с ограниченным доступом, который ограничивает его использование определенным API и указанным веб-сайтом.

  1. Чтобы создать новый ключ API, предназначенный исключительно для использования с API геолокации Google Maps, выполните следующую команду в терминале:
    gcloud services api-keys create --key-id=restricted-api-key \
      --display-name="restricted api key" \
      --api-target=service=geolocation.googleapis.com \
      --project=${PROJECT_ID}
    
    Эта команда создает новый ключ API, который можно использовать ТОЛЬКО для вызова службы геолокации Google Maps.
  2. Повысьте безопасность ключа, добавив ограничение для приложений. Ограничьте использование ключа только всеми путями внутри веб-сайта example.com . Выполните следующую команду, чтобы добавить ограничение для приложений к ключу:
    gcloud services api-keys update restricted-api-key \
      --location=global \
      --allowed-referrers="example.com/*" \
      --project=${PROJECT_ID}
    
    Вместо того чтобы разрешать использование ключа для конкретных веб-сайтов, вы можете использовать --allowed-application для определения разрешенных приложений Android или allowed-ips для определения разрешенных IP-адресов. Для получения полной информации обо всех параметрах обратитесь к документации .

Уборка

Удалите созданный вами ключ API, если вы не планируете его использовать:

gcloud services api-keys delete --key-id=restricted-api-key \
  --project=${PROJECT_ID}

4. Составьте каталог ваших API-ключей.

На этом шаге вы воспользуетесь CLI gcloud для получения списка ваших API-ключей. В полученном списке будут отображаться все активные (не удаленные) API-ключи, к которым у вас есть доступ.

  1. Выполните следующую команду, чтобы увидеть все имена ключей, идентификаторы и даты создания:
    gcloud services api-keys list --project=${PROJECT_ID} \
      --format='value(displayName,name.basename(),createTime.date())'
    
    В результате будет отображено удобочитаемое имя ключа, идентификатор ключа и дата его создания. Это будет выглядеть примерно так:
    api key 1	api-key-1	2024-05-10T07:53:24
    api key 2	api-key-2	2025-06-12T14:47:57
    
  2. Выберите один из идентификаторов ключей и вставьте следующую команду, чтобы проверить, есть ли у ключа какие-либо ограничения. Замените your-key-id значением выбранного идентификатора ключа:
    gcloud services api-keys describe "your-key-id" --project=${PROJECT_ID}
    

В выходных данных (в формате YAML) будет содержаться список ограничений в restrictions .

createTime: '2024-05-10T07:53:24.986528Z'
displayName: api key 1
etag: W/"u1WuY41K2tPKUZd7cfLoKg=="
name: projects/123456789012/locations/global/keys/api-key-1
restrictions:
  apiTargets:
  - service: geolocation.googleapis.com
  browserKeyRestrictions:
    allowedReferrers:
    - https://example.com/*
uid: 1a2b3c4d-1234-abcd-1234-a1b2c3d4e5f6
updateTime: '2024-05-10T07:53:24.071228Z'

Обратите внимание, что если ключ никогда не обновлялся, поля createTime и updateTime будут иметь одинаковую метку времени.

  1. Скачайте и запустите скрипт, который пройдёт по всем вашим проектам и выведет все ключи API, не имеющие ограничений :
    curl -fsSL -o unrestricted_api_keys.sh \
      "https://github.com/GoogleCloudPlatform/devrel-demos/blob/main/security/api-key-audit/unrestricted_api_keys.sh"
    chmod +x unrestricted_api_keys.sh
    ./unrestricted_api_keys.sh
    
    После запуска скрипта вы увидите следующий результат:
    DISPLAY NAME    KEY ID    PROJECT ID    CREATION DATE
    Key 1    1a2b3c4d-1234-abcd-1234-a1b2c3d4e5f6    my-project-1    2024-05-10T07:53:24.071228Z
    
    Все скрипты, использованные в этом CodeLab, можно найти в папке Security в репозитории devrel-demos на GitHub.

5. Узнайте, как использовать ключ API.

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

  1. Используйте тот же идентификатор ключа, что и на предыдущем шаге, или выберите другой идентификатор ключа. Замените your-key-id на выбранный идентификатор ключа в следующей команде:
    export KEY_UID=$(
       gcloud services api-keys describe "your-key-id" \
       --format='value(uid)' \
       --project=${PROJECT_ID})
    
  2. Настройте поиск таким образом, чтобы он охватывал историю использования за один год. Если вы хотите искать данные за более длительный или короткий период времени, замените число 365 (количество дней) на другое положительное число.
    export DAYS=365
    
  3. Обновите учетные данные приложения по умолчанию ( ADC ), чтобы включить прямой вызов API облачного мониторинга. Выполните следующую команду и следуйте инструкциям в терминале:
    gcloud auth application-default login
    
  4. Выполните следующую команду, чтобы отправить запрос на получение данных о метриках использования сервиса в API Cloud Monitoring:
curl -s -G -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  --data-urlencode "filter=metric.type=\"serviceruntime.googleapis.com/api/request_count\" AND resource.labels.credential_id=\"apikey:${KEY_UID}\"" \
  --data-urlencode "interval.startTime=$(date -u -d "${DAYS} days ago" +%Y-%m-%dT%H:%M:%SZ)" \
  --data-urlencode "interval.endTime=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
  "https://monitoring.googleapis.com/v3/projects/${PROJECT_ID}/timeSeries" \
  | jq -r '.timeSeries[]?.resource.labels.service' | sort -u

Эта команда запрашивает у встроенной метрики serviceruntime/api/request_count данные с меткой credential_id , которые соответствуют уникальному идентификатору выбранного ключа API. Затем она извлекает значения для метки service и выводит их, исключая повторения.

Ключ API для повышения уровня защиты

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

Вам понадобится тот же ключ API, что и на предыдущем шаге. При необходимости повторите инструкции с предыдущих шагов, чтобы убедиться, что переменные среды PROJECT_ID , KEY_UID и DAYS установлены.

  1. Выполните следующую команду, чтобы получить список API Google, вызываемых с использованием ключа API:

SERVICES=$(curl -s -G -H "Авторизация: Bearer $(gcloud auth application-default print-access-token)"
–data-urlencode "filter=metric.type="serviceruntime.googleapis.com/api/request_count" AND resource.labels.credential_id="apikey:${KEY_UID}""
–data-urlencode "interval.startTime=$(date -u -d "${DAYS} дней назад" +%Y-%m-%dT%H:%M:%SZ)"
–data-urlencode "interval.endTime=$(date -u +%Y-%m-%dT%H:%M:%SZ)"
"https://monitoring.googleapis.com/v3/projects/${PROJECT_ID}/timeSeries"
| jq -r '.timeSeries[]?.resource.labels.service' | sort -u)

1. Build the list of arguments to restrict the API usage for the API key based
on the retrieved list.

```shell
API_TARGET_ARGS=()
for SERVICE in $SERVICES; do
  API_TARGET_ARGS+=("--api-target=service=${SERVICE}")
done
  1. Замените список ограниченных API на непустой список:
    if [ ${#API_TARGET_ARGS[@]} -gt 0 ]; then
        gcloud services api-keys update "projects/${PROJECT_ID}/locations/global/keys/${KEY_UID}" \
        ${API_TARGET_ARGS}
    fi
    

6. Определение механизма обнаружения аномального использования.

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

Следующие инструкции создают оповещение, которое срабатывает, когда частота вызовов API с использованием ключа API увеличивается более чем на 10% за последние 5 минут. Оповещение настроено на запуск скрипта Cloud Build, который удаляет ключ API, чтобы предотвратить его дальнейшее использование. Ключ можно восстановить в течение следующих 30 дней. См. документацию , чтобы узнать, как восстановить удаленный ключ.

В инструкциях повторно используются переменные PROJECT_ID и KEY_UID , которые вы использовали на предыдущих шагах. Если вы хотите выбрать другой ключ и/или проект, установите новые значения для этих переменных, как описано в шагах «Настройка и обнаружение использования ключа API».

  1. Для создания файла политики оповещений выполните следующий скрипт:
    cat <<EOF > alert_policy.json
    {
      "displayName": "Credential API Request Count Increase Alert (Project: ${PROJECT_ID})",
      "combiner": "OR",
      "conditions": [
        {
          "displayName": "API Request Count Increase > 10% in 5m with Min Volume",
          "conditionPrometheusQueryLanguage": {
            "query": "(sum(increase(serviceruntime_googleapis_com:api_request_count{metric_label_credential_id=\\"apikey:${KEY_UID}\\"}[5m])) / (sum(increase(serviceruntime_googleapis_com:api_request_count{metric_label_credential_id=\\"apikey:${KEY_UID}\\"}[5m] offset 5m)) or on() vector(1)) > 1.10) and (sum(increase(serviceruntime_googleapis_com:api_request_count{metric_label_credential_id=\\"apikey:${KEY_UID}\\"}[5m])) > 50)",
            "duration": "0s",
            "evaluationInterval": "60s"
          }
        }
      ],
      "enabled": true
    }
    EOF
    
    Политика оповещений использует следующий PromQL-фильтр для запуска оповещения:
     (sum(
       increase(
         serviceruntime_googleapis_com:api_request_count{metric_label_credential_id="API_KEY_UID"}[5m])
     ) /
     (sum(
       increase(
         serviceruntime_googleapis_com:api_request_count{metric_label_credential_id="API_KEY_UID"}[5m] offset 5m)
     ) or on() vector(1)) > 1.10)
    and
     (sum(
       increase(
         serviceruntime_googleapis_com:api_request_count{metric_label_credential_id=\"YOUR_CREDENTIAL_ID_HERE\"}[5m])) > 50)
    
    Программа вычисляет темп роста и сравнивает его с предыдущим окном. Оповещение срабатывает только в том случае, если рост превышает заданное значение более чем на 10%. Чтобы избежать срабатывания оповещения, когда общее количество вызовов незначительно, условием срабатывания является наличие более 50 вызовов API в окне. Чтобы избежать вычисления NaN (удаление нуля), когда предыдущий 5-минутный темп равен 0, знаменатель заменяется на 1, если предыдущий темп равен нулю. Вы можете изменить параметры оповещения, такие как длина окна ( 5m ), минимальный порог ( 50 ) или порог увеличения на 10% ( 1.10 ). Дополнительные параметры политики определяют, что как только условие будет достигнуто, должно сработать оповещение ( duration ) и что условие должно проверяться каждые 60 секунд ( evaluationInterval ).
  2. Выполните следующую команду, чтобы создать тему PubSub, которая будет использоваться для отправки уведомлений об оповещениях:
    gcloud pubsub topics create api-key-alert-notifications --project=$PROJECT_ID
    
  3. Выполните следующую команду, чтобы создать каналы уведомлений для оповещений, использующие PubSub.
    CHANNEL_NAME=$(gcloud beta monitoring channels create \
      --display-name="Pub/Sub Alert Channel" \
      --type="pubsub" \
      --channel-labels="topic=projects/$PROJECT_ID/topics/api-key-alert-notifications" \
      --format='value(name)' \
      --project=$PROJECT_ID)
    
    Переменную среды CHANNEL_NAME вы будете использовать на этапе очистки.
  4. Выполните следующую команду, чтобы создать новое оповещение мониторинга:
    gcloud monitoring policies create --policy-from-file=alert_policy.json \
      --project=$PROJECT_ID
    
  5. Выполните следующую команду, чтобы предоставить службе Cloud Build разрешения на удаление ключей API в проекте.
    PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
    gcloud projects add-iam-policy-binding $PROJECT_ID \
      --member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
      --role="roles/apikeys.admin"
    
    Можно ограничить роль apikeys.admin возможностью управления только определенными экземплярами ключей API. Подробнее см. в условиях IAM .
  6. Запустите следующий скрипт, чтобы создать триггер Cloud Build, который удалит ключ API.
    cat <<EOF > trigger_config.yaml
    name: "delete-compromised-api-key"
    description: "Triggered by Pub/Sub alert to automatically delete the leaking API Key"
    pubsubConfig:
      topic: "projects/${PROJECT_ID}/topics/api-key-alert-notifications"
    build:
      steps:
      - name: "gcr.io/google.com/cloudsdktool/cloud-sdk:slim"
        args:
        - "gcloud"
        - "services"
        - "api-keys"
        - "delete"
        - "${KEY_UID}"
        - "--quiet"
    EOF
    
  7. Выполните следующую команду, чтобы создать новый триггер оповещения мониторинга:
    gcloud builds triggers create pubsub \
      --trigger-config=trigger_config.yaml \
      --project=$PROJECT_ID
    

Теперь вы можете удалить файлы конфигурации политики оповещений и триггеров Cloud Build:

rm alert_policy.json trigger_config.yaml

В качестве альтернативы вы можете настроить эту автоматизацию с помощью команды `terraform plan`. Загрузите файлы Terraform из папки `annormal-usage-detection` в репозитории Google Cloud DevRel. Команда `plan` принимает в качестве входных параметров идентификатор проекта и UID ключа API и настраивает ресурсы и конфигурации, которые вы видели на этом шаге.

7. Уборка

Чтобы избежать непредвиденных расходов на вашем аккаунте Google Cloud, не забудьте удалить тему Pub/Sub, триггер Cloud Build и политики оповещений, созданные в ходе этого упражнения.

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

gcloud builds triggers delete delete-compromised-api-key \
  --project=$PROJECT_ID
gcloud beta monitoring channels delete $CHANNEL_NAME \
  --project=$PROJECT_ID \
  --quiet
gcloud pubsub topics delete api-key-alert-notifications \
  --project=$PROJECT_ID
gcloud projects remove-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
  --role="roles/apikeys.admin"

8. Резюме

В этом практическом задании вы реализовали надежную комплексную систему безопасности и автоматизации для ключей API Google Cloud:

  1. Усиленные настройки по умолчанию : Вы создали и ограничили доступ к ключам API, чтобы ограничить доступ исключительно к необходимым API и доверенным платформам (например, к определенным HTTP-реферерам).
  2. Проведена проверка вашего ключевого реестра : вы просканировали среды вашего проекта, чтобы обнаружить и изолировать неограниченные ключи, представляющие непосредственную угрозу безопасности.
  3. Анализ данных об использовании : Вы программно запросили данные метрик Cloud Monitoring для анализа исторического использования ключей, что позволяет ограничивать использование ключей на основе подтвержденных данных об использовании.
  4. Автоматизированное смягчение угроз : Вы создали реактивный «автоматический выключатель», связав политику оповещений облачного мониторинга с темой Pub/Sub и триггером Cloud Build, что позволяет автоматически удалять скомпрометированные ключи во время аномальных всплесков трафика.

Следующие шаги

  • Примените ограничения ко всем вашим API-ключам : используйте полученные в этой лабораторной работе знания, чтобы обнаружить все частично ограниченные или неограниченные API-ключи и применить ограничения к API и клиенту.
  • Настройте «автоматический выключатель» для ключей API : дополнительно защитите свои ключи API от непредвиденного использования, настроив автоматическое удаление ключей в случае внезапного увеличения потребления. Используйте команды gcloud или Terraform, показанные в лабораторной работе. Рассмотрите возможность ужесточения прав доступа с помощью условий IAM.
  • Изучите функцию оповещения при мониторинге : узнайте больше о настройке оповещений с помощью сервиса Google Cloud Monitoring .
  • Узнайте больше о контроле доступа, доступном в Google Cloud : ознакомьтесь с политиками границ доступа и распространением изменений доступа .