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

authorized_user_env_vars?, from_env, from_system_default_path, from_well_known_path, interpret_options, load_gcloud_project_id, make_creds, service_account_env_vars?

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.



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

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



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

def self.make_creds options = {} # rubocop:disable Metrics/MethodLength
  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

  private_key, client_email, project_id, quota_project_id, universe_domain =
    if json_key_io
      json_key = MultiJson.load json_key_io.read
      if json_key.key? "type"
        json_key_io.rewind
      else # Defaults to class credential 'type' if missing.
        json_key["type"] = CREDENTIAL_TYPE_NAME
        json_key_io = StringIO.new MultiJson.dump(json_key)
      end
      CredentialsLoader.load_and_verify_json_key_type json_key_io, CREDENTIAL_TYPE_NAME
      read_json_key json_key_io
    else
      creds_from_env
    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



126
127
128
129
130
# File 'lib/googleauth/service_account.rb', line 126

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.



141
142
143
144
145
146
147
# File 'lib/googleauth/service_account.rb', line 141

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


108
109
110
111
112
113
114
115
116
117
118
# File 'lib/googleauth/service_account.rb', line 108

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)


48
49
50
51
52
53
54
# File 'lib/googleauth/service_account.rb', line 48

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)


150
151
152
# File 'lib/googleauth/service_account.rb', line 150

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:



167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/googleauth/service_account.rb', line 167

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