Я работаю над программой, которая будет работать в Google Cloud Run и будет хранить файлы в хранилище Google Cloud.
Проблема, с которой я сталкиваюсь, возникает при попытке создать подписанный URL-адрес для загрузки файла из облачного хранилища, которое обычно является частным. На моем локальном компьютере он работает нормально, но при работе в Cloud Run - нет.
Локально я использую сервисный аккаунт с Storage Object Admin
назначенная ему роль. Я загружаю разрешения, используя переменную среды с именем GOOGLE_APPLICATION_CREDENTIALS
со значением абсолютного пути к ключевому файлу .json, который я скачал из облачной консоли.
В Cloud Run я назначил ту же роль учетной записи службы, от которой работает служба. Однако, когда я пытаюсь что-либо там подписать, я получаю исключение:
java.io.IOException: код ошибки 403 пытается подписать предоставленные байты: у вызывающего абонента нет разрешения
В моем коде я не выбираю явно какую-либо учетную запись службы, поскольку документация SDK заставляет меня думать, что это делается автоматически. В Cloud Run у меня нет GOOGLE_APPLICATION_CREDENTIALS
набор переменных, потому что я думал, что это тоже было сделано автоматически.
Что меня смущает, так это то, что приложение, работающее в Cloud Run, может нормально загружать файлы в облачное хранилище, поэтому я думаю, что у него откуда-то есть учетные данные.
Что я делаю не так?
TL; DR: Убедитесь, что в учетной записи службы есть iam.serviceAccounts.signBlob
разрешение.
После дальнейшего изучения метода, который я использовал для получения учетных данных в Cloud Run:
GoogleCredentials credentials = ComputeEngineCredentials.create();
Storage storage = StorageOptions.newBuilder().setCredentials(credentials).build().getService();
Я прочитал javadoc для ComputeEngineCredentials
:
Учетные данные OAuth2, представляющие встроенную учетную запись службы для виртуальной машины Google Compute Engine. Получает токены доступа с сервера метаданных Google Compute Engine. Эти учетные данные используют IAM API для подписи данных. Смотрите знак (byte []) для более подробной информации.
После этого я прочитал javadoc для sign(byte[])
(курсив мой):
Подписывает предоставленные байты с помощью закрытого ключа, связанного с учетной записью службы. Проект Compute Engine должен включать API управления идентификацией и доступом (IAM), а учетная запись службы экземпляра должна иметь iam.serviceAccounts.signBlob разрешение.
Таким образом, я создал новую роль только с iam.serviceAccounts.signBlob
разрешение и назначил его учетной записи службы, которую использует моя конфигурация Cloud Run. После этого проблема сразу ушла (повторное развертывание не требуется)