-
Notifications
You must be signed in to change notification settings - Fork 987
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 #29974 - allow subnet helpers #7713
Fixes #29974 - allow subnet helpers #7713
Conversation
Issues: #29974 |
app/models/smart_proxy.rb
Outdated
@@ -172,6 +172,6 @@ def get_features | |||
end | |||
|
|||
class Jail < ::Safemode::Jail | |||
allow :id, :name | |||
allow :id, :name, :hostname, :hosts_count |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can it be a problem that Katello also defines the hostname?
https://github.com/Katello/katello/blob/a9abccc2c10f5f2c1194d564834d131d57b28401/app/models/katello/concerns/smart_proxy_extensions.rb#L336-L338
Either way, after merging this that can be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we need the hosts_count?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will do a followup PR into Katello.
That hosts_count
was added by accident, not needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done: Katello/katello#8748
f436b8d
to
e30c1ce
Compare
app/models/smart_proxy.rb
Outdated
@@ -172,6 +172,6 @@ def get_features | |||
end | |||
|
|||
class Jail < ::Safemode::Jail | |||
allow :id, :name | |||
allow :id, :name, :hostname, :hosts_count, :setting |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does setting
allow to retrieve any secret settings?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It allows retrieving settings of a smart proxy feature. I don't think those contain any secrets
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we perhaps expose those explicitly? Features are just strings and exposed on the individual proxies without any authentication so that's IMHO safe. If you're talking about exposed settings from a proxy then those can contain private information and they're only available via an authenticated endpoint (though I'm not aware of any secrets being passed now).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From my testing machine:
SmartProxyFeature.all.each { |f| puts "#{f.feature.name}: #{f.settings}" }
Pulp: {"pulp_url"=>"https://centos7-katello-nightly-stable.example.com/pulp"}
Pulpcore: {"pulp_url"=>"https://centos7-katello-nightly-stable.example.com", "mirror"=>false, "content_app_url"=>"https://centos7-katello-nightly-stable.example.com/pulp/content"}
TFTP: {"tftp_servername"=>nil}
Puppet CA: {"puppet_url"=>"https://centos7-katello-nightly-stable.example.com:8140", "use_provider"=>["puppetca_hostname_whitelisting", "puppetca_http_api"]}
Puppet: {"puppet_url"=>"https://centos7-katello-nightly-stable.example.com:8140", "use_provider"=>["puppet_proxy_puppet_api"]}
Logs: {}
Templates: {}
HTTPBoot: {"http_port"=>8000, "https_port"=>9090}
it looks like those don't contain any secrets, but that is no guarrantee that they never will
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/theforeman/smart_proxy_pulp/blob/55ff29f4cfab971f71bc00273c7623ee8dc5af96/lib/smart_proxy_pulp_plugin/pulpcore_plugin.rb#L17-L18 does expose a username/password. It's mostly used in the development workflow if you don't have certificates set up so you won't see it in production, but exposing this is a security risk.
Another thing to consider is that these settings are IMHO internal implementation details. You should always wrap them in high level logic. For example, the puppet server url has a one that also provides compatibility with older releases which didn't expose this:
foreman/app/models/concerns/host_common.rb
Lines 95 to 100 in c356041
def puppet_server_uri | |
return unless puppet_proxy | |
url = puppet_proxy.setting('Puppet', 'puppet_url') | |
url ||= "https://#{puppet_proxy}:8140" | |
URI(url) | |
end |
That particular helper should be exposed rather than raw settings.
👎 on exposing setting
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok how about that, I have implemented whitelisting.
e30c1ce
to
1194a15
Compare
app/models/smart_proxy.rb
Outdated
"https_port", | ||
] | ||
def safe_setting(feature, setting) | ||
raise ::Foreman::Exception.new(N_("Setting is not whitelisted: %s"), ALLOWED_SETTINGS) unless ALLOWED_SETTINGS.include?(setting) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shows what settings are allowed, but not which setting was actually requested
::Foreman::Exception.new(N_("Setting is not whitelisted: %s"), ALLOWED_SETTINGS).message
=> "ERF42-4295 [Foreman::Exception]: Setting is not whitelisted: [\"http_port\", \"https_port\"]"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixing and adding tests for this.
1194a15
to
5361a33
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👎 because I still think explicit wrappers are better. For example, this doesn't look at the feature at all. You will also end up with duplicated logic.
foreman/app/models/operatingsystem.rb
Lines 229 to 240 in c356041
if host.subnet&.httpboot? | |
if host.pxe_loader =~ /UEFI HTTPS/ | |
port = host.subnet.httpboot.setting(:HTTPBoot, 'https_port') || raise(::Foreman::Exception.new(N_("HTTPS boot requires proxy with httpboot feature and https_port exposed setting"))) | |
else | |
port = host.subnet.httpboot.setting(:HTTPBoot, 'http_port') || raise(::Foreman::Exception.new(N_("HTTP boot requires proxy with httpboot feature and http_port exposed setting"))) | |
end | |
hostname = URI.parse(host.subnet.httpboot.url).hostname | |
self.class.all_loaders_map(architecture, "#{hostname}:#{port}")[host.pxe_loader] | |
else | |
raise(::Foreman::Exception.new(N_("HTTP UEFI boot requires proxy with httpboot feature"))) if host.pxe_loader =~ /UEFI HTTP/ | |
self.class.all_loaders_map(architecture)[host.pxe_loader] | |
end |
That logic block contains a lot of the same things. We've already seen multiple times that users couldn't even manage to debug that error message. If we expose raw settings it'll be even harder. The wrapper can raise a proper error.
5361a33
to
f74beb3
Compare
Okay, I've extracted this into two methods. How about now? |
Tests are passing now @ekohl |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It exposes all the settings we need in a safe manner without exposing things we don't need. 👍 from me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! @tbrisker any last thoughts?
@@ -100,6 +100,14 @@ def setting(feature, setting) | |||
smart_proxy_features.find_by(:feature_id => Feature.find_by(:name => feature)).try(:settings).try(:[], setting) | |||
end | |||
|
|||
def httpboot_http_port | |||
setting(:HTTPBoot, 'http_port') || raise(::Foreman::Exception.new(N_("HTTP boot requires proxy with httpboot feature and http_port exposed setting"))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to check if the proxy has the appropriate feature?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC the data model is that the settings are stored in the Feature model. So having a setting implies the feature. It may be useful to check it separate when you want to raise more explicit exceptions. I can imagine a FeatureMissingException
or something. However, that's not a requirement for this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code actually does this. Method settings
uses try
. If you scroll to the right, you will see the error saying either feature is missing or port is not exposed.
Katello failures seem unrelated, merging |
Thank you @lzap! |
(cherry picked from commit 89c1e28)
(cherry picked from commit 89c1e28)
SSIA