Class: Google::Auth::Extras::ImpersonatedCredential

Inherits:
Signet::OAuth2::Client
  • Object
show all
Defined in:
lib/google/auth/extras/impersonated_credential.rb

Overview

This credential impersonates a service account.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(email_address:, base_credentials: nil, delegate_email_addresses: nil, include_email: nil, lifetime: nil, quota_project_id: nil, scope: nil, target_audience: nil, universe_domain: 'googleapis.com') ⇒ ImpersonatedCredential

A credential that impersonates a service account.

The email_address of the service account to impersonate may be the exact same as the one represented in base_credentials for any desired situation but a handy usage is for going from and access token to an ID token (aka using target_audience).

Parameters:

  • base_credentials (Hash, String, Signet::OAuth2::Client) (defaults to: nil) —

    Credentials to use to impersonate the provided email address.

  • delegate_email_addresses (String, Array<String>) (defaults to: nil) —

    The list of email address if there are intermediate service accounts that need to be impersonated using delegation.

  • email_address (String) —

    Email of the service account to impersonate.

  • include_email (Boolean) (defaults to: nil) —

    Include the service account email in the token. If set to true, the token will contain email and email_verified claims. Only supported when using a target_audience.

  • lifetime (String) (defaults to: nil) —

    The desired lifetime (in seconds) of the token before needing to be refreshed. Defaults to 1h, adjust as needed given a refresh is automatically performed when the token less than 60s of remaining life and refresh requires an additional API call. Only supported when not using a target_audience.

  • quota_project_id (String) (defaults to: nil) —

    The project ID used for quota and billing. This project may be different from the project used to create the credentials.

  • scope (String, Array<String>) (defaults to: nil) —

    The OAuth 2 scopes to request. Can either be formatted as a comma seperated string or array. Only supported when not using a target_audience.

  • target_audience (String) (defaults to: nil) —

    The audience for the token, such as the API or account that this token grants access to.

  • universe_domain (String) (defaults to: 'googleapis.com') —

    The universe domain of the credential, reported to gRPC google-cloud clients so they don't raise Gapic::UniverseDomainMismatch. Defaults to googleapis.com.

See Also:



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/google/auth/extras/impersonated_credential.rb', line 59

def initialize(
  email_address:,
  base_credentials: nil,
  delegate_email_addresses: nil,
  include_email: nil,
  lifetime: nil,
  quota_project_id: nil,
  scope: nil,
  target_audience: nil,
  universe_domain: 'googleapis.com'
)
  super(
    client_id: target_audience,
    scope: scope,
    target_audience: target_audience,
    universe_domain: base_credentials&.universe_domain || universe_domain,
  )

  if self.target_audience.nil? || self.target_audience.empty?
    raise(ArgumentError, 'Must provide scope or target_audience') if self.scope.nil? || self.scope.empty?
  elsif self.scope.nil? || self.scope.empty?
    # no-op
  else
    raise ArgumentError, 'Must provide scope or target_audience, not both'
  end

  @iam_credentials_service = Google::Apis::IamcredentialsV1::IAMCredentialsService.new.tap do |ics|
    ics.authorization = base_credentials if base_credentials
  end

  @impersonate_delegates = Array(delegate_email_addresses).map do |email|
    transform_email_to_name(email)
  end

  # This is true when target_audience is passed
  if token_type == :id_token
    @impersonate_include_email = include_email
  elsif !include_email.nil?
    raise ArgumentError, 'Can only provide include_email when using target_audience'
  end

  # This is true when scope is passed
  if token_type == :access_token
    @impersonate_lifetime = lifetime
  elsif !lifetime.nil?
    raise ArgumentError, 'Cannot provide lifetime when using target_audience'
  end

  @impersonate_name = transform_email_to_name(email_address)

  @quota_project_id = quota_project_id
end

Instance Attribute Details

#quota_project_id ⇒ Object (readonly)

Returns the value of attribute quota_project_id.



8
9
10
# File 'lib/google/auth/extras/impersonated_credential.rb', line 8

def quota_project_id
  @quota_project_id
end

Instance Method Details

#fetch_access_token ⇒ Object



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/google/auth/extras/impersonated_credential.rb', line 112

def fetch_access_token(*)
  token_request = if token_type == :id_token
                    Google::Apis::IamcredentialsV1::GenerateIdTokenRequest.new(
                      audience: target_audience,
                    )
                  else
                    Google::Apis::IamcredentialsV1::GenerateAccessTokenRequest.new(
                      scope: scope,
                    )
                  end

  # The Google SDK doesn't like nil repeated values, but be careful with others as well.
  token_request.delegates = @impersonate_delegates unless @impersonate_delegates.empty?
  if token_type == :id_token
    token_request.include_email = @impersonate_include_email unless @impersonate_include_email.nil?
  else
    token_request.lifetime = @impersonate_lifetime unless @impersonate_lifetime.nil?
  end

  if token_type == :id_token
    id_token_response = @iam_credentials_service.(@impersonate_name, token_request)

    {
      id_token: id_token_response.token,
    }
  else
    access_token_response = @iam_credentials_service.(@impersonate_name, token_request)

    {
      access_token: access_token_response.access_token,
      expires_at: DateTime.rfc3339(access_token_response.expire_time).to_time,
    }
  end
end

#inspect ⇒ Object



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/google/auth/extras/impersonated_credential.rb', line 147

def inspect
  if token_type == :id_token
    "#<#{self.class.name}" \
      " @expires_at=#{expires_at.inspect}" \
      " @id_token=#{@id_token ? '[REDACTED]' : 'nil'}" \
      " @impersonate_delegates=#{@impersonate_delegates.inspect}" \
      " @impersonate_include_email=#{@impersonate_include_email.inspect}" \
      " @impersonate_name=#{@impersonate_name.inspect}" \
      " @quota_project_id=#{@quota_project_id.inspect}" \
      " @target_audience=#{@target_audience.inspect}" \
      '>'
  else
    "#<#{self.class.name}" \
      " @access_token=#{@access_token ? '[REDACTED]' : 'nil'}" \
      " @expires_at=#{expires_at.inspect}" \
      " @impersonate_delegates=#{@impersonate_delegates.inspect}" \
      " @impersonate_lifetime=#{@impersonate_lifetime.inspect}" \
      " @impersonate_name=#{@impersonate_name.inspect}" \
      " @quota_project_id=#{@quota_project_id.inspect}" \
      '>'
  end
end