class Google::Auth::GCECredentials

Extends Signet::OAuth2::Client so that the auth token is obtained from the GCE metadata server.

Constants

COMPUTE_AUTH_TOKEN_URI

@private Unused and deprecated but retained to prevent breaking changes

COMPUTE_CHECK_URI

@private Unused and deprecated but retained to prevent breaking changes

COMPUTE_ID_TOKEN_URI

@private Unused and deprecated but retained to prevent breaking changes

DEFAULT_METADATA_HOST

@private Unused and deprecated but retained to prevent breaking changes

Attributes

disable_universe_domain_check[RW]

@private Temporary; remove when universe domain metadata endpoint is stable (see b/349488459).

Public Class Methods

compute_auth_token_uri() click to toggle source

@private Unused and deprecated

# File lib/googleauth/compute_engine.rb, line 60
def compute_auth_token_uri
  "#{compute_check_uri}/computeMetadata/v1/instance/service-accounts/default/token".freeze
end
compute_check_uri() click to toggle source

@private Unused and deprecated

# File lib/googleauth/compute_engine.rb, line 55
def compute_check_uri
  "http://#{metadata_host}".freeze
end
compute_id_token_uri() click to toggle source

@private Unused and deprecated

# File lib/googleauth/compute_engine.rb, line 65
def compute_id_token_uri
  "#{compute_check_uri}/computeMetadata/v1/instance/service-accounts/default/identity".freeze
end
metadata_host() click to toggle source

@private Unused and deprecated

# File lib/googleauth/compute_engine.rb, line 50
def metadata_host
  ENV.fetch "GCE_METADATA_HOST", DEFAULT_METADATA_HOST
end
new(options = {}) click to toggle source

Construct a GCECredentials

Calls superclass method
# File lib/googleauth/compute_engine.rb, line 87
def initialize options = {}
  # Override the constructor to remember whether the universe domain was
  # overridden by a constructor argument.
  @universe_domain_overridden = options["universe_domain"] || options[:universe_domain] ? true : false
  # TODO: Remove when universe domain metadata endpoint is stable (see b/349488459).
  @disable_universe_domain_check = true
  super options
end
on_gce?(_options = {}) click to toggle source

Detect if this appear to be a GCE instance, by checking if metadata is available. The parameters are deprecated and unused.

# File lib/googleauth/compute_engine.rb, line 72
def on_gce? _options = {}, _reload = false # rubocop:disable Style/OptionalBooleanParameter
  Google::Cloud.env.metadata?
end
reset_cache() click to toggle source
# File lib/googleauth/compute_engine.rb, line 76
def reset_cache
  Google::Cloud.env.compute_metadata.reset_existence!
  Google::Cloud.env.compute_metadata.cache.expire_all!
end
Also aliased as: unmemoize_all
unmemoize_all()
Alias for: reset_cache

Public Instance Methods

fetch_access_token(_options = {}) click to toggle source

Overrides the super class method to change how access tokens are fetched.

# File lib/googleauth/compute_engine.rb, line 111
def fetch_access_token _options = {}
  query, entry =
    if token_type == :id_token
      [{ "audience" => target_audience, "format" => "full" }, "service-accounts/default/identity"]
    else
      [{}, "service-accounts/default/token"]
    end
  query[:scopes] = Array(scope).join "," if scope
  begin
    log_fetch_query
    resp = Google::Cloud.env.lookup_metadata_response "instance", entry, query: query
    log_fetch_resp resp
    case resp.status
    when 200
      build_token_hash resp.body, resp.headers["content-type"], resp.retrieval_monotonic_time
    when 403, 500
      raise Signet::UnexpectedStatusError, "Unexpected error code #{resp.status} #{UNEXPECTED_ERROR_SUFFIX}"
    when 404
      raise Signet::AuthorizationError, NO_METADATA_SERVER_ERROR
    else
      raise Signet::AuthorizationError, "Unexpected error code #{resp.status} #{UNEXPECTED_ERROR_SUFFIX}"
    end
  rescue Google::Cloud::Env::MetadataServerNotResponding => e
    log_fetch_err e
    raise Signet::AuthorizationError, e.message
  end
end
universe_domain() click to toggle source

@private Overrides universe_domain getter to fetch lazily if it hasn’t been fetched yet. This is necessary specifically for Compute Engine because the universe comes from the metadata service, and isn’t known immediately on credential construction. All other credential types read the universe from their json key or other immediate input.

Calls superclass method
# File lib/googleauth/compute_engine.rb, line 102
def universe_domain
  value = super
  return value unless value.nil?
  fetch_access_token!
  super
end

Private Instance Methods

add_universe_domain_to(hash) click to toggle source
# File lib/googleauth/compute_engine.rb, line 198
def add_universe_domain_to hash
  return if @universe_domain_overridden
  universe_domain =
    if disable_universe_domain_check
      # TODO: Remove when universe domain metadata endpoint is stable (see b/349488459).
      "googleapis.com"
    else
      Google::Cloud.env.lookup_metadata "universe", "universe-domain"
    end
  universe_domain = "googleapis.com" if !universe_domain || universe_domain.empty?
  hash["universe_domain"] = universe_domain.strip
end
adjust_for_stale_expires_in(hash, retrieval_time) click to toggle source

The response might have been cached, which means expires_in might be stale. Update it based on the time since the data was retrieved. We also ensure expires_in is conservative; subtracting at least 1 second to offset any skew from metadata server latency.

# File lib/googleauth/compute_engine.rb, line 215
def adjust_for_stale_expires_in hash, retrieval_time
  return unless hash["expires_in"].is_a? Numeric
  offset = 1 + (Process.clock_gettime(Process::CLOCK_MONOTONIC) - retrieval_time).round
  hash["expires_in"] -= offset if offset.positive?
  hash["expires_in"] = 0 if hash["expires_in"].negative?
end
build_token_hash(body, content_type, retrieval_time) click to toggle source
# File lib/googleauth/compute_engine.rb, line 177
def build_token_hash body, content_type, retrieval_time
  hash =
    if ["text/html", "application/text"].include? content_type
      parse_encoded_token body
    else
      Signet::OAuth2.parse_credentials body, content_type
    end
  add_universe_domain_to hash
  adjust_for_stale_expires_in hash, retrieval_time
  hash
end
log_fetch_err(_err) click to toggle source
# File lib/googleauth/compute_engine.rb, line 168
def log_fetch_err _err
  logger&.info do
    Google::Logging::Message.from(
      message: "MDS did not respond to token request",
      "credentialsId" => object_id
    )
  end
end
log_fetch_query() click to toggle source
# File lib/googleauth/compute_engine.rb, line 141
def log_fetch_query
  if token_type == :id_token
    logger&.info do
      Google::Logging::Message.from(
        message: "Requesting id token from MDS with aud=#{target_audience}",
        "credentialsId" => object_id
      )
    end
  else
    logger&.info do
      Google::Logging::Message.from(
        message: "Requesting access token from MDS",
        "credentialsId" => object_id
      )
    end
  end
end
log_fetch_resp(resp) click to toggle source
# File lib/googleauth/compute_engine.rb, line 159
def log_fetch_resp resp
  logger&.info do
    Google::Logging::Message.from(
      message: "Received #{resp.status} from MDS",
      "credentialsId" => object_id
    )
  end
end
parse_encoded_token(body) click to toggle source
# File lib/googleauth/compute_engine.rb, line 189
def parse_encoded_token body
  hash = { token_type.to_s => body }
  if token_type == :id_token
    expires_at = expires_at_from_id_token body
    hash["expires_at"] = expires_at if expires_at
  end
  hash
end