gcp authorization external key zewnetrznym kluczem - ghdrako/doc_snipets GitHub Wiki

Custom Key JWT Authentication for Google Service Accounts

Autoryzacja zewnętrzna za pomocą niestandardowego klucza prywatnego i JWT (JSON Web Token)

Autoryzacji polega na wykorzystaniu zewnętrznego klucza do uzyskania dostępu do usług Google Cloud Platform (GCP) za pomocą konta usługi (Service Account). Proces autoryzacji wygląda następująco:

  1. Utworzenie konta usługi (Service Account) w GCP:
  • W konsoli Google Cloud wybierz odpowiedni projekt i utwórz konto usługi, które będzie miało wymagane uprawnienia do zasobów GCP.
# Ustaw projekt w GCP
gcloud config set project YOUR_PROJECT_ID

# Utwórz konto usługi
gcloud iam service-accounts create SERVICE_ACCOUNT_NAME \
    --display-name="Service Account for External Key Auth"

# Nadaj uprawnienia (np. viewer)
gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \
    --member="serviceAccount:SERVICE_ACCOUNT_NAME@YOUR_PROJECT_ID.iam.gserviceaccount.com" \
    --role="roles/viewer"
  1. Pobranie pliku JSON z kluczem konta usługi:
  • W trakcie tworzenia konta usługi lub później można wygenerować klucz prywatny (plik JSON) dla tego konta. Ten plik zawiera dane potrzebne do autoryzacji, takie jak private_key_id, client_email, client_id, client_x509_cert_url, oraz private_key.
# Wygeneruj klucz prywatny dla konta usługi i zapisz go jako JSON
gcloud iam service-accounts keys create service-account-key.json \
    --iam-account=SERVICE_ACCOUNT_NAME@YOUR_PROJECT_ID.iam.gserviceaccount.com

Plik service-account-key.json zawiera domyślny klucz prywatny generowany przez GCP.

  1. Przesłanie klucza publicznego z systemu zewnętrznego do gcp

przesłania klucza publicznego (w formacie PEM) do Google Cloud Platform (GCP) i powiązania go z określonym kontem usługi (Service Account). Zwraca szczegóły przesłanego klucza publicznego w formacie JSON i zapisuje je w pliku uploaded.json.

gcloud iam service-accounts keys \
   upload certificate.pem \
   --iam-account $CLIENT_EMAIL \
   --format json > uploaded.json

Sprawdzenie czy klucz sie dodal do sa:

gcloud iam service-accounts keys list --iam-account=SA_NAME@PROJECT_ID.iam.gserviceaccount.com

The output will contain the same unique identifier that was returned after the key was created:

KEY_ID CREATED_AT EXPIRES_AT DISABLED
c7b74879da78e4cdcbe7e1bf5e129375c0bfa8d0 2019-06-26T21:01:42Z 9999-12-31T23:59:59Z  

Wycieagniecie PRIVATE_KEY_ID

PRIVATE_KEY_ID=$(jq -r .name uploaded.json | \
   awk -F/ '{print $NF}')
  1. Przekazanie danych zewnętrznemu systemowi:
  • Aby system zewnętrzny mógł korzystać z konta usługi, musisz przekazać mu odpowiednie pola, takie jak private_key_id, client_email, client_id, i client_x509_cert_url. Dzięki nim system będzie mógł uwierzytelniać się na potrzeby korzystania z zasobów GCP.
  "project_id": "...",
  "private_key_id": "...",
  "client_email": "...",
  "client_id": "...",
  "client_x509_cert_url": "..."
  1. utworzenie przez system zewnetrzny pliku json do autoryzacji w gcp
  • Potrzebne dane:
    • private_key_id
    • client_email
    • client_id
    • client_x509_cert_url
    • Własny klucz prywatny (w formacie PEM) w postaci tekstowej, który posłuży jako private_key
  • wypelnij szablon pliku json
{
  "type": "service_account",
  "project_id": "YOUR_PROJECT_ID",
  "private_key_id": "YOUR_PRIVATE_KEY_ID",
  "private_key": "YOUR_PRIVATE_KEY",
  "client_email": "YOUR_CLIENT_EMAIL",
  "client_id": "YOUR_CLIENT_ID",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "YOUR_CLIENT_X509_CERT_URL"
}

private key musi byc sformatowany:

"private_key": "-----BEGIN PRIVATE KEY-----\nYOUR_KEY_CONTENT\n-----END PRIVATE KEY-----"

Example look-no-keys.json

{
  "type": "service_account",
  "project_id": "example-project",
  "private_key_id": "abc123456789",
  "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASC...\n-----END PRIVATE KEY-----",
  "client_email": "[email protected]",
  "client_id": "12345678901234567890",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/my-service-account%40example-project.iam.gserviceaccount.com"
}
touch look-no-keys.json
chmod 0600 look-no-keys.json

jq -n \
   --arg PRIVATE_KEY "$PRIVATE_KEY" \
   --arg PROJECT_ID $PROJECT_ID \
   --arg CLIENT_EMAIL $CLIENT_EMAIL \
   --arg CLIENT_ID $CLIENT_ID \
   --arg PRIVATE_KEY_ID $PRIVATE_KEY_ID \
  '{
  "type": "service_account",
  "project_id": $PROJECT_ID,
  "private_key_id": $PRIVATE_KEY_ID,
  "private_key": $PRIVATE_KEY,
  "client_email": $CLIENT_EMAIL,
  "client_id": $CLIENT_ID,
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": @uri "https://www.googleapis.com/robot/v1/metadata/x509/\($CLIENT_EMAIL)"
}' > look-no-keys.json
  1. Użycie klucza prywatnego po stronie systemu zewnętrznego:
  • Zewnętrzny system wykorzystuje private_key_id, client_email, client_id, client_x509_cert_url oraz własny klucz prywatny do uwierzytelniania za pomocą OAuth 2.0, co umożliwia mu uzyskanie tokenu dostępu (Access Token) do GCP. Token ten jest następnie używany do autoryzacji żądań do zasobów GCP.

uzycie z gcloud:

gcloud auth activate-service-account --key-file look-no-keys.json

uzycie w python

from google.oauth2 import service_account
import google.auth.transport.requests

# Ścieżka do pliku JSON
key_path = '/path/to/key.json'

# Załaduj poświadczenia
credentials = service_account.Credentials.from_service_account_file(
    key_path,
    scopes=["https://www.googleapis.com/auth/cloud-platform"]
)

# Wygeneruj token dostępu
request = google.auth.transport.requests.Request()
credentials.refresh(request)

print("Access Token:", credentials.token)

Ten model autoryzacji pozwala na integrację zewnętrznego systemu z GCP bez konieczności przechowywania pełnego klucza prywatnego w pliku JSON, co może być korzystne pod kątem bezpieczeństwa.

Opis dzialania Autoryzacja z JWT w GCP

Jeśli zewnętrzny system korzysta z JWT (JSON Web Token), schemat jest następujący:

  • System zewnętrzny generuje podpisany JWT przy użyciu swojego klucza prywatnego.
  • JWT jest przesyłany do GCP jako część żądania autoryzacji (np. w nagłówku HTTP Authorization).
  • GCP używa przypisanego klucza publicznego do weryfikacji tego podpisu.