Zarządzanie kluczami interfejsu API i ich bezpieczeństwo

1. Wprowadzenie

W przeszłości klucze interfejsu API Google były używane do uzyskiwania dostępu do interfejsów API Google, gdy inne metody były niedostępne lub niewygodne. Popularne przypadki użycia to dostęp do interfejsu API Map Google i interfejsów API Google udostępnianych przez Firebase. Wraz z wprowadzeniem modeli AI, agentów AI takich jak Gemini oraz platform AI Studio i pakiet Agent Development Kit klucze API stały się podstawową metodą dostępu do dużych modeli językowych Google.

Klucze API zapewniają niski poziom ochrony. Google Cloud udostępnia kilka metod zapobiegania nadużyciu kluczy, ale posiadanie aktywnego klucza interfejsu API umożliwia dostęp do interfejsów API Google bez dodatkowych weryfikacji uwierzytelniania lub autoryzacji. Metody ograniczania użycia kluczy interfejsu API są opisane w dokumentacji. Post Securing Your Gemini and Google API keys w Cloud Blog zawiera dodatkowe rekomendacje dotyczące zarządzania kluczami interfejsu API. W tym module z kodem zastosujesz te zalecenia w praktyce.

Jakie zadania wykonasz

  • Sprawdzanie wymuszonych ograniczeń podczas tworzenia nowych kluczy interfejsu API w Google Cloud
  • Skataloguj wszystkie klucze interfejsu API i znajdź te, które nie są zabezpieczone.
  • Wymuszanie ograniczeń w przypadku istniejących kluczy interfejsu API na podstawie ich wykorzystania
  • Zdefiniuj automatyzację, która usuwa klucz w przypadku nietypowego użycia.

Czego potrzebujesz

  • nowoczesna przeglądarka (np. Chrome);
  • Konto Google

2. Konfiguracja

Instrukcje w tym module zakładają, że polecenia są uruchamiane w Cloud Shell w konsoli Google Cloud. Jeśli masz gcloud CLI w środowisku lokalnym, możesz uruchamiać polecenia w tym interfejsie.

Operacje w tych krokach można wykonać za pomocą interfejsu konsoli Cloud, ale metody są inne. To ćwiczenie korzysta z interfejsu wiersza poleceń, aby uprościć interakcje i ułatwić integrację z nowoczesnymi agentami AI (takimi jak Antigravity CLI).

Uruchamianie terminalu Cloud Shell

  1. Otwórz konsolę Google Cloud w nowym oknie przeglądarki, korzystając z adresu https://console.cloud.google.com/. Aby uzyskać najlepsze wrażenia, zalecamy korzystanie z Chrome.
  2. Zaloguj się na konto Google w Google Cloud.
  3. Kliknij Aktywuj Cloud Shell Ikona aktywowania Cloud Shell u góry konsoli Google Cloud.
     Jeśli się pojawią, kliknij te okna:
    • Przejdź przez okno z informacjami o Cloud Shell.
    • Zezwól Cloud Shell na używanie Twoich danych logowania w celu wywoływania interfejsu Google Cloud API.

Wybierz projekt Google Cloud

Po otwarciu konsoli Cloud następuje uwierzytelnienie i zwykle wybierany jest projekt, w którym pracujesz. Identyfikator projektu to ciąg od 6 do 30 znaków, który składa się z małych liter, cyfr i łączników, np. qwiklabs-gcp-04-3075fc9fd77f. Terminal Cloud Shell skonfiguruje interfejs wiersza poleceń gcloud na potrzeby wybranego projektu. Zobaczysz dane wyjściowe podobne do tych:

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

Oznacza to, że kolejne polecenia wysyłane do gcloud będą używać identyfikatora projektu qwiklabs-gcp-04-3075fc9fd77f.

Ustaw identyfikator projektu jako zmienną środowiskową PROJECT_ID. Listę wszystkich projektów możesz wyświetlić za pomocą tego polecenia:

gcloud projects list
  • Jeśli chcesz użyć identyfikatora projektu innego niż skonfigurowany w gcloud, zastąp your-project-id i uruchom polecenie.
    export PROJECT_ID="your-project-id"
    
    Przykład:
    export PROJECT_ID="qwiklabs-gcp-04-3075fc9fd77f"
    
  • Jeśli chcesz użyć wybranego identyfikatora projektu, uruchom to polecenie:
    export PROJECT_ID=$(gcloud config get project)
    

3. Ograniczanie nowego klucza interfejsu API

W przeszłości użytkownicy mogli tworzyć klucze interfejsu API bez żadnych ograniczeń. Klucze bez ograniczeń można było używać do wywoływania DOWOLNEGO interfejsu API Google włączonego w projekcie, w którym został utworzony klucz. Konsola Google Cloud uniemożliwia użytkownikom tworzenie kluczy bez ograniczeń, ale można to zrobić za pomocą gcloud CLI lub bezpośrednich wywołań interfejsu API.

Poniższe kroki pokazują, jak utworzyć ograniczony klucz interfejsu API, który ogranicza użycie do określonego interfejsu API i określonej witryny.

  1. Aby utworzyć nowy klucz interfejsu API ograniczony do używania tylko z interfejsem API geolokalizacji Map Google, uruchom to polecenie w terminalu powłoki:
    gcloud services api-keys create --key-id=restricted-api-key \
      --display-name="restricted api key" \
      --api-target=service=geolocation.googleapis.com \
      --project=${PROJECT_ID}
    
    To polecenie tworzy nowy klucz API, którego można używać WYŁĄCZNIE do wywoływania usługi geolokalizacji Map Google.
  2. Zwiększ bezpieczeństwo klucza, dodając ograniczenie aplikacji. Ogranicz użycie klucza do wszystkich ścieżek w witrynie example.com. Aby dodać ograniczenie aplikacji do klucza, uruchom to polecenie:
    gcloud services api-keys update restricted-api-key \
      --location=global \
      --allowed-referrers="example.com/*" \
      --project=${PROJECT_ID}
    
    Zamiast zezwalać na używanie klucza w określonych witrynach, możesz użyć --allowed-application, aby zdefiniować dozwolone aplikacje na Androida luballowed-ips, aby zdefiniować dozwolone adresy IP. Wszystkie opcje znajdziesz w pełnej dokumentacji.

Czyszczenie danych

Usuń utworzony klucz interfejsu API, chyba że planujesz go używać:

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

4. Katalogowanie kluczy interfejsu API

W tym kroku użyjesz interfejsu gcloud CLI, aby uzyskać listę kluczy interfejsu API. Na liście wyświetlają się wszystkie aktywne (nieusunięte) klucze interfejsu API, do których masz dostęp.

  1. Aby wyświetlić wszystkie nazwy kluczy, identyfikatory i daty utworzenia, uruchom to polecenie:
    gcloud services api-keys list --project=${PROJECT_ID} \
      --format='value(displayName,name.basename(),createTime.date())'
    
    Dane wyjściowe będą zawierać nazwę klucza w formacie czytelnym dla człowieka, identyfikator klucza i datę utworzenia klucza. Będzie to wyglądać mniej więcej tak:
    api key 1	api-key-1	2024-05-10T07:53:24
    api key 2	api-key-2	2025-06-12T14:47:57
    
  2. Wybierz jeden z kluczowych identyfikatorów i wklej to polecenie, aby sprawdzić, czy klucz ma jakieś ograniczenia. Zastąp your-key-id wartością wybranego identyfikatora klucza:
    gcloud services api-keys describe "your-key-id" --project=${PROJECT_ID}
    

Dane wyjściowe (w formacie YAML) będą zawierać listę ograniczeń w sekcji 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'

Pamiętaj, że jeśli klucz nigdy nie został zaktualizowany, pola createTime i updateTime będą miały tę samą sygnaturę czasową.

  1. Pobierz i uruchom skrypt, który przechodzi przez wszystkie Twoje projekty i wyświetla wszystkie klucze interfejsu API, które NIE mają ograniczeń:
    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
    
    Po uruchomieniu skryptu zobaczysz dane wyjściowe w formie:
    DISPLAY NAME    KEY ID    PROJECT ID    CREATION DATE
    Key 1    1a2b3c4d-1234-abcd-1234-a1b2c3d4e5f6    my-project-1    2024-05-10T07:53:24.071228Z
    
    Wszystkie skrypty użyte w tym ćwiczeniu znajdziesz w folderze Security w repozytorium devrel-demos na GitHubie.

5. Sprawdzanie wykorzystania klucza interfejsu API

W tym kroku wyślesz zapytanie o dane Google Cloud, które pomogą Ci sprawdzić, jakie interfejsy API były wywoływane przy użyciu Twojego klucza interfejsu API. Na podstawie tych informacji możesz sprawdzić bieżące wykorzystanie kluczy i zastosować do nich ograniczenia interfejsu API na podstawie rzeczywistych danych, a nie domysłów.

  1. Użyj tego samego identyfikatora klucza, który został podany w poprzednim kroku, lub wybierz inny identyfikator. W tym poleceniu zastąp your-key-id wybranym identyfikatorem klucza:
    export KEY_UID=$(
       gcloud services api-keys describe "your-key-id" \
       --format='value(uid)' \
       --project=${PROJECT_ID})
    
  2. Ustaw wyszukiwanie tak, aby obejmowało historię użytkowania z ostatniego roku. Jeśli chcesz wyszukać dane z dłuższego lub krótszego okresu, zastąp symbol 365 (liczba dni) inną liczbą dodatnią.
    export DAYS=365
    
  3. Odśwież domyślne uwierzytelnianie aplikacji (ADC), aby umożliwić bezpośrednie wywoływanie interfejsu Cloud Monitoring API. Uruchom to polecenie i postępuj zgodnie z instrukcjami w terminalu:
    gcloud auth application-default login
    
  4. Aby wysłać żądanie danych o metrykach wykorzystania usługi do interfejsu Cloud Monitoring API, uruchom to polecenie:
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

Polecenie wysyła zapytanie do wbudowanych danych serviceruntime/api/request_count o punkty danych z etykietą credential_id, które pasują do wybranego unikalnego identyfikatora klucza interfejsu API. Następnie pobiera wartości etykiety service i wyświetla je, eliminując powtórzenia.

Wzmacnianie zabezpieczeń klucza interfejsu API

W tym kroku użyjesz informacji zebranych w poprzednich krokach, aby zaktualizować konfigurację ograniczeń klucza interfejsu API na podstawie informacji o użyciu.

Użyj tego samego klucza interfejsu API, który został użyty w poprzednim kroku. W razie potrzeby ponownie wykonaj instrukcje z poprzednich kroków, aby upewnić się, że zmienne środowiskowe PROJECT_ID, KEY_UID i DAYS są ustawione.

  1. Aby pobrać listę interfejsów API Google wywoływanych za pomocą klucza API, uruchom to polecenie:

SERVICES=$(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)

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. Zastąp listę ograniczonych interfejsów API niepustą listą:
    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. Definiowanie wykrywania anomalii użytkowania

W poprzednich krokach pokazaliśmy, jak badać i zabezpieczać klucze interfejsu API. Ten krok pokazuje, jak zautomatyzować reakcję na nieoczekiwany wzrost wykorzystania klucza za pomocą alertów monitorowania.

Poniższe instrukcje pozwolą Ci utworzyć alert, który będzie się włączać, gdy liczba wywołań interfejsu API, które używają klucza API, wzrośnie o ponad 10% w ciągu ostatnich 5 minut. Alert jest skonfigurowany tak, aby uruchamiać skrypt Cloud Build, który usuwa klucz interfejsu API, aby zapobiec jego dalszemu używaniu. Klucz można przywrócić w ciągu najbliższych 30 dni. Informacje o tym, jak przywrócić klucz, znajdziesz w dokumentacji.

Instrukcje ponownie wykorzystują zmienne PROJECT_ID i KEY_UID, które zostały użyte w poprzednich krokach. Jeśli chcesz wybrać inny klucz lub projekt, ustaw nowe wartości tych zmiennych zgodnie z instrukcjami w sekcji Konfigurowanie klucza interfejsu API i sprawdzanie jego wykorzystania.

  1. Aby utworzyć plik zasad alertów, uruchom ten skrypt:
    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
    
    Zasada tworzenia alertów używa tego filtra PromQL do wywoływania alertu:
     (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)
    
    Oblicza tempo wzrostu i porównuje je z poprzednim przedziałem czasu. Alert jest wywoływany tylko wtedy, gdy jest on o ponad 10% większy. Aby uniknąć wywoływania alertu, gdy łączna liczba wywołań jest znikoma, warunkiem wywołania jest wykonanie w okresie ponad 50 wywołań interfejsu API. Aby uniknąć obliczenia NaN (dzielenie przez zero), gdy poprzednia 5-minutowa stawka wynosiła 0, w przypadku, gdy stawka w poprzednim przedziale czasu wynosi 0, mianownik jest zastępowany wartością 1.Możesz zmienić parametry alertu, takie jak długość przedziału czasu (5m), minimalny próg (50) lub próg wzrostu o 10% (1.10).Dodatkowe parametry zasad określają, że po osiągnięciu warunku należy wywołać alert (duration), a warunek należy sprawdzać co 60 sekund (evaluationInterval).
  2. Aby utworzyć temat PubSub, który będzie używany do publikowania powiadomień o alertach, uruchom to polecenie:
    gcloud pubsub topics create api-key-alert-notifications --project=$PROJECT_ID
    
  3. Uruchom to polecenie, aby utworzyć kanały powiadomień o alertach, które korzystają z 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)
    
    W kroku Usuwanie użyjesz zmiennej środowiskowej CHANNEL_NAME.
  4. Aby utworzyć nowy alert monitorowania, uruchom to polecenie:
    gcloud monitoring policies create --policy-from-file=alert_policy.json \
      --project=$PROJECT_ID
    
  5. Uruchom to polecenie, aby przyznać usłudze Cloud Build uprawnienia do usuwania kluczy interfejsu API w projekcie.
    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"
    
    Możesz ograniczyć rolę apikeys.admin tak, aby można było za jej pomocą manipulować tylko określonymi instancjami kluczy interfejsu API. Więcej informacji znajdziesz w sekcji Warunki uprawnień.
  6. Uruchom ten skrypt, aby utworzyć aktywator kompilacji Cloud Build, który usuwa klucz interfejsu 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. Aby utworzyć nowy wyzwalacz alertu usługi Monitoring, uruchom to polecenie:
    gcloud builds triggers create pubsub \
      --trigger-config=trigger_config.yaml \
      --project=$PROJECT_ID
    

Teraz możesz usunąć pliki konfiguracyjne zasad tworzenia alertów i aktywatora kompilacji Cloud Build:

rm alert_policy.json trigger_config.yaml

Możesz też skonfigurować tę automatyzację za pomocą planu Terraform. Pobierz pliki Terraform z folderu abnormal-usage-detection w repozytorium Google Cloud DevRel. Plan przyjmuje identyfikator projektu i identyfikator UID klucza interfejsu API jako parametry wejściowe oraz konfiguruje zasoby i ustawienia, które zostały przedstawione w tym kroku.

7. Czyszczenie danych

Aby uniknąć nieoczekiwanych opłat na koncie Google Cloud, pamiętaj o usunięciu tematu Pub/Sub, aktywatora kompilacji Cloud Build i zasad tworzenia alertów utworzonych podczas tego ćwiczenia.

Aby usunąć wszystkie utworzone zasoby, uruchom te polecenia:

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

W tym ćwiczeniu z programowania udało Ci się wdrożyć solidne kompleksowe ramy zabezpieczeń i automatyzacji kluczy interfejsu API Google Cloud:

  1. Wzmocnione konfiguracje domyślne: utworzono i ograniczono klucze interfejsu API, aby ograniczyć dostęp wyłącznie do niezbędnych interfejsów API i zaufanych platform (np. określonych stron odsyłających HTTP).
  2. Przeprowadzono audyt zasobów kluczy: zeskanowano środowiska projektu, aby wykryć i odizolować nieograniczone klucze, które stanowią bezpośrednie zagrożenie dla bezpieczeństwa.
  3. Analizowane dane o użyciu: zapytania do danych wskaźników Cloud Monitoring wykonywane programowo w celu profilowania historycznego wykorzystania kluczy, co umożliwia ograniczanie kluczy na podstawie zweryfikowanych śladów użycia.
  4. Automatyczne ograniczanie zagrożeń: utworzono reaktywny „wyłącznik” przez połączenie zasady alertu Cloud Monitoring z tematem Pub/Sub i aktywatorem Cloud Build, co umożliwia automatyczne usuwanie naruszonych kluczy podczas nietypowych skoków natężenia ruchu.

Następne kroki

  • Zastosuj ograniczenia do wszystkich kluczy interfejsu API: wykorzystaj wiedzę zdobytą w tym ćwiczeniu, aby wykryć wszystkie częściowo ograniczone lub nieograniczone klucze interfejsu API i zastosować ograniczenia interfejsu API oraz klienta.
  • Skonfiguruj „bezpiecznik” kluczy interfejsu API: dodatkowo chroń klucze interfejsu API przed nieoczekiwanym użyciem, konfigurując automatyczne usuwanie kluczy w przypadku nagłego wzrostu wykorzystania. Użyj poleceń gcloud lub Terraform pokazanych w module. Rozważ ograniczenie uprawnień za pomocą warunków Cloud IAM.
  • Poznaj alerty w Monitoring: dowiedz się więcej o konfigurowaniu alertów za pomocą usługi Google Cloud Monitoring.
  • Dowiedz się więcej o kontroli dostępu dostępnej w Google Cloud: zapoznaj się z zasadami dotyczącymi granic dostępu i propagacją zmian dostępu.