duo-rest 0.0.1

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