conjur-api 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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