summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgroente <groente@puscii.nl>2018-11-13 10:13:54 +0000
committergroente <groente@puscii.nl>2018-11-13 10:13:54 +0000
commit7e88ef4330e2eab7477c72c9607d191fbbc64c1d (patch)
tree394bfbb8f089e97aef9d1bd2435bccd39d45a658
parent3f46bda93323cdca2acafb50beb0cf17fcc034cd (diff)
adding an update hook to the tails repo to check if weblate is playing nicebugfix/15402-update-hook-for-weblate-pushes
-rw-r--r--files/gitolite/hooks/tails-weblate-update.hook72
-rw-r--r--manifests/gitolite/hooks/tails.pp7
2 files changed, 79 insertions, 0 deletions
diff --git a/files/gitolite/hooks/tails-weblate-update.hook b/files/gitolite/hooks/tails-weblate-update.hook
new file mode 100644
index 0000000..d840678
--- /dev/null
+++ b/files/gitolite/hooks/tails-weblate-update.hook
@@ -0,0 +1,72 @@
+#!/usr/bin/env python3
+
+# Update git hook to ensure, that a user is only allowed to push modifications
+# to existiong files. Only works with gitolite ( as this sets the env variable GL_USER
+# that is connected to the ssh key used for pushing.
+
+# It is used to ensure, that Weblate is only allowed to push po files.
+
+import os
+import re
+import subprocess
+import sys
+
+# Gitolite sets env variable for the user for the SSH user
+GL_USER = "weblate"
+
+# Only allowed commiter mail
+COMMITTER = "weblate <tails-l10n@boum.org>"
+
+# Regex to match for modified po files in raw output format of git diff-tree
+# in-place edit :100644 100644 bcd1234... 0123456... M file0
+reModifyFile = re.compile("[^\t]* M\t.*\.po")
+
+# Regex to match the commiter line of git cat-file.
+# E.g "committer Sandro KnauƟ <hefee@debian.org> 1542020415 +0100"
+reCommitter = re.compile("committer (?P<committer>(?P<name>.*) (<(?P<mail>.*)>)) .*")
+
+def committer(rev):
+ """@returns the commiter for a given git hash (`rev`)"""
+ output = subprocess.check_output(["git", "cat-file", "commit", rev])
+ for l in output.decode().splitlines():
+ m = reCommitter.match(l)
+ if m:
+ return {
+ "committer": m['committer'],
+ "name":m['name'],
+ "mail": m['mail'],
+ }
+
+ return None
+
+def check_commit_author_weblate(oldrev, newrev):
+ """@returns issue, if there are resons to block the update."""
+
+ # get a list of committes
+ cmd = ["git", "rev-list", f"{oldrev}..{newrev}"]
+ rev_list = subprocess.check_output(cmd).decode()
+ for rev in rev_list.splitlines():
+ if COMMITTER != committer(rev).get('committer'):
+ return f"{rev[-10:]} - [POLICY] Weblate is only allowed to push commits with '{COMMITTER}' as committer."
+
+ # Check list of modified files.
+ _ = subprocess.check_output(["git", "diff-tree", "--no-commit-id", "--raw", "-r", rev])
+ files = _.decode().splitlines()
+ for line in files:
+ if not reModifyFile.match(line):
+ return f"{rev[-10:]} - [POLICY] Weblate is only allowed to modify po files."
+
+ return None
+
+ref = sys.argv[1]
+oldrev = sys.argv[2]
+newrev = sys.argv[3]
+
+os.environ["GL_USER"] = "weblate"
+
+if os.environ.get("GL_USER") == GL_USER:
+ if oldrev == "0000000000000000000000000000000000000000":
+ sys.exit("[POLICY] Weblate is not allowed to create new branches.")
+
+ issue = check_commit_author_weblate(oldrev, newrev)
+ sys.exit(issue)
diff --git a/manifests/gitolite/hooks/tails.pp b/manifests/gitolite/hooks/tails.pp
index 1bf249c..40cb865 100644
--- a/manifests/gitolite/hooks/tails.pp
+++ b/manifests/gitolite/hooks/tails.pp
@@ -23,6 +23,13 @@ class tails::gitolite::hooks::tails {
require => Package[curl],
}
+ file { '/var/lib/gitolite/repositories/tails.git/hooks/update.secondary':
+ source => 'puppet:///modules/tails/gitolite/hooks/tails-weblate-update.hook',
+ owner => root,
+ group => root,
+ mode => '0755',
+ }
+
ensure_packages(['curl'])
}