Skip to content
This repository was archived by the owner on Jun 2, 2021. It is now read-only.

Commit d8b71b6

Browse files
weymanfsethboyles
andcommitted
Remove support for Aliases/Anchors in Manifests
- move yaml body parsing to the controller action [#175290617] Co-authored-by: Weyman Fung <wfung@pivotal.io> Co-authored-by: Seth Boyles <sboyles@pivotal.io>
1 parent 9827bb8 commit d8b71b6

9 files changed

Lines changed: 136 additions & 89 deletions

File tree

app/controllers/v3/app_manifests_controller.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,10 @@ def request_content_type_is_yaml?
7979
end
8080

8181
def parsed_app_manifest_params
82-
parsed_application = params[:body]['applications'] && params[:body]['applications'].first
82+
parsed_application = parsed_yaml['applications'] && parsed_yaml['applications'].first
8383

8484
raise invalid_request!('Invalid app manifest') unless parsed_application.present?
8585

86-
parsed_application.to_unsafe_h
86+
parsed_application
8787
end
8888
end

app/controllers/v3/application_controller.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ def bad_request!(message)
3030
raise CloudController::Errors::ApiError.new_from_details('BadRequest', message)
3131
end
3232

33+
def message_parse_error!(message)
34+
raise CloudController::Errors::ApiError.new_from_details('MessageParseError', message)
35+
end
36+
3337
def service_unavailable!(message)
3438
raise CloudController::Errors::ApiError.new_from_details('ServiceUnavailable', message)
3539
end
@@ -80,6 +84,17 @@ def unmunged_body
8084
JSON.parse(request.body.string)
8185
end
8286

87+
def parsed_yaml
88+
return @parsed_yaml if @parsed_yaml
89+
90+
allow_yaml_aliases = false
91+
yaml = YAML.safe_load(request.body.string, [], [], allow_yaml_aliases)
92+
message_parse_error!('invalid request body') if !yaml.is_a? Hash
93+
@parsed_yaml = yaml
94+
rescue Psych::BadAlias
95+
bad_request!('Manifest does not support Anchors and Aliases')
96+
end
97+
8398
def roles
8499
VCAP::CloudController::SecurityContext.roles
85100
end

app/controllers/v3/space_manifests_controller.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def apply_manifest
1515
space_not_found! unless space && permission_queryer.can_read_from_space?(space.guid, space.organization.guid)
1616
unauthorized! unless permission_queryer.can_write_to_space?(space.guid)
1717

18-
messages = parsed_app_manifests.map(&:to_unsafe_h).map { |app_manifest| NamedAppManifestMessage.create_from_yml(app_manifest) }
18+
messages = parsed_app_manifests.map { |app_manifest| NamedAppManifestMessage.create_from_yml(app_manifest) }
1919
errors = messages.each_with_index.flat_map { |message, i| errors_for_message(message, i) }
2020
compound_error!(errors) unless errors.empty?
2121

@@ -49,7 +49,7 @@ def diff_manifest
4949

5050
parsed_manifests = parsed_app_manifests.map(&:to_hash)
5151

52-
messages = parsed_app_manifests.map(&:to_unsafe_h).map { |app_manifest| NamedAppManifestMessage.create_from_yml(app_manifest) }
52+
messages = parsed_app_manifests.map { |app_manifest| NamedAppManifestMessage.create_from_yml(app_manifest) }
5353
errors = messages.each_with_index.flat_map { |message, i| errors_for_message(message, i) }
5454
compound_error!(errors) unless errors.empty?
5555

@@ -92,13 +92,13 @@ def request_content_type_is_yaml?
9292
end
9393

9494
def check_version_is_supported!
95-
version = params[:body]['version']
95+
version = parsed_yaml['version']
9696
raise unprocessable!('Unsupported manifest schema version. Currently supported versions: [1].') unless !version || version == 1
9797
end
9898

9999
def parsed_app_manifests
100100
check_version_is_supported!
101-
parsed_applications = params[:body].permit!['applications']
101+
parsed_applications = parsed_yaml['applications']
102102
raise unprocessable!("Cannot parse manifest with no 'applications' field.") unless parsed_applications.present?
103103

104104
parsed_applications

config/application.rb

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,6 @@
22

33
class Application < ::Rails::Application
44
config.exceptions_app = self.routes
5-
6-
# For Rails 5 / Rack 2 - this is how to add a new parser
7-
original_parsers = ActionDispatch::Request.parameter_parsers
8-
9-
allow_yaml_aliases = true
10-
yaml_parser = lambda { |body| YAML.safe_load(body, [], [], allow_yaml_aliases).with_indifferent_access }
11-
new_parsers = original_parsers.merge({
12-
Mime::Type.lookup('application/x-yaml') => yaml_parser,
13-
Mime::Type.lookup('text/yaml') => yaml_parser,
14-
})
15-
ActionDispatch::Request.parameter_parsers = new_parsers
16-
175
config.middleware.delete ActionDispatch::Session::CookieStore
186
config.middleware.delete ActionDispatch::Cookies
197
config.middleware.delete ActionDispatch::Flash

docs/v3/source/includes/resources/manifests/_object.md.erb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
A manifest is a method for applying bulk configurations to apps and their underlying processes.
22

3+
Manifests are in the YAML format. However, anchors and aliases are not supported.
4+
35
### The manifest schema
46

57
```

spec/request/app_manifests_spec.rb

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -244,19 +244,12 @@
244244
YML
245245
end
246246

247-
it 'accepts yaml with anchors' do
247+
it 'does NOT accept yaml with anchors' do
248248
post "/v3/apps/#{app_model.guid}/actions/apply_manifest", yml_manifest, yml_headers(user_header)
249249

250-
expect(last_response.status).to eq(202)
251-
job_guid = VCAP::CloudController::PollableJobModel.last.guid
252-
expect(last_response.headers['Location']).to match(%r(/v3/jobs/#{job_guid}))
253-
254-
Delayed::Worker.new.work_off
255-
expect(VCAP::CloudController::PollableJobModel.find(guid: job_guid)).to be_complete
256-
257-
web_process = app_model.web_processes.first
258-
expect(web_process.memory).to eq(321)
259-
expect(web_process.disk_quota).to eq(321)
250+
expect(last_response.status).to eq(400)
251+
parsed_response = MultiJson.load(last_response.body)
252+
expect(parsed_response['errors'].first['detail']).to eq('Bad request: Manifest does not support Anchors and Aliases')
260253
end
261254
end
262255

spec/request/space_manifests_spec.rb

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,28 @@
458458
expect(other_events.map(&:type)).to eq(['audit.app.apply_manifest',])
459459
end
460460
end
461+
462+
context 'yaml anchors' do
463+
let(:yml_manifest) do
464+
<<~YML
465+
---
466+
applications:
467+
- name: blah
468+
processes:
469+
- type: web
470+
memory: &default_value 321M
471+
disk_quota: *default_value
472+
YML
473+
end
474+
475+
it 'does NOT accept yaml with anchors' do
476+
post "/v3/spaces/#{space.guid}/actions/apply_manifest", yml_manifest, yml_headers(user_header)
477+
478+
expect(last_response.status).to eq(400)
479+
parsed_response = MultiJson.load(last_response.body)
480+
expect(parsed_response['errors'].first['detail']).to eq('Bad request: Manifest does not support Anchors and Aliases')
481+
end
482+
end
461483
end
462484

463485
describe 'POST /v3/spaces/:guid/manifest_diff' do
@@ -713,5 +735,32 @@
713735
expect(last_response).to have_status_code(404)
714736
end
715737
end
738+
739+
context 'yaml anchors' do
740+
let(:yml_manifest) do
741+
<<~YML
742+
---
743+
applications:
744+
- name: blah
745+
processes:
746+
- type: web
747+
memory: &default_value 321M
748+
disk_quota: *default_value
749+
YML
750+
end
751+
752+
before do
753+
space.organization.add_user(user)
754+
space.add_developer(user)
755+
end
756+
757+
it 'does NOT accept yaml with anchors' do
758+
post "/v3/spaces/#{space.guid}/manifest_diff", yml_manifest, yml_headers(user_header)
759+
760+
expect(last_response.status).to eq(400)
761+
parsed_response = MultiJson.load(last_response.body)
762+
expect(parsed_response['errors'].first['detail']).to eq('Bad request: Manifest does not support Anchors and Aliases')
763+
end
764+
end
716765
end
717766
end

0 commit comments

Comments
 (0)