smartvpn-http-hooks 1.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +3 -0
  5. data/Gemfile.lock +39 -0
  6. data/LICENSE +19 -0
  7. data/README.md +22 -0
  8. data/bin/smartvpn-activate +6 -0
  9. data/bin/smartvpn-authenticate +8 -0
  10. data/bin/smartvpn-connect +6 -0
  11. data/bin/smartvpn-disconnect +7 -0
  12. data/lib/api/activation.rb +39 -0
  13. data/lib/api/authentication.rb +27 -0
  14. data/lib/api/billing.rb +44 -0
  15. data/lib/api/connect.rb +21 -0
  16. data/lib/api/connection.rb +66 -0
  17. data/lib/api/disconnect.rb +21 -0
  18. data/lib/exceptions/option_not_found.rb +2 -0
  19. data/lib/openvpn_password_authenticator.rb +18 -0
  20. data/lib/option/base.rb +30 -0
  21. data/lib/option/i2p.rb +28 -0
  22. data/lib/option/proxy.rb +66 -0
  23. data/lib/option/repository.rb +18 -0
  24. data/lib/signer.rb +7 -0
  25. data/lib/smartvpn-http-hooks.rb +19 -0
  26. data/lib/system/openvpn_status.rb +19 -0
  27. data/lib/system/openvpn_status_log_parser.rb +30 -0
  28. data/lib/system/openvpn_status_log_reader.rb +29 -0
  29. data/smartvpn-http-hooks.gemspec +17 -0
  30. data/spec/fixtures/active_connections.txt +10 -0
  31. data/spec/fixtures/multiple_connections.txt +11 -0
  32. data/spec/lib/api/activation_spec.rb +30 -0
  33. data/spec/lib/api/authentication_spec.rb +29 -0
  34. data/spec/lib/api/billing_spec.rb +71 -0
  35. data/spec/lib/api/connect_spec.rb +40 -0
  36. data/spec/lib/api/connection_spec.rb +59 -0
  37. data/spec/lib/api/disconnect_spec.rb +40 -0
  38. data/spec/lib/openvpn_password_authenticator_spec.rb +52 -0
  39. data/spec/lib/option/base_spec.rb +26 -0
  40. data/spec/lib/option/i2p_spec.rb +19 -0
  41. data/spec/lib/option/proxy_spec.rb +32 -0
  42. data/spec/lib/option/repository_spec.rb +25 -0
  43. data/spec/lib/signer_spec.rb +21 -0
  44. data/spec/lib/system/openvpn_status_log_parser_spec.rb +25 -0
  45. data/spec/lib/system/openvpn_status_log_reader_spec.rb +33 -0
  46. data/spec/lib/system/openvpn_status_spec.rb +22 -0
  47. data/spec/spec_helper.rb +9 -0
  48. metadata +135 -0
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe Api::Disconnect do
4
+ subject { described_class.new }
5
+
6
+ describe '#invoke' do
7
+ before do
8
+ subject.stubs(:response).returns(
9
+ JSON.parse(
10
+ '{"id":101,"common_name":"login","options":["i2p", "proxy"],"option_attributes":{"i2p":{"attr1": "value1"},"proxy":{"attr2": "value2"}}}'
11
+ )
12
+ )
13
+ subject.stubs(:trigger_script_return)
14
+ subject.stubs(:success_api_call?).returns(api_call_validation_result)
15
+ end
16
+
17
+ context 'successfull script call' do
18
+ let(:api_call_validation_result) { true }
19
+
20
+ it 'activates options' do
21
+ Option::I2p.any_instance.expects(:deactivate!)
22
+ Option::Proxy.any_instance.expects(:deactivate!)
23
+ subject.invoke
24
+ end
25
+ end
26
+
27
+ context 'unsuccessfull call' do
28
+ let(:api_call_validation_result) { false }
29
+
30
+ it 'does not activate options' do
31
+ Option::I2p.any_instance.expects(:deactivate!).never
32
+ subject.invoke
33
+ end
34
+ end
35
+ end
36
+
37
+ it 'represents disconnect action' do
38
+ expect(subject.action).to eq 'disconnect'
39
+ end
40
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+ require 'tempfile'
3
+
4
+ describe OpenvpnPasswordAuthenticator do
5
+ let!(:args) { [path_to_file] }
6
+ let!(:file) { Tempfile.new('credentials') }
7
+ let(:path_to_file) { file.path }
8
+ let(:file_content) { "login\npassword" }
9
+ let(:api_adapter_class) { Api::Authentication }
10
+ subject { described_class.new(args, api_adapter_class) }
11
+
12
+ before do
13
+ file.write(file_content)
14
+ file.rewind
15
+ end
16
+
17
+ describe ".new" do
18
+ it "read file with credentials" do
19
+ File.expects(:read).with(path_to_file).returns(file_content)
20
+ subject
21
+ end
22
+
23
+ it "creates new adapter instance with credentials" do
24
+ api_adapter_class.expects(:new).with('login', 'password')
25
+ subject
26
+ end
27
+ end
28
+
29
+ describe ".authenticate" do
30
+ before do
31
+ subject.api.stubs(:valid_credentials?).returns(validation_result)
32
+ end
33
+
34
+ context "credentials valid" do
35
+ let(:validation_result) { true }
36
+
37
+ it "exits with 0 code" do
38
+ subject.expects(:exit).with(0)
39
+ subject.authenticate
40
+ end
41
+ end
42
+
43
+ context "credentials invaid" do
44
+ let(:validation_result) { false }
45
+
46
+ it "exits with 1 code" do
47
+ subject.expects(:exit).with(1)
48
+ subject.authenticate
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Option::Base do
4
+ subject { described_class }
5
+ let(:common_name) { "login" }
6
+ let(:attributes) { Hash[] }
7
+
8
+ describe 'activate' do
9
+ it 'creates instance of class and calls activate! on it' do
10
+ object = mock()
11
+ object.expects(:activate!)
12
+ subject.expects(:new).with(common_name, attributes).returns(object)
13
+ subject.activate(common_name, attributes)
14
+ end
15
+ end
16
+
17
+ describe 'deactivate' do
18
+ it 'creates instance of class and calls deactivate! on it' do
19
+ object = mock()
20
+ object.expects(:deactivate!)
21
+ subject.expects(:new).with(common_name, attributes).returns(object)
22
+ subject.deactivate(common_name, attributes)
23
+ end
24
+ end
25
+
26
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe Option::I2p do
4
+ subject { described_class.new('login', {}) }
5
+
6
+ describe '.activate' do
7
+ it 'adds firewall rules' do
8
+ subject.expects(:add_firewall_routes)
9
+ subject.activate!
10
+ end
11
+ end
12
+
13
+ describe '.deactivate' do
14
+ it 'removes firewall rules' do
15
+ subject.expects(:remove_firewall_routes)
16
+ subject.deactivate!
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe Option::Proxy do
4
+ subject { described_class.new(common_name, attributes) }
5
+ let(:common_name) { 'login' }
6
+ let(:attributes) { Hash[] }
7
+
8
+ describe '.activate!' do
9
+ it 'has attributes assigned' do
10
+ expect(subject.attributes).to eq attributes
11
+ end
12
+
13
+ it 'it starts proxy daemon and firewall rules' do
14
+ subject.expects(:start_proxy_daemon).returns(9090)
15
+ subject.expects(:add_firewall_rules).with(9090)
16
+ subject.activate!
17
+ end
18
+ end
19
+
20
+ describe '.deactivate!' do
21
+ it 'has attributes assigned' do
22
+ expect(subject.attributes).to eq attributes
23
+ end
24
+
25
+ it 'stops daemon, removes firewall rule and cleans relays list' do
26
+ Option::Proxy::RelayManager.any_instance.stubs(:free).with(anything).returns(9090)
27
+ subject.expects(:remove_firewall_rules).with(9090)
28
+ subject.expects(:kill_proxy_daemon).with(9090)
29
+ subject.deactivate!
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Option::Repository do
4
+ describe '.find_by_code' do
5
+ subject { described_class.find_by_code(option_code) }
6
+
7
+ context 'option exists' do
8
+ let(:option_code) { 'i2p' }
9
+
10
+ it 'returns option class by code' do
11
+ expect(subject).to eq Option::I2p
12
+ end
13
+ end
14
+
15
+ context 'option does not exist' do
16
+ let(:option_code) { 'some_option' }
17
+
18
+ it 'raises error' do
19
+ expect {
20
+ subject
21
+ }.to raise_error OptionNotFound
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Signer do
4
+ describe ".sign_hash" do
5
+ let(:hash) { Hash[a: "a", c: "c", b: "b"] }
6
+ let(:key) { "some_key" }
7
+ subject { described_class.sign_hash(hash, key) }
8
+
9
+ it "sorts hash by values" do
10
+ expect(subject).not_to eq Digest::MD5.hexdigest("#{hash.values.join}#{key}")
11
+ end
12
+
13
+ it "joins values" do
14
+ expect(subject).not_to eq Digest::MD5.hexdigest("#{hash.values.sort}#{key}")
15
+ end
16
+
17
+ it "appends key to values" do
18
+ expect(subject).not_to eq Digest::MD5.hexdigest("#{hash.values.sort.join}")
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe System::OpenvpnStatusLogParser do
4
+ describe '.new' do
5
+ subject { described_class }
6
+
7
+ it 'calls parse method' do
8
+ subject.any_instance.expects(:parse)
9
+ subject.new("")
10
+ end
11
+ end
12
+
13
+ describe 'parse' do
14
+ let(:contents) { File.read('spec/fixtures/multiple_connections.txt') }
15
+ subject { described_class.new(contents) }
16
+
17
+ it 'returns status' do
18
+ expect(subject.status.class).to eq System::OpenvpnStatus
19
+ end
20
+
21
+ it 'status includes all connected clients' do
22
+ expect(subject.status.clients_list.size).to eq 2
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe System::OpenvpnStatusLogReader do
4
+ let!(:file_contents) { File.read('spec/fixtures/active_connections.txt') }
5
+ let(:common_name) { "e0c187715fa9e1bb9fd96882dfa7af22" }
6
+ let(:path_to_log) { described_class::LOGFILE_PATH }
7
+
8
+ before { File.stubs(:read).with(path_to_log).returns(file_contents) }
9
+
10
+ describe '.vpn_ip' do
11
+ subject { described_class }
12
+
13
+ it 'creates new instance and vpn_ip_for on it' do
14
+ object = mock()
15
+ object.expects(:vpn_ip_for).with(common_name)
16
+ subject.expects(:new).returns(object)
17
+ subject.vpn_ip(common_name)
18
+ end
19
+ end
20
+
21
+ describe '.new' do
22
+ it 'reads logfile' do
23
+ object = described_class.new
24
+ expect(object.log_content).not_to be_nil
25
+ end
26
+ end
27
+
28
+ describe '.vpn_ip_for' do
29
+ it 'returns user virtual ip by common name' do
30
+ expect(described_class.vpn_ip(common_name)).to eq '10.77.2.6'
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe System::OpenvpnStatus do
4
+ subject { described_class.new }
5
+
6
+ describe '.current_virtual_address' do
7
+ let(:virtual_address) { '10.0.0.1' }
8
+ before { ENV['ifconfig_pool_remote_ip'] = virtual_address }
9
+
10
+ it 'returns ENV vars value' do
11
+ expect(described_class.current_virtual_address).to eq virtual_address
12
+ end
13
+ end
14
+
15
+ it 'clients list is a hash' do
16
+ expect(subject.clients_list.class).to eq Hash
17
+ end
18
+
19
+ it 'clients_list is empty' do
20
+ expect(subject.clients_list).to be_empty
21
+ end
22
+ end
@@ -0,0 +1,9 @@
1
+ require 'rspec/autorun'
2
+ require 'webmock/rspec'
3
+ require 'smartvpn-http-hooks'
4
+
5
+ RSpec.configure do |config|
6
+ config.mock_with :mocha
7
+ end
8
+
9
+
metadata ADDED
@@ -0,0 +1,135 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: smartvpn-http-hooks
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.7
5
+ platform: ruby
6
+ authors:
7
+ - Stanislav Mekhonoshin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-01-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: mocha
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: webmock
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Trigger on openvpn events and notify HTTP API
56
+ email: ejabberd@gmail.com
57
+ executables:
58
+ - smartvpn-activate
59
+ - smartvpn-authenticate
60
+ - smartvpn-connect
61
+ - smartvpn-disconnect
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - ".gitignore"
66
+ - ".rspec"
67
+ - Gemfile
68
+ - Gemfile.lock
69
+ - LICENSE
70
+ - README.md
71
+ - bin/smartvpn-activate
72
+ - bin/smartvpn-authenticate
73
+ - bin/smartvpn-connect
74
+ - bin/smartvpn-disconnect
75
+ - lib/api/activation.rb
76
+ - lib/api/authentication.rb
77
+ - lib/api/billing.rb
78
+ - lib/api/connect.rb
79
+ - lib/api/connection.rb
80
+ - lib/api/disconnect.rb
81
+ - lib/exceptions/option_not_found.rb
82
+ - lib/openvpn_password_authenticator.rb
83
+ - lib/option/base.rb
84
+ - lib/option/i2p.rb
85
+ - lib/option/proxy.rb
86
+ - lib/option/repository.rb
87
+ - lib/signer.rb
88
+ - lib/smartvpn-http-hooks.rb
89
+ - lib/system/openvpn_status.rb
90
+ - lib/system/openvpn_status_log_parser.rb
91
+ - lib/system/openvpn_status_log_reader.rb
92
+ - smartvpn-http-hooks.gemspec
93
+ - spec/fixtures/active_connections.txt
94
+ - spec/fixtures/multiple_connections.txt
95
+ - spec/lib/api/activation_spec.rb
96
+ - spec/lib/api/authentication_spec.rb
97
+ - spec/lib/api/billing_spec.rb
98
+ - spec/lib/api/connect_spec.rb
99
+ - spec/lib/api/connection_spec.rb
100
+ - spec/lib/api/disconnect_spec.rb
101
+ - spec/lib/openvpn_password_authenticator_spec.rb
102
+ - spec/lib/option/base_spec.rb
103
+ - spec/lib/option/i2p_spec.rb
104
+ - spec/lib/option/proxy_spec.rb
105
+ - spec/lib/option/repository_spec.rb
106
+ - spec/lib/signer_spec.rb
107
+ - spec/lib/system/openvpn_status_log_parser_spec.rb
108
+ - spec/lib/system/openvpn_status_log_reader_spec.rb
109
+ - spec/lib/system/openvpn_status_spec.rb
110
+ - spec/spec_helper.rb
111
+ homepage: https://github.com/Mehonoshin/smartvpn-http-hooks
112
+ licenses:
113
+ - MIT
114
+ metadata: {}
115
+ post_install_message:
116
+ rdoc_options: []
117
+ require_paths:
118
+ - lib
119
+ required_ruby_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ required_rubygems_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ requirements: []
130
+ rubyforge_project:
131
+ rubygems_version: 2.5.2
132
+ signing_key:
133
+ specification_version: 4
134
+ summary: HTTP hooks for OpenVPN server
135
+ test_files: []