Class: Google::Auth::ServiceAccountCredentials

Inherits:
Signet::OAuth2::Client show all
Extended by:
CredentialsLoader, JsonKeyReader
Defined in:
lib/googleauth/service_account.rb

Overview

Authenticates requests using Google's Service Account credentials via an OAuth access token.

This class allows authorizing requests for service accounts directly from credentials from a json key file downloaded from the developer console (via 'Generate new Json Key').

cf Application Default Credentials

Constant Summary collapse

TOKEN_CRED_URI =
"https://www.googleapis.com/oauth2/v4/token".freeze

Constants included from CredentialsLoader

CredentialsLoader::ACCOUNT_TYPE_VAR, CredentialsLoader::AWS_ACCESS_KEY_ID_VAR, CredentialsLoader::AWS_DEFAULT_REGION_VAR, CredentialsLoader::AWS_REGION_VAR, CredentialsLoader::AWS_SECRET_ACCESS_KEY_VAR, CredentialsLoader::AWS_SESSION_TOKEN_VAR, CredentialsLoader::CLIENT_EMAIL_VAR, CredentialsLoader::CLIENT_ID_VAR, CredentialsLoader::CLIENT_SECRET_VAR, CredentialsLoader::CLOUD_SDK_CLIENT_ID, CredentialsLoader::CREDENTIALS_FILE_NAME, CredentialsLoader::ENV_VAR, CredentialsLoader::GCLOUD_CONFIG_COMMAND, CredentialsLoader::GCLOUD_POSIX_COMMAND, CredentialsLoader::GCLOUD_WINDOWS_COMMAND, CredentialsLoader::NOT_FOUND_ERROR, CredentialsLoader::PRIVATE_KEY_VAR, CredentialsLoader::PROJECT_ID_VAR, CredentialsLoader::REFRESH_TOKEN_VAR, CredentialsLoader::SYSTEM_DEFAULT_ERROR, CredentialsLoader::WELL_KNOWN_ERROR, CredentialsLoader::WELL_KNOWN_PATH

Constants included from BaseClient

BaseClient::AUTH_METADATA_KEY

Instance Attribute Summary collapse

Attributes inherited from Signet::OAuth2::Client

#universe_domain

Attributes included from BaseClient

#logger

Class Method Summary collapse

Instance Method Summary collapse

Methods included from CredentialsLoader

from_env, from_system_default_path, from_well_known_path, load_gcloud_project_id, make_creds

Methods included from JsonKeyReader

read_json_key

Methods inherited from Signet::OAuth2::Client

#build_default_connection, #configure_connection, #fetch_access_token!, #generate_access_token_request, #googleauth_orig_generate_access_token_request, #orig_fetch_access_token!, #retry_with_error, #token_type, #update_signet_base, #update_token!, #update_token_signet_base

Methods included from BaseClient

#apply, #expires_within?, #notify_refresh_listeners, #on_refresh, #updater_proc

Constructor Details

#initialize(options = {}) ⇒ ServiceAccountCredentials

Returns a new instance of ServiceAccountCredentials.



123
124
125
126
127
128
# File 'lib/googleauth/service_account.rb', line 123

def initialize options = {}
  @project_id = options[:project_id]
  @quota_project_id = options[:quota_project_id]
  @enable_self_signed_jwt = options[:enable_self_signed_jwt] ? true : false
  super options
end

Instance Attribute Details

#project_idObject (readonly)

Returns the value of attribute project_id.



41
42
43
# File 'lib/googleauth/service_account.rb', line 41

def project_id
  @project_id
end

#quota_project_idObject (readonly)

Returns the value of attribute quota_project_id.



42
43
44
# File 'lib/googleauth/service_account.rb', line 42

def quota_project_id
  @quota_project_id
end

Class Method Details

.make_creds(options = {}) ⇒ Object

Creates a ServiceAccountCredentials.

Parameters:

  • json_key_io (IO)

    An IO object containing the JSON key

  • scope (string|array|nil)

    the scope(s) to access

Raises:

  • (ArgumentError)

    If both scope and target_audience are specified



57
58
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
# File 'lib/googleauth/service_account.rb', line 57

def self.make_creds options = {}
  json_key_io, scope, enable_self_signed_jwt, target_audience, audience, token_credential_uri =
    options.values_at :json_key_io, :scope, :enable_self_signed_jwt, :target_audience,
                      :audience, :token_credential_uri
  raise ArgumentError, "Cannot specify both scope and target_audience" if scope && target_audience

  if json_key_io
    private_key, client_email, project_id, quota_project_id, universe_domain = read_json_key json_key_io
  else
    private_key = unescape ENV[CredentialsLoader::PRIVATE_KEY_VAR]
    client_email = ENV[CredentialsLoader::CLIENT_EMAIL_VAR]
    project_id = ENV[CredentialsLoader::PROJECT_ID_VAR]
    quota_project_id = nil
    universe_domain = nil
  end
  project_id ||= CredentialsLoader.load_gcloud_project_id

  new(token_credential_uri:   token_credential_uri || TOKEN_CRED_URI,
      audience:               audience || TOKEN_CRED_URI,
      scope:                  scope,
      enable_self_signed_jwt: enable_self_signed_jwt,
      target_audience:        target_audience,
      issuer:                 client_email,
      signing_key:            OpenSSL::PKey::RSA.new(private_key),
      project_id:             project_id,
      quota_project_id:       quota_project_id,
      universe_domain:        universe_domain || "googleapis.com")
    .configure_connection(options)
end

.unescape(str) ⇒ String

Handles certain escape sequences that sometimes appear in input. Specifically, interprets the "\n" sequence for newline, and removes enclosing quotes.

Parameters:

  • str (String)

    The string to unescape

Returns:

  • (String)

    The unescaped string



117
118
119
120
121
# File 'lib/googleauth/service_account.rb', line 117

def self.unescape str
  str = str.gsub '\n', "\n"
  str = str[1..-2] if str.start_with?('"') && str.end_with?('"')
  str
end

Instance Method Details

#apply!(a_hash, opts = {}) ⇒ Object

Extends the base class to use a transient ServiceAccountJwtHeaderCredentials for certain cases.



132
133
134
135
136
137
138
# File 'lib/googleauth/service_account.rb', line 132

def apply! a_hash, opts = {}
  if enable_self_signed_jwt?
    apply_self_signed_jwt! a_hash
  else
    super
  end
end

#duplicate(options = {}) ⇒ Object

Creates a duplicate of these credentials without the Signet::OAuth2::Client-specific transient state (e.g. cached tokens)

Parameters:

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

    Overrides for the credentials parameters. The following keys are recognized in addition to keys in the Signet::OAuth2::Client

    • :enable_self_signed_jwt Whether the self-signed JWT should be used for the authentication
    • project_id the project id to use during the authentication
    • quota_project_id the quota project id to use during the authentication


99
100
101
102
103
104
105
106
107
108
109
# File 'lib/googleauth/service_account.rb', line 99

def duplicate options = {}
  options = deep_hash_normalize options
  super(
    {
      enable_self_signed_jwt: @enable_self_signed_jwt,
      project_id: project_id,
      quota_project_id: quota_project_id,
      logger: logger
    }.merge(options)
  )
end

#enable_self_signed_jwt?Boolean

Returns:

  • (Boolean)


44
45
46
47
48
49
50
# File 'lib/googleauth/service_account.rb', line 44

def enable_self_signed_jwt?
  # Use a self-singed JWT if there's no information that can be used to
  # obtain an OAuth token, OR if there are scopes but also an assertion
  # that they are default scopes that shouldn't be used to fetch a token,
  # OR we are not in the default universe and thus OAuth isn't supported.
  target_audience.nil? && (scope.nil? || @enable_self_signed_jwt || universe_domain != "googleapis.com")
end

#needs_access_token?Boolean

Modifies this logic so it also requires self-signed-jwt to be disabled

Returns:

  • (Boolean)


141
142
143
# File 'lib/googleauth/service_account.rb', line 141

def needs_access_token?
  super && !enable_self_signed_jwt?
end

#update!(options = {}) ⇒ Google::Auth::ServiceAccountCredentials

Destructively updates these credentials

This method is called by Signet::OAuth2::Client's constructor

Parameters:

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

    Overrides for the credentials parameters. The following keys are recognized in addition to keys in the Signet::OAuth2::Client

    • :enable_self_signed_jwt Whether the self-signed JWT should be used for the authentication
    • project_id the project id to use during the authentication
    • quota_project_id the quota project id to use during the authentication

Returns:



158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/googleauth/service_account.rb', line 158

def update! options = {}
  # Normalize all keys to symbols to allow indifferent access.
  options = deep_hash_normalize options

  @enable_self_signed_jwt = options[:enable_self_signed_jwt] ? true : false
  @project_id = options[:project_id] if options.key? :project_id
  @quota_project_id = options[:quota_project_id] if options.key? :quota_project_id

  super(options)

  self
end