【问题标题】:GCP Storage - signing key not providedGCP 存储 - 未提供签名密钥
【发布时间】:2021-02-24 21:40:59
【问题描述】:

即使我在这里发现了一个类似的问题:

Signing key was not provided and could not be derived on google precondition

这不会解决我的问题。

我在本地对 Google Storage 默认服务帐户进行身份验证,我可以轻松读取存储桶对象,如下所示:

    private val storage: Storage = StorageOptions
        .newBuilder()
        .setProjectId(projectId)
        .build()
        .service

    fun read() {
        val blob = storage
            .get(BlobId.of(bucket, object))

        println(String(blob.getContent()))
    }

但是,当我尝试使用以下命令生成签名的上传网址时:

    fun uploadUrl(objectName: String): String = storage
        .signUrl(
            BlobInfo.newBuilder(BlobId.of(bucketName, objectName)).build(),
            15,
            TimeUnit.MINUTES,
            Storage.SignUrlOption.httpMethod(HttpMethod.PUT),
            Storage.SignUrlOption.withExtHeaders(mapOf("Content-Type" to "application/octet-stream")),
            Storage.SignUrlOption.withV4Signature()
        )
        .toString()

我收到signing key not provided

我发现我很难认出我到底错过了什么。我通过gcloud auth application-default loginowner 用户进行了身份验证,通常允许我执行任何gcloud 任务。这里有什么不同?

【问题讨论】:

    标签: google-cloud-platform google-cloud-storage gcloud gsutil


    【解决方案1】:

    要签署某些东西,您需要一个私钥。使用用户凭据,您不能,因为您的环境中只有一个刷新令牌。但是,在服务帐户密钥文件中,您有一个私钥。您可以下载并使用它,但出于安全原因,我不喜欢它。

    wrote an article and I found a workaround in Python。我在 Java 中构建了一个类似的 hack(对不起,我不是 kotlin 开发者!但我确信它每个都可以转换!)。

    Storage storage = StorageOptions.getDefaultInstance().getService();
    
    Credentials credentialsToSIgn = storage.getOptions().getCredentials();
    if (credentialsToSIgn instanceof UserCredentials) {
      credentialsToSIgn = ImpersonatedCredentials.create(
        (GoogleCredentials) credentialsToSIgn,
        "SERVICE_ACCOUNT_EMAIL",
        Collections.EMPTY_LIST, 
        Collections.EMPTY_LIST, 
        3600);
    }
    System.out.println(
      storage.signUrl(
        BlobInfo.newBuilder(BlobId.of(bucketName, objectName)).build(),
        15,
        TimeUnit.MINUTES,
        Storage.SignUrlOption.httpMethod(HttpMethod.PUT),
        Storage.SignUrlOption.withExtHeaders(mapOf("Content-Type" to "application/octet-stream")),
        Storage.SignUrlOption.withV4Signature()
        Storage.SignUrlOption.signWith((ServiceAccountSigner) credentialsToSIgn)
      )
    );
    

    ImpersonatedCredentials 仅在此处使用 sign method in the class。这个签到方法使用了call the Service Account Credential APIIAMUtils.sign方法,在我的文章中有所描述

    这不是一个很好的技巧,但它确实有效。您可以将服务帐户电子邮件放入参数中,并在本地环境之外将其省略,以确保不会在其他地方执行错误的操作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-07-23
      • 1970-01-01
      • 2021-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-20
      • 1970-01-01
      相关资源
      最近更新 更多