smart_proxy_ipam 0.0.21 → 0.1.3

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.
@@ -0,0 +1,17 @@
1
+ module Proxy::Phpipam
2
+ class Plugin < ::Proxy::Provider
3
+ plugin :externalipam_phpipam, Proxy::Ipam::VERSION
4
+
5
+ requires :externalipam, Proxy::Ipam::VERSION
6
+ validate :url, url: true
7
+ validate_presence :user, :password
8
+
9
+ load_classes(proc do
10
+ require 'smart_proxy_ipam/phpipam/phpipam_client'
11
+ end)
12
+
13
+ load_dependency_injection_wirings(proc do |container_instance, settings|
14
+ container_instance.dependency :externalipam_client, -> { ::Proxy::Phpipam::PhpipamClient.new(settings) }
15
+ end)
16
+ end
17
+ end
@@ -1,6 +1,5 @@
1
-
2
1
  module Proxy
3
2
  module Ipam
4
- VERSION = '0.0.21'
3
+ VERSION = '0.1.3'.freeze
5
4
  end
6
5
  end
@@ -1,8 +1,3 @@
1
1
  ---
2
2
  :enabled: true
3
-
4
- :externalipam:
5
- :phpipam:
6
- :url: 'http://phpipam.example.com'
7
- :user: 'phpipam_api_user'
8
- :password: 'phpipam_password'
3
+ :use_provider: externalipam_phpipam
@@ -0,0 +1,3 @@
1
+ ---
2
+ :url: 'https://netbox.example.com'
3
+ :token: 'netbox_api_token'
@@ -0,0 +1,4 @@
1
+ ---
2
+ :url: 'http://phpipam.example.com'
3
+ :user: 'phpipam_api_user'
4
+ :password: 'phpipam_password'
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smart_proxy_ipam
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.21
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christopher Smith
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-11 00:00:00.000000000 Z
11
+ date: 2020-12-09 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: Smart proxy plugin for IPAM integration with various IPAM providers
13
+ description: Smart proxy plugin for integration with various External IPAM providers
14
14
  email: chrisjsmith001@gmail.com
15
15
  executables: []
16
16
  extensions: []
@@ -22,19 +22,27 @@ files:
22
22
  - README.md
23
23
  - bundler.d/ipam.rb
24
24
  - lib/smart_proxy_ipam.rb
25
+ - lib/smart_proxy_ipam/api_resource.rb
26
+ - lib/smart_proxy_ipam/dependency_injection.rb
27
+ - lib/smart_proxy_ipam/ip_cache.rb
25
28
  - lib/smart_proxy_ipam/ipam.rb
29
+ - lib/smart_proxy_ipam/ipam_api.rb
30
+ - lib/smart_proxy_ipam/ipam_helper.rb
26
31
  - lib/smart_proxy_ipam/ipam_http_config.ru
27
- - lib/smart_proxy_ipam/ipam_main.rb
28
- - lib/smart_proxy_ipam/phpipam/phpipam_api.rb
32
+ - lib/smart_proxy_ipam/ipam_validator.rb
33
+ - lib/smart_proxy_ipam/netbox/netbox_client.rb
34
+ - lib/smart_proxy_ipam/netbox/netbox_plugin.rb
29
35
  - lib/smart_proxy_ipam/phpipam/phpipam_client.rb
30
- - lib/smart_proxy_ipam/phpipam/phpipam_helper.rb
36
+ - lib/smart_proxy_ipam/phpipam/phpipam_plugin.rb
31
37
  - lib/smart_proxy_ipam/version.rb
32
38
  - settings.d/externalipam.yml.example
39
+ - settings.d/externalipam_netbox.yml.example
40
+ - settings.d/externalipam_phpipam.yml.example
33
41
  homepage: http://github.com/grizzthedj/smart_proxy_ipam
34
42
  licenses:
35
43
  - GPL-3.0
36
44
  metadata: {}
37
- post_install_message:
45
+ post_install_message:
38
46
  rdoc_options: []
39
47
  require_paths:
40
48
  - lib
@@ -42,7 +50,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
42
50
  requirements:
43
51
  - - ">="
44
52
  - !ruby/object:Gem::Version
45
- version: '0'
53
+ version: '2.5'
46
54
  required_rubygems_version: !ruby/object:Gem::Requirement
47
55
  requirements:
48
56
  - - ">="
@@ -50,7 +58,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
50
58
  version: '0'
51
59
  requirements: []
52
60
  rubygems_version: 3.0.6
53
- signing_key:
61
+ signing_key:
54
62
  specification_version: 4
55
- summary: Smart proxy plugin for IPAM integration with various IPAM providers
63
+ summary: Smart proxy plugin for integration with External IPAM providers
56
64
  test_files: []
@@ -1,11 +0,0 @@
1
-
2
- module Proxy::Ipam
3
- extend ::Proxy::Util
4
- extend ::Proxy::Log
5
-
6
- class << self
7
- def get_config
8
- Proxy::Ipam::Plugin.settings.externalipam
9
- end
10
- end
11
- end
@@ -1,393 +0,0 @@
1
- require 'sinatra'
2
- require 'smart_proxy_ipam/ipam'
3
- require 'smart_proxy_ipam/ipam_main'
4
- require 'smart_proxy_ipam/phpipam/phpipam_client'
5
- require 'smart_proxy_ipam/phpipam/phpipam_helper'
6
-
7
- # TODO: Refactor later to handle multiple IPAM providers. For now, it is
8
- # just phpIPAM that is supported
9
- module Proxy::Phpipam
10
- class Api < ::Sinatra::Base
11
- include ::Proxy::Log
12
- helpers ::Proxy::Helpers
13
- helpers PhpipamHelper
14
-
15
- # Gets the next available IP address based on a given subnet
16
- #
17
- # Inputs: address: Network address of the subnet(e.g. 100.55.55.0)
18
- # prefix: Network prefix(e.g. 24)
19
- #
20
- # Returns: Hash with next available IP address in "data", or hash with "message" containing
21
- # error message from phpIPAM.
22
- #
23
- # Response if success:
24
- # {"code": 200, "success": true, "data": "100.55.55.3", "time": 0.012}
25
- get '/subnet/:address/:prefix/next_ip' do
26
- content_type :json
27
-
28
- begin
29
- err = validate_required_params(["address", "prefix", "mac"], params)
30
- return err if err.length > 0
31
-
32
- mac = params[:mac]
33
- cidr = params[:address] + '/' + params[:prefix]
34
- section_name = params[:group]
35
-
36
- phpipam_client = PhpipamClient.new
37
- return auth_error unless phpipam_client.authenticated?
38
-
39
- subnet = JSON.parse(phpipam_client.get_subnet(cidr, section_name))
40
-
41
- return {:code => subnet['code'], :error => subnet['error']}.to_json if no_subnets_found?(subnet)
42
-
43
- ipaddr = phpipam_client.get_next_ip(subnet['data']['id'], mac, cidr, section_name)
44
- ipaddr_parsed = JSON.parse(ipaddr)
45
-
46
- return {:code => 404, :error => ipaddr_parsed['error']}.to_json if no_free_ip_found?(ipaddr_parsed)
47
-
48
- ipaddr
49
- rescue Errno::ECONNREFUSED, Errno::ECONNRESET
50
- logger.debug(errors[:no_connection])
51
- raise
52
- end
53
- end
54
-
55
- # Gets the subnet from phpIPAM
56
- #
57
- # Inputs: address: Network address of the subnet
58
- # prefix: Network prefix(e.g. 24)
59
- #
60
- # Returns: JSON with "data" key on success, or JSON with "error" key when there is an error
61
- #
62
- # Examples:
63
- # Response if subnet exists:
64
- # {
65
- # "code":200,"success":true,"data":[{"id":"12","subnet":"100.30.30.0","mask":"24",
66
- # "sectionId":"5", "description":"Test Subnet","linked_subnet":null,"firewallAddressObject":null,
67
- # "vrfId":"0","masterSubnetId":"0","allowRequests":"0","vlanId":"0","showName":"0","device":"0",
68
- # "permissions":"[]","pingSubnet":"0","discoverSubnet":"0","DNSrecursive":"0","DNSrecords":"0",
69
- # "nameserverId":"0","scanAgent":"0","isFolder":"0","isFull":"0","tag":"2","threshold":"0",
70
- # "location":"0","editDate":null,"lastScan":null,"lastDiscovery":null}],"time":0.009
71
- # }
72
- #
73
- # Response if subnet not exists):
74
- # {
75
- # "code":200,"success":0,"message":"No subnets found","time":0.01
76
- # }
77
- get '/subnet/:address/:prefix' do
78
- content_type :json
79
-
80
- begin
81
- err = validate_required_params(["address", "prefix"], params)
82
- return err if err.length > 0
83
-
84
- cidr = params[:address] + '/' + params[:prefix]
85
-
86
- phpipam_client = PhpipamClient.new
87
- return auth_error unless phpipam_client.authenticated?
88
-
89
- phpipam_client.get_subnet(cidr)
90
- rescue Errno::ECONNREFUSED, Errno::ECONNRESET
91
- logger.debug(errors[:no_connection])
92
- raise
93
- end
94
- end
95
-
96
- # Get a list of sections from external ipam
97
- #
98
- # Input: None
99
- # Returns: An array of sections on success, hash with "error" key otherwise
100
- # Examples
101
- # Response if success: [
102
- # {"id":"5","name":"Awesome Section","description":"A totally awesome Section","masterSection":"0",
103
- # "permissions":"[]","strictMode":"1","subnetOrdering":"default","order":null,
104
- # "editDate":"2019-04-19 21:49:55","showVLAN":"1","showVRF":"1","showSupernetOnly":"1","DNS":null}]
105
- # ]
106
- # Response if :error =>
107
- # {"error":"Unable to connect to phpIPAM server"}
108
- get '/groups' do
109
- content_type :json
110
-
111
- begin
112
- phpipam_client = PhpipamClient.new
113
- return auth_error unless phpipam_client.authenticated?
114
-
115
- sections = phpipam_client.get_sections
116
- return {:code => 200, :data => []}.to_json if no_sections_found?(JSON.parse(sections))
117
-
118
- sections
119
- rescue Errno::ECONNREFUSED, Errno::ECONNRESET
120
- logger.debug(errors[:no_connection])
121
- raise
122
- end
123
- end
124
-
125
- # Get a single sections from external ipam
126
- #
127
- # Input: Section name
128
- # Returns: A JSON section on success, hash with "error" key otherwise
129
- # Examples
130
- # Response if success:
131
- # {"code":200,"success":true,"data":{"id":"80","name":"Development #1","description":null,
132
- # "masterSection":"0","permissions":"[]","strictMode":"1","subnetOrdering":"default","order":null,
133
- # "editDate":"2020-02-11 10:57:01","showVLAN":"1","showVRF":"1","showSupernetOnly":"1","DNS":null},"time":0.004}
134
- # Response if not found:
135
- # {"code":404,"error":"Not Found"}
136
- # Response if :error =>
137
- # {"error":"Unable to connect to phpIPAM server"}
138
- get '/groups/:group' do
139
- content_type :json
140
-
141
- begin
142
- err = validate_required_params(["group"], params)
143
- return err if err.length > 0
144
-
145
- phpipam_client = PhpipamClient.new
146
- return auth_error unless phpipam_client.authenticated?
147
-
148
- section = JSON.parse(phpipam_client.get_section(params[:group]))
149
- return {:code => section['code'], :message => section['message']}.to_json if no_section_found?(section)
150
-
151
- section.to_json
152
- rescue Errno::ECONNREFUSED, Errno::ECONNRESET
153
- logger.debug(errors[:no_connection])
154
- raise
155
- end
156
- end
157
-
158
- # Get a list of subnets for given external ipam section/group
159
- #
160
- # Input: section_name(string). The name of the external ipam section/group
161
- # Returns: Array of subnets(as json) in "data" key on success, hash with error otherwise
162
- # Examples:
163
- # Response if success:
164
- # {
165
- # "code":200,
166
- # "success":true,
167
- # "data":[
168
- # {
169
- # "id":"24",
170
- # "subnet":"100.10.10.0",
171
- # "mask":"24",
172
- # "sectionId":"10",
173
- # "description":"wrgwgwefwefw",
174
- # "linked_subnet":null,
175
- # "firewallAddressObject":null,
176
- # "vrfId":"0",
177
- # "masterSubnetId":"0",
178
- # "allowRequests":"0",
179
- # "vlanId":"0",
180
- # "showName":"0",
181
- # "device":"0",
182
- # "permissions":"[]",
183
- # "pingSubnet":"0",
184
- # "discoverSubnet":"0",
185
- # "DNSrecursive":"0",
186
- # "DNSrecords":"0",
187
- # "nameserverId":"0",
188
- # "scanAgent":"0",
189
- # "isFolder":"0",
190
- # "isFull":"0",
191
- # "tag":"2",
192
- # "threshold":"0",
193
- # "location":"0",
194
- # "editDate":null,
195
- # "lastScan":null,
196
- # "lastDiscovery":null,
197
- # "usage":{
198
- # "used":"0",
199
- # "maxhosts":"254",
200
- # "freehosts":"254",
201
- # "freehosts_percent":100,
202
- # "Offline_percent":0,
203
- # "Used_percent":0,
204
- # "Reserved_percent":0,
205
- # "DHCP_percent":0
206
- # }
207
- # }
208
- # ],
209
- # "time":0.012
210
- # }
211
- # Response if :error =>
212
- # {"error":"Unable to connect to External IPAM server"}
213
- get '/groups/:group/subnets' do
214
- content_type :json
215
-
216
- begin
217
- err = validate_required_params(["group"], params)
218
- return err if err.length > 0
219
-
220
- phpipam_client = PhpipamClient.new
221
- return auth_error unless phpipam_client.authenticated?
222
-
223
- section = JSON.parse(phpipam_client.get_section(params[:group]))
224
- return {:code => 404, :error => errors[:no_section]}.to_json if no_section_found?(section)
225
-
226
- phpipam_client.get_subnets(section['data']['id'].to_s, false)
227
- rescue Errno::ECONNREFUSED, Errno::ECONNRESET
228
- logger.debug(errors[:no_connection])
229
- raise
230
- end
231
- end
232
-
233
- # Checks whether an IP address has already been taken in external ipam.
234
- #
235
- # Params: 1. address: The network address of the IPv4 or IPv6 subnet.
236
- # 2. prefix: The subnet prefix(e.g. 24)
237
- # 3. ip: IP address to be queried
238
- #
239
- # Returns: JSON object with 'exists' field being either true or false
240
- #
241
- # Example:
242
- # Response if exists:
243
- # {"ip":"100.20.20.18","exists":true}
244
- # Response if not exists:
245
- # {"ip":"100.20.20.18","exists":false}
246
- get '/subnet/:address/:prefix/:ip' do
247
- content_type :json
248
-
249
- begin
250
- err = validate_required_params(["address", "prefix", "ip"], params)
251
- return err if err.length > 0
252
-
253
- ip = params[:ip]
254
- cidr = params[:address] + '/' + params[:prefix]
255
- section_name = params[:group]
256
-
257
- phpipam_client = PhpipamClient.new
258
- return auth_error unless phpipam_client.authenticated?
259
-
260
- subnet = JSON.parse(phpipam_client.get_subnet(cidr, section_name))
261
- return {:code => 404, :error => subnet['error']}.to_json if no_subnets_found?(subnet)
262
-
263
- ip_exists = JSON.parse(phpipam_client.ip_exists(ip, subnet['data']['id']))
264
-
265
- if ip_exists['data']
266
- return {:code => 200, :exists => true}.to_json
267
- else
268
- return {:code => 404, :exists => false}.to_json
269
- end
270
- rescue Errno::ECONNREFUSED, Errno::ECONNRESET
271
- logger.debug(errors[:no_connection])
272
- raise
273
- end
274
- end
275
-
276
- # Adds an IP address to the specified subnet
277
- #
278
- # Params: 1. address: The network address of the IPv4 or IPv6 subnet.
279
- # 2. prefix: The subnet prefix(e.g. 24)
280
- # 3. ip: IP address to be added
281
- #
282
- # Returns: Hash with "message" on success, or hash with "error"
283
- #
284
- # Examples:
285
- # Response if success:
286
- # IPv4: {"message":"IP 100.10.10.123 added to subnet 100.10.10.0/24 successfully."}
287
- # IPv6: {"message":"IP 2001:db8:abcd:12::3 added to subnet 2001:db8:abcd:12::/124 successfully."}
288
- # Response if :error =>
289
- # {"error":"The specified subnet does not exist in phpIPAM."}
290
- post '/subnet/:address/:prefix/:ip' do
291
- content_type :json
292
-
293
- begin
294
- err = validate_required_params(["address", "ip", "prefix"], params)
295
- return err if err.length > 0
296
-
297
- ip = params[:ip]
298
- cidr = params[:address] + '/' + params[:prefix]
299
- section_name = URI.escape(params[:group])
300
-
301
- phpipam_client = PhpipamClient.new
302
- return auth_error unless phpipam_client.authenticated?
303
-
304
- subnet = JSON.parse(phpipam_client.get_subnet(cidr, section_name))
305
- return {:code => 404, :error => subnet['error']}.to_json if no_subnets_found?(subnet)
306
-
307
- add_ip = JSON.parse(phpipam_client.add_ip_to_subnet(ip, subnet['data']['id'], 'Address auto added by Foreman'))
308
-
309
- if add_ip['message'] && add_ip['message'] == "Address created"
310
- return {:code => 200}.to_json
311
- else
312
- return {:code => 500, :error => add_ip['message']}.to_json
313
- end
314
- rescue Errno::ECONNREFUSED, Errno::ECONNRESET
315
- logger.debug(errors[:no_connection])
316
- raise
317
- end
318
- end
319
-
320
- # Deletes IP address from a given subnet
321
- #
322
- # Params: 1. address: The network address of the IPv4 or IPv6 subnet.
323
- # 2. prefix: The subnet prefix(e.g. 24)
324
- # 3. ip: IP address to be deleted
325
- #
326
- # Returns: JSON object
327
- # Example:
328
- # Response if success:
329
- # {"code": 200, "success": true, "message": "Address deleted", "time": 0.017}
330
- # Response if :error =>
331
- # {"code": 404, "success": 0, "message": "Address does not exist", "time": 0.008}
332
- delete '/subnet/:address/:prefix/:ip' do
333
- content_type :json
334
-
335
- begin
336
- err = validate_required_params(["address", "prefix", "ip"], params)
337
- return err if err.length > 0
338
-
339
- ip = params[:ip]
340
- cidr = params[:address] + '/' + params[:prefix]
341
- section_name = URI.escape(params[:group])
342
- phpipam_client = PhpipamClient.new
343
- return auth_error unless phpipam_client.authenticated?
344
-
345
- subnet = JSON.parse(phpipam_client.get_subnet(cidr, section_name))
346
- return {:code => 404, :error => subnet['error']}.to_json if no_subnets_found?(subnet)
347
-
348
- delete_ip = JSON.parse(phpipam_client.delete_ip_from_subnet(ip, subnet['data']['id']))
349
-
350
- if delete_ip['message'] && delete_ip['message'] == "Address deleted"
351
- return {:code => 200}.to_json
352
- else
353
- return {:code => 500, :error => delete_ip['message']}.to_json
354
- end
355
- rescue Errno::ECONNREFUSED, Errno::ECONNRESET
356
- logger.debug(errors[:no_connection])
357
- raise
358
- end
359
- end
360
-
361
- # Checks whether a subnet exists in a specific section.
362
- #
363
- # Params: 1. address: The network address of the IPv4 or IPv6 subnet.
364
- # 2. prefix: The subnet prefix(e.g. 24)
365
- # 3. group: The name of the section
366
- #
367
- # Returns: JSON object with 'data' field is exists, otherwise field with 'error'
368
- #
369
- # Example:
370
- # Response if exists:
371
- # {"code":200,"success":true,"data":{"id":"147","subnet":"172.55.55.0","mask":"29","sectionId":"84","description":null,"linked_subnet":null,"firewallAddressObject":null,"vrfId":"0","masterSubnetId":"0","allowRequests":"0","vlanId":"0","showName":"0","device":"0","permissions":"[]","pingSubnet":"0","discoverSubnet":"0","resolveDNS":"0","DNSrecursive":"0","DNSrecords":"0","nameserverId":"0","scanAgent":"0","customer_id":null,"isFolder":"0","isFull":"0","tag":"2","threshold":"0","location":"0","editDate":null,"lastScan":null,"lastDiscovery":null,"calculation":{"Type":"IPv4","IP address":"\/","Network":"172.55.55.0","Broadcast":"172.55.55.7","Subnet bitmask":"29","Subnet netmask":"255.255.255.248","Subnet wildcard":"0.0.0.7","Min host IP":"172.55.55.1","Max host IP":"172.55.55.6","Number of hosts":"6","Subnet Class":false}},"time":0.009}
372
- # Response if not exists:
373
- # {"code":404,"error":"No subnet 172.66.66.0/29 found in section :group"}
374
- get '/group/:group/subnet/:address/:prefix' do
375
- content_type :json
376
-
377
- begin
378
- err = validate_required_params(["address", "prefix", "group"], params)
379
- return err if err.length > 0
380
-
381
- cidr = params[:address] + '/' + params[:prefix]
382
-
383
- phpipam_client = PhpipamClient.new
384
- return auth_error unless phpipam_client.authenticated?
385
-
386
- phpipam_client.get_subnet_by_section(cidr, params[:group])
387
- rescue Errno::ECONNREFUSED, Errno::ECONNRESET
388
- logger.debug(errors[:no_connection])
389
- raise
390
- end
391
- end
392
- end
393
- end