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.
- checksums.yaml +4 -4
- data/.yardopts +1 -0
- data/CHANGELOG.md +8 -0
- data/Gemfile +0 -1
- data/README.md +59 -18
- data/conjur-api.gemspec +2 -1
- data/lib/conjur/acts_as_asset.rb +6 -9
- data/lib/conjur/acts_as_role.rb +54 -7
- data/lib/conjur/annotations.rb +52 -14
- data/lib/conjur/api/audit.rb +54 -8
- data/lib/conjur/api/authn.rb +54 -9
- data/lib/conjur/api/groups.rb +67 -4
- data/lib/conjur/api/hosts.rb +62 -3
- data/lib/conjur/api/layers.rb +48 -3
- data/lib/conjur/api/pubkeys.rb +140 -9
- data/lib/conjur/api.rb +13 -1
- data/lib/conjur/base.rb +93 -6
- data/lib/conjur/configuration.rb +247 -20
- data/lib/conjur/exists.rb +26 -0
- data/lib/conjur/group.rb +50 -4
- data/lib/conjur/has_attributes.rb +66 -5
- data/lib/conjur/resource.rb +155 -13
- data/lib/conjur/role.rb +1 -1
- data/lib/conjur/standard_methods.rb +7 -2
- data/lib/conjur/variable.rb +168 -6
- data/lib/conjur-api/version.rb +1 -1
- data/lib/conjur-api.rb +2 -0
- data/spec/api/authn_spec.rb +6 -3
- data/spec/api/groups_spec.rb +1 -1
- data/spec/api/pubkeys_spec.rb +4 -4
- data/spec/api/roles_spec.rb +4 -2
- data/spec/api/users_spec.rb +2 -2
- data/spec/api/variables_spec.rb +1 -1
- data/spec/helpers/errors_matcher.rb +34 -0
- data/spec/helpers/request_helpers.rb +10 -0
- data/spec/lib/annotations_spec.rb +5 -2
- data/spec/lib/audit_spec.rb +5 -5
- data/spec/lib/group_spec.rb +1 -1
- data/spec/lib/resource_spec.rb +11 -11
- data/spec/lib/role_spec.rb +8 -7
- data/spec/lib/user_spec.rb +7 -3
- data/spec/ssl_spec.rb +85 -0
- data/spec/standard_methods_helper.rb +2 -0
- data/spec/variable_spec.rb +5 -3
- metadata +34 -7
- data/lib/conjur/patches/rest-client.rb +0 -32
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fa094471717dc9bb39477d76468d2663895d9fd4
|
4
|
+
data.tar.gz: d688adf16203e25c50646994bc619170d5633b89
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Programmatic Ruby access to the Conjur API.
|
4
4
|
|
5
|
-
|
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
|
-
|
19
|
+
# Usage
|
20
20
|
|
21
|
-
|
21
|
+
Connecting to Conjur is a two-step process:
|
22
22
|
|
23
|
-
|
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
|
-
|
27
|
-
Conjur.
|
40
|
+
require 'conjur/cli'
|
41
|
+
Conjur::Config.load
|
42
|
+
Conjur::Config.apply
|
28
43
|
```
|
29
44
|
|
30
|
-
|
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
|
-
|
48
|
+
## Authentication
|
49
|
+
|
50
|
+
Once Conjur is configured, the connection can be established like this:
|
33
51
|
|
34
52
|
```ruby
|
35
|
-
|
53
|
+
conjur = Conjur::Authn.connect nil, noask: true
|
36
54
|
```
|
37
55
|
|
38
|
-
|
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
|
-
|
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
|
-
|
44
|
-
Conjur
|
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
|
-
|
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
|
-
|
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
|
-
|
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', '
|
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
|
data/lib/conjur/acts_as_asset.rb
CHANGED
@@ -20,15 +20,12 @@
|
|
20
20
|
#
|
21
21
|
module Conjur
|
22
22
|
module ActsAsAsset
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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
|
data/lib/conjur/acts_as_role.rb
CHANGED
@@ -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
|
-
#
|
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
|
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
|
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
|
data/lib/conjur/annotations.rb
CHANGED
@@ -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
|
-
#
|
24
|
-
#
|
30
|
+
# with {#[]} and update with {#[]=}, {#each} it, and {#merge!} to do bulk updates.
|
31
|
+
#
|
25
32
|
class Annotations
|
26
33
|
include Enumerable
|
27
|
-
|
28
|
-
#
|
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
|
56
|
-
#
|
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
|
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|
|
data/lib/conjur/api/audit.rb
CHANGED
@@ -20,24 +20,70 @@
|
|
20
20
|
|
21
21
|
require 'conjur/event_source'
|
22
22
|
module Conjur
|
23
|
+
|
24
|
+
|
23
25
|
class API
|
24
|
-
|
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
|
30
|
-
#
|
31
|
-
#
|
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)
|
data/lib/conjur/api/authn.rb
CHANGED
@@ -23,7 +23,28 @@ require 'conjur/user'
|
|
23
23
|
module Conjur
|
24
24
|
class API
|
25
25
|
class << self
|
26
|
-
|
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
|
-
#
|
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
|
-
#
|
60
|
-
#
|
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}"
|
data/lib/conjur/api/groups.rb
CHANGED
@@ -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
|