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
实用程序尝试过的内容:
在没有 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.
用 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 成功访问。
更新
- 澄清一下,我认为 CDN 的行为已经改变。
- 我已授予 CDN 对 GCS 存储桶的访问权限。这就是为什么 CDN 早些时候可以正常工作的原因。我实际上只有 运行
gsutil iam ch serviceAccount:service-PROJECT_NUM@cloud-cdn-fill.iam.gserviceaccount.com:objectViewer gs://[BUCKET]
两次来确保这一点。
- 我试过直接使用
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 的正常行为,但我会对此做更多研究。
几个月来,我一直在使用 Google Cloud CDN 从 GCS 存储桶中缓存内容。直到昨天(2019/09/19),我注意到我无法访问名称中包含空格的对象。通常,在签署整个 URL 之前,我将 encodeURIComponent
应用于对象的名称,直到昨天它一直运行良好。
以下是我迄今为止使用 gcloud
实用程序尝试过的内容:
在没有 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.用 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 成功访问。
更新
- 澄清一下,我认为 CDN 的行为已经改变。
- 我已授予 CDN 对 GCS 存储桶的访问权限。这就是为什么 CDN 早些时候可以正常工作的原因。我实际上只有 运行
gsutil iam ch serviceAccount:service-PROJECT_NUM@cloud-cdn-fill.iam.gserviceaccount.com:objectViewer gs://[BUCKET]
两次来确保这一点。 - 我试过直接使用
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 的正常行为,但我会对此做更多研究。