Google Cloud CDN 无法从 GCS 后端服务访问带有白色 space 的文件

Google Cloud CDN cannot access file with white space from GCS backend service

几个月来,我一直在使用 Google Cloud CDN 从 GCS 存储桶中缓存内容。直到昨天(2019/09/19),我注意到我无法访问名称中包含空格的对象。通常,在签署整个 URL 之前,我将 encodeURIComponent 应用于对象的名称,直到昨天它一直运行良好。

以下是我迄今为止使用 gcloud 实用程序尝试过的内容:

  1. 在没有 URL 的情况下签署 URL - 对文件名进行编码:

    $ gcloud compute sign-url --key-name my-key --key-file my-key --expires-in 15m "https://cdn.example.com/file-with-white space.txt"

    然后我访问了 URL 有无 %20。结果是403,显示在picture.

  2. 用 URL 编码的文件名签署 URL(这是我几个月来一直在做的,而且效果很好):

    $ gcloud compute sign-url --key-name my-key --key-file my-key --expires-in 15m "https://cdn.example.com/file-with-white%20space.txt"

    结果也是403,但不同message:

Anonymous caller does not have storage.objects.get access to bucket/file name

我也尝试过使用此 link 中的 Go 代码。结果是一样的

请注意,名称中没有空格的文件仍然可以通过 CDN 成功访问。


更新

  1. 澄清一下,我认为 CDN 的行为已经改变。
  2. 我已授予 CDN 对 GCS 存储桶的访问权限。这就是为什么 CDN 早些时候可以正常工作的原因。我实际上只有 运行 gsutil iam ch serviceAccount:service-PROJECT_NUM@cloud-cdn-fill.iam.gserviceaccount.com:objectViewer gs://[BUCKET] 两次来确保这一点。
  3. 我试过直接使用 gsutil 签署 GCS URL,而不使用 CDN,并且签署的 URL 有效。

更新 2

我已经尝试了 --validate 选项。这是我得到的:

$ gcloud compute sign-url --key-name cdn-signing-key \
  --key-file cdn-signing-key --expires-in 15m \
  --validate "https://cdn.domain.com/file%20with%20space"

signedUrl: https://cdn.domain.com/file%20with%20space?Expires=1569075302&KeyName=cdn-signing-key&Signature=e3SANudKHIT5txHWVlO1oijItXw=
validationResponseCode: 200

然而,当我通过浏览器访问 "signedUrl" 时,仍然收到 403。结果是 XML 页面 <Code>AccessDenied</Code>.

我无法复制这个。

可以对 GCS 存储桶中带有空格的(URL 编码)文件名进行签名和验证:

➜  gcloud compute sign-url --key-name "backend-key" \
  --key-file backend.key --expires-in 7d \
  --validate "https://cloud-cdn.questionable.services/file%20with%20spaces.txt"

signedUrl: https://cloud-cdn.questionable.services/file%20with%20spaces.txt?Expires=1569639576&KeyName=backend-key&Signature=pTsgDpBOpBcqHDNeTWFfFcTC2Ws=
validationResponseCode: 200

没有 URL 编码,验证和签名失败(如预期),因为 gcloud 不会自动百分比编码 URLs:

➜  gcloud compute sign-url --key-name "backend-key" \
  --key-file backend.key --expires-in 7d \
  --validate "https://cloud-cdn.questionable.services/file with spaces.txt"

signedUrl: https://cloud-cdn.questionable.services/file with spaces.txt?Expires=1569639586&KeyName=backend-key&Signature=AiJEBO6sHGgJh8EshLAH2IXlxe0=
validationResponseCode: 400

Cloud CDN 端的签名算法没有任何变化,gcloud SDK 中的 sign-url 命令也没有变化。我们过去没有隐式 URL 编码输入 URL。

今天早上,我再次尝试访问新签名的 URL 文件,其中包含空格。我发现了一些有趣的事情。

  • 有时,CDN 工作并且 returns 200 连同文件的内容。
  • 有时,CDN 从后端服务(在本例中为 GCS 存储桶)收到 301 响应,然后将我重定向到存储桶 URL,后者又 returns 403 连同 XML 页面。
  • 所以我尝试将存储桶的权限更改为 Public。如果 CDN 有效,我将像以前一样收到 200。如果 CDN 将我重定向到存储桶,现在我将随文件一起收到 200。

所以我要关闭这个问题,因为我认为它与文件名无关了。似乎 CDN 没有为我缓存内容,而是尝试将存储桶中的原始文件指向我。我不确定这是否是 CDN 的正常行为,但我会对此做更多研究。