From ec596ef0037a3ea7175c7e9c945984ba33a78b5b Mon Sep 17 00:00:00 2001 From: Shubhangi Singh Date: Fri, 11 Sep 2026 03:25:01 +0000 Subject: [PATCH 1/2] adding support for Workload identity --- .../acceptance/storage/signed_url_v2_test.rb | 35 +++++++++++ .../acceptance/storage/signed_url_v4_test.rb | 36 +++++++++++ .../lib/google/cloud/storage/bucket.rb | 20 +++--- .../lib/google/cloud/storage/file.rb | 20 +++--- .../google/cloud/storage/file/signer_v2.rb | 38 ++++++++---- .../google/cloud/storage/file/signer_v4.rb | 43 +++++++++---- .../lib/google/cloud/storage/iam_signer.rb | 48 ++++++++++++++ .../samples/acceptance/files_test.rb | 30 +++++++++ ...enerate_signed_url_v4_workload_identity.rb | 44 +++++++++++++ .../storage/bucket_signed_url_v2_test.rb | 33 ++++++---- .../storage/bucket_signed_url_v4_test.rb | 33 ++++++---- .../cloud/storage/file_signed_url_v2_test.rb | 62 +++++++++++++++---- .../cloud/storage/file_signed_url_v4_test.rb | 62 +++++++++++++++---- .../google/cloud/storage/iam_signer_test.rb | 49 +++++++++++++++ .../storage/lazy/bucket_signed_url_v2_test.rb | 33 ++++++---- .../storage/lazy/bucket_signed_url_v4_test.rb | 33 ++++++---- .../storage/lazy/file_signed_url_v2_test.rb | 33 ++++++---- .../storage/lazy/file_signed_url_v4_test.rb | 33 ++++++---- .../storage/project_signed_url_v2_test.rb | 33 ++++++---- .../storage/project_signed_url_v4_test.rb | 33 ++++++---- 20 files changed, 602 insertions(+), 149 deletions(-) create mode 100644 google-cloud-storage/lib/google/cloud/storage/iam_signer.rb create mode 100644 google-cloud-storage/samples/storage_generate_signed_url_v4_workload_identity.rb create mode 100644 google-cloud-storage/test/google/cloud/storage/iam_signer_test.rb diff --git a/google-cloud-storage/acceptance/storage/signed_url_v2_test.rb b/google-cloud-storage/acceptance/storage/signed_url_v2_test.rb index e8eb28d4c68d..4cbd0b113330 100644 --- a/google-cloud-storage/acceptance/storage/signed_url_v2_test.rb +++ b/google-cloud-storage/acceptance/storage/signed_url_v2_test.rb @@ -84,6 +84,41 @@ end describe Google::Cloud::Storage::Bucket, :signed_url do + it "should create a signed read url automatically using IAM API when on GCE/Workload Identity" do + local_file = File.new files[:logo][:path] + file = bucket.create_file local_file, "CloudLogoSignedUrlGetBucketAuto.png" + + issuer = bucket.service.credentials.issuer + skip "Test requires a service account with an issuer" unless issuer + + bucket.service.credentials.stub :signing_key, nil do + bucket.service.credentials.stub :issuer, nil do + Google::Cloud.env.stub :compute_engine?, true do + Google::Cloud.env.stub :lookup_metadata, issuer do + five_min_from_now = 5 * 60 + url = bucket.signed_url file.name, + method: "GET", + expires: five_min_from_now + + uri = URI url + http = Net::HTTP.new uri.host, uri.port + http.use_ssl = true + http.ca_file ||= ENV["SSL_CERT_FILE"] if ENV["SSL_CERT_FILE"] + + resp = http.get uri.request_uri + _(resp.code).must_equal "200" + + Tempfile.open ["google-cloud", ".png"] do |tmpfile| + tmpfile.binmode + tmpfile.write resp.body + _(tmpfile.size).must_equal local_file.size + end + end + end + end + end + end + it "should create a signed read url with space in file name" do local_file = File.new files[:logo][:path] file = bucket.create_file local_file, "CloudLogoSignedUrl GetBucket.png" diff --git a/google-cloud-storage/acceptance/storage/signed_url_v4_test.rb b/google-cloud-storage/acceptance/storage/signed_url_v4_test.rb index eea50fcf071d..e6bdf96f86e5 100644 --- a/google-cloud-storage/acceptance/storage/signed_url_v4_test.rb +++ b/google-cloud-storage/acceptance/storage/signed_url_v4_test.rb @@ -84,6 +84,42 @@ end describe Google::Cloud::Storage::Bucket, :signed_url do + it "should create a signed read url v4 automatically using IAM API when on GCE/Workload Identity" do + local_file = File.new files[:logo][:path] + file = bucket.create_file local_file, "CloudLogoSignedUrlGetBucketAuto.png" + + issuer = bucket.service.credentials.issuer + skip "Test requires a service account with an issuer" unless issuer + + bucket.service.credentials.stub :signing_key, nil do + bucket.service.credentials.stub :issuer, nil do + Google::Cloud.env.stub :compute_engine?, true do + Google::Cloud.env.stub :lookup_metadata, issuer do + five_min_from_now = 5 * 60 + url = bucket.signed_url file.name, + method: "GET", + expires: five_min_from_now, + version: :v4 + + uri = URI url + http = Net::HTTP.new uri.host, uri.port + http.use_ssl = true + http.ca_file ||= ENV["SSL_CERT_FILE"] if ENV["SSL_CERT_FILE"] + + resp = http.get uri.request_uri + _(resp.code).must_equal "200" + + Tempfile.open ["google-cloud", ".png"] do |tmpfile| + tmpfile.binmode + tmpfile.write resp.body + _(tmpfile.size).must_equal local_file.size + end + end + end + end + end + end + it "should create a signed read url version v4 with space in file name" do local_file = File.new files[:logo][:path] file = bucket.create_file local_file, "CloudLogoSignedUrl GetBucket.png" diff --git a/google-cloud-storage/lib/google/cloud/storage/bucket.rb b/google-cloud-storage/lib/google/cloud/storage/bucket.rb index 50cd2c739fcd..debe813efdcb 100644 --- a/google-cloud-storage/lib/google/cloud/storage/bucket.rb +++ b/google-cloud-storage/lib/google/cloud/storage/bucket.rb @@ -2261,6 +2261,10 @@ def compose sources, # steps in [Service Account Authentication]( # https://cloud.google.com/iam/docs/service-accounts). # + # When running in Google Cloud environments (like Compute Engine, Cloud Run, or + # Kubernetes Engine), the library automatically detects the environment and uses + # the IAM Credentials API to sign the URL. A local private key is not required. + # # @see https://cloud.google.com/storage/docs/access-control/signed-urls # Signed URLs guide # @see https://cloud.google.com/storage/docs/access-control/signed-urls#signing-resumable @@ -2284,7 +2288,12 @@ def compose sources, # @param [Hash] headers Google extension headers (custom HTTP headers # that begin with `x-goog-`) that must be included in requests that # use the signed URL. - # @param [String] issuer Service Account's Client Email. + # @param [String] issuer Service Account's Client Email. If not provided, the + # library will attempt to extract it from the standard credentials. If running + # in a Google Cloud environment (like GCE or GKE), the library will automatically + # fetch the default service account email from the metadata server. For external + # Workload Identity Federation (e.g., GitHub Actions or AWS), you must provide this + # value explicitly to use keyless signing. # @param [String] client_email Service Account's Client Email. # @param [OpenSSL::PKey::RSA, String, Proc] signing_key Service Account's # Private Key or a Proc that accepts a single String parameter and returns a @@ -2296,12 +2305,9 @@ def compose sources, # Private Key or a Proc that accepts a single String parameter and returns a # RSA SHA256 signature using a valid Google Service Account Private Key. # - # When using this method in environments such as GAE Flexible Environment, - # GKE, or Cloud Functions where the private key is unavailable, it may be - # necessary to provide a Proc (or lambda) via the signer parameter. This - # Proc should return a signature created using a RPC call to the - # [Service Account Credentials signBlob](https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/signBlob) - # method as shown in the example below. + # A custom proc used to sign the URL. This is no longer required for Workload + # Identity or keyless environments, as the library will automatically fallback to + # the IAM Credentials API if a private key is missing but an `issuer` is available. # @param [Hash] query Query string parameters to include in the signed # URL. The given parameters are not verified by the signature. # diff --git a/google-cloud-storage/lib/google/cloud/storage/file.rb b/google-cloud-storage/lib/google/cloud/storage/file.rb index 8956692f0feb..8a137fd2792a 100644 --- a/google-cloud-storage/lib/google/cloud/storage/file.rb +++ b/google-cloud-storage/lib/google/cloud/storage/file.rb @@ -1741,6 +1741,10 @@ def public_url protocol: :https # steps in [Service Account Authentication]( # https://cloud.google.com/iam/docs/service-accounts). # + # When running in Google Cloud environments (like Compute Engine, Cloud Run, or + # Kubernetes Engine), the library automatically detects the environment and uses + # the IAM Credentials API to sign the URL. A local private key is not required. + # # @see https://cloud.google.com/storage/docs/access-control/signed-urls # Signed URLs guide # @see https://cloud.google.com/storage/docs/access-control/signed-urls#signing-resumable @@ -1762,7 +1766,12 @@ def public_url protocol: :https # @param [Hash] headers Google extension headers (custom HTTP headers # that begin with `x-goog-`) that must be included in requests that # use the signed URL. - # @param [String] issuer Service Account's Client Email. + # @param [String] issuer Service Account's Client Email. If not provided, the + # library will attempt to extract it from the standard credentials. If running + # in a Google Cloud environment (like GCE or GKE), the library will automatically + # fetch the default service account email from the metadata server. For external + # Workload Identity Federation (e.g., GitHub Actions or AWS), you must provide this + # value explicitly to use keyless signing. # @param [String] client_email Service Account's Client Email. # @param [OpenSSL::PKey::RSA, String, Proc] signing_key Service Account's # Private Key or a Proc that accepts a single String parameter and returns a @@ -1774,12 +1783,9 @@ def public_url protocol: :https # Private Key or a Proc that accepts a single String parameter and returns a # RSA SHA256 signature using a valid Google Service Account Private Key. # - # When using this method in environments such as GAE Flexible Environment, - # GKE, or Cloud Functions where the private key is unavailable, it may be - # necessary to provide a Proc (or lambda) via the signer parameter. This - # Proc should return a signature created using a RPC call to the - # [Service Account Credentials signBlob](https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/signBlob) - # method as shown in the example below. + # A custom proc used to sign the URL. This is no longer required for Workload + # Identity or keyless environments, as the library will automatically fallback to + # the IAM Credentials API if a private key is missing but an `issuer` is available. # @param [Hash] query Query string parameters to include in the signed # URL. The given parameters are not verified by the signature. # diff --git a/google-cloud-storage/lib/google/cloud/storage/file/signer_v2.rb b/google-cloud-storage/lib/google/cloud/storage/file/signer_v2.rb index b07889464f50..2087c362aa34 100644 --- a/google-cloud-storage/lib/google/cloud/storage/file/signer_v2.rb +++ b/google-cloud-storage/lib/google/cloud/storage/file/signer_v2.rb @@ -78,14 +78,15 @@ def signature_str options end def determine_signing_key options = {} - signing_key = options[:signing_key] || options[:private_key] || - options[:signer] || @service.credentials.signing_key - raise SignedUrlUnavailable, error_msg("signing_key (private_key, signer)") unless signing_key - signing_key + options[:signing_key] || options[:private_key] || + options[:signer] || @service.credentials.signing_key end def determine_issuer options = {} issuer = options[:issuer] || options[:client_email] || @service.credentials.issuer + if issuer.nil? && Google::Cloud.env.compute_engine? + issuer = Google::Cloud.env.lookup_metadata "instance", "service-accounts/default/email" + end raise SignedUrlUnavailable, error_msg("issuer (client_email)") unless issuer issuer end @@ -111,7 +112,7 @@ def post_object options policy_str = p.to_json policy = Base64.strict_encode64(policy_str).delete "\n" - signature = generate_signature s, policy + signature = generate_signature i, s, policy fields[:GoogleAccessId] = i fields[:signature] = signature @@ -126,19 +127,23 @@ def signed_url options i = determine_issuer options s = determine_signing_key options - sig = generate_signature s, signature_str(options) + sig = generate_signature i, s, signature_str(options) generate_signed_url i, sig, options[:expires], options[:query] end - def generate_signature signing_key, secret + def generate_signature issuer, signing_key, secret unencoded_signature = "" - if signing_key.is_a? Proc - unencoded_signature = signing_key.call secret - else - unless signing_key.respond_to? :sign - signing_key = OpenSSL::PKey::RSA.new signing_key + if signing_key + if signing_key.is_a? Proc + unencoded_signature = signing_key.call secret + else + unless signing_key.respond_to? :sign + signing_key = OpenSSL::PKey::RSA.new signing_key + end + unencoded_signature = signing_key.sign OpenSSL::Digest::SHA256.new, secret end - unencoded_signature = signing_key.sign OpenSSL::Digest::SHA256.new, secret + else + unencoded_signature = iam_signer_instance.sign issuer, secret end Base64.strict_encode64(unencoded_signature).delete "\n" end @@ -168,6 +173,13 @@ def format_extension_headers headers def url_escape str CGI.escape String str end + + def iam_signer_instance + @iam_signer_instance ||= begin + require "google/cloud/storage/iam_signer" + Google::Cloud::Storage::IAMSigner.new + end + end end end end diff --git a/google-cloud-storage/lib/google/cloud/storage/file/signer_v4.rb b/google-cloud-storage/lib/google/cloud/storage/file/signer_v4.rb index fe84fa82d0cf..1a9936d421b9 100644 --- a/google-cloud-storage/lib/google/cloud/storage/file/signer_v4.rb +++ b/google-cloud-storage/lib/google/cloud/storage/file/signer_v4.rb @@ -66,7 +66,7 @@ def post_object issuer: nil, policy_str = escape_characters p.to_json policy = Base64.strict_encode64(policy_str).force_encoding "utf-8" - signature = generate_signature s, policy + signature = generate_signature i, s, policy post_fields["x-goog-signature"] = signature post_fields["policy"] = policy @@ -195,14 +195,15 @@ def signed_url_hostname scheme, virtual_hosted_style, bucket_bound_hostname def determine_issuer issuer, client_email # Parse the Service Account and get client id and private key issuer = issuer || client_email || @service.credentials.issuer + if issuer.nil? && Google::Cloud.env.compute_engine? + issuer = Google::Cloud.env.lookup_metadata "instance", "service-accounts/default/email" + end raise SignedUrlUnavailable, error_msg("issuer (client_email)") unless issuer issuer end def determine_signing_key signing_key, private_key, signer - signing_key = signing_key || private_key || signer || @service.credentials.signing_key - raise SignedUrlUnavailable, error_msg("signing_key (private_key, signer)") unless signing_key - signing_key + signing_key || private_key || signer || @service.credentials.signing_key end def error_msg attr_name @@ -229,7 +230,14 @@ def service_account_signer signer def issuer_and_signer issuer, client_email, signing_key, private_key, signer issuer = determine_issuer issuer, client_email signing_key = determine_signing_key signing_key, private_key, signer - signer = service_account_signer signing_key + if signing_key + signer = service_account_signer signing_key + else + signer = lambda do |string_to_sign| + sig = iam_signer_instance.sign issuer, string_to_sign + sig.unpack1 "H*" + end + end [issuer, signer] end @@ -351,18 +359,29 @@ def post_object_ext_url scheme, virtual_hosted_style, bucket_bound_hostname end end - def generate_signature signing_key, data + def generate_signature issuer, signing_key, data packed_signature = nil - if signing_key.is_a? Proc - packed_signature = signing_key.call data - else - unless signing_key.respond_to? :sign - signing_key = OpenSSL::PKey::RSA.new signing_key + if signing_key + if signing_key.is_a? Proc + packed_signature = signing_key.call data + else + unless signing_key.respond_to? :sign + signing_key = OpenSSL::PKey::RSA.new signing_key + end + packed_signature = signing_key.sign OpenSSL::Digest::SHA256.new, data end - packed_signature = signing_key.sign OpenSSL::Digest::SHA256.new, data + else + packed_signature = iam_signer_instance.sign issuer, data end packed_signature.unpack1("H*").force_encoding "utf-8" end + + def iam_signer_instance + @iam_signer_instance ||= begin + require "google/cloud/storage/iam_signer" + Google::Cloud::Storage::IAMSigner.new + end + end end end end diff --git a/google-cloud-storage/lib/google/cloud/storage/iam_signer.rb b/google-cloud-storage/lib/google/cloud/storage/iam_signer.rb new file mode 100644 index 000000000000..8eda6959b275 --- /dev/null +++ b/google-cloud-storage/lib/google/cloud/storage/iam_signer.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +require "googleauth" + +module Google + module Cloud + module Storage + ## + # @private + # Helper class for signing blobs via the IAM Credentials API. + class IAMSigner + def initialize + require "google/apis/iamcredentials_v1" + + @client = Google::Apis::IamcredentialsV1::IAMCredentialsService.new + @client.authorization = Google::Auth.get_application_default( + ["https://www.googleapis.com/auth/iam"] + ) + end + + def sign issuer, string_to_sign + request = Google::Apis::IamcredentialsV1::SignBlobRequest.new( + payload: string_to_sign + ) + resource = "projects/-/serviceAccounts/#{issuer}" + + response = @client.sign_service_account_blob resource, request + + response.signed_blob + end + end + end + end +end diff --git a/google-cloud-storage/samples/acceptance/files_test.rb b/google-cloud-storage/samples/acceptance/files_test.rb index aa8bf1f10f49..84c129cab6fd 100644 --- a/google-cloud-storage/samples/acceptance/files_test.rb +++ b/google-cloud-storage/samples/acceptance/files_test.rb @@ -29,6 +29,7 @@ require_relative "../storage_generate_encryption_key" require_relative "../storage_generate_signed_post_policy_v4" require_relative "../storage_generate_signed_url_v4" +require_relative "../storage_generate_signed_url_v4_workload_identity" require_relative "../storage_generate_upload_signed_url_v4" require_relative "../storage_get_metadata" require_relative "../storage_get_object_contexts" @@ -606,6 +607,35 @@ def mock_cipher.random_key assert bucket.file remote_file_name end + + it "generate_signed_url_v4_workload_identity" do + bucket.create_file local_file, remote_file_name + + # Skip this test if credentials lack an issuer since it is a prerequisite for automatic fallback + issuer = bucket.service.credentials.issuer + skip "Test requires a service account with an issuer" unless issuer + + # Temporarily remove private key to trigger keyless environment logic + bucket.service.credentials.stub :signing_key, nil do + bucket.service.credentials.stub :issuer, nil do + Google::Cloud.env.stub :compute_engine?, true do + Google::Cloud.env.stub :lookup_metadata, issuer do + out, _err = capture_io do + generate_signed_url_v4_workload_identity bucket_name: bucket.name, + file_name: remote_file_name + end + + signed_url = out.scan(/http.*$/).first + refute_nil signed_url + + file_contents = Net::HTTP.get URI(signed_url) + assert_equal file_contents, File.read(local_file) + end + end + end + end + end + describe "post object" do require "net/http" require "uri" diff --git a/google-cloud-storage/samples/storage_generate_signed_url_v4_workload_identity.rb b/google-cloud-storage/samples/storage_generate_signed_url_v4_workload_identity.rb new file mode 100644 index 000000000000..156c44f195c3 --- /dev/null +++ b/google-cloud-storage/samples/storage_generate_signed_url_v4_workload_identity.rb @@ -0,0 +1,44 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# [START storage_generate_signed_url_v4_workload_identity] +def generate_signed_url_v4_workload_identity bucket_name:, file_name: + # The ID of your GCS bucket + # bucket_name = "your-unique-bucket-name" + + # The ID of your GCS object + # file_name = "your-file-name" + + require "google/cloud/storage" + + # Initialize the client. In a Google Cloud environment (like GKE Workload + # Identity or Compute Engine), credentials are automatically discovered. + storage = Google::Cloud::Storage.new + storage_expiry_time = 5 * 60 # 5 minutes + + # Generate the signed URL. The google-cloud-storage library will automatically + # detect the keyless environment and fallback to using the IAM Credentials API + # to sign the URL. + url = storage.signed_url bucket_name, file_name, method: "GET", + expires: storage_expiry_time, + version: :v4 + + puts "Generated GET signed url:" + puts url + puts "You can use this URL with any user agent, for example:" + puts "curl '#{url}'" +end +# [END storage_generate_signed_url_v4_workload_identity] + +generate_signed_url_v4_workload_identity bucket_name: ARGV.shift, file_name: ARGV.shift if $PROGRAM_NAME == __FILE__ diff --git a/google-cloud-storage/test/google/cloud/storage/bucket_signed_url_v2_test.rb b/google-cloud-storage/test/google/cloud/storage/bucket_signed_url_v2_test.rb index 49a5fe59b9a0..1f7a45177fc6 100644 --- a/google-cloud-storage/test/google/cloud/storage/bucket_signed_url_v2_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/bucket_signed_url_v2_test.rb @@ -143,22 +143,33 @@ end end - it "raises when missing issuer" do + it "raises SignedUrlUnavailable when missing both signing_key and issuer" do + + credentials.issuer = nil - credentials.signing_key = PoisonSigningKey.new - expect { - bucket.signed_url file_path - }.must_raise Google::Cloud::Storage::SignedUrlUnavailable - end - it "raises when missing signing_key" do - credentials.issuer = "native_issuer" credentials.signing_key = nil - expect { - bucket.signed_url file_path - }.must_raise Google::Cloud::Storage::SignedUrlUnavailable + + + + + Google::Cloud.env.stub :compute_engine?, false do + + + expect { + + + bucket.signed_url file_path + + + }.must_raise Google::Cloud::Storage::SignedUrlUnavailable + + + end + + end it "raises with issuer and lambda with incorrect argument count" do diff --git a/google-cloud-storage/test/google/cloud/storage/bucket_signed_url_v4_test.rb b/google-cloud-storage/test/google/cloud/storage/bucket_signed_url_v4_test.rb index e30573d22700..0cf8dcd6db28 100644 --- a/google-cloud-storage/test/google/cloud/storage/bucket_signed_url_v4_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/bucket_signed_url_v4_test.rb @@ -169,22 +169,33 @@ end end - it "raises when missing issuer" do + it "raises SignedUrlUnavailable when missing both signing_key and issuer" do + + credentials.issuer = nil - credentials.signing_key = PoisonSigningKey.new - expect { - bucket.signed_url file_path, version: :v4 - }.must_raise Google::Cloud::Storage::SignedUrlUnavailable - end - it "raises when missing signing_key" do - credentials.issuer = "native_issuer" credentials.signing_key = nil - expect { - bucket.signed_url file_path, version: :v4 - }.must_raise Google::Cloud::Storage::SignedUrlUnavailable + + + + + Google::Cloud.env.stub :compute_engine?, false do + + + expect { + + + bucket.signed_url file_path, version: :v4 + + + }.must_raise Google::Cloud::Storage::SignedUrlUnavailable + + + end + + end it "raises with issuer and lambda with incorrect argument count" do diff --git a/google-cloud-storage/test/google/cloud/storage/file_signed_url_v2_test.rb b/google-cloud-storage/test/google/cloud/storage/file_signed_url_v2_test.rb index 7bfde415e579..ff8f247cd6e1 100644 --- a/google-cloud-storage/test/google/cloud/storage/file_signed_url_v2_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/file_signed_url_v2_test.rb @@ -13,6 +13,7 @@ # limitations under the License. require "helper" +require "google/cloud/storage/iam_signer" describe Google::Cloud::Storage::File, :signed_url, :mock_storage do let(:bucket_name) { "bucket" } @@ -144,22 +145,61 @@ end end - it "raises when missing issuer" do + it "raises SignedUrlUnavailable when missing both signing_key and issuer" do credentials.issuer = nil - credentials.signing_key = PoisonSigningKey.new + credentials.signing_key = nil - expect { - file.signed_url - }.must_raise Google::Cloud::Storage::SignedUrlUnavailable + Google::Cloud.env.stub :compute_engine?, false do + expect { + file.signed_url + }.must_raise Google::Cloud::Storage::SignedUrlUnavailable + end end - it "raises when missing signing_key" do - credentials.issuer = "native_issuer" - credentials.signing_key = nil + it "falls back to IAMSigner when missing signing_key" do + Time.stub :now, Time.new(2012,1,1,0,0,0, "+00:00") do + credentials.issuer = "native_issuer@email.com" + credentials.signing_key = nil - expect { - file.signed_url - }.must_raise Google::Cloud::Storage::SignedUrlUnavailable + iam_signer_mock = Minitest::Mock.new + iam_signer_mock.expect :sign, "iam-signature", ["native_issuer@email.com", "GET\n\n\n1325376300\n/bucket/file.ext"] + + Google::Cloud.env.stub :compute_engine?, false do + Google::Cloud::Storage::IAMSigner.stub :new, iam_signer_mock do + signed_url = file.signed_url + + signed_url_params = CGI::parse(URI(signed_url).query) + _(signed_url_params["GoogleAccessId"]).must_equal ["native_issuer@email.com"] + _(signed_url_params["Signature"]).must_equal [Base64.strict_encode64("iam-signature").delete("\n")] + end + end + + iam_signer_mock.verify + end + end + + it "uses IAMSigner and auto-detects issuer if compute_engine? is true" do + Time.stub :now, Time.new(2012,1,1,0,0,0, "+00:00") do + credentials.issuer = nil + credentials.signing_key = nil + + iam_signer_mock = Minitest::Mock.new + iam_signer_mock.expect :sign, "iam-signature", ["metadata_issuer@email.com", "GET\n\n\n1325376300\n/bucket/file.ext"] + + Google::Cloud.env.stub :compute_engine?, true do + Google::Cloud.env.stub :lookup_metadata, "metadata_issuer@email.com" do + Google::Cloud::Storage::IAMSigner.stub :new, iam_signer_mock do + signed_url = file.signed_url + + signed_url_params = CGI::parse(URI(signed_url).query) + _(signed_url_params["GoogleAccessId"]).must_equal ["metadata_issuer@email.com"] + _(signed_url_params["Signature"]).must_equal [Base64.strict_encode64("iam-signature").delete("\n")] + end + end + end + + iam_signer_mock.verify + end end it "raises with issuer and lambda with incorrect argument count" do diff --git a/google-cloud-storage/test/google/cloud/storage/file_signed_url_v4_test.rb b/google-cloud-storage/test/google/cloud/storage/file_signed_url_v4_test.rb index 6f6818d1a6b4..1001e6ded350 100644 --- a/google-cloud-storage/test/google/cloud/storage/file_signed_url_v4_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/file_signed_url_v4_test.rb @@ -13,6 +13,7 @@ # limitations under the License. require "helper" +require "google/cloud/storage/iam_signer" describe Google::Cloud::Storage::File, :signed_url, :v4, :mock_storage do let(:bucket_name) { "bucket" } @@ -145,22 +146,61 @@ end end - it "raises when missing issuer" do + it "raises SignedUrlUnavailable when missing both signing_key and issuer" do credentials.issuer = nil - credentials.signing_key = PoisonSigningKey.new + credentials.signing_key = nil - expect { - file.signed_url version: :v4 - }.must_raise Google::Cloud::Storage::SignedUrlUnavailable + Google::Cloud.env.stub :compute_engine?, false do + expect { + file.signed_url version: :v4 + }.must_raise Google::Cloud::Storage::SignedUrlUnavailable + end end - it "raises when missing signing_key" do - credentials.issuer = "native_issuer" - credentials.signing_key = nil + it "falls back to IAMSigner when missing signing_key" do + Time.stub :now, Time.new(2012,1,1,0,0,0, "+00:00") do + credentials.issuer = "native_issuer@email.com" + credentials.signing_key = nil - expect { - file.signed_url version: :v4 - }.must_raise Google::Cloud::Storage::SignedUrlUnavailable + iam_signer_mock = Minitest::Mock.new + iam_signer_mock.expect :sign, "iam-signature", ["native_issuer@email.com", String] + + Google::Cloud.env.stub :compute_engine?, false do + Google::Cloud::Storage::IAMSigner.stub :new, iam_signer_mock do + signed_url = file.signed_url version: :v4 + + signed_url_params = CGI::parse(URI(signed_url).query) + _(signed_url_params["X-Goog-Credential"]).must_equal ["native_issuer@email.com/20120101/auto/storage/goog4_request"] + _(signed_url_params["X-Goog-Signature"]).must_equal ["iam-signature".unpack1("H*")] + end + end + + iam_signer_mock.verify + end + end + + it "uses IAMSigner and auto-detects issuer if compute_engine? is true" do + Time.stub :now, Time.new(2012,1,1,0,0,0, "+00:00") do + credentials.issuer = nil + credentials.signing_key = nil + + iam_signer_mock = Minitest::Mock.new + iam_signer_mock.expect :sign, "iam-signature", ["metadata_issuer@email.com", String] + + Google::Cloud.env.stub :compute_engine?, true do + Google::Cloud.env.stub :lookup_metadata, "metadata_issuer@email.com" do + Google::Cloud::Storage::IAMSigner.stub :new, iam_signer_mock do + signed_url = file.signed_url version: :v4 + + signed_url_params = CGI::parse(URI(signed_url).query) + _(signed_url_params["X-Goog-Credential"]).must_equal ["metadata_issuer@email.com/20120101/auto/storage/goog4_request"] + _(signed_url_params["X-Goog-Signature"]).must_equal ["iam-signature".unpack1("H*")] + end + end + end + + iam_signer_mock.verify + end end it "raises with issuer and lambda with incorrect argument count" do diff --git a/google-cloud-storage/test/google/cloud/storage/iam_signer_test.rb b/google-cloud-storage/test/google/cloud/storage/iam_signer_test.rb new file mode 100644 index 000000000000..0f057e225d70 --- /dev/null +++ b/google-cloud-storage/test/google/cloud/storage/iam_signer_test.rb @@ -0,0 +1,49 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +require "helper" +require "google/cloud/storage/iam_signer" +require "google/apis/iamcredentials_v1" + +describe Google::Cloud::Storage::IAMSigner do + it "signs a payload using IAMCredentialsService" do + issuer = "test@email.com" + payload = "my-payload" + expected_resource = "projects/-/serviceAccounts/test@email.com" + expected_signature = "mocked-signature" + + mock_auth = Minitest::Mock.new + + mock_response = Minitest::Mock.new + mock_response.expect :signed_blob, expected_signature + + mock_service = Minitest::Mock.new + mock_service.expect :authorization=, nil, [mock_auth] + mock_service.expect :sign_service_account_blob, mock_response do |resource, request| + resource == expected_resource && request.payload == payload + end + + Google::Auth.stub :get_application_default, mock_auth do + Google::Apis::IamcredentialsV1::IAMCredentialsService.stub :new, mock_service do + signer = Google::Cloud::Storage::IAMSigner.new + signature = signer.sign issuer, payload + + _(signature).must_equal expected_signature + end + end + + mock_service.verify + mock_response.verify + end +end diff --git a/google-cloud-storage/test/google/cloud/storage/lazy/bucket_signed_url_v2_test.rb b/google-cloud-storage/test/google/cloud/storage/lazy/bucket_signed_url_v2_test.rb index aef004762e0f..8cc960fd5d6a 100644 --- a/google-cloud-storage/test/google/cloud/storage/lazy/bucket_signed_url_v2_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/lazy/bucket_signed_url_v2_test.rb @@ -101,22 +101,33 @@ end end - it "raises when missing issuer" do + it "raises SignedUrlUnavailable when missing both signing_key and issuer" do + + credentials.issuer = nil - credentials.signing_key = PoisonSigningKey.new - expect { - bucket.signed_url file_path - }.must_raise Google::Cloud::Storage::SignedUrlUnavailable - end - it "raises when missing signing_key" do - credentials.issuer = "native_issuer" credentials.signing_key = nil - expect { - bucket.signed_url file_path - }.must_raise Google::Cloud::Storage::SignedUrlUnavailable + + + + + Google::Cloud.env.stub :compute_engine?, false do + + + expect { + + + bucket.signed_url file_path + + + }.must_raise Google::Cloud::Storage::SignedUrlUnavailable + + + end + + end describe "Files with spaces in them" do diff --git a/google-cloud-storage/test/google/cloud/storage/lazy/bucket_signed_url_v4_test.rb b/google-cloud-storage/test/google/cloud/storage/lazy/bucket_signed_url_v4_test.rb index 9b2251ad8ced..cf9038823b31 100644 --- a/google-cloud-storage/test/google/cloud/storage/lazy/bucket_signed_url_v4_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/lazy/bucket_signed_url_v4_test.rb @@ -120,22 +120,33 @@ end end - it "raises when missing issuer" do + it "raises SignedUrlUnavailable when missing both signing_key and issuer" do + + credentials.issuer = nil - credentials.signing_key = PoisonSigningKey.new - expect { - bucket.signed_url file_path, version: :v4 - }.must_raise Google::Cloud::Storage::SignedUrlUnavailable - end - it "raises when missing signing_key" do - credentials.issuer = "native_issuer" credentials.signing_key = nil - expect { - bucket.signed_url file_path, version: :v4 - }.must_raise Google::Cloud::Storage::SignedUrlUnavailable + + + + + Google::Cloud.env.stub :compute_engine?, false do + + + expect { + + + bucket.signed_url file_path, version: :v4 + + + }.must_raise Google::Cloud::Storage::SignedUrlUnavailable + + + end + + end it "allows query params to be passed in" do diff --git a/google-cloud-storage/test/google/cloud/storage/lazy/file_signed_url_v2_test.rb b/google-cloud-storage/test/google/cloud/storage/lazy/file_signed_url_v2_test.rb index 384651493002..cc023e2d378f 100644 --- a/google-cloud-storage/test/google/cloud/storage/lazy/file_signed_url_v2_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/lazy/file_signed_url_v2_test.rb @@ -123,22 +123,33 @@ end end - it "raises when missing issuer" do + it "raises SignedUrlUnavailable when missing both signing_key and issuer" do + + credentials.issuer = nil - credentials.signing_key = PoisonSigningKey.new - expect { - file.signed_url - }.must_raise Google::Cloud::Storage::SignedUrlUnavailable - end - it "raises when missing signing_key" do - credentials.issuer = "native_issuer" credentials.signing_key = nil - expect { - file.signed_url - }.must_raise Google::Cloud::Storage::SignedUrlUnavailable + + + + + Google::Cloud.env.stub :compute_engine?, false do + + + expect { + + + file.signed_url + + + }.must_raise Google::Cloud::Storage::SignedUrlUnavailable + + + end + + end describe "Files with spaces in them" do diff --git a/google-cloud-storage/test/google/cloud/storage/lazy/file_signed_url_v4_test.rb b/google-cloud-storage/test/google/cloud/storage/lazy/file_signed_url_v4_test.rb index d6123dc6a5b8..d4729d143d1e 100644 --- a/google-cloud-storage/test/google/cloud/storage/lazy/file_signed_url_v4_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/lazy/file_signed_url_v4_test.rb @@ -118,22 +118,33 @@ end end - it "raises when missing issuer" do + it "raises SignedUrlUnavailable when missing both signing_key and issuer" do + + credentials.issuer = nil - credentials.signing_key = PoisonSigningKey.new - expect { - file.signed_url version: :v4 - }.must_raise Google::Cloud::Storage::SignedUrlUnavailable - end - it "raises when missing signing_key" do - credentials.issuer = "native_issuer" credentials.signing_key = nil - expect { - file.signed_url version: :v4 - }.must_raise Google::Cloud::Storage::SignedUrlUnavailable + + + + + Google::Cloud.env.stub :compute_engine?, false do + + + expect { + + + file.signed_url version: :v4 + + + }.must_raise Google::Cloud::Storage::SignedUrlUnavailable + + + end + + end it "allows query params to be passed in" do diff --git a/google-cloud-storage/test/google/cloud/storage/project_signed_url_v2_test.rb b/google-cloud-storage/test/google/cloud/storage/project_signed_url_v2_test.rb index bdeb28976e5a..476b0bdb7748 100644 --- a/google-cloud-storage/test/google/cloud/storage/project_signed_url_v2_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/project_signed_url_v2_test.rb @@ -141,22 +141,33 @@ end end - it "raises when missing issuer" do + it "raises SignedUrlUnavailable when missing both signing_key and issuer" do + + credentials.issuer = nil - credentials.signing_key = PoisonSigningKey.new - expect { - storage.signed_url bucket_name, file_path - }.must_raise Google::Cloud::Storage::SignedUrlUnavailable - end - it "raises when missing signing_key" do - credentials.issuer = "native_issuer" credentials.signing_key = nil - expect { - storage.signed_url bucket_name, file_path - }.must_raise Google::Cloud::Storage::SignedUrlUnavailable + + + + + Google::Cloud.env.stub :compute_engine?, false do + + + expect { + + + storage.signed_url bucket_name, file_path + + + }.must_raise Google::Cloud::Storage::SignedUrlUnavailable + + + end + + end it "raises with issuer and lambda with incorrect argument count" do diff --git a/google-cloud-storage/test/google/cloud/storage/project_signed_url_v4_test.rb b/google-cloud-storage/test/google/cloud/storage/project_signed_url_v4_test.rb index 8005f6fa84a9..7cc879e1ab3b 100644 --- a/google-cloud-storage/test/google/cloud/storage/project_signed_url_v4_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/project_signed_url_v4_test.rb @@ -142,22 +142,33 @@ end end - it "raises when missing issuer" do + it "raises SignedUrlUnavailable when missing both signing_key and issuer" do + + credentials.issuer = nil - credentials.signing_key = PoisonSigningKey.new - expect { - storage.signed_url bucket_name, file_path, version: :v4 - }.must_raise Google::Cloud::Storage::SignedUrlUnavailable - end - it "raises when missing signing_key" do - credentials.issuer = "native_issuer" credentials.signing_key = nil - expect { - storage.signed_url bucket_name, file_path, version: :v4 - }.must_raise Google::Cloud::Storage::SignedUrlUnavailable + + + + + Google::Cloud.env.stub :compute_engine?, false do + + + expect { + + + storage.signed_url bucket_name, file_path, version: :v4 + + + }.must_raise Google::Cloud::Storage::SignedUrlUnavailable + + + end + + end it "raises with issuer and lambda with incorrect argument count" do From b753e0b0c9d56759bf1b101c343f83b7c68bde0a Mon Sep 17 00:00:00 2001 From: Shubhangi Singh Date: Fri, 11 Sep 2026 03:45:41 +0000 Subject: [PATCH 2/2] adding support for all serverless environment --- .../acceptance/storage/signed_url_v2_test.rb | 2 +- .../acceptance/storage/signed_url_v4_test.rb | 2 +- .../lib/google/cloud/storage/file/signer_v2.rb | 4 ++-- .../lib/google/cloud/storage/file/signer_v4.rb | 4 ++-- .../lib/google/cloud/storage/iam_signer.rb | 15 ++++++++------- .../samples/acceptance/files_test.rb | 2 +- .../cloud/storage/bucket_signed_url_v2_test.rb | 2 +- .../cloud/storage/bucket_signed_url_v4_test.rb | 2 +- .../cloud/storage/file_signed_url_v2_test.rb | 8 ++++---- .../cloud/storage/file_signed_url_v4_test.rb | 8 ++++---- .../test/google/cloud/storage/iam_signer_test.rb | 13 +++++++------ .../storage/lazy/bucket_signed_url_v2_test.rb | 2 +- .../storage/lazy/bucket_signed_url_v4_test.rb | 2 +- .../cloud/storage/lazy/file_signed_url_v2_test.rb | 2 +- .../cloud/storage/lazy/file_signed_url_v4_test.rb | 2 +- .../cloud/storage/project_signed_url_v2_test.rb | 2 +- .../cloud/storage/project_signed_url_v4_test.rb | 2 +- 17 files changed, 38 insertions(+), 36 deletions(-) diff --git a/google-cloud-storage/acceptance/storage/signed_url_v2_test.rb b/google-cloud-storage/acceptance/storage/signed_url_v2_test.rb index 4cbd0b113330..06ec7b5ff296 100644 --- a/google-cloud-storage/acceptance/storage/signed_url_v2_test.rb +++ b/google-cloud-storage/acceptance/storage/signed_url_v2_test.rb @@ -93,7 +93,7 @@ bucket.service.credentials.stub :signing_key, nil do bucket.service.credentials.stub :issuer, nil do - Google::Cloud.env.stub :compute_engine?, true do + Google::Cloud.env.stub :metadata?, true do Google::Cloud.env.stub :lookup_metadata, issuer do five_min_from_now = 5 * 60 url = bucket.signed_url file.name, diff --git a/google-cloud-storage/acceptance/storage/signed_url_v4_test.rb b/google-cloud-storage/acceptance/storage/signed_url_v4_test.rb index e6bdf96f86e5..8720dacd6d3c 100644 --- a/google-cloud-storage/acceptance/storage/signed_url_v4_test.rb +++ b/google-cloud-storage/acceptance/storage/signed_url_v4_test.rb @@ -93,7 +93,7 @@ bucket.service.credentials.stub :signing_key, nil do bucket.service.credentials.stub :issuer, nil do - Google::Cloud.env.stub :compute_engine?, true do + Google::Cloud.env.stub :metadata?, true do Google::Cloud.env.stub :lookup_metadata, issuer do five_min_from_now = 5 * 60 url = bucket.signed_url file.name, diff --git a/google-cloud-storage/lib/google/cloud/storage/file/signer_v2.rb b/google-cloud-storage/lib/google/cloud/storage/file/signer_v2.rb index 2087c362aa34..c0c117c4820e 100644 --- a/google-cloud-storage/lib/google/cloud/storage/file/signer_v2.rb +++ b/google-cloud-storage/lib/google/cloud/storage/file/signer_v2.rb @@ -84,7 +84,7 @@ def determine_signing_key options = {} def determine_issuer options = {} issuer = options[:issuer] || options[:client_email] || @service.credentials.issuer - if issuer.nil? && Google::Cloud.env.compute_engine? + if issuer.nil? && Google::Cloud.env.metadata? issuer = Google::Cloud.env.lookup_metadata "instance", "service-accounts/default/email" end raise SignedUrlUnavailable, error_msg("issuer (client_email)") unless issuer @@ -177,7 +177,7 @@ def url_escape str def iam_signer_instance @iam_signer_instance ||= begin require "google/cloud/storage/iam_signer" - Google::Cloud::Storage::IAMSigner.new + Google::Cloud::Storage::IAMSigner.new(@service.credentials) end end end diff --git a/google-cloud-storage/lib/google/cloud/storage/file/signer_v4.rb b/google-cloud-storage/lib/google/cloud/storage/file/signer_v4.rb index 1a9936d421b9..78669a973e70 100644 --- a/google-cloud-storage/lib/google/cloud/storage/file/signer_v4.rb +++ b/google-cloud-storage/lib/google/cloud/storage/file/signer_v4.rb @@ -195,7 +195,7 @@ def signed_url_hostname scheme, virtual_hosted_style, bucket_bound_hostname def determine_issuer issuer, client_email # Parse the Service Account and get client id and private key issuer = issuer || client_email || @service.credentials.issuer - if issuer.nil? && Google::Cloud.env.compute_engine? + if issuer.nil? && Google::Cloud.env.metadata? issuer = Google::Cloud.env.lookup_metadata "instance", "service-accounts/default/email" end raise SignedUrlUnavailable, error_msg("issuer (client_email)") unless issuer @@ -379,7 +379,7 @@ def generate_signature issuer, signing_key, data def iam_signer_instance @iam_signer_instance ||= begin require "google/cloud/storage/iam_signer" - Google::Cloud::Storage::IAMSigner.new + Google::Cloud::Storage::IAMSigner.new(@service.credentials) end end end diff --git a/google-cloud-storage/lib/google/cloud/storage/iam_signer.rb b/google-cloud-storage/lib/google/cloud/storage/iam_signer.rb index 8eda6959b275..825305d8618a 100644 --- a/google-cloud-storage/lib/google/cloud/storage/iam_signer.rb +++ b/google-cloud-storage/lib/google/cloud/storage/iam_signer.rb @@ -23,13 +23,11 @@ module Storage # @private # Helper class for signing blobs via the IAM Credentials API. class IAMSigner - def initialize + def initialize credentials require "google/apis/iamcredentials_v1" @client = Google::Apis::IamcredentialsV1::IAMCredentialsService.new - @client.authorization = Google::Auth.get_application_default( - ["https://www.googleapis.com/auth/iam"] - ) + @client.authorization = credentials.client end def sign issuer, string_to_sign @@ -38,9 +36,12 @@ def sign issuer, string_to_sign ) resource = "projects/-/serviceAccounts/#{issuer}" - response = @client.sign_service_account_blob resource, request - - response.signed_blob + begin + response = @client.sign_service_account_blob resource, request + response.signed_blob + rescue Google::Apis::Error => e + raise Google::Cloud::Storage::SignedUrlUnavailable, "Failed to sign URL via IAM Credentials API. Ensure the Workload Identity service account has the 'Service Account Token Creator' role. Underlying error: #{e.message}" + end end end end diff --git a/google-cloud-storage/samples/acceptance/files_test.rb b/google-cloud-storage/samples/acceptance/files_test.rb index 84c129cab6fd..21e5023d66d3 100644 --- a/google-cloud-storage/samples/acceptance/files_test.rb +++ b/google-cloud-storage/samples/acceptance/files_test.rb @@ -618,7 +618,7 @@ def mock_cipher.random_key # Temporarily remove private key to trigger keyless environment logic bucket.service.credentials.stub :signing_key, nil do bucket.service.credentials.stub :issuer, nil do - Google::Cloud.env.stub :compute_engine?, true do + Google::Cloud.env.stub :metadata?, true do Google::Cloud.env.stub :lookup_metadata, issuer do out, _err = capture_io do generate_signed_url_v4_workload_identity bucket_name: bucket.name, diff --git a/google-cloud-storage/test/google/cloud/storage/bucket_signed_url_v2_test.rb b/google-cloud-storage/test/google/cloud/storage/bucket_signed_url_v2_test.rb index 1f7a45177fc6..91b3e4546eac 100644 --- a/google-cloud-storage/test/google/cloud/storage/bucket_signed_url_v2_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/bucket_signed_url_v2_test.rb @@ -155,7 +155,7 @@ - Google::Cloud.env.stub :compute_engine?, false do + Google::Cloud.env.stub :metadata?, false do expect { diff --git a/google-cloud-storage/test/google/cloud/storage/bucket_signed_url_v4_test.rb b/google-cloud-storage/test/google/cloud/storage/bucket_signed_url_v4_test.rb index 0cf8dcd6db28..72b452e99c23 100644 --- a/google-cloud-storage/test/google/cloud/storage/bucket_signed_url_v4_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/bucket_signed_url_v4_test.rb @@ -181,7 +181,7 @@ - Google::Cloud.env.stub :compute_engine?, false do + Google::Cloud.env.stub :metadata?, false do expect { diff --git a/google-cloud-storage/test/google/cloud/storage/file_signed_url_v2_test.rb b/google-cloud-storage/test/google/cloud/storage/file_signed_url_v2_test.rb index ff8f247cd6e1..3bffb38f88d4 100644 --- a/google-cloud-storage/test/google/cloud/storage/file_signed_url_v2_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/file_signed_url_v2_test.rb @@ -149,7 +149,7 @@ credentials.issuer = nil credentials.signing_key = nil - Google::Cloud.env.stub :compute_engine?, false do + Google::Cloud.env.stub :metadata?, false do expect { file.signed_url }.must_raise Google::Cloud::Storage::SignedUrlUnavailable @@ -164,7 +164,7 @@ iam_signer_mock = Minitest::Mock.new iam_signer_mock.expect :sign, "iam-signature", ["native_issuer@email.com", "GET\n\n\n1325376300\n/bucket/file.ext"] - Google::Cloud.env.stub :compute_engine?, false do + Google::Cloud.env.stub :metadata?, false do Google::Cloud::Storage::IAMSigner.stub :new, iam_signer_mock do signed_url = file.signed_url @@ -178,7 +178,7 @@ end end - it "uses IAMSigner and auto-detects issuer if compute_engine? is true" do + it "uses IAMSigner and auto-detects issuer if metadata? is true" do Time.stub :now, Time.new(2012,1,1,0,0,0, "+00:00") do credentials.issuer = nil credentials.signing_key = nil @@ -186,7 +186,7 @@ iam_signer_mock = Minitest::Mock.new iam_signer_mock.expect :sign, "iam-signature", ["metadata_issuer@email.com", "GET\n\n\n1325376300\n/bucket/file.ext"] - Google::Cloud.env.stub :compute_engine?, true do + Google::Cloud.env.stub :metadata?, true do Google::Cloud.env.stub :lookup_metadata, "metadata_issuer@email.com" do Google::Cloud::Storage::IAMSigner.stub :new, iam_signer_mock do signed_url = file.signed_url diff --git a/google-cloud-storage/test/google/cloud/storage/file_signed_url_v4_test.rb b/google-cloud-storage/test/google/cloud/storage/file_signed_url_v4_test.rb index 1001e6ded350..25434db955a6 100644 --- a/google-cloud-storage/test/google/cloud/storage/file_signed_url_v4_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/file_signed_url_v4_test.rb @@ -150,7 +150,7 @@ credentials.issuer = nil credentials.signing_key = nil - Google::Cloud.env.stub :compute_engine?, false do + Google::Cloud.env.stub :metadata?, false do expect { file.signed_url version: :v4 }.must_raise Google::Cloud::Storage::SignedUrlUnavailable @@ -165,7 +165,7 @@ iam_signer_mock = Minitest::Mock.new iam_signer_mock.expect :sign, "iam-signature", ["native_issuer@email.com", String] - Google::Cloud.env.stub :compute_engine?, false do + Google::Cloud.env.stub :metadata?, false do Google::Cloud::Storage::IAMSigner.stub :new, iam_signer_mock do signed_url = file.signed_url version: :v4 @@ -179,7 +179,7 @@ end end - it "uses IAMSigner and auto-detects issuer if compute_engine? is true" do + it "uses IAMSigner and auto-detects issuer if metadata? is true" do Time.stub :now, Time.new(2012,1,1,0,0,0, "+00:00") do credentials.issuer = nil credentials.signing_key = nil @@ -187,7 +187,7 @@ iam_signer_mock = Minitest::Mock.new iam_signer_mock.expect :sign, "iam-signature", ["metadata_issuer@email.com", String] - Google::Cloud.env.stub :compute_engine?, true do + Google::Cloud.env.stub :metadata?, true do Google::Cloud.env.stub :lookup_metadata, "metadata_issuer@email.com" do Google::Cloud::Storage::IAMSigner.stub :new, iam_signer_mock do signed_url = file.signed_url version: :v4 diff --git a/google-cloud-storage/test/google/cloud/storage/iam_signer_test.rb b/google-cloud-storage/test/google/cloud/storage/iam_signer_test.rb index 0f057e225d70..23133d661968 100644 --- a/google-cloud-storage/test/google/cloud/storage/iam_signer_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/iam_signer_test.rb @@ -34,13 +34,14 @@ resource == expected_resource && request.payload == payload end - Google::Auth.stub :get_application_default, mock_auth do - Google::Apis::IamcredentialsV1::IAMCredentialsService.stub :new, mock_service do - signer = Google::Cloud::Storage::IAMSigner.new - signature = signer.sign issuer, payload + mock_credentials = Minitest::Mock.new + mock_credentials.expect :client, mock_auth - _(signature).must_equal expected_signature - end + Google::Apis::IamcredentialsV1::IAMCredentialsService.stub :new, mock_service do + signer = Google::Cloud::Storage::IAMSigner.new mock_credentials + signature = signer.sign issuer, payload + + _(signature).must_equal expected_signature end mock_service.verify diff --git a/google-cloud-storage/test/google/cloud/storage/lazy/bucket_signed_url_v2_test.rb b/google-cloud-storage/test/google/cloud/storage/lazy/bucket_signed_url_v2_test.rb index 8cc960fd5d6a..7c3efa966fdf 100644 --- a/google-cloud-storage/test/google/cloud/storage/lazy/bucket_signed_url_v2_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/lazy/bucket_signed_url_v2_test.rb @@ -113,7 +113,7 @@ - Google::Cloud.env.stub :compute_engine?, false do + Google::Cloud.env.stub :metadata?, false do expect { diff --git a/google-cloud-storage/test/google/cloud/storage/lazy/bucket_signed_url_v4_test.rb b/google-cloud-storage/test/google/cloud/storage/lazy/bucket_signed_url_v4_test.rb index cf9038823b31..de7640928387 100644 --- a/google-cloud-storage/test/google/cloud/storage/lazy/bucket_signed_url_v4_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/lazy/bucket_signed_url_v4_test.rb @@ -132,7 +132,7 @@ - Google::Cloud.env.stub :compute_engine?, false do + Google::Cloud.env.stub :metadata?, false do expect { diff --git a/google-cloud-storage/test/google/cloud/storage/lazy/file_signed_url_v2_test.rb b/google-cloud-storage/test/google/cloud/storage/lazy/file_signed_url_v2_test.rb index cc023e2d378f..ee4ef92cf6fd 100644 --- a/google-cloud-storage/test/google/cloud/storage/lazy/file_signed_url_v2_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/lazy/file_signed_url_v2_test.rb @@ -135,7 +135,7 @@ - Google::Cloud.env.stub :compute_engine?, false do + Google::Cloud.env.stub :metadata?, false do expect { diff --git a/google-cloud-storage/test/google/cloud/storage/lazy/file_signed_url_v4_test.rb b/google-cloud-storage/test/google/cloud/storage/lazy/file_signed_url_v4_test.rb index d4729d143d1e..e9483705f166 100644 --- a/google-cloud-storage/test/google/cloud/storage/lazy/file_signed_url_v4_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/lazy/file_signed_url_v4_test.rb @@ -130,7 +130,7 @@ - Google::Cloud.env.stub :compute_engine?, false do + Google::Cloud.env.stub :metadata?, false do expect { diff --git a/google-cloud-storage/test/google/cloud/storage/project_signed_url_v2_test.rb b/google-cloud-storage/test/google/cloud/storage/project_signed_url_v2_test.rb index 476b0bdb7748..a7fb33818223 100644 --- a/google-cloud-storage/test/google/cloud/storage/project_signed_url_v2_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/project_signed_url_v2_test.rb @@ -153,7 +153,7 @@ - Google::Cloud.env.stub :compute_engine?, false do + Google::Cloud.env.stub :metadata?, false do expect { diff --git a/google-cloud-storage/test/google/cloud/storage/project_signed_url_v4_test.rb b/google-cloud-storage/test/google/cloud/storage/project_signed_url_v4_test.rb index 7cc879e1ab3b..3eeae0b47052 100644 --- a/google-cloud-storage/test/google/cloud/storage/project_signed_url_v4_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/project_signed_url_v4_test.rb @@ -154,7 +154,7 @@ - Google::Cloud.env.stub :compute_engine?, false do + Google::Cloud.env.stub :metadata?, false do expect {