Class: Google::Auth::ImpersonatedServiceAccountCredentials

Inherits:
Object
  • Object
show all
Includes:
BaseClient, Helpers::Connection
Defined in:
lib/googleauth/impersonated_service_account.rb

Overview

Authenticates requests using impersonation from base credentials. This is a two-step process: first authentication claim from the base credentials is created and then that claim is exchanged for a short-lived token at an IAMCredentials endpoint. The short-lived token and its expiration time are cached.

Constant Summary

Constants included from BaseClient

BaseClient::AUTH_METADATA_KEY

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Helpers::Connection

connection, default_connection, default_connection=

Methods included from BaseClient

#apply, #apply!, #needs_access_token?, #notify_refresh_listeners, #on_refresh, #updater_proc

Constructor Details

#initialize(options = {}) ⇒ Google::Auth::ImpersonatedServiceAccountCredentials

Initializes a new instance of ImpersonatedServiceAccountCredentials.

Options Hash (options):

  • :base_credentials (Object) — default: required

    The authenticated principal. It will be used as following:

    • will be duplicated (with IAM scope) to create the source credentials if it supports duplication
    • as source credentials otherwise.
  • :impersonation_url (String) — default: required

    The URL to impersonate the service account. This URL should follow the format: https://iamcredentials.{universe_domain}/v1/projects/-/serviceAccounts/{source_sa_email}:generateAccessToken, where:

    • {universe_domain} is the domain of the IAMCredentials API endpoint (e.g., googleapis.com).
    • {source_sa_email} is the email address of the service account to impersonate.
  • :scope (Array<String>, String) — default: required

    The scope(s) for the short-lived impersonation token, defining the permissions required for the token. It will override the scope from the json_key_io file if provided.

  • :source_credentials (Object)

    The authenticated principal that will be used to fetch the short-lived impersonation access token. It is an alternative to providing the base credentials. It is redundant to provide both source and base credentials as only source will be used, but it can be done, e.g. when duplicating existing credentials.

Raises:

  • (ArgumentError)

    If any of the required options are missing.



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/googleauth/impersonated_service_account.rb', line 168

def initialize options = {}
  @base_credentials, @impersonation_url, @scope =
    options.values_at :base_credentials,
                      :impersonation_url,
                      :scope

  # Fail-fast checks for required parameters
  if @base_credentials.nil? && !options.key?(:source_credentials)
    raise ArgumentError, "Missing required option: either :base_credentials or :source_credentials"
  end
  raise ArgumentError, "Missing required option: :impersonation_url" if @impersonation_url.nil?
  raise ArgumentError, "Missing required option: :scope" if @scope.nil?

  # Some credentials (all Signet-based ones and this one) include scope and a bunch of transient state
  # (e.g. refresh status) as part of themselves
  # so a copy needs to be created with the scope overriden and transient state dropped.
  #
  # If a credentials does not support `duplicate` we'll try to use it as is assuming it has a broad enough scope.
  # This might result in an "access denied" error downstream when the token from that credentials is being used
  # for the token exchange.
  @source_credentials = if options.key? :source_credentials
                          options[:source_credentials]
                        elsif @base_credentials.respond_to? :duplicate
                          @base_credentials.duplicate({
                                                        scope: IAM_SCOPE
                                                      })
                        else
                          @base_credentials
                        end
end

Instance Attribute Details

#access_tokenString? (readonly)



63
64
65
# File 'lib/googleauth/impersonated_service_account.rb', line 63

def access_token
  @access_token
end

#base_credentialsObject (readonly)



47
48
49
# File 'lib/googleauth/impersonated_service_account.rb', line 47

def base_credentials
  @base_credentials
end

#expires_atTime?



67
68
69
# File 'lib/googleauth/impersonated_service_account.rb', line 67

def expires_at
  @expires_at
end

#impersonation_urlString (readonly)



55
56
57
# File 'lib/googleauth/impersonated_service_account.rb', line 55

def impersonation_url
  @impersonation_url
end

#scopeArray<String>, String (readonly)



59
60
61
# File 'lib/googleauth/impersonated_service_account.rb', line 59

def scope
  @scope
end

#source_credentialsObject (readonly)



51
52
53
# File 'lib/googleauth/impersonated_service_account.rb', line 51

def source_credentials
  @source_credentials
end

Class Method Details

.make_creds(options = {}) ⇒ Google::Auth::ImpersonatedServiceAccountCredentials

Note:

Warning:

Create a ImpersonatedServiceAccountCredentials When you use service account impersonation, you start with an authenticated principal (e.g. your user account or a service account) and request short-lived credentials for a service account that has the authorization that your use case requires.

This method does not validate the credential configuration. A security risk occurs when a credential configuration configured with malicious urls is used. When the credential configuration is accepted from an untrusted source, you should validate it before using with this method. See https://cloud.google.com/docs/authentication/external/externally-sourced-credentials for more details.

Options Hash (options):

  • :base_credentials (Object) — default: required

    The authenticated principal. It will be used as following:

    • will be duplicated (with IAM scope) to create the source credentials if it supports duplication
    • as source credentials otherwise.
  • :impersonation_url (String) — default: required

    The URL to impersonate the service account. This URL should follow the format: https://iamcredentials.{universe_domain}/v1/projects/-/serviceAccounts/{source_sa_email}:generateAccessToken, where:

    • {universe_domain} is the domain of the IAMCredentials API endpoint (e.g., googleapis.com).
    • {source_sa_email} is the email address of the service account to impersonate.
  • :scope (Array<String>, String) — default: required

    The scope(s) for the short-lived impersonation token, defining the permissions required for the token.

  • :source_credentials (Object)

    The authenticated principal that will be used to fetch the short-lived impersonation access token. It is an alternative to providing the base credentials.

  • :json_key_io (IO)

    The IO object that contains the credential configuration. It is exclusive with :base_credentials and :source_credentials options.



103
104
105
106
107
108
109
# File 'lib/googleauth/impersonated_service_account.rb', line 103

def self.make_creds options = {}
  if options[:json_key_io]
    make_creds_from_json options
  else
    new options
  end
end

Instance Method Details

#duplicate(options = {}) ⇒ Google::Auth::ImpersonatedServiceAccountCredentials

Creates a duplicate of these credentials without transient token state



233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/googleauth/impersonated_service_account.rb', line 233

def duplicate options = {}
  options = deep_hash_normalize options

  options = {
    base_credentials: @base_credentials,
    source_credentials: @source_credentials,
    impersonation_url: @impersonation_url,
    scope: @scope
  }.merge(options)

  self.class.new options
end

#expires_within?(seconds) ⇒ Boolean

Determines whether the current access token expires within the specified number of seconds.



204
205
206
207
# File 'lib/googleauth/impersonated_service_account.rb', line 204

def expires_within? seconds
  # This method is needed for BaseClient
  @expires_at && @expires_at - Time.now.utc < seconds
end

#loggerLogger?



218
219
220
# File 'lib/googleauth/impersonated_service_account.rb', line 218

def logger
  @source_credentials.logger if source_credentials.respond_to? :logger
end

#universe_domainString

The universe domain of the impersonated credentials. Effectively this retrieves the universe domain of the source credentials.



213
214
215
# File 'lib/googleauth/impersonated_service_account.rb', line 213

def universe_domain
  @source_credentials.universe_domain
end