lib/conjur/base.rb in conjur-api-4.23.0 vs lib/conjur/base.rb in conjur-api-4.24.0

- old
+ new

@@ -1,7 +1,7 @@ # -# Copyright (C) 2013-2014 Conjur Inc +# Copyright (C) 2013-2016 Conjur Inc # # Permission is hereby granted, free of charge, to any person obtaining a copy of # this software and associated documentation files (the "Software"), to deal in # the Software without restriction, including without limitation the rights to # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of @@ -220,26 +220,18 @@ # @return [String] the host def host self.class.host end - # The token used to authenticate requests made with the api. The token will be fetched - # if it hasn't already, or if it has expired. Accordingly, this method may raise a RestClient::Unauthorized - # exception if the credentials are invalid. + # The token used to authenticate requests made with the api. The token will be fetched, + # if possible, when not present or about to expire. Accordingly, this + # method may raise a RestClient::Unauthorized exception if the credentials are invalid. # - # @note calling this method on an {Conjur::API} instance created with {Conjur::API.new_from_token} will have - # undefined behavior if the token is expired. - # # @return [Hash] the authentication token as a Hash # @raise [RestClient::Unauthorized] if the username and api key are invalid. def token - @token = nil unless token_valid? - - @token ||= Conjur::API.authenticate(@username, @api_key) - - validate_token - + refresh_token if needs_token_refresh? return @token end # Credentials that can be merged with options to be passed to `RestClient::Resource` HTTP request methods. # These include a username and an Authorization header containing the authentication token. @@ -283,30 +275,37 @@ end end private - def token_valid? - begin - validate_token - return true - rescue Exception - return false - end + + # Tries to refresh the token if possible. + # + # @return [Hash, false] false if the token couldn't be refreshed due to + # unavailable API key; otherwise, the new token. + def refresh_token + return false unless @api_key + @token_born = gettime + @token = Conjur::API.authenticate(@username, @api_key) end - # Check to see if @token is defined, and whether it's expired + TOKEN_STALE = 5.minutes + + # Checks if the token is old (or not present). # - # @raise [Exception] if the token is invalid - def validate_token - fail "token not present" unless @token - - # Actual token expiration is 8 minutes, but why cut it so close - expiration = 5.minutes - lag = Time.now - Time.parse(@token['timestamp']) - unless lag < expiration - fail "obtained token is invalid: "\ - "token timestamp is #{@token['timestamp']}, #{lag} seconds ago" - end + # @return [Boolean] + def needs_token_refresh? + !@token || ((token_age || 0) > TOKEN_STALE) + end + + def gettime + Process.clock_gettime Process::CLOCK_MONOTONIC + rescue + # fall back to normal clock if there's no CLOCK_MONOTONIC + Time.now.to_f + end + + def token_age + @token_born && (gettime - @token_born) end end end