Skip to content

Commit 021be88

Browse files
committed
Added pxe server request validation.
1 parent 96aedf6 commit 021be88

File tree

3 files changed

+112
-33
lines changed

3 files changed

+112
-33
lines changed
Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,40 @@
11
module Api
22
class PxeServersController < BaseController
3-
INVALID_PXE_SERVER_ATTRS = %w[id href].freeze # Cannot update or create these
4-
53
include Subcollections::PxeImages
64
include Subcollections::PxeMenus
5+
INVALID_ATTRIBUTES = {
6+
"PxeServer" => %w[id href], # Cannot update or create these
7+
}.freeze
8+
PXE_ATTRIBUTES = {
9+
"PxeServer" => %w[name uri],
10+
"PxeMenu" => %w[file_name],
11+
"Authentication" => %w[userid password]
12+
}.freeze
713

814
def create_resource(_type, _id, data = {})
9-
validate_pxe_server_create_data(data)
15+
authentication = data.delete('authentication')
1016
menus = data.delete('pxe_menus')
17+
validate_data_for('PxeServer', data)
1118

12-
server = collection_class(:pxe_servers).create(data)
13-
if server.invalid?
14-
raise BadRequestError, "Failed to add a pxe server - #{server.errors.full_messages.join(', ')}"
15-
end
19+
PxeServer.transaction do
20+
server = collection_class(:pxe_servers).new(data)
21+
# generates uir_prefix which checks if server needs authentication or not
22+
server.verify_uri_prefix_before_save
23+
24+
if server.requires_credentials? && server.missing_credentials?
25+
validate_data_for('Authentication', authentication || {})
26+
server.update_authentication({:default => authentication.compact}, {:save => true})
27+
end
28+
29+
server.pxe_menus = create_pxe_menus(menus) if menus
30+
31+
if server.invalid?
32+
raise BadRequestError, "Failed to add a pxe server - #{server.errors.full_messages.join(', ')}"
33+
end
1634

17-
server.pxe_menus = create_pxe_menus(menus) if menus
18-
server
35+
server.save
36+
server
37+
end
1938
end
2039

2140
def delete_resource(_type, id = nil, data = nil)
@@ -27,34 +46,33 @@ def delete_resource(_type, id = nil, data = nil)
2746
def edit_resource(type, id, data)
2847
server = resource_search(id, type, collection_class(:pxe_servers))
2948
menus = data.delete('pxe_menus')
30-
if menus
31-
server.pxe_menus.clear
32-
data['pxe_menus'] = create_pxe_menus(menus)
49+
authentication = data.delete('authentication')
50+
PxeServer.transaction do
51+
if menus
52+
server.pxe_menus.clear
53+
data['pxe_menus'] = create_pxe_menus(menus)
54+
end
55+
server.update!(data)
56+
server.update_authentication({:default => authentication.transform_keys(&:to_sym)}, {:save => true}) if authentication && server.requires_credentials?
57+
server
3358
end
34-
35-
server.update!(data)
36-
server
3759
end
3860

3961
private
4062

4163
def create_pxe_menus(menus)
64+
menus.each do |menu|
65+
validate_data_for('PxeMenu', menu)
66+
end
4267
menus.map do |menu|
4368
collection_class(:pxe_menus).create(menu)
4469
end
4570
end
4671

47-
def validate_pxe_server_data(data)
48-
bad_attrs = data.keys.select { |k| INVALID_PXE_SERVER_ATTRS.include?(k) }.compact.join(", ")
49-
raise BadRequestError, "Invalid attribute(s) #{bad_attrs} specified for a pxe server" if bad_attrs.present?
50-
end
51-
52-
def validate_pxe_server_create_data(data)
53-
validate_pxe_server_data(data)
54-
req_attrs = %w[name uri]
72+
def validate_data_for(klass, data)
5573
bad_attrs = []
56-
req_attrs.each { |attr| bad_attrs << attr if data[attr].blank? }
57-
raise BadRequestError, "Missing attribute(s) #{bad_attrs.join(', ')} for creating a pxe server" if bad_attrs.present?
74+
PXE_ATTRIBUTES[klass].each { |attr| bad_attrs << attr if data[attr].blank? }
75+
raise BadRequestError, "Missing attribute(s) #{bad_attrs.join(', ')} for creating a #{klass}" if bad_attrs.present?
5876
end
5977
end
6078
end

config/api.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2420,6 +2420,8 @@
24202420
:post:
24212421
- :name: create
24222422
:identifier: pxe_server_create
2423+
- :name: edit
2424+
:identifier: pxe_server_edit
24232425
:patch:
24242426
- :name: edit
24252427
:identifier: pxe_server_edit
@@ -2433,6 +2435,17 @@
24332435
:get:
24342436
- :name: read
24352437
:identifier: pxe_server_view
2438+
:patch:
2439+
- :name: edit
2440+
:identifier: pxe_server_edit
2441+
:post:
2442+
- :name: create
2443+
:identifier: pxe_server_create
2444+
- :name: edit
2445+
:identifier: pxe_server_edit
2446+
:delete:
2447+
- :name: delete
2448+
:identifier: pxe_server_delete
24362449
:quotas:
24372450
:description: TenantQuotas
24382451
:options:

spec/requests/pxe_servers_spec.rb

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
RSpec.describe 'PxeServers API' do
2-
let!(:pxe_server) { FactoryBot.create(:pxe_server) }
2+
let(:pxe_server) { FactoryBot.build(:pxe_server).tap { |x| x.update_authentication(:default => {:userid => 'foo', :password => 'bar'}) } }
33
let!(:pxe_image_1) { FactoryBot.create(:pxe_image, :pxe_server => pxe_server) }
44
let!(:pxe_image_2) { FactoryBot.create(:pxe_image, :pxe_server => pxe_server) }
55
let!(:pxe_menu_1) { FactoryBot.create(:pxe_menu, :pxe_server => pxe_server) }
@@ -142,31 +142,73 @@
142142

143143
it 'create new pxe server' do
144144
api_basic_authorize collection_action_identifier(:pxe_servers, :create, :post)
145-
post(url, :params => {:name => 'foo', :uri => 'bar/quax'})
145+
post(
146+
url,
147+
:params => {
148+
:name => 'test server',
149+
:uri => 'bar://quax',
150+
:authentication => {
151+
:userid => 'foo',
152+
:password => 'bar'
153+
}
154+
}
155+
)
156+
expect(response).to have_http_status(:ok)
157+
expect(response.parsed_body['results'].first['name']).to eq('test server')
158+
expect(response.parsed_body['results'].first['uri']).to eq('bar://quax')
159+
expect(response.parsed_body['results'].first['uri_prefix']).to eq('bar')
160+
end
161+
162+
it 'create new nfs pxe server without authentication' do
163+
api_basic_authorize collection_action_identifier(:pxe_servers, :create, :post)
164+
post(url, :params => {:name => 'test server', :uri => 'nfs://quax'})
146165
expect(response).to have_http_status(:ok)
147-
expect(response.parsed_body['results'].first['name']).to eq('foo')
148-
expect(response.parsed_body['results'].first['uri']).to eq('bar/quax')
166+
expect(response.parsed_body['results'].first['name']).to eq('test server')
167+
expect(response.parsed_body['results'].first['uri']).to eq('nfs://quax')
168+
expect(response.parsed_body['results'].first['uri_prefix']).to eq('nfs')
149169
end
150170

151171
it 'create new pxe server with pxe menu' do
152172
api_basic_authorize collection_action_identifier(:pxe_servers, :create, :post)
153-
post(url, :params => {:name => 'foo', :uri => 'bar/quax', :pxe_menus => [{:file_name => 'menu_1'}]})
173+
post(url, :params => {:name => 'foo', :uri => 'bar://quax',
174+
:pxe_menus => [{:file_name => 'menu_1'}, {:file_name => 'menu_2'}],
175+
:authentication => {:userid => 'foo', :password => 'bar' }})
154176
expect(response).to have_http_status(:ok)
155177
expect(PxeServer.find(response.parsed_body['results'].first['id']).pxe_menus.first[:file_name]).to eq('menu_1')
156178
end
179+
180+
it 'fail to create new non nfs pxe server without correct authentication' do
181+
api_basic_authorize collection_action_identifier(:pxe_servers, :create, :post)
182+
post(url, :params => {:name => 'test server', :uri => 'smb://quax', :authentication => {:userid => 'user'}})
183+
expect(response).to have_http_status(:bad_request)
184+
end
185+
186+
it 'will forbid create action withouth an appropriate authorization' do
187+
api_basic_authorize
188+
post(url, :params => {:name => 'foo', :uri => 'bar/quax',
189+
:pxe_menus => [{:file_name => 'menu_1'}, {:file_name => 'menu_2'}],
190+
:authentication => {:userid => 'foo', :password => 'bar' }})
191+
expect(response).to have_http_status(:forbidden)
192+
end
157193
end
158194

159-
describe 'patch /api/pxe_servers/:id' do
195+
describe 'update /api/pxe_servers/:id' do
160196
let(:url) { "/api/pxe_servers/#{pxe_server.id}" }
161197

162198
it 'update pxe server' do
163199
api_basic_authorize collection_action_identifier(:pxe_servers, :edit, :patch)
164-
patch(url, :params => {:name => 'updated name', :uri => 'updated/url', :pxe_menus => [{:file_name => 'updated menu'}]})
200+
patch(url, :params => {:name => 'updated name', :uri => 'updated://url', :pxe_menus => [{:file_name => 'updated menu'}]})
165201
expect(response).to have_http_status(:ok)
166202
expect(response.parsed_body['name']).to eq('updated name')
167-
expect(response.parsed_body['uri']).to eq('updated/url')
203+
expect(response.parsed_body['uri']).to eq('updated://url')
168204
expect(PxeServer.find(response.parsed_body['id']).pxe_menus.first[:file_name]).to eq('updated menu')
169205
end
206+
207+
it 'will forbid update action withouth an appropriate authorization' do
208+
api_basic_authorize
209+
patch(url, :params => {:name => 'updated name', :uri => 'updated://url', :pxe_menus => [{:file_name => 'updated menu'}]})
210+
expect(response).to have_http_status(:forbidden)
211+
end
170212
end
171213

172214
describe 'delete /api/pxe_servers/:id' do
@@ -178,5 +220,11 @@
178220
expect(response).to have_http_status(:no_content)
179221
expect(PxeServer.exists?(pxe_server.id)).to be_falsey
180222
end
223+
224+
it 'will forbid delete action withouth an appropriate authorization' do
225+
api_basic_authorize
226+
delete(url)
227+
expect(response).to have_http_status(:forbidden)
228+
end
181229
end
182230
end

0 commit comments

Comments
 (0)