def prepare(reponame): """Make sure basic things are in place for post-receive scripts to work. The post-receive hook calls hook-mux, which multiplexes everything on standard input to multiple scripts found in the post-recieve.d directory. This makes it possible to have multiple (post-receive) hooks. """ hook_dir = repository.directory('git', reponame) + 'hooks' # Make sure multiplexer script is in place. It should be a shell script # that calls the actual real script. The old situation is that the # post-receive script was actually a script to call only git-multimail.py. # The reason why we have a call to the script instead of a symlink, is # because we can not guarantee the executable bit of the target. if not shellscript.hasSignature(hook_dir + 'post-receive', signature): rewrite_hook(reponame, 'post-receive', 'hook-mux', interpreter='/bin/bash', args='post-receive') # make sure multiplexer dir exists # because www user can check if files in this directory exists, but # we can't chgrp() the dir, we set the mode explicitly to 0755. The # parent dir is only open to git user and www group, with mode 0750. mkdirs(hook_dir + 'post-receive.d', mode=0o755)
def add(name): """Create a new repository with name *name*""" if not name.endswith(".mock"): name += ".mock" reposdir = options.env_path('mock_dir', default='mock') + name if os.path.exists(str(reposdir)): raise PermissionError("Could not create %s, already exists." % name) mkdirs(reposdir)
def create_dir(self, directory): """Create a relative or absulute directory, if it doesn't exist already""" if not directory.absolute: directory = self.env + directory if not os.path.exists(str(directory)): try: mkdirs(str(directory), mode=0o700) except OSError as e: print "making dir %s failed, do you have permissions?" % str(directory) raise e
def create_dir(self, directory): """Create a relative or absulute directory, if it doesn't exist already""" if not directory.absolute: directory = self.env + directory if not os.path.exists(str(directory)): try: mkdirs(str(directory), mode=0o700) except OSError as e: print 'making dir %s failed, do you have permissions?' % \ str(directory) raise e
def create_dir(env, directory): """Create a relative or absulute directory, if it doesn't exist already. Requires `env` to be a Path object.""" if not directory.absolute: directory = env + directory try: mkdirs(str(directory), mode=0o700) except OSError as e: print 'making dir %s failed, do you have permissions?' % \ str(directory) raise e
def create(vcs_type, reposname, adminUser): from submin.models.repository import directory as repodir basedir = options.env_path('trac_dir') mkdirs(str(basedir)) tracenv = basedir + reposname projectname = reposname vcsdir = repodir(vcs_type, reposname) admin_command( tracenv, ['initenv', projectname, 'sqlite:db/trac.db', vcs_type, vcsdir]) admin_command(tracenv, ['permission', 'add', adminUser.name, "TRAC_ADMIN"]) components = [ 'tracopt.ticket.commit_updater.*', 'tracopt.versioncontrol.%s.*' % vcs_type ] for component in components: admin_command(tracenv, ['config', 'set', 'components', component, 'enabled']) admin_command(tracenv, ['config', 'set', 'header_logo', 'alt', 'Trac']) admin_command(tracenv, ['config', 'set', 'header_logo', 'height', '61']) admin_command(tracenv, [ 'config', 'set', 'header_logo', 'link', "%s/%s" % (options.value('base_url_trac'), reposname) ]) admin_command(tracenv, ['config', 'set', 'header_logo', 'src', 'trac_banner.png']) admin_command(tracenv, ['config', 'set', 'header_logo', 'width', '214']) admin_command( tracenv, ['config', 'set', 'project', 'descr', 'Repository %s' % reposname]) admin_command(tracenv, [ 'config', 'set', 'svn', 'authz_file', options.env_path('svn_authz_file') ]) admin_command(tracenv, ['config', 'set', 'svn', 'authz_module_name', reposname]) admin_command(tracenv, [ 'config', 'set', 'trac', 'authz_file', options.env_path('svn_authz_file') ]) permission_policies = admin_command( tracenv, ['config', 'get', 'trac', 'permission_policies']) admin_command(tracenv, [ 'config', 'set', 'trac', 'permission_policies', 'AuthzSourcePolicy,' + permission_policies ]) admin_command(tracenv, ['config', 'set', 'trac', 'repository_dir', vcsdir])
def setCommitEmailHook(reponame, enable): prepare(reponame) reposdir = repository.directory('git', reponame) hook_dir = reposdir + 'hooks' + 'post-receive.d' mkdirs(hook_dir) hook_dest = hook_dir + '001-commit-email.hook' if enable: variables = { 'submin_lib_dir': options.lib_path(), 'base_url': options.url_path('base_url_submin'), 'http_vhost': options.http_vhost(), 'hook_version': HOOK_VERSIONS['commit-email'], } hook = evaluate('plugins/vcs/git/post-receive', variables) try: os.unlink(hook_dest) except OSError as e: if e.errno != errno.ENOENT: raise try: with file(hook_dest, 'w') as f: f.write(hook) os.chmod(hook_dest, 0o755) except OSError as e: raise repository.PermissionError("Enabling hook failed: %s" % (str(e), )) try: cfg = repository.directory('git', reponame) + 'config' email = options.value( 'commit_email_from', 'Please configure commit_email_from <*****@*****.**>') set_git_config(cfg, 'multimailhook.emailmaxlines', '2000') prefix = '[%s]' % reponame set_git_config(cfg, 'multimailhook.emailprefix', prefix) set_git_config(cfg, 'multimailhook.envelopesender', email) except SetGitConfigError as e: raise repository.PermissionError( "Enabling hook succeeded, but configuring it failed: %s" % (str(e))) else: try: os.unlink(hook_dest) except OSError as e: if e.errno != errno.ENOENT: raise repository.PermissionError("Removing hook failed: %s" % (str(e), ))
def setCommitEmailHook(reponame, enable): prepare(reponame) reposdir = repository.directory('git', reponame) hook_dir = reposdir + 'hooks' + 'post-receive.d' mkdirs(hook_dir) hook_dest = hook_dir + '001-commit-email.hook' if enable: variables = { 'submin_lib_dir': options.lib_path(), 'base_url': options.url_path('base_url_submin'), 'http_vhost': options.http_vhost(), 'hook_version': HOOK_VERSIONS['commit-email'], } hook = evaluate('plugins/vcs/git/post-receive', variables) try: os.unlink(hook_dest) except OSError as e: if e.errno != errno.ENOENT: raise try: with file(hook_dest, 'w') as f: f.write(hook) os.chmod(hook_dest, 0o755) except OSError as e: raise repository.PermissionError( "Enabling hook failed: %s" % (str(e),)) try: cfg = repository.directory('git', reponame) + 'config' email = options.value('commit_email_from', 'Please configure commit_email_from <*****@*****.**>') set_git_config(cfg, 'multimailhook.emailmaxlines', '2000') prefix = '[%s]' % reponame set_git_config(cfg, 'multimailhook.emailprefix', prefix) set_git_config(cfg, 'multimailhook.envelopesender', email) except SetGitConfigError as e: raise repository.PermissionError( "Enabling hook succeeded, but configuring it failed: %s" % (str(e))) else: try: os.unlink(hook_dest) except OSError as e: if e.errno != errno.ENOENT: raise repository.PermissionError( "Removing hook failed: %s" % (str(e),))
def settings_defaults(self, filename): # write the bootstrap settings file submin_settings = ''' import os storage = "sql" sqlite_path = os.path.join(os.path.dirname(__file__), "submin.db") ''' dirname = os.path.dirname(filename) mkdirs(dirname) file(filename, 'w').write(submin_settings) # after writing the bootstrap file, we setup all models self.sa.ensure_storage() from submin.models import storage storage.database_evolve() # And now we can use the models from submin.models import options import platform http_base = '' default_options = { 'base_url_submin': http_base + '/submin', 'base_url_svn': http_base + '/svn', 'base_url_git': http_base + '/git', 'base_url_trac': http_base + '/trac', 'http_vhost': platform.node(), 'auth_type': 'sql', 'svn_dir': 'svn', 'git_dir': 'git', 'trac_dir': 'trac', 'dir_bin': 'static/bin', 'enabled_trac': 'no', 'enabled_external': 'no', 'external_server': 'ldaps://example.net', 'external_base_dn': 'DC=example,DC=net', 'external_group_dn': 'CN=SVN,OU=SVN,DC=example,DC=net', 'external_user': '******', 'external_passwd': 'secret', 'external_upn_suffix': 'example.net', 'session_salt': self.session_salt(), 'env_path': '/bin:/usr/bin:/usr/local/bin:/opt/local/bin', 'vcs_plugins': 'git,svn', } for (key, value) in default_options.iteritems(): options.set_value(key, value) self.generate_cgi()
def settings_defaults(self, filename): # write the bootstrap settings file submin_settings = ''' import os storage = "sql" sqlite_path = os.path.join(os.path.dirname(__file__), "submin.db") ''' dirname = os.path.dirname(filename) mkdirs(dirname) file(filename, 'w').write(submin_settings) # after writing the bootstrap file, we setup all models self.sa.ensure_storage() from submin.models import storage storage.database_evolve() # And now we can use the models from submin.models import options import platform http_base = '' default_options = { 'base_url_submin': http_base + '/submin', 'base_url_svn': http_base + '/svn', 'base_url_git': http_base + '/git', 'base_url_trac': http_base + '/trac', 'http_vhost': platform.node(), 'auth_type': 'sql', 'svn_dir': 'svn', 'git_dir': 'git', 'trac_dir': 'trac', 'dir_bin': 'static/bin', 'enabled_trac': 'no', 'session_salt': self.session_salt(), 'env_path': '/bin:/usr/bin:/usr/local/bin:/opt/local/bin', 'vcs_plugins': 'git,svn', } for (key, value) in default_options.iteritems(): options.set_value(key, value) self.generate_cgi()
def subcmd_create(self, argv): from submin.models import options if len(argv) == 0: self.sa.execute(['help', 'nginxconf']) return if argv[0] != 'all': # the only option at the moment self.sa.execute(['help', 'nginxconf']) return if len(argv) > 1: # not always true with 'all' self.init_vars['output'] = argv[1] else: # argv[0] must be 'all' self.init_vars['output'] = options.env_path() + 'conf' + 'nginx.conf' mkdirs(self.sa.env + '/run') self._nginx_conf_create() self.sa.execute(['unixperms', 'fix'])
def create(vcs_type, reposname, adminUser): from submin.models.repository import directory as repodir basedir = options.env_path('trac_dir') mkdirs(str(basedir)) tracenv = basedir + reposname projectname = reposname vcsdir = repodir(vcs_type, reposname) admin_command(tracenv, ['initenv', projectname, 'sqlite:db/trac.db', vcs_type, vcsdir]) admin_command(tracenv, ['permission', 'add', adminUser.name, "TRAC_ADMIN"]) components = [ 'tracopt.ticket.commit_updater.*', 'tracopt.versioncontrol.%s.*' % vcs_type ] for component in components: admin_command(tracenv, ['config', 'set', 'components', component, 'enabled'])
def subcmd_create(self, argv): from submin.models import options if len(argv) == 0: self.sa.execute(['help', 'nginxconf']) return if argv[0] != 'all': # the only option at the moment self.sa.execute(['help', 'nginxconf']) return if len(argv) > 1: # not always true with 'all' self.init_vars['output'] = argv[1] else: # argv[0] must be 'all' self.init_vars['output'] = options.env_path( ) + 'conf' + 'nginx.conf' mkdirs(self.sa.env + '/run') self._nginx_conf_create() self.sa.execute(['unixperms', 'fix'])
def create(vcs_type, reposname, adminUser): from submin.models.repository import directory as repodir basedir = options.env_path('trac_dir') mkdirs(str(basedir)) tracenv = basedir + reposname projectname = reposname vcsdir = repodir(vcs_type, reposname) admin_command( tracenv, ['initenv', projectname, 'sqlite:db/trac.db', vcs_type, vcsdir]) admin_command(tracenv, ['permission', 'add', adminUser.name, "TRAC_ADMIN"]) components = [ 'tracopt.ticket.commit_updater.*', 'tracopt.versioncontrol.%s.*' % vcs_type ] for component in components: admin_command(tracenv, ['config', 'set', 'components', component, 'enabled'])
def chgrp_relevant_files(self, git_uid, git_gid): from submin.models import options # Fix permissions for paths, which the git-user needs to be able to # access, in order to also access files within os.chown(str(options.env_path()), -1, int(git_gid)) os.chmod(str(options.env_path()), 0o750) conf_dir = options.env_path() + "conf" os.chown(str(conf_dir), -1, int(git_gid)) # now make everything in git's home-dir owned by the git user and apache group from submin.subminadmin import c_unixperms apache = www_user() git_dir = options.env_path("git_dir") ssh_dir = git_dir + ".ssh" # make ssh dir, if not already exists mkdirs(ssh_dir) for root, dirs, files in os.walk(git_dir): for f in files: path = os.path.join(root, f) if root == ssh_dir: os.chown(path, int(git_uid), int(git_gid)) os.chmod(path, 0o700) else: # don't chown anything that is symlinked if not os.path.islink(path): os.chown(path, int(git_uid), int(apache.pw_gid)) os.chmod(path, 0o750) for d in dirs: path = os.path.join(root, d) os.chown(path, int(git_uid), int(apache.pw_gid)) os.chmod(path, 0o750 | stat.S_ISGID) # The git-directory itself should also be available to the apache-user, # So it can list the repositories os.chmod(git_dir, 0o750 | stat.S_ISGID) os.chown(git_dir, int(git_uid), int(apache.pw_gid)) # The ssh-directory can be really strict, only allow git os.chmod(ssh_dir, 0o700) os.chown(ssh_dir, int(git_uid), int(git_gid)) # Now, fix the permissions for the actual files os.chown(str(conf_dir + "settings.py"), -1, int(git_gid)) os.chown(str(conf_dir + "submin.db"), -1, int(git_gid)) # These last ones are a bit tricky, id_dsa and id_dsa.pub are # NOT owned by the git user, as they are client files owned # by the www user. However, SSH requires strict permissions # and id_dsa.pub needs to be readable by the git user, so it # can add the public key to the authorized_keys file. os.chown(str(conf_dir + "id_dsa.pub"), -1, int(git_gid)) os.chmod(str(conf_dir + "id_dsa"), 0o600) # now check if trac is enabled, because we need access to it # if the trac-sync script is enabled if options.value('enabled_trac', 'no') != 'no': trac_dir = options.env_path('trac_dir') os.chown(trac_dir, int(apache.pw_uid), int(git_gid)) os.chmod(trac_dir, 0o2770) # set-gid