summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Henkel <tobias.henkel@bmw.de>2019-02-23 09:18:50 +0100
committerTobias Henkel <tobias.henkel@bmw.de>2019-02-28 18:09:22 +0100
commitfcbb91582f47b4f1d2d3fb6843dfbc764bd8a6f5 (patch)
tree72ce2b804678e51c21950725553e36236bc4131f
parentd60346181ba5f076a214f5d02103e0a3b24b10ac (diff)
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
Notes
Notes (review): Code-Review+2: James E. Blair <corvus@inaugust.com> Code-Review+1: Jan Kundrát <jkt@kde.org> Code-Review+2: Monty Taylor <mordred@inaugust.com> Workflow+1: Monty Taylor <mordred@inaugust.com> Verified+2: Zuul Submitted-by: Zuul Submitted-at: Thu, 28 Feb 2019 18:06:55 +0000 Reviewed-on: https://review.openstack.org/638801 Project: openstack-infra/zuul Branch: refs/heads/master
-rw-r--r--doc/source/user/jobs.rst13
-rw-r--r--releasenotes/notes/zuul-message-a36f1a6adc7da31c.yaml8
-rw-r--r--tests/fixtures/config/inventory/git/common-config/playbooks/jinja2-message.yaml2
-rw-r--r--tests/unit/test_inventory.py9
-rw-r--r--zuul/executor/server.py6
-rw-r--r--zuul/lib/yamlutil.py20
6 files changed, 30 insertions, 28 deletions
diff --git a/doc/source/user/jobs.rst b/doc/source/user/jobs.rst
index f6d4a66..e8f036b 100644
--- a/doc/source/user/jobs.rst
+++ b/doc/source/user/jobs.rst
@@ -566,7 +566,18 @@ are available:
566 566
567 .. var:: message 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
571Branch Items 582Branch Items
572~~~~~~~~~~~~ 583~~~~~~~~~~~~
diff --git a/releasenotes/notes/zuul-message-a36f1a6adc7da31c.yaml b/releasenotes/notes/zuul-message-a36f1a6adc7da31c.yaml
new file mode 100644
index 0000000..7f9b085
--- /dev/null
+++ b/releasenotes/notes/zuul-message-a36f1a6adc7da31c.yaml
@@ -0,0 +1,8 @@
1---
2upgrade:
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 }}``.
diff --git a/tests/fixtures/config/inventory/git/common-config/playbooks/jinja2-message.yaml b/tests/fixtures/config/inventory/git/common-config/playbooks/jinja2-message.yaml
index fbfb791..834c3cb 100644
--- a/tests/fixtures/config/inventory/git/common-config/playbooks/jinja2-message.yaml
+++ b/tests/fixtures/config/inventory/git/common-config/playbooks/jinja2-message.yaml
@@ -2,5 +2,5 @@
2 tasks: 2 tasks:
3 - name: Dump commit message 3 - name: Dump commit message
4 copy: 4 copy:
5 content: "{{ zuul.message }}" 5 content: "{{ zuul.message | b64decode }}"
6 dest: "{{ zuul.executor.log_root }}/commit-message.txt" 6 dest: "{{ zuul.executor.log_root }}/commit-message.txt"
diff --git a/tests/unit/test_inventory.py b/tests/unit/test_inventory.py
index 9d26d2c..2521b9f 100644
--- a/tests/unit/test_inventory.py
+++ b/tests/unit/test_inventory.py
@@ -12,6 +12,7 @@
12# License for the specific language governing permissions and limitations 12# License for the specific language governing permissions and limitations
13# under the License. 13# under the License.
14 14
15import base64
15import os 16import os
16 17
17import yaml 18import yaml
@@ -61,7 +62,7 @@ class TestInventory(TestInventoryBase):
61 self.assertIn('src_root', z_vars['executor']) 62 self.assertIn('src_root', z_vars['executor'])
62 self.assertIn('job', z_vars) 63 self.assertIn('job', z_vars)
63 self.assertEqual(z_vars['job'], 'single-inventory') 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 self.executor_server.release() 67 self.executor_server.release()
67 self.waitUntilSettled() 68 self.waitUntilSettled()
@@ -192,9 +193,9 @@ class TestAnsibleInventory(AnsibleZuulTestCase):
192 inv_path = os.path.join(build.jobdir.root, 'ansible', 'inventory.yaml') 193 inv_path = os.path.join(build.jobdir.root, 'ansible', 'inventory.yaml')
193 inventory = yaml.safe_load(open(inv_path, 'r')) 194 inventory = yaml.safe_load(open(inv_path, 'r'))
194 195
195 self.assertEqual( 196 decoded_message = base64.b64decode(
196 inventory['all']['vars']['zuul']['message'].unsafe_var, 197 inventory['all']['vars']['zuul']['message']).decode('utf-8')
197 expected_message) 198 self.assertEqual(decoded_message, expected_message)
198 199
199 obtained_message = self._get_file(self.history[0], 200 obtained_message = self._get_file(self.history[0],
200 'work/logs/commit-message.txt') 201 'work/logs/commit-message.txt')
diff --git a/zuul/executor/server.py b/zuul/executor/server.py
index 184028d..dc668c2 100644
--- a/zuul/executor/server.py
+++ b/zuul/executor/server.py
@@ -12,6 +12,7 @@
12# License for the specific language governing permissions and limitations 12# License for the specific language governing permissions and limitations
13# under the License. 13# under the License.
14 14
15import base64
15import collections 16import collections
16import datetime 17import datetime
17import json 18import json
@@ -29,7 +30,7 @@ import traceback
29import git 30import git
30from urllib.parse import urlsplit 31from urllib.parse import urlsplit
31 32
32from zuul.lib.yamlutil import yaml, UnsafeTag 33from zuul.lib.yamlutil import yaml
33from zuul.lib.config import get_default 34from zuul.lib.config import get_default
34from zuul.lib.statsd import get_statsd 35from zuul.lib.statsd import get_statsd
35from zuul.lib import filecomments 36from zuul.lib import filecomments
@@ -593,7 +594,8 @@ def make_inventory_dict(nodes, args, all_vars):
593 594
594 zuul_vars = all_vars['zuul'] 595 zuul_vars = all_vars['zuul']
595 if 'message' in zuul_vars: 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 inventory = { 600 inventory = {
599 'all': { 601 'all': {
diff --git a/zuul/lib/yamlutil.py b/zuul/lib/yamlutil.py
index a1162f7..2c84b06 100644
--- a/zuul/lib/yamlutil.py
+++ b/zuul/lib/yamlutil.py
@@ -25,26 +25,6 @@ except ImportError:
25 Mark = yaml.Mark 25 Mark = yaml.Mark
26 26
27 27
28class 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
48def safe_load(stream, *args, **kwargs): 28def safe_load(stream, *args, **kwargs):
49 return yaml.load(stream, *args, Loader=SafeLoader, **kwargs) 29 return yaml.load(stream, *args, Loader=SafeLoader, **kwargs)
50 30