You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
An approved catalog operation's inputs are Ansible-templated on the management host #181
An approved catalog operation's inputs reach the team's own playbook as --extra-vars JSON (sdk/src/cloudfall/decision.py:874, run_command), and Ansible templates extra-var values. An input holding {{ lookup('pipe', '...') }} is evaluated on the management host when the playbook starts, with the operator's rights.
Why it matters
The proposal is approved before it runs, so a person sees the input; but an approver reads it as a value, not as code, and an agent proposing the operation chooses it. It also breaks an honest input holding {{.
The inputs aren't Cloudfall config: marking them unsafe changes what the team's playbook receives (a playbook that templates an input on purpose would stop working), and the replay code in sdk/src/cloudfall/recording.py would need to read the marked form.
Checked on main (745c129): run_command in sdk/src/cloudfall/decision.py passes invocation.inputs as --extra-vars JSON unmarked, and Ansible templates extra-var values, the same class of bug as #174.
Have the replay in sdk/src/cloudfall/recording.py read the marked form, so recorded runs replay as before
A regression test running a real ansible-playbook with an input holding {{ lookup('pipe', 'touch <marker>') }}: the marker is never created and the playbook sees the literal text
Behaviour change: a team playbook that relied on an input being evaluated as Jinja would get the literal text. I'll link the PR here.
@romamo Decision needed: should the inputs of an approved catalog operation reach the team's playbook as plain text, never evaluated as {{ ... }}?
Plain text (recommended): an input can't run code on the management host, and an honest {{ in an input works; a team playbook that wanted an input evaluated as a template gets the literal text instead
Refuse inputs holding {{ or {% when the operation is proposed: nothing changes for the playbook, but such inputs can't be given at all
Leave it: the approval of the proposal is the boundary, and the approver has to spot the expression
Reply here with a number or your own answer; shipmill takes this up on the tick after your reply.
PR: #189, on the maintainer's answer (1, plain text).
run_command in sdk/src/cloudfall/decision.py, the one place that builds a catalog operation's --extra-vars, now marks every input string with as_ansible_data from #179, so check mode, decisions approve and agent investigate hand an input holding {{ ... }} to the team's playbook as written; integers and booleans keep their types. The replay in recording.py reads the marked argv back unmarked, so recordings made before the change still match. The decision record's inputs and its schema are unchanged.
Behaviour change: a team playbook that relied on an input being evaluated as Jinja gets the literal text. Proof: a real ansible-playbook run with {{ lookup('pipe', 'touch <marker>') }} as an input creates the marker on main and not on the PR.
Released in v0.8.0rc14 (pre-release).
A plain install gets it with the next stable release.
If you filed this: react 👍 on this comment once it works for you, or reply if it doesn't.
Activity
shipmill-romamo commentedon Oct 30, 2026
Triage: implement. Waits on your decision below.
Checked on main (745c129):
run_commandinsdk/src/cloudfall/decision.pypassesinvocation.inputsas--extra-varsJSON unmarked, and Ansible templates extra-var values, the same class of bug as #174.The plan, once decided:
{"__ansible_unsafe": ...}) in the--extra-varsJSON, the form Hand declared config strings to Ansible as data, never as templates (#174) #179 uses for the inventorysdk/src/cloudfall/recording.pyread the marked form, so recorded runs replay as beforeansible-playbookwith an input holding{{ lookup('pipe', 'touch <marker>') }}: the marker is never created and the playbook sees the literal textBehaviour change: a team playbook that relied on an input being evaluated as Jinja would get the literal text. I'll link the PR here.
shipmill-romamo commentedon Oct 30, 2026
@romamo Decision needed: should the inputs of an approved catalog operation reach the team's playbook as plain text, never evaluated as
{{ ... }}?{{in an input works; a team playbook that wanted an input evaluated as a template gets the literal text instead{{or{%when the operation is proposed: nothing changes for the playbook, but such inputs can't be given at allReply here with a number or your own answer; shipmill takes this up on the tick after your reply.
shipmill-romamo commentedon Oct 31, 2026
Decision by @romamo, relayed by Claude Code
shipmill-romamo commentedon Oct 31, 2026
PR: #189, on the maintainer's answer (1, plain text).
run_commandinsdk/src/cloudfall/decision.py, the one place that builds a catalog operation's--extra-vars, now marks every input string withas_ansible_datafrom #179, so check mode,decisions approveandagent investigatehand an input holding{{ ... }}to the team's playbook as written; integers and booleans keep their types. The replay inrecording.pyreads the marked argv back unmarked, so recordings made before the change still match. The decision record'sinputsand its schema are unchanged.Behaviour change: a team playbook that relied on an input being evaluated as Jinja gets the literal text. Proof: a real
ansible-playbookrun with{{ lookup('pipe', 'touch <marker>') }}as an input creates the marker on main and not on the PR.shipmill-romamo commentedon Oct 31, 2026
Released in v0.8.0rc14 (pre-release).
A plain install gets it with the next stable release.
If you filed this: react 👍 on this comment once it works for you, or reply if it doesn't.