nimbussecure 0.5.0
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 +5 -0
- data/Gemfile +4 -0
- data/README.md +104 -0
- data/Rakefile +6 -0
- data/bin/nimbussecure +102 -0
- data/lib/nimbussecure.rb +72 -0
- data/lib/nimbussecure/accounts.rb +16 -0
- data/lib/nimbussecure/attr_accessor.rb +21 -0
- data/lib/nimbussecure/base.rb +44 -0
- data/lib/nimbussecure/config.rb +19 -0
- data/lib/nimbussecure/connect.rb +60 -0
- data/lib/nimbussecure/crypt_key.rb +75 -0
- data/lib/nimbussecure/errors.rb +7 -0
- data/lib/nimbussecure/results.rb +20 -0
- data/lib/nimbussecure/stored_key.rb +47 -0
- data/lib/nimbussecure/version.rb +3 -0
- data/nimbussecure.gemspec +27 -0
- data/pry_load.rb +2 -0
- data/test/accounts_spec.rb +18 -0
- data/test/basic_key_lookup_spec.rb +31 -0
- data/test/fixtures/vcr_cassettes/accounts/test.yml +52 -0
- data/test/fixtures/vcr_cassettes/lookup/key1.yml +52 -0
- data/test/fixtures/vcr_cassettes/lookup/key2.yml +101 -0
- data/test/fixtures/vcr_cassettes/lookup/key3.yml +52 -0
- data/test/minitest_helper.rb +10 -0
- data/test/run_tests.rb +6 -0
- metadata +135 -0
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
# Nimbus Secure Store Client
|
2
|
+
This gem provides the functionality required to talk to the Nimbus Secure
|
3
|
+
service.
|
4
|
+
Nimbus Secure is a service that provides highly encrypted storage of
|
5
|
+
keys, passwords, tokens, and other private information necessary for running
|
6
|
+
an application.
|
7
|
+
For instance, you may store database credentials, service credentials,
|
8
|
+
session cookie encryption keys, AWS keys, and other sensitive information
|
9
|
+
without fear of them being stolen or accessible from any unauthorized
|
10
|
+
individual.
|
11
|
+
The data is stored encrypted, and the encryption keys are not communicated
|
12
|
+
to the Nimbus Secure, meaning no one other than you may have access
|
13
|
+
to this secure information.
|
14
|
+
|
15
|
+
# The Service
|
16
|
+
To use this Gem, you must sign up for the service by visiting
|
17
|
+
www.nimbus secure.com and signing up for an account. Both
|
18
|
+
paid and free accounts are available.
|
19
|
+
|
20
|
+
Once you sign up for the service, you create crypt keys, which are
|
21
|
+
secured tokens used to encrypt and decrypt the data you store within
|
22
|
+
the service. While you set up the crypt keys from the service
|
23
|
+
website, the crypt keys themselves are never sent to our servers,
|
24
|
+
only you and anyone or system you authorize by giving them your
|
25
|
+
crypt key will have access to the stored data within the service.
|
26
|
+
|
27
|
+
You may create as many crypt keys as you desire. Typically, one per
|
28
|
+
service or system is a good choice. Additionally, you can add new
|
29
|
+
crypt keys and roll your data over to use a new crypt key very
|
30
|
+
easily in order to increase your security (key rotation). Each crypt
|
31
|
+
key has a name for easy identification, and we store a salted digest
|
32
|
+
of the key itself to verify correctness when it is provided.
|
33
|
+
|
34
|
+
Once your crypt keys are setup, you then enter all your sensitive data
|
35
|
+
as "stored keys". Stored keys are encrypted using your specified
|
36
|
+
crypt_keys before they are uploaded to our servers.
|
37
|
+
|
38
|
+
For security purposes, anytime the website or this Gem require a
|
39
|
+
crypt key, it must be provided by you (the user of the website or Gem),
|
40
|
+
and the value provided is checked against a stored signed digest
|
41
|
+
for valdity before it is used to perform the requested encryption/decryption.
|
42
|
+
The requested encryption/decryption occurs entirely within the client's
|
43
|
+
computer (user's browser for the website, application server for users
|
44
|
+
of the Gem), and is never communicated with Nimbus Secure directly.
|
45
|
+
|
46
|
+
# Using the Secured Data
|
47
|
+
Once you have your data uploaded to your service, you can then
|
48
|
+
install this Gem into your application, and use it's programmatic
|
49
|
+
interface (or command line) to download and decrypt the stored
|
50
|
+
credential so you may use it within your application.
|
51
|
+
|
52
|
+
# Needed Credentials
|
53
|
+
In order to use this Gem, you need two pieces of secure information.
|
54
|
+
The first is an API key that provides access to the API and allows
|
55
|
+
you to access your online account. You can create an API key by
|
56
|
+
logging into the service.
|
57
|
+
|
58
|
+
The second is the crypt key that you created above that is used
|
59
|
+
to encrypt/decrypt your stored data. If you used more than one key,
|
60
|
+
then you will need all the encrypted keys.
|
61
|
+
|
62
|
+
Typically, you store these two pieces of information outside of your
|
63
|
+
application source repository itself, and only provide them to your
|
64
|
+
application during application startup (typically via ENVIRONMENT
|
65
|
+
variables or other boot parameters). That way, you do not have
|
66
|
+
to share the credentials or persist them source repository.
|
67
|
+
|
68
|
+
Given these two pieces of information, this Gem, and the properly
|
69
|
+
setup service, you can dynamically grab all your sensitive credentials
|
70
|
+
and data needed to run your application. This typically happens during
|
71
|
+
your application boot up process.
|
72
|
+
|
73
|
+
# Setting up your .nibmussecure.yml file:
|
74
|
+
The easiest way to setup Nimbus Secure is to setup a configuration file in your home directory.
|
75
|
+
This file will contain sensitive information, so it should be marked as readable to you only
|
76
|
+
(permission mode 400). The following is a sample configuration file:
|
77
|
+
|
78
|
+
account: <my_account_id>
|
79
|
+
apikey: <my_accounts_apikey>
|
80
|
+
crypt_keys:
|
81
|
+
key1: <my_secret_value_for_key1>
|
82
|
+
key2: <my_secret_value_for_key2>
|
83
|
+
|
84
|
+
The value "<my_account_id>" is the same value that appears in the base part of your URL you use to
|
85
|
+
access Nmbus Secure. So, for example, if the URL you use to access Nimbus Secure is this:
|
86
|
+
|
87
|
+
https://www.nimbussecure.com/myaccount
|
88
|
+
|
89
|
+
Then your account id is "myaccount". Your "apikey" can be retrieved from the "Api Keys" tab in
|
90
|
+
Nimbus Secure.
|
91
|
+
|
92
|
+
For each encryption key you have in your account and you wish to use, you must have a line in the
|
93
|
+
"crypt_keys:"" section of the config file. In the above example, "key1" is the name assigned to the
|
94
|
+
first encryption key, and "<my_secret_value_for_key1>" is the secret value you assigned when
|
95
|
+
you created this encryption key.
|
96
|
+
|
97
|
+
# Using in Ruby
|
98
|
+
Assuming you have a stored key with a name "testmessage" setup, with an approprate encryption key.
|
99
|
+
Also assuming your ~/.nimbussecure.yml file is setup with your account identifier, API Key,
|
100
|
+
and the encryption key value. Then the following can be used to retrieve and decrypt a stored key:
|
101
|
+
|
102
|
+
require 'nimbussecure'
|
103
|
+
stored_value=nimbussecure.lookup_value "testmessage"
|
104
|
+
puts "The decrypted stored value is: #{stored_value}"
|
data/Rakefile
ADDED
data/bin/nimbussecure
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'yaml'
|
3
|
+
lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
|
4
|
+
$LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
|
5
|
+
require 'nimbussecure'
|
6
|
+
|
7
|
+
def keystore
|
8
|
+
$keystore||=NimbusSecure.new config_file: $filename
|
9
|
+
end
|
10
|
+
|
11
|
+
def usage
|
12
|
+
puts "
|
13
|
+
Usage:
|
14
|
+
nimbussecure [-f <config_file>] account
|
15
|
+
nimbussecure [-f <config_file>] lookup <name>
|
16
|
+
<value> is sent to stdout
|
17
|
+
Where:
|
18
|
+
-f <config_file> Specifies a config file (rather than \"~/.nimbussecure.yml\")
|
19
|
+
<value> is the specific value being encrypted and stored.
|
20
|
+
|
21
|
+
Config File
|
22
|
+
The config file should look like the following:
|
23
|
+
================
|
24
|
+
account: myacct
|
25
|
+
apikey: myapikey
|
26
|
+
crypt_keys:
|
27
|
+
key1: value1
|
28
|
+
key2: value2
|
29
|
+
================
|
30
|
+
|
31
|
+
NOTE:
|
32
|
+
account:
|
33
|
+
The account value (\"myacct\" in the example above) can be found based on the
|
34
|
+
URL you use to access Nimbus Secure.
|
35
|
+
If your URL is:
|
36
|
+
https://www.nimbussecure.com/my_acct/
|
37
|
+
Then the \"account\" value in your config file should be \"my_acct\"
|
38
|
+
apikey:
|
39
|
+
You can find your API Key by clicking on \"API Keys\" when you are logged into
|
40
|
+
the Nimbus Secure website.
|
41
|
+
crypt_keys:
|
42
|
+
This is a set of key/value pairs. The key is the name as defined in your
|
43
|
+
Nimbus Secure \"Encryption Keys\" section, and the value is the secret value
|
44
|
+
you used when you created your encryption key.
|
45
|
+
"
|
46
|
+
exit 1
|
47
|
+
end
|
48
|
+
def show_error
|
49
|
+
puts "Error: #{keystore.last_error_message}"
|
50
|
+
keystore.last_error_details.each do |subject,error_list|
|
51
|
+
error_list.each do |error|
|
52
|
+
puts " #{subject} #{error}"
|
53
|
+
end
|
54
|
+
end if keystore.last_error_details
|
55
|
+
end
|
56
|
+
|
57
|
+
def main
|
58
|
+
usage if ARGV.size<1
|
59
|
+
idx=0
|
60
|
+
$filename="~/.nimbussecure.yml"
|
61
|
+
if ARGV[idx]=='-f'
|
62
|
+
usage if ARGV.size<=2
|
63
|
+
$filename=ARGV[idx+1]
|
64
|
+
idx+=2
|
65
|
+
end
|
66
|
+
case ARGV[idx]
|
67
|
+
when "account" then
|
68
|
+
usage if ARGV.size!=idx+1
|
69
|
+
account
|
70
|
+
when "lookup" then
|
71
|
+
usage if ARGV.size!=idx+2
|
72
|
+
lookup ARGV[idx+1]
|
73
|
+
else
|
74
|
+
usage
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def account
|
79
|
+
begin
|
80
|
+
account=keystore.account
|
81
|
+
puts " Name: #{account.name}"
|
82
|
+
puts " # Crypt Keys: #{account.num_crypt_keys}"
|
83
|
+
puts " # Stored Keys: #{account.num_stored_keys}"
|
84
|
+
rescue => error
|
85
|
+
puts "Error: #{error}"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def lookup name
|
90
|
+
begin
|
91
|
+
res=keystore.lookup name
|
92
|
+
if res.nil?
|
93
|
+
show_error
|
94
|
+
return
|
95
|
+
end
|
96
|
+
puts res.decrypted_value
|
97
|
+
rescue => error
|
98
|
+
puts "Error: #{error}"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
main
|
data/lib/nimbussecure.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require "nimbussecure/version"
|
2
|
+
require "nimbussecure/errors"
|
3
|
+
require "nimbussecure/attr_accessor"
|
4
|
+
require "nimbussecure/config"
|
5
|
+
require "nimbussecure/base"
|
6
|
+
require "nimbussecure/connect"
|
7
|
+
require "nimbussecure/results"
|
8
|
+
require "nimbussecure/accounts"
|
9
|
+
require "nimbussecure/crypt_key"
|
10
|
+
require "nimbussecure/stored_key"
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
#
|
15
|
+
# Simplified Usage
|
16
|
+
# (assumes ~/.nimbussecure.yml is setup)
|
17
|
+
# ======================================
|
18
|
+
#
|
19
|
+
# Get account details:
|
20
|
+
# nimbussecure.account
|
21
|
+
#
|
22
|
+
# Lookup a stored value and return the decrypted version (assumes crypt key is in ~/.nimbussecure.yml):
|
23
|
+
# nimbussecure.lookup_value :storedvalue_identifier
|
24
|
+
#
|
25
|
+
# Full Usage
|
26
|
+
# ==========
|
27
|
+
#
|
28
|
+
# Setup access:
|
29
|
+
# * Assumes ~/.nimbussecure.yml is setup:
|
30
|
+
# ns=NimbusSecure.new
|
31
|
+
# * Assumes otherfile.yml is setup:
|
32
|
+
# ns=NimbusSecure.new config_file: "otherfile.yml"
|
33
|
+
# * Manual Configuration:
|
34
|
+
# ns=NimbusSecure account: "ident", apikey: "apikey", crypt_keys: {key1: "value1",key2: "value2"}
|
35
|
+
#
|
36
|
+
# Get account details
|
37
|
+
# account=ns.account
|
38
|
+
# account.name
|
39
|
+
# account.num_crypt_keys
|
40
|
+
# account.num_stored_keys
|
41
|
+
#
|
42
|
+
# Get details on all configured encryption keys:
|
43
|
+
# crypt_keys=ns.crypt_keys
|
44
|
+
#
|
45
|
+
# Get all stored values:
|
46
|
+
# stored_keys=ns.stored_keys
|
47
|
+
#
|
48
|
+
# Lookup a single stored value:
|
49
|
+
# stored_key=ns.lookup ident
|
50
|
+
#
|
51
|
+
# With the stored_key object:
|
52
|
+
# stored_key.ident
|
53
|
+
# stored_key.decrypted_value # Assuming secret value for corresponding crypt_key is available locally
|
54
|
+
# stored_key.encrypted_value
|
55
|
+
# stored_key.key_type
|
56
|
+
#
|
57
|
+
# Ruby on Rails Usage
|
58
|
+
# ===================
|
59
|
+
#
|
60
|
+
# Example usage in Rails to load the secret_token (config/initializers/secret_token.rb):
|
61
|
+
# require 'nimbussecure'
|
62
|
+
# secret_token=nimbussecure.lookup "secret_token"
|
63
|
+
# raise "Secret token missing" unless secret_token
|
64
|
+
# NimbusData::Application.config.secret_token = secret_token.decrypted_value
|
65
|
+
# Or, alternately:
|
66
|
+
# require 'nimbussecure'
|
67
|
+
# secret_token=nimbussecure.lookup_value "secret_token"
|
68
|
+
# raise "Secret token missing" unless secret_token
|
69
|
+
# NimbusData::Application.config.secret_token = secret_token
|
70
|
+
#
|
71
|
+
# Assumes config file in ~/.nimbussecure
|
72
|
+
#
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class NimbusSecure
|
2
|
+
class Account<NimbusSecure::Base
|
3
|
+
nimbus_attr_accessor :name,:num_crypt_keys,:num_stored_keys
|
4
|
+
def initialize name,num_crypt_keys,num_stored_keys
|
5
|
+
@name=name
|
6
|
+
@num_crypt_keys=num_crypt_keys
|
7
|
+
@num_stored_keys=num_stored_keys
|
8
|
+
end
|
9
|
+
end
|
10
|
+
def account
|
11
|
+
return @account if @account
|
12
|
+
res=request_get "/account"
|
13
|
+
raise ServerError,"Invalid Account" unless res and res["account"]
|
14
|
+
@account=Account.new res["account"]["name"],res["account"]["num_crypt_keys"],res["account"]["num_stored_keys"]
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module NimbusSecureAttrAccessor
|
2
|
+
def nimbus_attr_accessor *list
|
3
|
+
list.each do |attr|
|
4
|
+
define_method(attr) do
|
5
|
+
instance_variable_get("@#{attr}")
|
6
|
+
end
|
7
|
+
|
8
|
+
define_method("#{attr}=") do |val|
|
9
|
+
instance_variable_set("@#{attr}",val)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
class NimbusSecure
|
15
|
+
private
|
16
|
+
class Base
|
17
|
+
class<<self
|
18
|
+
include NimbusSecureAttrAccessor
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class NimbusSecure
|
2
|
+
#
|
3
|
+
# Possible ways to initialize:
|
4
|
+
#
|
5
|
+
# 1) Explicit:
|
6
|
+
# ns=NimbusSecure.new account: "ident",apikey: "xyzzy", crypt_keys:{"key1":"value1","key2":"value2"}
|
7
|
+
# 2) File:
|
8
|
+
# ns=NimbusSecure.new config_file: "./nsconfig.yml"
|
9
|
+
# nsconfig.yml:
|
10
|
+
# -------------
|
11
|
+
# account: ident
|
12
|
+
# apikey: xxx
|
13
|
+
# crypt_keys:
|
14
|
+
# key1: value1
|
15
|
+
# key2: value2
|
16
|
+
# 3) YAML string (not file):
|
17
|
+
# ns=NimbusSecure.new config: "account: ident\napikey: xxx\ncrypt_keys:\n key1: value1\n key2:value2\n"
|
18
|
+
# 4) Default:
|
19
|
+
# ns=NimbusSecure.new
|
20
|
+
# ...reads configuration from ~/nimbussecure.yml
|
21
|
+
#
|
22
|
+
def initialize opts={}
|
23
|
+
raise InvalidConfig unless opts.respond_to?(:size) and opts.respond_to?(:[])
|
24
|
+
opts[:config_file]=File.expand_path("~/.nimbussecure.yml") if opts.size==0
|
25
|
+
if opts[:config] || opts[:config_file]
|
26
|
+
raw_config_str=opts[:config]
|
27
|
+
raw_config_str = File.read(File.expand_path(opts[:config_file])) if opts[:config_file]
|
28
|
+
raise InvalidConfigFile unless raw_config_str
|
29
|
+
opts=YAML.load(raw_config_str)
|
30
|
+
raise InvalidConfigFile unless opts
|
31
|
+
end
|
32
|
+
opts=Hash[opts.map{ |k, v| [k.to_sym, v] }]
|
33
|
+
config.account="xxx"
|
34
|
+
config.endpoint=opts[:endpoint].to_s if opts[:endpoint]
|
35
|
+
config.account=opts[:account].to_s
|
36
|
+
config.apikey=opts[:apikey].to_s
|
37
|
+
config.crypt_keys=Hash[opts[:crypt_keys].map{ |k, v| [k.to_sym, v.to_s] }] if opts[:crypt_keys]
|
38
|
+
raise InvalidConfig,"Config is missing or incomplete" unless config.valid?
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
def nimbussecure
|
43
|
+
@nimbussecure||=NimbusSecure.new
|
44
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
class NimbusSecure
|
3
|
+
class Config
|
4
|
+
attr_accessor :endpoint,:account,:apikey,:crypt_keys
|
5
|
+
def initialize
|
6
|
+
@crypt_keys={}
|
7
|
+
@endpoint="https://www.nimbussecure.com"
|
8
|
+
end
|
9
|
+
def invalid?
|
10
|
+
endpoint.nil? || account.nil? || apikey.nil? || crypt_keys.size==0
|
11
|
+
end
|
12
|
+
def valid?
|
13
|
+
!invalid?
|
14
|
+
end
|
15
|
+
end
|
16
|
+
def config
|
17
|
+
@config||=Config.new
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'faraday'
|
3
|
+
class NimbusSecure
|
4
|
+
private
|
5
|
+
def request_get path,data={}
|
6
|
+
response=request_connection.get do |req|
|
7
|
+
req.url "/#{config.account}/api/v1#{path}"
|
8
|
+
req.params data unless data.nil? or data.size==0
|
9
|
+
end
|
10
|
+
process_response response
|
11
|
+
end
|
12
|
+
def request_post path,data={}
|
13
|
+
response=request_connection.post do |req|
|
14
|
+
req.url "/#{config.account}/api/v1#{path}"
|
15
|
+
req.body=data
|
16
|
+
end
|
17
|
+
process_response response
|
18
|
+
end
|
19
|
+
def request_connection
|
20
|
+
raise MissingOrInvalidConfiguation if config.endpoint.nil? or config.apikey.nil?
|
21
|
+
@request_connection||=Faraday.new(url:config.endpoint) do |builder|
|
22
|
+
builder.request :url_encoded
|
23
|
+
# builder.response :logger
|
24
|
+
builder.use AuthenticationMiddleware,config.apikey
|
25
|
+
builder.adapter :net_http
|
26
|
+
end
|
27
|
+
end
|
28
|
+
def process_response response
|
29
|
+
raise ServerError,response if(response.status!=200)
|
30
|
+
@last_result=JSON.parse(response.body)
|
31
|
+
@last_status=@last_result["status"]
|
32
|
+
@last_error_message=nil
|
33
|
+
@last_error_details=nil
|
34
|
+
@last_error_message=@last_result["errormsg"] if @last_status!="success"
|
35
|
+
@last_error_details=@last_result["errordetails"] if @last_status!="success"
|
36
|
+
@last_result.delete "status"
|
37
|
+
@last_result.delete "errormsg"
|
38
|
+
@last_result.delete "errordetails"
|
39
|
+
return nil if @last_status!="success"
|
40
|
+
@last_result
|
41
|
+
end
|
42
|
+
class AuthenticationMiddleware < Faraday::Middleware
|
43
|
+
def initialize(app,apikey)
|
44
|
+
super(app)
|
45
|
+
@apikey=apikey
|
46
|
+
end
|
47
|
+
def call(env)
|
48
|
+
set_header env,'X-Nimbus-Component-Key',@apikey
|
49
|
+
set_header env,'X-Nimbus-Client-Version',NimbusSecure::VERSION
|
50
|
+
set_header env,'X-Nimbus-Client',"muskratsoftware/NimbusSecureClient"
|
51
|
+
set_header env,'X-Nimbus-Language',"ruby"
|
52
|
+
@app.call(env)
|
53
|
+
end
|
54
|
+
def set_header(env,header,value)
|
55
|
+
unless env[:request_headers][header]
|
56
|
+
env[:request_headers][header] = value
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'gibberish'
|
2
|
+
class NimbusSecure
|
3
|
+
#
|
4
|
+
#
|
5
|
+
# Crypt Key
|
6
|
+
#
|
7
|
+
#
|
8
|
+
class CryptKey<NimbusSecure::Base
|
9
|
+
nimbus_attr_accessor :id,:valid,:ident,:salt,:digest,:key_value
|
10
|
+
def initialize nss,ck
|
11
|
+
@valid=true
|
12
|
+
@id=ck["id"]
|
13
|
+
@ident=ck["ident"].to_sym
|
14
|
+
@salt=ck["salt"]
|
15
|
+
@digest=ck["digest"]
|
16
|
+
if nss.config.crypt_keys[@ident.to_sym]
|
17
|
+
@key_value=nss.config.crypt_keys[@ident.to_sym]
|
18
|
+
sha256=Digest::SHA256.new
|
19
|
+
sha256 << @salt+@key_value
|
20
|
+
digest=sha256.to_s
|
21
|
+
if digest!=@digest
|
22
|
+
@valid=false
|
23
|
+
@salt=nil
|
24
|
+
@digest=nil
|
25
|
+
@key_value=nil
|
26
|
+
@invalid_message="Local encryption key does not match stored digest on server"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
def valid?
|
31
|
+
@valid
|
32
|
+
end
|
33
|
+
def has_key_value?
|
34
|
+
return false unless valid?
|
35
|
+
!@key_value.nil?
|
36
|
+
end
|
37
|
+
|
38
|
+
def encrypt data
|
39
|
+
cipher.enc(data)
|
40
|
+
end
|
41
|
+
def decrypt data
|
42
|
+
cipher.dec(data)
|
43
|
+
end
|
44
|
+
private ################################################################################
|
45
|
+
def cipher
|
46
|
+
raise InvalidEncryptionKey,@invalid_message if @invalid_message
|
47
|
+
raise InvalidEncryptionKey,"Encryption Key does not have value configured locally" unless self.has_key_value?
|
48
|
+
raise InvalidEncryptionKey,"Invalid encryption key" unless self.valid?
|
49
|
+
Gibberish::AES.new(@key_value)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
#
|
55
|
+
# Access Crypt Keys
|
56
|
+
#
|
57
|
+
#
|
58
|
+
def crypt_keys
|
59
|
+
res=request_get "/crypt_keys"
|
60
|
+
@cached_crypt_keys=res["crypt_keys"].map{|key|NimbusSecure::CryptKey.new self,key}
|
61
|
+
end
|
62
|
+
def crypt_keys_from_cache
|
63
|
+
return @cached_crypt_keys if @cached_crypt_keys
|
64
|
+
crypt_keys
|
65
|
+
end
|
66
|
+
def clear_crypt_key_cache
|
67
|
+
@cached_crypt_keys=nil
|
68
|
+
end
|
69
|
+
def crypt_key ident
|
70
|
+
crypt_keys_from_cache.each do |ck|
|
71
|
+
return ck if ck.ident==ident.to_sym
|
72
|
+
end
|
73
|
+
return nil
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class NimbusSecure
|
2
|
+
def last_result
|
3
|
+
@last_result
|
4
|
+
end
|
5
|
+
def last_status
|
6
|
+
@last_status
|
7
|
+
end
|
8
|
+
def success?
|
9
|
+
last_status=="success"
|
10
|
+
end
|
11
|
+
def failed?
|
12
|
+
last_status!="success"
|
13
|
+
end
|
14
|
+
def last_error_message
|
15
|
+
@last_error_message
|
16
|
+
end
|
17
|
+
def last_error_details
|
18
|
+
@last_error_details
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'gibberish'
|
2
|
+
class NimbusSecure
|
3
|
+
#
|
4
|
+
#
|
5
|
+
# Stored Key
|
6
|
+
#
|
7
|
+
#
|
8
|
+
#
|
9
|
+
class StoredKey<NimbusSecure::Base
|
10
|
+
nimbus_attr_accessor :id,:ident,:encrypted_value,:decrypted_value,:crypt_key,:key_type
|
11
|
+
def initialize nss,skparams
|
12
|
+
@id=skparams["id"]
|
13
|
+
@ident=skparams["ident"]
|
14
|
+
@encrypted_value=skparams["encrypted_value"]
|
15
|
+
@decrypted_value=nil
|
16
|
+
@crypt_key=NimbusSecure::CryptKey.new(nss,skparams["crypt_key"])
|
17
|
+
@key_type=skparams["key_type"]
|
18
|
+
end
|
19
|
+
def apply_crypt_key ck
|
20
|
+
self.decrypted_value=ck.decrypt self.encrypted_value
|
21
|
+
end
|
22
|
+
def value
|
23
|
+
apply_crypt_key self.crypt_key unless decrypted_value
|
24
|
+
decrypted_value
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def lookup ident #,crypt_key
|
29
|
+
res=request_get "/stored_keys/#{ident}/locate"
|
30
|
+
return nil unless res
|
31
|
+
return nil unless res["stored_key"]
|
32
|
+
stored_key=NimbusSecure::StoredKey.new self,res["stored_key"]
|
33
|
+
ck=stored_key.crypt_key
|
34
|
+
return nil unless stored_key.encrypted_value
|
35
|
+
stored_key.apply_crypt_key ck
|
36
|
+
stored_key
|
37
|
+
end
|
38
|
+
def lookup_value ident
|
39
|
+
sk=lookup ident
|
40
|
+
return nil if sk.nil?
|
41
|
+
sk.value
|
42
|
+
end
|
43
|
+
def stored_keys
|
44
|
+
res=request_get "/stored_keys"
|
45
|
+
res["stored_keys"].map{|key|NimbusSecure::StoredKey.new self,key}
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "nimbussecure/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "nimbussecure"
|
7
|
+
s.version = NimbusSecure::VERSION
|
8
|
+
s.authors = ["Lee Atchison"]
|
9
|
+
s.email = ["lee@nimbussecure.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{Client library for NimbusSecure}
|
12
|
+
s.description = %q{Client library for NimbusSecure}
|
13
|
+
|
14
|
+
s.rubyforge_project = "nimbussecure"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_development_dependency "minitest"
|
22
|
+
s.add_development_dependency "vcr"
|
23
|
+
s.add_development_dependency "fakeweb"
|
24
|
+
s.add_runtime_dependency "faraday"
|
25
|
+
# s.add_runtime_dependency "rest-client"
|
26
|
+
s.add_runtime_dependency "gibberish"
|
27
|
+
end
|
data/pry_load.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
|
3
|
+
describe NimbusSecure::Account do
|
4
|
+
before do
|
5
|
+
@ns=NimbusSecure.new({endpoint: "http://localhost:3000",
|
6
|
+
account: "vcrtest",
|
7
|
+
apikey: "34807a2d4d-a9990c4748218eb6ed-70886bc0fd",
|
8
|
+
crypt_keys:{"primary"=>"xyzzyxyzzy"}})
|
9
|
+
end
|
10
|
+
it "should get a list of all accounts (when there is just one)" do
|
11
|
+
VCR.use_cassette "accounts/test" do
|
12
|
+
acct=@ns.account
|
13
|
+
acct.name.must_equal "VCR Account"
|
14
|
+
acct.num_crypt_keys.must_equal 23
|
15
|
+
acct.num_stored_keys.must_equal 34
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
describe "Key Lookup" do
|
3
|
+
before do
|
4
|
+
@ns=NimbusSecure.new({endpoint: "http://localhost:3000",
|
5
|
+
account: "vcrtest",
|
6
|
+
apikey: "34807a2d4d-a9990c4748218eb6ed-70886bc0fd",
|
7
|
+
crypt_keys:{"primary"=>"xyzzyxyzzy","secondary"=>"yzzyxyzzyx"}})
|
8
|
+
end
|
9
|
+
it "should be able to lookup a key and decrypt it" do
|
10
|
+
VCR.use_cassette "lookup/key1" do
|
11
|
+
@ns.lookup_value(:test1).must_equal "This is a test stored key"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
it "should be able to lookup a second key and decrypt it" do
|
15
|
+
VCR.use_cassette "lookup/key2" do
|
16
|
+
code=@ns.lookup_value(:test1).must_equal "This is a test stored key"
|
17
|
+
code=@ns.lookup_value(:test2).must_equal "This is another test stored key"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
it "should be able to fail gracefully if key is not found" do
|
21
|
+
VCR.use_cassette "lookup/key3" do
|
22
|
+
code=@ns.lookup_value :invalidkey
|
23
|
+
code.must_be_nil
|
24
|
+
@ns.success?.must_equal false
|
25
|
+
@ns.last_error_message.must_equal "Could not locate Stored Key invalidkey"
|
26
|
+
@ns.last_error_details.must_be_nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# TODO: We don't get an error when we lookup a key that doesn't exist...and other error cases...
|
@@ -0,0 +1,52 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://localhost:3000/vcrtest/api/v1/account
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
x-nimbus-component-key:
|
11
|
+
- 34807a2d4d-a9990c4748218eb6ed-70886bc0fd
|
12
|
+
x-nimbus-client-version:
|
13
|
+
- 0.4.0
|
14
|
+
x-nimbus-client:
|
15
|
+
- muskratsoftware/NimbusSecureClient
|
16
|
+
x-nimbus-language:
|
17
|
+
- ruby
|
18
|
+
accept-encoding:
|
19
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
20
|
+
accept:
|
21
|
+
- ! '*/*'
|
22
|
+
user-agent:
|
23
|
+
- Ruby
|
24
|
+
response:
|
25
|
+
status:
|
26
|
+
code: 200
|
27
|
+
message: OK
|
28
|
+
headers:
|
29
|
+
content-type:
|
30
|
+
- application/json; charset=utf-8
|
31
|
+
x-ua-compatible:
|
32
|
+
- IE=Edge
|
33
|
+
etag:
|
34
|
+
- ! '"e3a4296c05b32d0ff0c13b3792a87ec5"'
|
35
|
+
cache-control:
|
36
|
+
- max-age=0, private, must-revalidate
|
37
|
+
x-request-id:
|
38
|
+
- 31dee43871629934ff8e333f5151a2a3
|
39
|
+
x-runtime:
|
40
|
+
- '0.024024'
|
41
|
+
content-length:
|
42
|
+
- '92'
|
43
|
+
connection:
|
44
|
+
- close
|
45
|
+
server:
|
46
|
+
- thin 1.4.1 codename Chromeo
|
47
|
+
body:
|
48
|
+
encoding: US-ASCII
|
49
|
+
string: ! '{"status":"success","account":{"name":"VCR Account","num_crypt_keys":23,"num_stored_keys":34}}'
|
50
|
+
http_version: '1.1'
|
51
|
+
recorded_at: Thu, 02 Aug 2012 03:54:45 GMT
|
52
|
+
recorded_with: VCR 2.2.4
|
@@ -0,0 +1,52 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://localhost:3000/vcrtest/api/v1/stored_keys/test1/locate
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
x-nimbus-component-key:
|
11
|
+
- 34807a2d4d-a9990c4748218eb6ed-70886bc0fd
|
12
|
+
x-nimbus-client-version:
|
13
|
+
- 0.4.0
|
14
|
+
x-nimbus-client:
|
15
|
+
- muskratsoftware/NimbusSecureClient
|
16
|
+
x-nimbus-language:
|
17
|
+
- ruby
|
18
|
+
accept-encoding:
|
19
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
20
|
+
accept:
|
21
|
+
- ! '*/*'
|
22
|
+
user-agent:
|
23
|
+
- Ruby
|
24
|
+
response:
|
25
|
+
status:
|
26
|
+
code: 200
|
27
|
+
message: OK
|
28
|
+
headers:
|
29
|
+
content-type:
|
30
|
+
- application/json; charset=utf-8
|
31
|
+
x-ua-compatible:
|
32
|
+
- IE=Edge
|
33
|
+
etag:
|
34
|
+
- ! '"af24594f0840cb2713181cae549d7d53"'
|
35
|
+
cache-control:
|
36
|
+
- max-age=0, private, must-revalidate
|
37
|
+
x-request-id:
|
38
|
+
- 5588bd8d8d6058def7ed0ac007ea17b2
|
39
|
+
x-runtime:
|
40
|
+
- '0.029527'
|
41
|
+
content-length:
|
42
|
+
- '324'
|
43
|
+
connection:
|
44
|
+
- close
|
45
|
+
server:
|
46
|
+
- thin 1.4.1 codename Chromeo
|
47
|
+
body:
|
48
|
+
encoding: US-ASCII
|
49
|
+
string: ! '{"status":"success","stored_key":{"id":3,"ident":"test1","encrypted_value":"U2FsdGVkX1/GKKaIUe5+lSzPJ0shgBrFDx0oGQO0LBNvOPmo69NiN7SiuLMBQTCV\r\n","key_type":"symmetric","crypt_key":{"id":9,"ident":"primary","salt":"$2a$10$zT38XT42BXYjcfd5uFO2E.","digest":"d6992c3ad871a429b4485967456b87fbc916a126b60c788516e11dd4cb3e1410"}}}'
|
50
|
+
http_version: '1.1'
|
51
|
+
recorded_at: Thu, 02 Aug 2012 03:59:40 GMT
|
52
|
+
recorded_with: VCR 2.2.4
|
@@ -0,0 +1,101 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://localhost:3000/vcrtest/api/v1/stored_keys/test1/locate
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
x-nimbus-component-key:
|
11
|
+
- 34807a2d4d-a9990c4748218eb6ed-70886bc0fd
|
12
|
+
x-nimbus-client-version:
|
13
|
+
- 0.4.0
|
14
|
+
x-nimbus-client:
|
15
|
+
- muskratsoftware/NimbusSecureClient
|
16
|
+
x-nimbus-language:
|
17
|
+
- ruby
|
18
|
+
accept-encoding:
|
19
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
20
|
+
accept:
|
21
|
+
- ! '*/*'
|
22
|
+
user-agent:
|
23
|
+
- Ruby
|
24
|
+
response:
|
25
|
+
status:
|
26
|
+
code: 200
|
27
|
+
message: OK
|
28
|
+
headers:
|
29
|
+
content-type:
|
30
|
+
- application/json; charset=utf-8
|
31
|
+
x-ua-compatible:
|
32
|
+
- IE=Edge
|
33
|
+
etag:
|
34
|
+
- ! '"af24594f0840cb2713181cae549d7d53"'
|
35
|
+
cache-control:
|
36
|
+
- max-age=0, private, must-revalidate
|
37
|
+
x-request-id:
|
38
|
+
- 2a95b9c8862fb4b248da9467446f8c9c
|
39
|
+
x-runtime:
|
40
|
+
- '0.033637'
|
41
|
+
content-length:
|
42
|
+
- '324'
|
43
|
+
connection:
|
44
|
+
- close
|
45
|
+
server:
|
46
|
+
- thin 1.4.1 codename Chromeo
|
47
|
+
body:
|
48
|
+
encoding: US-ASCII
|
49
|
+
string: ! '{"status":"success","stored_key":{"id":3,"ident":"test1","encrypted_value":"U2FsdGVkX1/GKKaIUe5+lSzPJ0shgBrFDx0oGQO0LBNvOPmo69NiN7SiuLMBQTCV\r\n","key_type":"symmetric","crypt_key":{"id":9,"ident":"primary","salt":"$2a$10$zT38XT42BXYjcfd5uFO2E.","digest":"d6992c3ad871a429b4485967456b87fbc916a126b60c788516e11dd4cb3e1410"}}}'
|
50
|
+
http_version: '1.1'
|
51
|
+
recorded_at: Thu, 02 Aug 2012 03:59:40 GMT
|
52
|
+
- request:
|
53
|
+
method: get
|
54
|
+
uri: http://localhost:3000/vcrtest/api/v1/stored_keys/test2/locate
|
55
|
+
body:
|
56
|
+
encoding: US-ASCII
|
57
|
+
string: ''
|
58
|
+
headers:
|
59
|
+
x-nimbus-component-key:
|
60
|
+
- 34807a2d4d-a9990c4748218eb6ed-70886bc0fd
|
61
|
+
x-nimbus-client-version:
|
62
|
+
- 0.4.0
|
63
|
+
x-nimbus-client:
|
64
|
+
- muskratsoftware/NimbusSecureClient
|
65
|
+
x-nimbus-language:
|
66
|
+
- ruby
|
67
|
+
accept-encoding:
|
68
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
69
|
+
accept:
|
70
|
+
- ! '*/*'
|
71
|
+
user-agent:
|
72
|
+
- Ruby
|
73
|
+
response:
|
74
|
+
status:
|
75
|
+
code: 200
|
76
|
+
message: OK
|
77
|
+
headers:
|
78
|
+
content-type:
|
79
|
+
- application/json; charset=utf-8
|
80
|
+
x-ua-compatible:
|
81
|
+
- IE=Edge
|
82
|
+
etag:
|
83
|
+
- ! '"63fba6143471cebd1321622de55ef88e"'
|
84
|
+
cache-control:
|
85
|
+
- max-age=0, private, must-revalidate
|
86
|
+
x-request-id:
|
87
|
+
- 570fcdfafe42ade8d7f96cc9fe8fcb8e
|
88
|
+
x-runtime:
|
89
|
+
- '0.106230'
|
90
|
+
content-length:
|
91
|
+
- '327'
|
92
|
+
connection:
|
93
|
+
- close
|
94
|
+
server:
|
95
|
+
- thin 1.4.1 codename Chromeo
|
96
|
+
body:
|
97
|
+
encoding: US-ASCII
|
98
|
+
string: ! '{"status":"success","stored_key":{"id":4,"ident":"test2","encrypted_value":"U2FsdGVkX18WTqz1XtiUi7s1riXV6w49980V3E4ysvhyNgVxTY8eocj8jgsGn4PG\r\n","key_type":"symmetric","crypt_key":{"id":10,"ident":"secondary","salt":"$2a$10$bcYes9rn8wAX0W/eIVSUBu","digest":"09890ee6ed6bb70d8a8671ab8bd6102da2d6e4f2e8311ccb5ca83195276e4581"}}}'
|
99
|
+
http_version: '1.1'
|
100
|
+
recorded_at: Thu, 02 Aug 2012 03:59:40 GMT
|
101
|
+
recorded_with: VCR 2.2.4
|
@@ -0,0 +1,52 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://localhost:3000/vcrtest/api/v1/stored_keys/invalidkey/locate
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
x-nimbus-component-key:
|
11
|
+
- 34807a2d4d-a9990c4748218eb6ed-70886bc0fd
|
12
|
+
x-nimbus-client-version:
|
13
|
+
- 0.4.0
|
14
|
+
x-nimbus-client:
|
15
|
+
- muskratsoftware/NimbusSecureClient
|
16
|
+
x-nimbus-language:
|
17
|
+
- ruby
|
18
|
+
accept-encoding:
|
19
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
20
|
+
accept:
|
21
|
+
- ! '*/*'
|
22
|
+
user-agent:
|
23
|
+
- Ruby
|
24
|
+
response:
|
25
|
+
status:
|
26
|
+
code: 200
|
27
|
+
message: OK
|
28
|
+
headers:
|
29
|
+
content-type:
|
30
|
+
- application/json; charset=utf-8
|
31
|
+
x-ua-compatible:
|
32
|
+
- IE=Edge
|
33
|
+
etag:
|
34
|
+
- ! '"fe603117385eb96a83f0de7440c7ad4e"'
|
35
|
+
cache-control:
|
36
|
+
- max-age=0, private, must-revalidate
|
37
|
+
x-request-id:
|
38
|
+
- 3dd7d8ef85311f6e9d0d8e2a6e064421
|
39
|
+
x-runtime:
|
40
|
+
- '0.021249'
|
41
|
+
content-length:
|
42
|
+
- '90'
|
43
|
+
connection:
|
44
|
+
- close
|
45
|
+
server:
|
46
|
+
- thin 1.4.1 codename Chromeo
|
47
|
+
body:
|
48
|
+
encoding: US-ASCII
|
49
|
+
string: ! '{"status":"error","errormsg":"Could not locate Stored Key invalidkey","errordetails":null}'
|
50
|
+
http_version: '1.1'
|
51
|
+
recorded_at: Thu, 02 Aug 2012 03:59:40 GMT
|
52
|
+
recorded_with: VCR 2.2.4
|
@@ -0,0 +1,10 @@
|
|
1
|
+
$LOAD_PATH << File.dirname(File.expand_path(__FILE__).to_s).to_s+"/../lib/"
|
2
|
+
require 'minitest/autorun'
|
3
|
+
require 'vcr'
|
4
|
+
require 'nimbussecure'
|
5
|
+
|
6
|
+
VCR.configure do |c|
|
7
|
+
c.cassette_library_dir = 'test/fixtures/vcr_cassettes'
|
8
|
+
c.hook_into :fakeweb
|
9
|
+
# c.stub_with :fakeweb
|
10
|
+
end
|
data/test/run_tests.rb
ADDED
metadata
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nimbussecure
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Lee Atchison
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-08-02 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: minitest
|
16
|
+
requirement: &70236373001520 !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: *70236373001520
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: vcr
|
27
|
+
requirement: &70236373001100 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70236373001100
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: fakeweb
|
38
|
+
requirement: &70236373000680 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70236373000680
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: faraday
|
49
|
+
requirement: &70236373000240 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70236373000240
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: gibberish
|
60
|
+
requirement: &70236372999780 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70236372999780
|
69
|
+
description: Client library for NimbusSecure
|
70
|
+
email:
|
71
|
+
- lee@nimbussecure.com
|
72
|
+
executables:
|
73
|
+
- nimbussecure
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- .gitignore
|
78
|
+
- Gemfile
|
79
|
+
- README.md
|
80
|
+
- Rakefile
|
81
|
+
- bin/nimbussecure
|
82
|
+
- lib/nimbussecure.rb
|
83
|
+
- lib/nimbussecure/accounts.rb
|
84
|
+
- lib/nimbussecure/attr_accessor.rb
|
85
|
+
- lib/nimbussecure/base.rb
|
86
|
+
- lib/nimbussecure/config.rb
|
87
|
+
- lib/nimbussecure/connect.rb
|
88
|
+
- lib/nimbussecure/crypt_key.rb
|
89
|
+
- lib/nimbussecure/errors.rb
|
90
|
+
- lib/nimbussecure/results.rb
|
91
|
+
- lib/nimbussecure/stored_key.rb
|
92
|
+
- lib/nimbussecure/version.rb
|
93
|
+
- nimbussecure.gemspec
|
94
|
+
- pry_load.rb
|
95
|
+
- test/accounts_spec.rb
|
96
|
+
- test/basic_key_lookup_spec.rb
|
97
|
+
- test/fixtures/vcr_cassettes/accounts/test.yml
|
98
|
+
- test/fixtures/vcr_cassettes/lookup/key1.yml
|
99
|
+
- test/fixtures/vcr_cassettes/lookup/key2.yml
|
100
|
+
- test/fixtures/vcr_cassettes/lookup/key3.yml
|
101
|
+
- test/minitest_helper.rb
|
102
|
+
- test/run_tests.rb
|
103
|
+
homepage: ''
|
104
|
+
licenses: []
|
105
|
+
post_install_message:
|
106
|
+
rdoc_options: []
|
107
|
+
require_paths:
|
108
|
+
- lib
|
109
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
110
|
+
none: false
|
111
|
+
requirements:
|
112
|
+
- - ! '>='
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
|
+
none: false
|
117
|
+
requirements:
|
118
|
+
- - ! '>='
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '0'
|
121
|
+
requirements: []
|
122
|
+
rubyforge_project: nimbussecure
|
123
|
+
rubygems_version: 1.8.15
|
124
|
+
signing_key:
|
125
|
+
specification_version: 3
|
126
|
+
summary: Client library for NimbusSecure
|
127
|
+
test_files:
|
128
|
+
- test/accounts_spec.rb
|
129
|
+
- test/basic_key_lookup_spec.rb
|
130
|
+
- test/fixtures/vcr_cassettes/accounts/test.yml
|
131
|
+
- test/fixtures/vcr_cassettes/lookup/key1.yml
|
132
|
+
- test/fixtures/vcr_cassettes/lookup/key2.yml
|
133
|
+
- test/fixtures/vcr_cassettes/lookup/key3.yml
|
134
|
+
- test/minitest_helper.rb
|
135
|
+
- test/run_tests.rb
|