pritunl_api_client 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 57de66a4a4b74e8312eeacb682b1ce8060736965
4
+ data.tar.gz: 10234f4f8f1bb0ba189516c3c0dec406d9ec5df5
5
+ SHA512:
6
+ metadata.gz: 5cf7ad74463442d38984f0c1bd1a4a3bf43f06edaa57a4b0631539a843cf44b40171206ef162f1cced53a9cd9a1fcec52a3095d1c427272e23ba02d21cc04525
7
+ data.tar.gz: 37b243f542fc76c9da1f5ed4e227ea5c78ef6091eb0220cbb47ea091493286c3492fcc42da6aab76ce6d4986b8992ce137860ca26d104eb618244e5542cd68f3
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in pritunl_api_client.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Eric Terry
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,518 @@
1
+ # Pritunl API Client
2
+
3
+ API client for Pritunl written in Ruby.
4
+
5
+ [Pritunl](https://github.com/pritunl/pritunl) is a distributed enterprise
6
+ vpn server built using the OpenVPN protocol. See the official Pritunl API
7
+ documentation here: https://pritunl.com/api.html. I am not affiliated with
8
+ Pritunl at all, but couldn't find a Ruby client for their API. So I scratched
9
+ my own itch and created it myself.
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ gem install pritunl_api_client
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ ```ruby
20
+ require 'pritunl_api_client'
21
+
22
+ @pritunl = PritunlApiClient::Client.new(
23
+ base_url: 'https://localhost:9700',
24
+ api_token: 'p7g444S3IZ5wmFvmzWmx14qACXdzQ25b',
25
+ api_secret: 'OpS9fjxkPI3DclkdKDDr6mqYVd0DJh4i',
26
+ verify_ssl: false
27
+ )
28
+ ```
29
+
30
+ ## Ping
31
+
32
+ ### Server healthcheck.
33
+
34
+ ```ruby
35
+ @pritunl.ping
36
+ ```
37
+
38
+ ## Status
39
+
40
+ ### Returns general information about the pritunl server.
41
+
42
+ ```ruby
43
+ @pritunl.status
44
+
45
+ {
46
+ "host_count" => 1,
47
+ "servers_online" => 1,
48
+ "hosts_online" => 1,
49
+ "server_count" => 2,
50
+ "server_version" => "1.11.813.26",
51
+ "public_ip" => "10.55.87.4",
52
+ "user_count" => 1,
53
+ "notification" => "",
54
+ "users_online" => 1,
55
+ "local_networks" => ["10.55.87.3/31", "10.2.214.0/31"],
56
+ "current_host" => "0f273a6c32ed45259c1ecb1ec3ac05ce",
57
+ "org_count" => 2
58
+ }
59
+ ```
60
+
61
+ ## Log
62
+
63
+ ### Returns a list of server log entries sorted by time.
64
+
65
+ ```ruby
66
+ @pritunl.log
67
+
68
+ [
69
+ {
70
+ "timestamp" => 1450429682,
71
+ "message" => "Deleted organization 'org1'.",
72
+ "id" => "567386a32221390ea53d8047"
73
+ },
74
+ {
75
+ "timestamp" => 1450429682,
76
+ "message" => "Deleted user 'user1'.",
77
+ "id" => "567386a32221390ea53d8045"
78
+ },
79
+ {
80
+ "timestamp" => 1450429681,
81
+ "message" => "Enabled user 'user2'.",
82
+ "id" => "567386a22221390ea53d8042"
83
+ }
84
+ ]
85
+ ```
86
+
87
+ ## Events
88
+
89
+ ### Get a list of events (will poll up to 30 seconds)
90
+
91
+ ```ruby
92
+ @pritunl.event( cursor: '55e9f1f1b0e730245677dc31' )
93
+
94
+ [
95
+ {
96
+ "id" => "55e9f1f1b0e730245677dc31",
97
+ "type" => "users_updated",
98
+ "timestamp" => 1388495793,
99
+ "resource_id" => "55e9f1f8b0e730245677dc34"
100
+ },
101
+ {
102
+ "id" => "55e9f1f2b0e730245677dc32",
103
+ "type" => "server_organizations_updated",
104
+ "timestamp" => 1388495805,
105
+ "resource_id" => "55e9f1f8b0e730245677dc33"
106
+ }
107
+ ]
108
+ ```
109
+
110
+ ## Settings
111
+
112
+ ### Get system settings.
113
+
114
+ ```ruby
115
+ @pritunl.settings.all
116
+
117
+ {
118
+ "username" => "user6",
119
+ "sso_admin" => nil,
120
+ "theme" => "dark",
121
+ "sso" => nil,
122
+ "sso_match" => nil,
123
+ "server_cert" => "-----BEGIN CERTIFICATE----------END CERTIFICATE-----",
124
+ "public_address" => "10.5.8.46",
125
+ "routed_subnet6" => nil,
126
+ "email_username" => "user1",
127
+ "sso_saml_issuer_url" => nil,
128
+ "sso_saml_cert" => nil,
129
+ "sso_token" => nil,
130
+ "email_password" => true,
131
+ "sso_onelogin_key" => nil,
132
+ "email_server" => "smtp.example.com",
133
+ "auditing" => nil,
134
+ "sso_secret" => nil,
135
+ "server_key" => "-----BEGIN PRIVATE KEY----------END PRIVATE KEY-----",
136
+ "default" => nil,
137
+ "sso_host" => nil,
138
+ "public_address6" => "2605:1480:2:a210::1",
139
+ "secret" => "9D1ZJTscrr2mK4Xnxw76ltmpwnH7udeO",
140
+ "sso_okta_token" => nil,
141
+ "sso_saml_url" => nil,
142
+ "token" => "UQRM0R3bsXDpy3p6nqtjfrbjujSadaAx",
143
+ "sso_org" => nil,
144
+ "email_from" => "first.last@example.com"
145
+ }
146
+ ```
147
+
148
+ ### Change the system settings.
149
+
150
+ ```ruby
151
+ @pritunl.settings.update( theme: 'dark' )
152
+
153
+ @pritunl.settings.update(
154
+ email_username: 'user1',
155
+ email_password: '12345',
156
+ email_server: 'smtp.example.com',
157
+ email_from: 'first.last@example.com'
158
+ )
159
+ ```
160
+
161
+ ## Users
162
+
163
+ ### Returns a list of users in an organization sorted by name.
164
+
165
+ ```ruby
166
+ @pritunl.user.all( organization_id: org['id'] )
167
+
168
+ [
169
+ {
170
+ "auth_type" => "local",
171
+ "status" => false,
172
+ "dns_servers" => nil,
173
+ "otp_secret" => "OPT4HTURJTW6JLQN",
174
+ "dns_mapping" => nil,
175
+ "dns_suffix" => nil,
176
+ "servers" => [
177
+ {
178
+ "status" => false,
179
+ "platform" => nil,
180
+ "server_id" => "567369be2231390ea53d76d4",
181
+ "local_address" => "10.139.82.6",
182
+ "remote_address" => "10.139.82.7",
183
+ "virt_address6" => "fd00:c0a8:e800:0:10.139.82.6",
184
+ "virt_address" => "10.139.82.6",
185
+ "name" => "server1",
186
+ "real_address" => "8.8.8.8:41536",
187
+ "connected_since" => 1388498640,
188
+ "id" => "55e9f995b0e73033d45b44da",
189
+ "device_name" => nil
190
+ }
191
+ ],
192
+ "disabled" => false,
193
+ "network_links" => [],
194
+ "sso" => nil,
195
+ "bypass_secondary" => false,
196
+ "id" => "55e9f98cb0e73033d45b44d7",
197
+ "audit" => false,
198
+ "name" => "user0",
199
+ "organization_name" => "org1",
200
+ "gravatar" => true,
201
+ "otp_auth" => false,
202
+ "organization" => "55e9f7c7b0e73033d45b44d4",
203
+ "type" => "client",
204
+ "email" => "user0@example.com"
205
+ }
206
+ ]
207
+ ```
208
+
209
+ ### Returns a user from an organization.
210
+
211
+ ```ruby
212
+ @pritunl.user.find( user['id'], organization_id: org['id'] )
213
+
214
+ {
215
+ "auth_type" => "local",
216
+ "dns_servers" => nil,
217
+ "otp_secret" => "OPT4HTURJTW6JLQN",
218
+ "dns_suffix" => nil,
219
+ "disabled" => true,
220
+ "bypass_secondary" => false,
221
+ "id" => "55e9f98cb0e73033d45b44d7",
222
+ "name" => "user0",
223
+ "organization_name" => "org1",
224
+ "organization" => "55e9f7c7b0e73033d45b44d4",
225
+ "type" => "client",
226
+ "email" => "user0@example.com"
227
+ }
228
+ ```
229
+
230
+ ### Create a new user in an organization. An array of users can be sent for bulk adding users.
231
+
232
+ ```ruby
233
+ @pritunl.user.create(
234
+ organization_id: org['id'],
235
+ name: 'new_user',
236
+ email: 'new_user@example.com',
237
+ disabled: true
238
+ )
239
+ ```
240
+
241
+ ### Rename or disabled an existing user in an organization. Disabling will also disconnect the user.
242
+
243
+ ```ruby
244
+ @pritunl.user.update( user['id'],
245
+ organization_id: org['id'],
246
+ name: 'new_name',
247
+ email: 'new_email@example.com',
248
+ disabled: false
249
+ )
250
+ ```
251
+
252
+ ### Delete an existing user in an organization, this will disconnect the user.
253
+
254
+ ```ruby
255
+ @pritunl.user.delete( user['id'], organization_id: org['id'] )
256
+ ```
257
+
258
+ ### Generate a new two-step authentication secret for an existing user.
259
+
260
+ ```ruby
261
+ @pritunl.user.otp_secret( user['id'], organization_id: org['id'] )
262
+ ```
263
+
264
+ ## Organizations
265
+
266
+ ### Returns a list of organizations on the server sorted by name.
267
+
268
+ ```ruby
269
+ @pritunl.organization.all
270
+
271
+ [
272
+ {
273
+ "user_count" => 512,
274
+ "id" => "55e99499b0e7300fef77e2b1",
275
+ "name" => "org1"
276
+ },
277
+ {
278
+ "user_count" => 1024,
279
+ "id" => "55e9f1d4b0e730245677dc2d",
280
+ "name" => "org2"
281
+ }
282
+ ]
283
+ ```
284
+
285
+ ### Returns an organization.
286
+
287
+ ```ruby
288
+ @pritunl.organization.find( org['id'] )
289
+
290
+ {
291
+ "user_count" => 512,
292
+ "id" => "55e99499b0e7300fef77e2b1",
293
+ "name" => "org1"
294
+ }
295
+ ```
296
+
297
+ ### Create a new organization.
298
+
299
+ ```ruby
300
+ @pritunl.organization.create( name: 'new_org' )
301
+ ```
302
+
303
+ ### Rename an existing organization.
304
+
305
+ ```ruby
306
+ @pritunl.organization.update( org['id'], name: 'new_name' )
307
+ ```
308
+
309
+ ### Delete an existing organization.
310
+
311
+ ```ruby
312
+ @pritunl.organization.delete( org['id'] )
313
+ ```
314
+
315
+ ## Keys
316
+
317
+ ### Download a users key tar archive.
318
+
319
+ ```ruby
320
+ @pritunl.key.download_tar( organization_id: org['id'], user_id: user['id'], path: 'output.tar' )
321
+ ```
322
+
323
+ ### Download a users onc key zip archive.
324
+
325
+ ```ruby
326
+ @pritunl.key.download_zip( organization_id: org['id'], user_id: user['id'], path: 'output.zip' )
327
+ ```
328
+
329
+ ### Generate a temporary url to download a users key archive.
330
+
331
+ ```ruby
332
+ @pritunl.key.temporary_url( organization_id: org['id'], user_id: user['id'] )
333
+
334
+ {
335
+ "view_url" => "/k/MjyaVvGk",
336
+ "key_url" => "/key/4f5bd04d85414e20b0a451d642dab06d.tar",
337
+ "uri_url" => "/ku/MjyaVvGk",
338
+ "key_zip_url" => "/key/4f5bd04d85414e20b0a451d642dab06d.zip",
339
+ "key_onc_url" => "/key_onc/4f5bd04d85414e20b0a451d642dab06d.zip",
340
+ "id" => "4f5bd04d85414e20b0a451d642dab06d"
341
+ }
342
+ ```
343
+
344
+ ## Servers
345
+
346
+ ### Returns a list of servers.
347
+
348
+ ```ruby
349
+ @pritunl.server.all
350
+ ```
351
+
352
+ ### Returns a server.
353
+
354
+ ```ruby
355
+ @pritunl.server.find( server['id'] )
356
+
357
+ {
358
+ "status" => "pending",
359
+ "lzo_compression" => false,
360
+ "dns_servers" => ["8.8.4.4"],
361
+ "protocol" => "udp",
362
+ "ping_interval" => 10,
363
+ "dns_mapping" => false,
364
+ "network_mode" => "tunnel",
365
+ "debug" => false,
366
+ "network_end" => nil,
367
+ "bind_address" => nil,
368
+ "link_ping_interval" => 1,
369
+ "hash" => "sha1",
370
+ "ipv6_firewall" => true,
371
+ "inter_client" => true,
372
+ "id" => "5678d5286231390ea53eda96",
373
+ "network_start" => nil,
374
+ "network" => "10.11.6.0/24",
375
+ "local_networks" => [],
376
+ "uptime" => nil,
377
+ "user_count" => 0,
378
+ "name" => "server1",
379
+ "dh_param_bits" => 2048,
380
+ "max_clients" => 2048,
381
+ "users_online" => 0,
382
+ "replica_count" => 1,
383
+ "link_ping_timeout" => 5,
384
+ "port" => 12533,
385
+ "devices_online" => 0,
386
+ "ping_timeout" => 60,
387
+ "mode" => "all_traffic",
388
+ "ipv6" => false,
389
+ "otp_auth" => false,
390
+ "jumbo_frames" => false,
391
+ "multi_device" => false,
392
+ "search_domain" => "example.com",
393
+ "cipher" => "aes256"
394
+ }
395
+ ```
396
+
397
+ ### Create a new server.
398
+
399
+ ```ruby
400
+ @pritunl.server.create(
401
+ name: 'server1',
402
+ network: '10.11.6.0/24',
403
+ bind_address: nil,
404
+ port: 12533,
405
+ protocol: 'udp',
406
+ dh_param_bits: 2048,
407
+ mode: 'all_traffic',
408
+ network_mode: 'tunnel',
409
+ network_start: nil,
410
+ network_end: nil,
411
+ multi_device: false,
412
+ local_networks: [],
413
+ dns_servers: ['8.8.4.4'],
414
+ search_domain: 'pritunl.com',
415
+ otp_auth: false,
416
+ cipher: 'aes256',
417
+ jumbo_frames: false,
418
+ lzo_compression: false,
419
+ inter_client: true,
420
+ ping_interval: 10,
421
+ ping_timeout: 60,
422
+ max_clients: 2048,
423
+ replica_count: 1,
424
+ debug: false
425
+ )
426
+ ```
427
+
428
+ ### Update an existing server.
429
+
430
+ ```ruby
431
+ @pritunl.server.update( server['id'], name: 'server1-rename', dns_servers: ['8.8.8.8', '8.8.4.4'] )
432
+ ```
433
+
434
+ ### Delete an existing server.
435
+
436
+ ```ruby
437
+ @pritunl.server.delete( server['id'] )
438
+ ```
439
+
440
+ ### Start, stop or restart an existing server.
441
+
442
+ ```ruby
443
+ @pritunl.server.start( server['id'] )
444
+ @pritunl.server.stop( server['id'] )
445
+ @pritunl.server.restart( server['id'] )
446
+ ```
447
+
448
+ ### Returns a list of organizations attached to a server.
449
+
450
+ ```ruby
451
+ @pritunl.server.organizations( server['id'] )
452
+
453
+ [
454
+ {
455
+ "id" => "5678d0f48831390da53ef8ae",
456
+ "name" => "org1",
457
+ "server" => "5678d5286231390ea53eda96"
458
+ },
459
+ {
460
+ "id" => "5678d0f48831392ba71ad3cb",
461
+ "name" => "org2",
462
+ "server" => "5678d5286231390ea53eda96"
463
+ }
464
+ ]
465
+ ```
466
+
467
+ ### Attach an organization to an existing server.
468
+
469
+ ```ruby
470
+ @pritunl.server.attach_organization( server['id'], organization_id: org['id'] )
471
+
472
+ {
473
+ "id" => "5678d0f48831390da53ef8ae",
474
+ "name" => "org1",
475
+ "server" => "5678d5286231390ea53eda96"
476
+ }
477
+ ```
478
+
479
+ ### Remove an organization from an existing server.
480
+
481
+ ```ruby
482
+ @pritunl.server.remove_organization( server['id'], organization_id: org['id'] )
483
+ ```
484
+
485
+ ### Get the output of a server.
486
+
487
+ ```ruby
488
+ @pritunl.server.output( server['id'] )
489
+
490
+ {
491
+ "id" => "5678d5286231390ea53eda96",
492
+ "output" => [
493
+ "[patient-forest-4024] Mon Dec 21 23:45:15 2015 OpenVPN 2.3.2 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [EPOLL] [PKCS11] [eurephia] [MH] [IPv6] built on Dec 1 2014",
494
+ "[patient-forest-4024] Mon Dec 21 23:45:15 2015 Control Channel Authentication: tls-auth using INLINE static key file",
495
+ "[patient-forest-4024] Mon Dec 21 23:45:15 2015 TUN/TAP device tun11 opened",
496
+ "[patient-forest-4024] Mon Dec 21 23:45:15 2015 do_ifconfig, tt->ipv6=0, tt->did_ifconfig_ipv6_setup=0",
497
+ "[patient-forest-4024] Mon Dec 21 23:45:15 2015 /sbin/ip link set dev tun11 up mtu 1500",
498
+ "[patient-forest-4024] Mon Dec 21 23:45:15 2015 /sbin/ip addr add dev tun11 10.11.6.1/24 broadcast 10.11.6.255",
499
+ "[patient-forest-4024] Mon Dec 21 23:45:15 2015 UDPv4 link local (bound): [undef]",
500
+ "[patient-forest-4024] Mon Dec 21 23:45:15 2015 UDPv4 link remote: [undef]",
501
+ "[patient-forest-4024] Mon Dec 21 23:45:15 2015 Initialization Sequence Completed"
502
+ ]
503
+ }
504
+ ```
505
+
506
+ ### Clear the output of a server.
507
+
508
+ ```ruby
509
+ @pritunl.server.clear_output( server['id'] )
510
+ ```
511
+
512
+ ## Contributing
513
+
514
+ Bug reports and pull requests are welcome on GitHub at https://github.com/eterry1388/pritunl_api_client.
515
+
516
+ ## License
517
+
518
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new( :spec )
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'pritunl_api_client'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require 'pry'
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,103 @@
1
+ require_relative 'pritunl_api_client/api'
2
+ require_relative 'pritunl_api_client/settings'
3
+ require_relative 'pritunl_api_client/organization'
4
+ require_relative 'pritunl_api_client/user'
5
+ require_relative 'pritunl_api_client/key'
6
+ require_relative 'pritunl_api_client/server'
7
+
8
+ # API client for Pritunl. Pritunl is a distributed enterprise vpn server built
9
+ # using the OpenVPN protocol. See the official Pritunl API documentation here:
10
+ # https://pritunl.com/api.html. I am not affiliated with Pritunl at all, but
11
+ # couldn't find a Ruby client for their API. So I scratched my own itch and
12
+ # created it myself.
13
+ #
14
+ # @author {mailto:eterry1388@aol.com Eric Terry}
15
+ # @see https://github.com/eterry1388/pritunl_api_client
16
+ module PritunlApiClient
17
+
18
+ # Main interface to the Pritunl api
19
+ class Client
20
+
21
+ # @param base_url [String] Full URL to a running Pritunl server (include the "https://")
22
+ # @param api_token [String
23
+ # @param api_secret [String]
24
+ # @param verify_ssl [Boolean] Whether or not to verify SSL certificate
25
+ def initialize( base_url:, api_token:, api_secret:, verify_ssl: true )
26
+ @base_url = base_url
27
+ @api_token = api_token
28
+ @api_secret = api_secret
29
+ @verify_ssl = verify_ssl
30
+ @api = Api.new( base_url: base_url, api_token: api_token, api_secret: api_secret, verify_ssl: verify_ssl )
31
+ end
32
+
33
+ # Get a list of events (will poll up to 30 seconds)
34
+ #
35
+ # @param cursor [String, NilClass] Optional id of last event. If left out, only events
36
+ # that occurred after request is sent will be returned.
37
+ # @return [Array]
38
+ def event( cursor: nil )
39
+ @api.get( "/event/#{cursor}" )
40
+ end
41
+
42
+ # Server healthcheck
43
+ #
44
+ # @return [Boolean]
45
+ def ping
46
+ begin
47
+ @api.get( '/ping' ) == ''
48
+ rescue
49
+ false
50
+ end
51
+ end
52
+
53
+ # Returns general information about the pritunl server
54
+ #
55
+ # @return [Hash]
56
+ def status
57
+ @api.get( '/status' )
58
+ end
59
+
60
+ # Returns a list of server log entries
61
+ #
62
+ # @return [Array]
63
+ def log
64
+ @api.get( '/log' )
65
+ end
66
+
67
+ # Setting apis
68
+ #
69
+ # @return [PritunlApiClient::Settings]
70
+ def settings
71
+ @settings ||= Settings.new( @api )
72
+ end
73
+
74
+ # Organization apis
75
+ #
76
+ # @return [PritunlApiClient::Organization]
77
+ def organization
78
+ @organization ||= Organization.new( @api )
79
+ end
80
+
81
+ # User apis
82
+ #
83
+ # @return [PritunlApiClient::User]
84
+ def user
85
+ @user ||= User.new( @api )
86
+ end
87
+
88
+ # Key apis
89
+ #
90
+ # @return [PritunlApiClient::Key]
91
+ def key
92
+ @key ||= Key.new( @api )
93
+ end
94
+
95
+ # Server apis
96
+ #
97
+ # @return [PritunlApiClient::Server]
98
+ def server
99
+ @server ||= Server.new( @api )
100
+ end
101
+
102
+ end
103
+ end
@@ -0,0 +1,121 @@
1
+ require 'rest-client'
2
+ require 'securerandom'
3
+ require 'base64'
4
+ require 'json'
5
+
6
+ module PritunlApiClient
7
+
8
+ # Low-level communication to api server
9
+ class Api
10
+
11
+ # @param base_url [String] Full URL to a running Pritunl server (include the "https://")
12
+ # @param api_token [String
13
+ # @param api_secret [String]
14
+ # @param verify_ssl [Boolean] Whether or not to verify SSL certificate]
15
+ def initialize( base_url:, api_token:, api_secret:, verify_ssl: true )
16
+ @api_token = api_token
17
+ @api_secret = api_secret
18
+ @client = RestClient::Resource.new( base_url, verify_ssl: verify_ssl )
19
+ end
20
+
21
+ # Send post request to api server
22
+ #
23
+ # @param path [String] URL path of api
24
+ # @param params [Hash, NilClass] Api parameters
25
+ # @return [Hash, Array, String] Response from api server
26
+ def post( path, params = nil )
27
+ headers = common_headers.merge( generate_auth_headers( path: path, params: params, method: 'POST' ) )
28
+ params = JSON.generate( params, space: ' ' ) if params
29
+ parse_data @client[path].post( params, headers )
30
+ end
31
+
32
+ # Send get request to api server
33
+ #
34
+ # @param path [String] URL path of api
35
+ # @param params [Hash, NilClass] Api parameters
36
+ # @return [Hash, Array, String] Response from api server
37
+ def get( path, params = nil )
38
+ parameters = { params: params }
39
+ parameters.merge!( common_headers )
40
+ parameters.merge!( generate_auth_headers( path: path, params: params, method: 'GET' ) )
41
+ parse_data @client[path].get( parameters )
42
+ end
43
+
44
+ # Send put request to api server
45
+ #
46
+ # @param path [String] URL path of api
47
+ # @param params [Hash, NilClass] Api parameters
48
+ # @return [Hash, Array, String] Response from api server
49
+ def put( path, params = nil )
50
+ headers = common_headers.merge( generate_auth_headers( path: path, params: params, method: 'PUT' ) )
51
+ params = JSON.generate( params, space: ' ' ) if params
52
+ parse_data @client[path].put( params, headers )
53
+ end
54
+
55
+ # Send delete request to api server
56
+ #
57
+ # @param path [String] URL path of api
58
+ # @param params [Hash, NilClass] Api parameters
59
+ # @return [Hash, Array, String] Response from api server
60
+ def delete( path, params = nil )
61
+ parameters = { params: params }
62
+ parameters.merge!( common_headers )
63
+ parameters.merge!( generate_auth_headers( path: path, params: params, method: 'DELETE' ) )
64
+ parse_data @client[path].delete( parameters )
65
+ end
66
+
67
+ # Send head request to api server
68
+ #
69
+ # @param path [String] URL path of api
70
+ # @param params [Hash, NilClass] Api parameters
71
+ # @return [Hash, Array, String] Response from api server
72
+ def head( path, params = nil )
73
+ headers = common_headers.merge( generate_auth_headers( path: path, params: params, method: 'HEAD' ) )
74
+ params = JSON.generate( params, space: ' ' ) if params
75
+ parse_data @client[path].head( params, headers )
76
+ end
77
+
78
+ private
79
+
80
+ # Common headers to add to every request
81
+ #
82
+ # @return [Hash]
83
+ def common_headers
84
+ { content_type: :json, accept: :json }
85
+ end
86
+
87
+ # Authentication algorithm that is included in every request
88
+ #
89
+ # @param path [String] URL path of api
90
+ # @param params [Hash, NilClass] Api parameters
91
+ # @param method [String] Uppercase method for the request
92
+ # @return [Hash]
93
+ def generate_auth_headers( path:, params: nil, method: )
94
+ auth_timestamp = Time.now.to_i
95
+ auth_nonce = SecureRandom.hex( 16 )
96
+ auth_string = [@api_token, auth_timestamp, auth_nonce, method, path]
97
+ auth_string << JSON.generate( params, space: ' ' ) if params
98
+ auth_string = auth_string.join( '&' )
99
+ digest = OpenSSL::Digest.new( 'sha256' )
100
+ hmac = OpenSSL::HMAC.digest( digest, @api_secret, auth_string )
101
+ auth_signature = Base64.encode64( hmac ).chomp
102
+ {
103
+ auth_token: @api_token,
104
+ auth_timestamp: auth_timestamp,
105
+ auth_nonce: auth_nonce,
106
+ auth_signature: auth_signature
107
+ }
108
+ end
109
+
110
+ # Parse responses back from api server
111
+ #
112
+ # @param data [String]
113
+ # @return [Hash, Array, String]
114
+ def parse_data( data )
115
+ JSON.parse( data )
116
+ rescue JSON::ParserError => e
117
+ data
118
+ end
119
+
120
+ end
121
+ end
@@ -0,0 +1,45 @@
1
+ module PritunlApiClient
2
+
3
+ # Interact with /key api's
4
+ class Key
5
+
6
+ # @param api [PritunlApiClient::Api]
7
+ def initialize( api )
8
+ @api = api
9
+ end
10
+
11
+ # Download a users key tar archive
12
+ #
13
+ # @param organization_id [String]
14
+ # @param user_id [String]
15
+ # @param path [String] Local path to save downloaded file
16
+ # @return [String] Local path to downloaded file
17
+ def download_tar( organization_id:, user_id:, path: )
18
+ data = @api.get( "/key/#{organization_id}/#{user_id}.tar" )
19
+ File.write( path, data )
20
+ path
21
+ end
22
+
23
+ # Download a users onc key zip archive
24
+ #
25
+ # @param organization_id [String]
26
+ # @param user_id [String]
27
+ # @param path [String] Local path to save downloaded file
28
+ # @return [String] Local path to downloaded file
29
+ def download_zip( organization_id:, user_id:, path: )
30
+ data = @api.get( "/key_onc/#{organization_id}/#{user_id}.zip" )
31
+ File.write( path, data )
32
+ path
33
+ end
34
+
35
+ # Generate a temporary url to download a users key archive
36
+ #
37
+ # @param organization_id [String]
38
+ # @param user_id [String]
39
+ # @return [Hash]
40
+ def temporary_url( organization_id:, user_id: )
41
+ @api.get( "/key/#{organization_id}/#{user_id}" )
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,55 @@
1
+ module PritunlApiClient
2
+
3
+ # Interact with /organization api's
4
+ class Organization
5
+
6
+ # @param api [PritunlApiClient::Api]
7
+ def initialize( api )
8
+ @api = api
9
+ end
10
+
11
+ # Returns a list of organizations on the server
12
+ #
13
+ # @return [Array]
14
+ def all
15
+ @api.get( '/organization' )
16
+ end
17
+
18
+ # Returns an organization
19
+ #
20
+ # @param id [String] Organization ID
21
+ # @return [Hash]
22
+ def find( id )
23
+ @api.get( "/organization/#{id}" )
24
+ end
25
+
26
+ # Create a new organization
27
+ #
28
+ # @param params [Hash]
29
+ # @raise [ArgumentError] if params is not a Hash
30
+ # @return [Hash]
31
+ def create( params )
32
+ fail ArgumentError, 'params must be a Hash' unless params.is_a? Hash
33
+ @api.post( '/organization', params )
34
+ end
35
+
36
+ # Modify an existing organization
37
+ #
38
+ # @param id [String] Organization ID
39
+ # @param params [Hash]
40
+ # @raise [ArgumentError] if params is not a Hash
41
+ # @return [Hash]
42
+ def update( id, params )
43
+ fail ArgumentError, 'params must be a Hash' unless params.is_a? Hash
44
+ @api.put( "/organization/#{id}", params )
45
+ end
46
+
47
+ # Delete an existing organization
48
+ #
49
+ # @param id [String] Organization ID
50
+ def delete( id )
51
+ @api.delete( "/organization/#{id}" )
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,117 @@
1
+ module PritunlApiClient
2
+
3
+ # Interact with /server api's
4
+ class Server
5
+
6
+ # @param api [PritunlApiClient::Api]
7
+ def initialize( api )
8
+ @api = api
9
+ end
10
+
11
+ # Returns a list of servers
12
+ #
13
+ # @return [Array]
14
+ def all
15
+ @api.get( '/server' )
16
+ end
17
+
18
+ # Returns a server
19
+ #
20
+ # @param id [String] Server ID
21
+ # @return [Hash]
22
+ def find( id )
23
+ @api.get( "/server/#{id}" )
24
+ end
25
+
26
+ # Create a new server
27
+ #
28
+ # @param params [Hash]
29
+ # @raise [ArgumentError] if params is not a Hash
30
+ # @return [Hash]
31
+ def create( params )
32
+ fail ArgumentError, 'params must be a Hash' unless params.is_a? Hash
33
+ @api.post( '/server', params )
34
+ end
35
+
36
+ # Update an existing server
37
+ #
38
+ # @param id [String] Server ID
39
+ # @param params [Hash]
40
+ # @raise [ArgumentError] if params is not a Hash
41
+ # @return [Hash]
42
+ def update( id, params )
43
+ fail ArgumentError, 'params must be a Hash' unless params.is_a? Hash
44
+ @api.put( "/server/#{id}", params )
45
+ end
46
+
47
+ # Delete an existing server
48
+ #
49
+ # @param id [String] Server ID
50
+ def delete( id )
51
+ @api.delete( "/server/#{id}" )
52
+ end
53
+
54
+ # Start an existing server
55
+ #
56
+ # @param id [String] Server ID
57
+ # @return [Hash]
58
+ def start( id )
59
+ @api.put( "/server/#{id}/start" )
60
+ end
61
+
62
+ # Stop an existing server
63
+ #
64
+ # @param id [String] Server ID
65
+ # @return [Hash]
66
+ def stop( id )
67
+ @api.put( "/server/#{id}/stop" )
68
+ end
69
+
70
+ # Restart an existing server
71
+ #
72
+ # @param id [String] Server ID
73
+ # @return [Hash]
74
+ def restart( id )
75
+ @api.put( "/server/#{id}/restart" )
76
+ end
77
+
78
+ # Returns a list of organizations attached to a server
79
+ #
80
+ # @param id [String] Server ID
81
+ # @return [Array]
82
+ def organizations( id )
83
+ @api.get( "/server/#{id}/organization" )
84
+ end
85
+
86
+ # Attach an organization to an existing server
87
+ #
88
+ # @param id [String] Server ID
89
+ # @return [Hash]
90
+ def attach_organization( id, organization_id: )
91
+ @api.put( "/server/#{id}/organization/#{organization_id}" )
92
+ end
93
+
94
+ # Remove an organization from an existing server
95
+ #
96
+ # @param id [String] Server ID
97
+ def remove_organization( id, organization_id: )
98
+ @api.delete( "/server/#{id}/organization/#{organization_id}" )
99
+ end
100
+
101
+ # Get the output of a server
102
+ #
103
+ # @param id [String] Server ID
104
+ # @return [Hash]
105
+ def output( id )
106
+ @api.get( "/server/#{id}/output" )
107
+ end
108
+
109
+ # Clear the output of a server
110
+ #
111
+ # @param id [String] Server ID
112
+ def clear_output( id )
113
+ @api.delete( "/server/#{id}/output" )
114
+ end
115
+
116
+ end
117
+ end
@@ -0,0 +1,29 @@
1
+ module PritunlApiClient
2
+
3
+ # Interact with /settings api's
4
+ class Settings
5
+
6
+ # @param api [PritunlApiClient::Api]
7
+ def initialize( api )
8
+ @api = api
9
+ end
10
+
11
+ # Get system settings
12
+ #
13
+ # @return [Array]
14
+ def all
15
+ @api.get( '/settings' )
16
+ end
17
+
18
+ # Change the system settings
19
+ #
20
+ # @param params [Hash]
21
+ # @raise [ArgumentError] if params is not a Hash
22
+ # @return [Hash]
23
+ def update( params )
24
+ fail ArgumentError, 'params must be a Hash' unless params.is_a? Hash
25
+ @api.put( '/settings', params )
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,73 @@
1
+ module PritunlApiClient
2
+
3
+ # Interact with /user api's
4
+ class User
5
+
6
+ # @param api [PritunlApiClient::Api]
7
+ def initialize( api )
8
+ @api = api
9
+ end
10
+
11
+ # Returns a list of users in an organization
12
+ #
13
+ # @param organization_id [String]
14
+ # @return [Array]
15
+ def all( organization_id: )
16
+ @api.get( "/user/#{organization_id}" )
17
+ end
18
+
19
+ # Returns a user from an organization
20
+ #
21
+ # @param id [String] User ID
22
+ # @param organization_id [String]
23
+ # @return [Hash]
24
+ def find( id, organization_id: )
25
+ @api.get( "/user/#{organization_id}/#{id}" )
26
+ end
27
+
28
+ # Create a new user in an organization. An array of users can be sent for bulk adding users
29
+ #
30
+ # @param params [Hash, Array]
31
+ # @raise [ArgumentError] if params is not a Hash or an Array
32
+ # @raise [ArgumentError] if organization_id is not passed into the parameter list
33
+ # @return [Hash, Array]
34
+ def create( params )
35
+ fail ArgumentError, 'params must be a Hash or an Array' unless ( params.is_a?( Hash ) || params.is_a?( Array ) )
36
+ fail ArgumentError, '"organization_id" is a required parameter' unless params.keys.include? :organization_id
37
+ organization_id = params.delete( :organization_id )
38
+ @api.post( "/user/#{organization_id}", params )
39
+ end
40
+
41
+ # Update an existing user in an organization
42
+ #
43
+ # @param id [String] User ID
44
+ # @param params [Hash]
45
+ # @raise [ArgumentError] if params is not a Hash
46
+ # @raise [ArgumentError] if organization_id is not passed into the parameter list
47
+ # @return [Hash]
48
+ def update( id, params )
49
+ fail ArgumentError, 'params must be a Hash' unless params.is_a? Hash
50
+ fail ArgumentError, '"organization_id" is a required parameter' unless params.keys.include? :organization_id
51
+ organization_id = params.delete( :organization_id )
52
+ @api.put( "/user/#{organization_id}/#{id}", params )
53
+ end
54
+
55
+ # Delete an existing user in an organization, this will disconnect the user
56
+ #
57
+ # @param id [String] User ID
58
+ # @param organization_id [String]
59
+ def delete( id, organization_id: )
60
+ @api.delete( "/user/#{organization_id}/#{id}" )
61
+ end
62
+
63
+ # Generate a new two-step authentication secret for an existing user
64
+ #
65
+ # @param id [String] User ID
66
+ # @param organization_id [String]
67
+ # @return [Hash]
68
+ def otp_secret( id, organization_id: )
69
+ @api.put( "/user/#{organization_id}/#{id}/otp_secret" )
70
+ end
71
+
72
+ end
73
+ end
@@ -0,0 +1,3 @@
1
+ module PritunlApiClient
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path( '../lib', __FILE__ )
3
+ $LOAD_PATH.unshift( lib ) unless $LOAD_PATH.include?( lib )
4
+ require 'pritunl_api_client/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'pritunl_api_client'
8
+ spec.version = PritunlApiClient::VERSION
9
+ spec.authors = ['Eric Terry']
10
+ spec.email = ['eterry1388@aol.com']
11
+
12
+ spec.summary = 'Pritunl Ruby API Client'
13
+ spec.description = 'API client for Pritunl written in Ruby'
14
+ spec.homepage = 'http://eterry1388.github.io/pritunl_api_client'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split( "\x0" ).reject { |f| f.match( %r{^(test|spec|features)/} ) }
18
+ spec.executables = spec.files.grep( %r{^bin/} ) { |f| File.basename( f ) }
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.required_ruby_version = '>= 2.1.0'
22
+
23
+ spec.add_dependency 'rest-client'
24
+
25
+ spec.add_development_dependency 'bundler', '~> 1.10'
26
+ spec.add_development_dependency 'rake', '~> 10.0'
27
+ spec.add_development_dependency 'rspec', '~> 3.3'
28
+ end
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pritunl_api_client
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Eric Terry
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-12-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rest-client
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
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: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.10'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.10'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.3'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.3'
69
+ description: API client for Pritunl written in Ruby
70
+ email:
71
+ - eterry1388@aol.com
72
+ executables:
73
+ - console
74
+ - setup
75
+ extensions: []
76
+ extra_rdoc_files: []
77
+ files:
78
+ - ".gitignore"
79
+ - ".rspec"
80
+ - Gemfile
81
+ - LICENSE
82
+ - README.md
83
+ - Rakefile
84
+ - bin/console
85
+ - bin/setup
86
+ - lib/pritunl_api_client.rb
87
+ - lib/pritunl_api_client/api.rb
88
+ - lib/pritunl_api_client/key.rb
89
+ - lib/pritunl_api_client/organization.rb
90
+ - lib/pritunl_api_client/server.rb
91
+ - lib/pritunl_api_client/settings.rb
92
+ - lib/pritunl_api_client/user.rb
93
+ - lib/pritunl_api_client/version.rb
94
+ - pritunl_api_client.gemspec
95
+ homepage: http://eterry1388.github.io/pritunl_api_client
96
+ licenses:
97
+ - MIT
98
+ metadata: {}
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: 2.1.0
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ requirements: []
114
+ rubyforge_project:
115
+ rubygems_version: 2.4.8
116
+ signing_key:
117
+ specification_version: 4
118
+ summary: Pritunl Ruby API Client
119
+ test_files: []