From aea27f76fc3f0212b35c38fa264d7f59e34121eb Mon Sep 17 00:00:00 2001 From: Markus Lehtonen Date: Thu, 5 Dec 2013 10:55:11 +0200 Subject: [PATCH] Ability to run gbs under different user/group This change adds new configuration file options to set the user/group under which gbs is run in the service. The service itself is run under whatever user/group the source service server itself is configured to use. The service now spawns a separate thread for gbs and sets the uid/gid there before calling gbs - this is accomplished by utilizing functionality from the obs-service-git-buildpackage-utils module. Change-Id: I0c8a9c4d2349cd0ca629f816cb9011f26a42b3bb Signed-off-by: Markus Lehtonen --- config/gbs | 8 ++++++++ obs_service_gbs/command.py | 23 +++++++++++++++++++---- packaging/obs-service-gbs.spec | 2 ++ tests/test_obs_service_gbs.py | 15 +++++++++++++++ 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/config/gbs b/config/gbs index 098d52b..3d68906 100644 --- a/config/gbs +++ b/config/gbs @@ -10,3 +10,11 @@ ## You probably need to define if the service is run on the client side as ## the default directory is likely not accessible by regular users. #repo-cache-dir = /var/cache/obs/git-buildpackage-repos/ + +## User and group +## The user and group under which gbs is run. The service itself is run under +## whatever user/group the source service server is configured to use - this +## user must have the privileges to set uid/gid if you configure these settings. +## You can give the user and group as name or uid/gid number directly. +#gbs-user = gbsservice +#gbs-group = gbsservice diff --git a/obs_service_gbs/command.py b/obs_service_gbs/command.py index fabeaa3..07f16f9 100644 --- a/obs_service_gbs/command.py +++ b/obs_service_gbs/command.py @@ -32,6 +32,7 @@ import gbp.log as gbplog import gbp_repocache from gbp_repocache import CachedRepo, CachedRepoError +from obs_service_gbp_utils import GbpServiceError, fork_call, sanitize_uid_gid # Setup logging @@ -64,7 +65,9 @@ def construct_gbs_args(args, outdir, gitdir): def read_config(filenames): '''Read configuration file(s)''' - defaults = {'repo-cache-dir': '/var/cache/obs/gbs-repos/'} + defaults = {'repo-cache-dir': '/var/cache/obs/gbs-repos/', + 'gbs-user': None, + 'gbs-group': None} filenames = [os.path.expanduser(fname) for fname in filenames] LOGGER.debug('Trying %s config files: %s' % (len(filenames), filenames)) @@ -85,7 +88,7 @@ def read_config(filenames): # We only use keys from one section, for now return dict(parser.items('general')) -def gbs_export(repo, args): +def gbs_export(repo, args, config): '''Export packaging files with GBS''' # Create temporary directory try: @@ -93,13 +96,25 @@ def gbs_export(repo, args): except OSError as err: raise ServiceError('Failed to create tmpdir: %s' % err, 1) + # Determine UID/GID and grant permissions to tmpdir + try: + uid, gid = sanitize_uid_gid(config['gbs-user'], config['gbs-group']) + except GbpServiceError as err: + raise ServiceError(err, 1) + os.chown(tmpdir, uid, gid) + # Do export try: gbs_args = construct_gbs_args(args, tmpdir, repo.repodir) LOGGER.info('Exporting packaging files with GBS') LOGGER.debug('gbs args: %s' % gbs_args) try: - cmd_export(gbs_args) + fork_call(uid, gid, cmd_export, gbs_args) + except GbpServiceError as err: + LOGGER.error('Internal service error when trying to run GBS: ' + '%s' % err) + LOGGER.error('Most likely a configuration error (or a BUG)!') + raise ServiceError('Failed to run GBS thread: %s' % err, 1) except CmdError as err: raise ServiceError('GBS export failed: %s' % err, 2) except Exception as err: @@ -168,7 +183,7 @@ def main(argv=None): raise ServiceError('Failed to create outdir: %s' % err, 1) # Export sources with GBS - gbs_export(repo, args) + gbs_export(repo, args, config) except ServiceError as err: LOGGER.error(err[0]) diff --git a/packaging/obs-service-gbs.spec b/packaging/obs-service-gbs.spec index 088420d..7350cb3 100644 --- a/packaging/obs-service-gbs.spec +++ b/packaging/obs-service-gbs.spec @@ -16,6 +16,7 @@ Source: %{name}-%{version}.tar.bz2 Requires: gbs-export Requires: git-buildpackage-common Requires: gbp-repocache +Requires: obs-service-git-buildpackage-utils BuildRequires: python BuildRequires: python-setuptools %if 0%{?do_unittests} @@ -24,6 +25,7 @@ BuildRequires: python-nose BuildRequires: gbs-export BuildRequires: git-buildpackage-common BuildRequires: gbp-repocache +BuildRequires: obs-service-git-buildpackage-utils %endif BuildArch: noarch diff --git a/tests/test_obs_service_gbs.py b/tests/test_obs_service_gbs.py index 4fc0d6c..26a31d5 100644 --- a/tests/test_obs_service_gbs.py +++ b/tests/test_obs_service_gbs.py @@ -18,6 +18,7 @@ # MA 02110-1301, USA. """Tests for the GBS source service""" +import grp import os import shutil import stat @@ -190,4 +191,18 @@ class TestGbsService(UnitTestsBase): ok_(not os.path.exists(default_cache), os.listdir('.')) ok_(os.path.exists('my-repo-cache'), os.listdir('.')) + def test_user_group_config(self): + """Test the user/group settings""" + # Changing to current user/group should succeed + os.environ['OBS_GBS_GBS_USER'] = str(os.getuid()) + os.environ['OBS_GBS_GBS_GROUP'] = grp.getgrgid(os.getgid()).gr_name + eq_(service(['--url', self.orig_repo.path]), 0) + + # Changing to non-existent user should fail + os.environ['OBS_GBS_GBS_USER'] = '_non_existent_user' + del os.environ['OBS_GBS_GBS_GROUP'] + eq_(service(['--url', self.orig_repo.path]), 1) + + # Return env + del os.environ['OBS_GBS_GBS_USER'] -- 2.7.4