conjur-api 4.14.0 → 4.15.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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/CHANGELOG.md +4 -0
  4. data/lib/conjur-api/version.rb +1 -1
  5. data/lib/conjur/acts_as_asset.rb +44 -3
  6. data/lib/conjur/acts_as_resource.rb +53 -4
  7. data/lib/conjur/acts_as_user.rb +17 -7
  8. data/lib/conjur/annotations.rb +49 -3
  9. data/lib/conjur/api.rb +30 -3
  10. data/lib/conjur/api/deputies.rb +25 -1
  11. data/lib/conjur/api/resources.rb +109 -5
  12. data/lib/conjur/api/roles.rb +103 -11
  13. data/lib/conjur/api/secrets.rb +16 -1
  14. data/lib/conjur/api/users.rb +65 -1
  15. data/lib/conjur/api/variables.rb +65 -1
  16. data/lib/conjur/audit-api.rb +3 -0
  17. data/lib/conjur/authn-api.rb +4 -0
  18. data/lib/conjur/authz-api.rb +4 -0
  19. data/lib/conjur/base.rb +31 -30
  20. data/lib/conjur/build_from_response.rb +11 -0
  21. data/lib/conjur/cast.rb +5 -1
  22. data/lib/conjur/core-api.rb +22 -2
  23. data/lib/conjur/deputy.rb +19 -2
  24. data/lib/conjur/env.rb +18 -3
  25. data/lib/conjur/escape.rb +65 -4
  26. data/lib/conjur/event_source.rb +15 -2
  27. data/lib/conjur/graph.rb +103 -12
  28. data/lib/conjur/has_id.rb +13 -1
  29. data/lib/conjur/has_identifier.rb +9 -6
  30. data/lib/conjur/has_owner.rb +21 -7
  31. data/lib/conjur/host.rb +8 -0
  32. data/lib/conjur/layer-api.rb +4 -0
  33. data/lib/conjur/layer.rb +50 -3
  34. data/lib/conjur/log.rb +22 -2
  35. data/lib/conjur/log_source.rb +27 -0
  36. data/lib/conjur/path_based.rb +47 -2
  37. data/lib/conjur/pubkeys-api.rb +12 -0
  38. data/lib/conjur/role.rb +220 -9
  39. data/lib/conjur/role_grant.rb +50 -2
  40. data/lib/conjur/secret.rb +9 -1
  41. data/lib/conjur/standard_methods.rb +31 -3
  42. data/lib/conjur/user.rb +55 -3
  43. data/spec/lib/role_spec.rb +1 -2
  44. metadata +2 -2
@@ -19,7 +19,18 @@
19
19
  # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
20
  #
21
21
  module Conjur
22
+ # @api private
23
+ # This module is included by classes that can be built from JSON responses.
22
24
  module BuildFromResponse
25
+ # @api private
26
+ #
27
+ # Build a Conjur asset from a REST response.
28
+ #
29
+ # @param [RestCliet::Response] response the response to build the object from
30
+ # @param [Hash] credentials options as {Conjur::API#credentials} used to perform requests in methods on
31
+ # the created asset.
32
+ #
33
+ # @return [Object] an object of this type
23
34
  def build_from_response(response, credentials)
24
35
  new(response.headers[:location], credentials).tap do |obj|
25
36
  obj.attributes = JSON.parse(response.body)
data/lib/conjur/cast.rb CHANGED
@@ -21,7 +21,11 @@
21
21
  module Conjur
22
22
  module Cast
23
23
  protected
24
-
24
+
25
+ # Convert a value to a role or resource identifier.
26
+ #
27
+ # @param [String, Array, #roleid, #resourceid] obj the value to cast
28
+ # @param [Symbol] kind must be either `:roleid` or `:resourceid`
25
29
  def cast(obj, kind)
26
30
  case kind
27
31
  when :roleid, :resourceid
@@ -21,6 +21,11 @@
21
21
  module Conjur
22
22
  class API
23
23
  class << self
24
+ # @api private
25
+ #
26
+ # Host for the core service. We don't really use this anymore.
27
+ #
28
+ # @return [String] the core asset host
24
29
  def core_asset_host
25
30
  ::Conjur::Core::API.host
26
31
  end
@@ -30,14 +35,29 @@ module Conjur
30
35
  module Core
31
36
  class API < Conjur::API
32
37
  class << self
38
+ # @api private
39
+ # @deprecated
40
+ # The host for the Conjur directory service
41
+ # @return [String] the host.
33
42
  def host
34
43
  Conjur.configuration.core_url
35
44
  end
36
-
45
+
46
+ # Returns the account as determined by the conjur server.
47
+ #
48
+ # You should generally provide the account with {Conjur::Configuration#account}, but this method
49
+ # can determine it by asking the server.
50
+ #
51
+ # You do not need any credentials to call this method.
37
52
  def conjur_account
38
53
  info['account'] or raise "No account field in #{info.inspect}"
39
54
  end
40
-
55
+
56
+ # @api private
57
+ #
58
+ # Used to fetch an `info` hash from the server.
59
+ #
60
+ # @return [Hash] a hash containing an `'account'` field that specifies the current Conjur account.
41
61
  def info
42
62
  @info ||= JSON.parse RestClient::Resource.new(Conjur::Core::API.host)['info'].get
43
63
  end
data/lib/conjur/deputy.rb CHANGED
@@ -19,6 +19,14 @@
19
19
  # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
20
  #
21
21
  module Conjur
22
+ # A Deputy is an actor, typically representing a service. It is given a login and
23
+ # an api key, just like {Conjur::Host}s and {Conjur::User}s, and can perform various
24
+ # actions.
25
+ #
26
+ # You should not create instances of this class directly. Instead, you can get a {Conjur::Deputy}
27
+ # instance with {Conjur::API#deputy} or {Conjur::API#create_deputy}.
28
+ #
29
+ # The deputies api is stable, but is primarily used internally.
22
30
  class Deputy < RestClient::Resource
23
31
  include Exists
24
32
  include HasId
@@ -26,11 +34,20 @@ module Conjur
26
34
  include HasAttributes
27
35
  include ActsAsUser
28
36
  include ActsAsResource
29
-
37
+
38
+ # Login for the deputy. Of the form "deputy/<deputy-id>".
39
+ #
40
+ # @return [String] the login.
30
41
  def login
31
42
  [ self.class.name.split('::')[-1].downcase, id ].join('/')
32
43
  end
33
-
44
+
45
+ # API Key that can be used to login as the deputy.
46
+ #
47
+ # This is only available if the {Conjur::Deputy} was returned
48
+ # by {Conjur::API#create_deputy}.
49
+ #
50
+ # @return [String] the api key.
34
51
  def api_key
35
52
  self.attributes['api_key']
36
53
  end
data/lib/conjur/env.rb CHANGED
@@ -21,18 +21,33 @@
21
21
  module Conjur
22
22
  extend self
23
23
 
24
+ # @deprecated
25
+ # @api private
26
+ # This method delegates to {Conjur::Configuration#service_base_port}
27
+ #
28
+ # @return [Integer] the service base port
24
29
  def service_base_port
25
30
  Conjur.configuration.service_base_port
26
31
  end
27
-
32
+
33
+ # This method delegates to {Conjur::Configuration#account}
34
+ #
35
+ # @return [String] the value of `Conjur.configuration.account`
28
36
  def account
29
37
  Conjur.configuration.account
30
38
  end
31
-
39
+
40
+ # This method delegates to {Conjur::Configuration#env}
41
+ # @return [String] the value of `Conjur.configuration.env`
32
42
  def env
33
43
  Conjur.configuration.env
34
44
  end
35
-
45
+
46
+ # @api private
47
+ # @deprecated
48
+ # This method delegates to {Conjur::Configuration#stack}
49
+ #
50
+ # @return [String] the value of `Conjur.configuration.stack`
36
51
  def stack
37
52
  Conjur.configuration.stack
38
53
  end
data/lib/conjur/escape.rb CHANGED
@@ -19,21 +19,56 @@
19
19
  # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
20
  #
21
21
  module Conjur
22
+
23
+ # Provides helpers for escaping url components.
24
+ #
25
+ # The helpers are added as both class and isntance methods.
22
26
  module Escape
23
27
  module ClassMethods
28
+ # URL escape the entire string. This is essentially the same as calling `CGI.escape str`.
29
+ #
30
+ # @example
31
+ # fully_escape 'foo/bar@baz'
32
+ # # => "foo%2Fbar%40baz"
33
+ #
34
+ # @param [String] str the string to escape
35
+ # @return [String] the escaped string
24
36
  def fully_escape(str)
25
37
  require 'cgi'
26
38
  CGI.escape(str.to_s)
27
39
  end
28
-
40
+
41
+ # Escape a URI path component.
42
+ #
43
+ # This method simply calls {Conjur::Escape::ClassMethods#path_or_query_escape}.
44
+ #
45
+ # @param [String] str the string to escape
46
+ # @return [String] the escaped string
47
+ # @see Conjur::Escape::ClassMethods#path_or_query_escape
29
48
  def path_escape(str)
30
49
  path_or_query_escape str
31
50
  end
32
51
 
52
+ # Escape a URI query value.
53
+ #
54
+ # This method simply calls {Conjur::Escape::ClassMethods#path_or_query_escape}.
55
+ #
56
+ # @param [String] str the string to escape
57
+ # @return [String] the escaped string
58
+ # @see Conjur::Escape::ClassMethods#path_or_query_escape
33
59
  def query_escape(str)
34
60
  path_or_query_escape str
35
61
  end
36
-
62
+
63
+ # Escape a path or query value.
64
+ #
65
+ # This method is *similar* to `URI.escape`, but it has several important differences:
66
+ # * If a falsey value is given, the string `"false"` is returned.
67
+ # * If the value given responds to `#id`, the value returned by `str.id` is escaped instead.
68
+ # * The value is escaped without modifying `':'` or `'/'`.
69
+ #
70
+ # @param [String, FalseClass, NilClass, #id] str the value to escape
71
+ # @return [String] the value escaped as described
37
72
  def path_or_query_escape(str)
38
73
  return "false" unless str
39
74
  str = str.id if str.respond_to?(:id)
@@ -43,19 +78,45 @@ module Conjur
43
78
  URI.escape(str.to_s, Regexp.new("[^#{pattern}]"))
44
79
  end
45
80
  end
46
-
81
+
82
+ # @api private
83
+ # :nodoc:
47
84
  def self.included(base)
48
85
  base.extend ClassMethods
49
86
  end
50
-
87
+
88
+ # URL escape the entire string. This is essentially the same as calling `CGI.escape str`.
89
+ #
90
+ # @example
91
+ # fully_escape 'foo/bar@baz'
92
+ # # => "foo%2Fbar%40baz"
93
+ #
94
+ # @param [String] str the string to escape
95
+ # @return [String] the escaped string
96
+ # @see Conjur::Escape::ClassMethods#fully_escape
51
97
  def fully_escape(str)
52
98
  self.class.fully_escape str
53
99
  end
54
100
 
101
+ # Escape a URI path component.
102
+ #
103
+ # This method simply calls {Conjur::Escape::ClassMethods#path_or_query_escape}.
104
+ #
105
+ # @param [String] str the string to escape
106
+ # @return [String] the escaped string
107
+ # @see Conjur::Escape::ClassMethods#path_or_query_escape
55
108
  def path_escape(str)
56
109
  self.class.path_escape str
57
110
  end
58
111
 
112
+
113
+ # Escape a URI query value.
114
+ #
115
+ # This method simply calls {Conjur::Escape::ClassMethods#path_or_query_escape}.
116
+ #
117
+ # @param [String] str the string to escape
118
+ # @return [String] the escaped string
119
+ # @see Conjur::Escape::ClassMethods#path_or_query_escape
59
120
  def query_escape(str)
60
121
  self.class.query_escape str
61
122
  end
@@ -1,7 +1,13 @@
1
1
  module Conjur
2
+ # @api private
2
3
  # An EventSource instance is used to parse a stream in the format given by
3
4
  # the Server Sent Events standard: http://www.whatwg.org/specs/web-apps/current-work/#server-sent-events
5
+ #
6
+ # This class is used internally by the audit methods in follow mode.
7
+ #
4
8
  class EventSource
9
+ # @api private
10
+ # Representation of a SSE event
5
11
  class Event < Struct.new(:data, :name, :id);
6
12
  end
7
13
 
@@ -20,6 +26,8 @@ module Conjur
20
26
  attr_accessor :json
21
27
  alias json? json
22
28
 
29
+ # @api private
30
+ # Create an EventSource
23
31
  def initialize
24
32
  @json = true
25
33
  @on = {}
@@ -27,9 +35,11 @@ module Conjur
27
35
  @buffer = ""
28
36
  end
29
37
 
30
- # Feed a chunk of data to the EventSource and dispatch any fully receieved
38
+ # @api private
39
+ # Feed a chunk of data to the EventSource and dispatch any fully received
31
40
  # events.
32
41
  # @param [String] chunk the data to parse
42
+ # @return [void]
33
43
  def feed chunk
34
44
  @buffer << chunk
35
45
 
@@ -38,7 +48,10 @@ module Conjur
38
48
  end
39
49
  end
40
50
 
41
- # Adds a listener for :name:
51
+ # Add a block to be called when events with an `'event'` field of `name` are received.
52
+ #
53
+ # @param [String, Symbol] name the name to listen for
54
+ # @yieldparam [Conjur::EventSource::Event] the event
42
55
  def on name, &block
43
56
  (@on[name.to_sym] ||= []) << block
44
57
  end
data/lib/conjur/graph.rb CHANGED
@@ -19,15 +19,30 @@
19
19
  # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
20
  #
21
21
  module Conjur
22
+
23
+ # A Graph represents a directed graph of roles.
24
+ #
25
+ # An instance of this class is returned by {Conjur::API#role_graph}.
26
+ #
27
+ # @example Graphs act like arrays of edges
28
+ # graph.each do |edge|
29
+ # puts "#{edge.parent} -> #{edge.child}"
30
+ # end
31
+ # # role1 -> role2
32
+ # # role2 -> role3
33
+ #
22
34
  class Graph
23
35
 
24
36
  include Enumerable
25
37
 
26
- # @!attribute r edges
27
- # @return [Array<Conjur::Graph::Edge>] the edges of this graph
38
+ # Returns an array containing the directed edges of the graph.
39
+ #
40
+ # @return [Array<Conjur::Graph::Edge>] the edges of this graph
28
41
  attr_reader :edges
29
42
 
30
43
  # @api private
44
+ #
45
+ # @param val [String, Hash, Array, Graph] Data from which to initialize the instance
31
46
  def initialize val
32
47
  @edges = case val
33
48
  when String then JSON.parse(val)['graph']
@@ -41,8 +56,9 @@ module Conjur
41
56
  end
42
57
 
43
58
  # Enumerates the edges of this graph.
44
- # @yieldparam [Conjur::Graph::Edge] each edge of the graph
45
- # @return edge [Conjur::Graph] this graph
59
+ #
60
+ # @yieldparam [Conjur::Graph::Edge] edge each edge of the graph
61
+ # @return [Conjur::Graph] this graph
46
62
  def each_edge
47
63
  return enum_for(__method__) unless block_given?
48
64
  edges.each{|e| yield e}
@@ -52,28 +68,59 @@ module Conjur
52
68
  alias each each_edge
53
69
 
54
70
  # Enumerates the vertices (roles) of this graph
55
- # @yieldparam vertex [Conjur::Role] each vertex in this graph
71
+ # @yieldparam [Conjur::Role] vertex each vertex in this graph
56
72
  # @return [Conjur::Graph] this graph
57
73
  def each_vertex
58
74
  return enum_for(__method__) unless block_given?
59
75
  vertices.each{|v| yield v}
60
76
  end
61
77
 
62
-
78
+ # Serialize the graph as JSON
79
+ # @param [Boolean] short when true, the graph is serialized as an array of arrays instead of an array of hashes.
80
+ # @return [String] the JSON serialized graph.
81
+ # @see #as_json
82
+ #
63
83
  def to_json short = false
64
84
  as_json(short).to_json
65
85
  end
66
86
 
87
+ # Convert the graph to a JSON serializable data structure. The value returned by this method can have two
88
+ # forms: An array of arrays when `short` is `true`, or hash like
89
+ # `{ 'graph' => [ {'parent' => 'roleid', 'child' => 'roleid'} ]}` otherwise.
90
+ #
91
+ # @example Graph formats
92
+ # graph = api.role_graph 'conjur:group:pubkeys-1.0/key-managers'
93
+ #
94
+ # # Short format
95
+ # graph.as_json true
96
+ # # => [
97
+ # # ["conjur:group:pubkeys-1.0/key-managers", "conjur:group:pubkeys-1.0/admin"],
98
+ # # ["conjur:group:pubkeys-1.0/admin", "conjur:user:admin"]
99
+ # # ]
100
+ #
101
+ # # Default format (you can omit the false parameter in this case)
102
+ # graph.as_json false
103
+ # # => {
104
+ # # "graph" => [
105
+ # # {"parent"=>"conjur:group:pubkeys-1.0/key-managers", "child"=>"conjur:group:pubkeys-1.0/admin"},
106
+ # # {"parent"=>"conjur:group:pubkeys-1.0/admin", "child"=>"conjur:user:admin"}
107
+ # # ]
108
+ # #}
109
+ #
110
+ # @param [Boolean] short whether to use short of default format
111
+ # @return [Hash, Array] JSON serializable representation of the graph
67
112
  def as_json short = false
68
113
  edges = self.edges.map{|e| e.as_json(short)}
69
114
  short ? edges : {'graph' => edges}
70
115
  end
71
116
 
72
- # @param [String, NilClass] name to assign to the graph. Usually this can be omitted unless you
73
- # are writing multiple graphs to a single file. Must be in the ID format specified by
74
- # http://www.graphviz.org/content/dot-language
117
+ # Returns a string formatted for use by the {http://www.graphviz.org/ graphviz dot} tool.
118
+ #
119
+ # @param [String, NilClass] name An identifier to assign to the graph. This can be omitted unless you
120
+ # are writing multiple graphs to a single file. This must be in the ID format specified by
121
+ # http://www.graphviz.org/content/dot-language.
75
122
  #
76
- # @return [String] the dot format (used by graphvis, among others) representation of this graph.
123
+ # @return [String] the dot format (used by graphviz, among others) representation of this graph.
77
124
  def to_dot name = nil
78
125
  dot = "digraph #{name || ''} {"
79
126
  vertices.each do |v|
@@ -84,7 +131,9 @@ module Conjur
84
131
  end
85
132
  dot << "\n}"
86
133
  end
87
-
134
+
135
+ # Return the vertices (roles) of the graph as an array.
136
+ # @return [Array<Conjur::Role>] the vertices/roles
88
137
  def vertices
89
138
  @vertices ||= edges.inject([]) {|a, pair| a.concat pair.to_a }.uniq
90
139
  end
@@ -148,41 +197,83 @@ module Conjur
148
197
  "#{parent_id} -> #{child_id}"
149
198
  end
150
199
 
151
- # an edge consisting of a parent & child, both of which are Conjur::Role instances
200
+ # Represents a directed Edge between a parent role and a child role.
201
+ #
202
+ # In this context, the parent role is a *member of* the child role. For example,
203
+ # the `admin` role is a parent of every role, either directly or indirectly, because
204
+ # it is added as a member to all roles it creates.
152
205
  class Edge
206
+
207
+ # Return the parent of this edge. The {#parent} role *is a member of* the {#child} role.
208
+ # @return [Conjur::Role] the parent role
153
209
  attr_reader :parent
210
+
211
+ # Return the child of this edge. The {#parent} role *is a member of* the {#child} role.
212
+ # @return [Conjur::Role] the child role
154
213
  attr_reader :child
155
214
 
215
+ # Create a directed edge with a parent and child
216
+ #
217
+ # @param [Conjur::Role] parent the parent or source of this edge
218
+ # @param [Conjur::Role] child the child or destination of this edge
156
219
  def initialize parent, child
157
220
  @parent = parent
158
221
  @child = child
159
222
  end
160
223
 
224
+ # Serialize this edge as JSON.
225
+ #
226
+ # @see #as_json
227
+ # @param [Boolean] short when true, serialize the edge as an Array instead of a Hash
228
+ # @return [String] the JSON serialized edge
161
229
  def to_json short = false
162
230
  as_json(short).to_json
163
231
  end
164
232
 
233
+ # Return a value suitable for JSON serialization.
234
+ #
235
+ # The `short` parameter determines whether to return a `["parent", "child"]` Array
236
+ # or a Hash like `{"parent" => "parent-role", "child" => "child-role"}`.
237
+ #
238
+ # @param [Boolean] short return an Array when true, otherwise return a Hash.
239
+ # @return [Array, Hash] value suitable for JSON serialization
165
240
  def as_json short = false
166
241
  short ? to_a : to_h
167
242
  end
168
243
 
244
+ # Return this edge as a Hash like {"parent" => "...", "child" => "..."}.
245
+ #
246
+ # Note that the keys in the hash are strings.
247
+ #
248
+ # @return [Hash] a Hash representing this edge
169
249
  def to_h
170
250
  # return string keys to make testing less brittle
171
251
  {'parent' => @parent, 'child' => @child}
172
252
  end
173
253
 
254
+ # Return this edge as an Array like ["parent", "child"]
255
+ #
256
+ # @return [Array<String>] the edge as an Array
174
257
  def to_a
175
258
  [@parent, @child]
176
259
  end
177
260
 
261
+ # @api private
262
+ # :nodoc:
178
263
  def to_s
179
264
  "<Edge #{parent.id} --> #{child.id}>"
180
265
  end
181
266
 
267
+ # Support using edges as hash keys
268
+ # @api private
269
+ # :nodoc:
182
270
  def hash
183
271
  @hash ||= to_a.map(&:to_s).hash
184
272
  end
185
273
 
274
+ # Support using edges as hash keys and equality testing
275
+ # @api private
276
+ # :nodoc:
186
277
  def == other
187
278
  other.kind_of?(self.class) and other.parent == parent and other.child == child
188
279
  end