conjur-api 4.19.1 → 4.20.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.
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (C) 2013 Conjur Inc
2
+ # Copyright (C) 2013-2015 Conjur Inc
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy of
5
5
  # this software and associated documentation files (the "Software"), to deal in
@@ -19,6 +19,7 @@
19
19
  # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
20
  #
21
21
  require 'conjur/user'
22
+ require 'conjur/cidr'
22
23
 
23
24
  module Conjur
24
25
  class API
@@ -48,12 +49,16 @@ module Conjur
48
49
  # @param [String] login the login for the new user
49
50
  # @param [Hash] options options for user creation
50
51
  # @option options [String] :acting_as Qualified id of a role to perform the action as
52
+ # @option options [Array<String, IPAddr>] :cidr CIDR addresses of networks
53
+ # the new user will be allower to login from
51
54
  # @option options [String, Integer] :uidnumber UID number to assign to the new user. If not given, one will be generated.
52
55
  # @option options [String] :password when present, the user will be given a password in addition to a randomly
53
56
  # generated api key.
54
57
  # @return [Conjur::User] an object representing the new user
55
58
  # @raise [RestClient::Conflict] If the user already exists, or a user with the given uidnumber exists.
56
59
  def create_user(login, options = {})
60
+ options = options.merge \
61
+ cidr: [*options[:cidr]].map(&CIDR.method(:validate)).map(&:to_s) if options[:cidr]
57
62
  standard_create Conjur::Core::API.host, :user, nil, options.merge(login: login)
58
63
  end
59
64
 
@@ -105,6 +105,30 @@ module Conjur
105
105
  end
106
106
  end
107
107
 
108
+ # Fetch all visible variables that expire within the given
109
+ # interval (relative to the current time on the Conjur Server). If
110
+ # no interval is specifed, all variables that are set to expire
111
+ # will be returned.
112
+ #
113
+ # interval should either be a String containing an ISO8601
114
+ # duration, or it should implement #to_i to return a number of
115
+ # seconds.
116
+ #
117
+ # @example Use an ISO8601 duration to return variables expiring in the next month
118
+ # expirations = api.variable_expirations('P1M')
119
+ #
120
+ # @example Use ActiveSupport to return variables expiring in the next month
121
+ # require 'active_support/all'
122
+ # expirations = api.variable_expirations(1.month)
123
+
124
+ # param interval a String containing an ISO8601 duration , or a number of seconds
125
+ # return [Hash] variable expirations that occur within the interval
126
+ def variable_expirations(interval = nil)
127
+ duration = interval.try { |i| i.respond_to?(:to_str) ? i : "PT#{i.to_i}S" }
128
+ params = {}.tap { |p| p.merge!({:params => {:duration => duration }}) if duration }
129
+ JSON.parse(RestClient::Resource.new(Conjur::Core::API.host, self.credentials)['variables/expirations'].get(params).body)
130
+ end
131
+
108
132
  #@!endgroup
109
133
  end
110
134
  end
@@ -0,0 +1,71 @@
1
+ #
2
+ # Copyright (C) 2015 Conjur Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
5
+ # this software and associated documentation files (the "Software"), to deal in
6
+ # the Software without restriction, including without limitation the rights to
7
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8
+ # the Software, and to permit persons to whom the Software is furnished to do so,
9
+ # subject to the following conditions:
10
+ ##
11
+ # The above copyright notice and this permission notice shall be included in all
12
+ # copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ #
21
+
22
+ require 'ipaddr'
23
+
24
+ module Conjur
25
+ # Utility methods for CIDR network addresses
26
+ module CIDR
27
+ # Parse addr into an IPAddr if it's not one already, then extend it with CIDR
28
+ # module. This will force validation and will raise ArgumentError if invalid.
29
+ # @return [IPAddr] the address (extended with CIDR module)
30
+ def self.validate addr
31
+ addr = IPAddr.new addr unless addr.kind_of? IPAddr
32
+ addr.extend self
33
+ end
34
+
35
+ def self.extended addr
36
+ addr.prefixlen # validates
37
+ end
38
+
39
+ # Error raised when an address is not a valid CIDR network address
40
+ class InvalidCIDR < ArgumentError
41
+ end
42
+
43
+ attr_reader :mask_addr
44
+
45
+ # @return [String] the address as an "address/mask length" string
46
+ # @example
47
+ # IPAddr.new("192.0.2.0/255.255.255.0").extend(CIDR).to_s == "192.0.2.0/24"
48
+ def to_s
49
+ [super, prefixlen].join '/'
50
+ end
51
+
52
+ # @return [Fixnum] the length of the network mask prefix
53
+ def prefixlen
54
+ unless @prefixlen
55
+ return @prefixlen = 0 if (mask = mask_addr) == 0
56
+
57
+ @prefixlen = ipv4? ? 32 : 128
58
+
59
+ while (mask & 1) == 0
60
+ mask >>= 1
61
+ @prefixlen -= 1
62
+ end
63
+
64
+ if mask != ((1 << @prefixlen) - 1)
65
+ fail InvalidCIDR, "#{inspect} is not a valid CIDR network address"
66
+ end
67
+ end
68
+ return @prefixlen
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,4 @@
1
+ module Conjur
2
+ class FeatureNotAvailable < StandardError
3
+ end
4
+ end
@@ -0,0 +1,38 @@
1
+ #
2
+ # Copyright (C) 2014 Conjur Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
5
+ # this software and associated documentation files (the "Software"), to deal in
6
+ # the Software without restriction, including without limitation the rights to
7
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8
+ # the Software, and to permit persons to whom the Software is furnished to do so,
9
+ # subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in all
12
+ # copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ #
21
+ require 'conjur/api'
22
+ require 'conjur/configuration'
23
+
24
+ class Conjur::Configuration
25
+ add_option :host_factory_url do
26
+ account_service_url 'host_factories', 500
27
+ end
28
+ end
29
+
30
+ class Conjur::API
31
+ class << self
32
+ def host_factory_asset_host
33
+ Conjur.configuration.host_factory_url
34
+ end
35
+ end
36
+ end
37
+
38
+ require 'conjur/api/host_factories'
data/lib/conjur/host.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (C) 2013 Conjur Inc
2
+ # Copyright (C) 2013-2015 Conjur Inc
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy of
5
5
  # this software and associated documentation files (the "Software"), to deal in
@@ -34,5 +34,24 @@ module Conjur
34
34
  end
35
35
  self['enrollment_url'].head{|response, request, result| response }.headers[:location]
36
36
  end
37
+
38
+ # Assign new attributes to the host. Currently, this method only lets you change the
39
+ # `:cidr` attribute.
40
+ #
41
+ # ### Permissions
42
+ # You must have update permission on the hosts's resource or be the host to
43
+ # update CIDR restrictions.
44
+ #
45
+ # @note This feature requires Conjur server version 4.6 or later.
46
+ #
47
+ # @param [Hash] options attributes to change
48
+ # @option options [Array<String, IPAddr>] :cidr the network restrictions for this host
49
+ # @return [void]
50
+ # @raise [ArgumentError] if cidr isn't valid
51
+ def update options
52
+ if cidr = options[:cidr]
53
+ set_cidr_restrictions cidr
54
+ end
55
+ end
37
56
  end
38
- end
57
+ end
@@ -0,0 +1,75 @@
1
+ #
2
+ # Copyright (C) 2014 Conjur Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
5
+ # this software and associated documentation files (the "Software"), to deal in
6
+ # the Software without restriction, including without limitation the rights to
7
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8
+ # the Software, and to permit persons to whom the Software is furnished to do so,
9
+ # subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in all
12
+ # copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ #
21
+ require 'conjur/host_factory_token'
22
+
23
+ module Conjur
24
+ class HostFactory < RestClient::Resource
25
+ include ActsAsAsset
26
+
27
+ def roleid
28
+ attributes['roleid']
29
+ end
30
+
31
+ def role
32
+ Role.new(Conjur::Authz::API.host, self.options)[Conjur::API.parse_role_id(roleid).join('/')]
33
+ end
34
+
35
+ def deputy
36
+ Conjur::Deputy.new(Conjur::API.core_asset_host, options)["deputies/#{fully_escape id}"]
37
+ end
38
+
39
+ def deputy_api_key
40
+ attributes['deputy_api_key']
41
+ end
42
+
43
+ def create_token(expiration, options = {})
44
+ create_tokens(expiration, 1, options)[0]
45
+ end
46
+
47
+ def create_tokens(expiration, count, options = {})
48
+ parameters = options.merge({
49
+ expiration: expiration.iso8601,
50
+ count: count
51
+ })
52
+ response = RestClient::Resource.new(Conjur::API.host_factory_asset_host, self.options)[fully_escape id]["tokens"].post(parameters).body
53
+ JSON.parse(response).map do |attrs|
54
+ build_host_factory_token attrs
55
+ end
56
+ end
57
+
58
+ def tokens
59
+ # Tokens list is not returned by +show+ if the caller doesn't have permission
60
+ return nil unless self.attributes['tokens']
61
+
62
+ self.attributes['tokens'].collect do |attrs|
63
+ build_host_factory_token attrs
64
+ end
65
+ end
66
+
67
+ protected
68
+
69
+ def build_host_factory_token attrs
70
+ Conjur::HostFactoryToken.new(Conjur::API.host_factory_asset_host, self.options)["tokens"][attrs['token']].tap do |token|
71
+ token.attributes = attrs
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,63 @@
1
+ #
2
+ # Copyright (C) 2014 Conjur Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
5
+ # this software and associated documentation files (the "Software"), to deal in
6
+ # the Software without restriction, including without limitation the rights to
7
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8
+ # the Software, and to permit persons to whom the Software is furnished to do so,
9
+ # subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in all
12
+ # copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ #
21
+ module Conjur
22
+ class HostFactoryToken < RestClient::Resource
23
+ include HasAttributes
24
+
25
+ def to_json(options = {})
26
+ { token: token, expiration: expiration, cidr: cidr }
27
+ end
28
+
29
+ def token
30
+ self.url.split('/')[-1]
31
+ end
32
+
33
+ alias id token
34
+
35
+ def expiration
36
+ DateTime.iso8601(attributes['expiration'])
37
+ end
38
+
39
+ def host_factory
40
+ Conjur::HostFactory.new(Conjur::API.host_factory_asset_host, options)[fully_escape attributes['host_factory']['id']]
41
+ end
42
+
43
+ def cidr
44
+ attributes['cidr']
45
+ end
46
+
47
+ def revoke!
48
+ invalidate do
49
+ RestClient::Resource.new(self['revoke'].url, options).post
50
+ end
51
+ end
52
+
53
+ def save
54
+ raise "HostFactoryToken attributes are not updatable"
55
+ end
56
+
57
+ protected
58
+
59
+ def fetch
60
+ raise "HostFactoryToken attributes are not fetchable"
61
+ end
62
+ end
63
+ end
@@ -97,7 +97,7 @@ module Conjur
97
97
  # resource.permit 'execute', api.user('jon')
98
98
  # resource.permitted_roles 'execute' # => ['conjur:user:admin', 'conjur:user:jon']
99
99
  #
100
- # @param permission [String] the permission``
100
+ # @param permission [String] the permission
101
101
  # @param options [Hash, nil] extra options to pass to RestClient::Resource#get
102
102
  # @return [Array<String>] the ids of roles that have `permission` on this resource.
103
103
  def permitted_roles(permission, options = {})
data/lib/conjur/user.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (C) 2013 Conjur Inc
2
+ # Copyright (C) 2013-2015 Conjur Inc
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy of
5
5
  # this software and associated documentation files (the "Software"), to deal in
@@ -34,27 +34,35 @@ module Conjur
34
34
  # @return [String] the login for this user
35
35
  def login; id end
36
36
 
37
- # Assign new attributes to the user. Currently, this method only lets you change the
38
- # `:uidnumber` attribute.
37
+ # Assign new attributes to the user.
39
38
  #
40
39
  # If a user with the given `:uidnumber` already exists, this method will raise `RestClient::Forbidden`, with
41
40
  # the response body providing additional details if possible.
42
41
  #
43
42
  # ### Permissions
44
- # You must be a member of the user's role to call this method.
43
+ # You must be a member of the user's role to update the uidnumber.
44
+ # You must have update permission on the user's resource or be the user to
45
+ # update CIDR restrictions.
45
46
  #
46
- # @note This feature requires Conjur server version 4.3 or later.
47
+ # @note Updating `uidnumber` requires Conjur server version 4.3 or later.
48
+ # @note Updating `cidr` requires Conjur server version 4.6 or later.
47
49
  #
48
50
  # @param [Hash] options attributes to change
49
- # @option options [FixNum] :uidnumber the new uidnumber for this user. This option *must* be present.
51
+ # @option options [FixNum] :uidnumber the new uidnumber for this user.
52
+ # @option options [Array<String, IPAddr>] :cidr the network restrictions for this user. Requires Conjur server version 4.6 or later
50
53
  # @return [void]
51
54
  # @raise [RestClient::Conflict] if the uidnumber is already in use
52
- # @raise [ArgumentError] if uidnumber isn't a `Fixnum` or isn't present in `options`
55
+ # @raise [ArgumentError] if uidnumber or cidr aren't valid
53
56
  def update options
54
- # Currently the server raises a 400 Bad Request if uidnumber is missing, require it here
55
- raise ArgumentError "options[:uidnumber] is required" unless uidnumber = options[:uidnumber]
56
- raise ArgumentError, "options[:uidnumber] must be a Fixnum" unless uidnumber.kind_of?(Fixnum)
57
- self.put(options)
57
+ if uidnumber = options[:uidnumber]
58
+ # Currently the server raises a 400 Bad Request if uidnumber is missing, require it here
59
+ raise ArgumentError, "options[:uidnumber] must be a Fixnum" unless uidnumber.kind_of?(Fixnum)
60
+ self.put(options)
61
+ end
62
+
63
+ if cidr = options[:cidr]
64
+ set_cidr_restrictions cidr
65
+ end
58
66
  end
59
67
 
60
68
  # Get the user's uidnumber, which is used by LDAP and SSH login, among other things.
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (C) 2013 Conjur Inc
2
+ # Copyright (C) 2013-2016 Conjur Inc
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy of
5
5
  # this software and associated documentation files (the "Software"), to deal in
@@ -205,5 +205,28 @@ module Conjur
205
205
  url << "?version=#{version}" if version
206
206
  self[url].get.body
207
207
  end
208
+
209
+ # Set the variable to expire after the given interval. The
210
+ # interval can either be an ISO8601 duration or it can the number
211
+ # of seconds for which the variable should be valid. Once a
212
+ # variable has expired, its value will no longer be retrievable.
213
+ #
214
+ # You must have the **`'update'`** permission on a variable to call this method.
215
+ #
216
+ # @example Use an ISO8601 duration to set the expiration for a variable to tomorrow
217
+ # var = api.variable 'my-secret'
218
+ # var.expires_in "P1D"
219
+ #
220
+ # @example Use ActiveSupport to set the expiration for a variable to tomorrow
221
+ # require 'active_support/all'
222
+ # var = api.variable 'my-secret'
223
+ # var.expires_in 1.day
224
+ # @param interval a String containing an ISO8601 duration, otherwise the number of seconds before the variable xpires
225
+ # @return [Hash] description of the variable's expiration, including the (Conjur server) time when it expires
226
+ def expires_in interval
227
+ duration = interval.respond_to?(:to_str) ? interval : "PT#{interval.to_i}S"
228
+ JSON::parse(self['expiration'].post(duration: duration).body)
229
+ end
230
+
208
231
  end
209
- end
232
+ end