lib/conjur/base.rb in conjur-api-4.16.0 vs lib/conjur/base.rb in conjur-api-4.19.0
- old
+ new
@@ -98,14 +98,15 @@
# @example Authentication is lazy
# api = Conjur::API.new_from_key 'admin', 'wrongpassword' # succeeds
# api.user 'foo' # raises a 401 error
#
# @param [String] username the username to use when making authenticated requests.
- # @param [Sring] api_key the api key or password for `username`
+ # @param [String] api_key the api key or password for `username`
+ # @param [String] remote_ip the optional IP address to be recorded in the audit record.
# @return [Conjur::API] an api that will authenticate with the given username and api key.
- def new_from_key(username, api_key)
- self.new username, api_key, nil
+ def new_from_key(username, api_key, remote_ip = nil)
+ self.new username, api_key, nil, remote_ip
end
# Create a new {Conjur::API} instance from a token issued by the
# {http://developer.conjur.net/reference/services/authentication Conjur authentication service}
@@ -133,13 +134,14 @@
#
# proxy_to_service request
# end
#
# @param [Hash] token the authentication token as parsed JSON to use when making authenticated requests
+ # @param [String] remote_ip the optional IP address to be recorded in the audit record.
# @return [Conjur::API] an api that will authenticate with the token
- def new_from_token(token)
- self.new nil, nil, token
+ def new_from_token(token, remote_ip = nil)
+ self.new nil, nil, token, remote_ip
end
end
# Create a new instance from a username and api key or a token.
#
@@ -149,26 +151,36 @@
# This method requires that you pass **either** a username and api_key **or** a token Hash.
#
# @param [String] username the username to authenticate as
# @param [String] api_key the api key or password to use when authenticating
# @param [Hash] token the token to use when making authenticated requuests.
+ # @param [String] remote_ip the optional IP address to be recorded in the audit record.
#
# @api internal
- def initialize username, api_key, token
+ def initialize username, api_key, token, remote_ip = nil
@username = username
@api_key = api_key
@token = token
+ @remote_ip = remote_ip
raise "Expecting ( username and api_key ) or token" unless ( username && api_key ) || token
end
#@!attribute [r] api_key
# The api key used to create this instance. This is only present when you created the api with {Conjur::API.new_from_key}.#
#
# @return [String] the api key, or nil if this instance was created from a token.
attr_reader :api_key
+
+ #@!attribute [r] remote_ip
+ # An optional IP address to be recorded in the audit record for any actions performed by this API instance.
+ attr_reader :remote_ip
+ #@!attribute [r] privilege
+ # The optional global privilege (e.g. 'elevate' or 'reveal') which should be attempted on the request.
+ attr_accessor :privilege
+
# The name of the user as which this api instance is authenticated. This is available whether the api
# instance was created from credentials or an authentication token.
#
# @return [String] the login of the current user.
def username
@@ -194,11 +206,11 @@
def token
@token = nil unless token_valid?
@token ||= Conjur::API.authenticate(@username, @api_key)
- fail "obtained token is invalid" unless token_valid? # sanity check
+ validate_token
return @token
end
# Credentials that can be merged with options to be passed to `RestClient::Resource` HTTP request methods.
@@ -206,22 +218,49 @@
#
# @return [Hash] the options.
# @raise [RestClient::Unauthorized] if fetching the token fails.
# @see {#token}
def credentials
- { headers: { authorization: "Token token=\"#{Base64.strict_encode64 token.to_json}\"" }, username: username }
+ headers = {}.tap do |h|
+ h[:authorization] = "Token token=\"#{Base64.strict_encode64 token.to_json}\""
+ h[:x_conjur_privilege] = @privilege if @privilege
+ h[:x_forwarded_for] = @remote_ip if @remote_ip
+ end
+ { headers: headers, username: username }
end
+ # Return a new API object with the specified X-Conjur-Privilege.
+ #
+ # @return The API instance.
+ def with_privilege privilege
+ self.class.new(username, api_key, token, remote_ip).tap do |api|
+ api.privilege = privilege
+ end
+ end
+
private
+ def token_valid?
+ begin
+ validate_token
+ return true
+ rescue Exception
+ return false
+ end
+ end
+
# Check to see if @token is defined, and whether it's expired
#
- # @return [Boolean] whether or not the token is valid.
- def token_valid?
- return false unless @token
+ # @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
- Time.now - Time.parse(@token['timestamp']) < expiration
+ lag = Time.now - Time.parse(@token['timestamp'])
+ unless lag < expiration
+ fail "obtained token is invalid: "\
+ "token timestamp is #{@token['timestamp']}, #{lag} seconds ago"
+ end
end
end
end