lib/conjur/api/authn.rb
#
# Copyright 2013-2017 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
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
require 'conjur/user'
module Conjur
class API
def whoami
JSON.parse(url_for(:whoami, credentials).get)
end
class << self
#@!group Authentication
# Exchanges a username and a password for an api key. The api key
# is preferable for storage and use in code, as it can be rotated and has far greater entropy than
# a user memorizable password.
#
# * Note that this method works only for {Conjur::User}s. While
# {Conjur::Host}s are roles, they do not have passwords.
# * If you pass an api key to this method instead of a password, it will verify and return the API key.
# * This method uses HTTP Basic Authentication to send the credentials.
#
# @example
# bob_api_key = Conjur::API.login('bob', 'bob_password')
# bob_api_key == Conjur::API.login('bob', bob_api_key) # => true
#
# @param [String] username The `username` or `login` for the
# {http://developer.conjur.net/reference/services/directory/user Conjur User}.
# @param [String] password The `password` or `api key` to authenticate with.
# @param [String] account The organization account.
# @return [String] the API key.
def login username, password, account: Conjur.configuration.account
if Conjur.log
Conjur.log << "Logging in #{username} to account #{account} via Basic authentication\n"
end
url_for(:authn_login, account, username, password).get
end
# Authenticates using a third party authenticator like authn-oidc. It will return an
# access token to be used to authenticate further API calls.
#
# @param [String] authenticator
# @param [String] service_id
# @param [String] account The organization account.
# @param [Hash] params Additional params to send to authenticator
# @return [String] A JSON formatted authentication token.
def authenticator_authenticate authenticator, service_id, account: Conjur.configuration.account, options: {}
JSON.parse authenticator_authenticate_get authenticator, service_id, account: account, options: options
end
# Authenticates using a third party authenticator like authn-oidc via GET request.
# It will return an response object containing access/refresh token data.
#
# @param [String] authenticator
# @param [String] service_id
# @param [String] account The organization account.
# @param [Hash] params Additional params to send to authenticator
# @return [RestClient::Response] Response object
def authenticator_authenticate_get authenticator, service_id, account: Conjur.configuration.account, options: {}
if Conjur.log
Conjur.log << "Authenticating to account #{account} using #{authenticator}/#{service_id}\n"
end
url_for(:authenticator_authenticate, account, service_id, authenticator, options).get
end
# Exchanges Conjur the API key (refresh token) for an access token. The access token can
# then be used to authenticate further API calls.
#
# @param [String] username The username or host id for which we want a token
# @param [String] api_key The api key
# @param [String] account The organization account.
# @return [String] A JSON formatted authentication token.
def authenticate username, api_key, account: Conjur.configuration.account
account ||= Conjur.configuration.account
if Conjur.log
Conjur.log << "Authenticating #{username} to account #{account}\n"
end
JSON.parse url_for(:authn_authenticate, account, username).post(api_key, content_type: 'text/plain')
end
# Obtains an access token from the +authn_local+ service. The access token can
# then be used to authenticate further API calls.
#
# @param [String] username The username or host id for which we want a token
# @param [String] account The organization account.
# @return [String] A JSON formatted authentication token.
def authenticate_local username, account: Conjur.configuration.account, expiration: nil, cidr: nil
account ||= Conjur.configuration.account
if Conjur.log
Conjur.log << "Authenticating #{username} to account #{account} using authn_local\n"
end
require 'json'
require 'socket'
message = url_for(:authn_authenticate_local, username, account, expiration, cidr)
JSON.parse(UNIXSocket.open(Conjur.configuration.authn_local_socket) {|s| s.puts message; s.gets })
end
# Change a user's password. To do this, you must have the user's current password. This does not change or rotate
# api keys. However, you *can* use the user's api key as the *current* password, if the user was not created
# with a password.
#
# @param [String] username the name of the user whose password we want to change.
# @param [String] password the user's *current* password *or* api key.
# @param [String] new_password the new password for the user.
# @param [String] account The organization account.
# @return [void]
def update_password username, password, new_password, account: Conjur.configuration.account
if Conjur.log
Conjur.log << "Updating password for #{username} in account #{account}\n"
end
url_for(:authn_update_password, account, username, password).put new_password
end
#@!endgroup
#@!group Password and API key management
# Rotate the currently authenticated user or host API key by generating and returning a new one.
# The old API key is no longer valid after calling this method. You must have the current
# API key or password to perform this operation. This method *does not* affect a user's password.
#
# @param [String] username the name of the user or host whose API key we want to change
# @param [String] password the user's current api key
# @param [String] account The organization account.
# @return [String] the new API key
def rotate_api_key username, password, account: Conjur.configuration.account
if Conjur.log
Conjur.log << "Rotating API key for self (#{username} in account #{account})\n"
end
url_for(:authn_rotate_own_api_key, account, username, password).put('').body
end
#@!endgroup
end
end
end