Class: Conjur::API

Inherits:
Object
  • Object
show all
Includes:
Cast, Escape, LogSource
Defined in:
lib/conjur/base.rb,
lib/conjur/api/info.rb,
lib/conjur/core-api.rb,
lib/conjur/api/audit.rb,
lib/conjur/api/authn.rb,
lib/conjur/api/hosts.rb,
lib/conjur/api/roles.rb,
lib/conjur/api/users.rb,
lib/conjur/layer-api.rb,
lib/conjur/api/groups.rb,
lib/conjur/api/layers.rb,
lib/conjur-api/version.rb,
lib/conjur/api/pubkeys.rb,
lib/conjur/api/secrets.rb,
lib/conjur/pubkeys-api.rb,
lib/conjur/api/deputies.rb,
lib/conjur/api/ldapsync.rb,
lib/conjur/api/resources.rb,
lib/conjur/api/variables.rb,
lib/conjur/host-factory-api.rb,
lib/conjur/api/host_factories.rb

Overview

This class provides access to the Conjur services.

Defined Under Namespace

Modules: MonotonicTime, TokenExpiration Classes: APIKeyAuthenticator, TokenFileAuthenticator, UnableAuthenticator

Authorization: Resources collapse

GLOBAL_PRIVILEGE_RESOURCE =

The resource which grants global privileges to Conjur. Privileges given on this resource apply to any record in the system. There are two defined global privileges:

  • elevate permission is granted for any action.
  • reveal methods which list records will always return every matching record, regardless of whether the user has any privileges on these records or not. Services can also choose to attach additional semantics to reveal, such as allowing the user to show non-sensitive attributes of any record.

Global privileges are available in Conjur 4.5 and later.

"!:!:conjur"

Constant Summary collapse

VERSION =
"4.30.0"

Instance Attribute Summary collapse

Audit Service collapse

Authentication Methods collapse

Password and API key management collapse

Directory: Hosts collapse

Authorization: Roles collapse

Directory: Users collapse

Directory: Groups collapse

Directory: Layers collapse

Public Keys Service collapse

Directory: Deputies collapse

LDAP Sync Service collapse

Authorization: Resources collapse

Directory: Variables collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from LogSource

#log

Methods included from Escape

#fully_escape, #path_escape, #query_escape

Instance Attribute Details

#api_keyString (readonly)

The api key used to create this instance. This is only present when you created the api with new_from_key.#

Returns:

  • (String)

    the api key, or nil if this instance was created from a token.



170
171
172
# File 'lib/conjur/base.rb', line 170

def api_key
  @api_key
end

#audit_resourcesObject

An array of resource ids that should be included in any audit records generated by requsts made by this instance of the api.



188
189
190
# File 'lib/conjur/base.rb', line 188

def audit_resources
  @audit_resources
end

#audit_rolesObject

An array of role ids that should be included in any audit records generated by requsts made by this instance of the api.



183
184
185
# File 'lib/conjur/base.rb', line 183

def audit_roles
  @audit_roles
end

#authenticatorObject (readonly)

Returns the value of attribute authenticator.



390
391
392
# File 'lib/conjur/base.rb', line 390

def authenticator
  @authenticator
end

#privilegeObject

The optional global privilege (e.g. 'elevate' or 'reveal') which should be attempted on the request.



178
179
180
# File 'lib/conjur/base.rb', line 178

def privilege
  @privilege
end

#remote_ipObject (readonly)

An optional IP address to be recorded in the audit record for any actions performed by this API instance.



174
175
176
# File 'lib/conjur/base.rb', line 174

def remote_ip
  @remote_ip
end

Class Method Details

.appliance_health(remote_host = nil) ⇒ Hash

Note:

When called without an argument, this method requires a Conjur server running version 4.5 or later. When called with an argument, it requires 4.6 or later.

Return a Hash containing health information for this appliance, or for another host.

If the remote_host argument is provided, the health of that appliance is reported from the perspective of the appliance being queried (as specified by the appliance_url configuration variable).

Parameters:

  • remote_host (String, NilClass) (defaults to: nil)

    a hostname for a remote host

Returns:

  • (Hash)

    the appliance health information.



83
84
85
# File 'lib/conjur/api/info.rb', line 83

def appliance_health remote_host=nil
  remote_host.nil? ? own_health : remote_health(remote_host)
end

.appliance_infoHash

Note:

This feature requires Conjur appliance version 4.6 or above.

Return a Hash containing various information about the Conjur appliance.

If the appliance does not support this feature, raise Conjur::FeatureNotAvailable.

Returns:

  • (Hash)

    various information about the Conjur appliance.



66
67
68
69
70
# File 'lib/conjur/api/info.rb', line 66

def appliance_info
  JSON.parse(RestClient::Resource.new(appliance_info_url).get.body)
rescue RestClient::ResourceNotFound
  raise Conjur::FeatureNotAvailable.new('Your appliance does not support the /info URL needed by Conjur::API.appliance_info (you need 4.6 or later)')
end

.authenticate(username, password) ⇒ String

The Conjur authenticate operation exchanges Conjur credentials for a token. The token can then be used to authenticate further API calls.

You will generally not need to use this method, as the API manages tokens automatically for you.

Parameters:

  • username (String)

    The username or host id for which we want a token

  • password (String)

    The password or api key

Returns:

  • (String)

    A JSON formatted authentication token.



82
83
84
85
86
87
# File 'lib/conjur/api/authn.rb', line 82

def authenticate username, password
  if Conjur.log
    Conjur.log << "Authenticating #{username}\n"
  end
  JSON::parse(RestClient::Resource.new(Conjur::Authn::API.host)["users/#{fully_escape username}/authenticate"].post password, content_type: 'text/plain')
end

.decode_audit_ids(ids) ⇒ Object



160
161
162
# File 'lib/conjur/base.rb', line 160

def decode_audit_ids(ids)
  ids.split('&').collect{|id| CGI::unescape(id)}
end

.encode_audit_ids(ids) ⇒ Object



156
157
158
# File 'lib/conjur/base.rb', line 156

def encode_audit_ids(ids)
  ids.collect{|id| CGI::escape(id)}.join('&')
end

.host_factory_asset_hostObject



32
33
34
# File 'lib/conjur/host-factory-api.rb', line 32

def host_factory_asset_host
  Conjur.configuration.host_factory_url
end

.host_factory_create_host(token, id, options = {}) ⇒ Object

Creates a host and returns the response Hash.



27
28
29
30
31
32
33
34
# File 'lib/conjur/api/host_factories.rb', line 27

def host_factory_create_host token, id, options = {}
  token = token.token if token.is_a?(HostFactoryToken)
  http_options = {
    headers: { authorization: %Q(Token token="#{token}") }
  }
  response = RestClient::Resource.new(Conjur::API.host_factory_asset_host, http_options)["hosts"].post(options.merge(id: id)).body
  JSON.parse(response)
end

.login(username, password) ⇒ String

The Conjur login operation 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 Users. While Hosts possess Conjur identities, they do not have passwords.
  • If you pass an api key to this method instead of a password, it will simply return the API key.
  • This method uses Basic Auth to send the credentials.

Examples:

bob_api_key = Conjur::API.('bob', 'bob_password')
bob_api_key == Conjur::API.('bob', bob_api_key)  # => true

Parameters:

  • username (String)

    The username or login for the Conjur User.

  • password (String)

    The password or api key to authenticate with.

Returns:

  • (String)

    the API key.

Raises:

  • (RestClient::Exception)

    when the request fails or the identity provided is invalid.



48
49
50
51
52
53
# File 'lib/conjur/api/authn.rb', line 48

def  username, password
  if Conjur.log
    Conjur.log << "Logging in #{username} via Basic authentication\n"
  end
  RestClient::Resource.new(Conjur::Authn::API.host, user: username, password: password)['users/login'].get
end

.login_cas(username, password, cas_api_url) ⇒ String

This method logs in via CAS. It is similar to the login method, the only difference being that you need a cas_api_url, provided by the administrator of your CAS service.

Parameters:

  • username (String)

    the Conjur username

  • password (String)

    the Conjur password

  • cas_api_url (String)

    the url of the CAS service

Returns:

  • (String)

    a CAS ticket

See Also:



65
66
67
68
69
70
71
72
# File 'lib/conjur/api/authn.rb', line 65

def  username, password, cas_api_url
  if Conjur.log
    Conjur.log << "Logging in #{username} via CAS authentication\n"
  end
  require 'cas_rest_client'
  client = CasRestClient.new(:username => username, :password => password, :uri => [ cas_api_url, 'v1', 'tickets' ].join('/'), :use_cookies => false)
  client.get("#{Conjur::Authn::API.host}/users/login").body
end

.new_from_key(username, api_key, remote_ip = nil) ⇒ Conjur::API

Create a new Conjur::API instance from a username and a password or api key.

Examples:

Create an API with valid credentials

api = Conjur::API.new_from_key 'admin', '<admin password>'
api.current_role # => 'conjur:user:admin'
api.token['data'] # => 'admin'

Authentication is lazy

api = Conjur::API.new_from_key 'admin', 'wrongpassword'   # succeeds
api.user 'foo' # raises a 401 error

Parameters:

  • username (String)

    the username to use when making authenticated requests.

  • api_key (String)

    the api key or password for username

  • remote_ip (String) (defaults to: nil)

    the optional IP address to be recorded in the audit record.

Returns:

  • (Conjur::API)

    an api that will authenticate with the given username and api key.



107
108
109
# File 'lib/conjur/base.rb', line 107

def new_from_key(username, api_key, remote_ip = nil)
  self.new.init_from_key username, api_key, remote_ip
end

.new_from_token(token, remote_ip = nil) ⇒ Conjur::API

Create a new Conjur::API instance from a token issued by the Conjur authentication service

Generally, you will have a Conjur identitiy (username and api key), and create an Conjur::API instance for the identity using new_from_key. This method is useful when you are performing authorization checks given a token. For example, a Conjur gateway that requires you to prove that you can 'read' a resource named 'super-secret' might get the token from a request header, create an Conjur::API instance with this method, and use Resource#permitted? to decide whether to accept and forward the request.

Examples:

A simple gatekeeper

RESOURCE_NAME = 'protected-service'

def handle_request request
  token_header = request.header 'X-Conjur-Token'
  token = JSON.parse Base64.b64decode(token_header)

  api = Conjur::API.new_from_token token
  raise Forbidden unless api.resource(RESOURCE_NAME).permitted? 'read'

  proxy_to_service request
end

Parameters:

  • token (Hash)

    the authentication token as parsed JSON to use when making authenticated requests

  • remote_ip (String) (defaults to: nil)

    the optional IP address to be recorded in the audit record.

Returns:

  • (Conjur::API)

    an api that will authenticate with the token



137
138
139
# File 'lib/conjur/base.rb', line 137

def new_from_token(token, remote_ip = nil)
  self.new.init_from_token token, remote_ip
end

.new_from_token_file(token_file, remote_ip = nil) ⇒ Conjur::API

Create a new Conjur::API instance from a file containing a token issued by the Conjur authentication service. The file is read the first time that a token is required. It is also re-read whenever the API decides that the token it already has is getting close to expiration.

This method is useful when an external process, such as a sidecar container, is continuously obtaining fresh tokens and writing them to a known file.

Parameters:

  • token_file (String)

    the file path containing an authentication token as parsed JSON.

  • remote_ip (String) (defaults to: nil)

    the optional IP address to be recorded in the audit record.

Returns:

  • (Conjur::API)

    an api that will authenticate with the tokens provided in the file.



152
153
154
# File 'lib/conjur/base.rb', line 152

def new_from_token_file(token_file, remote_ip = nil)
  self.new.init_from_token_file token_file, remote_ip
end

.rotate_api_key(username, password) ⇒ String

Note:

If the user does not have a password, the returned API key will be the only way to authenticate as the user. Therefore, you'd best save it.

Note:

This feature requires version 4.6 of the Conjur appliance.

Rotate the currently authenticated user's 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 user's current API key or password to perform this operation. This method does not affect the user's password.

Parameters:

  • username (String)

    the name of the user whose password we want to change

  • password (String)

    the user's current password or api key

Returns:

  • (String)

    the new API key for the user



121
122
123
124
125
126
127
128
129
130
131
# File 'lib/conjur/api/authn.rb', line 121

def rotate_api_key username, password
  if Conjur.log
    Conjur.log << "Rotating API key for self (#{username})\n"
  end

  RestClient::Resource.new(
        Conjur::Authn::API.host,
        user: username,
        password: password
  )['users/api_key'].put('').body
end

.service_namesArray<String>

Return an Array of valid service names for your appliance.

Returns:

  • (Array<String>)

    the names of services on the appliance.



55
56
57
# File 'lib/conjur/api/info.rb', line 55

def service_names
  appliance_info['services'].keys
end

.service_version(service) ⇒ Semantic::Version

Return the version of the given service presently running on the Conjur appliance.

This feature is useful for determining whether the Conjur appliance has a particular feature.

If the given service does not exist, this method will raise an exception. To retrieve a list of valid service names, you can use Conjur::API.service_names

Examples:

Check that the authn service is at least version 4.6

if api.service_version('authn') >= '4.6.0'.to_version
  puts "Authn version is at least 4.6.0"
end

Parameters:

  • service (String)

    the name of the service.

Returns:

  • (Semantic::Version)

    the version of the service.



40
41
42
43
44
45
46
47
48
49
50
# File 'lib/conjur/api/info.rb', line 40

def service_version service
  if (service_info = appliance_info['services'][service]).nil?
    raise "Unknown service #{service} (services are #{service_names.join(', ')}."
  else
    # Pre-release versions are discarded, because they make testing harder:
    # 2.0.0-p598 :004 > Semantic::Version.new("4.5.0") <= Semantic::Version.new("4.5.0-1")
    # => false
    major, minor, patch, pre = service_info['version'].split(/[.-]/)[0..3]
    Semantic::Version.new "#{major}.#{minor}.#{patch}"
  end
end

.update_password(username, password, new_password)

This method returns an undefined value.

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.

Parameters:

  • username (String)

    the name of the user whose password we want to change

  • password (String)

    the user's current password or api key

  • new_password (String)

    the new password for the user.



98
99
100
101
102
103
# File 'lib/conjur/api/authn.rb', line 98

def update_password username, password, new_password
  if Conjur.log
    Conjur.log << "Updating password for #{username}\n"
  end
  RestClient::Resource.new(Conjur::Authn::API.host, user: username, password: password)['users/password'].put new_password
end

Instance Method Details

#add_public_key(username, key) ⇒ Object

Add an SSH public key for username.

Key Format

This method will raise an exception if key is not of the format "<algorithm> <data> <name>" (that is, key.split(\s+)).length must be 3). The <name> field is used by the service to identify individual keys for a user.

Permissions

You must have permission to 'update' the pubkeys service resource. When the Conjur appliance is configured, it creates the pubkeys service resource with this identifier '<organizational account>:service:pubkeys-1.0/public-keys'.

Rather than granting permissions to this resource directly to user roles, we recommend that you add them to the 'key-managers' group, whose unqualified identifier is 'pubkeys-1.0/key-managers', which has permission to add public keys.

Hiding Existence

Because attackers could use this method to determine the existence of Conjur users, it will not raise an error if the user does not exist.

Examples:

add a user's public key

# Check that the user exists so that we can fail when he doesn't.  Otherwise, this method
# will silently fail.
raise "No such user!" unless api.user('bob').exists?

# Add a key from a file
key = File.read('/path/to/public/key.pub')
api.add_public_key('bob', key)

Parameters:

  • username (String)

    the name of the Conjur

  • key (String)

    an SSH formated public key

Returns:

  • void

Raises:

  • RestClient::BadRequest when the key is not in the correct format.



134
135
136
# File 'lib/conjur/api/pubkeys.rb', line 134

def add_public_key username, key
  public_keys_resource(username).post key
end

#audit(options = {}, &block) ⇒ Array<Hash>

Return up to 100 audit events visible to the current authorized role.

An audit event is visible to a role if that role or one of it's ancestors is in the event's :roles field, or the role has a privilege any of the event's :resources field.

Parameters:

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :till (Time, nil)

    only show events before this time

  • :since (Time, nil)

    only show events after this time

  • :has_annotation (String, nil)

    only show events for resources with an annotation with this name

  • :follow (Boolean)

    block the current thread and call block with Array of audit events as the occur.

Returns:

  • (Array<Hash>)

    the audit events

See Also:



43
44
45
# File 'lib/conjur/api/audit.rb', line 43

def audit options={}, &block
  audit_event_feed "", options, &block
end

#audit_resource(resource, options = {}, &block) ⇒ Array<Hash>

Return up to 100 audit events visible to the current role and related to the given resource.

See #audit for the conditions under which an event is visible to a role.

An event is said to be "related to" a role iff the role is a member of the event's :roles field.

Parameters:

  • resource (Conjur::Resource, String, #resourceid)

    the resource to audit (when a string is given, it must be of the form 'account:kind:id').

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :till (Time, nil)

    only show events before this time

  • :since (Time, nil)

    only show events after this time

  • :has_annotation (String, nil)

    only show events for resources with an annotation with this name

  • :follow (Boolean)

    block the current thread and call block with Array of audit events as the occur.

Returns:

  • (Array<Hash>)

    the audit events



83
84
85
# File 'lib/conjur/api/audit.rb', line 83

def audit_resource resource, options={}, &block
  audit_event_feed "resources/#{CGI.escape cast(resource, :resourceid)}", options, &block
end

#audit_role(role, options = {}, &block) ⇒ Array<Hash>

Return up to 100 audit events visible to the current role and related to the given role.

See #audit for the conditions under which an event is visible to a role.

An event is said to be "related to" a role iff the role is a member of the event's :roles field.

Parameters:

  • role (Conjur::Role, String, #roleid)

    the role to audit (if a string is given, it must be of the form 'account:kind:id').

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :till (Time, nil)

    only show events before this time

  • :since (Time, nil)

    only show events after this time

  • :follow (Boolean)

    block the current thread and call block with Array of audit events as the occur.

Returns:

  • (Array<Hash>)

    the audit events



63
64
65
# File 'lib/conjur/api/audit.rb', line 63

def audit_role role, options={}, &block
  audit_event_feed "roles/#{CGI.escape cast(role, :roleid)}", options, &block
end

#audit_send(input) ⇒ Object

Send custom audit event

Parameters:

  • input (String|Hash|Array)

    event or array of events (optionally serialized to JSON)



89
90
91
92
93
94
95
96
97
98
99
# File 'lib/conjur/api/audit.rb', line 89

def audit_send input 
  json = if input.kind_of? String
            input
         elsif input.kind_of? Array or input.kind_of? Hash
            input.to_json
         else
            raise ArgumentError, "Parameter should be either String, Hash or Array"
         end
  rest_api = RestClient::Resource.new(Conjur::Authz::API.host, credentials)["audit"]
  rest_api.post json, content_type: "text/plain"
end

#bootstrap(listener) ⇒ Object

Perform all commands in Conjur::Bootstrap::Command.



199
200
201
202
203
204
205
# File 'lib/conjur/base.rb', line 199

def bootstrap listener
    Conjur::Bootstrap::Command.constants.map{|c| Conjur::Bootstrap::Command.const_get(c)}.each do |cls|
    next unless cls.is_a?(Class)
    next unless cls.superclass == Conjur::Bootstrap::Command::Base
    cls.new(self, listener).perform
  end
end

#create_deputy(options = {}) ⇒ Conjur::Deputy

Create a Conjur deputy.

Deputies are used internally by Conjur services that need to perform actions as a particular role. While the deputies API is stable, it isn't intended for use by end users.

Parameters:

  • options (Hash) (defaults to: {})

    options for deputy creation

Options Hash (options):

  • :id (String)

    the unqualified id for the new deputy. If not present, the deputy will be given a randomly generated id.

Returns:

Raises:

  • (RestClient::Conflict)

    if a deputy already exists with the given id.



40
41
42
# File 'lib/conjur/api/deputies.rb', line 40

def create_deputy options = {}
  standard_create Conjur::Core::API.host, :deputy, nil, options
end

#create_group(id, options = {}) ⇒ Conjur::Group

Create a new group with the given identifier.

Groups can be created with a gidnumber attribute, which is used when mapping LDAP/ActiveDirectory groups to Conjur groups, and when performing PAM authentication to assign a unix GID.

Examples:

group = api.create_group 'cats'
puts group.attributes
# Output
{"id"=>"cats",
  "userid"=>"admin",
  "ownerid"=>"conjur:user:admin",
  "gidnumber"=>nil,
  "roleid"=>"conjur:group:cats",
  "resource_identifier"=>"conjur:group:cats"}

Create a group with a GID number.

group = api.create_group 'dogs', gidnumber: 1337
puts group.attributes['gidnumber']
# Output
1337

Parameters:

  • id (String)

    the identifier for this group

  • options (Hash) (defaults to: {})

    options for group creation

Options Hash (options):

  • :gidnumber (FixNum)

    gidnumber to assign to this group (if not present, the group will not have a gidnumber, in contrast to Conjur User instances).

Returns:



69
70
71
# File 'lib/conjur/api/groups.rb', line 69

def create_group(id, options = {})
  standard_create Conjur::Core::API.host, :group, id, options
end

#create_host(options = nil) ⇒ Conjur::Host

Create a new host asset.

By default this method will create a host with a random id. However, you may create a host with a specific name by passing an :id option.

Permissions

  • Any Conjur role may perform this method without an :ownerid option. The new hosts owner will be the current role.
  • If you pass an `:ownerid option, you must be a member of the given role.

Examples:

# Create a host with a random id
anon = api.create_host
anon.id # => "wyzg17"

# Create a host with a given id
foo = api.create_host id: 'foo'
foo.id # => "foo"

# Trying to create a new host named foo fails
foo2 = api.create_host id: 'foo' # raises RestClient::Conflict

# Create a host owned by user 'alice' (assuming we're authenticated as
# a role of which alice is a member).
alice_host = api.create_host id: "host-for-alice", ownerid: 'conjur:user:ailce'
alice_host.ownerid # => "conjur:user:alice"

Parameters:

  • options (Hash, nil) (defaults to: nil)

    options for the new host

Options Hash (options):

  • :id (String)

    the id for the new host

  • :ownerid (String)

    set the new hosts owner to this role

Returns:

Raises:

  • RestClient::Conflict when id is given and a host with that id already exists.

  • RestClient::Forbidden when ownerid is given and the owner role does not exist, or you are not a member of the owner role.



80
81
82
83
84
# File 'lib/conjur/api/hosts.rb', line 80

def create_host options = nil
  options = options.merge \
      cidr: [*options[:cidr]].map(&CIDR.method(:validate)).map(&:to_s) if options[:cidr]
  standard_create Conjur::Core::API.host, :host, nil, options
end

#create_host_factory(id, options = {}) ⇒ Object

Options: +layers+ list of host factory layers +roleid+ host factory role id +role+ host factory role. If this is provided, it is converted to roleid.



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/conjur/api/host_factories.rb', line 41

def create_host_factory(id, options = {})
  if options[:layers]
    options[:layers] = options[:layers].map do |layer|
      if layer.is_a?(Conjur::Layer)
        layer.id
      elsif layer.is_a?(String)
        layer
      else
        raise "Can't interpret layer #{layer}"
      end
    end
  end
  if role = options.delete(:role)
    options[:roleid] = role.roleid
  end
  log do |logger|
    logger << "Creating host_factory #{id}"
    unless options.blank?
      logger << " with options #{options.to_json}"
    end
  end
  options ||= {}
  options[:id] = id
  resp = RestClient::Resource.new(Conjur::API.host_factory_asset_host, credentials).post(options)
  Conjur::HostFactory.build_from_response(resp, credentials)
end

#create_layer(id, options = {}) ⇒ Conjur::Layer

Create a new layer with the given id

Examples:

# create a new layer named 'webservers'
webservers = api.create_layer 'webservices'

# create layer is *not* idempotent
api.create_layer 'webservices' # raises RestClient::Conflict

# create a layer owned by user 'alice'
api.create_layer 'webservices', ownerid: 'alice'
api.owner # => 'conjur:user:alice'

Parameters:

  • id (String)

    an unqualified id for the layer.

Returns:



22
23
24
# File 'lib/conjur/api/layers.rb', line 22

def create_layer(id, options = {})
  standard_create Conjur::API.layer_asset_host, :layer, id, options
end

#create_resource(identifier, options = {}) ⇒ Conjur::Role

Create a Conjur Resource. Resources are entities on which roles have permissions. A resource might represent a secret, a web service route, or be part of a higher level construct such as a user or group.

If :acting_as is not present in options, you will be the owner of the new role. If it is present, your role must be a member of the given role (see Role#member_of?).

Examples:

Create an abstract resource to represent a web service route

# Notice that we can omit the account in the identifier
service_resource = api.create_resource 'web-service:list-gadgets'
service_resource.resource_id # => 'conjur:web-service:list-gadgets'

# In a gatekeeper for the web service, we can use the resource to control access
get '/gadgets' do
  # We'll assume that we've verified the Conjur authn token in the request, and stored the
  # corresponding identifier in `request_role_id`
  halt(403) unless api.resource('conjur:web-service:list-gadgets').permitted? 'read', request_role_id
  render_json find_gadgets
end

Create a role owned by another role

alice = api.role('user:alice')
api.current_role.member_of? alice # true, the operation will fail if this is false
res = api.create_resource 'example:owned', acting_as: 'user:alice'
res.owner # "conjur:user:alice"

Parameters:

  • identifier (String)

    an id of the form "<account>:<kind>:<id>" or "<kind>:<id>"

  • options (Hash) (defaults to: {})

    options for the request

Options Hash (options):

  • :acting_as (String, #role_id)

    the role-ish thing or role id that will own the new resource

Returns:



57
58
59
60
61
# File 'lib/conjur/api/resources.rb', line 57

def create_resource(identifier, options = {})
  resource(identifier).tap do |r|
    r.create(options)
  end
end

#create_role(role, options = {}) ⇒ Conjur::Role

Create a Role with the given id.

Permissions

  • All Conjur roles can create new roles.
  • The creator role (either the current role or the role given by the :acting_as option) is made a member of the new role. The new role is also made a member of itself.
  • If you give an :acting_as option, you must be a (transitive) member of the :acting_as role.
  • The new role is granted to the creator role with admin option: that is, the creator role is able to grant the created role to other roles.

Examples:

Basic role creation

# Current role is 'user:jon', assume the organizational account is 'conjur'
 api.current_role # => 'conjur:user:jon'

# Create a Conjur actor to control the permissions of a chron job (rebuild_indices)
role = api.create_role 'robot:rebuild_indices'
role.role_id # => "conjur:robot:rebuild_indices"
role.members.map{ |grant| grant.member.role_id } # => ['conjur:user:jon', 'conjur:robot:rebuild_indices']
api.role('user:jon').admin_of?(role) # => true

Parameters:

  • role (String)

    a qualified role identifier for the new role

  • options (Hash) (defaults to: {})

    options for the action

Options Hash (options):

  • :acting_as (String)

    the resource will effectively be created by this role

Returns:

Raises:

  • (RestClient::MethodNotAllowed)

    if the role already exists. Note that this differs from the RestClient::Conflict exception raised when trying to create existing high level (user, group, etc.) Conjur assets.



79
80
81
82
83
# File 'lib/conjur/api/roles.rb', line 79

def create_role(role, options = {})
  role(role).tap do |r|
    r.create(options)
  end
end

#create_user(login, options = {}) ⇒ Conjur::User

Create a Conjur User. Conjur users are identities for humans.

When you create a user for the first time, the returned object will have an api_key field. You can then use this to set a password for the user if you want to. Note that when the user is fetched later with the #user method, it will not have an api_key. Use it or lose it.

Permissions

Any authenticated role may call this method.

Examples:

Create a user 'alice' and set her password to 'frogger'

alice = api.create_user 'alice', password: 'frogger'

# Now we can login as 'alice'.
alice_api = Conjur::API.new_from_key 'alice', 'frogger'
alice_api.current_role # => 'conjur:user:alice'

Create a user and save her api_key for later use

alice = api.create_user 'alice' # note that we're not giving a password
save_api_key 'alice', alice.api_key

Parameters:

  • login (String)

    the login for the new user

  • options (Hash) (defaults to: {})

    options for user creation

Options Hash (options):

  • :acting_as (String)

    Qualified id of a role to perform the action as

  • :cidr (Array<String, IPAddr>)

    CIDR addresses of networks the new user will be allower to login from

  • :uidnumber (String, Integer)

    UID number to assign to the new user. If not given, one will be generated.

  • :password (String)

    when present, the user will be given a password in addition to a randomly generated api key.

Returns:

Raises:

  • (RestClient::Conflict)

    If the user already exists, or a user with the given uidnumber exists.



59
60
61
62
63
# File 'lib/conjur/api/users.rb', line 59

def create_user(, options = {})
  options = options.merge \
      cidr: [*options[:cidr]].map(&CIDR.method(:validate)).map(&:to_s) if options[:cidr]
  standard_create Conjur::Core::API.host, :user, nil, options.merge(login: )
end

#create_variable(mime_type, kind, options = {}) ⇒ Conjur::Variable

Create a Conjur Variable. See Variable for operations on Conjur variables.

Permissions

Any authenticated role may call this method

Examples:

Create a variable to store a database connection string

db_uri = "mysql://username:[email protected]/mydb"
var = api.create_variable 'text/plain', 'mysql-connection-string', id: 'production/mysql/uri'
var.add_value db_uri

# Alternatively, we could have done this:
var = api.create_variable 'text/plain', 'mysql-connection-string',
      id: 'production/mysql/uri',
      value: db_uri

Create a variable with a unique random id

var = api.create_variable 'text/plain', 'secret'
var.id # => 'kngeqg'

Parameters:

  • mime_type (String)

    MIME type for the variable value, used to set the "Content-Type"header when serving the variable's value. Must be non-empty.

  • kind (String)

    user defined kind for the variable. This is useful as a simple way to document the variable's purpose. Must be non-empty

  • options (Hash) (defaults to: {})

    options for the new variable

Options Hash (options):

  • :id (String)

    specify an id for the new variable. Must be non-empty.

  • :value (String)

    specify an initial value for the variable

Returns:

Raises:

  • (RestClient::Conflict)

    if you give an :id option and the variable already exists

  • (RestClient::UnprocessableEntity)

    if mime_type, kind, or options[:id] is the empty string.



57
58
59
# File 'lib/conjur/api/variables.rb', line 57

def create_variable(mime_type, kind, options = {})
  standard_create Conjur::Core::API.host, :variable, nil, options.merge(mime_type: mime_type, kind: kind)
end

#credentialsHash

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.

Returns:

  • (Hash)

    the options.

Raises:

  • (RestClient::Unauthorized)

    if fetching the token fails.

See Also:

  • Conjur::API.{{#token}


231
232
233
234
235
236
237
238
239
240
# File 'lib/conjur/base.rb', line 231

def credentials
  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
    h[:conjur_audit_roles] = Conjur::API.encode_audit_ids(@audit_roles) if @audit_roles
    h[:conjur_audit_resources] = Conjur::API.encode_audit_ids(@audit_resources) if @audit_resources
  end
  { headers: headers, username: username }
end

#current_roleConjur::Role

Return a Role object representing the role (typically a user or host) that this api is authenticated as. This is derived either from the login argument to new_from_key or from the contents of the token given to new_from_token.

Examples:

Current role for a user

api = Conjur::API.new_from_key 'jon', 'somepassword'
api.current_role.roleid # => 'conjur:user:jon'

Current role for a host

host = api.create_host id: 'exapmle-host'

# Host and User have an `api` method that returns an api with their credentials.  Note
# that this only works with a newly created host or user, which has an `api_key` attribute.
host.api.current_role.roleid # => 'conjur:host:example-host'

Returns:

  • (Conjur::Role)

    the authenticated role for this API instance



130
131
132
# File 'lib/conjur/api/roles.rb', line 130

def current_role
  role_from_username username
end

#delete_public_key(username, keyname)

This method returns an undefined value.

Delete a specific public key for a user.

Permissions

You must have permission to 'update' the pubkeys service resource. When the Conjur appliance is configured, it creates the pubkeys service resource with this identifier '<organizational account>:service:pubkeys-1.0/public-keys'.

Rather than granting permissions to this resource directly to user roles, we recommend that you add them to the 'key-managers' group, whose unqualified identifier is 'pubkeys-1.0/key-managers', which has permission to add public keys.

Hiding Existence

Because attackers could use this method to determine the existence of Conjur users, it will not raise an error if the user does not exist.

Examples:

Delete all public keys for 'bob'


api.public_key_names('bob').count # => 6
api.public_key_names('bob').each do |keyname|
  api.delete_public_key 'bob', keyname
end
api.public_key_names('bob').count # => 0

Parameters:

  • username (String)

    the Conjur username/login

  • keyname (String)

    the individual key to delete.



166
167
168
# File 'lib/conjur/api/pubkeys.rb', line 166

def delete_public_key username, keyname
  public_keys_resource(username, keyname).delete
end

#deputy(id) ⇒ Conjur::Deputy

Find a Conjur deputy by id. Deputies are used internally by Conjur services that need to perform actions as a particular role. While the deputies API is stable, it isn't intended for use by end users.

Parameters:

  • id (String)

    the deputy's unqualified id

Returns:



53
54
55
# File 'lib/conjur/api/deputies.rb', line 53

def deputy id
  standard_show Conjur::Core::API.host, :deputy, id
end

#find_groups(options) ⇒ Array<String>

Find groups by GID. Note that gidnumbers are not unique for groups.

Examples:

dogs = api.create_group 'dogs', gidnumber: 42
cats = api.create_group 'cats', gidnumber: 42
api.find_groups gidnumber: 42
# => ['cats', 'dogs']
groups = api.find_groups(gidnumber: 42).map{|id| api.group(id)}
groups.map(&:class) # => [Conjur::Group, Conjur::Group]

Parameters:

  • options (Hash)

    search criteria

Options Hash (options):

  • :gidnumber (Integer)

    GID number

Returns:

  • (Array<String>)

    group names matching the criteria



106
107
108
# File 'lib/conjur/api/groups.rb', line 106

def find_groups options
  JSON.parse(RestClient::Resource.new(Conjur::Core::API.host, credentials)["groups/search?#{options.to_query}"].get)
end

#global_privilege_permitted?(privilege) ⇒ Boolean

Checks whether the client has a particular global privilege. The global privileges are elevate and reveal.

Returns:

  • (Boolean)


171
172
173
# File 'lib/conjur/api/resources.rb', line 171

def global_privilege_permitted? privilege
  resource(GLOBAL_PRIVILEGE_RESOURCE).permitted? privilege
end

#group(id) ⇒ Conjur::Group

Fetch a group with the given id. Note that the id is unqualified -- it must not contain account or id parts. For example,

Examples:

group = api.create_group 'fish'
right = api.group 'fish'
wrong = api.group 'conjur:group:fish'
right.exists? # => true
wrong.exists? # => false

Parameters:

  • id (String)

    the identifier of the group

Returns:



87
88
89
# File 'lib/conjur/api/groups.rb', line 87

def group id
  standard_show Conjur::Core::API.host, :group, id
end

#groups(options = {}) ⇒ Array<Conjur::Group>

List all Conjur groups visible to the current role. This method does not support advanced query options. If you want those, use #resources with the :kind option set to 'group'.

Examples:

api.groups.count # => 163 (yikes!)

Parameters:

  • options (Hash) (defaults to: {})

    included for compatibility. Do not use this parameter!

Returns:



37
38
39
# File 'lib/conjur/api/groups.rb', line 37

def groups(options={})
  standard_list Conjur::Core::API.host, :group, options
end

#host(id) ⇒ Conjur::Host

Get a host by its unqualified id.

Like other Conjur methods, this will return a Host whether or not the record is found, and you must use the Exists#exists? method to check this.

Examples:

api.create_host id: 'foo'
foo = api.host "foo" # => returns a Conjur::Host
puts foo.resourceid # => "conjur:host:foo"
puts foo.id # => "foo"
mistake = api.host "doesnotexist" # => Also returns a Conjur::Host
foo.exists? # => true
mistake.exists? # => false

Parameters:

  • id (String)

    the unqualified id of the host

Returns:

  • (Conjur::Host)

    an object representing the host, which may or may not exist.



210
211
212
# File 'lib/conjur/base.rb', line 210

def host
  self.class.host
end

#host_factory(id) ⇒ Object



68
69
70
# File 'lib/conjur/api/host_factories.rb', line 68

def host_factory id
  Conjur::HostFactory.new(Conjur::API.host_factory_asset_host, credentials)[fully_escape(id)]
end

#host_factory_create_host(token, id, options = {}) ⇒ Object

Creates a Host and returns a Host object.



86
87
88
89
90
91
# File 'lib/conjur/api/host_factories.rb', line 86

def host_factory_create_host token, id, options = {}
  attributes = self.class.host_factory_create_host token, id, options
  Conjur::Host.new(Conjur::API.core_asset_host, credentials)["hosts"][fully_escape attributes['id']].tap do |host|
    host.attributes = attributes
  end
end

#init_from_key(username, api_key, remote_ip = nil) ⇒ Object



369
370
371
372
373
374
375
# File 'lib/conjur/base.rb', line 369

def init_from_key username, api_key, remote_ip = nil
  @username = username
  @api_key = api_key
  @remote_ip = remote_ip
  @authenticator = APIKeyAuthenticator.new(username, api_key)
  self
end

#init_from_token(token, remote_ip = nil) ⇒ Object



377
378
379
380
381
382
# File 'lib/conjur/base.rb', line 377

def init_from_token token, remote_ip = nil
  @token = token
  @remote_ip = remote_ip
  @authenticator = UnableAuthenticator.new
  self
end

#init_from_token_file(token_file, remote_ip = nil) ⇒ Object



384
385
386
387
388
# File 'lib/conjur/base.rb', line 384

def init_from_token_file token_file, remote_ip = nil
  @remote_ip = remote_ip
  @authenticator = TokenFileAuthenticator.new(token_file)
  self
end

#layer(id) ⇒ Conjur::Layer

Get a layer by its unqualified id.

Like other Conjur methods, this will return a Layer whether or not the record is found, and you must use the Exists#exists? method to check this.

Examples:

api.create_layer id: 'foo'
foo = api.layer "foo" # => returns a Conjur::Layer
puts foo.resourceid # => "conjur:layer:foo"
puts foo.id # => "foo"
mistake = api.layer "doesnotexist" # => Also returns a Conjur::Layer
foo.exists? # => true
mistake.exists? # => false

Parameters:

  • id (String)

    the unqualified id of the layer

Returns:

  • (Conjur::Layer)

    an object representing the layer, which may or may not exist.



56
57
58
# File 'lib/conjur/api/layers.rb', line 56

def layer id
  standard_show Conjur::API.layer_asset_host, :layer, id
end

#layers(options = {}) ⇒ Array<Conjur::Layer>

Get all layers visible to the current role.

The options parameter is only included for backwards compatibility and has no effect. You should call this method without arguments.

Parameters:

  • options (Hash) (defaults to: {})

    deprecated, unused

Returns:

  • (Array<Conjur::Layer>)

    all layers visible to the current role



34
35
36
# File 'lib/conjur/api/layers.rb', line 34

def layers options={}
  standard_list Conjur::API.layer_asset_host, :layer, options
end

#ldap_sync_policy(profile, options = {}) ⇒ Object

Fetch a Conjur policy that will bring Conjur into sync with the LDAP server specified by a profile.

Parameters:

  • profile (String)

    the name of the LDAP server profile

  • options (Hash) (defaults to: {})

    reserved for future use



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/conjur/api/ldapsync.rb', line 32

def ldap_sync_policy profile, options = {}
  
  headers = credentials.dup.tap {|h|
    h[:headers][:accept] = 'text/event-stream'
  }

  options = options.merge(:config_name => profile)
  url = Conjur.configuration.appliance_url + "/ldap-sync/policy?#{options.to_query}"

  # Even though we're using SSE to return the policy, fetch the
  # whole thing at once into a single response. Retrieving it in
  # chunks doesn't buy us much of anything except more complicated
  # client code.
  response = RestClient::Resource.new(url, headers).get
  JSON.parse(get_json("policy", response)).merge('events' => find_log_events(response))
end

#ldap_sync_show_profile(profile, options = {}) ⇒ Object

Parameters:

  • profile (String)

    name

  • options (Hash) (defaults to: {})

    reserved



54
55
56
57
58
# File 'lib/conjur/api/ldapsync.rb', line 54

def ldap_sync_show_profile(profile, options = {})
  url = Conjur.configuration.appliance_url
  resp = RestClient::Resource.new(url, credentials)['ldap-sync']['config'][profile].get(options)
  JSON.parse(resp.body)
end

#public_key(username, keyname) ⇒ String

Fetch a specific key by name. The key name is the last token in the public key itself, typically formatted as '<login>@<hostname>'.

Permissions

You do not need any special permissions to call this method, since public keys are, well, public.

Examples:

Get bob's key for 'bob@somehost'

key = begin
  api.public_key 'bob', 'bob@somehost'
rescue RestClient::ResourceNotFound
  puts "Key or user not found!"
  # Deal with it
end

Parameters:

  • username (String)

    A Conjur username

  • keyname (String)

    The name or identifier of the key

Returns:

  • (String)

    the public key

Raises:

  • (RestClient::ResourceNotFound)

    if the user or key does not exist.



69
70
71
# File 'lib/conjur/api/pubkeys.rb', line 69

def public_key username, keyname
  public_keys_resource(username, keyname).get
end

#public_key_names(username) ⇒ Array<String>

List the public key names for the given user.

If the given user does not exist, an empty Array will be returned. This is to prevent attackers from determining whether a user exists.

Permissions

You do not need any special permissions to call this method, since public keys are, well, public.

Examples:

List the names of public keys for 'otto'

api.public_key_names('otto').each{|n| puts n}
# otto@somehost
# admin@someotherhost

A non existent user has no public keys

user = api.user('doesnotexist')
user.exists? # => false
user.public_key_names # => []

Parameters:

  • username (String)

    the Conjur username

Returns:

  • (Array<String>)

    the names of the user's public keys



94
95
96
# File 'lib/conjur/api/pubkeys.rb', line 94

def public_key_names username
  public_keys(username).lines.map{|s| s.split(' ')[-1]}
end

#public_keys(username) ⇒ String

Fetch all public keys for the user. This method returns a newline delimited String for compatibility with the authorized_keys SSH format.

If the given user does not exist, an empty String will be returned. This is to prevent attackers from determining whether a user exists.

Permissions

You do not need any special permissions to call this method, since public keys are, well, public.

Examples:

puts api.public_keys('jon')
# ssh-rsa [big long string] jon@albert
# ssh-rsa [big long string] jon@conjurops

Parameters:

  • username (String)

    the unqualified Conjur username

Returns:

  • (String)

    newline delimited public keys



45
46
47
# File 'lib/conjur/api/pubkeys.rb', line 45

def public_keys username
  public_keys_resource(username).get
end

#resource(identifier) ⇒ Conjur::Resource

Find a resource by it's id. The id given to this method must be qualified by a kind, but the account is optional.

Permissions

The resource must be visible to the current role. This is the case if the current role is the owner of the resource, or has any privilege on it.

Examples:

Find or create a resource

def find_or_create_resource resource_id
   resource = api.resource resource_id
   unless resource.exists?
     resource = api.create_resource resource_id
   end
   resource
 end

 # ...
 example_resource = find_or_create_resource 'example:find-or-create'
 example_resource.exists? # always true

Parameters:

  • identifier (String)

    a qualified resource identifier, optionally including an account

Returns:



86
87
88
# File 'lib/conjur/api/resources.rb', line 86

def resource identifier
  Resource.new(Conjur::Authz::API.host, credentials)[self.class.parse_resource_id(identifier).join('/')]
end

#resources(opts = {}) ⇒ Array<Conjur::Resource>

Find all resources visible to the current role that match the given search criteria.

Conjur supports full text search over the identifiers and annotation values of resources. For example, if opts[:search] is "pubkeys", any resource with an id containing "pubkeys" or an annotation whose value contains "pubkeys" will match.

Notes

  • Annotation keys are not indexed for full text search.
  • Conjur indexes the content of ids and annotation values by word.
  • Only resources visible to the current role (either owned by that role or having a privilege on it) are returned.
  • If you do not provide :offset or :limit, all records will be returned. For systems with a huge number of resources, you may want to paginate as shown in the example below.
  • If :offset is provided and :limit is not, 10 records starting at :offset will be returned. You may choose an arbitrarily large number for :limit, but the same performance considerations apply as when omitting :offset and :limit.

Examples:

Search for resources annotated with the text "WebService Route"

webservice_routes = api.resources search: "WebService Route"

# Check that it worked:
webservice_routes.each do |resource|
   searchable = [resource.annotations.to_h.values, resource.resource_id]
   raise "FAILED" unless searchable.flatten.any?{|s| s.include? "WebService Route"}
end

Restrict the search to 'group' resources

groups = api.resources kind: 'group'

# Correct behavior:
expect(groups.all?{|g| g.kind == 'group'}).to be_true

Get every single resource in a performant way

resources = []
limit = 25
offset = 0
until (batch = api.resources limit: limit, offset: offset).empty?
  offset += batch.length
  resources.concat results
end
# do something with your resources

Parameters:

  • opts (Hash) (defaults to: {})

    search criteria

Options Hash (opts):

  • :search (String)

    find resources whose ids or annotations contain this string

  • :kind (String)

    find resources whose kind matches this string

  • :limit (Integer)

    the maximum number of records to return (Conjur may return fewer)

  • :offset (Integer)

    offset of the first record to return

Returns:



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/conjur/api/resources.rb', line 140

def resources opts = {}
  opts = { host: Conjur::Authz::API.host, credentials: credentials }.merge opts
  opts[:account] ||= Conjur.
  
  result = Resource.all(opts)
  if result.is_a?(Numeric)
    result
  else
    result.map do |result|
      resource(result['id']).tap do |r|
        r.attributes = result
      end
    end
  end
end

#resources_permitted?(kind, identifiers, privilege) ⇒ Array

Returns first element is a Boolean, true if all checks passed, false otherwise. If some checks fail, second element is the check result for each resource.

Parameters:

  • kind (String)

    the kind of resources to check

  • identifiers (Array<String>)

    the (unqualified) identifiers of the resources

  • privilege (String)

    the privilege to check for

Returns:

  • (Array)

    first element is a Boolean, true if all checks passed, false otherwise. If some checks fail, second element is the check result for each resource.



188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/conjur/api/resources.rb', line 188

def resources_permitted? kind, identifiers, privilege
  options = {
    privilege: privilege,
    identifiers: identifiers
  }
  resp = RestClient::Resource.new(Conjur::Authz::API.host, credentials)["#{Conjur.}/resources/#{kind}?check=true"].post(options)
  if resp.code == 204
    [true, []]
  else
    [false, JSON.parse(resp.body)]
  end
end

#revoke_host_factory_token(token) ⇒ Object



72
73
74
75
# File 'lib/conjur/api/host_factories.rb', line 72

def revoke_host_factory_token token
  token = token.token if token.is_a?(Conjur::HostFactoryToken)
  RestClient::Resource.new(Conjur::API.host_factory_asset_host, credentials)["tokens/#{token}"].delete
end

#role(role) ⇒ Conjur::Role

Return a Role representing a role with the given id. Note that the Role may or may not exist (see Exists#exists?).

Permissions

Because this method returns roles that may or may not exist, it doesn't require any permissions to call it: in fact, it does not perform an HTTP request (except for authentication if necessary).

Examples:

Create and show a role

api.create_role 'cat:iggy'
iggy = api.role 'cat:iggy'
iggy.exists? # true
iggy.members.map(&:member).map(&:roleid) # => ['conjur:user:admin']
api.current_role.roleid # => 'conjur:user:admin' # creator role is a member of created role.

No permissions are required to call this method

api.current_role # => "user:no-access"

# current role is only a member of itself, so it can't see other roles.
api.current_role.memberships.count # => 1
admin = api.role 'user:admin' # OK
admin.exists? # => true
admin.members # => RestClient::Forbidden: 403 Forbidden

Parameters:

  • role (String)

    the id of the role, which must contain at least kind and id tokens (account is optional).

Returns:



110
111
112
# File 'lib/conjur/api/roles.rb', line 110

def role role
  Role.new(Conjur::Authz::API.host, credentials)[self.class.parse_role_id(role).join('/')]
end

#role_graph(roles, options = {}) ⇒ Conjur::Graph

Fetch a Graph representing the relationships of a given role or roles. Such graphs are transitive, and follow the normal permissions for role visibility.

Parameters:

  • roles (Array<Conjur::Role, String>, String, Conjur::Role)

    role or or array of roles roles whose relationships we're interested in

  • options (Hash) (defaults to: {})

    options for the request

Options Hash (options):

  • :ancestors (Boolean)

    Whether to return ancestors ("roles that your role has") of the given roles (true by default)

  • :descendants (Boolean)

    Whether to return descendants ("roles that have your role") of the given roles (true by default)

  • :as_role (Conjur::Role, String)

    Only roles visible to this role will be included in the graph

Returns:

  • (Conjur::Graph)

    An object representing the role memberships digraph



38
39
40
41
42
43
44
45
46
47
48
# File 'lib/conjur/api/roles.rb', line 38

def role_graph roles, options = {}
  roles = [roles] unless roles.kind_of? Array
  roles.map!{|r| normalize_roleid(r) }
  options[:as_role] = normalize_roleid(options[:as_role]) if options.include?(:as_role)
  options.reverse_merge! as_role: normalize_roleid(current_role), descendants: true, ancestors: true

  query = {from_role: options.delete(:as_role)}
    .merge(options.slice(:ancestors, :descendants))
    .merge(roles: roles).to_query
  Conjur::Graph.new RestClient::Resource.new(Conjur::Authz::API.host, credentials)["#{Conjur.}/roles?#{query}"].get
end

#show_host_factory_token(token) ⇒ Object



77
78
79
80
81
82
83
# File 'lib/conjur/api/host_factories.rb', line 77

def show_host_factory_token token
  token = token.token if token.is_a?(Conjur::HostFactoryToken)
  attrs = JSON.parse(RestClient::Resource.new(Conjur::API.host_factory_asset_host, credentials)["tokens/#{token}"].get.body)
  Conjur::HostFactoryToken.new(Conjur::API.host_factory_asset_host, credentials)["tokens"][attrs['token']].tap do |token|
    token.attributes = attrs
  end
end

#tokenHash

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.

Returns:

  • (Hash)

    the authentication token as a Hash

Raises:

  • (RestClient::Unauthorized)

    if the username and api key are invalid.



220
221
222
223
# File 'lib/conjur/base.rb', line 220

def token
  refresh_token if needs_token_refresh?
  return @token
end

#user(login) ⇒ Conjur::User

Return an object representing a user with the given login. The User object returned may or may not exist. You can check whether it exists with the Exists#exists? method.

The returned User will not have an api_key.

Permissions

Any authenticated role may call this method.

Parameters:

  • login (String)

    the user's login

Returns:



75
76
77
# File 'lib/conjur/api/users.rb', line 75

def user 
  standard_show Conjur::Core::API.host, :user, 
end

#usernameString

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.

Returns:

  • (String)

    the login of the current user.



194
195
196
# File 'lib/conjur/base.rb', line 194

def username
  @username || @token['data']
end

#variable(id) ⇒ Conjur::Variable

Retrieve an object representing a Conjur Variable. The Variable returned may or may not exist, and your permissions on the corresponding resource determine the operations you can perform on it.

Permissions

Any authenticated role can call this method.

Parameters:

  • id (String)

    the unqualified id of the variable

Returns:



70
71
72
# File 'lib/conjur/api/variables.rb', line 70

def variable id
  standard_show Conjur::Core::API.host, :variable, id
end

#variable_expirations(interval = nil) ⇒ Object

param interval a String containing an ISO8601 duration , or a number of seconds return [Hash] variable expirations that occur within the interval



126
127
128
129
130
# File 'lib/conjur/api/variables.rb', line 126

def variable_expirations(interval = nil)
  duration = interval.try { |i| i.respond_to?(:to_str) ? i : "PT#{i.to_i}S" }
  params = {}.tap { |p| p.merge!({:params => {:duration => duration }}) if duration }
  JSON.parse(RestClient::Resource.new(Conjur::Core::API.host, self.credentials)['variables/expirations'].get(params).body)
end

#variable_values(varlist) ⇒ Hash

Fetch the values of a list of variables. This operation is more efficient than fetching the values one by one.

This method will fail unless:

  • All of the variables exist
  • You have permission to 'execute' all of the variables

This method is used to implement the conjur env commands. You may consider using that instead to run your program in an environment with the necessary secrets.

Examples:

Fetch multiple variable values

values = variable_values ['postgres_uri', 'aws_secret_access_key', 'aws_access_key_id']
values # =>
{
   "postgres_uri" => "postgres://..."
   "aws_secret_access_key" => "..."
   "aws_access_key_id" => "..."
}

Parameters:

  • varlist (Array<String>)

    list of variable ids to fetch

Returns:

  • (Hash)

    a hash mapping variable ids to variable values

Raises:

  • (RestClient::Forbidden, RestClient::ResourceNotFound)

    if any of the variables don't exist or aren't accessible.



96
97
98
99
100
101
102
103
104
105
106
# File 'lib/conjur/api/variables.rb', line 96

def variable_values(varlist)
  raise ArgumentError, "Variables list must be an array" unless varlist.kind_of? Array 
  raise ArgumentError, "Variables list is empty" if varlist.empty?
  opts = "?vars=#{varlist.map { |v| fully_escape(v) }.join(',')}"
  begin 
    resp = RestClient::Resource.new(Conjur::Core::API.host, self.credentials)['variables/values'+opts].get
    return JSON.parse( resp.body ) 
  rescue RestClient::ResourceNotFound 
    return Hash[ *varlist.map { |v| [ v, variable(v).value ]  }.flatten ]  
  end
end

#with_audit_resources(resource_ids) ⇒ Object



259
260
261
262
263
264
265
# File 'lib/conjur/base.rb', line 259

def with_audit_resources resource_ids
  resource_ids = Array(resource_ids)
  self.clone.tap do |api|
    # Ensure that all resource ids are fully qualified
    api.audit_resources = resource_ids.collect { |id| api.resource(id).resourceid }
  end
end

#with_audit_roles(role_ids) ⇒ Object



251
252
253
254
255
256
257
# File 'lib/conjur/base.rb', line 251

def with_audit_roles role_ids
  role_ids = Array(role_ids)
  self.clone.tap do |api|
    # Ensure that all role ids are fully qualified
    api.audit_roles = role_ids.collect { |id| api.role(id).roleid }
  end
end

#with_privilege(privilege) ⇒ Object

Return a new API object with the specified X-Conjur-Privilege.

Returns:

  • The API instance.



245
246
247
248
249
# File 'lib/conjur/base.rb', line 245

def with_privilege privilege
  self.clone.tap do |api|
    api.privilege = privilege
  end
end