Подписание URL-адреса Google Cloud Storage - PullRequest
0 голосов
/ 16 апреля 2019

У меня есть подписант, который отлично работает для выгрузки и загрузки из GCS. Большой! Подписавшийся выглядит так:

def sign_url(client, bucket, key, opts \\ []) do
  verb = opts[:verb] || "GET"
  md5_digest = opts[:md5_digest] || ""
  content_type = opts[:content_type] || ""
  expires = opts[:expires] || Utils.years(10)
  resource = "/#{bucket}/#{key}"

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

  url = "#{@base_url}#{resource}"

  qs =
    %{
      "GoogleAccessId" => client.client_email,
      "Expires" => expires,
      "Signature" => signature
    }
    |> URI.encode_query()

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

defp generate_signature(string, client) do
  private_key = get_private_key(client)

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

defp get_private_key(client) do
  client.private_key
  |> :public_key.pem_decode()
  |> Kernel.hd()
  |> :public_key.pem_entry_decode()
end

У меня возникает проблема, если я хочу добавить заголовок x-goog, например x-goog-copy-source. При этом я получаю сообщение об ошибке:

The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method.

Теперь я знаю, что подписанный URL-адрес поддерживает пользовательские заголовки, но я не уверен, как обновить подпись, чтобы поддержать его. Я не могу найти в Интернете никаких ресурсов, включая документы Google, которые описывают это.

Кто-нибудь еще имел опыт с этим?

Спасибо

1 Ответ

2 голосов
/ 17 апреля 2019

Я немного изменил ваш код, чтобы добавить заголовки. Они ожидаются после истечения срока действия в строке для подписи.

Я недостаточно хорошо знаю Эликсир, но, надеюсь, это укажет вам правильное направление. Он основан на реализации Ruby Storage (https://github.com/googleapis/google-cloud-ruby/blob/master/google-cloud-storage/lib/google/cloud/storage/file/signer_v2.rb#L62)

Редактировать: Документацию по этой конструкции можно найти здесь .

def sign_url(client, bucket, key, opts \\ []) do
  verb = opts[:verb] || "GET"
  md5_digest = opts[:md5_digest] || ""
  content_type = opts[:content_type] || ""
  expires = opts[:expires] || Utils.years(10)
  resource = "/#{bucket}/#{key}"
  headers = 
    Enum.map(opts[:headers], fn ({key, value}) -> "#{key}:#{value}" end)
           |> Enum.join("\n")

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

  url = "#{@base_url}#{resource}"

  qs =
    %{
      "GoogleAccessId" => client.client_email,
      "Expires" => expires,
      "Signature" => signature
    }
    |> URI.encode_query()

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

defp generate_signature(string, client) do
  private_key = get_private_key(client)

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

defp get_private_key(client) do
  client.private_key
  |> :public_key.pem_decode()
  |> Kernel.hd()
  |> :public_key.pem_entry_decode()
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...