GCS 私有桶作 GCP CDN 源站

原创 server  2024-08-31 13:50  阅读 64 次

概览

GCS作为CDN源站是一种常见的场景,为了对存储桶里的文件访问进行保护,所以会将存储桶设置为私有权限,接入CDN无法访问,可以使用签名URL,这样只要携带签名就会获得限时的资源访问权限。

配置存储桶

将已创建好的桶设为私有

GCS 私有桶作 GCP CDN 源站 技术笔记 第1张

创建HTTP(S)负载均衡,开启CDN

GCS 私有桶作 GCP CDN 源站 技术笔记 第2张

前端配置

注意:网络层级需要选择Premium,否则无法开启CDN

GCS 私有桶作 GCP CDN 源站 技术笔记 第3张

后端配置

GCS 私有桶作 GCP CDN 源站 技术笔记 第4张

Cloud Storage bucket选择需要作为源站的私有桶

GCS 私有桶作 GCP CDN 源站 技术笔记 第5张

展开Additional configurations,Restricted content 配置选择"Restrict access using signed URLs and signed cookies"

GCS 私有桶作 GCP CDN 源站 技术笔记 第6张

创建URL signing keys,将Signing key value保存到本地文件中,本例保存在/Users/dqyan/key-value

GCS 私有桶作 GCP CDN 源站 技术笔记 第7张

路由配置使用缺省配置即可

点击创建 ,至此LB配置完成

因为私有桶限制了可以读取对象的用户,所以必须向 Cloud CDN 授予读取对象的权限,方法是将 Cloud CDN 服务帐号添加到 Cloud Storage ACL 中。这里无需创建服务帐号。因为首次将密钥添加到项目中的后端存储分区时,系统将自动创建服务帐号。

注意:在运行以下命令之前,请确保已经向项目中的后端存储分区添加了至少一个密钥。否则,该命令会失败并显示错误,这是因为您必须先为项目添加一个或多个密钥,系统才会创建 Cloud CDN 缓存填充服务帐号。

执行以下命令:

gsutil iam ch \
serviceAccount:service-<PROJECT_NUMBER> @cloud-cdn-fill.iam.gserviceaccount.com:objectViewer \
gs://daqi-private

<PROJECT_NUMBER> 替换成资源所在项目的项目号,项目号可以在控制台上如下位置找到。

GCS 私有桶作 GCP CDN 源站 技术笔记 第8张

访问测试

上传一张测试图片到存储桶

此时我们先访问测试发现访问返回403

GCS 私有桶作 GCP CDN 源站 技术笔记 第9张

因为访问请求中不带有 URL 签名,Cloud CDN 不做签名验证而将请求直接发给源站 Cloud Storage,但是 Cloud Storage 不允许不经过 URL 签名验证的请求访问其私有文件,因此拒绝访问。

创建签名URL

gcloud compute sign-url \
  "http://34.117.145.59/dqyan.jpeg" \
  --key-name test-key \
  --key-file key-value \
  --expires-in 30m \
  --validate

执行后会返回签名url,使用返回的URL访问测试

携带签名访问测试

注意:如果是用curl访问测试,查询参数符号前记得加"\"

curl -I http://34.117.145.59/dqyan.jpeg\?Expires=1681906459\&KeyName=tests-key\&Signature=4INg-niG21Y1K6MN7YmpfJ9tYl8=
GCS 私有桶作 GCP CDN 源站 技术笔记 第10张

使用 URL 前缀签名

为签名URL使用URL前缀,这样就不必为带有 Expires 和 KeyName 查询参数的完整请求网址签名,而是可以仅对 URLPrefix、Expires 和 KeyName 查询参数进行签名。这样一来,您就可以在多个与 URLPrefix 相匹配的网址中重复使用 URLPrefix、Expires、KeyName 和 Signature 查询参数的给定组合,而不需要为每个不同网址创建一个新签名。

Python代码示例

def sign_url_prefix(url, url_prefix, key_name, base64_key, expiration_time):
    """Gets the Signed URL string for the specified URL prefix and configuration.

    Args:
        url: URL of request.
        url_prefix: URL prefix to sign as a string.
        key_name: name of the signing key as a string.
        base64_key: signing key as a base64 encoded string.
        expiration_time: expiration time as a UTC datetime object.

    Returns:
        Returns the Signed URL appended with the query parameters based on the
        specified URL prefix and configuration.
    """
    stripped_url = url.strip()
    parsed_url = urllib.parse.urlsplit(stripped_url)
    query_params = urllib.parse.parse_qs(
        parsed_url.query, keep_blank_values=True)
    encoded_url_prefix = base64.urlsafe_b64encode(
            url_prefix.strip().encode('utf-8')).decode('utf-8')
    epoch = datetime.datetime.utcfromtimestamp(0)
    expiration_timestamp = int((expiration_time - epoch).total_seconds())
    decoded_key = base64.urlsafe_b64decode(base64_key)

    policy_pattern = u'URLPrefix={encoded_url_prefix}&Expires={expires}&KeyName={key_name}'
    policy = policy_pattern.format(
            encoded_url_prefix=encoded_url_prefix,
            expires=expiration_timestamp,
            key_name=key_name)

    digest = hmac.new(
            decoded_key, policy.encode('utf-8'), hashlib.sha1).digest()
    signature = base64.urlsafe_b64encode(digest).decode('utf-8')

    signed_url = u'{url}{separator}{policy}&Signature={signature}'.format(
            url=stripped_url,
            separator='&' if query_params else '?',
            policy=policy,
            signature=signature)

    print(signed_url)

Github:
github.com/GoogleCloudP 执行结果:

GCS 私有桶作 GCP CDN 源站 技术笔记 第11张

利用产生的签名来请求两个不同文件 dqyan.jpeg和Alan.jpeg。 查看结果均请求成功

GCS 私有桶作 GCP CDN 源站 技术笔记 第12张
本文地址:https://www.91hosts.com/technical-notes/849.html
关注我们:请关注一下我们的微信公众号:扫描二维码谷歌云GCP/亚马逊AWS/微软云AZURE/阿里云国际代理商-91hosts的公众号
版权声明:本文为原创文章,版权归 server 所有,欢迎分享本文,转载请保留出处!

评论已关闭!