This package works with Elixir >= 1.8 and Erlang/OTP >= 22.3
Add gcs_signed_url
to your list of dependencies in mix.exs
:
def deps do
[{:gcs_signed_url, "~> 0.4"}]
end
This library creates signed URLs for the Google Cloud Storage in three steps:
- Create a string to sign (use V4 signing process - V2 signing process is stil supported but deprecated)
- Sign the string to sign with the private key of a Google service account (GSA)
- Form the URL including the signature
The actual signing can be done on-premise on the machine your application is executed or it can be delegated to the Google IAM SignBlob API. The method of signing depends on your setup. Both methods work for creating V4 or V2 (deprecated) signatures.
If your application runs on the Google Kubernetes Engine, the preferred way of accessing Google Cloud services is through a Workload Identity. In this scenario, you run your application under a Kubernetes service account (KSA) which is related to a GSA. Using Goth, you would get an OAuth2 access token and use it to create a signed URL through the SignBlob API.
In this scenario, the GSA you get the access token for (GSA_AUTH
) acts as a Google Service Account GSA_SIGNER
and
signs the URL on his behalf. This requires the GSA_AUTH
go have the Google IAM permission
iam.serviceAccounts.signBlob on the GSA_SIGNER
, e.g. by giving it the built in
role roles/iam.serviceAccountTokenCreator on GSA_SIGNER
.
GSA_AUTH
and GSA_SIGNER
can also be the same service account in which case he needs to have the permission
iam.serviceAccounts.signBlob on itself.
iex> {:ok, %{token: access_token}} = Goth.Token.for_scope("https://www.googleapis.com/auth/devstorage.read_write")
iex> oauth_config = %GcsSignedUrl.SignBlob.OAuthConfig{service_account: "project@gcs_signed_url.iam.gserviceaccount.com", access_token: access_token}
iex> GcsSignedUrl.generate_v4(oauth_config, "my-bucket", "my-object.jpg", verb: "PUT", expires: 1800, headers: ["Content-Type": "application/jpeg"])
{:ok, "https://storage.googleapis.com/my-bucket/my-object.jpg?X-Goog-Expires=1800..."}
In this scenario you have a service account key in form of a JSON file on your machine. The library will use the private key to create the signature, no network calls are needed.
-
Load the client
iex> GcsSignedUrl.Client.load_from_file("/home/alexandrubagu/config/google.json")
or
iex> service_account = service_account_json_string |> Jason.decode! iex> GcsSignedUrl.Client.load(service_account)
-
Generate signed url
GcsSignedUrl.generate_v4(client, "my-bucket", "my-object.mp4") GcsSignedUrl.generate_v4(client, "my-bucket", "my-object.mp4", expires: 3 * 3600) # 3 hours