From 7f4d58ec592282cfcec72c46c584bc9f66862039 Mon Sep 17 00:00:00 2001 From: Joe Rafaniello Date: Thu, 8 Aug 2024 16:36:55 -0400 Subject: [PATCH] Permit yaml safe_load of aliases in automate ruby methods Psych 4 defaults to safe_load, which defaults to not permitting aliases or classes not in an approved list. This is similar to what we do in the core application here: https://github.com/ManageIQ/manageiq/blob/46c992aaee664ea79713020e60c0342f703a8bc6/lib/extensions/yaml_load_aliases.rb#L9 The difference is we don't want to pull in application models/classes as permitted classes, at least until we know why we need them. Also, automate's ruby invocation is somewhat isolated from the application and doesn't really pull much into the remote ruby process beyond active support and some minor changes. We're instead, just extending YAML.safe_load to permit aliases in this change. We can add more later or find a better way to share code if that is needed. --- .../miq_ae_engine/drb_remote_invoker.rb | 8 +++++ spec/engine/miq_ae_method_spec.rb | 32 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/lib/miq_automation_engine/engine/miq_ae_engine/drb_remote_invoker.rb b/lib/miq_automation_engine/engine/miq_ae_engine/drb_remote_invoker.rb index 11b0bcf0..cdd08866 100644 --- a/lib/miq_automation_engine/engine/miq_ae_engine/drb_remote_invoker.rb +++ b/lib/miq_automation_engine/engine/miq_ae_engine/drb_remote_invoker.rb @@ -110,6 +110,14 @@ class AutomateMethodException < StandardError require 'drb' require 'yaml' + YAML.singleton_class.prepend( + Module.new do + def safe_load(yaml, aliases: false, **kwargs) + super(yaml, aliases: true, **kwargs) + end + end + ) + Time.zone = 'UTC' MIQ_OK = 0 diff --git a/spec/engine/miq_ae_method_spec.rb b/spec/engine/miq_ae_method_spec.rb index ea5c1142..f89667e7 100644 --- a/spec/engine/miq_ae_method_spec.rb +++ b/spec/engine/miq_ae_method_spec.rb @@ -47,6 +47,38 @@ def root end end + context "with a script that tries to YAML.load with aliases" do + let(:script) do + <<-RUBY + YAML.load("---\na: &a\n b: true \n\ndevelopment:\n <<: *a\n c: false\n\n") + RUBY + end + + it "logs and returns the correct exit status" do + allow($miq_ae_logger).to receive(:info).and_call_original + expect($miq_ae_logger).to receive(:info).with("Method exited with rc=MIQ_OK", :resource_id => 123).at_least(:once) + expect($miq_ae_logger).to_not receive(:error) + + expect(subject).to eq(0) + end + end + + context "with a script that tries to YAML.safe_load with aliases" do + let(:script) do + <<-RUBY + YAML.safe_load("---\na: &a\n b: true \n\ndevelopment:\n <<: *a\n c: false\n\n") + RUBY + end + + it "logs and returns the correct exit status" do + allow($miq_ae_logger).to receive(:info).and_call_original + expect($miq_ae_logger).to receive(:info).with("Method exited with rc=MIQ_OK", :resource_id => 123).at_least(:once) + expect($miq_ae_logger).to_not receive(:error) + + expect(subject).to eq(0) + end + end + context "with a script that raises" do let(:script) do <<-RUBY