mirror of
https://github.com/ansible/awx.git
synced 2026-03-20 18:37:39 -02:30
fix a bug that prevents boolean inputs from being used in injectors
when used as environment variables, boolean credential values are stringified; when used in extra_vars, they are treated as actual JSON boolean values (where possible) see: #6776
This commit is contained in:
@@ -30,7 +30,7 @@ from awx.main.models.rbac import (
|
|||||||
ROLE_SINGLETON_SYSTEM_ADMINISTRATOR,
|
ROLE_SINGLETON_SYSTEM_ADMINISTRATOR,
|
||||||
ROLE_SINGLETON_SYSTEM_AUDITOR,
|
ROLE_SINGLETON_SYSTEM_AUDITOR,
|
||||||
)
|
)
|
||||||
from awx.main.utils import encrypt_field
|
from awx.main.utils import encrypt_field, to_python_boolean
|
||||||
|
|
||||||
__all__ = ['Credential', 'CredentialType', 'V1Credential']
|
__all__ = ['Credential', 'CredentialType', 'V1Credential']
|
||||||
|
|
||||||
@@ -535,6 +535,12 @@ class CredentialType(CommonModelNameNotUnique):
|
|||||||
# ansible-playbook) and a safe namespace with secret values hidden (for
|
# ansible-playbook) and a safe namespace with secret values hidden (for
|
||||||
# DB storage)
|
# DB storage)
|
||||||
for field_name, value in credential.inputs.items():
|
for field_name, value in credential.inputs.items():
|
||||||
|
|
||||||
|
if type(value) is bool:
|
||||||
|
# boolean values can't be secret/encrypted
|
||||||
|
safe_namespace[field_name] = namespace[field_name] = value
|
||||||
|
continue
|
||||||
|
|
||||||
if field_name in self.secret_fields:
|
if field_name in self.secret_fields:
|
||||||
value = decrypt_field(credential, field_name)
|
value = decrypt_field(credential, field_name)
|
||||||
safe_namespace[field_name] = '**********'
|
safe_namespace[field_name] = '**********'
|
||||||
@@ -567,6 +573,13 @@ class CredentialType(CommonModelNameNotUnique):
|
|||||||
extra_vars[var_name] = Template(tmpl).render(**namespace)
|
extra_vars[var_name] = Template(tmpl).render(**namespace)
|
||||||
safe_extra_vars[var_name] = Template(tmpl).render(**safe_namespace)
|
safe_extra_vars[var_name] = Template(tmpl).render(**safe_namespace)
|
||||||
|
|
||||||
|
# If the template renders to a stringified Boolean, they've _probably_
|
||||||
|
# set up an extra_var injection with a boolean field; extra_vars supports JSON,
|
||||||
|
# so give them the actual boolean type they want
|
||||||
|
for v in (extra_vars, safe_extra_vars):
|
||||||
|
if v[var_name] in ('True', 'False'):
|
||||||
|
v[var_name] = to_python_boolean(v[var_name])
|
||||||
|
|
||||||
if extra_vars:
|
if extra_vars:
|
||||||
args.extend(['-e', json.dumps(extra_vars)])
|
args.extend(['-e', json.dumps(extra_vars)])
|
||||||
|
|
||||||
|
|||||||
@@ -724,6 +724,37 @@ class TestJobCredentials(TestJobExecution):
|
|||||||
|
|
||||||
assert env['MY_CLOUD_API_TOKEN'] == 'ABC123'
|
assert env['MY_CLOUD_API_TOKEN'] == 'ABC123'
|
||||||
|
|
||||||
|
def test_custom_environment_injectors_with_boolean_env_var(self):
|
||||||
|
some_cloud = CredentialType(
|
||||||
|
kind='cloud',
|
||||||
|
name='SomeCloud',
|
||||||
|
managed_by_tower=False,
|
||||||
|
inputs={
|
||||||
|
'fields': [{
|
||||||
|
'id': 'turbo_button',
|
||||||
|
'label': 'Turbo Button',
|
||||||
|
'type': 'boolean'
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
injectors={
|
||||||
|
'env': {
|
||||||
|
'TURBO_BUTTON': '{{turbo_button}}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
credential = Credential(
|
||||||
|
pk=1,
|
||||||
|
credential_type=some_cloud,
|
||||||
|
inputs={'turbo_button': True}
|
||||||
|
)
|
||||||
|
self.instance.extra_credentials.add(credential)
|
||||||
|
self.task.run(self.pk)
|
||||||
|
|
||||||
|
assert self.run_pexpect.call_count == 1
|
||||||
|
call_args, _ = self.run_pexpect.call_args_list[0]
|
||||||
|
args, cwd, env, stdout = call_args
|
||||||
|
assert env['TURBO_BUTTON'] == str(True)
|
||||||
|
|
||||||
def test_custom_environment_injectors_with_reserved_env_var(self):
|
def test_custom_environment_injectors_with_reserved_env_var(self):
|
||||||
some_cloud = CredentialType(
|
some_cloud = CredentialType(
|
||||||
kind='cloud',
|
kind='cloud',
|
||||||
@@ -823,6 +854,68 @@ class TestJobCredentials(TestJobExecution):
|
|||||||
|
|
||||||
assert '-e {"api_token": "ABC123"}' in ' '.join(args)
|
assert '-e {"api_token": "ABC123"}' in ' '.join(args)
|
||||||
|
|
||||||
|
def test_custom_environment_injectors_with_boolean_extra_vars(self):
|
||||||
|
some_cloud = CredentialType(
|
||||||
|
kind='cloud',
|
||||||
|
name='SomeCloud',
|
||||||
|
managed_by_tower=False,
|
||||||
|
inputs={
|
||||||
|
'fields': [{
|
||||||
|
'id': 'turbo_button',
|
||||||
|
'label': 'Turbo Button',
|
||||||
|
'type': 'boolean'
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
injectors={
|
||||||
|
'extra_vars': {
|
||||||
|
'turbo_button': '{{turbo_button}}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
credential = Credential(
|
||||||
|
pk=1,
|
||||||
|
credential_type=some_cloud,
|
||||||
|
inputs={'turbo_button': True}
|
||||||
|
)
|
||||||
|
self.instance.extra_credentials.add(credential)
|
||||||
|
self.task.run(self.pk)
|
||||||
|
|
||||||
|
assert self.run_pexpect.call_count == 1
|
||||||
|
call_args, _ = self.run_pexpect.call_args_list[0]
|
||||||
|
args, cwd, env, stdout = call_args
|
||||||
|
assert '-e {"turbo_button": true}' in ' '.join(args)
|
||||||
|
|
||||||
|
def test_custom_environment_injectors_with_complicated_boolean_template(self):
|
||||||
|
some_cloud = CredentialType(
|
||||||
|
kind='cloud',
|
||||||
|
name='SomeCloud',
|
||||||
|
managed_by_tower=False,
|
||||||
|
inputs={
|
||||||
|
'fields': [{
|
||||||
|
'id': 'turbo_button',
|
||||||
|
'label': 'Turbo Button',
|
||||||
|
'type': 'boolean'
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
injectors={
|
||||||
|
'extra_vars': {
|
||||||
|
'turbo_button': '{% if turbo_button %}FAST!{% else %}SLOW!{% endif %}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
credential = Credential(
|
||||||
|
pk=1,
|
||||||
|
credential_type=some_cloud,
|
||||||
|
inputs={'turbo_button': True}
|
||||||
|
)
|
||||||
|
self.instance.extra_credentials.add(credential)
|
||||||
|
self.task.run(self.pk)
|
||||||
|
|
||||||
|
assert self.run_pexpect.call_count == 1
|
||||||
|
call_args, _ = self.run_pexpect.call_args_list[0]
|
||||||
|
args, cwd, env, stdout = call_args
|
||||||
|
assert '-e {"turbo_button": "FAST!"}' in ' '.join(args)
|
||||||
|
|
||||||
def test_custom_environment_injectors_with_secret_extra_vars(self):
|
def test_custom_environment_injectors_with_secret_extra_vars(self):
|
||||||
"""
|
"""
|
||||||
extra_vars that contain secret field values should be censored in the DB
|
extra_vars that contain secret field values should be censored in the DB
|
||||||
|
|||||||
Reference in New Issue
Block a user