conjur-api 2.0.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 (57) hide show
  1. data/.gitignore +18 -0
  2. data/.project +18 -0
  3. data/.rspec +2 -0
  4. data/.rvmrc +1 -0
  5. data/Gemfile +10 -0
  6. data/LICENSE +22 -0
  7. data/README.md +29 -0
  8. data/Rakefile +20 -0
  9. data/conjur-api.gemspec +28 -0
  10. data/features/enroll_server.feature +26 -0
  11. data/features/login.feature +13 -0
  12. data/features/ping_as_server.feature +16 -0
  13. data/features/ping_as_user.feature +9 -0
  14. data/lib/conjur-api/version.rb +5 -0
  15. data/lib/conjur/acts_as_resource.rb +21 -0
  16. data/lib/conjur/acts_as_role.rb +8 -0
  17. data/lib/conjur/acts_as_user.rb +13 -0
  18. data/lib/conjur/api.rb +22 -0
  19. data/lib/conjur/api/authn.rb +66 -0
  20. data/lib/conjur/api/das.rb +33 -0
  21. data/lib/conjur/api/groups.rb +18 -0
  22. data/lib/conjur/api/hosts.rb +37 -0
  23. data/lib/conjur/api/resources.rb +9 -0
  24. data/lib/conjur/api/roles.rb +18 -0
  25. data/lib/conjur/api/secrets.rb +23 -0
  26. data/lib/conjur/api/users.rb +23 -0
  27. data/lib/conjur/api/variables.rb +25 -0
  28. data/lib/conjur/authn-api.rb +22 -0
  29. data/lib/conjur/authz-api.rb +23 -0
  30. data/lib/conjur/base.rb +50 -0
  31. data/lib/conjur/core-api.rb +26 -0
  32. data/lib/conjur/das-api.rb +22 -0
  33. data/lib/conjur/env.rb +24 -0
  34. data/lib/conjur/escape.rb +31 -0
  35. data/lib/conjur/exists.rb +12 -0
  36. data/lib/conjur/group.rb +11 -0
  37. data/lib/conjur/has_attributes.rb +30 -0
  38. data/lib/conjur/has_id.rb +8 -0
  39. data/lib/conjur/has_identifier.rb +13 -0
  40. data/lib/conjur/host.rb +20 -0
  41. data/lib/conjur/log.rb +52 -0
  42. data/lib/conjur/log_source.rb +13 -0
  43. data/lib/conjur/resource.rb +81 -0
  44. data/lib/conjur/role.rb +52 -0
  45. data/lib/conjur/secret.rb +12 -0
  46. data/lib/conjur/user.rb +13 -0
  47. data/lib/conjur/variable.rb +27 -0
  48. data/spec/lib/api_spec.rb +98 -0
  49. data/spec/lib/das_spec.rb +33 -0
  50. data/spec/lib/resource_spec.rb +84 -0
  51. data/spec/lib/role_spec.rb +24 -0
  52. data/spec/lib/user_spec.rb +33 -0
  53. data/spec/spec_helper.rb +86 -0
  54. data/spec/vcr_cassettes/Conjur_Resource/_create/with_path-like_identifier.yml +87 -0
  55. data/spec/vcr_cassettes/Conjur_Resource/_create/with_un-encoded_path-like_identifier.yml +87 -0
  56. data/spec/vcr_cassettes/Conjur_Resource/_create/with_uuid_identifier.yml +87 -0
  57. metadata +266 -0
@@ -0,0 +1,9 @@
1
+ require 'conjur/resource'
2
+
3
+ module Conjur
4
+ class API
5
+ def resource kind, identifier
6
+ Resource.new("#{Conjur::Authz::API.host}/#{kind}/#{path_escape identifier}", credentials)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,18 @@
1
+ require 'conjur/role'
2
+
3
+ module Conjur
4
+ class API
5
+ def create_role(role, options = {})
6
+ log do |logger|
7
+ logger << "Creating role "
8
+ logger << role
9
+ end
10
+ RestClient::Resource.new(Conjur::Authz::API.host, credentials)["/roles/#{path_escape role}"].put(options)
11
+ Role.new(role, credentials)
12
+ end
13
+
14
+ def role identifier
15
+ Role.new("#{Conjur::Authz::API.host}/roles/#{path_escape identifier}", credentials)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,23 @@
1
+ require 'conjur/secret'
2
+
3
+ module Conjur
4
+ class API
5
+ def create_secret(value, options = {})
6
+ log do |logger|
7
+ logger << "Creating secret "
8
+ logger << value
9
+ end
10
+ resp = RestClient::Resource.new(Conjur::Core::API.host, credentials)['/secrets'].post(options.merge(value: value))
11
+ Secret.new(resp.headers[:location], credentials).tap do |secret|
12
+ log do |logger|
13
+ logger << "Created secret "
14
+ logger << secret.id
15
+ end
16
+ end
17
+ end
18
+
19
+ def secret id
20
+ Secret.new("#{Conjur::Core::API.host}/secrets/#{path_escape id}", credentials)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ require 'conjur/user'
2
+
3
+ module Conjur
4
+ class API
5
+ def create_user(login, options = {})
6
+ log do |logger|
7
+ logger << "Creating user "
8
+ logger << login
9
+ end
10
+ resp = JSON.parse RestClient::Resource.new(Conjur::Core::API.host, credentials)['/users'].post(options.merge(login: login))
11
+ user(resp['login']).tap do |u|
12
+ log do |logger|
13
+ logger << "Created user #{u.login}"
14
+ end
15
+ u.attributes = resp
16
+ end
17
+ end
18
+
19
+ def user login
20
+ User.new(Conjur::Core::API.host, credentials)["/users/#{path_escape login}"]
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,25 @@
1
+ require 'conjur/variable'
2
+
3
+ module Conjur
4
+ class API
5
+ def create_variable(mime_type, kind, options = {})
6
+ log do |logger|
7
+ logger << "Creating #{mime_type} variable #{kind}"
8
+ if options
9
+ logger << " with options #{options.inspect}"
10
+ end
11
+ end
12
+ resp = RestClient::Resource.new(Conjur::Core::API.host, credentials)['variables'].post(options.merge(mime_type: mime_type, kind: kind))
13
+ Variable.new(resp.headers[:location], credentials).tap do |variable|
14
+ log do |logger|
15
+ logger << "Created variable "
16
+ logger << variable.id
17
+ end
18
+ end
19
+ end
20
+
21
+ def variable id
22
+ Variable.new("#{Conjur::Core::API.host}/variables/#{path_escape id}", credentials)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,22 @@
1
+ module Conjur
2
+ module Authn
3
+ class API < Conjur::API
4
+ class << self
5
+ def host
6
+ ENV['CONJUR_AUTHN_URL'] || default_host
7
+ end
8
+
9
+ def default_host
10
+ case Conjur.env
11
+ when 'test', 'development'
12
+ "http://localhost:#{Conjur.service_base_port}"
13
+ else
14
+ "https://authn-#{Conjur.stack}-conjur.herokuapp.com"
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ require 'conjur/api/authn'
@@ -0,0 +1,23 @@
1
+ module Conjur
2
+ module Authz
3
+ class API < Conjur::API
4
+ class << self
5
+ def host
6
+ ENV['CONJUR_AUTHZ_URL'] || default_host
7
+ end
8
+
9
+ def default_host
10
+ case Conjur.env
11
+ when 'test', 'development'
12
+ "http://localhost:#{Conjur.service_base_port + 100}"
13
+ else
14
+ "https://authz-#{Conjur.stack}-conjur.herokuapp.com"
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ require 'conjur/api/roles'
23
+ require 'conjur/api/resources'
@@ -0,0 +1,50 @@
1
+ require 'rest-client'
2
+ require 'json'
3
+
4
+ require 'conjur/exists'
5
+ require 'conjur/has_attributes'
6
+ require 'conjur/escape'
7
+ require 'conjur/log'
8
+ require 'conjur/log_source'
9
+
10
+ module Conjur
11
+ class API
12
+ include Escape
13
+ include LogSource
14
+
15
+ class << self
16
+ def new_from_key(username, api_key)
17
+ self.new username, api_key, nil
18
+ end
19
+
20
+ def new_from_token(token)
21
+ self.new nil, nil, token
22
+ end
23
+ end
24
+
25
+ def initialize username, api_key, token
26
+ @username = username
27
+ @api_key = api_key
28
+ @token = token
29
+ raise "Expecting ( username and api_key ) or token" unless ( username && api_key ) || token
30
+ end
31
+
32
+ attr_reader :api_key, :username, :token
33
+
34
+ def username
35
+ @username || token['data']
36
+ end
37
+
38
+ def host
39
+ self.class.host
40
+ end
41
+
42
+ def credentials
43
+ if token
44
+ { headers: { authorization: "Token token=\"#{Base64.strict_encode64 token.to_json}\"" }, username: username }
45
+ else
46
+ { user: username, password: api_key }
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,26 @@
1
+ module Conjur
2
+ module Core
3
+ class API < Conjur::API
4
+ class << self
5
+ def host
6
+ ENV['CONJUR_CORE_URL'] || default_host
7
+ end
8
+
9
+ def default_host
10
+ case Conjur.env
11
+ when 'test', 'development'
12
+ "http://localhost:#{Conjur.service_base_port + 300}"
13
+ else
14
+ "https://core-#{Conjur.stack}-conjur.herokuapp.com"
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ require 'conjur/api/hosts'
23
+ require 'conjur/api/secrets'
24
+ require 'conjur/api/users'
25
+ require 'conjur/api/groups'
26
+ require 'conjur/api/variables'
@@ -0,0 +1,22 @@
1
+ module Conjur
2
+ module DAS
3
+ class API < Conjur::API
4
+ class << self
5
+ def host
6
+ ENV['CONJUR_DAS_URL'] || default_host
7
+ end
8
+
9
+ def default_host
10
+ case Conjur.env
11
+ when 'test', 'development'
12
+ "http://localhost:#{Conjur.service_base_port + 200}"
13
+ else
14
+ "https://das-#{Conjur.stack}-conjur.herokuapp.com"
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ require 'conjur/api/das'
@@ -0,0 +1,24 @@
1
+ module Conjur
2
+ extend self
3
+
4
+ def service_base_port
5
+ (ENV['CONJUR_SERVICE_BASE_PORT'] || 5000 ).to_i
6
+ end
7
+
8
+ def account
9
+ ENV['CONJUR_ACCOUNT'] or raise "No CONJUR_ACCOUNT defined"
10
+ end
11
+
12
+ def env
13
+ ENV['CONJUR_ENV'] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || "development"
14
+ end
15
+
16
+ def stack
17
+ ENV['CONJUR_STACK'] || case env
18
+ when "production"
19
+ "v2"
20
+ else
21
+ env
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,31 @@
1
+ module Conjur
2
+ module Escape
3
+ module ClassMethods
4
+ def path_escape(str)
5
+ return "false" unless str
6
+ str = str.id if str.respond_to?(:id)
7
+ require 'uri'
8
+ URI.escape(str.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
9
+ end
10
+
11
+ def query_escape(str)
12
+ return "false" unless str
13
+ str = str.id if str.respond_to?(:id)
14
+ require 'uri'
15
+ URI.escape(str.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
16
+ end
17
+ end
18
+
19
+ def self.included(base)
20
+ base.extend ClassMethods
21
+ end
22
+
23
+ def path_escape(str)
24
+ self.class.path_escape str
25
+ end
26
+
27
+ def query_escape(str)
28
+ self.class.query_escape str
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,12 @@
1
+ module Conjur
2
+ module Exists
3
+ def exists?(options = {})
4
+ begin
5
+ self.head(options)
6
+ true
7
+ rescue RestClient::ResourceNotFound
8
+ false
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ module Conjur
2
+ class Group < RestClient::Resource
3
+ include ActsAsResource
4
+ include ActsAsRole
5
+ include HasId
6
+
7
+ def roleid
8
+ "group:#{id}"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,30 @@
1
+ module Conjur
2
+ module HasAttributes
3
+ def attributes=(a); @attributes = a; end
4
+ def attributes
5
+ return @attributes if @attributes
6
+ fetch
7
+ end
8
+
9
+ def save
10
+ self.put(attributes.to_json)
11
+ end
12
+
13
+ # Reload the attributes. This action can be used to guarantee a current view of the entity in the case
14
+ # that it has been modified by an update method or by an external party.
15
+ def refresh
16
+ fetch
17
+ end
18
+
19
+ protected
20
+
21
+ def invalidate(&block)
22
+ yield
23
+ @attributes = nil
24
+ end
25
+
26
+ def fetch
27
+ @attributes = JSON.parse(get.body)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,8 @@
1
+ module Conjur
2
+ module HasId
3
+ def id
4
+ require 'uri'
5
+ URI.unescape URI.parse(self.url).path.split('/')[-1]
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,13 @@
1
+ module Conjur
2
+ module HasIdentifier
3
+ def self.included(base)
4
+ base.instance_eval do
5
+ include HasAttributes
6
+ end
7
+ end
8
+
9
+ def identifier
10
+ attributes['identifier']
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,20 @@
1
+ module Conjur
2
+ class Host < RestClient::Resource
3
+ include Exists
4
+ include HasId
5
+ include HasIdentifier
6
+ include HasAttributes
7
+ include ActsAsUser
8
+
9
+ def roleid
10
+ "host-#{id}"
11
+ end
12
+
13
+ def enrollment_url
14
+ log do |logger|
15
+ logger << "Fetching enrollment_url for #{id}"
16
+ end
17
+ self['enrollment_url'].head{|response, request, result| response }.headers[:location]
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,52 @@
1
+ # Logging mechanism borrowed from rest-client
2
+ module Conjur
3
+ # You can also configure logging by the environment variable CONJURAPI_LOG.
4
+ def self.log= log
5
+ @@log = create_log log
6
+ end
7
+
8
+ # Create a log that respond to << like a logger
9
+ # param can be 'stdout', 'stderr', a string (then we will log to that file) or a logger (then we return it)
10
+ def self.create_log param
11
+ if param
12
+ if param.is_a? String
13
+ if param == 'stdout'
14
+ stdout_logger = Class.new do
15
+ def << obj
16
+ STDOUT.write obj
17
+ end
18
+ end
19
+ stdout_logger.new
20
+ elsif param == 'stderr'
21
+ stderr_logger = Class.new do
22
+ def << obj
23
+ STDERR.write obj
24
+ end
25
+ end
26
+ stderr_logger.new
27
+ else
28
+ file_logger = Class.new do
29
+ attr_writer :target_file
30
+
31
+ def << obj
32
+ File.open(@target_file, 'a') { |f| f.write obj }
33
+ end
34
+ end
35
+ logger = file_logger.new
36
+ logger.target_file = param
37
+ logger
38
+ end
39
+ else
40
+ param
41
+ end
42
+ end
43
+ end
44
+
45
+ @@env_log = create_log ENV['CONJURAPI_LOG']
46
+
47
+ @@log = nil
48
+
49
+ def self.log # :nodoc:
50
+ @@env_log || @@log
51
+ end
52
+ end