smart_proxy_ipam 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf80d5537986cfb15d05ac927e2c0498a9cdcab10c98866dab18b4ead3a91131
4
- data.tar.gz: 57d175cf91379394aae2f6ba477d0c89a84b4774363e9e391bc473fa9454bc5f
3
+ metadata.gz: f64f77c875cf2954bfe2d9fb2e1c56e1848e402ec8259959382771da8cd7158b
4
+ data.tar.gz: a4e3900fd2ad8a2ec16e9ab3887dd6412ce567b16f7cdb98278407c80add8e9c
5
5
  SHA512:
6
- metadata.gz: 47f2404f8982398568a8d6d1984116658e7dd9eead7679f836c74bef9772bab678b084b82cdddfbfcc8d6b6b19adf3962510c5b566c0f7a1b80d53b9e9505da8
7
- data.tar.gz: e3dc74e8020a7af4c7f660ef7204c03130088a58dd5fff23a0d18440061d3f602182f6a13f0a1d363429ad860499ce87ab33f71fa524a7f10f8006075f469e44
6
+ metadata.gz: 3608be9d60dda80356bdf9e9c59f79cf0edcd1c69210cb7c10aa818237ec85e1485e8fd12d2ee1c1d527ca3ab926d1090ef20c2a6bc4faf8f2c4b262f86df44c
7
+ data.tar.gz: a99d59aab8ce7b3f1a1b6d4b90e861fef90435c9071e0b42d3f7863834a660050d8e96af471473b4e6f0a0b8db8b1f1d212502e01ac80073e79a1542d731fff6
data/README.md CHANGED
@@ -1,8 +1,12 @@
1
- # smart_proxy_phpipam
1
+ # smart_proxy_ipam
2
2
 
3
- Foreman Smart Proxy plugin for IPAM integration with [phpIPAM](https://phpipam.net/).
3
+ Foreman Smart Proxy plugin for IPAM integration with various IPAM providers.
4
+
5
+ Currently supported Providers:
6
+ 1. [phpIPAM](https://phpipam.net/).
7
+
8
+ Provides a basic Dashboard for viewing phpIPAM sections, subnets. Also supports obtaining of the next available IPv4 address for a given subnet(via [IPAM Smart Proxy Plugin](https://github.com/grizzthedj/smart_proxy_ipam)).
4
9
 
5
- Used for obtaining the next available IPv4 address from phpIPAM, for a given subnet.
6
10
 
7
11
  ## Installation
8
12
 
@@ -1,11 +1,6 @@
1
1
 
2
2
  require 'smart_proxy_ipam/phpipam/phpipam_api'
3
- require 'smart_proxy_ipam/ipam/ipam_api'
4
3
 
5
- map '/phpipam' do
4
+ map '/ipam' do
6
5
  run Proxy::Phpipam::Api
7
6
  end
8
-
9
- map '/ipam' do
10
- run Proxy::Ipam::Api
11
- end
@@ -3,11 +3,27 @@ require 'smart_proxy_ipam/ipam'
3
3
  require 'smart_proxy_ipam/ipam_main'
4
4
  require 'smart_proxy_ipam/phpipam/phpipam_client'
5
5
 
6
+ # TODO: Refactor later to handle multiple IPAM providers. For now, it is
7
+ # just phpIPAM that is supported
6
8
  module Proxy::Phpipam
7
9
  class Api < ::Sinatra::Base
8
10
  include ::Proxy::Log
9
11
  helpers ::Proxy::Helpers
10
12
 
13
+ get '/providers' do
14
+ content_type :json
15
+ {ipam_providers: ['phpIPAM']}.to_json
16
+ end
17
+
18
+ # Gets the next available IP address based on a given subnet
19
+ #
20
+ # Input: cidr(string): CIDR address in the format: "100.20.20.0/24"
21
+ # Returns: Hash with "next_ip", or hash with "error"
22
+ # Examples:
23
+ # Response if success:
24
+ # {"cidr":"100.20.20.0/24","next_ip":"100.20.20.11"}
25
+ # Response if error:
26
+ # {"error":"The specified subnet does not exist in phpIPAM."}
11
27
  get '/next_ip' do
12
28
  content_type :json
13
29
 
@@ -22,10 +38,10 @@ module Proxy::Phpipam
22
38
  response = phpipam_client.get_subnet(cidr)
23
39
 
24
40
  if response['message'] && response['message'].downcase == "no subnets found"
25
- return {error: "The specified subnet does not exist in phpIPAM."}.to_json
41
+ return {error: "The specified subnet does not exist in External IPAM."}.to_json
26
42
  end
27
43
 
28
- subnet_id = response['data'][0]['id']
44
+ subnet_id = JSON.parse(response)[0]['id']
29
45
  response = phpipam_client.get_next_ip(subnet_id)
30
46
 
31
47
  if response['message'] && response['message'].downcase == "no free addresses found"
@@ -34,10 +50,29 @@ module Proxy::Phpipam
34
50
 
35
51
  {cidr: cidr, next_ip: response['data']}.to_json
36
52
  rescue Errno::ECONNREFUSED
37
- return {error: "Unable to connect to phpIPAM server"}.to_json
53
+ return {error: "Unable to connect to External IPAM server"}.to_json
38
54
  end
39
55
  end
40
56
 
57
+ # Gets the subnet from phpIPAM
58
+ #
59
+ # Input: cidr(string): CIDR address in the format: "100.20.20.0/24"
60
+ # Returns: JSON with "data" key on success, or JSON with "error" key when there is an error
61
+ # Examples:
62
+ # Response if subnet exists:
63
+ # {
64
+ # "code":200,"success":true,"data":[{"id":"12","subnet":"100.30.30.0","mask":"24",
65
+ # "sectionId":"5", "description":"Test Subnet","linked_subnet":null,"firewallAddressObject":null,
66
+ # "vrfId":"0","masterSubnetId":"0","allowRequests":"0","vlanId":"0","showName":"0","device":"0",
67
+ # "permissions":"[]","pingSubnet":"0","discoverSubnet":"0","DNSrecursive":"0","DNSrecords":"0",
68
+ # "nameserverId":"0","scanAgent":"0","isFolder":"0","isFull":"0","tag":"2","threshold":"0",
69
+ # "location":"0","editDate":null,"lastScan":null,"lastDiscovery":null}],"time":0.009
70
+ # }
71
+ #
72
+ # Response if subnet not exists):
73
+ # {
74
+ # "code":200,"success":0,"message":"No subnets found","time":0.01
75
+ # }
41
76
  get '/get_subnet' do
42
77
  content_type :json
43
78
 
@@ -52,10 +87,22 @@ module Proxy::Phpipam
52
87
  subnet = phpipam_client.get_subnet(cidr)
53
88
  subnet.to_json
54
89
  rescue Errno::ECONNREFUSED
55
- return {error: "Unable to connect to phpIPAM server"}.to_json
90
+ return {error: "Unable to connect to External IPAM server"}.to_json
56
91
  end
57
92
  end
58
93
 
94
+ # Get a list of sections from external ipam
95
+ #
96
+ # Input: None
97
+ # Returns: An array of sections on success, hash with "error" key otherwise
98
+ # Examples
99
+ # Response if success: [
100
+ # {"id":"5","name":"Awesome Section","description":"A totally awesome Section","masterSection":"0",
101
+ # "permissions":"[]","strictMode":"1","subnetOrdering":"default","order":null,
102
+ # "editDate":"2019-04-19 21:49:55","showVLAN":"1","showVRF":"1","showSupernetOnly":"1","DNS":null}]
103
+ # ]
104
+ # Response if error:
105
+ # {"error":"Unable to connect to phpIPAM server"}
59
106
  get '/sections' do
60
107
  content_type :json
61
108
 
@@ -64,10 +111,65 @@ module Proxy::Phpipam
64
111
  sections = phpipam_client.get_sections
65
112
  sections.to_json
66
113
  rescue Errno::ECONNREFUSED
67
- return {error: "Unable to connect to phpIPAM server"}.to_json
114
+ return {error: "Unable to connect to External IPAM server"}.to_json
68
115
  end
69
116
  end
70
117
 
118
+ # Get a list of subnets for given external ipam section
119
+ #
120
+ # Input: section_id(integer). The id of the external ipam section
121
+ # Returns: Array of subnets(as json) in "data" key on success, hash with error otherwise
122
+ # Examples:
123
+ # Response if success:
124
+ # {
125
+ # "code":200,
126
+ # "success":true,
127
+ # "data":[
128
+ # {
129
+ # "id":"24",
130
+ # "subnet":"100.10.10.0",
131
+ # "mask":"24",
132
+ # "sectionId":"10",
133
+ # "description":"wrgwgwefwefw",
134
+ # "linked_subnet":null,
135
+ # "firewallAddressObject":null,
136
+ # "vrfId":"0",
137
+ # "masterSubnetId":"0",
138
+ # "allowRequests":"0",
139
+ # "vlanId":"0",
140
+ # "showName":"0",
141
+ # "device":"0",
142
+ # "permissions":"[]",
143
+ # "pingSubnet":"0",
144
+ # "discoverSubnet":"0",
145
+ # "DNSrecursive":"0",
146
+ # "DNSrecords":"0",
147
+ # "nameserverId":"0",
148
+ # "scanAgent":"0",
149
+ # "isFolder":"0",
150
+ # "isFull":"0",
151
+ # "tag":"2",
152
+ # "threshold":"0",
153
+ # "location":"0",
154
+ # "editDate":null,
155
+ # "lastScan":null,
156
+ # "lastDiscovery":null,
157
+ # "usage":{
158
+ # "used":"0",
159
+ # "maxhosts":"254",
160
+ # "freehosts":"254",
161
+ # "freehosts_percent":100,
162
+ # "Offline_percent":0,
163
+ # "Used_percent":0,
164
+ # "Reserved_percent":0,
165
+ # "DHCP_percent":0
166
+ # }
167
+ # }
168
+ # ],
169
+ # "time":0.012
170
+ # }
171
+ # Response if error:
172
+ # {"error":"Unable to connect to phpIPAM server"}
71
173
  get '/sections/:section_id/subnets' do
72
174
  content_type :json
73
175
 
@@ -82,10 +184,20 @@ module Proxy::Phpipam
82
184
  subnets = phpipam_client.get_subnets(section_id)
83
185
  subnets.to_json
84
186
  rescue Errno::ECONNREFUSED
85
- return {error: "Unable to connect to phpIPAM server"}.to_json
187
+ return {error: "Unable to connect to External IPAM server"}.to_json
86
188
  end
87
189
  end
88
190
 
191
+ # Checks whether an IP address has already been taken in external ipam.
192
+ #
193
+ # Inputs: 1. ip(string). IP address to be checked.
194
+ # 2. cidr(string): CIDR address in the format: "100.20.20.0/24"
195
+ # Returns: JSON object with 'exists' field being either true or false
196
+ # Example:
197
+ # Response if exists:
198
+ # {"ip":"100.20.20.18","exists":true}
199
+ # Response if not exists:
200
+ # {"ip":"100.20.20.18","exists":false}
89
201
  get '/ip_exists' do
90
202
  content_type :json
91
203
 
@@ -100,31 +212,27 @@ module Proxy::Phpipam
100
212
  subnet = phpipam_client.get_subnet(cidr)
101
213
 
102
214
  if subnet['message'] && subnet['message'].downcase == "no subnets found"
103
- return {error: "The specified subnet does not exist in phpIPAM."}.to_json
215
+ return {error: "The specified subnet does not exist in External IPAM."}.to_json
104
216
  end
105
217
 
106
- subnet_id = subnet['data'][0]['id']
107
- usage = phpipam_client.get_subnet_usage(subnet_id)
108
-
109
- # We need to check subnet usage first in the case there are zero ips in the subnet. Checking
110
- # the ip existence on an empty subnet returns a malformed response from phpIPAM, containing
111
- # HTML in the JSON response.
112
- if usage['data']['used'] == "0"
113
- return {ip: ip, exists: false}.to_json
114
- else
115
- response = phpipam_client.ip_exists(ip, subnet_id)
116
-
117
- if response && response['message'] && response['message'].downcase == 'no addresses found'
118
- return {ip: ip, exists: false}.to_json
119
- else
120
- return {ip: ip, exists: true}.to_json
121
- end
122
- end
218
+ subnet_id = JSON.parse(subnet)[0]['id']
219
+ phpipam_client.ip_exists(ip, subnet_id)
123
220
  rescue Errno::ECONNREFUSED
124
- return {error: "Unable to connect to phpIPAM server"}.to_json
221
+ return {error: "Unable to connect to External IPAM server"}.to_json
125
222
  end
126
223
  end
127
224
 
225
+ # Adds an IP address to the specified subnet
226
+ #
227
+ # Inputs: 1. ip(string). IP address to be added.
228
+ # 2. subnet_id(integer). The id of the external ipam subnet
229
+ # 3. description(string). IP address description
230
+ # Returns: Hash with "message" on success, or hash with "error"
231
+ # Examples:
232
+ # Response if success:
233
+ # {"message":"IP 100.10.10.123 added to subnet 100.10.10.0/24 successfully."}
234
+ # Response if error:
235
+ # {"error":"The specified subnet does not exist in phpIPAM."}
128
236
  post '/add_ip_to_subnet' do
129
237
  content_type :json
130
238
 
@@ -139,19 +247,29 @@ module Proxy::Phpipam
139
247
  response = phpipam_client.get_subnet(cidr)
140
248
 
141
249
  if response['message'] && response['message'].downcase == "no subnets found"
142
- return {error: "The specified subnet does not exist in phpIPAM."}.to_json
250
+ return {error: "The specified subnet does not exist in External IPAM."}.to_json
143
251
  end
144
252
 
145
- subnet_id = response['data'][0]['id']
253
+ subnet_id = JSON.parse(response)[0]['id']
146
254
 
147
255
  phpipam_client.add_ip_to_subnet(ip, subnet_id, 'Address auto added by Foreman')
148
256
 
149
257
  {message: "IP #{ip} added to subnet #{cidr} successfully."}.to_json
150
258
  rescue Errno::ECONNREFUSED
151
- return {error: "Unable to connect to phpIPAM server"}.to_json
259
+ return {error: "Unable to connect to External IPAM server"}.to_json
152
260
  end
153
261
  end
154
262
 
263
+ # Deletes IP address from a given subnet
264
+ #
265
+ # Inputs: 1. ip(string). IP address to be checked.
266
+ # 2. cidr(string): CIDR address in the format: "100.20.20.0/24"
267
+ # Returns: JSON object
268
+ # Example:
269
+ # Response if success:
270
+ # {"code": 200, "success": true, "message": "Address deleted", "time": 0.017}
271
+ # Response if error:
272
+ # {"code": 404, "success": 0, "message": "Address does not exist", "time": 0.008}
155
273
  post '/delete_ip_from_subnet' do
156
274
  content_type :json
157
275
 
@@ -166,16 +284,16 @@ module Proxy::Phpipam
166
284
  response = phpipam_client.get_subnet(cidr)
167
285
 
168
286
  if response['message'] && response['message'].downcase == "no subnets found"
169
- return {error: "The specified subnet does not exist in phpIPAM."}.to_json
287
+ return {error: "The specified subnet does not exist in External IPAM."}.to_json
170
288
  end
171
289
 
172
- subnet_id = response['data'][0]['id']
290
+ subnet_id = JSON.parse(response)[0]['id']
173
291
 
174
292
  phpipam_client.delete_ip_from_subnet(ip, subnet_id)
175
293
 
176
294
  {message: "IP #{ip} deleted from subnet #{cidr} successfully."}.to_json
177
295
  rescue Errno::ECONNREFUSED
178
- return {error: "Unable to connect to phpIPAM server"}.to_json
296
+ return {error: "Unable to connect to External IPAM server"}.to_json
179
297
  end
180
298
  end
181
299
 
@@ -6,22 +6,40 @@ require 'smart_proxy_ipam/ipam'
6
6
  require 'smart_proxy_ipam/ipam_main'
7
7
 
8
8
  module Proxy::Phpipam
9
- class PhpipamClient
9
+ class PhpipamClient
10
10
  def initialize
11
11
  conf = Proxy::Ipam.get_config[:phpipam]
12
12
  @phpipam_config = {url: conf[:url], user: conf[:user], password: conf[:password]}
13
- @api_base = conf[:url] + '/api/' + conf[:user] + '/'
13
+ @api_base = "#{conf[:url]}/api/#{conf[:user]}/"
14
14
  @token = nil
15
15
  end
16
16
 
17
- def get_subnet(cidr)
18
- url = 'subnets/cidr/' + cidr.to_s + '/'
19
- get(url)
17
+ def init_reservations
18
+ @@ipam_reservations = {}
20
19
  end
21
20
 
22
- def get_next_ip(subnet_id)
23
- url = 'subnets/' + subnet_id.to_s + '/first_free/'
24
- get(url)
21
+ def get_subnet(cidr)
22
+ url = "subnets/cidr/#{cidr.to_s}"
23
+ subnets = get(url)
24
+ response = []
25
+
26
+ if subnets
27
+ if subnets['message'] && subnets['message'].downcase == 'no subnets found'
28
+ return {"message": "no subnets found"}.to_json
29
+ else
30
+ # Only return the relevant fields to Foreman
31
+ subnets['data'].each do |subnet|
32
+ response.push({
33
+ "id": subnet['id'],
34
+ "subnet": subnet['subnet'],
35
+ "description": subnet['description'],
36
+ "mask": subnet['mask']
37
+ })
38
+ end
39
+
40
+ return response.to_json
41
+ end
42
+ end
25
43
  end
26
44
 
27
45
  def add_ip_to_subnet(ip, subnet_id, desc)
@@ -30,26 +48,74 @@ module Proxy::Phpipam
30
48
  end
31
49
 
32
50
  def get_sections
33
- get('sections/')['data']
51
+ sections = get('sections/')['data']
52
+ response = []
53
+
54
+ if sections
55
+ sections.each do |section|
56
+ response.push({
57
+ "id": section['id'],
58
+ "name": section['name'],
59
+ "description": section['description']
60
+ })
61
+ end
62
+ end
63
+
64
+ response
34
65
  end
35
66
 
36
67
  def get_subnets(section_id)
37
- get('sections/' + section_id.to_s + '/subnets/')
68
+ subnets = get("sections/#{section_id.to_s}/subnets/")
69
+ response = []
70
+
71
+ if subnets && subnets['data']
72
+ # Only return the relevant data
73
+ subnets['data'].each do |subnet|
74
+ response.push({
75
+ "id": subnet['id'],
76
+ "subnet": subnet['subnet'],
77
+ "mask": subnet['mask'],
78
+ "sectionId": subnet['sectionId'],
79
+ "description": subnet['description']
80
+ })
81
+ end
82
+ end
83
+
84
+ response
38
85
  end
39
86
 
40
87
  def ip_exists(ip, subnet_id)
41
- get('subnets/' + subnet_id.to_s + '/addresses/' + ip + '/')
88
+ usage = get_subnet_usage(subnet_id)
89
+
90
+ # We need to check subnet usage first in the case there are zero ips in the subnet. Checking
91
+ # the ip existence on an empty subnet returns a malformed response from phpIPAM, containing
92
+ # HTML in the JSON response.
93
+ if usage['data']['used'] == "0"
94
+ return {ip: ip, exists: false}.to_json
95
+ else
96
+ response = get("subnets/#{subnet_id.to_s}/addresses/#{ip}/")
97
+
98
+ if response && response['message'] && response['message'].downcase == 'no addresses found'
99
+ return {ip: ip, exists: false}.to_json
100
+ else
101
+ return {ip: ip, exists: true}.to_json
102
+ end
103
+ end
42
104
  end
43
105
 
106
+
44
107
  def get_subnet_usage(subnet_id)
45
- get('subnets/' + subnet_id.to_s + '/usage/')
108
+ get("subnets/#{subnet_id.to_s}/usage/")
46
109
  end
47
110
 
48
111
  def delete_ip_from_subnet(ip, subnet_id)
49
- delete('addresses/' + ip + '/' + subnet_id.to_s + '/')
112
+ delete("addresses/#{ip}/#{subnet_id.to_s}/")
50
113
  end
51
114
 
52
- private
115
+ def get_next_ip(subnet_id)
116
+ url = "subnets/#{subnet_id.to_s}/first_free/"
117
+ get(url)
118
+ end
53
119
 
54
120
  def get(path, body=nil)
55
121
  authenticate
@@ -1,6 +1,6 @@
1
1
 
2
2
  module Proxy
3
3
  module Ipam
4
- VERSION = '0.0.4'
4
+ VERSION = '0.0.5'
5
5
  end
6
6
  end
@@ -6,7 +6,3 @@
6
6
  :url: 'http://172.16.16.217'
7
7
  :user: 'foreman'
8
8
  :password: 'Test1234!'
9
- :netbox:
10
- :url: 'http://172.16.16.217'
11
- :user: 'netbox'
12
- :password: 'Test1234!'
@@ -6,7 +6,3 @@
6
6
  :url: 'http://phpipam.example.com'
7
7
  :user: 'phpipam_api_user'
8
8
  :password: 'phpipam_password'
9
- :netbox:
10
- :url: 'http://netbox.example.com'
11
- :user: 'netbox_api_user'
12
- :password: 'netbox_api_password'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smart_proxy_ipam
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christopher Smith
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-12 00:00:00.000000000 Z
11
+ date: 2019-07-10 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Smart proxy plugin for IPAM integration with various IPAM providers
14
14
  email: chrisjsmith001@gmail.com
@@ -23,7 +23,6 @@ files:
23
23
  - bundler.d/ipam.rb
24
24
  - lib/smart_proxy_ipam.rb
25
25
  - lib/smart_proxy_ipam/ipam.rb
26
- - lib/smart_proxy_ipam/ipam/ipam_api.rb
27
26
  - lib/smart_proxy_ipam/ipam_http_config.ru
28
27
  - lib/smart_proxy_ipam/ipam_main.rb
29
28
  - lib/smart_proxy_ipam/phpipam/phpipam_api.rb
@@ -1,15 +0,0 @@
1
- require 'sinatra'
2
- require 'smart_proxy_ipam/ipam'
3
- require 'smart_proxy_ipam/ipam_main'
4
-
5
- module Proxy::Ipam
6
- class Api < ::Sinatra::Base
7
- include ::Proxy::Log
8
- helpers ::Proxy::Helpers
9
-
10
- get '/providers' do
11
- content_type :json
12
- {ipam_providers: ['phpIPAM']}.to_json
13
- end
14
- end
15
- end