如何使用实例服务帐户为Google云存储对象生成签名URL [英] How to generate Signed URL for google cloud storage objects using service-accounts-for-instances

查看:97
本文介绍了如何使用实例服务帐户为Google云存储对象生成签名URL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用签名URL 给我客户端临时访问Google云存储对象

我有一个服务帐户json,看起来像这样:

I am using signed-urls to give my clients temporary access to google cloud storage objects
I have a service account json which looks like this:

{
  "type": "service_account",
  "project_id": "my-project",
  "private_key_id": "abcdef1234567890",
  "private_key": "-----BEGIN PRIVATE KEY-----\n<key...>\n-----END PRIVATE KEY-----\n",
  "client_email": "my-app@my-project.iam.gserviceaccount.com",
  "client_id": "1234567890",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/my-app%my-project.iam.gserviceaccount.com"
}

这就是我的方法创建用elixir编写的签名url-代码(来自 gcs_signer lib)

and here is how I create the signed url -code written in elixir (code from gcs_signer lib)

 def sign_url(private_key, client_email, bucket, object) do
    verb = "GET"
    md5_digest = ""
    content_type = ""
    expires = DateTime.utc_now() |> DateTime.to_unix() |> Kernel.+(1 * 3600)
    resource = "/#{bucket}/#{object}"

    signature = [verb, md5_digest, content_type, expires, resource]
                |> Enum.join("\n") |> generate_signature(private_key)

    url = "https://storage.googleapis.com#{resource}"
    qs = %{
           "GoogleAccessId" => client_email,
           "Expires" => expires,
           "Signature" => signature
         } |> URI.encode_query

    Enum.join([url, "?", qs])
  end

  defp generate_signature(string, private_key) do
    private_key = process_key(private_key)

    string
    |> :public_key.sign(:sha256, private_key)
    |> Base.encode64
  end

  defp process_key(private_key) do
    private_key
    |> :public_key.pem_decode
    |> (fn [x] -> x end).()
    |> :public_key.pem_entry_decode
    |> normalize_private_key
  end

  defp normalize_private_key(private_key) do
    # grab privateKey from the record tuple
    private_key
    |> elem(3)
    |> (fn pk -> :public_key.der_decode(:RSAPrivateKey, pk) end).()
  end

这是我使用json文件

in this was I create a signed url using the private_key from the json file

出于安全原因,我们移至实例服务而不是使用json凭据


我的问题是,在使用 service-accounts-for时如何创建一个签名的URL -instances 当我没有json凭证时?

我唯一拥有的是 servie_account_email ,它看起来像这样: my-app-gsa@my-project.iam .gserviceaccount.com

我应该使用 signBlob API?如果是,我的curl请求看起来如何?

for security reasons we moved to service-accounts-for-instances instead of using json credentials

my question is how to create a signed url when using service-accounts-for-instances when I don't have a json credential?
the only thing I have is the servie_account_email which look like this: my-app-gsa@my-project.iam.gserviceaccount.com
Should I use the signBlob api? if so how would my curl requests look like?

推荐答案

这是我在elixir中的代码以以下格式返回加密的链接:
https://storage.googleapis.com/my-bucket/my-file?Expires=1576437298&GoogleAccessId=my-gsa%40project.iam.gserviceaccount.com&Signature=FUgBzvfFCa0YAL

在google api之后跟随 signBlob

here is my code in elixir returns an encrypted link in the following format: https://storage.googleapis.com/my-bucket/my-file?Expires=1576437298&GoogleAccessId=my-gsa%40project.iam.gserviceaccount.com&Signature=FUgBzvfFCa0YAL
following google api for signBlob

@base_url @https://storage.googleapis.com

def generate_encrypted_url() do
    gcp_service_account = "my-gsa@project.iam.gserviceaccount.com"
    bucket = "my-bucket", 
    object ="my-file"
    get_signed_url(gcp_service_account, bucket, object)
end



  def get_signed_url(gcp_service_account, bucket, object) do
    %Tesla.Client{pre: [{Tesla.Middleware.Headers, :call, [auth_headers]}]} = get_connection()
    headers = [{"Content-Type", "application/json"}] ++ auth_headers
    url = "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/#{gcp_service_account}:signBlob"
    expires = DateTime.utc_now() |> DateTime.to_unix() |> Kernel.+(1 * 3600)
    resource = "/#{bucket}/#{object}"
    signature = ["GET", "", "", expires, resource] |> Enum.join("\n") |> Base.encode64()
    body = %{"payload" => signature} |> Poison.encode!()
    {:ok, %{status_code: 200, body: result}} = HTTPoison.post(url, body, headers)

    %{"signedBlob" => signed_blob} = Poison.decode!(result)
    qs = %{
           "GoogleAccessId" => gcp_service_account,
           "Expires" => expires,
           "Signature" => signed_blob
         } |> URI.encode_query
    Enum.join(["#{@base_url}#{resource}", "?", qs])
  end

  def get_connection() do
    {:ok, token} = Goth.Token.for_scope("https://www.googleapis.com/auth/cloud-platform")
    GoogleApi.Storage.V1.Connection.new(token.token)
  end

这篇关于如何使用实例服务帐户为Google云存储对象生成签名URL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆