Browse Source

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
tags/3.6.0
Tobias Henkel 3 months ago
parent
commit
fcbb91582f
No account linked to committer's email address

+ 12
- 1
doc/source/user/jobs.rst View File

@@ -566,7 +566,18 @@ are available:
566 566
 
567 567
    .. var:: message
568 568
 
569
-      The commit or pull request message of the change.
569
+      The commit or pull request message of the change base64 encoded. Use the
570
+      `b64decode` filter in ansible when working with it.
571
+
572
+      .. code-block:: yaml
573
+
574
+         - hosts: all
575
+           tasks:
576
+             - name: Dump commit message
577
+               copy:
578
+                 content: "{{ zuul.message | b64decode }}"
579
+                 dest: "{{ zuul.executor.log_root }}/commit-message.txt"
580
+
570 581
 
571 582
 Branch Items
572 583
 ~~~~~~~~~~~~

+ 8
- 0
releasenotes/notes/zuul-message-a36f1a6adc7da31c.yaml View File

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

+ 1
- 1
tests/fixtures/config/inventory/git/common-config/playbooks/jinja2-message.yaml View File

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

+ 5
- 4
tests/unit/test_inventory.py View File

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

+ 4
- 2
zuul/executor/server.py View File

@@ -12,6 +12,7 @@
12 12
 # License for the specific language governing permissions and limitations
13 13
 # under the License.
14 14
 
15
+import base64
15 16
 import collections
16 17
 import datetime
17 18
 import json
@@ -29,7 +30,7 @@ import traceback
29 30
 import git
30 31
 from urllib.parse import urlsplit
31 32
 
32
-from zuul.lib.yamlutil import yaml, UnsafeTag
33
+from zuul.lib.yamlutil import yaml
33 34
 from zuul.lib.config import get_default
34 35
 from zuul.lib.statsd import get_statsd
35 36
 from zuul.lib import filecomments
@@ -593,7 +594,8 @@ def make_inventory_dict(nodes, args, all_vars):
593 594
 
594 595
     zuul_vars = all_vars['zuul']
595 596
     if 'message' in zuul_vars:
596
-        zuul_vars['message'] = UnsafeTag(zuul_vars['message'])
597
+        zuul_vars['message'] = base64.b64encode(
598
+            zuul_vars['message'].encode("utf-8")).decode('utf-8')
597 599
 
598 600
     inventory = {
599 601
         'all': {

+ 0
- 20
zuul/lib/yamlutil.py View File

@@ -25,26 +25,6 @@ except ImportError:
25 25
     Mark = yaml.Mark
26 26
 
27 27
 
28
-class UnsafeTag(yaml.YAMLObject):
29
-    yaml_tag = u'!unsafe'
30
-    yaml_dumper = yaml.SafeDumper
31
-    yaml_loader = yaml.SafeLoader
32
-
33
-    def __init__(self, unsafe_var):
34
-        self.unsafe_var = unsafe_var
35
-
36
-    @classmethod
37
-    def from_yaml(cls, loader, node):
38
-        return UnsafeTag(node.value)
39
-
40
-    @classmethod
41
-    def to_yaml(cls, dumper, data):
42
-        return dumper.represent_scalar(cls.yaml_tag, data.unsafe_var)
43
-
44
-    def __str__(self):
45
-        return self.unsafe_var
46
-
47
-
48 28
 def safe_load(stream, *args, **kwargs):
49 29
     return yaml.load(stream, *args, Loader=SafeLoader, **kwargs)
50 30
 

Loading…
Cancel
Save