-
Notifications
You must be signed in to change notification settings - Fork 112
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 #37418 - Fixes an issue that caused hidden Ansible variables to be shown in plain text on the Host-Details page #717
base: master
Are you sure you want to change the base?
Changes from all commits
1b2ed8b
00c8843
0db5002
aba8374
cfb1bc0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,18 +2,33 @@ module Presenters | |
class OverridenAnsibleVariablePresenter | ||
attr_reader :ansible_variable | ||
|
||
delegate :id, :key, :description, :override?, | ||
:parameter_type, :hidden_value?, :omit, :required, | ||
:validator_type, :validator_rule, :default_value, | ||
delegate :id, :key, :description, | ||
:parameter_type, :omit, :required, | ||
:validator_type, :validator_rule, | ||
:ansible_role, :current_value, :to => :ansible_variable | ||
def hidden_value | ||
ansible_variable.hidden_value? | ||
end | ||
|
||
def override | ||
ansible_variable.override? | ||
end | ||
|
||
def initialize(ansible_variable, override_resolver) | ||
@ansible_variable = ansible_variable | ||
@override_resolver = override_resolver | ||
end | ||
|
||
def default_value | ||
ansible_variable.editable_by_user? ? ansible_variable.default_value : '*****' | ||
Thorben-D marked this conversation as resolved.
Show resolved
Hide resolved
|
||
end | ||
|
||
def current_value | ||
@override_resolver.resolve @ansible_variable | ||
resolved = @override_resolver.resolve @ansible_variable | ||
unless resolved.nil? | ||
resolved[:value] = '*****' unless ansible_variable.editable_by_user? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here, we can use |
||
end | ||
Thorben-D marked this conversation as resolved.
Show resolved
Hide resolved
|
||
resolved | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,18 @@ | ||
module ForemanAnsible | ||
class AnsibleInfo < ::HostInfo::Provider | ||
def host_info | ||
{ 'parameters' => ansible_params } | ||
def host_info(redact_secrets = false) | ||
{ 'parameters' => ansible_params(redact_secrets) } | ||
end | ||
|
||
def ansible_params | ||
def ansible_params(redact_secrets = false) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the value of |
||
variables = AnsibleVariable.where(:ansible_role_id => host.all_ansible_roles.pluck(:id), :override => true) | ||
values = variables.values_hash(host) | ||
|
||
variables.each_with_object({}) do |var, memo| | ||
value = values[var] | ||
memo[var.key] = value unless value.nil? | ||
unless value.nil? | ||
memo[var.key] = redact_secrets && var.hidden_value? ? var.hidden_value : value | ||
end | ||
memo | ||
end | ||
end | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,28 +19,32 @@ def initialize(hosts, template_invocation = nil) | |
# more advanced cases). Therefore we have only the 'all' group | ||
# with all hosts. | ||
def to_hash | ||
to_hash_with_secrets_redacted(false) | ||
end | ||
|
||
def to_hash_with_secrets_redacted(redact_secrets = true) | ||
Thorben-D marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't see a need to add this new method if it’s just duplicating the content of |
||
hosts = @hosts.map(&:name) | ||
|
||
{ 'all' => { 'hosts' => hosts, | ||
'vars' => template_inputs(@template_invocation) }, | ||
'_meta' => { 'hostvars' => hosts_vars } } | ||
'_meta' => { 'hostvars' => hosts_vars(redact_secrets) } } | ||
end | ||
|
||
def hosts_vars | ||
def hosts_vars(redact_secrets = false) | ||
hosts.reduce({}) do |hash, host| | ||
hash.update( | ||
host.name => host_vars(host) | ||
host.name => host_vars(host, redact_secrets) | ||
) | ||
end | ||
end | ||
|
||
def host_vars(host) | ||
def host_vars(host, redact_secrets = false) | ||
{ | ||
'foreman' => reduced_host_info(host).fetch('parameters', {}), | ||
'foreman_ansible_roles' => host_roles(host) | ||
}.merge(connection_params(host)). | ||
merge(host_params(host)). | ||
merge(ansible_params(host)) | ||
merge(ansible_params(host, redact_secrets)) | ||
end | ||
|
||
def connection_params(host) | ||
|
@@ -62,8 +66,8 @@ def host_roles(host) | |
host.all_ansible_roles.map(&:name) | ||
end | ||
|
||
def ansible_params(host) | ||
ForemanAnsible::AnsibleInfo.new(host).ansible_params | ||
def ansible_params(host, redact_secrets = false) | ||
ForemanAnsible::AnsibleInfo.new(host).ansible_params(redact_secrets) | ||
end | ||
|
||
def reduced_host_info(host) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,7 +9,10 @@ import AnsibleHostInventory from './AnsibleHostInventory'; | |
import ErrorState from '../../../ErrorState'; | ||
|
||
const WrappedAnsibleHostInventory = ({ hostId }) => { | ||
const params = useMemo(() => ({ params: { host_ids: [hostId] } }), [hostId]); | ||
const params = useMemo( | ||
() => ({ params: { host_ids: [hostId], redact_secrets: true } }), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why are we always sending There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For the inventory, I am unsure what's best. As opposed to the variables, there is no action to toggle the visibility of hidden variables. I chose to hide hidden variables in the inventory for everyone, as permitted users are able to view those values under the "Variables" tab. I also feel like showing the values by default sort of defeats the purpose of hiding them. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As I mentioned, I prefer not to change the current behavior where authorized users can view hidden values in the inventory. Consider a scenario where someone is using Foreman with a script that makes API calls to retrieve the inventory and relies on those variable values. If we change this behavior, it could break their setup. However, if you believe your approach is better, feel free to initiate a discussion in the community to gather more opinions. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I should note that the variables are only hidden if |
||
[hostId] | ||
); | ||
|
||
const url = hostId && foremanUrl('/ansible/api/ansible_inventories/hosts'); | ||
const { response: inventory, status } = useAPI('get', url, params); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
import React from 'react'; | ||
import { TextInput } from '@patternfly/react-core'; | ||
import { TimesIcon, CheckIcon } from '@patternfly/react-icons'; | ||
import { sprintf, translate as __ } from 'foremanReact/common/I18n'; | ||
|
||
|
@@ -22,6 +23,21 @@ export const formatValue = variable => { | |
? variable.currentValue.value | ||
: variable.defaultValue; | ||
|
||
if (variable.hiddenValue) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unfortunately, the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On second thought, this block isn't necessary. If the user is authorized to view hidden values, we can simply display them as is. If they aren’t authorized, the value should already be hidden by the backend before it's sent. |
||
return ( | ||
<TextInput | ||
value="Not the secrets you're looking for..." | ||
type="password" | ||
aria-label="hidden ansible variable" | ||
isDisabled | ||
style={{ | ||
'--pf-c-form-control--BackgroundColor': 'white', | ||
color: 'black', | ||
}} | ||
/> | ||
); | ||
} | ||
|
||
switch (variable.parameterType) { | ||
case 'boolean': | ||
return value ? <CheckIcon /> : <TimesIcon />; | ||
|
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.
Where are we using this value?
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.
Currently nowhere. This is added by #716
You mentioned removing unnecessary fields. This one could be removed, but it will have to be done in the other PR.