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.
- data/.gitignore +18 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +24 -0
- data/README.md +30 -0
- data/Rakefile +10 -0
- data/duo-rest.gemspec +23 -0
- data/duo_test_info_example.yml +4 -0
- data/duotest.rb +0 -0
- data/lib/duo-rest.rb +8 -0
- data/lib/duo-rest/connection.rb +91 -0
- data/lib/duo-rest/version.rb +3 -0
- data/test/.DS_Store +0 -0
- data/test/duo-rest.rb +71 -0
- metadata +96 -0
data/.gitignore
ADDED
|
@@ -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
data/Gemfile.lock
ADDED
|
@@ -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
|
data/README.md
ADDED
|
@@ -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)
|
data/Rakefile
ADDED
data/duo-rest.gemspec
ADDED
|
@@ -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
|
data/duotest.rb
ADDED
|
File without changes
|
data/lib/duo-rest.rb
ADDED
|
@@ -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
|
data/test/.DS_Store
ADDED
|
Binary file
|
data/test/duo-rest.rb
ADDED
|
@@ -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
|