skles 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +25 -0
- data/.rspec +1 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +38 -0
- data/LICENSE +20 -0
- data/README.textile +22 -0
- data/Rakefile +37 -0
- data/VERSION +1 -0
- data/lib/skles.rb +153 -0
- data/lib/skles_api.rb +113 -0
- data/skles.gemspec +61 -0
- data/spec/skles_api_spec.rb +130 -0
- data/spec/skles_spec.rb +97 -0
- data/spec/spec_helper.rb +9 -0
- metadata +94 -0
data/.document
ADDED
data/.gitignore
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
## MAC OS
|
2
|
+
.DS_Store
|
3
|
+
|
4
|
+
## TEXTMATE
|
5
|
+
*.tmproj
|
6
|
+
tmtags
|
7
|
+
|
8
|
+
## EMACS
|
9
|
+
*~
|
10
|
+
\#*
|
11
|
+
.\#*
|
12
|
+
|
13
|
+
## VIM
|
14
|
+
*.swp
|
15
|
+
|
16
|
+
## PROJECT::GENERAL
|
17
|
+
pkg
|
18
|
+
.rvm
|
19
|
+
.idea
|
20
|
+
.rvmrc
|
21
|
+
.bundle
|
22
|
+
|
23
|
+
## PROJECT::DOCUMENTATION
|
24
|
+
.yardoc
|
25
|
+
doc
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
-cfs
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
RedCloth (4.2.3)
|
5
|
+
builder (2.1.2)
|
6
|
+
crack (0.1.8)
|
7
|
+
diff-lcs (1.1.2)
|
8
|
+
gemcutter (0.6.1)
|
9
|
+
git (1.2.5)
|
10
|
+
jeweler (1.4.0)
|
11
|
+
gemcutter (>= 0.1.0)
|
12
|
+
git (>= 1.2.5)
|
13
|
+
rubyforge (>= 2.0.0)
|
14
|
+
json_pure (1.4.6)
|
15
|
+
rspec (2.1.0)
|
16
|
+
rspec-core (~> 2.1.0)
|
17
|
+
rspec-expectations (~> 2.1.0)
|
18
|
+
rspec-mocks (~> 2.1.0)
|
19
|
+
rspec-core (2.1.0)
|
20
|
+
rspec-expectations (2.1.0)
|
21
|
+
diff-lcs (~> 1.1.2)
|
22
|
+
rspec-mocks (2.1.0)
|
23
|
+
rubyforge (2.0.4)
|
24
|
+
json_pure (>= 1.1.7)
|
25
|
+
savon (0.7.9)
|
26
|
+
builder (>= 2.1.2)
|
27
|
+
crack (>= 0.1.4)
|
28
|
+
yard (0.6.1)
|
29
|
+
|
30
|
+
PLATFORMS
|
31
|
+
ruby
|
32
|
+
|
33
|
+
DEPENDENCIES
|
34
|
+
RedCloth
|
35
|
+
jeweler
|
36
|
+
rspec
|
37
|
+
savon
|
38
|
+
yard
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Tim Morgan
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.textile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
h1. SKLES: Ruby interface for StrongKey Lite boxes
|
2
|
+
|
3
|
+
| *Author* | Tim Morgan |
|
4
|
+
| *Version* | Version 1.0 (Nov 13, 2010) |
|
5
|
+
| *License* | Released under the MIT license. |
|
6
|
+
|
7
|
+
The SKLES gem is an interface to StrongAuth's StrongKey Lite credit card vault
|
8
|
+
system (http://www.strongauth.com/). You will need a StrongKey Lite install to
|
9
|
+
make any reasonable use of this gem.
|
10
|
+
|
11
|
+
|
12
|
+
Usage is simple:
|
13
|
+
|
14
|
+
<pre><code>
|
15
|
+
require 'skles'
|
16
|
+
skles = StrongKeyLite.new('http://your.strongauth.server', your_domain_id)
|
17
|
+
skles.add_user('encrypt_only', 'password', :encrypt)
|
18
|
+
skles.add_user('decrypt_only', 'password', :decrypt)
|
19
|
+
|
20
|
+
skles.encrypt('1234123412341234') #=> token
|
21
|
+
skles.decrypt(token) #=> credit card number
|
22
|
+
</code></pre>
|
data/Rakefile
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'rake'
|
2
|
+
begin
|
3
|
+
require 'bundler'
|
4
|
+
rescue LoadError
|
5
|
+
puts "Bundler is not installed; install with `gem install bundler`."
|
6
|
+
exit 1
|
7
|
+
end
|
8
|
+
|
9
|
+
Bundler.require :default
|
10
|
+
|
11
|
+
Jeweler::Tasks.new do |gem|
|
12
|
+
gem.name = "skles"
|
13
|
+
gem.summary = %Q{Ruby interface for SKLES (StrongKey Light Encryption System) boxes}
|
14
|
+
gem.description = %Q{A Ruby wrapper around the StrongKey Lite SOAP client API.}
|
15
|
+
gem.email = "git@timothymorgan.info"
|
16
|
+
gem.homepage = "http://github.com/RISCfuture/skles"
|
17
|
+
gem.authors = [ "Tim Morgan" ]
|
18
|
+
gem.add_dependency 'savon'
|
19
|
+
gem.required_ruby_version = '>= 1.9'
|
20
|
+
end
|
21
|
+
Jeweler::GemcutterTasks.new
|
22
|
+
|
23
|
+
require 'rspec/core/rake_task'
|
24
|
+
RSpec::Core::RakeTask.new
|
25
|
+
|
26
|
+
YARD::Rake::YardocTask.new('doc') do |doc|
|
27
|
+
doc.options << "-m" << "textile"
|
28
|
+
doc.options << "--protected"
|
29
|
+
doc.options << "--no-private"
|
30
|
+
doc.options << "-r" << "README.textile"
|
31
|
+
doc.options << "-o" << "doc"
|
32
|
+
doc.options << "--title" << "Ruby SKLES Documentation".inspect
|
33
|
+
|
34
|
+
doc.files = [ 'lib/**/*', 'README.textile' ]
|
35
|
+
end
|
36
|
+
|
37
|
+
task(default: :spec)
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.0
|
data/lib/skles.rb
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
require 'savon'
|
2
|
+
require File.dirname(__FILE__) + '/skles_api'
|
3
|
+
|
4
|
+
# can't have plaintext CC #s being logged
|
5
|
+
Savon::Request.log = false
|
6
|
+
|
7
|
+
# Client for the StrongKey Lite Encryption System (SKLES) SOAP-based API. An
|
8
|
+
# instance of this API interfaces with your StrongKey Lite box to encrypt and
|
9
|
+
# decrypt credit card numbers into the vault.
|
10
|
+
#
|
11
|
+
# Since many StrongKey Lite setups use different logins to perform different
|
12
|
+
# tasks (e.g., a more secure login/password is used to decrypt credit cards than
|
13
|
+
# to encrypt them), this class supports storing multiple sets of credentials,
|
14
|
+
# choosing them depending on the operation being performed.
|
15
|
+
#
|
16
|
+
# @example Single-user SKLES interface for the test domain
|
17
|
+
# skles = StrongKeyLite.new("https://demo.strongauth.com:8181", # the URL to the demo StrongKey Lite service
|
18
|
+
# 1, # your domain ID
|
19
|
+
# login: 'mylogin', password: 'mypassword' # your API user login and password for the demo box
|
20
|
+
# http: { verify_mode: OpenSSL::SSL::VERIFY_NONE }, # the demo service has an invalid cert, so we override cert verification
|
21
|
+
#
|
22
|
+
# @example Multi-user SKLES interface for a production domain
|
23
|
+
# skles = StrongKeyLite.new("https://strongauth.company.com:8181", 15)
|
24
|
+
# skles.add_user 'encrypt_only', 'thepassword', :encrypt, :batch_encrypt
|
25
|
+
# skles.add_user 'decrypt', 'anotherpassword', :decrypt, :batch_decrypt
|
26
|
+
|
27
|
+
class StrongKeyLite
|
28
|
+
include API
|
29
|
+
|
30
|
+
# The domain ID of the StrongKey service.
|
31
|
+
attr_accessor :domain_id
|
32
|
+
|
33
|
+
# Creates a new client interface.
|
34
|
+
#
|
35
|
+
# @param [String] service_url The protocol, host, and port for your StrongKey
|
36
|
+
# Lite service; _e.g._, "http://demo.strongauth.com:8181"
|
37
|
+
# @param [Fixnum] domain_id The domain ID.
|
38
|
+
# @param [Hash] options Additional options.
|
39
|
+
# @option options [String] :login You can provide the login of a user who will
|
40
|
+
# be used for all actions.
|
41
|
+
# @option options [String] :password The password for this user.
|
42
|
+
# @option options [Hash] :http Additional options to be given to the
|
43
|
+
# @Net::HTTP@ object. The keys will be invoked as setter methods on the HTTP
|
44
|
+
# object (_e.g._, passing @http: { timeout: 60 }@ will result in a call like
|
45
|
+
# @http.timeout = 60@).
|
46
|
+
|
47
|
+
def initialize(service_url, domain_id, options={})
|
48
|
+
@client = Savon::Client.new("#{service_url}/strongkeyliteWAR/EncryptionService?wsdl")
|
49
|
+
options[:http].each { |key, val| @client.request.http.send :"#{key}=", val } if options[:http].kind_of?(Hash)
|
50
|
+
|
51
|
+
self.domain_id = domain_id
|
52
|
+
|
53
|
+
@users = {}
|
54
|
+
@users_for_action = {}
|
55
|
+
|
56
|
+
add_user(options[:login], options[:password], :all) if options[:login] and options[:password]
|
57
|
+
end
|
58
|
+
|
59
|
+
# Adds a user by login and password. These users are used to perform API
|
60
|
+
# actions.
|
61
|
+
#
|
62
|
+
# @overload add_user(login, password)
|
63
|
+
# Adds a user. You can tell the client to use this user for certain actions
|
64
|
+
# by calling {#set_user_for_actions}.
|
65
|
+
# @overload add_user(login, password, action, ...)
|
66
|
+
# Adds a user and tells the client to use this user for the given list of
|
67
|
+
# actions.
|
68
|
+
# @param [Symbol] action An API action (such as @:ping@) that this user
|
69
|
+
# should be used to perform. Replaces the previous user assigned to this
|
70
|
+
# action.
|
71
|
+
# @raise [ArgumentError] If an unknown action is provided.
|
72
|
+
# @overload add_user(login, password, :all)
|
73
|
+
# Adds a user and tells the client to use this user for all API actions.
|
74
|
+
# @param [String] login The user's login.
|
75
|
+
# @param [String] password The user's password.
|
76
|
+
|
77
|
+
def add_user(login, password, *actions_for_user)
|
78
|
+
@users[login] = password
|
79
|
+
if actions_for_user == [ :all ] then
|
80
|
+
actions.each { |action| set_user_for_action(login, action) }
|
81
|
+
else
|
82
|
+
actions_for_user.each { |action| set_user_for_action(login, action) }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# @overload set_user_for_actions(login, action, ...)
|
87
|
+
# Tells the client to use this user for a list of actions. Calls made via
|
88
|
+
# the API of one of these actions will use this user. Replaces the previous
|
89
|
+
# user assigned to these actions.
|
90
|
+
# @param [String] login The user's login.
|
91
|
+
# @param [Symbol] the API action (such as @:ping@).
|
92
|
+
# @raise [ArgumentError] If an unknown action is provided.
|
93
|
+
|
94
|
+
def set_user_for_actions(login, *actions_for_user)
|
95
|
+
actions.flatten!
|
96
|
+
raise ArgumentError, "Unknown action(s): #{(actions_for_user - actions).join(',' )}" unless (actions_for_user - actions).empty?
|
97
|
+
actions_for_user.each { |action| @users_for_action[action] = login }
|
98
|
+
end
|
99
|
+
alias_method :set_user_for_action, :set_user_for_actions
|
100
|
+
|
101
|
+
# @return [Array<Symbol>] A list of actions that the API can perform.
|
102
|
+
|
103
|
+
def actions
|
104
|
+
@actions ||= @client.wsdl.soap_actions
|
105
|
+
end
|
106
|
+
|
107
|
+
# Makes an API call and returns the result as a hash. This method is the basis
|
108
|
+
# of all the more high-level API methods.
|
109
|
+
#
|
110
|
+
# @param [Symbol] meth The API method.
|
111
|
+
# @param [Hash] options The arguments for the API method. The @:did@,
|
112
|
+
# @:login@, and @:password@ arguments are set for you automatically.
|
113
|
+
# @return [Hash] The response fields.
|
114
|
+
# @raise [SOAPError] If a SOAP fault occurs.
|
115
|
+
# @raise [HTTPError] If an HTTP error occurs.
|
116
|
+
|
117
|
+
def call(meth, options={})
|
118
|
+
raise ArgumentError, "Unknown action #{meth.inspect}" unless actions.include?(meth)
|
119
|
+
|
120
|
+
login = @users_for_action[meth]
|
121
|
+
raise "No user has been assigned to action #{meth.inspect}" unless login
|
122
|
+
password = @users[login]
|
123
|
+
|
124
|
+
response = @client.send(meth) { |soap| soap.body = { did: domain_id, username: login, password: password }.merge(options) }
|
125
|
+
raise SOAPError(response.soap_fault, response) if response.soap_fault?
|
126
|
+
raise HTTPError(response.http_error, response) if response.http_error?
|
127
|
+
|
128
|
+
return response.to_hash
|
129
|
+
end
|
130
|
+
|
131
|
+
# Superclass of all {StrongKeyLite} exceptions.
|
132
|
+
|
133
|
+
class ResponseError < StandardError
|
134
|
+
|
135
|
+
# The @Savon::Response@ object resulting from the API call.
|
136
|
+
attr_reader :response
|
137
|
+
|
138
|
+
# @private
|
139
|
+
def initialize(msg, response)
|
140
|
+
super msg
|
141
|
+
@response = response
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# Raised when SOAP responses indicate errors.
|
146
|
+
|
147
|
+
class SOAPError < ResponseError; end
|
148
|
+
|
149
|
+
# Raised when @Net::HTTP@ returns a response other than 200 OK, or there is a
|
150
|
+
# socket error.
|
151
|
+
|
152
|
+
class HTTPError < ResponseError; end
|
153
|
+
end
|
data/lib/skles_api.rb
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
class StrongKeyLite
|
2
|
+
|
3
|
+
# Module included into {StrongKeyLite} with higher-level API actions.
|
4
|
+
|
5
|
+
module API
|
6
|
+
|
7
|
+
# Pings the service and returns information about its health. You must have
|
8
|
+
# a user set for the @:ping@ API action.
|
9
|
+
#
|
10
|
+
# @return [Hash] A hash of service status information (see example).
|
11
|
+
# @example Example response
|
12
|
+
# { :version => "1.0",
|
13
|
+
# :build => 40,
|
14
|
+
# :hostname => "demo.strongauth.com",
|
15
|
+
# :current_time => #<Time Thu Nov 11 18:52:45 PST 2010>,
|
16
|
+
# :up_since => #<Time Mon Sep 27 20:58:05 PDT 2010>,
|
17
|
+
# :well_known_pan => 1235711131719230,
|
18
|
+
# :encryptions_since_startup => 6,
|
19
|
+
# :encryptions_total => 17,
|
20
|
+
# :decryptions_since_startup => 9,
|
21
|
+
# :decryptions_total => 20,
|
22
|
+
# :deletions_since_startup => 0,
|
23
|
+
# :deletions_total => 0,
|
24
|
+
# :searches_since_startup => 1,
|
25
|
+
# :searches_total => 3,
|
26
|
+
# :batch_operations_since_startup => 0,
|
27
|
+
# :batch_operations_total => 0,
|
28
|
+
# :domain_id => 21
|
29
|
+
# }
|
30
|
+
|
31
|
+
def ping
|
32
|
+
msg = call(:ping)[:ping_response][:return]
|
33
|
+
info = Hash.new
|
34
|
+
msg.each_line do |line|
|
35
|
+
if line =~ /^SKLES (.+?) \(Build (\d+)\)$/
|
36
|
+
info[:version] = $1
|
37
|
+
info[:build] = $2.to_i
|
38
|
+
elsif line =~ /^Hostname: (.+?)$/ then
|
39
|
+
info[:hostname] = $1
|
40
|
+
elsif line =~ /^Current time: (.+?)$/ then
|
41
|
+
info[:current_time] = Time.parse($1)
|
42
|
+
elsif line =~ /^Up since: (.+?)$/ then
|
43
|
+
info[:up_since] = Time.parse($1)
|
44
|
+
elsif line =~ /^Well-known PAN: (\d+?)$/ then
|
45
|
+
info[:well_known_pan] = $1.to_i
|
46
|
+
elsif line =~ /^ENC: (\d+)\/(\d+)$/ then
|
47
|
+
info[:encryptions_since_startup] = $1.to_i
|
48
|
+
info[:encryptions_total] = $2.to_i
|
49
|
+
elsif line =~ /^DEC: (\d+)\/(\d+)$/ then
|
50
|
+
info[:decryptions_since_startup] = $1.to_i
|
51
|
+
info[:decryptions_total] = $2.to_i
|
52
|
+
elsif line =~ /^DEL: (\d+)\/(\d+)$/ then
|
53
|
+
info[:deletions_since_startup] = $1.to_i
|
54
|
+
info[:deletions_total] = $2.to_i
|
55
|
+
elsif line =~ /^SRC: (\d+)\/(\d+)$/ then
|
56
|
+
info[:searches_since_startup] = $1.to_i
|
57
|
+
info[:searches_total] = $2.to_i
|
58
|
+
elsif line =~ /^BAT: (\d+)\/(\d+)$/ then
|
59
|
+
info[:batch_operations_since_startup] = $1.to_i
|
60
|
+
info[:batch_operations_total] = $2.to_i
|
61
|
+
elsif line =~ /SKLES Domain (\d+) is (.+?)$/ then
|
62
|
+
info[:domain_id] = $1.to_i
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
return info
|
67
|
+
end
|
68
|
+
|
69
|
+
# Stores a credit card number (or any other plain text content) to the vault
|
70
|
+
# and returns an obscured token for later retrieval.
|
71
|
+
#
|
72
|
+
# @param [String] plaintext The text to encrypt and store.
|
73
|
+
# @return [String] A token that can be used to {#decrypt} the text. The text
|
74
|
+
# is not derivable from the token without access to the StrongKey Lite
|
75
|
+
# server.
|
76
|
+
|
77
|
+
def encrypt(plaintext)
|
78
|
+
call(:encrypt, plaintext: plaintext)[:encrypt_response][:return]
|
79
|
+
end
|
80
|
+
|
81
|
+
# Retrieves a credit card number (or any other encrypted content) from the
|
82
|
+
# vault using a ciphered token generated by a call to {#encrypt}.
|
83
|
+
#
|
84
|
+
# @param [String] token The ciphertext returned from @encrypt@.
|
85
|
+
# @return [String] The text that was encrypted.
|
86
|
+
|
87
|
+
def decrypt(token)
|
88
|
+
call(:decrypt, token: token)[:decrypt_response][:return]
|
89
|
+
end
|
90
|
+
|
91
|
+
# Removes a credit card number (or any other encrypted content) from the
|
92
|
+
# vault.
|
93
|
+
#
|
94
|
+
# @param [String] token The ciphertext returned from {#encrypt}.
|
95
|
+
# @return [true, false] Whether or not the encrypted content was
|
96
|
+
# successfully deleted.
|
97
|
+
|
98
|
+
def delete(token)
|
99
|
+
call(:delete, token: token)[:delete_response][:return]
|
100
|
+
end
|
101
|
+
|
102
|
+
# Determines if a credit card number (or any other plain text content) is
|
103
|
+
# stored in the vault. If so, returns its token.
|
104
|
+
#
|
105
|
+
# @param [String] plaintext The text to search for.
|
106
|
+
# @return [String, nil] The token for the text, if stored, or @nil@ if no
|
107
|
+
# such text is stored in the vault.
|
108
|
+
|
109
|
+
def search(plaintext)
|
110
|
+
call(:search, plaintext: plaintext)[:search_response][:return]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
data/skles.gemspec
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{skles}
|
8
|
+
s.version = "1.0.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Tim Morgan"]
|
12
|
+
s.date = %q{2010-11-13}
|
13
|
+
s.description = %q{A Ruby wrapper around the StrongKey Lite SOAP client API.}
|
14
|
+
s.email = %q{git@timothymorgan.info}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.textile"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".gitignore",
|
22
|
+
".rspec",
|
23
|
+
"Gemfile",
|
24
|
+
"Gemfile.lock",
|
25
|
+
"LICENSE",
|
26
|
+
"README.textile",
|
27
|
+
"Rakefile",
|
28
|
+
"VERSION",
|
29
|
+
"lib/skles.rb",
|
30
|
+
"lib/skles_api.rb",
|
31
|
+
"skles.gemspec",
|
32
|
+
"spec/skles_api_spec.rb",
|
33
|
+
"spec/skles_spec.rb",
|
34
|
+
"spec/spec_helper.rb"
|
35
|
+
]
|
36
|
+
s.homepage = %q{http://github.com/RISCfuture/skles}
|
37
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
38
|
+
s.require_paths = ["lib"]
|
39
|
+
s.required_ruby_version = Gem::Requirement.new(">= 1.9")
|
40
|
+
s.rubygems_version = %q{1.3.7}
|
41
|
+
s.summary = %q{Ruby interface for SKLES (StrongKey Light Encryption System) boxes}
|
42
|
+
s.test_files = [
|
43
|
+
"spec/skles_api_spec.rb",
|
44
|
+
"spec/skles_spec.rb",
|
45
|
+
"spec/spec_helper.rb"
|
46
|
+
]
|
47
|
+
|
48
|
+
if s.respond_to? :specification_version then
|
49
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
50
|
+
s.specification_version = 3
|
51
|
+
|
52
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
53
|
+
s.add_runtime_dependency(%q<savon>, [">= 0"])
|
54
|
+
else
|
55
|
+
s.add_dependency(%q<savon>, [">= 0"])
|
56
|
+
end
|
57
|
+
else
|
58
|
+
s.add_dependency(%q<savon>, [">= 0"])
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe StrongKeyLite::API do
|
4
|
+
before :each do
|
5
|
+
@client = mock('Savon::Client', request: nil, wsdl: mock('Savon::WSDL', soap_actions: [ :ping ]))
|
6
|
+
Savon::Client.stub!(:new).and_return(@client)
|
7
|
+
@response = mock('Soap::Response', :soap_fault? => false, :http_error? => false, soap_fault: nil, http_error: nil, to_hash: {})
|
8
|
+
@skles = StrongKeyLite.new('http://test.host', 1, login: 'login', password: 'password')
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#ping" do
|
12
|
+
before :each do
|
13
|
+
@time = mock('Time')
|
14
|
+
Time.stub!(:parse).and_return(@time)
|
15
|
+
@client.should_receive(:ping).once.and_return(@response)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should parse the ping response" do
|
19
|
+
ping_response = <<-EOF
|
20
|
+
SKLES 1.0 (Build 40)
|
21
|
+
Hostname: demo.strongauth.com
|
22
|
+
Current time: Sat Nov 13 12:44:03 PST 2010
|
23
|
+
Up since: Mon Sep 27 20:58:05 PDT 2010
|
24
|
+
Well-known PAN: 1235711131719230
|
25
|
+
ENC: 8/19
|
26
|
+
DEC: 10/21
|
27
|
+
DEL: 1/1
|
28
|
+
SRC: 11/13
|
29
|
+
BAT: 0/0
|
30
|
+
SKLES Domain 21 is alive!
|
31
|
+
EOF
|
32
|
+
|
33
|
+
@response.stub(:to_hash).and_return(ping_response: { return: ping_response })
|
34
|
+
@skles.ping.should eql({ version: "1.0", build: 40, hostname: "demo.strongauth.com",
|
35
|
+
current_time: @time, up_since: @time,
|
36
|
+
well_known_pan: 1235711131719230,
|
37
|
+
encryptions_since_startup: 8, encryptions_total: 19,
|
38
|
+
decryptions_since_startup: 10, decryptions_total: 21,
|
39
|
+
deletions_since_startup: 1, deletions_total: 1,
|
40
|
+
searches_since_startup: 11, searches_total: 13,
|
41
|
+
batch_operations_since_startup: 0, batch_operations_total: 0,
|
42
|
+
domain_id: 21 })
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should not error if the response is malformed" do
|
46
|
+
ping_response = <<-EOF
|
47
|
+
SKLES 1.0 (Build 40)
|
48
|
+
Hostname: demo.strongauth.com
|
49
|
+
Current time: Sat Nov 13 12:44:03 PST 2010
|
50
|
+
Up since: Mon Sep 27 20:58:05 PDT 2010
|
51
|
+
Well-known PAN: 1235711131719230
|
52
|
+
ENC: 8/19
|
53
|
+
DEL: 1/1
|
54
|
+
SRC: 11/13
|
55
|
+
BAT: 0/0
|
56
|
+
SKLES Domain 21 is alive!
|
57
|
+
EOF
|
58
|
+
|
59
|
+
@response.stub(:to_hash).and_return(ping_response: { return: ping_response })
|
60
|
+
@skles.ping.should eql({ version: "1.0", build: 40, hostname: "demo.strongauth.com",
|
61
|
+
current_time: @time, up_since: @time,
|
62
|
+
well_known_pan: 1235711131719230,
|
63
|
+
encryptions_since_startup: 8, encryptions_total: 19,
|
64
|
+
deletions_since_startup: 1, deletions_total: 1,
|
65
|
+
searches_since_startup: 11, searches_total: 13,
|
66
|
+
batch_operations_since_startup: 0, batch_operations_total: 0,
|
67
|
+
domain_id: 21 })
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "#encrypt" do
|
72
|
+
it "should make the appropriate API call" do
|
73
|
+
@skles.stub!(:actions).and_return([ :encrypt ])
|
74
|
+
@skles.add_user('login', 'password', :encrypt)
|
75
|
+
|
76
|
+
@response.stub(:to_hash).and_return(encrypt_response: { return: '123456' })
|
77
|
+
soap = mock('Savon::SOAP')
|
78
|
+
soap.should_receive(:body=).once.with(hash_including(plaintext: 'plaintext'))
|
79
|
+
|
80
|
+
@client.should_receive(:encrypt).once.and_yield(soap).and_return(@response)
|
81
|
+
|
82
|
+
@skles.encrypt('plaintext').should eql('123456')
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "#decrypt" do
|
87
|
+
it "should make the appropriate API call" do
|
88
|
+
@skles.stub!(:actions).and_return([ :decrypt ])
|
89
|
+
@skles.add_user('login', 'password', :decrypt)
|
90
|
+
|
91
|
+
@response.stub(:to_hash).and_return(decrypt_response: { return: 'plaintext' })
|
92
|
+
soap = mock('Savon::SOAP')
|
93
|
+
soap.should_receive(:body=).once.with(hash_including(token: '123456'))
|
94
|
+
|
95
|
+
@client.should_receive(:decrypt).once.and_yield(soap).and_return(@response)
|
96
|
+
|
97
|
+
@skles.decrypt('123456').should eql('plaintext')
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "#delete" do
|
102
|
+
it "should make the appropriate API call" do
|
103
|
+
@skles.stub!(:actions).and_return([ :delete ])
|
104
|
+
@skles.add_user('login', 'password', :delete)
|
105
|
+
|
106
|
+
@response.stub(:to_hash).and_return(delete_response: { return: true })
|
107
|
+
soap = mock('Savon::SOAP')
|
108
|
+
soap.should_receive(:body=).once.with(hash_including(token: '123456'))
|
109
|
+
|
110
|
+
@client.should_receive(:delete).once.and_yield(soap).and_return(@response)
|
111
|
+
|
112
|
+
@skles.delete('123456').should be_true
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "#search" do
|
117
|
+
it "should make the appropriate API call" do
|
118
|
+
@skles.stub!(:actions).and_return([ :search ])
|
119
|
+
@skles.add_user('login', 'password', :search)
|
120
|
+
|
121
|
+
@response.stub(:to_hash).and_return(search_response: { return: '123456' })
|
122
|
+
soap = mock('Savon::SOAP')
|
123
|
+
soap.should_receive(:body=).once.with(hash_including(plaintext: 'plaintext'))
|
124
|
+
|
125
|
+
@client.should_receive(:search).once.and_yield(soap).and_return(@response)
|
126
|
+
|
127
|
+
@skles.search('plaintext').should eql('123456')
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
data/spec/skles_spec.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe StrongKeyLite do
|
4
|
+
before :each do
|
5
|
+
@client = mock('Savon::Client', request: nil)
|
6
|
+
Savon::Client.stub!(:new).and_return(@client)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#initialize" do
|
10
|
+
it "should accept a host for the WSDL" do
|
11
|
+
Savon::Client.should_receive(:new).once.with("http://test.host/strongkeyliteWAR/EncryptionService?wsdl").and_return(@client)
|
12
|
+
StrongKeyLite.new('http://test.host', 1)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should set the domain ID" do
|
16
|
+
StrongKeyLite.new('http://test.host', 15).domain_id.should eql(15)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should accept and apply HTTP options" do
|
20
|
+
http = mock('Net::HTTP')
|
21
|
+
request = mock('Savon::Request', http: http)
|
22
|
+
@client.stub!(:request).and_return(request)
|
23
|
+
|
24
|
+
http.should_receive(:timeout=).once.with(60)
|
25
|
+
StrongKeyLite.new('http://test.host', 1, http: { timeout: 60 })
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should optionally accept a login and password" do
|
29
|
+
pending "Need a good way to test this"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#call" do
|
34
|
+
before :each do
|
35
|
+
@client = mock('Savon::Client', request: nil, wsdl: mock('Savon::WSDL', soap_actions: [ :ping ]))
|
36
|
+
Savon::Client.stub!(:new).and_return(@client)
|
37
|
+
@skles = StrongKeyLite.new('http://test.host', 1)
|
38
|
+
|
39
|
+
@response = mock('Soap::Response', :soap_fault? => false, :http_error? => false, soap_fault: nil, http_error: nil, to_hash: {})
|
40
|
+
@response.stub(:to_hash).and_return(ping_response: { return: '' })
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should raise an error if no user has been assigned to the action" do
|
44
|
+
-> { @skles.ping }.should raise_error(/No user/)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should invoke the proper action on the Savon client and use the appropriate user" do
|
48
|
+
@skles.add_user('login', 'password', :ping)
|
49
|
+
|
50
|
+
soap = mock('Savon::Request')
|
51
|
+
soap.should_receive(:body=).once.with({ did: 1, username: 'login', password: 'password' })
|
52
|
+
@client.should_receive(:ping).once.and_yield(soap).and_return(@response)
|
53
|
+
@skles.ping
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should assign a user to all actions when given :all" do
|
57
|
+
@skles.add_user('all', 'password', :all)
|
58
|
+
|
59
|
+
soap = mock('Savon::Request')
|
60
|
+
soap.should_receive(:body=).once.with({ did: 1, username: 'all', password: 'password' })
|
61
|
+
@client.should_receive(:ping).once.and_yield(soap).and_return(@response)
|
62
|
+
@skles.ping
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should replace an older user assigned to an action" do
|
66
|
+
@skles.add_user('all', 'password', :all)
|
67
|
+
@skles.add_user('ping', 'password', :ping)
|
68
|
+
|
69
|
+
soap = mock('Savon::Request')
|
70
|
+
soap.should_receive(:body=).once.with({ did: 1, username: 'ping', password: 'password' })
|
71
|
+
@client.should_receive(:ping).once.and_yield(soap).and_return(@response)
|
72
|
+
@skles.ping
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "#actions" do
|
77
|
+
before :each do
|
78
|
+
@wsdl = mock('Savon::WSDL')
|
79
|
+
@client = mock('Savon::Client', request: nil, wsdl: @wsdl)
|
80
|
+
Savon::Client.stub!(:new).and_return(@client)
|
81
|
+
@skles = StrongKeyLite.new('http://test.host', 1)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should return a list of SOAP actions" do
|
85
|
+
@wsdl.should_receive(:soap_actions).once.and_return([ :one, :two, :three ])
|
86
|
+
@skles.actions.should eql([ :one, :two, :three ])
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should cache the list" do
|
90
|
+
@wsdl.should_receive(:soap_actions).once.and_return([ :one, :two, :three ])
|
91
|
+
@skles.actions.should eql([ :one, :two, :three ])
|
92
|
+
|
93
|
+
@wsdl.should_not_receive(:soap_actions)
|
94
|
+
@skles.actions.should eql([ :one, :two, :three ])
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: skles
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 1
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
version: 1.0.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Tim Morgan
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-11-13 00:00:00 -08:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: savon
|
22
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
version: "0"
|
30
|
+
type: :runtime
|
31
|
+
prerelease: false
|
32
|
+
version_requirements: *id001
|
33
|
+
description: A Ruby wrapper around the StrongKey Lite SOAP client API.
|
34
|
+
email: git@timothymorgan.info
|
35
|
+
executables: []
|
36
|
+
|
37
|
+
extensions: []
|
38
|
+
|
39
|
+
extra_rdoc_files:
|
40
|
+
- LICENSE
|
41
|
+
- README.textile
|
42
|
+
files:
|
43
|
+
- .document
|
44
|
+
- .gitignore
|
45
|
+
- .rspec
|
46
|
+
- Gemfile
|
47
|
+
- Gemfile.lock
|
48
|
+
- LICENSE
|
49
|
+
- README.textile
|
50
|
+
- Rakefile
|
51
|
+
- VERSION
|
52
|
+
- lib/skles.rb
|
53
|
+
- lib/skles_api.rb
|
54
|
+
- skles.gemspec
|
55
|
+
- spec/skles_api_spec.rb
|
56
|
+
- spec/skles_spec.rb
|
57
|
+
- spec/spec_helper.rb
|
58
|
+
has_rdoc: true
|
59
|
+
homepage: http://github.com/RISCfuture/skles
|
60
|
+
licenses: []
|
61
|
+
|
62
|
+
post_install_message:
|
63
|
+
rdoc_options:
|
64
|
+
- --charset=UTF-8
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
segments:
|
73
|
+
- 1
|
74
|
+
- 9
|
75
|
+
version: "1.9"
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
segments:
|
82
|
+
- 0
|
83
|
+
version: "0"
|
84
|
+
requirements: []
|
85
|
+
|
86
|
+
rubyforge_project:
|
87
|
+
rubygems_version: 1.3.7
|
88
|
+
signing_key:
|
89
|
+
specification_version: 3
|
90
|
+
summary: Ruby interface for SKLES (StrongKey Light Encryption System) boxes
|
91
|
+
test_files:
|
92
|
+
- spec/skles_api_spec.rb
|
93
|
+
- spec/skles_spec.rb
|
94
|
+
- spec/spec_helper.rb
|