Google Cloud Auth для внутреннего интерфейса командной строки с использованием Cloud Run - PullRequest
0 голосов
/ 24 сентября 2019

Мы создали несколько сервисов, используя Cloud Run.Наша цель - создать внутренний CLI, который позволит нашим разработчикам совершать звонки в эти сервисы.У нас возникают проблемы при создании id_token для использования с Identity Aware Proxy, который находится перед службами Cloud Run.

Согласно документам, выполнение вызовов к службам Cloud Run может быть выполнено с помощью gcloud и команда gcloud auth print-identity-token.Это прекрасно работает.Это также избавляет от необходимости загружать и передавать учетные данные учетной записи службы нашим разработчикам, так как этот метод использует учетные данные вашего приложения по умолчанию.

Мы попытались реализовать что-то для репликации этой print-identity-token функциональности в Go, но безуспешно.Сгенерированный id_token возвращает 401 для всех наших API Cloud Run.Пример кода для генерации токена:

func GetIDToken() string {
    ctx := context.Background()
    tokenSource, err := google.DefaultTokenSource(ctx, "openid", "email")

    if err != nil {
        log.Fatal(err)
    }

    token, err := tokenSource.Token()

    if err != nil {
        log.Fatal(err)
    }

    return fmt.Sprintf("%v", token.Extra("id_token"))
}

Возвращает id_token, но не работает с API.Кажется, что области видимости правильны в соответствии с документами.

Это оставляет нам два вопроса:

  1. Это правильный подход для генерации токена Id для IAP?
  2. Есть ли лучший способ реализовать аутентификацию для наших разработчиков по этим внутренним API?

1 Ответ

0 голосов
/ 24 сентября 2019

Этот ответ предназначен для создания Identity Token из учетной записи службы.Этот пример в Python.Если потребуется, я напишу это на Go.Я только что написал этот код на Python.

В приведенном ниже коде первый блок кода - это раздел, который берет учетную запись службы и запрашивает Identity Token от Google.Обратите внимание, что я не использую какие-либо области.Области используются при запросе токенов доступа Google OAuth.Жетоны идентификации хранятся в них.Вместо этого вам нужно указать аудиторию (URL), для которой предназначен Identity Token.Не всем службам требуется допустимое значение аудитории.

Мой код также показывает, как декодировать Identity Token для просмотра JSON заголовка и полезной нагрузки.Полезная нагрузка содержит идентификатор, который проверяет Google IAP.

Получив токен идентификации, включайте заголовок HTTP authorization: bearer TOKEN при отправке запросов в Cloud Run.

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

credentials = google.oauth2.service_account.IDTokenCredentials.from_service_account_file(
        json_filename,
        target_audience=aud)

request = google.auth.transport.requests.Request()

credentials.refresh(request)
  1. Изменитьпуть к учетной записи службы, соответствующий вашему программному обеспечению.
  2. Измените aud на URL-адрес своего облачного запуска.

Пример полного исходного кода:

'''
This program creates an OIDC Identity Token from a service account
'''

import json
import base64

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

# The service account JSON key file to use to create the Identity Token
json_filename = '/config/service-account.json'

# The audience that this ID token is intended for (example Google Cloud Run service URL)
aud = 'http://localhost'

def pad(data):
    """ pad base64 string """

    missing_padding = len(data) % 4
    data += '=' * (4 - missing_padding)
    return data

def print_jwt(signed_jwt):
    """ Print a JWT Header and Payload """

    s = signed_jwt.decode('utf-8').split('.')

    print('Header:')
    h = base64.urlsafe_b64decode(pad(s[0])).decode('utf-8')
    print(json.dumps(json.loads(h), indent=4))

    print('Payload:')
    p = base64.urlsafe_b64decode(pad(s[1])).decode('utf-8')
    print(json.dumps(json.loads(p), indent=4))

if __name__ == '__main__':
    credentials = google.oauth2.service_account.IDTokenCredentials.from_service_account_file(
            json_filename,
            target_audience=aud)

    request = google.auth.transport.requests.Request()

    credentials.refresh(request)

    #print(dir(credentials))

    # This is debug code to show how to decode Identity Token
    print('Decoded Identity Token:')
    print_jwt(credentials.token.encode())

    # This is the actual Identity Token
    print()
    print('Identity Token:')
    print(credentials.token)
...