Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #32881 - expose previous app record through safemode #8620

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 8 additions & 2 deletions app/models/application_record.rb
Expand Up @@ -9,10 +9,16 @@ class ApplicationRecord < ActiveRecord::Base
name_desc = @meta[:name_desc] || "Name of the #{@meta[:friendly_name] || @meta[:class_scope]}#{meta_example}"
property :name, String, desc: name_desc
property :present?, one_of: [true, false], desc: 'Object presence (always true)'
property :previous_revision, ApplicationRecord, desc: "Previous revision of the record as tracked in the audit, returns the same object if there is no previous revision"
end

class Jail < Safemode::Jail
allow :id, :name, :present?
class Jail < ::Safemode::Jail
allow :id, :name, :present?, :previous_revision
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would this work for resources that aren't audited?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would work? SafeMode will either work or throw a MethodNotFound exception as expected.

For Webhooks, all exposed models do have audit, we expose just couple of them at the moment.

end

# Overriden by audited for some models
def previous_revision
raise "Class #{self.class.name} is not audited"
end

self.abstract_class = true
Expand Down
4 changes: 4 additions & 0 deletions app/models/concerns/audit_associations.rb
Expand Up @@ -8,6 +8,10 @@ def audited_attributes
super.merge(associated_attributes)
end

def previous_revision
ares marked this conversation as resolved.
Show resolved Hide resolved
revision(:previous)
end

protected

# Prevent associations from being set when looking at revisions since
Expand Down
2 changes: 1 addition & 1 deletion app/models/domain.rb
Expand Up @@ -56,7 +56,7 @@ class Domain < ApplicationRecord
prop_group :basic_model_props, ApplicationRecord, meta: { example: 'example.com' }
property :fullname, String, desc: 'User name for this domain, e.g. "Primary domain for our company"'
end
class Jail < Safemode::Jail
class Jail < ApplicationRecord::Jail
allow :id, :name, :fullname
end

Expand Down
2 changes: 1 addition & 1 deletion app/models/host/managed.rb
Expand Up @@ -161,7 +161,7 @@ def build_hooks
property :created_at, 'ActiveSupport::TimeWithZone', desc: 'The time when the host was created'
property :comment, String, desc: 'Returns comment/description of this host'
end
class Jail < ::Safemode::Jail
class Jail < ApplicationRecord::Jail
allow :id, :name, :created_at, :diskLayout, :puppetmaster, :puppet_server, :puppet_ca_server, :operatingsystem, :os, :ptable, :hostgroup,
:url_for_boot, :hostgroup, :compute_resource, :domain, :ip, :ip6, :mac, :shortname, :architecture,
:model, :certname, :capabilities, :provider, :subnet, :subnet6, :token, :location, :organization, :provision_method,
Expand Down
2 changes: 1 addition & 1 deletion app/models/host_status/status.rb
Expand Up @@ -16,7 +16,7 @@ def self.presenter
::HostStatusPresenter.new(self)
end

class Jail < ::Safemode::Jail
class Jail < ApplicationRecord::Jail
allow :host, :to_global, :to_label, :status, :name, :relevant?
allow_class_method :status_name, :humanized_name
end
Expand Down
2 changes: 1 addition & 1 deletion app/models/hostgroup.rb
Expand Up @@ -107,7 +107,7 @@ class Hostgroup < ApplicationRecord
property :pxe_loader, String, desc: 'Returns boot loader to be applied on each host within this host group'
property :title, String, desc: 'Returns full title of this host group, e.g. Base/CentOS 7'
end
class Jail < Safemode::Jail
class Jail < ApplicationRecord::Jail
allow :id, :name, :diskLayout, :puppetmaster, :puppet_server, :operatingsystem, :architecture,
:ptable, :url_for_boot, :params, :puppet_proxy, :puppet_ca_server,
:os, :arch, :domain, :subnet, :subnet6, :hosts, :realm,
Expand Down
2 changes: 1 addition & 1 deletion app/models/nic/base.rb
Expand Up @@ -116,7 +116,7 @@ class Base < ApplicationRecord
property :bmc?, one_of: [true, false], desc: 'Returns true if the type of the interface is BMC, false otherwise'
property :link, one_of: [true, false], desc: 'Returns true if the interface is up, false otherwise'
end
class Jail < ::Safemode::Jail
class Jail < ApplicationRecord::Jail
allow :id, :subnet, :subnet6, :virtual?, :physical?, :mac, :ip, :ip6, :identifier, :attached_to,
:link, :tag, :domain, :vlanid, :mtu, :bond_options, :attached_devices, :mode,
:attached_devices_identifiers, :primary, :provision, :alias?, :inheriting_mac,
Expand Down
2 changes: 1 addition & 1 deletion app/models/operatingsystem.rb
Expand Up @@ -90,7 +90,7 @@ class Operatingsystem < ApplicationRecord
property :pxe_type, String, desc: 'PXE type of the operating system, e.g. kickstart'
property :password_hash, String, desc: 'Encrypted hash of the operating system password'
end
class Jail < Safemode::Jail
class Jail < ApplicationRecord::Jail
allow :id, :name, :major, :minor, :family, :to_s, :==, :release, :release_name, :kernel, :initrd, :pxe_type, :boot_files_uri, :password_hash, :mediumpath
end

Expand Down
2 changes: 1 addition & 1 deletion app/models/ptable.rb
Expand Up @@ -64,7 +64,7 @@ def base_class
sections only: %w[all additional]
prop_group :basic_model_props, ApplicationRecord, meta: { friendly_name: 'partition table', example: 'Kickstart default' }
end
class Jail < Safemode::Jail
class Jail < ApplicationRecord::Jail
allow :id, :name
end

Expand Down
2 changes: 1 addition & 1 deletion app/models/realm.rb
Expand Up @@ -39,7 +39,7 @@ class Realm < ApplicationRecord
prop_group :basic_model_props, ApplicationRecord, meta: { example: 'EXAMPLE.COM' }
property :realm_type, String, desc: 'Realm type, e.g. FreeIPA or Active Directory'
end
class Jail < ::Safemode::Jail
class Jail < ApplicationRecord::Jail
allow :id, :name, :realm_type
end
end
2 changes: 1 addition & 1 deletion app/models/smart_proxy.rb
Expand Up @@ -206,7 +206,7 @@ def get_features
property :httpboot_https_port, Integer, desc: 'Returns proxy port for HTTPS boot'
property :httpboot_https_port!, Integer, desc: 'Same as httpboot_https_port, but raises Foreman::Exception if no port is set'
end
class Jail < ::Safemode::Jail
class Jail < ApplicationRecord::Jail
allow :id, :name, :hostname, :httpboot_http_port, :httpboot_https_port, :httpboot_http_port!, :httpboot_https_port!, :url
end
end
2 changes: 1 addition & 1 deletion app/models/ssh_key.rb
Expand Up @@ -48,7 +48,7 @@ class SshKey < ApplicationRecord
property :comment, String, desc: 'Returns a key comment. The comment is usually a user identifier',
example: '@ssh-key.comment # => forman@foreman.example.com'
end
class Jail < ::Safemode::Jail
class Jail < ApplicationRecord::Jail
allow :id, :name, :user, :key, :to_export, :fingerprint, :length, :ssh_key, :type, :comment
end

Expand Down
2 changes: 1 addition & 1 deletion app/models/subnet.rb
Expand Up @@ -155,7 +155,7 @@ def model_name
property :to_label, String, desc: 'Returns the the subnet label which is a combination of name and the network address'
property :vlanid, Integer, desc: 'Returns the VLAN ID for of this subnet'
end
class Jail < ::Safemode::Jail
class Jail < ApplicationRecord::Jail
allow :id, :name, :network, :mask, :cidr, :title, :to_label, :gateway, :dns_primary, :dns_secondary, :dns_servers,
:vlanid, :mtu, :nic_delay, :boot_mode, :nil?, :has_vlanid?, :dhcp_boot_mode?, :description, :present?,
:dhcp, :dhcp?, :tftp, :tftp?, :dns, :dns?, :httpboot, :httpboot?, :template, :template?, :ipam, :ipam?
Expand Down
2 changes: 1 addition & 1 deletion app/models/template.rb
Expand Up @@ -29,7 +29,7 @@ class Template < ApplicationRecord
sections only: %w[all additional]
prop_group :basic_model_props, ApplicationRecord
end
class Jail < Safemode::Jail
class Jail < ApplicationRecord::Jail
allow :id, :name
end

Expand Down
2 changes: 1 addition & 1 deletion app/models/token.rb
Expand Up @@ -4,7 +4,7 @@ class Token < ApplicationRecord

validates :value, :host_id, :presence => true

class Jail < ::Safemode::Jail
class Jail < ApplicationRecord::Jail
allow :id, :host, :value, :expires, :nil?, :present?
end

Expand Down
2 changes: 1 addition & 1 deletion app/models/user.rb
Expand Up @@ -161,7 +161,7 @@ def as_json(options = {})
property :last_login_on, 'ActiveSupport::TimeWithZone', desc: 'Returns the user last login time, in UTC time zone'
property :disabled, one_of: [true, false], desc: 'Returns true if the user account is disabled, false otherwise'
end
class Jail < ::Safemode::Jail
class Jail < ApplicationRecord::Jail
allow :id, :login, :ssh_keys, :ssh_authorized_keys, :description, :firstname, :lastname, :mail, :last_login_on, :disabled
end

Expand Down
2 changes: 1 addition & 1 deletion app/models/usergroup.rb
Expand Up @@ -43,7 +43,7 @@ class Usergroup < ApplicationRecord

accepts_nested_attributes_for :external_usergroups, :reject_if => ->(a) { a[:name].blank? }, :allow_destroy => true

class Jail < ::Safemode::Jail
class Jail < ApplicationRecord::Jail
allow :id, :ssh_keys, :all_users, :ssh_authorized_keys
end

Expand Down
14 changes: 14 additions & 0 deletions app/registries/foreman/plugin.rb
Expand Up @@ -639,6 +639,20 @@ def extend_observable_events(events)
(@observable_events << events).flatten!.uniq!
end

def extend_allowed_instance_methods_for_jail(jail_class, *methods)
raise "Jail not defined for #{jail_class}" unless jail_class.const_defined?(:Jail)
methods.each do |method|
Object.const_get("#{jail_class}::Jail").allow_instance_method method.to_sym
end
end

def extend_allowed_class_methods_for_jail(jail_class, *methods)
raise "Jail not defined for #{jail_class}" unless jail_class.const_defined?(:Jail)
methods.each do |method|
Object.const_get("#{jail_class}::Jail").allow_class_method method.to_sym
end
end

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Example use:

diff --git a/app/models/concerns/foreman_bootdisk/host_ext.rb b/app/models/concerns/foreman_bootdisk/host_ext.rb
index 19103d7..f6b3058 100644
--- a/app/models/concerns/foreman_bootdisk/host_ext.rb
+++ b/app/models/concerns/foreman_bootdisk/host_ext.rb
@@ -44,7 +44,3 @@ module ForemanBootdisk
     end
   end
 end
-
-class Host::Managed::Jail < Safemode::Jail
-  allow :bootdisk_build?
-end
diff --git a/lib/foreman_bootdisk/engine.rb b/lib/foreman_bootdisk/engine.rb
index 84f8e43..b20f7d3 100644
--- a/lib/foreman_bootdisk/engine.rb
+++ b/lib/foreman_bootdisk/engine.rb
@@ -58,6 +58,7 @@ module ForemanBootdisk
         provision_method 'bootdisk', N_('Boot disk based')
         template_labels 'Bootdisk' => N_('Boot disk embedded template')
         allowed_template_helpers :bootdisk_chain_url, :bootdisk_raise
+        extend_allowed_instance_methods_for_jail ::Host::Managed, :bootdisk_build?

         extend_page "subnets/index" do |cx|
           cx.add_pagelet :subnet_index_action_buttons, name: 'Bootdisk', partial: 'subnets/bootdisk_action_buttons'

delegate :subscribe, to: ActiveSupport::Notifications

private
Expand Down
2 changes: 1 addition & 1 deletion app/services/medium_providers/provider.rb
Expand Up @@ -13,7 +13,7 @@ def self.friendly_name
name
end

class Jail < Safemode::Jail
class Jail < ::Safemode::Jail
allow :medium_uri, :unique_id, :errors
end

Expand Down
11 changes: 11 additions & 0 deletions test/unit/foreman/renderer/safe_mode_renderer_test.rb
Expand Up @@ -24,4 +24,15 @@ def renderer

assert_include exception.message, 'parse error on value ")"'
end

test "application record allowed methods" do
assert ::ApplicationRecord::Jail.allowed? :name
assert ::ApplicationRecord::Jail.allowed? :present?
end

test "application record child allowed methods" do
assert ::Domain::Jail.allowed? :name
assert ::Domain::Jail.allowed? :fullname
assert ::Domain::Jail.allowed? :present?
end
end