smaak 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -3
- data/lib/smaak/client.rb +7 -2
- data/lib/smaak/request_signing_validator.rb +20 -0
- data/lib/smaak/version.rb +1 -1
- data/lib/smaak.rb +3 -2
- data/spec/lib/smaak/client_spec.rb +5 -4
- data/spec/lib/smaak_spec.rb +2 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b1fa033c8f361f4af863c394544ffd64c8a9d9d0
|
4
|
+
data.tar.gz: fcccba2f5edd21f6112754588e86f34fccc72871
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3e70ec242a2eb128ae0e63363b4828f7f35bec12057f5be3cd9110063b6fbcf16327c6554571044906ed35a6ca9c7e4145f29f1167c5b5a0893589ee9f374618
|
7
|
+
data.tar.gz: 3a77ea6150c62382e5c01ebcb6e7362a5f8d926660cf212828f782d994aa51d316eaf7c337d683843c87a4efd1db50169c6bad65450953c975df425a63ea913e
|
data/README.md
CHANGED
@@ -18,11 +18,11 @@ Or install it yourself as:
|
|
18
18
|
|
19
19
|
## Use cases
|
20
20
|
|
21
|
-
This gem and mechanism
|
21
|
+
This gem and mechanism attempts to alleviate the following attacks and concerns for inter-service communication. This is not a public client/server mechanism.
|
22
22
|
|
23
23
|
Man-in-the-middle attack:
|
24
24
|
|
25
|
-
Use this gem to communicate inside an
|
25
|
+
Use this gem to communicate inside an HTTPS tunnel that you trust. For internal private networks, place a secure CA on your network.
|
26
26
|
|
27
27
|
Masquerading:
|
28
28
|
|
@@ -36,7 +36,9 @@ Replay:
|
|
36
36
|
|
37
37
|
The request is signed with an expiry and a nonce.
|
38
38
|
|
39
|
-
Designing for future protocol security requirements. The nonce and expiry
|
39
|
+
Designing for future protocol security requirements. The nonce and expiry becomes an optional feature (timestamp header signed could replace these). Passing in a RequestData object for signing, and a RequestSigningValidator object that validates the data content includes all that is required for security, allows us to, in future, cater for man-in-the-middle attacks as well if, for example, the validator requires timestamp, url, form data/querystring, method, etc. to be in the data. If this is all signed, a device in the middle cannot modify the request without the source's private key, and man-in-the-middle is defeated.
|
40
|
+
|
41
|
+
Though arbitrary data can be added for signature and an arbitrary validator provided to ensure the data and headers required are included for signing on request, on the server side the payload is not automatically checked by the Smaak::Server class. Ensure after verification of signature that you look in message_data['data'] and verify your payload has what you require to prove no man-in-the middle modification. This could be automated in a future release.
|
40
42
|
|
41
43
|
## Usage
|
42
44
|
|
data/lib/smaak/client.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'smaak.rb'
|
2
2
|
require 'smaak/associate.rb'
|
3
|
+
require 'smaak/request_signing_validator.rb'
|
3
4
|
|
4
5
|
module Smaak
|
5
6
|
class Client < Associate
|
@@ -14,11 +15,15 @@ module Smaak
|
|
14
15
|
@identity = identity
|
15
16
|
end
|
16
17
|
|
17
|
-
def build_auth_header(associate_identity,
|
18
|
+
def build_auth_header(associate_identity,
|
19
|
+
request_signing_data = {},
|
20
|
+
request_signing_data_validator = RequestSigningValidator.new)
|
18
21
|
raise ArgumentError.new("Associate invalid") if not validate_associate(associate_identity)
|
22
|
+
request_signing_data_validator.validate(request_signing_data)
|
19
23
|
associate = @association_store[associate_identity]
|
20
|
-
message_data = Smaak::compile_auth_message_data(associate['public_key'], associate['psk'], @token_life, @identity)
|
24
|
+
message_data = Smaak::compile_auth_message_data(associate['public_key'], associate['psk'], @token_life, @identity, request_signing_data)
|
21
25
|
signature = Smaak::sign_message_data(message_data, @key)
|
26
|
+
#TBD add request_signing_data approved by validator here
|
22
27
|
message = Smaak::build_message(message_data)
|
23
28
|
auth_body = { 'message' => message,
|
24
29
|
'signature' => Base64.encode64(signature) }
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Smaak
|
2
|
+
class RequestSigningValidator
|
3
|
+
def validate(data)
|
4
|
+
raise ArgumentError.new("Request data needs to be a Hash") if not data.is_a? Hash
|
5
|
+
ensure_present(data, "HTTPRequestMethod")
|
6
|
+
ensure_present(data, "CanonicalURI")
|
7
|
+
ensure_present(data, "CanonicalQueryString")
|
8
|
+
ensure_present(data, "CanonicalHeaders")
|
9
|
+
ensure_present(data, "SignedHeaders")
|
10
|
+
ensure_present(data, "RequestPayload")
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def ensure_present(data, key)
|
16
|
+
# raise ArgumentError.new("Request data needs to include #{key}") if data[key].nil?
|
17
|
+
puts "WARNING: Request data needs to include #{key}" if data[key].nil?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/smaak/version.rb
CHANGED
data/lib/smaak.rb
CHANGED
@@ -22,12 +22,13 @@ module Smaak
|
|
22
22
|
SecureRandom::random_number(10000000000)
|
23
23
|
end
|
24
24
|
|
25
|
-
def self.compile_auth_message_data(recipient_public_key, recipient_psk, token_life, identity)
|
25
|
+
def self.compile_auth_message_data(recipient_public_key, recipient_psk, token_life, identity, request_signing_data)
|
26
26
|
{ 'recipient' => recipient_public_key.export,
|
27
27
|
'identity' => identity,
|
28
28
|
'psk' => Smaak::obfuscate_psk(recipient_psk),
|
29
29
|
'expires' => Time.now.to_i + token_life,
|
30
|
-
'nonce' => Smaak::generate_nonce
|
30
|
+
'nonce' => Smaak::generate_nonce,
|
31
|
+
'data' => request_signing_data }
|
31
32
|
end
|
32
33
|
end
|
33
34
|
|
@@ -8,6 +8,7 @@ describe Smaak::Client do
|
|
8
8
|
@test_client_private_key = OpenSSL::PKey::RSA.new(4096)
|
9
9
|
@test_service_private_key = OpenSSL::PKey::RSA.new(4096)
|
10
10
|
@test_service_public_key = @test_service_private_key.public_key
|
11
|
+
@test_data = {}
|
11
12
|
@iut = Smaak::Client.new
|
12
13
|
@test_identity = 'test-client'
|
13
14
|
@test_token_life = 5
|
@@ -37,13 +38,13 @@ describe Smaak::Client do
|
|
37
38
|
end
|
38
39
|
|
39
40
|
it "should compile the auth message data using the associate details" do
|
40
|
-
expect(Smaak).to receive(:compile_auth_message_data).with(@test_service_public_key, @test_service_psk, @test_token_life, @test_identity)
|
41
|
+
expect(Smaak).to receive(:compile_auth_message_data).with(@test_service_public_key, @test_service_psk, @test_token_life, @test_identity, @test_data)
|
41
42
|
@iut.build_auth_header(@test_service_identity)
|
42
43
|
end
|
43
44
|
|
44
45
|
it "should build the message" do
|
45
46
|
expect(Smaak).to receive(:generate_nonce).twice().and_return(12345)
|
46
|
-
test_message_data = Smaak::compile_auth_message_data(@test_service_public_key, @test_service_psk, @test_token_life, @test_identity)
|
47
|
+
test_message_data = Smaak::compile_auth_message_data(@test_service_public_key, @test_service_psk, @test_token_life, @test_identity, @test_data)
|
47
48
|
expect(Smaak).to receive(:build_message).with(test_message_data)
|
48
49
|
expect{
|
49
50
|
@iut.build_auth_header(@test_service_identity)
|
@@ -52,7 +53,7 @@ describe Smaak::Client do
|
|
52
53
|
|
53
54
|
it "should sign the message" do
|
54
55
|
expect(Smaak).to receive(:generate_nonce).twice().and_return(12345)
|
55
|
-
test_message_data = Smaak::compile_auth_message_data(@test_service_public_key, @test_service_psk, @test_token_life, @test_identity)
|
56
|
+
test_message_data = Smaak::compile_auth_message_data(@test_service_public_key, @test_service_psk, @test_token_life, @test_identity, @test_data)
|
56
57
|
expect(Smaak).to receive(:sign_message_data).with(test_message_data, @test_client_private_key)
|
57
58
|
expect{
|
58
59
|
@iut.build_auth_header(@test_service_identity)
|
@@ -61,7 +62,7 @@ describe Smaak::Client do
|
|
61
62
|
|
62
63
|
it "should place the message and its signature (encoded base64) in a JSON dictionary" do
|
63
64
|
expect(Smaak).to receive(:generate_nonce).twice().and_return(12345)
|
64
|
-
test_message_data = Smaak::compile_auth_message_data(@test_service_public_key, @test_service_psk, @test_token_life, @test_identity)
|
65
|
+
test_message_data = Smaak::compile_auth_message_data(@test_service_public_key, @test_service_psk, @test_token_life, @test_identity, @test_data)
|
65
66
|
test_signature = Smaak::sign_message_data(test_message_data, @test_client_private_key)
|
66
67
|
test_message = Smaak::build_message(test_message_data)
|
67
68
|
test_envelope = { 'message' => test_message, 'signature' => Base64.encode64(test_signature) }.to_json
|
data/spec/lib/smaak_spec.rb
CHANGED
@@ -57,10 +57,11 @@ describe Smaak do
|
|
57
57
|
@associate_psk = 'sharedsecret'
|
58
58
|
@token_life = 3
|
59
59
|
@identity = 'test-service'
|
60
|
+
@test_data = {}
|
60
61
|
end
|
61
62
|
|
62
63
|
before :each do
|
63
|
-
@iut = Smaak::compile_auth_message_data(@associate_public_key, @associate_psk, @token_life, @identity)
|
64
|
+
@iut = Smaak::compile_auth_message_data(@associate_public_key, @associate_psk, @token_life, @identity, @test_data)
|
64
65
|
@timestamp = Time.now.to_i
|
65
66
|
end
|
66
67
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: smaak
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ernst van Graan
|
@@ -140,6 +140,7 @@ files:
|
|
140
140
|
- lib/smaak/associate.rb
|
141
141
|
- lib/smaak/auth_message.rb
|
142
142
|
- lib/smaak/client.rb
|
143
|
+
- lib/smaak/request_signing_validator.rb
|
143
144
|
- lib/smaak/server.rb
|
144
145
|
- lib/smaak/version.rb
|
145
146
|
- smaak.gemspec
|