From 8e0bdd7a003fbd1717c4861e5d891e0a2bd49b85 Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: Wed, 1 Feb 2023 11:32:27 +0100 Subject: [PATCH] sidetag: allowed list for rpm macros Related: https://pagure.io/koji/issue/3673 --- docs/source/plugins.rst | 12 ++++++++++++ plugins/hub/sidetag_hub.py | 37 ++++++++++++++++++++++++++++++++----- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/docs/source/plugins.rst b/docs/source/plugins.rst index 66545047..c370709a 100644 --- a/docs/source/plugins.rst +++ b/docs/source/plugins.rst @@ -145,6 +145,18 @@ Plugin has also its own configuration file Python string template to be used for generation of sidetag name. It needs to contain both basetag/tag_id placeholders. +Parent tag can define following extras: + +.. glossary:: + sidetag_debuginfo_allowed = 0 + If set to 1/True, debuginfo repo could be created (``with_debuginfo`` can + be set for tag by sidetag owner via ``--debuginfo`` option) + + sidetag_rpm_macros_allowed = None + This option can be set to space-separated fnmatch masks which allows user + to override specific rpm macros. + (``koji edit-sidetag --rpm-macro ``). + CLI --- diff --git a/plugins/hub/sidetag_hub.py b/plugins/hub/sidetag_hub.py index 4882e750..660d66eb 100644 --- a/plugins/hub/sidetag_hub.py +++ b/plugins/hub/sidetag_hub.py @@ -5,6 +5,7 @@ import koji from koji.context import context from koji.plugin import callback, export +from koji.util import multi_fnmatch import koji.policy from kojihub import ( _create_build_target, @@ -229,12 +230,17 @@ def listSideTags(basetag=None, user=None, queryOpts=None): return query.execute() +def _valid_rpm_macro_name(macro): + # https://github.com/rpm-software-management/rpm/blob/master/rpmio/macro.c#L627 + return len(macro) > 1 and (macro[0].isalpha() or macro[0] == '_') + + @export def editSideTag(sidetag, debuginfo=None, rpm_macros=None, remove_rpm_macros=None, extra=None, remove_extra=None): """Restricted ability to modify sidetags, parent tag must have: sidetag_debuginfo_allowed: 1 - sidetag_rpm_macros_allowed: 1 + sidetag_rpm_macros_allowed: list of allowed macros (or str.split() compatible string) in extra, if modifying functions should work. For blocking/unblocking further policy must be compatible with these operations. @@ -272,9 +278,23 @@ def editSideTag(sidetag, debuginfo=None, rpm_macros=None, remove_rpm_macros=None if debuginfo is not None and not parent['extra'].get('sidetag_debuginfo_allowed'): raise koji.GenericError("Debuginfo setting is not allowed in parent tag.") - if (rpm_macros is not None or remove_rpm_macros is not None) \ - and not parent['extra'].get('sidetag_rpm_macros_allowed'): - raise koji.GenericError("RPM macros change is not allowed in parent tag.") + if (rpm_macros or remove_rpm_macros): + # sanity checks on parent's rpm_macros_allowed + rpm_macros_allowed = parent['extra'].get('sidetag_rpm_macros_allowed', []) + if rpm_macros_allowed is None: + rpm_macros_allowed = [] + elif isinstance(rpm_macros_allowed, str): + rpm_macros_allowed = rpm_macros_allowed.split() + elif not isinstance(rpm_macros_allowed, list): + raise koji.GenericError(f"rpm_macros_allowed in {parent['name']} has invalid type: " + f"{type(rpm_macros_allowed)}") + for macro in rpm_macros_allowed: + if not isinstance(macro, str): + raise koji.GenericError(f"Allowed rpm macro list {rpm_macros_allowed:r} " + f"is invalid for {parent['name']}.") + + if not rpm_macros_allowed: + raise koji.GenericError("RPM macros change is not allowed in parent tag.") kwargs = {'extra': extra, 'remove_extra': remove_extra} if debuginfo is not None: @@ -282,10 +302,17 @@ def editSideTag(sidetag, debuginfo=None, rpm_macros=None, remove_rpm_macros=None if rpm_macros is not None: convert_value(rpm_macros, cast=dict, check_only=True) for macro, value in rpm_macros.items(): + if not _valid_rpm_macro_name(macro): + raise koji.GenericError(f"Invalid macro name {macro:r}") + if not multi_fnmatch(macro, rpm_macros_allowed): + raise koji.GenericError(f"RPM macro {macro} editing is not allowed via parent tag") kwargs['extra']['rpm.macro.%s' % macro] = value if remove_rpm_macros is not None: convert_value(remove_rpm_macros, cast=list, check_only=True) - kwargs['remove_extra'] += ['rpm.macro.%s' % m for m in remove_rpm_macros] + for macro in remove_rpm_macros: + if not multi_fnmatch(macro, rpm_macros_allowed): + raise koji.GenericError(f"RPM macro {macro} editing is not allowed via parent tag") + kwargs['remove_extra'] = ['rpm.macro.%s' % m for m in remove_rpm_macros] _edit_tag(sidetag['id'], **kwargs)