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,18 @@
1
+ build_number
2
+ *.gem
3
+ *.rbc
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
@@ -0,0 +1,18 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <projectDescription>
3
+ <name>conjur-api</name>
4
+ <comment></comment>
5
+ <projects>
6
+ </projects>
7
+ <buildSpec>
8
+ <buildCommand>
9
+ <name>com.aptana.ide.core.unifiedBuilder</name>
10
+ <arguments>
11
+ </arguments>
12
+ </buildCommand>
13
+ </buildSpec>
14
+ <natures>
15
+ <nature>com.aptana.ruby.core.rubynature</nature>
16
+ <nature>com.aptana.projects.webnature</nature>
17
+ </natures>
18
+ </projectDescription>
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format Fuubar
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.9.3@conjur-api-ruby --create
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in conjur-api.gemspec
4
+ gemspec
5
+
6
+ gem 'slosilo', :git => 'https://github.com/inscitiv/slosilo.git'
7
+
8
+ group :test do
9
+ gem 'fuubar'
10
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Rafał Rzepecki
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,29 @@
1
+ # Conjur::API
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'conjur-api'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install conjur-api
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ begin
5
+ require 'rspec/core/rake_task'
6
+ RSpec::Core::RakeTask.new(:spec)
7
+ rescue LoadError
8
+ $stderr.puts "RSpec Rake tasks not available in environment #{ENV['RACK_ENV']}"
9
+ end
10
+
11
+ task :jenkins do
12
+ if ENV['BUILD_NUMBER']
13
+ File.write('build_number', ENV['BUILD_NUMBER'])
14
+ end
15
+ require 'ci/reporter/rake/rspec'
16
+ Rake::Task["ci:setup:rspec"].invoke
17
+ Rake::Task["spec"].invoke
18
+ end
19
+
20
+ task default: :spec
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/conjur-api/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Rafa\305\202 Rzepecki","Kevin Gilpin"]
6
+ gem.email = ["divided.mind@gmail.com","kevin.gilpin@inscitiv.com"]
7
+ gem.description = %q{Conjur API}
8
+ gem.summary = %q{Conjur API}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\) + Dir['build_number']
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "conjur-api"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Conjur::API::VERSION
17
+
18
+ gem.add_runtime_dependency 'rest-client'
19
+ gem.add_runtime_dependency 'slosilo'
20
+ gem.add_runtime_dependency 'activesupport'
21
+
22
+ gem.add_development_dependency 'rake'
23
+ gem.add_development_dependency 'spork'
24
+ gem.add_development_dependency 'rspec'
25
+ gem.add_development_dependency 'vcr'
26
+ gem.add_development_dependency 'webmock'
27
+ gem.add_development_dependency 'ci_reporter'
28
+ end
@@ -0,0 +1,26 @@
1
+ Feature: Server enrollment
2
+
3
+ Background:
4
+ When I login with my username and password
5
+ And I receive an API key
6
+
7
+ Scenario: Enroll this server
8
+ When I enroll a server
9
+ Then the request succeeds
10
+ Then I receive an enrollment key
11
+
12
+ Scenario: The server is granted no other roles by default
13
+ Given I enroll a server
14
+ And I switch to the server role
15
+ When I list my roles
16
+ Then the result contains 1 item
17
+
18
+ Scenario: The server can be granted other roles
19
+ Given I enroll a server
20
+ And I create a role
21
+ And I grant the role to the server
22
+ And I switch to the server role
23
+ And I list my roles
24
+ Then the result contains 2 items
25
+
26
+
@@ -0,0 +1,13 @@
1
+ Feature: Login
2
+
3
+ Scenario: Login with my username and password
4
+ When I login with my username and password
5
+ Then the request succeeds
6
+ And I receive an API key
7
+
8
+ Scenario: Login with my username and password
9
+ When I login with my username and invalid password
10
+ Then the request fails with error 401
11
+
12
+
13
+
@@ -0,0 +1,16 @@
1
+ Feature: Ping
2
+
3
+ Background:
4
+ Given I login with my username and password
5
+ And I receive an API key
6
+ And I enroll a server
7
+ And I switch to the server role
8
+
9
+ Scenario: Ping using the server enrollment key
10
+ When I ping
11
+ Then the request succeeds
12
+
13
+ Scenario: Server credentials do not work from a different host
14
+ Given I force the request IP address to 127.0.0.1
15
+ When I ping
16
+ Then the request fails with error 401
@@ -0,0 +1,9 @@
1
+ Feature: Ping
2
+
3
+ Background:
4
+ When I login with my username and password
5
+ And I receive an API key
6
+
7
+ Scenario: Ping using an API key
8
+ When I ping
9
+ Then the request succeeds
@@ -0,0 +1,5 @@
1
+ module Conjur
2
+ class API
3
+ VERSION = "2.0.0"
4
+ end
5
+ end
@@ -0,0 +1,21 @@
1
+ module Conjur
2
+ module ActsAsResource
3
+ def resource
4
+ require 'conjur/resource'
5
+ Conjur::Resource.new("#{Conjur::Authz::API.host}/#{path_escape resource_kind}/#{path_escape resource_id}", self.options)
6
+ end
7
+
8
+ def resource_kind
9
+ self.class.name.split("::")[1..-1].join('-').downcase
10
+ end
11
+
12
+ def resource_id
13
+ id
14
+ end
15
+
16
+ def delete
17
+ resource.delete
18
+ super
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,8 @@
1
+ module Conjur
2
+ module ActsAsRole
3
+ def role
4
+ require 'conjur/role'
5
+ Conjur::Role.new("#{Conjur::Authz::API.host}/roles/#{path_escape roleid}", self.options)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,13 @@
1
+ module Conjur
2
+ module ActsAsUser
3
+ def self.included(base)
4
+ base.instance_eval do
5
+ include ActsAsRole
6
+ end
7
+ end
8
+
9
+ def roleid
10
+ id
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,22 @@
1
+ require 'conjur/env'
2
+ require 'conjur/base'
3
+ require 'conjur/acts_as_resource'
4
+ require 'conjur/acts_as_role'
5
+ require 'conjur/acts_as_user'
6
+ require 'conjur/log_source'
7
+ require 'conjur/has_attributes'
8
+ require 'conjur/has_identifier'
9
+ require 'conjur/has_id'
10
+ require 'conjur/das-api'
11
+ require 'conjur/authn-api'
12
+ require 'conjur/authz-api'
13
+ require 'conjur/core-api'
14
+
15
+ class RestClient::Resource
16
+ include Conjur::Escape
17
+ include Conjur::LogSource
18
+
19
+ def username
20
+ options[:user] || options[:username]
21
+ end
22
+ end
@@ -0,0 +1,66 @@
1
+ require 'conjur/user'
2
+
3
+ # Fails for the CLI client because it has no slosilo key
4
+ #require 'rest-client'
5
+
6
+ #RestClient.add_before_execution_proc do |req, params|
7
+ # require 'slosilo'
8
+ # req.extend Slosilo::HTTPRequest
9
+ # req.keyname = :authn
10
+ #end
11
+
12
+ module Conjur
13
+ class API
14
+ class << self
15
+ # Perform login by Basic authentication.
16
+ def login username, password
17
+ if Conjur.log
18
+ Conjur.log << "Logging in #{username} via Basic authentication\n"
19
+ end
20
+ RestClient::Resource.new(Conjur::Authn::API.host, user: username, password: password)['/users/login'].get
21
+ end
22
+
23
+ # Perform login by CAS authentication.
24
+ def login_cas username, password, cas_api_url
25
+ if Conjur.log
26
+ Conjur.log << "Logging in #{username} via CAS authentication\n"
27
+ end
28
+ require 'cas_rest_client'
29
+ client = CasRestClient.new(:username => username, :password => password, :uri => [ cas_api_url, 'v1', 'tickets' ].join('/'), :use_cookies => false)
30
+ client.get("#{Conjur::Authn::API.host}/users/login").body
31
+ end
32
+
33
+ def authenticate username, password
34
+ if Conjur.log
35
+ Conjur.log << "Authenticating #{username}\n"
36
+ end
37
+ JSON::parse(RestClient::Resource.new(Conjur::Authn::API.host)["/users/#{path_escape username}/authenticate"].post password, content_type: 'text/plain').tap do |token|
38
+ raise InvalidToken.new unless token_valid?(token)
39
+ end
40
+ end
41
+
42
+ def token_valid? token
43
+ require 'slosilo'
44
+ key = Slosilo[:authn]
45
+ if key
46
+ key.token_valid? token
47
+ else
48
+ raise KeyError, "authn key not found in Slosilo keystore"
49
+ end
50
+ end
51
+ end
52
+
53
+ # Options:
54
+ # +password+
55
+ #
56
+ # Response:
57
+ # +login+
58
+ # +api_key+
59
+ def create_authn_user login, options = {}
60
+ log do |logger|
61
+ logger << "Creating authn user #{login}"
62
+ end
63
+ JSON.parse RestClient::Resource.new(Conjur::Authn::API.host, credentials)['/users'].post(options.merge(login: login))
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,33 @@
1
+
2
+ module Conjur
3
+ class API
4
+ class << self
5
+ def data_access_service_url(account, path = nil, params = {})
6
+ provider = 'inscitiv'
7
+ base_url = if path.nil? || path.empty?
8
+ "#{Conjur::DAS::API.host}/data/#{account}/#{provider}"
9
+ else
10
+ path = path.split('/').collect do |p|
11
+ # Best possible answer I could find
12
+ # http://stackoverflow.com/questions/2834034/how-do-i-raw-url-encode-decode-in-javascript-and-ruby-to-get-the-same-values-in
13
+ URI.escape(p, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
14
+ end.join('/')
15
+ "#{Conjur::DAS::API.host}/data/#{account}/#{provider}/#{path}"
16
+ end
17
+ if params.nil? || params.empty?
18
+ base_url
19
+ else
20
+ query_string = params.map do |name,values|
21
+ values = [ values ] unless values.is_a?(Array)
22
+ values.map do |value|
23
+ name = URI.escape(name, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
24
+ value = URI.escape(value || "", Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
25
+ "#{name}=#{value}"
26
+ end
27
+ end.flatten.join("&")
28
+ "#{base_url}?#{query_string}"
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,18 @@
1
+ require 'conjur/group'
2
+
3
+ module Conjur
4
+ class API
5
+ def create_group(id, options = {})
6
+ log do |logger|
7
+ logger << "Creating group "
8
+ logger << id
9
+ end
10
+ resp = RestClient::Resource.new(Conjur::Core::API.host, credentials)['/groups'].post(options.merge(id: id))
11
+ Group.new(resp.headers[:location], credentials)
12
+ end
13
+
14
+ def group id
15
+ Group.new(Conjur::Core::API.host)["/groups/#{path_escape id}"]
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,37 @@
1
+ require 'conjur/host'
2
+
3
+ module Conjur
4
+ class API
5
+ def create_host options
6
+ log do |logger|
7
+ logger << "Creating host"
8
+ end
9
+ resp = JSON.parse RestClient::Resource.new("#{Conjur::Core::API.host}/hosts", credentials).post(options)
10
+ host(resp['id']).tap do |h|
11
+ log do |logger|
12
+ logger << "Created host #{h.id}"
13
+ end
14
+ h.attributes = resp
15
+ end
16
+ end
17
+
18
+ class << self
19
+ def enroll_host(url)
20
+ if Conjur.log
21
+ logger << "Enrolling host with URL #{url}"
22
+ end
23
+ require 'uri'
24
+ url = URI.parse(url) if url.is_a?(String)
25
+ response = Net::HTTP.get_response url
26
+ raise "Host enrollment failed with status #{response.code} : #{response.body}" unless response.code.to_i == 200
27
+ mime_type = response['Content-Type']
28
+ body = response.body
29
+ [ mime_type, body ]
30
+ end
31
+ end
32
+
33
+ def host id
34
+ Host.new("#{Conjur::Core::API.host}/hosts/#{path_escape id}", credentials)
35
+ end
36
+ end
37
+ end