From 725c157fbdaf9a7f2f9d11baddb975ade8c7fe0d Mon Sep 17 00:00:00 2001 From: Jana Cupova Date: Jan 25 2022 14:47:27 +0000 Subject: Allow password in SCM url with new builder option Fixes: https://pagure.io/koji/issue/3179 --- diff --git a/builder/kojid b/builder/kojid index bc82985..35a7e52 100755 --- a/builder/kojid +++ b/builder/kojid @@ -1644,7 +1644,7 @@ class BuildMavenTask(BaseBuildTask): opts = {} self.opts = opts - scm = SCM(url) + scm = SCM(url, allow_password=self.options.allow_password_in_scm_url) scm_policy_opts = { 'user_id': self.taskinfo['owner'], 'channel': self.session.getChannel(self.taskinfo['channel_id'], @@ -1728,7 +1728,8 @@ class BuildMavenTask(BaseBuildTask): # Checkout out patches, if present if self.opts.get('patches'): patchlog = self.workdir + '/patches.log' - patch_scm = SCM(self.opts.get('patches')) + patch_scm = SCM(self.opts.get('patches'), + allow_password=self.options.allow_password_in_scm_url) patch_scm.assert_allowed(allowed=self.options.allowed_scms, session=self.session, by_config=self.options.allowed_scms_use_config, @@ -2015,7 +2016,7 @@ class WrapperRPMTask(BaseBuildTask): # can't happen assert False # pragma: no cover - scm = SCM(spec_url) + scm = SCM(spec_url, allow_password=self.options.allow_password_in_scm_url) scm.assert_allowed(allowed=self.options.allowed_scms, session=self.session, by_config=self.options.allowed_scms_use_config, @@ -3016,7 +3017,7 @@ class ImageTask(BaseTaskHandler): koji.ensuredir(scmdir) self.logger.debug("ksfile = %s" % ksfile) if self.opts.get('ksurl'): - scm = SCM(self.opts['ksurl']) + scm = SCM(self.opts['ksurl'], allow_password=self.options.allow_password_in_scm_url) scm.assert_allowed(allowed=self.options.allowed_scms, session=self.session, by_config=self.options.allowed_scms_use_config, @@ -3499,7 +3500,7 @@ class LiveMediaTask(ImageTask): An absolute path (from within the chroot) to where livemedia-creator can find the checked out templates. """ - scm = SCM(self.opts['lorax_url']) + scm = SCM(self.opts['lorax_url'], allow_password=self.options.allow_password_in_scm_url) scm.assert_allowed(allowed=self.options.allowed_scms, session=self.session, by_config=self.options.allowed_scms_use_config, @@ -3755,7 +3756,7 @@ class OzImageTask(BaseTaskHandler): ksfile = self.opts.get('kickstart') self.logger.debug("ksfile = %s" % ksfile) if self.opts.get('ksurl'): - scm = SCM(self.opts['ksurl']) + scm = SCM(self.opts['ksurl'], allow_password=self.options.allow_password_in_scm_url) scm.assert_allowed(allowed=self.options.allowed_scms, session=self.session, by_config=self.options.allowed_scms_use_config, @@ -4591,7 +4592,7 @@ class BuildIndirectionImageTask(OzImageTask): # to be entirely self contained. Revisit if anyone feels like a refactor. self.logger.debug("filepath = %s" % filepath) if fileurl: - scm = SCM(fileurl) + scm = SCM(fileurl, allow_password=self.options.allow_password_in_scm_url) scm.assert_allowed(allowed=self.options.allowed_scms, session=self.session, by_config=self.options.allowed_scms_use_config, @@ -5012,7 +5013,7 @@ class BuildSRPMFromSCMTask(BaseBuildTask): if opts is None: opts = {} # will throw a BuildError if the url is invalid - scm = SCM(url) + scm = SCM(url, allow_password=self.options.allow_password_in_scm_url) scm.assert_allowed(allowed=self.options.allowed_scms, session=self.session, by_config=self.options.allowed_scms_use_config, @@ -6486,7 +6487,8 @@ def get_options(): 'task_avail_delay': 300, 'cert': None, 'serverca': None, - 'allow_noverifyssl': False} + 'allow_noverifyssl': False, + 'allow_password_in_scm_url': False} if config.has_section('kojid'): for name, value in config.items('kojid'): if name in ['sleeptime', 'maxjobs', 'minspace', 'retry_interval', @@ -6502,7 +6504,7 @@ def get_options(): 'createrepo_update', 'use_fast_upload', 'support_rpm_source_layout', 'build_arch_can_fail', 'no_ssl_verify', 'log_timestamps', 'allow_noverifyssl', 'allowed_scms_use_config', - 'allowed_scms_use_policy']: + 'allowed_scms_use_policy', 'allow_password_in_scm_url']: defaults[name] = config.getboolean('kojid', name) elif name in ['plugin', 'plugins']: defaults['plugin'] = value.split() diff --git a/builder/kojid.conf b/builder/kojid.conf index 777a421..0cb4595 100644 --- a/builder/kojid.conf +++ b/builder/kojid.conf @@ -149,3 +149,6 @@ from_addr=Koji Build System ;allow passing noverifyssl option to anaconda for image builds ;allow_noverifyssl = False + +;allow password in SCM url +;allow_password_in_scm_url = False diff --git a/koji/daemon.py b/koji/daemon.py index 2c834c8..9c3aa55 100644 --- a/koji/daemon.py +++ b/koji/daemon.py @@ -209,7 +209,7 @@ class SCM(object): else: return False - def __init__(self, url): + def __init__(self, url, allow_password=False): """ Initialize the SCM object using the specified url. The expected url format is: @@ -237,10 +237,14 @@ class SCM(object): raise koji.GenericError('Invalid SCM URL: %s' % url) self.url = url - scheme, user, host, path, query, fragment = self._parse_url() + scheme, user, password, host, path, query, fragment = self._parse_url( + allow_password=allow_password) self.scheme = scheme - self.user = user + if password is not None: + self.user = '%s:%s' % (user, password) + else: + self.user = user self.host = host self.repository = path self.module = query @@ -261,7 +265,7 @@ class SCM(object): keys = ["url", "scheme", "user", "host", "repository", "module", "revision", "scmtype"] return dslice(vars(self), keys) - def _parse_url(self): + def _parse_url(self, allow_password=False): """ Parse the SCM url into usable components. Return the following tuple: @@ -275,23 +279,29 @@ class SCM(object): # replace the scheme with http:// so that the urlparse works in all cases dummyurl = self.url.replace(scheme, 'http://', 1) - dummyscheme, netloc, path, params, query, fragment = urllib.parse.urlparse(dummyurl) + parsed_url = urllib.parse.urlparse(dummyurl) + path = parsed_url.path + params = parsed_url.params + query = parsed_url.query + fragment = parsed_url.fragment user = None - userhost = netloc.split('@') - if len(userhost) == 2: - user = userhost[0] - if not user: - # Don't return an empty string - user = None - elif ':' in user: - raise koji.GenericError('username:password format not supported: %s' % user) - netloc = userhost[1] - elif len(userhost) > 2: - raise koji.GenericError('Invalid username@hostname specified: %s' % netloc) - if not netloc: + password = None + + userhost = parsed_url.netloc.split('@') + if len(userhost) > 2: + raise koji.GenericError('Invalid username@hostname specified: %s' % userhost) + if not userhost: raise koji.GenericError( 'Unable to parse SCM URL: %s . Could not find the netloc element.' % self.url) + if parsed_url.username: + user = parsed_url.username + if parsed_url.password: + password = parsed_url.password + if password is not None and not allow_password: + raise koji.GenericError('username:password format not supported: %s:%s' + % (user, password)) + netloc = parsed_url.hostname # check for empty path before we apply normpath if not path: @@ -326,7 +336,7 @@ class SCM(object): 'Unable to parse SCM URL: %s . Could not find the fragment element.' % self.url) # return parsed values - return (scheme, user, netloc, path, query, fragment) + return (scheme, user, password, netloc, path, query, fragment) def assert_allowed(self, allowed='', session=None, by_config=True, by_policy=False, policy_data=None):