conjur-api 4.13.0 → 4.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/CHANGELOG.md +8 -0
  4. data/Gemfile +0 -1
  5. data/README.md +59 -18
  6. data/conjur-api.gemspec +2 -1
  7. data/lib/conjur/acts_as_asset.rb +6 -9
  8. data/lib/conjur/acts_as_role.rb +54 -7
  9. data/lib/conjur/annotations.rb +52 -14
  10. data/lib/conjur/api/audit.rb +54 -8
  11. data/lib/conjur/api/authn.rb +54 -9
  12. data/lib/conjur/api/groups.rb +67 -4
  13. data/lib/conjur/api/hosts.rb +62 -3
  14. data/lib/conjur/api/layers.rb +48 -3
  15. data/lib/conjur/api/pubkeys.rb +140 -9
  16. data/lib/conjur/api.rb +13 -1
  17. data/lib/conjur/base.rb +93 -6
  18. data/lib/conjur/configuration.rb +247 -20
  19. data/lib/conjur/exists.rb +26 -0
  20. data/lib/conjur/group.rb +50 -4
  21. data/lib/conjur/has_attributes.rb +66 -5
  22. data/lib/conjur/resource.rb +155 -13
  23. data/lib/conjur/role.rb +1 -1
  24. data/lib/conjur/standard_methods.rb +7 -2
  25. data/lib/conjur/variable.rb +168 -6
  26. data/lib/conjur-api/version.rb +1 -1
  27. data/lib/conjur-api.rb +2 -0
  28. data/spec/api/authn_spec.rb +6 -3
  29. data/spec/api/groups_spec.rb +1 -1
  30. data/spec/api/pubkeys_spec.rb +4 -4
  31. data/spec/api/roles_spec.rb +4 -2
  32. data/spec/api/users_spec.rb +2 -2
  33. data/spec/api/variables_spec.rb +1 -1
  34. data/spec/helpers/errors_matcher.rb +34 -0
  35. data/spec/helpers/request_helpers.rb +10 -0
  36. data/spec/lib/annotations_spec.rb +5 -2
  37. data/spec/lib/audit_spec.rb +5 -5
  38. data/spec/lib/group_spec.rb +1 -1
  39. data/spec/lib/resource_spec.rb +11 -11
  40. data/spec/lib/role_spec.rb +8 -7
  41. data/spec/lib/user_spec.rb +7 -3
  42. data/spec/ssl_spec.rb +85 -0
  43. data/spec/standard_methods_helper.rb +2 -0
  44. data/spec/variable_spec.rb +5 -3
  45. metadata +34 -7
  46. data/lib/conjur/patches/rest-client.rb +0 -32
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 30c179935696f866037eeb767bc75a37fa852d2f
4
- data.tar.gz: dbb483606b3f77c0340e4fd46c97ac954cb72920
3
+ metadata.gz: fa094471717dc9bb39477d76468d2663895d9fd4
4
+ data.tar.gz: d688adf16203e25c50646994bc619170d5633b89
5
5
  SHA512:
6
- metadata.gz: 3b328c7fc9790246d738f07f9983c787d5024643fd41655430992d4526fd07106ddaae791572c4581a6f222b2bff370e6954125de91fa6f56382f7d93d93eed1
7
- data.tar.gz: d754a280ea0ad20a031d1b0561ca1338bc08bcff3df5d99b4992e605106c18b2c02b66d5207e3fe108d5b76fba7ed91e3096f04a74e6d2c002a9ec97482504aa
6
+ metadata.gz: 434da500b0bb392deb9f0e8380dab357394aa2b16f28bb5063f2619a484646c1a1912267ee48eed7e3cea4d9e88ac256e23c466f6bd25faf1123294cce68af58
7
+ data.tar.gz: d9097541c2faff292c2f2c201a5b2d7dac162ca4c023b45d52093215acb310a17ce295762dc221d3a7c2952554c0efff59b911518853eea4282feca61648e330
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --hide-void-return --markup markdown --no-private --hide-api private lib/**/*.rb
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ # v4.14.0
2
+
3
+ * Bump rest-client version, remove the troublesome mime-types patch
4
+ * Make sure SSL certificate verification is enabled
5
+ * Bugfix: Don't escape ids twice when listing records
6
+ * Add a stub so that require 'conjur-api' works
7
+ * Lots of doc updates
8
+
1
9
  # v4.13.0
2
10
 
3
11
  * Add GID handling utilities
data/Gemfile CHANGED
@@ -8,4 +8,3 @@ gemspec
8
8
  group :development do
9
9
  gem 'pry'
10
10
  end
11
-
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Programmatic Ruby access to the Conjur API.
4
4
 
5
- ## Installation
5
+ # Installation
6
6
 
7
7
  Add this line to your application's Gemfile:
8
8
 
@@ -16,44 +16,85 @@ Or install it yourself as:
16
16
 
17
17
  $ gem install conjur-api
18
18
 
19
- ## Usage
19
+ # Usage
20
20
 
21
- ### Programmatic configuration
21
+ Connecting to Conjur is a two-step process:
22
22
 
23
- To configure the API to connect to Conjur, specify the account and appliance_url (both of which are required) like this:
23
+ * **Configuration** Instruct the API where to find the Conjur endpoint and how to secure the connection.
24
+ * **Authentication** Provide the API with credentials that it can use to authenticate.
25
+
26
+ ## Configuration
27
+
28
+ The simplest way to configure the Conjur API is to use the configuration file stored on the machine.
29
+ If you have configured the machine with [conjur init](http://developer.conjur.net/reference/tools/init.html),
30
+ it's default location is `~/.conjurrc`.
31
+
32
+ The Conjur configuration process also checks `/etc/conjur.conf` for global settings. This is typically used
33
+ in server environments.
34
+
35
+ For custom scenarios, the location of the file can be overridden using the `CONJURRC` environment variable.
36
+
37
+ You can load the Conjur configuration file using the following Ruby code:
24
38
 
25
39
  ```ruby
26
- Conjur.configuration.account = 'my-account'
27
- Conjur.configuration.appliance_url = 'https://conjur.mydomain.com/api'
40
+ require 'conjur/cli'
41
+ Conjur::Config.load
42
+ Conjur::Config.apply
28
43
  ```
29
44
 
30
- You can also specify these values in environment variables, which is often a bit more convenient. Environment variables are mapped to configuration variables by prepending CONJUR_ to the all-caps name of the configuration variable, for example, `appliance_url` is `CONJUR_APPLIANCE_URL`, `account` is `CONJUR_ACCOUNT`, etc.
45
+ **Note** this code requires the [conjur-cli](https://github.com/conjurinc/cli-ruby) gem, which should also be in your
46
+ gemset or bundle.
31
47
 
32
- In either case, if you are using Conjur's self-signed cert, you will also need to configure certificate trust:
48
+ ## Authentication
49
+
50
+ Once Conjur is configured, the connection can be established like this:
33
51
 
34
52
  ```ruby
35
- OpenSSL::SSL::SSLContext::DEFAULT_CERT_STORE.add_file "/path/to/conjur-youraccount.pem"
53
+ conjur = Conjur::Authn.connect nil, noask: true
36
54
  ```
37
55
 
38
- ### Using Conjur system configuraiton
56
+ To [authenticate](http://developer.conjur.net/reference/services/authentication/authenticate.html), the API client must
57
+ provide a `login` name and `api_key`. The `Conjur::Authn.connect` will attempt the following, in order:
58
+
59
+ 1. Look for `login` in environment variable `CONJUR_AUTHN_LOGIN`, and `api_key` in `CONJUR_AUTHN_API_KEY`
60
+ 2. Look for credentials on disk. The default credentials file is `~/.netrc`. The location of the credentials file
61
+ can be overridden using the configuration file `netrc_path` option.
62
+ 3. Prompt for credentials. This can be disabled using the option `noask: true`.
63
+
64
+ ## Connecting Without Files
39
65
 
40
- To instantiate the API using configuration stored stored in `/etc/conjur.conf` and/or `~/.conjurrc`:
66
+ It's possible to configure and authenticate the Conjur connection without using any files, and without requiring
67
+ the `conjur-cli` gem.
68
+
69
+ To accomplish this, apply the configuration settings directly to the [Conjur::Configuration](https://github.com/conjurinc/api-ruby/blob/master/lib/conjur/configuration.rb)
70
+ object.
71
+
72
+ For example, specify the `account` and `appliance_url` (both of which are required) like this:
41
73
 
42
74
  ```ruby
43
- require 'conjur/cli'
44
- Conjur::Config.load
45
- Conjur::Config.apply
46
- conjur = Conjur::API.new_from_key username, api_key
75
+ Conjur.configuration.account = 'my-account'
76
+ Conjur.configuration.appliance_url = 'https://conjur.mydomain.com/api'
47
77
  ```
48
78
 
49
- `username` and `api_key` can also be provided by environment variables: `CONJUR_AUTHN_LOGIN` and `CONJUR_AUTHN_API_KEY`. If the login is a host, the `CONJUR_AUTHN_LOGIN` should be prefixed with `host/`. For example: `host/myhost.example.com`.
79
+ You can also specify these values using environment variables, which is often a bit more convenient.
80
+ Environment variables are mapped to configuration variables by prepending `CONJUR_` to the all-caps name of the
81
+ configuration variable. For example, `appliance_url` is `CONJUR_APPLIANCE_URL`, `account` is `CONJUR_ACCOUNT`.
82
+
83
+ In either case, you will also need to configure certificate trust. For example:
84
+
85
+ ```ruby
86
+ OpenSSL::SSL::SSLContext::DEFAULT_CERT_STORE.add_file "/etc/conjur-yourorg.pem"
87
+ ```
50
88
 
51
- If the login and API key are provided by `netrc` or by the environment, you can construct an API client using:
89
+ Once Conjur is configured, you can create a new API client by providing a `login` and `api_key`:
52
90
 
53
91
  ```ruby
54
- conjur = Conjur::Authn.connect
92
+ Conjur::API.new_from_key login, api_key
55
93
  ```
56
94
 
95
+ Note that if you are connecting as a [Host](http://developer.conjur.net/reference/services/directory/host), the login should be
96
+ prefixed with `host/`. For example: `host/myhost.example.com`, not just `myhost.example.com`.
97
+
57
98
  ## Contributing
58
99
 
59
100
  1. Fork it
data/conjur-api.gemspec CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |gem|
19
19
  gem.required_ruby_version = '>= 1.9'
20
20
 
21
21
 
22
- gem.add_dependency 'rest-client', '= 1.6.7' # with newer versions adding certificates to OpenSSL does not work
22
+ gem.add_dependency 'rest-client', '~> 1.7', '>= 1.7.3'
23
23
  gem.add_dependency 'activesupport'
24
24
 
25
25
  gem.add_development_dependency 'rake'
@@ -33,4 +33,5 @@ Gem::Specification.new do |gem|
33
33
  gem.add_development_dependency 'yard'
34
34
  gem.add_development_dependency 'redcarpet'
35
35
  gem.add_development_dependency 'timecop'
36
+ gem.add_development_dependency 'inch'
36
37
  end
@@ -20,15 +20,12 @@
20
20
  #
21
21
  module Conjur
22
22
  module ActsAsAsset
23
- def self.included(base)
24
- base.instance_eval do
25
- include HasId
26
- include Exists
27
- include HasOwner
28
- include ActsAsResource
29
- include HasAttributes
30
- end
31
- end
23
+ include HasId
24
+ include Exists
25
+ include HasOwner
26
+ include ActsAsResource
27
+ include HasAttributes
28
+
32
29
 
33
30
  def add_member(role_name, member, options = {})
34
31
  owned_role(role_name).grant_to member, options
@@ -19,29 +19,76 @@
19
19
  # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
20
  #
21
21
  module Conjur
22
+
23
+ # This module provides methods for things that have an associated {Conjur::Role}.
24
+ #
25
+ # All high level Conjur assets (groups and users, for example) are composed of both a role and a resource. This allows
26
+ # these assets to have permissions on other assets, and for other assets to have permission
27
+ # on them.
28
+ #
29
+ # The {Conjur::ActsAsRole} module itself should be considered private, but it's methods are
30
+ # public when added to a Conjur asset class.
22
31
  module ActsAsRole
32
+
33
+ # The qualified identifier for the role associated with this asset. A *qualified* identifier
34
+ # prepends the asset's account and kind, for example, a {Conjur::User} with login `'bob'` in a
35
+ # system with organizational account `'conjur'` would have a `roleid` of `'conjur:user:bob'`
36
+ #
37
+ # @return [String] the qualified role id
23
38
  def roleid
24
39
  [ core_conjur_account, role_kind, id ].join(':')
25
40
  end
26
-
41
+ alias role_id roleid
42
+
43
+ # The `kind` of a role. This may be any value, but standard ones correspond to various high level
44
+ # Conjur assets, for example, `'user'`, `'group'`, or `'variable'`.
45
+ #
46
+ # Note that this method derives the role kind from the asset's class name.
47
+ #
48
+ # @return [String] the role kind
27
49
  def role_kind
28
50
  self.class.name.split('::')[-1].underscore
29
51
  end
30
-
31
- # NOTE: parse_role_id returns tuple of path components
32
- # (basically, same components as in 'roleid' plus some prefixes)
52
+
53
+ # Get a {Conjur::Role} instance corresponding to the `role` associated with this asset.
33
54
  def role
34
55
  require 'conjur/role'
35
56
  Conjur::Role.new(Conjur::Authz::API.host, self.options)[Conjur::API.parse_role_id(self.roleid).join('/')]
36
57
  end
37
-
38
- # Permit this role to perform a privileged action.
58
+
59
+ # Permit the asset to perform `privilege` on `resource`. You can also use this method to control whether the role
60
+ # is able to grant the privilege on the resource to other roles by passing a `:grant_option` option.
61
+ #
62
+ # This method is primarily intended for use in the
63
+ # {http://developer.conjur.net/reference/tools/utilities/policy-load.html Conjur Policy DSL},
64
+ # and simply delegates to {Conjur::Resource#permit}. For code clarity, you might consider using
65
+ # that method instead.
66
+ #
67
+ # ### Permissions
68
+ #
69
+ # To call this method, you must *own* the resource, or have the privilege on it with grant option set to true.
70
+ #
71
+ # @api dsl
72
+ # @param [String] privilege the privilege to allow this role to perform, e.g. `'execute'` or `'update'`
73
+ # @param [Conjur::Resource, #resource_id, String] resource the resource to grant `privilege` on.
74
+ # @param [Hash] options Options to pass through to RestClient::Resource#post
75
+ # @option options [Boolean] :grant_option whether this role will be able to grant the privilege to other roles.
76
+ # @return [void]
39
77
  def can(privilege, resource, options = {})
40
78
  require 'conjur/resource'
41
79
  Conjur::Resource.new(Conjur::Authz::API.host, self.options)[Conjur::API.parse_resource_id(resource).join('/')].permit privilege, self.roleid, options
42
80
  end
43
81
 
44
- # Deny this role from performing perform a privileged action.
82
+ # Deny the asset's role the ability to perform `privilege` on `resource`. This operation is the inverse of {#can}.
83
+ #
84
+ # This method is primarily intended for use in the
85
+ # {http://developer.conjur.net/reference/tools/utilities/policy-load.html Conjur Policy DSL},
86
+ # and simply delegates to {Conjur::Resource#permit}. For code clarity, you might consider using
87
+ # that method instead.
88
+ #
89
+ # @see Conjur::Resource#deny
90
+ #
91
+ # @api dsl
45
92
  def cannot(privilege, resource, options = {})
46
93
  require 'conjur/resource'
47
94
  Conjur::Resource.new(Conjur::Authz::API.host, self.options)[Conjur::API.parse_resource_id(resource).join('/')].deny privilege, self.roleid
@@ -19,13 +19,26 @@
19
19
  # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
20
  #
21
21
  module Conjur
22
+ # Conjur allows {http://developer.conjur.net/reference/services/authorization/resource Resource}
23
+ # instances to be {http://developer.conjur.net/reference/services/authorization/resource/annotate.html annotated}
24
+ # with arbitrary key-value data. This data is generally for "user consumption", and it *is not* governed
25
+ # by any particular schema or constraints. Your applications can define their own schema for annotations they
26
+ # use. If you do so, we recommend prefixing your annotations, for example, `'myapp:Name'`, in order to avoid
27
+ # conflict with annotations used, for example, by the Conjur UI.
28
+ #
22
29
  # An Annotations instance acts like a Hash: you can fetch an annotation
23
- # with '[]' and update with '[]=', 'each' it, and 'merge!' to do bulk updates
24
- # (although merge! is not more efficient than setting each pair with '[]=').
30
+ # with {#[]} and update with {#[]=}, {#each} it, and {#merge!} to do bulk updates.
31
+ #
25
32
  class Annotations
26
33
  include Enumerable
27
-
28
- # @api private
34
+
35
+ # Create an `Annotations` instance for the given {Conjur::Resource}.
36
+ #
37
+ # Note that you will generally use the {Conjur::Resource#annotations} method to get
38
+ # the `Annotations` for a {Conjur::Resource}.
39
+ #
40
+ # @param resource [Conjur::Resource]
41
+ #
29
42
  def initialize resource
30
43
  @resource = resource
31
44
  end
@@ -37,11 +50,15 @@ module Conjur
37
50
  annotations_hash[name.to_sym]
38
51
  end
39
52
 
40
- # Set an annotation value
53
+ # Set an annotation value. This will perform an api call to set the annotation
54
+ # on the server.
55
+ #
41
56
  # @param [String, Symbol] name the annotation name
42
57
  # @param [String] value the annotation value
58
+ #
59
+ # @return [String] the new annotation value
43
60
  def []= name, value
44
- update_annotation name, value
61
+ update_annotation name.to_sym, value
45
62
  value
46
63
  end
47
64
 
@@ -52,31 +69,48 @@ module Conjur
52
69
  self
53
70
  end
54
71
 
55
- # Set annotations from key,value pairs in +hash+
56
- # @param [#each] hash
72
+ # Set annotations from key,value pairs in `hash`.
73
+ #
74
+ # @note this is currently no more efficient than setting each
75
+ # annotation with {#[]=}.
76
+ #
77
+ # @param [Hash, #each] hash
57
78
  # @return [Conjur::Annotations] self
58
79
  def merge! hash
59
80
  hash.each{|k,v| self[k] = v }
60
81
  self
61
82
  end
62
83
 
63
- # Return a proper hash containing a +copy+ of ourself. Note that
84
+ # Return a proper hash containing a **copy** of the annotations. Note that
64
85
  # updates to this hash have no effect on the actual annotations.
86
+ #
65
87
  # @return [Hash]
66
88
  def to_h
67
89
  annotations_hash.dup
68
90
  end
69
-
91
+
92
+ # Return the annotations hash as a string. This method simply delegates to
93
+ # `Hash#to_s`.
94
+ #
95
+ # @return [String]
70
96
  def to_s
71
97
  annotations_hash.to_s
72
98
  end
73
-
99
+
100
+ # Return an informative representation of the annotations, including
101
+ # the resource to which they're attached. Suitable for debugging.
102
+ #
103
+ # @return [String]
74
104
  def inspect
75
105
  "<Annotations for #{@resource.resourceid}: #{to_s}>"
76
106
  end
77
107
 
78
108
  protected
79
-
109
+ #@api private
110
+ # Update an annotation on the server.
111
+ # @param name [String]
112
+ # @param value [String, #to_s]
113
+ # @return [void]
80
114
  def update_annotation name, value
81
115
  @resource.invalidate do
82
116
  @annotations_hash = nil
@@ -84,11 +118,15 @@ module Conjur
84
118
  RestClient::Resource.new(Conjur::Authz::API.host, @resource.options)[path].put name: name, value: value
85
119
  end
86
120
  end
87
-
121
+
122
+ # @api private
123
+ # Our internal {Hash} of annotations. Lazily loaded.
88
124
  def annotations_hash
89
125
  @annotations_hash ||= fetch_annotations
90
126
  end
91
-
127
+
128
+ # @api private
129
+ # Fetch the annotations from the server.
92
130
  def fetch_annotations
93
131
  {}.tap do |hash|
94
132
  @resource.attributes['annotations'].each do |annotation|
@@ -20,24 +20,70 @@
20
20
 
21
21
  require 'conjur/event_source'
22
22
  module Conjur
23
+
24
+
23
25
  class API
24
- # Return all events visible to the current authorized role
26
+ #@!group Audit Service
27
+
28
+ # Return up to 100 audit events visible to the current authorized role.
29
+ #
30
+ # An audit event is visible to a role if that role or one of it's ancestors is in the
31
+ # event's `:roles` field, or the role has a privilege any of the event's `:resources` field.
32
+ #
33
+ # @param options [Hash]
34
+ # @option options [Time, nil] :till only show events before this time
35
+ # @option options [Time, nil] :since only show events after this time
36
+ # @option options [Boolean] :follow block the current thread and call `block` with `Array` of
37
+ # audit events as the occur.
38
+ #
39
+ # @see #audit_role
40
+ #
41
+ # @return [Array<Hash>] the audit events
25
42
  def audit options={}, &block
26
43
  audit_event_feed "", options, &block
27
44
  end
28
-
29
- # Return audit events related to the given role_id. Identitical to audit_events
30
- # except that a String may be given instead of a Role object.
31
- # @param role [String] the role for which events should be returned.
45
+
46
+ # Return up to 100 audit events visible to the current role and related to the given role.
47
+ #
48
+ # See {#audit} for the conditions under which an event is visible to a role.
49
+ #
50
+ # An event is said to be "related to" a role iff the role is a member of the event's
51
+ # `:roles` field.
52
+ #
53
+ # @param role [Conjur::Role, String, #roleid] the role to audit (if a string is given, it must
54
+ # be of the form `'account:kind:id'`).
55
+ # @param options [Hash]
56
+ # @option options [Time, nil] :till only show events before this time
57
+ # @option options [Time, nil] :since only show events after this time
58
+ # @option options [Boolean] :follow block the current thread and call `block` with `Array` of
59
+ # audit events as the occur.
60
+ #
61
+ # @return [Array<Hash>] the audit events
32
62
  def audit_role role, options={}, &block
33
63
  audit_event_feed "roles/#{CGI.escape cast(role, :roleid)}", options, &block
34
64
  end
35
-
36
- # Return audit events related to the given resource
65
+
66
+ # Return up to 100 audit events visible to the current role and related to the given resource.
67
+ #
68
+ # See {#audit} for the conditions under which an event is visible to a role.
69
+ #
70
+ # An event is said to be "related to" a role iff the role is a member of the event's
71
+ # `:roles` field.
72
+ # @param resource [Conjur::Resource, String, #resourceid] the resource to audit (when a string is given, it must be
73
+ # of the form `'account:kind:id'`).
74
+ # @param options [Hash]
75
+ # @option options [Time, nil] :till only show events before this time
76
+ # @option options [Time, nil] :since only show events after this time
77
+ # @option options [Boolean] :follow block the current thread and call `block` with `Array` of
78
+ # audit events as the occur.
79
+ #
80
+ # @return [Array<Hash>] the audit events
37
81
  def audit_resource resource, options={}, &block
38
82
  audit_event_feed "resources/#{CGI.escape cast(resource, :resourceid)}", options, &block
39
83
  end
40
-
84
+
85
+ #@!endgroup
86
+
41
87
  private
42
88
  def audit_event_feed path, options={}, &block
43
89
  query = options.slice(:since, :till)
@@ -23,7 +23,28 @@ require 'conjur/user'
23
23
  module Conjur
24
24
  class API
25
25
  class << self
26
- # Perform login by Basic authentication.
26
+ #@!group Authentication Methods
27
+
28
+ # The Conjur {http://developer.conjur.net/reference/services/authentication/login.html login}
29
+ # operation exchanges a username and a password for an api key. The api key
30
+ # is preferable for storage and use in code, as it can be rotated and has far greater entropy than
31
+ # a user memorizable password.
32
+ #
33
+ # * Note that this method works only for {http://developer.conjur.net/reference/services/directory/user Users}. While
34
+ # {http://developer.conjur.net/reference/services/directory/hosts Hosts} possess Conjur identities, they do not
35
+ # have passwords.
36
+ # * If you pass an api key to this method instead of a password, it will simply return the API key.
37
+ # * This method uses Basic Auth to send the credentials.
38
+ #
39
+ # @example
40
+ # bob_api_key = Conjur::API.login('bob', 'bob_password')
41
+ # bob_api_key == Conjur::API.login('bob', bob_api_key) # => true
42
+ #
43
+ # @param [String] username The `username` or `login` for the
44
+ # {http://developer.conjur.net/reference/services/directory/user Conjur User}.
45
+ # @param [String] password The `password` or `api key` to authenticate with.
46
+ # @return [String] the API key.
47
+ # @raise [RestClient::Exception] when the request fails or the identity provided is invalid.
27
48
  def login username, password
28
49
  if Conjur.log
29
50
  Conjur.log << "Logging in #{username} via Basic authentication\n"
@@ -31,7 +52,16 @@ module Conjur
31
52
  RestClient::Resource.new(Conjur::Authn::API.host, user: username, password: password)['users/login'].get
32
53
  end
33
54
 
34
- # Perform login by CAS authentication.
55
+ # TODO I have NO idea how to document login_cas!
56
+
57
+ # This method logs in via CAS. It is similar to the {.login} method, the only difference being that
58
+ # you need a `cas_api_url`, provided by the administrator of your `CAS` service.
59
+ #
60
+ # @see .login
61
+ # @param [String] username the Conjur username
62
+ # @param [String] password the Conjur password
63
+ # @param [String] cas_api_url the url of the CAS service
64
+ # @return [String] a `CAS` ticket
35
65
  def login_cas username, password, cas_api_url
36
66
  if Conjur.log
37
67
  Conjur.log << "Logging in #{username} via CAS authentication\n"
@@ -41,27 +71,42 @@ module Conjur
41
71
  client.get("#{Conjur::Authn::API.host}/users/login").body
42
72
  end
43
73
 
74
+ # The Conjur {http://developer.conjur.net/reference/services/authentication/authenticate.html authenticate} operation
75
+ # exchanges Conjur credentials for a token. The token can then be used to authenticate further API calls.
76
+ #
77
+ # You will generally not need to use this method, as the API manages tokens automatically for you.
78
+ #
79
+ # @param [String] username The username or host id for which we want a token
80
+ # @param [String] password The password or api key
81
+ # @return [String] A JSON formatted authentication token.
44
82
  def authenticate username, password
45
83
  if Conjur.log
46
84
  Conjur.log << "Authenticating #{username}\n"
47
85
  end
48
86
  JSON::parse(RestClient::Resource.new(Conjur::Authn::API.host)["users/#{fully_escape username}/authenticate"].post password, content_type: 'text/plain')
49
87
  end
50
-
88
+
89
+ # Change a user's password. To do this, you must have the user's current password. This does not change or rotate
90
+ # api keys. However, you *can* use the user's api key as the *current* password, if the user was not created
91
+ # with a password.
92
+ #
93
+ # @param [String] username the name of the user whose password we want to change
94
+ # @param [String] password the user's *current* password *or* api key
95
+ # @param [String] new_password the new password for the user.
96
+ # @return [void]
51
97
  def update_password username, password, new_password
52
98
  if Conjur.log
53
99
  Conjur.log << "Updating password for #{username}\n"
54
100
  end
55
101
  RestClient::Resource.new(Conjur::Authn::API.host, user: username, password: password)['users/password'].put new_password
56
102
  end
103
+
104
+ #@!endgroup
57
105
  end
58
106
 
59
- # Options:
60
- # +password+
61
- #
62
- # Response:
63
- # +login+
64
- # +api_key+
107
+ # @api private
108
+ # This is used internally to create a user that we can log in as without creating
109
+ # an actual user in the directory, as with #create_user.
65
110
  def create_authn_user login, options = {}
66
111
  log do |logger|
67
112
  logger << "Creating authn user #{login}"
@@ -20,29 +20,92 @@
20
20
  require 'conjur/group'
21
21
 
22
22
  module Conjur
23
+
24
+
23
25
  class API
26
+ # @!group Directory: Groups
27
+
28
+ # List all Conjur groups visible to the current role. This method does not
29
+ # support advanced query options. If you want those, use `#resources` with
30
+ # the `:kind` option set to `'group'`.
31
+ #
32
+ # @example
33
+ # api.groups.count # => 163 (yikes!)
34
+ #
35
+ # @param options [Hash] included for compatibility. Do not use this parameter!
36
+ # @return [Array<Conjur::Group>]
24
37
  def groups(options={})
25
38
  standard_list Conjur::Core::API.host, :group, options
26
39
  end
27
40
 
41
+ # Create a new group with the given identifier.
42
+ #
43
+ # Groups can be created with a gidnumber attribute, which is used when mapping LDAP/ActiveDirectory groups
44
+ # to Conjur groups, and when performing PAM authentication to assign a unix GID.
45
+ #
46
+ #
47
+ # @example
48
+ # group = api.create_group 'cats'
49
+ # puts group.attributes
50
+ # # Output
51
+ # {"id"=>"cats",
52
+ # "userid"=>"admin",
53
+ # "ownerid"=>"conjur:user:admin",
54
+ # "gidnumber"=>nil,
55
+ # "roleid"=>"conjur:group:cats",
56
+ # "resource_identifier"=>"conjur:group:cats"}
57
+ #
58
+ # @example Create a group with a GID number.
59
+ # group = api.create_group 'dogs', gidnumber: 1337
60
+ # puts group.attributes['gidnumber']
61
+ # # Output
62
+ # 1337
63
+ #
64
+ # @param [String] id the identifier for this group
65
+ # @param [Hash] options options for group creation
66
+ # @option options [FixNum] :gidnumber gidnumber to assign to this group (if not present, the
67
+ # group will *not* have a gidnumber, in contrast to Conjur {Conjur::User} instances).
68
+ # @return [Conjur::Group] the group created.
28
69
  def create_group(id, options = {})
29
70
  standard_create Conjur::Core::API.host, :group, id, options
30
71
  end
31
72
 
73
+
74
+ # Fetch a group with the given id. Note that the id is *unqualified* -- it must not contain
75
+ # `account` or `id` parts. For example,
76
+ #
77
+ # @example
78
+ # group = api.create_group 'fish'
79
+ # right = api.group 'fish'
80
+ # wrong = api.group 'conjur:group:fish'
81
+ # right.exists? # => true
82
+ # wrong.exists? # => false
83
+ #
84
+ # @param [String] id the identifier of the group
85
+ # @return [Conjur::Group] the group, which may or may not exist (you must check this using the {Conjur::Exists#exists?})
86
+ # method.
32
87
  def group id
33
88
  standard_show Conjur::Core::API.host, :group, id
34
89
  end
35
90
 
36
- # Find groups by GID.
91
+ # Find groups by GID. Note that gidnumbers are *not* unique for groups.
92
+ #
93
+ # @example
94
+ # dogs = api.create_group 'dogs', gidnumber: 42
95
+ # cats = api.create_group 'cats', gidnumber: 42
96
+ # api.find_groups gidnumber: 42
97
+ # # => ['cats', 'dogs']
98
+ #
99
+ # @example
100
+ # groups = api.find_groups(gidnumber: 42).map{|id| api.group(id)}
101
+ # groups.map(&:class) # => [Conjur::Group, Conjur::Group]
37
102
  #
38
103
  # @param [Hash] options search criteria
39
104
  # @option options [Integer] :gidnumber GID number
40
105
  # @return [Array<String>] group names matching the criteria
41
- #
42
- # @note You can get a {Conjur::Group} by calling {Conjur::API#group}, eg.:
43
- # +api.find_groups(gidnumber: 12345).map(&api.method(:group))+
44
106
  def find_groups options
45
107
  JSON.parse(RestClient::Resource.new(Conjur::Core::API.host, credentials)["groups/search?#{options.to_query}"].get)
46
108
  end
109
+ #@!endgroup
47
110
  end
48
111
  end