smart_proxy_dhcp_bluecat 0.1.0 → 0.1.5
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.
- checksums.yaml +5 -5
- data/LICENSE +673 -673
- data/README.md +47 -47
- data/bundler.d/dhcp_bluecat.rb +1 -1
- data/config/dhcp_bluecat.yml.example +35 -35
- data/lib/smart_proxy_dhcp_bluecat.rb +11 -11
- data/lib/smart_proxy_dhcp_bluecat/bluecat_api.rb +386 -345
- data/lib/smart_proxy_dhcp_bluecat/dhcp_bluecat_main.rb +128 -109
- data/lib/smart_proxy_dhcp_bluecat/dhcp_bluecat_plugin.rb +38 -34
- data/lib/smart_proxy_dhcp_bluecat/dhcp_bluecat_version.rb +1 -1
- data/lib/smart_proxy_dhcp_bluecat/module_loader.rb +12 -6
- data/lib/smart_proxy_dhcp_bluecat/plugin_configuration.rb +37 -33
- data/lib/smart_proxy_dhcp_bluecat/settings_validator.rb +66 -62
- metadata +18 -27
- data/lib/lib/smart_proxy_dhcp_bluecat.rb +0 -11
- data/lib/lib/smart_proxy_dhcp_bluecat/bluecat_api.rb +0 -345
- data/lib/lib/smart_proxy_dhcp_bluecat/dhcp_bluecat_main.rb +0 -109
- data/lib/lib/smart_proxy_dhcp_bluecat/dhcp_bluecat_plugin.rb +0 -34
- data/lib/lib/smart_proxy_dhcp_bluecat/dhcp_bluecat_version.rb +0 -7
- data/lib/lib/smart_proxy_dhcp_bluecat/module_loader.rb +0 -6
- data/lib/lib/smart_proxy_dhcp_bluecat/plugin_configuration.rb +0 -33
- data/lib/lib/smart_proxy_dhcp_bluecat/settings_validator.rb +0 -62
data/README.md
CHANGED
@@ -1,47 +1,47 @@
|
|
1
|
-
# SmartProxyDhcpBlueCat
|
2
|
-
|
3
|
-
This plugin adds a new DHCP provider for managing records with BlueCat Address Manager.
|
4
|
-
The Provider manages dhcp reservations and A&PTR records.
|
5
|
-
|
6
|
-
## Installation
|
7
|
-
|
8
|
-
See [How_to_Install_a_Smart-Proxy_Plugin](http://projects.theforeman.org/projects/foreman/wiki/How_to_Install_a_Smart-Proxy_Plugin)
|
9
|
-
for how to install Smart Proxy plugins
|
10
|
-
|
11
|
-
This plugin is compatible with Smart Proxy 1.16 or higher.
|
12
|
-
|
13
|
-
When installing using "gem", make sure to install the bundle file:
|
14
|
-
|
15
|
-
echo "gem 'smart_proxy_dhcp_bluecat', :git => 'https://github.com/theforeman/smart_proxy_dhcp_bluecat'" > /usr/share/foreman-proxy/bundler.d/dhcp_bluecat.rb
|
16
|
-
|
17
|
-
## Configuration
|
18
|
-
|
19
|
-
To enable this DHCP provider, edit `/etc/foreman-proxy/settings.d/dhcp.yml` and set:
|
20
|
-
|
21
|
-
:use_provider: dhcp_bluecat
|
22
|
-
:subnets: subnets you want to use (optional)
|
23
|
-
|
24
|
-
Configuration options for this plugin are in `/etc/foreman-proxy/settings.d/dhcp_bluecat.yml` and include:
|
25
|
-
|
26
|
-
:scheme: connection mode to the Bluecat address manager
|
27
|
-
:verify: validate ssl connection
|
28
|
-
:host: FQDN or IP of the Bluecat address manager
|
29
|
-
:parent_block: parent_block Id that holds your subnets
|
30
|
-
:view_name: Bluecat DNS view name
|
31
|
-
:config_id: Bluecat configuration id
|
32
|
-
:config_name: Bluecat configuration name
|
33
|
-
:server_id: id of your dhcp server
|
34
|
-
:username: API Username
|
35
|
-
:password: API Password
|
36
|
-
|
37
|
-
## Limitations
|
38
|
-
IPv6 Records are currently not implemented
|
39
|
-
Adresses with expired DHCP Leases are not handed out as free IPs by Bluecat
|
40
|
-
|
41
|
-
## Contributing
|
42
|
-
|
43
|
-
Fork and send a Pull Request. Thanks!
|
44
|
-
|
45
|
-
## Copyright
|
46
|
-
|
47
|
-
Copyright (c) 2018 Sixt GmbH & Co. Autovermietung KG
|
1
|
+
# SmartProxyDhcpBlueCat
|
2
|
+
|
3
|
+
This plugin adds a new DHCP provider for managing records with BlueCat Address Manager.
|
4
|
+
The Provider manages dhcp reservations and A&PTR records.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
See [How_to_Install_a_Smart-Proxy_Plugin](http://projects.theforeman.org/projects/foreman/wiki/How_to_Install_a_Smart-Proxy_Plugin)
|
9
|
+
for how to install Smart Proxy plugins
|
10
|
+
|
11
|
+
This plugin is compatible with Smart Proxy 1.16 or higher.
|
12
|
+
|
13
|
+
When installing using "gem", make sure to install the bundle file:
|
14
|
+
|
15
|
+
echo "gem 'smart_proxy_dhcp_bluecat', :git => 'https://github.com/theforeman/smart_proxy_dhcp_bluecat'" > /usr/share/foreman-proxy/bundler.d/dhcp_bluecat.rb
|
16
|
+
|
17
|
+
## Configuration
|
18
|
+
|
19
|
+
To enable this DHCP provider, edit `/etc/foreman-proxy/settings.d/dhcp.yml` and set:
|
20
|
+
|
21
|
+
:use_provider: dhcp_bluecat
|
22
|
+
:subnets: subnets you want to use (optional)
|
23
|
+
|
24
|
+
Configuration options for this plugin are in `/etc/foreman-proxy/settings.d/dhcp_bluecat.yml` and include:
|
25
|
+
|
26
|
+
:scheme: connection mode to the Bluecat address manager
|
27
|
+
:verify: validate ssl connection
|
28
|
+
:host: FQDN or IP of the Bluecat address manager
|
29
|
+
:parent_block: parent_block Id that holds your subnets
|
30
|
+
:view_name: Bluecat DNS view name
|
31
|
+
:config_id: Bluecat configuration id
|
32
|
+
:config_name: Bluecat configuration name
|
33
|
+
:server_id: id of your dhcp server
|
34
|
+
:username: API Username
|
35
|
+
:password: API Password
|
36
|
+
|
37
|
+
## Limitations
|
38
|
+
IPv6 Records are currently not implemented
|
39
|
+
Adresses with expired DHCP Leases are not handed out as free IPs by Bluecat
|
40
|
+
|
41
|
+
## Contributing
|
42
|
+
|
43
|
+
Fork and send a Pull Request. Thanks!
|
44
|
+
|
45
|
+
## Copyright
|
46
|
+
|
47
|
+
Copyright (c) 2018 Sixt GmbH & Co. Autovermietung KG
|
data/bundler.d/dhcp_bluecat.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
gem 'smart_proxy_dhcp_bluecat'
|
1
|
+
gem 'smart_proxy_dhcp_bluecat'
|
@@ -1,35 +1,35 @@
|
|
1
|
-
---
|
2
|
-
#
|
3
|
-
# Configuration file for 'dhcp_bluecat' dhcp provider
|
4
|
-
#
|
5
|
-
|
6
|
-
#connection mode to the address manager
|
7
|
-
#https or http
|
8
|
-
:scheme: "https"
|
9
|
-
|
10
|
-
# validate ssl connection
|
11
|
-
# true or false
|
12
|
-
:verify: true
|
13
|
-
|
14
|
-
#fqdn or ip of your bluecat address manager
|
15
|
-
:host: "192.168.0.2"
|
16
|
-
|
17
|
-
# id of the parent_block that holds the subnets that you want to use
|
18
|
-
:parent_block: 00000
|
19
|
-
|
20
|
-
# name of your dns view
|
21
|
-
:view_name: "internal"
|
22
|
-
|
23
|
-
# id of your Bluecat configuration
|
24
|
-
:config_id: 000000
|
25
|
-
|
26
|
-
# Name of your Bluecat configuration
|
27
|
-
:config_name: "default"
|
28
|
-
|
29
|
-
# id of the server that holds your dhcp
|
30
|
-
:server_id: 000000
|
31
|
-
|
32
|
-
|
33
|
-
# credentials of your api user
|
34
|
-
:username: "username"
|
35
|
-
:password: "password"
|
1
|
+
---
|
2
|
+
#
|
3
|
+
# Configuration file for 'dhcp_bluecat' dhcp provider
|
4
|
+
#
|
5
|
+
|
6
|
+
# connection mode to the address manager
|
7
|
+
# https or http
|
8
|
+
:scheme: "https"
|
9
|
+
|
10
|
+
# validate ssl connection
|
11
|
+
# true or false
|
12
|
+
:verify: true
|
13
|
+
|
14
|
+
# fqdn or ip of your bluecat address manager
|
15
|
+
:host: "192.168.0.2"
|
16
|
+
|
17
|
+
# id of the parent_block that holds the subnets that you want to use
|
18
|
+
:parent_block: 00000
|
19
|
+
|
20
|
+
# name of your dns view
|
21
|
+
:view_name: "internal"
|
22
|
+
|
23
|
+
# id of your Bluecat configuration
|
24
|
+
:config_id: 000000
|
25
|
+
|
26
|
+
# Name of your Bluecat configuration
|
27
|
+
:config_name: "default"
|
28
|
+
|
29
|
+
# id of the server that holds your dhcp
|
30
|
+
:server_id: 000000
|
31
|
+
|
32
|
+
|
33
|
+
# credentials of your api user
|
34
|
+
:username: "username"
|
35
|
+
:password: "password"
|
@@ -1,11 +1,11 @@
|
|
1
|
-
module Proxy
|
2
|
-
module DHCP
|
3
|
-
module BlueCat; end
|
4
|
-
end
|
5
|
-
end
|
6
|
-
|
7
|
-
require 'smart_proxy_dhcp_bluecat/plugin_configuration'
|
8
|
-
require 'smart_proxy_dhcp_bluecat/module_loader'
|
9
|
-
require 'smart_proxy_dhcp_bluecat/settings_validator'
|
10
|
-
require 'smart_proxy_dhcp_bluecat/dhcp_bluecat_version'
|
11
|
-
require 'smart_proxy_dhcp_bluecat/dhcp_bluecat_plugin'
|
1
|
+
module Proxy
|
2
|
+
module DHCP
|
3
|
+
module BlueCat; end
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'smart_proxy_dhcp_bluecat/plugin_configuration'
|
8
|
+
require 'smart_proxy_dhcp_bluecat/module_loader'
|
9
|
+
require 'smart_proxy_dhcp_bluecat/settings_validator'
|
10
|
+
require 'smart_proxy_dhcp_bluecat/dhcp_bluecat_version'
|
11
|
+
require 'smart_proxy_dhcp_bluecat/dhcp_bluecat_plugin'
|
@@ -1,345 +1,386 @@
|
|
1
|
-
require 'httparty'
|
2
|
-
require 'ipaddress'
|
3
|
-
require 'json'
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
1
|
+
require 'httparty'
|
2
|
+
require 'ipaddress'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Proxy
|
6
|
+
module DHCP
|
7
|
+
module BlueCat
|
8
|
+
##
|
9
|
+
# This Class handles all commuincation to the bluecat address manager
|
10
|
+
class BlueCatAPI
|
11
|
+
include ::Proxy::Log
|
12
|
+
|
13
|
+
# connection mode to the address manager. http or https
|
14
|
+
attr_reader :scheme
|
15
|
+
|
16
|
+
# validate ssl connection. true or false
|
17
|
+
attr_reader :verify
|
18
|
+
|
19
|
+
# fqdn or ip of your bluecat address manager
|
20
|
+
attr_reader :host
|
21
|
+
|
22
|
+
# id of the parent_block that holds the subnets that you want to use
|
23
|
+
attr_reader :parent_block
|
24
|
+
|
25
|
+
# name of your dns view
|
26
|
+
attr_reader :view_name
|
27
|
+
|
28
|
+
# Name of your Bluecat configuration
|
29
|
+
attr_reader :config_name
|
30
|
+
|
31
|
+
# id of your Bluecat configuration
|
32
|
+
attr_reader :config_id
|
33
|
+
|
34
|
+
# id of the server that holds your dhcp
|
35
|
+
attr_reader :server_id
|
36
|
+
|
37
|
+
# credentials of your api user
|
38
|
+
attr_reader :username
|
39
|
+
|
40
|
+
# credentials of your api user
|
41
|
+
attr_reader :password
|
42
|
+
|
43
|
+
class << self
|
44
|
+
# contains the bluecat api token
|
45
|
+
attr_accessor :token
|
46
|
+
end
|
47
|
+
|
48
|
+
def initialize(scheme, verify, host, parent_block, view_name, config_name, config_id, server_id, username, password)
|
49
|
+
@scheme = scheme
|
50
|
+
@verify = verify
|
51
|
+
@host = host
|
52
|
+
@parent_block = parent_block
|
53
|
+
@view_name = view_name
|
54
|
+
@config_name = config_name
|
55
|
+
@config_id = config_id
|
56
|
+
@server_id = server_id
|
57
|
+
@username = username
|
58
|
+
@password = password
|
59
|
+
end
|
60
|
+
|
61
|
+
# login to bam, parse the session token
|
62
|
+
def rest_login
|
63
|
+
logger.debug('BAM Login ' + @scheme + ' ' + @host + ' ')
|
64
|
+
response = HTTParty.get(format('%s://%s/Services/REST/v1/login?username=%s&password=%s', @scheme, @host, @username, @password),
|
65
|
+
headers: { 'Content-Type' => 'text/plain' },
|
66
|
+
verify => @verify)
|
67
|
+
if response.code != 200
|
68
|
+
logger.error('BAM Login Failed. HTTP' + response.code.to_s + ' ' + response.body.to_s)
|
69
|
+
end
|
70
|
+
body = response.body.to_s
|
71
|
+
token = body.match(/BAMAuthToken:\s+(\S+)/).captures
|
72
|
+
|
73
|
+
logger.debug('BAM Login Body ' + response.body)
|
74
|
+
logger.debug('BAM Login Token ' + token[0].to_s)
|
75
|
+
self.class.token = token[0].to_s
|
76
|
+
end
|
77
|
+
|
78
|
+
# logout from bam
|
79
|
+
def rest_logout
|
80
|
+
logger.debug('BAM Logout ')
|
81
|
+
response = HTTParty.get(format('%s://%s/Services/REST/v1/logout', @scheme, @host),
|
82
|
+
headers: { 'Authorization' => 'BAMAuthToken: ' + self.class.token, 'Content-Type' => 'application/json' },
|
83
|
+
verify: @verify)
|
84
|
+
logger.error('BAM Logout Failed. HTTP' + response.code.to_s + ' ' + response.body.to_s) if response.code != 200
|
85
|
+
end
|
86
|
+
|
87
|
+
# wrapper function to for rest get requests
|
88
|
+
def rest_get(endpoint, querystring)
|
89
|
+
rest_login if self.class.token.nil?
|
90
|
+
|
91
|
+
logger.debug('BAM GET ' + endpoint + '?' + querystring)
|
92
|
+
|
93
|
+
response = HTTParty.get(format('%s://%s/Services/REST/v1/%s?%s', @scheme, @host, endpoint, querystring),
|
94
|
+
headers: { 'Authorization' => 'BAMAuthToken: ' + self.class.token, 'Content-Type' => 'application/json' },
|
95
|
+
verify: @verify)
|
96
|
+
# Session propably expired, refresh it and do the request again
|
97
|
+
if response.code == 401
|
98
|
+
rest_login
|
99
|
+
response = HTTParty.get(format('%s://%s/Services/REST/v1/%s?%s', @scheme, @host, endpoint, querystring),
|
100
|
+
headers: { 'Authorization' => 'BAMAuthToken: ' + self.class.token, 'Content-Type' => 'application/json' },
|
101
|
+
verify: @verify)
|
102
|
+
end
|
103
|
+
|
104
|
+
return response.body if response.code == 200
|
105
|
+
logger.error('BAM GET Failed. HTTP' + response.code.to_s + ' ' + response.body.to_s)
|
106
|
+
end
|
107
|
+
|
108
|
+
# wrapper function to for rest post requests
|
109
|
+
def rest_post(endpoint, querystring)
|
110
|
+
logger.debug('BAM POST ' + endpoint + '?' + querystring)
|
111
|
+
response = HTTParty.post(format('%s://%s/Services/REST/v1/%s?%s', @scheme, @host, endpoint, querystring),
|
112
|
+
headers: { 'Authorization' => 'BAMAuthToken: ' + self.class.token, 'Content-Type' => 'application/json' },
|
113
|
+
verify: @verify
|
114
|
+
)
|
115
|
+
# Session propably expired, refresh it and do the request again
|
116
|
+
if response.code == 401
|
117
|
+
rest_login
|
118
|
+
response = HTTParty.post(format('%s://%s/Services/REST/v1/%s?%s', @scheme, @host, endpoint, querystring),
|
119
|
+
headers: { 'Authorization' => 'BAMAuthToken: ' + self.class.token, 'Content-Type' => 'application/json' },
|
120
|
+
verify: @verify)
|
121
|
+
end
|
122
|
+
return response.body if response.code == 200
|
123
|
+
logger.error('BAM POST Failed. HTTP' + response.code.to_s + ' ' + response.body.to_s)
|
124
|
+
end
|
125
|
+
|
126
|
+
# wrapper function to for rest put requests
|
127
|
+
def rest_put(endpoint, querystring)
|
128
|
+
logger.debug('BAM PUT ' + endpoint + '?' + querystring)
|
129
|
+
response = HTTParty.put(format('%s://%s/Services/REST/v1/%s?%s', @scheme, @host, endpoint, querystring),
|
130
|
+
headers: { 'Authorization' => 'BAMAuthToken: ' + self.class.token, 'Content-Type' => 'application/json' },
|
131
|
+
verify: @verify)
|
132
|
+
# Session propably expired, refresh it and do the request again
|
133
|
+
if response.code == 401
|
134
|
+
rest_login
|
135
|
+
response = HTTParty.put(format('%s://%s/Services/REST/v1/%s?%s', @scheme, @host, endpoint, querystring),
|
136
|
+
headers: { 'Authorization' => 'BAMAuthToken: ' + self.class.token, 'Content-Type' => 'application/json' },
|
137
|
+
verify: @verify)
|
138
|
+
end
|
139
|
+
return response.body if response.code == 200
|
140
|
+
logger.error('BAM PUT Failed. HTTP' + response.code.to_s + ' ' + response.body.to_s)
|
141
|
+
end
|
142
|
+
|
143
|
+
# wrapper function to for rest delete requests
|
144
|
+
def rest_delete(endpoint, querystring)
|
145
|
+
logger.debug('BAM DELETE ' + endpoint + '?' + querystring)
|
146
|
+
response = HTTParty.delete(format('%s://%s/Services/REST/v1/%s?%s', @scheme, @host, endpoint, querystring),
|
147
|
+
headers: { 'Authorization' => 'BAMAuthToken: ' + self.class.token, 'Content-Type' => 'application/json' },
|
148
|
+
verify: @verify)
|
149
|
+
|
150
|
+
# Session propably expired, refresh it and do the request again
|
151
|
+
if response.code == 401
|
152
|
+
rest_login
|
153
|
+
response = HTTParty.delete(format('%s://%s/Services/REST/v1/%s?%s', @scheme, @host, endpoint, querystring),
|
154
|
+
headers: { 'Authorization' => 'BAMAuthToken: ' + self.class.token, 'Content-Type' => 'application/json' },
|
155
|
+
verify: @verify)
|
156
|
+
end
|
157
|
+
return response.body if response.code == 200
|
158
|
+
logger.error('BAM DELETE Failed. HTTP' + response.code.to_s + ' ' + response.body.to_s)
|
159
|
+
end
|
160
|
+
|
161
|
+
# helper function to get the object id of a ip by an ip address
|
162
|
+
def get_addressid_by_ip(ip)
|
163
|
+
json = rest_get('getIP4Address', 'containerId=' + @config_id.to_s + '&address=' + ip)
|
164
|
+
result = JSON.parse(json)
|
165
|
+
return nil if result.empty?
|
166
|
+
result['id'].to_s
|
167
|
+
end
|
168
|
+
|
169
|
+
# helper function to get the object id of a subnet by an ip address
|
170
|
+
def get_networkid_by_ip(ip)
|
171
|
+
logger.debug('BAM get_networkid_by_ip ' + ip)
|
172
|
+
querystring = 'containerId=' + @config_id.to_s + '&type=IP4Network' + '&address=' + ip.to_s
|
173
|
+
json = rest_get('getIPRangedByIP', querystring)
|
174
|
+
result = JSON.parse(json)
|
175
|
+
return nil if result.empty?
|
176
|
+
result['id'].to_s
|
177
|
+
end
|
178
|
+
|
179
|
+
# helper function to get the whole subnet informarions by an ip address
|
180
|
+
def get_network_by_ip(ip)
|
181
|
+
logger.debug('BAM get_network_by_ip ' + ip)
|
182
|
+
querystring = 'containerId=' + @config_id.to_s + '&type=IP4Network' + '&address=' + ip.to_s
|
183
|
+
json = rest_get('getIPRangedByIP', querystring)
|
184
|
+
result = JSON.parse(json)
|
185
|
+
properties = parse_properties(result['properties'])
|
186
|
+
properties['CIDR'].to_s
|
187
|
+
end
|
188
|
+
|
189
|
+
# helper function to parse the properties scheme of bluecat into a hash
|
190
|
+
#
|
191
|
+
# properies: a string that contains properties for the object in attribute=value format, with each separated by a | (pipe) character.
|
192
|
+
# For example, a host record object may have a properties field such as ttl=123|comments=my comment|.
|
193
|
+
def parse_properties(properties)
|
194
|
+
properties = properties.split('|')
|
195
|
+
h = {}
|
196
|
+
properties.each do |property|
|
197
|
+
h[property.split('=').first.to_s] = property.split('=').last.to_s
|
198
|
+
end
|
199
|
+
h
|
200
|
+
end
|
201
|
+
|
202
|
+
# public
|
203
|
+
# wrapper function to add the dhcp reservation and dns records
|
204
|
+
def add_host(options)
|
205
|
+
# add the ip and hostname and mac as static
|
206
|
+
rest_post('addDeviceInstance', 'configName=' + @config_name +
|
207
|
+
'&ipAddressMode=PASS_VALUE' \
|
208
|
+
'&ipEntity=' + options['ip'] +
|
209
|
+
'&viewName=' + @view_name +
|
210
|
+
'&zoneName=' + options['hostname'].split('.', 2).last +
|
211
|
+
'&deviceName=' + options['hostname'] +
|
212
|
+
'&recordName=' + options['hostname'] +
|
213
|
+
'&macAddressMode=PASS_VALUE' \
|
214
|
+
'&macEntity=' + options['mac'] +
|
215
|
+
'&options=AllowDuplicateHosts=true%7C')
|
216
|
+
|
217
|
+
address_id = get_addressid_by_ip(options['ip'])
|
218
|
+
|
219
|
+
# update the state of the ip from static to dhcp reserved
|
220
|
+
rest_put('changeStateIP4Address', 'addressId=' + address_id +
|
221
|
+
'&targetState=MAKE_DHCP_RESERVED' \
|
222
|
+
'&macAddress=' + options['mac'])
|
223
|
+
|
224
|
+
unless options['nextServer'].nil? or options['filename'].nil?
|
225
|
+
rest_post('addDHCPClientDeploymentOption', 'entityId=' + address_id.to_s + '&name=tftp-server-name' + "&value=" + options['nextServer'].to_s)
|
226
|
+
rest_post('addDHCPClientDeploymentOption', 'entityId=' + address_id.to_s + '&name=boot-file-name' + "&value=" + options['filename'].to_s)
|
227
|
+
end
|
228
|
+
|
229
|
+
# deploy the config
|
230
|
+
rest_post('deployServerConfig', 'serverId=' + @server_id.to_s + '&properties=services=DHCP')
|
231
|
+
# lets wait a little bit for the complete dhcp deploy
|
232
|
+
sleep 3
|
233
|
+
rest_post('deployServerConfig', 'serverId=' + @server_id.to_s + '&properties=services=DNS')
|
234
|
+
nil
|
235
|
+
end
|
236
|
+
|
237
|
+
# public
|
238
|
+
# wrapper function to remove a ip record and depending dns records
|
239
|
+
def remove_host(ip)
|
240
|
+
ipid = get_addressid_by_ip(ip)
|
241
|
+
json = rest_get('getLinkedEntities', 'entityId=' + ipid.to_s + '&type=HostRecord&start=0&count=2')
|
242
|
+
results = JSON.parse(json)
|
243
|
+
|
244
|
+
hosts = results.map do |result|
|
245
|
+
rest_delete('delete', 'objectId=' + result['id'].to_s)
|
246
|
+
end
|
247
|
+
rest_delete('delete', 'objectId=' + ipid.to_s)
|
248
|
+
|
249
|
+
rest_post('deployServerConfig', 'serverId=' + @server_id.to_s + '&properties=services=DHCP,DNS')
|
250
|
+
end
|
251
|
+
|
252
|
+
# public
|
253
|
+
# fetches the next free address in a subnet
|
254
|
+
# +end_ip not implemented+
|
255
|
+
def next_ip(netadress, start_ip, end_ip)
|
256
|
+
networkid = get_networkid_by_ip(netadress)
|
257
|
+
|
258
|
+
start_ip = IPAddress.parse(netadress).first if start_ip.to_s.empty?
|
259
|
+
|
260
|
+
properties = 'offset=' + start_ip.to_s + '%7CexcludeDHCPRange=false'
|
261
|
+
result = rest_get('getNextIP4Address', 'parentId=' + networkid.to_s + '&properties=' + properties)
|
262
|
+
return if result.empty?
|
263
|
+
result.tr('"', '')
|
264
|
+
end
|
265
|
+
|
266
|
+
# public
|
267
|
+
# fetches all subnets under the parent_block
|
268
|
+
def subnets
|
269
|
+
json = rest_get('getEntities', 'parentId=' + @parent_block.to_s + '&type=IP4Network&start=0&count=10000')
|
270
|
+
results = JSON.parse(json)
|
271
|
+
subnets = results.map do |result|
|
272
|
+
properties = parse_properties(result['properties'])
|
273
|
+
net = IPAddress.parse(properties['CIDR'])
|
274
|
+
opts = { routers: [properties['gateway']] }
|
275
|
+
|
276
|
+
if properties['gateway'].nil?
|
277
|
+
logger.error("subnet issue: " + properties['CIDR'] + " skipped, due missing gateway in bluecat")
|
278
|
+
next
|
279
|
+
end
|
280
|
+
|
281
|
+
::Proxy::DHCP::Subnet.new(net.address, net.netmask, opts)
|
282
|
+
end
|
283
|
+
subnets.compact
|
284
|
+
end
|
285
|
+
|
286
|
+
# public
|
287
|
+
# fetches a subnet by its network address
|
288
|
+
def find_mysubnet(subnet_address)
|
289
|
+
net = IPAddress.parse(get_network_by_ip(subnet_address))
|
290
|
+
subnet = ::Proxy::DHCP::Subnet.new(net.address, net.netmask)
|
291
|
+
subnet
|
292
|
+
end
|
293
|
+
|
294
|
+
# public
|
295
|
+
# fetches all dhcp reservations in a subnet
|
296
|
+
def hosts(network_address)
|
297
|
+
netid = get_networkid_by_ip(network_address)
|
298
|
+
net = IPAddress.parse(get_network_by_ip(network_address))
|
299
|
+
subnet = ::Proxy::DHCP::Subnet.new(net.address, net.netmask)
|
300
|
+
|
301
|
+
json = rest_get('getNetworkLinkedProperties', 'networkId=' + netid.to_s)
|
302
|
+
results = JSON.parse(json)
|
303
|
+
|
304
|
+
hosts = results.map do |result|
|
305
|
+
properties = parse_properties(result['properties'])
|
306
|
+
|
307
|
+
## Static Addresses and Gateway are not needed here
|
308
|
+
## But lets keep the logic to identify them
|
309
|
+
# if properties.length() >= 4
|
310
|
+
# if properties["state"] == "Gateway" or properties["state"] == "Static"
|
311
|
+
# address = properties[0].split("=").last()
|
312
|
+
# macAddress = "00:00:00:00:00:00"
|
313
|
+
# hosttag = properties[3].split("=").last().split(":")
|
314
|
+
# name = hosttag[1] + "." + hosttag[3]
|
315
|
+
# opts = {:hostname => name}
|
316
|
+
# ::Proxy::DHCP::Reservation.new(name, address, macAddress, subnet, opts)
|
317
|
+
# end
|
318
|
+
# end
|
319
|
+
next unless properties.length >= 5
|
320
|
+
next unless properties['state'] == 'DHCP Reserved'
|
321
|
+
hosttag = properties['host'].split(':')
|
322
|
+
name = hosttag[1] + '.' + hosttag[3]
|
323
|
+
opts = { hostname: name }
|
324
|
+
::Proxy::DHCP::Reservation.new(name, properties['address'], properties['macAddress'].tr('-', ':'), subnet, opts)
|
325
|
+
end
|
326
|
+
hosts.compact
|
327
|
+
end
|
328
|
+
|
329
|
+
# public
|
330
|
+
# fetches a host by its ip
|
331
|
+
def hosts_by_ip(ip)
|
332
|
+
hosts = []
|
333
|
+
net = IPAddress.parse(get_network_by_ip(ip))
|
334
|
+
subnet = ::Proxy::DHCP::Subnet.new(net.address, net.netmask)
|
335
|
+
ipid = get_addressid_by_ip(ip)
|
336
|
+
return nil if ipid.to_s == '0'
|
337
|
+
json = rest_get('getLinkedEntities', 'entityId=' + ipid + '&type=HostRecord&start=0&count=2')
|
338
|
+
results = JSON.parse(json)
|
339
|
+
|
340
|
+
if results.empty? || (results == "Link request is not supported")
|
341
|
+
# no host record on ip, fetch mac only
|
342
|
+
json2 = rest_get('getIP4Address', 'containerId=' + @config_id.to_s + '&address=' + ip)
|
343
|
+
result2 = JSON.parse(json2)
|
344
|
+
properties2 = parse_properties(result2['properties'])
|
345
|
+
unless properties2['macAddress'].nil?
|
346
|
+
mac_address = properties2['macAddress'].tr('-', ':')
|
347
|
+
hosts.push(Proxy::DHCP::Reservation.new("", ip, mac_address, subnet, {}))
|
348
|
+
end
|
349
|
+
else
|
350
|
+
# host record on ip, return more infos
|
351
|
+
results.each do |result|
|
352
|
+
properties = parse_properties(result['properties'])
|
353
|
+
opts = { hostname: properties['absoluteName'] }
|
354
|
+
|
355
|
+
next unless properties['reverseRecord'].to_s == 'true'.to_s
|
356
|
+
json2 = rest_get('getEntityById', 'id=' + ipid)
|
357
|
+
result2 = JSON.parse(json2)
|
358
|
+
properties2 = parse_properties(result2['properties'])
|
359
|
+
unless properties2['macAddress'].nil?
|
360
|
+
mac_address = properties2['macAddress'].tr('-', ':')
|
361
|
+
hosts.push(Proxy::DHCP::Reservation.new(properties['absoluteName'], ip, mac_address, subnet, opts))
|
362
|
+
end
|
363
|
+
end
|
364
|
+
end
|
365
|
+
hosts.compact
|
366
|
+
end
|
367
|
+
|
368
|
+
# public
|
369
|
+
# fetches all dhcp reservations by a mac
|
370
|
+
def host_by_mac(mac)
|
371
|
+
json = rest_get('getMACAddress', 'configurationId=' + @config_id.to_s + '&macAddress=' + mac.to_s)
|
372
|
+
result = JSON.parse(json)
|
373
|
+
macid = result['id'].to_s
|
374
|
+
return if macid == '0'
|
375
|
+
json2 = rest_get('getLinkedEntities', 'entityId=' + macid + '&type=IP4Address&start=0&count=1')
|
376
|
+
result2 = JSON.parse(json2)
|
377
|
+
return if result2.empty?
|
378
|
+
properties = parse_properties(result2[0]['properties'])
|
379
|
+
host = hosts_by_ip(properties['address'])
|
380
|
+
return if host.nil?
|
381
|
+
host[0]
|
382
|
+
end
|
383
|
+
end
|
384
|
+
end
|
385
|
+
end
|
386
|
+
end
|