Как сгенерировать подписанные URL-адреса для объектов Google Cloud Storage в GKE (Go) - PullRequest
0 голосов
/ 18 июня 2020

Цель:

Создание подписанных URL-адресов внутри модулей GKE без ручного ввода ключа JSON учетной записи службы. Синтаксис для их создания требует электронной почты учетной записи службы и закрытого ключа.

//import "cloud.google.com/go/storage"
url, err := storage.SignedURL(bucketName, objectName, &storage.SignedURLOptions{
    ContentType:    contentType,
    GoogleAccessID: saEmail,
    PrivateKey:     saPrivateKey,
})

Другими словами, я хотел бы загрузить saEmail и saPrivateKey из учетных данных по умолчанию, автоматически доступных в узлах GKE.

Попытка:

ctx := context.Background()
//errors ignored for brevity
//import "golang.org/x/oauth2/google"
creds, _ := google.FindDefaultCredentials(ctx, storage.ScopeReadWrite)
cfg, _ := google.JWTConfigFromJSON(creds.JSON)
url, _ := storage.SignedURL(bucketName, objectName, &storage.SignedURLOptions{
    ContentType:    contentType,
    GoogleAccessID: cfg.Email,
    PrivateKey:     cfg.PrivateKey,
})

Когда я запускал google.FindDefaultCredentials() внутри модуля GKE, результат JSON пуст.

Среда:

  • Go 1,13
  • GKE 1.14.10-gke.36
  • cloud.google.com/go v0.58.0
  • cloud.google.com/go/storage v1.8.0

Дополнительные примечания:

Я протестировал две возможные альтернативы, включающие введение ключа учетной записи службы (JSON) вручную в модуль, но я надеюсь избежать их, если это возможно:

  • Запись ключа учетной записи службы в файл и установив GOOGLE_APPLICATION_CREDENTIALS в его путь. Когда это будет сделано, google.FindDefaultCredentials() загружает электронную почту и закрытый ключ.

  • Передача ключа учетной записи службы в виде строки в модуль и его синтаксический анализ с помощью google.JWTConfigFromJSON().

1 Ответ

2 голосов
/ 18 июня 2020

Для создания подписанного URL-адреса вам нужен закрытый ключ.

Когда вы используете сервисы GCP (здесь, в Compute Instances, узел вашего кластера K8S, но то же самое с Cloud RUn, Cloud Functions и другими сервисами GCP) и вы используете учетные данные по умолчанию (и там не определена переменная GOOGLE_APPLICATION_CREDENTIALS env), библиотека использует сервер метаданных .

Сервер метаданных позволяет вам сгенерировать токен доступа

curl -H "Metadata-Flavor: Google" \
http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token

или идентификационный токен (с аудиторией в параметре)

curl -H "Metadata-Flavor: Google" \
http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=https://www.google.com

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

Однако сервер метаданных не предоставляет секрет (закрытый ключ), и вы не можете использовать его для сгенерированных подписанных URL-адресов.

Здесь вам нужен файл ключа учетной записи службы

У вас есть несколько способов предоставить его модулю безопасным образом.

Я не рекомендую вам класть файл ключей своей сервисной учетной записи прямо в контейнер, это небезопасно

Другое решение

В конечном итоге вы можете сгенерировать на лету ключ и определить его как ключ учетной записи службы (его имя ключ пользовательской учетной записи службы ).

  • Вы можете сгенерировать его при развертывании службы в кластере. Таким образом, вам не нужно хранить секрет, он генерируется каждый раз на лету.
  • Вы можете сгенерировать ключ при запуске контейнера, установить его в учетной записи службы и сохранить в памяти.

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

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

...