Encode zuul.message with base64

Zuul recently added zuul.message which needs to be protected against
interpretation by jinja in ansible. This was initially done by marking
it with the !unsafe tag. However this has the disadvantage that the
inventory is no longer parsable by standard yaml parsers without
teaching them the !unsafe tag.

There is a similar simple possibility that doesn't rely on this tag by
base64 encoding the commit message. Ansible has filters for decoding
this so it is still quite easy to deal with base64 encoded vars in
ansible via '{{ zuul.message | b64decode }}'.

Change-Id: I9628e2770dda120b269612e28bb6217036942b8e
This commit is contained in:
Tobias Henkel 2019-02-23 09:18:50 +01:00
parent d60346181b
commit fcbb91582f
No known key found for this signature in database
GPG Key ID: 03750DEC158E5FA2
6 changed files with 30 additions and 28 deletions

View File

@ -566,7 +566,18 @@ are available:
.. var:: message
The commit or pull request message of the change.
The commit or pull request message of the change base64 encoded. Use the
`b64decode` filter in ansible when working with it.
.. code-block:: yaml
- hosts: all
tasks:
- name: Dump commit message
copy:
content: "{{ zuul.message | b64decode }}"
dest: "{{ zuul.executor.log_root }}/commit-message.txt"
Branch Items
~~~~~~~~~~~~

View File

@ -0,0 +1,8 @@
---
upgrade:
- |
Zuul recently added the job variable :var:`zuul.message`. This can contain
jinja tags which can cause problems accessing the zuul variable in the job.
Because of this the message is now base64 encoded and any job evaluating
this variable needs to be changed from ``{{ zuul.message }}`` to
``{{ zuul.message | b64decode }}``.

View File

@ -2,5 +2,5 @@
tasks:
- name: Dump commit message
copy:
content: "{{ zuul.message }}"
content: "{{ zuul.message | b64decode }}"
dest: "{{ zuul.executor.log_root }}/commit-message.txt"

View File

@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import base64
import os
import yaml
@ -61,7 +62,7 @@ class TestInventory(TestInventoryBase):
self.assertIn('src_root', z_vars['executor'])
self.assertIn('job', z_vars)
self.assertEqual(z_vars['job'], 'single-inventory')
self.assertEqual(str(z_vars['message']), 'A')
self.assertEqual(z_vars['message'], 'QQ==')
self.executor_server.release()
self.waitUntilSettled()
@ -192,9 +193,9 @@ class TestAnsibleInventory(AnsibleZuulTestCase):
inv_path = os.path.join(build.jobdir.root, 'ansible', 'inventory.yaml')
inventory = yaml.safe_load(open(inv_path, 'r'))
self.assertEqual(
inventory['all']['vars']['zuul']['message'].unsafe_var,
expected_message)
decoded_message = base64.b64decode(
inventory['all']['vars']['zuul']['message']).decode('utf-8')
self.assertEqual(decoded_message, expected_message)
obtained_message = self._get_file(self.history[0],
'work/logs/commit-message.txt')

View File

@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import base64
import collections
import datetime
import json
@ -29,7 +30,7 @@ import traceback
import git
from urllib.parse import urlsplit
from zuul.lib.yamlutil import yaml, UnsafeTag
from zuul.lib.yamlutil import yaml
from zuul.lib.config import get_default
from zuul.lib.statsd import get_statsd
from zuul.lib import filecomments
@ -593,7 +594,8 @@ def make_inventory_dict(nodes, args, all_vars):
zuul_vars = all_vars['zuul']
if 'message' in zuul_vars:
zuul_vars['message'] = UnsafeTag(zuul_vars['message'])
zuul_vars['message'] = base64.b64encode(
zuul_vars['message'].encode("utf-8")).decode('utf-8')
inventory = {
'all': {

View File

@ -25,26 +25,6 @@ except ImportError:
Mark = yaml.Mark
class UnsafeTag(yaml.YAMLObject):
yaml_tag = u'!unsafe'
yaml_dumper = yaml.SafeDumper
yaml_loader = yaml.SafeLoader
def __init__(self, unsafe_var):
self.unsafe_var = unsafe_var
@classmethod
def from_yaml(cls, loader, node):
return UnsafeTag(node.value)
@classmethod
def to_yaml(cls, dumper, data):
return dumper.represent_scalar(cls.yaml_tag, data.unsafe_var)
def __str__(self):
return self.unsafe_var
def safe_load(stream, *args, **kwargs):
return yaml.load(stream, *args, Loader=SafeLoader, **kwargs)