duo-rest 0.0.1

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.
@@ -0,0 +1,18 @@
1
+ # See http://help.github.com/ignore-files/ for more about ignoring files.
2
+ #
3
+ # If you find yourself ignoring temporary files generated by your text editor
4
+ # or operating system, you probably want to add a global ignore instead:
5
+ # git config --global core.excludesfile ~/.gitignore_global
6
+
7
+ # Ignore bundler config
8
+ /.bundle
9
+
10
+ # Ignore the default SQLite database.
11
+ /db/*.sqlite3
12
+
13
+ # Ignore all logfiles and tempfiles.
14
+ /log/*.log
15
+ /tmp
16
+ duo_test_info.yml
17
+
18
+ */config/database.yml
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,24 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ duo-rest (0.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ coderay (1.0.7)
10
+ method_source (0.7.1)
11
+ pry (0.9.9.6)
12
+ coderay (~> 1.0.5)
13
+ method_source (~> 0.7.1)
14
+ slop (>= 2.4.4, < 3)
15
+ rake (0.9.2.2)
16
+ slop (2.4.4)
17
+
18
+ PLATFORMS
19
+ ruby
20
+
21
+ DEPENDENCIES
22
+ duo-rest!
23
+ pry
24
+ rake
@@ -0,0 +1,30 @@
1
+ duo-rest
2
+ ===========
3
+
4
+ This is a gem that provides access to the Duo Security Rest Api.
5
+
6
+ Methods
7
+ -------
8
+
9
+ 1. **ping**
10
+
11
+ tests the connection to duo security rest api
12
+
13
+ 2. **check**
14
+
15
+ checks your credentials for the correct keys
16
+
17
+ 3. **preauth**(username)
18
+
19
+ information to display to the user to decide which way they want to log in.
20
+
21
+ 4. **auth**(username, auth_method)
22
+
23
+ logging the user in.
24
+
25
+ *the only tested auth method right now is push*
26
+
27
+ More Info
28
+ ---------
29
+
30
+ For more info about the duo security process go [here](http://www.duosecurity.com/docs/duorest#process)
@@ -0,0 +1,10 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'test'
5
+ t.test_files = `git ls-files -- test/*`.split("\n")
6
+ t.verbose = true
7
+ end
8
+
9
+ desc "Run tests"
10
+ task :default => :test
@@ -0,0 +1,23 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+ require "duo-rest/version"
3
+ require "rubygems"
4
+ require "bundler/setup"
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'duo-rest'
8
+ s.version = DuoRest::VERSION
9
+ s.platform = Gem::Platform::RUBY
10
+ s.date = '2012-06-27'
11
+ s.summary = "Duo Security Rest Api"
12
+ s.description = "Gem interface for Duo security rest api"
13
+ s.authors = ["Kelly Mahan"]
14
+ s.email = 'kmahan@kmahan.com'
15
+ s.homepage = 'http://rubygems.org/gems/duo-rest'
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_development_dependency("pry")
22
+ s.add_development_dependency("rake")
23
+ end
@@ -0,0 +1,4 @@
1
+ hostname: "api-xxxxxxxxx.duosecurity.com"
2
+ integration_key: "1234"
3
+ secret_key: "asdfsdfsdfhgdfghfdhgdfg"
4
+ username: "test"
File without changes
@@ -0,0 +1,8 @@
1
+
2
+ module DuoRest
3
+
4
+ end
5
+
6
+
7
+ require 'duo-rest/version'
8
+ require 'duo-rest/connection'
@@ -0,0 +1,91 @@
1
+ require 'open-uri'
2
+ require 'net/http'
3
+ require 'net/https'
4
+ require "uri"
5
+ require 'json'
6
+ require 'base64'
7
+ require 'openssl'
8
+ require "cgi"
9
+
10
+ module DuoRest
11
+
12
+ class Connection
13
+
14
+ REST_VERSION = 'rest/v1'
15
+
16
+ attr_accessor :api_hostname, :response, :http, :user, :key
17
+
18
+ def initialize(api_hostname, user, key)
19
+ @key = key
20
+ @user = user
21
+ @api_hostname = api_hostname
22
+ @http = Net::HTTP.new("#{@api_hostname}", 443)
23
+ @http.use_ssl = true
24
+ end
25
+
26
+ def ping
27
+ url = "#{REST_VERSION}/ping"
28
+ get(url)
29
+ end
30
+
31
+ def check
32
+ url = "#{REST_VERSION}/check"
33
+ get(url)
34
+ end
35
+
36
+ def preauth(user)
37
+ url = "#{REST_VERSION}/preauth"
38
+ data = {user: user}
39
+ post(url, data)
40
+ end
41
+
42
+ def auth(user, factor_method, options = {})
43
+ ipaddress = options[:ipaddress] || ''
44
+ async = options[:async]
45
+ url = "#{REST_VERSION}/auth"
46
+ data = {auto: factor_method, factor: 'auto', ipaddr: ipaddress, user: user}
47
+ data.merge({async: "1"}) if async
48
+ post(url, data)
49
+ end
50
+
51
+ private
52
+
53
+ def get(url)
54
+ uri = URI("https://#{@api_hostname}/#{url}")
55
+ req = Net::HTTP::Get.new(uri.request_uri)
56
+ req.basic_auth @user, sign_hmac(url, '', "GET")
57
+
58
+ @response = Net::HTTP.start(uri.hostname, uri.port, :use_ssl => (uri.scheme == 'https')) {|http| http.request(req) }
59
+ JSON.parse(@response.body).to_hash
60
+ end
61
+
62
+ def post(url, data)
63
+ uri = URI("https://#{@api_hostname}/#{url}")
64
+ req = Net::HTTP::Post.new(uri.request_uri)
65
+ pass = sign_hmac(url, to_query(data), "POST")
66
+ puts pass
67
+ req.basic_auth @user, pass
68
+ req.set_form_data(data)
69
+ @response = Net::HTTP.start(uri.hostname, uri.port, :use_ssl => (uri.scheme == 'https')) {|http| http.request(req) }
70
+ JSON.parse(@response.body).to_hash
71
+ end
72
+
73
+ def sign_hmac(url, data, method)
74
+ request = "#{method}\n"
75
+ request << "#{@api_hostname}\n"
76
+ request << "/#{url}\n"
77
+ request << "#{data}"
78
+ # puts "\n"
79
+ # puts request
80
+ sig = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('sha1'), @key, request)
81
+ return sig
82
+ end
83
+
84
+ def to_query(hash)
85
+ puts hash
86
+ hash.map{|k,v| "#{k}=#{CGI.escape(v)}"}.join("&")
87
+ end
88
+
89
+ end
90
+
91
+ end
@@ -0,0 +1,3 @@
1
+ module DuoRest
2
+ VERSION = "0.0.1"
3
+ end
Binary file
@@ -0,0 +1,71 @@
1
+ require 'test/unit'
2
+ require 'duo-rest'
3
+
4
+ class DuoRestTest < Test::Unit::TestCase
5
+
6
+ CONFIG = YAML::load( File.open( 'duo_test_info.yml' ) )
7
+
8
+ API_HOSTNAME = CONFIG['hostname']
9
+ API_INTEGRATION_KEY = CONFIG['integration_key']
10
+ API_SECRET_KEY = CONFIG['secret_key']
11
+ API_USERNAME = CONFIG['username']
12
+ # simple passing test
13
+ def test_version
14
+ assert_equal "0.0.1", DuoRest::VERSION
15
+ end
16
+
17
+ def test_connection
18
+ connection = DuoRest::Connection.new(API_HOSTNAME, API_INTEGRATION_KEY, API_SECRET_KEY).ping
19
+ assert_equal({"response" => "pong", "stat" => "OK"}, connection)
20
+ end
21
+
22
+ def test_check
23
+ check = DuoRest::Connection.new(API_HOSTNAME, API_INTEGRATION_KEY, API_SECRET_KEY).check
24
+ assert_equal({"response" => "valid", "stat" => "OK"}, check)
25
+ end
26
+
27
+ def test_preauth
28
+ preauth = DuoRest::Connection.new(API_HOSTNAME, API_INTEGRATION_KEY, API_SECRET_KEY).preauth(API_USERNAME)
29
+ assert_equal("OK", preauth["stat"])
30
+
31
+ # this wont be the same for every user but this is the expected style
32
+ # assert_equal({
33
+ # "response" => {
34
+ # "factors"=> {"1"=>"push1", "2"=>"phone1", "3"=>"sms1", "default"=>"push1"},
35
+ # "prompt"=> "Duo two-factor login for kellymahan\n\nEnter a passcode or select one of the following options:\n\n 1. Duo Push to XXX-XXX-9990\n 2. Phone call to XXX-XXX-9990\n 3. SMS passcodes to XXX-XXX-9990\n\nPasscode or option (1-3): ",
36
+ # "result"=>"auth"
37
+ # },
38
+ # "stat" => "OK"
39
+ # }, preauth)
40
+ end
41
+
42
+ def test_auth
43
+ auth = DuoRest::Connection.new(API_HOSTNAME, API_INTEGRATION_KEY, API_SECRET_KEY).auth(API_USERNAME, "push1")
44
+ assert_equal("OK", auth["stat"])
45
+
46
+ # this wont be the same for every user but this is the expected style
47
+ # assert_equal({
48
+ # "response"=>{"result"=>"allow", "status"=>"Success. Logging you in..."},
49
+ # "stat"=>"OK"
50
+ # }, auth)
51
+ end
52
+
53
+
54
+ # So far this is not working as expected and ignored for now since it isn't a requirement
55
+ # def test_delayed_auth
56
+ # auth = DuoRest::Connection.new(API_HOSTNAME, API_INTEGRATION_KEY, API_SECRET_KEY).auth(API_USERNAME, "push1", {async: true})
57
+ # assert_equal("OK", auth["stat"])
58
+ # # this wont be the same for every user but this is the expected style
59
+ # assert_equal({
60
+ # "response"=>{"result"=>"allow", "status"=>"Success. Logging you in..."},
61
+ # "stat"=>"OK"
62
+ # }, auth)
63
+ # end
64
+
65
+
66
+ #used to check for a delayed auth
67
+ def test_status
68
+ #TODO once delayed auth is working
69
+ end
70
+
71
+ end
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: duo-rest
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Kelly Mahan
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-06-27 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: pry
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: Gem interface for Duo security rest api
47
+ email: kmahan@kmahan.com
48
+ executables: []
49
+ extensions: []
50
+ extra_rdoc_files: []
51
+ files:
52
+ - .gitignore
53
+ - Gemfile
54
+ - Gemfile.lock
55
+ - README.md
56
+ - Rakefile
57
+ - duo-rest.gemspec
58
+ - duo_test_info_example.yml
59
+ - duotest.rb
60
+ - lib/duo-rest.rb
61
+ - lib/duo-rest/connection.rb
62
+ - lib/duo-rest/version.rb
63
+ - test/.DS_Store
64
+ - test/duo-rest.rb
65
+ homepage: http://rubygems.org/gems/duo-rest
66
+ licenses: []
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ segments:
78
+ - 0
79
+ hash: 3510725538051197660
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ segments:
87
+ - 0
88
+ hash: 3510725538051197660
89
+ requirements: []
90
+ rubyforge_project:
91
+ rubygems_version: 1.8.24
92
+ signing_key:
93
+ specification_version: 3
94
+ summary: Duo Security Rest Api
95
+ test_files:
96
+ - test/duo-rest.rb