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.

Parameters:

  • options (Hash) (defaults to: {})

    A hash of options to configure the credentials.

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)

Returns The short-lived impersonation access token, retrieved and cached after making the impersonation request.

Returns:

  • (String, nil)

    The short-lived impersonation access token, retrieved and cached after making the impersonation request



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

def access_token
  @access_token
end

#base_credentialsObject (readonly)

Returns The original authenticated credentials used to fetch short-lived impersonation access tokens.

Returns:

  • (Object)

    The original authenticated credentials used to fetch short-lived impersonation access tokens



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

def base_credentials
  @base_credentials
end

#expires_atTime?

Returns The expiration time of the current access token, used to determine if the token is still valid.

Returns:

  • (Time, nil)

    The expiration time of the current access token, used to determine if the token is still valid



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

def expires_at
  @expires_at
end

#impersonation_urlString (readonly)

Returns The URL endpoint used to generate an impersonation token. This URL should follow a specific format to specify the impersonated service account.

Returns:

  • (String)

    The URL endpoint used to generate an impersonation token. This URL should follow a specific format to specify the impersonated service account.



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

def impersonation_url
  @impersonation_url
end

#scopeArray<String>, String (readonly)

Returns The scope(s) required for the impersonated access token, indicating the permissions needed for the short-lived token.

Returns:

  • (Array<String>, String)

    The scope(s) required for the impersonated access token, indicating the permissions needed for the short-lived token



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

def scope
  @scope
end

#source_credentialsObject (readonly)

Returns The modified version of base credentials, tailored for impersonation purposes with necessary scope adjustments.

Returns:

  • (Object)

    The modified version of base credentials, tailored for impersonation purposes with necessary scope adjustments



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.

Parameters:

  • options (Hash) (defaults to: {})

    A hash of options to configure the credentials.

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.

Returns:



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

Parameters:

  • options (Hash) (defaults to: {})

    Overrides for the credentials parameters. The following keys are recognized

    • base_credentials the base credentials used to initialize the impersonation
    • source_credentials the authenticated credentials which usually would be base credentials with scope overridden to IAM_SCOPE
    • impersonation_url the URL to use to make an impersonation token exchange
    • scope the scope(s) to access

Returns:



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.

Parameters:

  • seconds (Integer)

    The number of seconds to check against the token's expiration time.

Returns:

  • (Boolean)

    Whether the access token expires within the given time frame



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?

Returns The logger of the credentials.

Returns:

  • (Logger, nil)

    The logger of the credentials.



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.

Returns:

  • (String)

    The universe domain of the credentials.



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

def universe_domain
  @source_credentials.universe_domain
end