Example #1
0
def git_dir_wrong_perms():
    submin_env = options.env_path()
    git_dir = options.env_path("git_dir")
    try:
        git_user = pwd.getpwnam(options.value("git_user"))
    except UnknownKeyError:
        return []

    apache = www_user()

    wrong_permissions = []
    checkdir = git_dir
    while checkdir != "/" and checkdir != submin_env:
        try:
            st = os.stat(checkdir)
        except OSError as e:
            if e.errno == errno.EACCES:
                wrong_permissions.append({"dir": checkdir, "reason": "unknown"})
        else:
            if (st.st_uid != git_user.pw_uid or st.st_gid != apache.pw_gid or st.st_mode & 0o750 != 0o750) and (
                st.st_mode & 0o005 != 0o005
            ):
                wrong_permissions.append({"dir": checkdir, "reason": "incorrect"})

        checkdir = os.path.dirname(checkdir)

    return wrong_permissions
Example #2
0
def trigger_user_hook(event, **args):
	user_hooks_path = options.env_path() + "hooks" + event
	if not user_hooks_path.exists():
		return

	user_hooks = sorted(glob.glob(str(user_hooks_path + "*")))

	cwd = os.getcwd()
	os.chdir(str(options.env_path()))

	env = dict([(key.upper(), value) for key, value in args.iteritems()
			if value])
	for hook in user_hooks:
		try:
			# XXX What to do with system hooks which are not executable?
			# (since they are located in the site-packages directory)
			p = Popen([hook], env=env)
			p.wait() # wait for the hook to terminate
		except OSError as e:
			# XXX: log the error
			# log("An OS error occured while processing hook "
			# 	"%s. The error was: %s" % (hook, e))
			pass

	os.chdir(cwd)
Example #3
0
def trigger_user_hook(event, **args):
    user_hooks_path = options.env_path() + "hooks" + event
    if not user_hooks_path.exists():
        return

    user_hooks = sorted(glob.glob(str(user_hooks_path + "*")))

    cwd = os.getcwd()
    os.chdir(str(options.env_path()))

    env = dict([(key.upper(), value) for key, value in args.iteritems()
                if value])
    for hook in user_hooks:
        try:
            # XXX What to do with system hooks which are not executable?
            # (since they are located in the site-packages directory)
            p = Popen([hook], env=env)
            p.wait()  # wait for the hook to terminate
        except OSError as e:
            # XXX: log the error
            # log("An OS error occured while processing hook "
            # 	"%s. The error was: %s" % (hook, e))
            pass

    os.chdir(cwd)
Example #4
0
def git_dir_wrong_perms():
    submin_env = options.env_path()
    git_dir = options.env_path("git_dir")
    try:
        git_user = pwd.getpwnam(options.value("git_user"))
    except UnknownKeyError:
        return []

    apache = www_user()

    wrong_permissions = []
    checkdir = git_dir
    while checkdir != '/' and checkdir != submin_env:
        try:
            st = os.stat(checkdir)
        except OSError as e:
            if e.errno == errno.EACCES:
                wrong_permissions.append({
                    'dir': checkdir,
                    'reason': 'unknown'
                })
        else:
            if (st.st_uid != git_user.pw_uid or st.st_gid != apache.pw_gid
                    or st.st_mode & 0o750 != 0o750) and (st.st_mode & 0o005 !=
                                                         0o005):
                wrong_permissions.append({
                    'dir': checkdir,
                    'reason': 'incorrect'
                })

        checkdir = os.path.dirname(checkdir)

    return wrong_permissions
Example #5
0
	def setUp(self):
		self.submin_env = tempfile.mkdtemp(prefix='submin-unittest')
		self.conf_dir = os.path.join(self.submin_env, 'conf')
		os.mkdir(self.conf_dir)
		self.authz_file = os.path.join(self.submin_env, 'conf', 'authz')

		mock_settings.base_dir = self.submin_env
		storage.open(mock_settings)
		storage.database_evolve()
		options.set_value('vcs_plugins', 'svn')
		options.set_value('svn_dir', 'svn')
		options.set_value('trac_dir', 'trac')
		options.set_value('svn_authz_file', 'conf/authz')
		options.set_value('enabled_trac', 'no')
		options.set_value('http_vhost', 'localhost')
		options.set_value('base_url_submin', '/submin')

		self.svn_dir = str(options.env_path('svn_dir'))
		self.trac_dir = str(options.env_path('trac_dir'))
		os.mkdir(self.svn_dir)
		os.mkdir(self.trac_dir)

		# now make some repositories
		self.repositories = [
			{'name': 'foo', 'status': 'ok', 'vcs': 'svn'},
			{'name': 'invalidperm', 'status': 'permission denied', 'vcs': 'svn'},
			{'name': 'invalidperm2', 'status': 'permission denied', 'vcs': 'svn'},
			{'name': 'example', 'status': 'ok', 'vcs': 'svn'},
			{'name': 'subdirs', 'status': 'ok', 'vcs': 'svn'},
		]
		self.has_invalidperm = False
		self.has_invalidperm2 = False
Example #6
0
def export_notifications(**kwargs):
    """Export a mailer.py config file
	For each user/repository pair, a config group is created. Only if a user
	has read or read/write permission to one or multiple paths in that
	repository, _and_ if the user has notifications enabled for that
	repository, _and_ if the user has a non-empty email-address. Multiple
	paths are grouped together by a regexp group (multiple|paths)"""
    bindir = options.static_path("hooks") + 'svn'

    # get a list of all users
    from submin.models import user
    users = [user.User(name) for name in user.list(user.FakeAdminUser())]

    groups = []
    for u in users:
        if not u.email:
            continue

        u_notif = u.notifications()

        for repos in u_notif:
            repos_path = str(options.env_path("svn_dir") + repos)
            if not u_notif[repos]["enabled"]:
                continue

            # strip leading /
            paths = [
                x[1:]
                for x in permissions.list_readable_user_paths(repos, "svn", u)
            ]
            if len(paths) == 0:
                continue
            elif len(paths) == 1:
                for_paths = paths[0]
            elif len(paths) > 0:
                for_paths = "(" + "|".join(paths) + ")"

            # Only match complete path, not partial paths (ticket #257)
            repos_path_re = '^' + repos_path + '$'

            g = {
                "repos_name": repos,
                "for_repos": repos_path_re,
                "email": u.email,
                "for_paths": for_paths,
                "username": u.name
            }
            groups.append(g)

    email = options.value(
        'commit_email_from',
        'Please configure commit_email_from <*****@*****.**>')
    templatevariables = {"groups": groups, 'from_addr': email}

    from submin.template.shortcuts import evaluate
    content = evaluate("plugins/vcs/svn/mailer.conf", templatevariables)
    filename = str((options.env_path() + 'conf') + 'mailer.py.conf')
    file(filename, 'w').writelines(content.encode('utf-8'))
Example #7
0
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])
Example #8
0
    def setUp(self):
        self.submin_env = tempfile.mkdtemp(prefix='submin-unittest')
        self.conf_dir = os.path.join(self.submin_env, 'conf')
        os.mkdir(self.conf_dir)
        self.authz_file = os.path.join(self.submin_env, 'conf', 'authz')

        mock_settings.base_dir = self.submin_env
        storage.open(mock_settings)
        storage.database_evolve()
        options.set_value('vcs_plugins', 'svn')
        options.set_value('svn_dir', 'svn')
        options.set_value('trac_dir', 'trac')
        options.set_value('svn_authz_file', 'conf/authz')
        options.set_value('enabled_trac', 'no')
        options.set_value('http_vhost', 'localhost')
        options.set_value('base_url_submin', '/submin')

        self.svn_dir = str(options.env_path('svn_dir'))
        self.trac_dir = str(options.env_path('trac_dir'))
        os.mkdir(self.svn_dir)
        os.mkdir(self.trac_dir)

        # now make some repositories
        self.repositories = [
            {
                'name': 'foo',
                'status': 'ok',
                'vcs': 'svn'
            },
            {
                'name': 'invalidperm',
                'status': 'permission denied',
                'vcs': 'svn'
            },
            {
                'name': 'invalidperm2',
                'status': 'permission denied',
                'vcs': 'svn'
            },
            {
                'name': 'example',
                'status': 'ok',
                'vcs': 'svn'
            },
            {
                'name': 'subdirs',
                'status': 'ok',
                'vcs': 'svn'
            },
        ]
        self.has_invalidperm = False
        self.has_invalidperm2 = False
Example #9
0
    def run(self):
        os.environ['SUBMIN_ENV'] = self.sa.env
        from submin.models import options

        if len(self.argv) < 1:
            self.sa.execute(['help', 'apacheconf'])
            return

        self.defaults = {
            'type': 'all',
        }
        cgi_bin_dir = os.path.join(self.sa.env, 'cgi-bin')
        self.init_vars = {
            'submin_env': self.canonicalize(self.sa.env),
            'www_dir': self.canonicalize(str(self.sa.basedir_www)),
            'cgi_bin_dir': self.canonicalize(str(cgi_bin_dir)),
            # Don't use options.url_path here, we need the url without
            # trailing slash.
            'submin_base_url': self.urlpath(options.value('base_url_submin')),
            'svn_base_url': self.urlpath(options.value('base_url_svn')),
            'trac_base_url': self.urlpath(options.value('base_url_trac')),
            'svn_dir': options.env_path('svn_dir'),
            'trac_dir': options.env_path('trac_dir'),
            'authz_file': options.env_path('svn_authz_file'),
            'enabled_external':
            options.value('enabled_external', 'no') != 'no',
            'external_server': options.value('external_server'),
            'external_base_dn': options.value('external_base_dn'),
            'external_group_dn': options.value('external_group_dn'),
            'external_user': options.value('external_user'),
            'external_passwd': options.value('external_passwd'),
            'external_upn_suffix': options.value('external_upn_suffix'),
        }
        self.auth_type = options.value('auth_type')

        # variables depending on auth type
        if self.auth_type == "sql":
            pass
        elif options.value('auth_type') == "htaccess":
            self.init_vars.update({
                'access file':
                options.value('auth_access_file'),
            })

        try:
            subcmd = getattr(self, 'subcmd_%s' % self.argv[0])
        except AttributeError:
            self.sa.execute(['help', 'apacheconf'])
            return

        subcmd(self.argv[1:])
Example #10
0
def export_notifications(**kwargs):
	"""Export a mailer.py config file
	For each user/repository pair, a config group is created. Only if a user
	has read or read/write permission to one or multiple paths in that
	repository, _and_ if the user has notifications enabled for that
	repository, _and_ if the user has a non-empty email-address. Multiple
	paths are grouped together by a regexp group (multiple|paths)"""
	bindir = options.static_path("hooks") + 'svn'
	
	# get a list of all users
	from submin.models import user
	users = [user.User(name) for name in user.list(user.FakeAdminUser())]

	groups = []
	for u in users:
		if not u.email:
			continue

		u_notif = u.notifications()

		for repos in u_notif:
			repos_path = str(options.env_path("svn_dir") + repos)
			if not u_notif[repos]["enabled"]:
				continue

			# strip leading /
			paths = [x[1:] for x in permissions.list_readable_user_paths(repos, "svn", u)]
			if len(paths) == 0:
				continue
			elif len(paths) == 1:
				for_paths = paths[0]
			elif len(paths) > 0:
				for_paths = "(" + "|".join(paths) + ")"

			# Only match complete path, not partial paths (ticket #257)
			repos_path_re = '^' + repos_path + '$'

			g = {"repos_name": repos, "for_repos": repos_path_re, "email": u.email,
				"for_paths": for_paths, "username": u.name}
			groups.append(g)

	email = options.value('commit_email_from', 'Please configure commit_email_from <*****@*****.**>')
	templatevariables = {"groups": groups, 'from_addr': email}

	from submin.template.shortcuts import evaluate
	content = evaluate("plugins/vcs/svn/mailer.conf", templatevariables)
	filename = str((options.env_path() + 'conf') + 'mailer.py.conf')
	file(filename, 'w').writelines(content.encode('utf-8'))
Example #11
0
def diagnostics():
	results = {}
	results['enabled_svn'] = 'svn' in options.value('vcs_plugins', '')

	if not results['enabled_svn']:
		results['enabled_svn_label'] = 'disabled'
		results['svn_all_label'] = 'disabled'
		return results

	try:
		svn_dir = options.env_path('svn_dir')
	except UnknownKeyError:
		results['svn_dir_set'] = False
	else:
		results['svn_dir_set'] = True

	found_mods = {}
	amods = []
	required_mods = ['dav', 'dav_svn', 'authz_svn', 'authn_dbd', 'dbd']
	try:
		amods = apache_modules()
	except ApacheCtlError as e:
		results['svn_apache_modules_ok'] = False
		results['svn_apache_modules_exec_ok'] = False
		results['svn_apache_modules_errmsg'] = str(e)
	else:
		results['svn_apache_modules_exec_ok'] = True

	for mod in required_mods:
		found_mods.update({mod: mod in amods})

	results['svn_apache_modules'] = found_mods
	results['svn_apache_modules_ok'] = False not in found_mods.values()
	
	return add_labels(results, 'svn_all', warnings, fails)
Example #12
0
def diagnostics():
    results = {}
    results['enabled_svn'] = 'svn' in options.value('vcs_plugins', '')

    if not results['enabled_svn']:
        results['enabled_svn_label'] = 'disabled'
        results['svn_all_label'] = 'disabled'
        return results

    try:
        svn_dir = options.env_path('svn_dir')
    except UnknownKeyError:
        results['svn_dir_set'] = False
    else:
        results['svn_dir_set'] = True

    found_mods = {}
    amods = []
    required_mods = ['dav', 'dav_svn', 'authz_svn', 'authn_dbd', 'dbd']
    try:
        amods = apache_modules()
    except ApacheCtlError as e:
        results['svn_apache_modules_ok'] = False
        results['svn_apache_modules_exec_ok'] = False
        results['svn_apache_modules_errmsg'] = str(e)
    else:
        results['svn_apache_modules_exec_ok'] = True

    for mod in required_mods:
        found_mods.update({mod: mod in amods})

    results['svn_apache_modules'] = found_mods
    results['svn_apache_modules_ok'] = False not in found_mods.values()

    return add_labels(results, 'svn_all', warnings, fails)
Example #13
0
    def subcmd_fix(self, argv):
        from submin.models import options
        if os.getuid() != 0:
            print('''
To set permissions and ownerships properly, execute:

    sudo submin2-admin %s unixperms fix

This should also remove possible following warnings.
''' % self.sa.env)
            self.root = False

        vcs_plugins = options.value("vcs_plugins")
        # git should be owned by the git user, let 'git fix_perms' handle it
        if 'git' in vcs_plugins.split(','):
            git_dir = options.env_path('git_dir')
            self.ignore_dirs.append(git_dir)

        if len(argv) > 0:
            self._fix(argv[0])
        else:
            self._fix('')

        if 'git' in vcs_plugins.split(','):
            self.sa.execute(['git', 'fix_perms'])
Example #14
0
	def run(self):
		os.environ['SUBMIN_ENV'] = self.sa.env
		from submin.models import options

		if len(self.argv) < 1:
			self.sa.execute(['help', 'nginxconf'])
			return

		self.defaults = {
			'output': options.env_path() + 'conf' + 'nginx.conf'
		}
		user = www_user()
		self.init_vars = {
			'submin_env': self.canonicalize(str(self.sa.env)),
			'www_dir': self.canonicalize(str(self.sa.basedir_www)),
			# Don't use options.url_path here, we need the url without
			# trailing slash.
			'submin_base_url': self.urlpath(options.value('base_url_submin')),
			'www_uid': user.pw_uid,
			'www_gid': user.pw_gid,
		}
		self.init_vars['real_wsgi'] = os.path.realpath(
			os.path.join(self.init_vars['www_dir'], 'submin.wsgi'))

		try:
			subcmd = getattr(self, 'subcmd_%s' % self.argv[0])
		except AttributeError:
			self.sa.execute(['help', 'nginxconf'])
			return

		subcmd(self.argv[1:])
Example #15
0
    def run(self):
        os.environ['SUBMIN_ENV'] = self.sa.env
        from submin.models import options

        if len(self.argv) < 1:
            self.sa.execute(['help', 'nginxconf'])
            return

        self.defaults = {'output': options.env_path() + 'conf' + 'nginx.conf'}
        user = www_user()
        self.init_vars = {
            'submin_env': self.canonicalize(str(self.sa.env)),
            'www_dir': self.canonicalize(str(self.sa.basedir_www)),
            # Don't use options.url_path here, we need the url without
            # trailing slash.
            'submin_base_url': self.urlpath(options.value('base_url_submin')),
            'www_uid': user.pw_uid,
            'www_gid': user.pw_gid,
        }
        self.init_vars['real_wsgi'] = os.path.realpath(
            os.path.join(self.init_vars['www_dir'], 'submin.wsgi'))

        try:
            subcmd = getattr(self, 'subcmd_%s' % self.argv[0])
        except AttributeError:
            self.sa.execute(['help', 'nginxconf'])
            return

        subcmd(self.argv[1:])
Example #16
0
def setTracSyncHook(reponame, enable):
    prepare(reponame)

    hook_dir = repository.directory('git', reponame) + 'hooks'
    hook = hook_dir + 'post-receive.d' + '002-trac-sync.hook'

    try:
        os.unlink(hook)
    except OSError as e:
        if e.errno != errno.ENOENT:
            raise repository.PermissionError(
                "Removing trac-sync hook failed: %s" % (str(e), ))

    if not enable:
        return

    variables = {
        'submin_env': str(options.env_path()),
        'repository': reponame,
        'hook_version': HOOK_VERSIONS['trac-sync'],
    }
    contents = evaluate('plugins/vcs/git/trac-sync', variables)
    with file(hook, 'w') as f:
        f.writelines(contents)

    os.chmod(hook, 0o755)
Example #17
0
def export_authz(**kwargs):
	"""Export authorization/authentication info"""
	# XXX the import here is to prevent a circular import :( design problem!
	from .repository import list as list_repos

	authz_filename = options.env_path("svn_authz_file")
	authz = codecs.open(str(authz_filename), "w+", "utf-8")

	# Write all groups
	authz.write("[groups]\n")
	for groupname in group.list(FakeAdminUser()):
		g = group.Group(groupname)
		authz.write("%s = %s\n" % (groupname, ', '.join(g.members())))
	authz.write("\n")

	# Write all repositories and their permissions
	for repository in list_repos():
		if repository["status"] != "ok":
			continue

		for path in permissions.list_paths(repository["name"], "svn"):
			authz.write("[%s:%s]\n" % (repository["name"], path))

			for perm in permissions.list_by_path(repository["name"], "svn", path):
				if perm["type"] == "group":
					authz.write("@")
				authz.write("%s = %s\n" % (perm["name"], perm["permission"]))
			authz.write("\n")

	authz.close()
Example #18
0
def setTracSyncHook(reponame, enable):
	prepare(reponame)

	hook_dir = repository.directory('git', reponame) + 'hooks'
	hook = hook_dir + 'post-receive.d' + '002-trac-sync.hook'

	try:
		os.unlink(hook)
	except OSError as e:
		if e.errno != errno.ENOENT:
			raise repository.PermissionError(
				"Removing trac-sync hook failed: %s" % (str(e),))

	if not enable:
		return

	variables = {
		'submin_env': str(options.env_path()),
		'repository': reponame,
		'hook_version': HOOK_VERSIONS['trac-sync'],
	}
	contents = evaluate('plugins/vcs/git/trac-sync', variables)
	with file(hook, 'w') as f:
		f.writelines(contents)

	os.chmod(hook, 0o755)
Example #19
0
    def run(self):
        from submin.models import options
        from submin.template.shortcuts import evaluate
        from submin.diagnostics import trac, git, svn, email

        localvars = {}

        diagnostics = {}
        if len(self.argv) > 0:
            which = self.argv[0]
        else:
            which = 'all'

        if which in ('all', 'email'):
            diagnostics.update(email.diagnostics())
        if which in ('all', 'git'):
            diagnostics.update(git.diagnostics())
        if which in ('all', 'svn'):
            diagnostics.update(svn.diagnostics())
        if which in ('all', 'trac'):
            diagnostics.update(trac.diagnostics())
        localvars['diag'] = diagnostics
        localvars['subminenv'] = options.env_path()

        formatted = evaluate('diagnostics.%s.print' % (which, ), localvars)
        print(formatted)
Example #20
0
	def subcmd_fix(self, argv):
		from submin.models import options
		if os.getuid() != 0:
			print '''
To set permissions and ownerships properly, execute:

    sudo submin2-admin %s unixperms fix

This should also remove possible following warnings.
''' % self.sa.env
			self.root = False

		vcs_plugins = options.value("vcs_plugins")
		# git should be owned by the git user, let 'git fix_perms' handle it
		if 'git' in vcs_plugins.split(','):
			git_dir = options.env_path('git_dir')
			self.ignore_dirs.append(git_dir)

		if len(argv) > 0:
			self._fix(argv[0])
		else:
			self._fix('')

		if 'git' in vcs_plugins.split(','):
			self.sa.execute(['git', 'fix_perms'])
Example #21
0
def export_authz(**kwargs):
    """Export authorization/authentication info"""
    # XXX the import here is to prevent a circular import :( design problem!
    from .repository import list as list_repos

    authz_filename = options.env_path("svn_authz_file")
    authz = codecs.open(str(authz_filename), "w+", "utf-8")

    # Write all groups
    authz.write("[groups]\n")
    for groupname in group.list(FakeAdminUser()):
        g = group.Group(groupname)
        authz.write("%s = %s\n" % (groupname, ', '.join(g.members())))
    authz.write("\n")

    # Write all repositories and their permissions
    for repository in list_repos():
        if repository["status"] != "ok":
            continue

        for path in permissions.list_paths(repository["name"], "svn"):
            authz.write("[%s:%s]\n" % (repository["name"], path))

            for perm in permissions.list_by_path(repository["name"], "svn",
                                                 path):
                if perm["type"] == "group":
                    authz.write("@")
                authz.write("%s = %s\n" % (perm["name"], perm["permission"]))
            authz.write("\n")

    authz.close()
Example #22
0
	def run(self):
		from submin.models import options
		from submin.template.shortcuts import evaluate
		from submin.diagnostics import trac, git, svn, email

		localvars = {}

		diagnostics = {}
		if len(self.argv) > 0:
			which = self.argv[0]
		else:
			which = 'all'

		if which in ('all', 'email'):
			diagnostics.update(email.diagnostics())
		if which in ('all', 'git'):
			diagnostics.update(git.diagnostics())
		if which in ('all', 'svn'):
			diagnostics.update(svn.diagnostics())
		if which in ('all', 'trac'):
			diagnostics.update(trac.diagnostics())
		localvars['diag'] = diagnostics
		localvars['subminenv'] = options.env_path()

		formatted = evaluate('diagnostics.%s.print' % (which,), localvars)
		print(formatted)
Example #23
0
def dispatcher(request):
	# Add session information to request
	request.session = Session(request)

	# session expiry time is for cleanup purposes, not for security purposes
	future_expiry = int(time.time()) + 60 * 60 * 24 * 7
	future_refresh = request.session.expires - 60 * 60 * 24

	if time.time() >= future_refresh:
		request.session.expires = future_expiry

	path = request.path_info.strip('/').split('/')

	handlerName = 'handler'
	if path[0].lower() in classes:
		tupl = classes[path[0].lower()]
		cls = tupl[0](request, tupl[1])
		if not hasattr(cls, handlerName):
			raise Exception("No handler %r found for view %r" % (handlerName, path[0].lower()))

		del path[0]
		handler = getattr(cls, handlerName)
		try:
			response = handler(request, path)

			if not issubclass(response.__class__, Response):
				raise Exception("Handler %r should return a Response instance" % handler)
		except UnknownKeyError as e:
			env = options.env_path() # this should never trigger another UnknownKeyError
			summary = "It seems your installation is missing a configuration option (%s)" % str(e)
			details = """
You can add the missing config option by executing the following commandline:

submin2-admin %s config set %s &lt;value&gt;

Unfortunately, this error handling does not know the value you should set, but
the name of the missing option should give you a hint to its value :)""" % \
	(env, str(e))

			if not request.is_ajax():
				response = ErrorResponse(summary, request=request, details=details)
			else:
				details = summary + '\n\n' + details
				response = XMLStatusResponse('', False, details)
		except Exception as e:
			import traceback
			details = traceback.format_exc()

			if not request.is_ajax():
				response = ErrorResponse(str(e), request=request, details=details)
			else:
				response = XMLStatusResponse('', False, str(e), details=details)

	else:
		response = HTTP404('/'.join(path))

	response.setCookieHeaders(request.cookieHeaders())

	return response
Example #24
0
    def subcmd_init(self, argv):
        from submin.models import options
        from submin.subminadmin import trac
        """Initialize trac
		Why not just distribute them with submin? Two reasons: one is because
		they might change with each version of trac, two is because those scripts
		have a different license and IANAL so this is easier (reason one should
		be enough anyway).
		"""
        tmp_trac_dir = options.env_path() + 'tmp-trac'
        tmp_deploy_dir = tmp_trac_dir + 'deploy'

        if not trac.exists():
            print(
                "Could not find 'trac-admin' command. If you want to use Trac, please"
            ),
            print("install trac and run: `submin2-admin %s trac init`" %
                  options.env_path())
            return

        print(
            'Initializing trac files. This might take a while, please wait ...'
        )
        # first, create a temp trac env, because 'deploy' needs a working trac
        # env (sigh)
        trac.initenv(str(tmp_trac_dir), 'dummy', 'svn', '/tmp/non-existing')

        # then generate the scripts
        trac.deploy(str(tmp_trac_dir), str(tmp_deploy_dir))

        # copy them to our cgi-bin
        cgi_bin_dir = options.env_path() + 'cgi-bin'
        for root, dirs, files in os.walk(str(tmp_deploy_dir + 'cgi-bin')):
            for filename in files:
                src = os.path.join(root, filename)
                dst = os.path.join(str(cgi_bin_dir), filename)
                self.generate_Xgi_script(src, dst)

        # ... and remove the temporary trac env
        shutil.rmtree(str(tmp_trac_dir))

        # finally, set all permissions and ownerships
        self.sa.execute(['unixperms', 'fix'])
        print('Done.')
        return
Example #25
0
    def rewritePostCommitHook(self, signature, new_hook, enable):
        reposdir = options.env_path('svn_dir')
        hook = reposdir + self.name + 'hooks' + 'post-commit'

        shellscript.rewriteWithSignature(hook,
                                         signature,
                                         new_hook,
                                         enable,
                                         mode=0o755)
Example #26
0
    def setUp(self):
        self.submin_env = tempfile.mkdtemp(prefix='submin-unittest')
        self.conf_dir = os.path.join(self.submin_env, 'conf')
        os.mkdir(self.conf_dir)
        mock_settings.base_dir = self.submin_env
        storage.open(mock_settings)
        storage.database_evolve()

        options.set_value('vcs_plugins', 'svn')
        options.set_value('svn_dir', 'svn')
        options.set_value('trac_dir', 'trac')
        options.set_value('svn_authz_file', 'conf/authz')
        options.set_value('enabled_trac', 'yes')

        self.svn_dir = str(options.env_path('svn_dir'))
        self.trac_dir = str(options.env_path('trac_dir'))
        os.mkdir(self.svn_dir)
        os.mkdir(self.trac_dir)
Example #27
0
	def setUp(self):
		self.submin_env = tempfile.mkdtemp(prefix='submin-unittest')
		self.conf_dir = os.path.join(self.submin_env, 'conf')
		os.mkdir(self.conf_dir)
		mock_settings.base_dir = self.submin_env
		storage.open(mock_settings)
		storage.database_evolve()

		options.set_value('vcs_plugins', 'svn')
		options.set_value('svn_dir', 'svn')
		options.set_value('trac_dir', 'trac')
		options.set_value('svn_authz_file', 'conf/authz')
		options.set_value('enabled_trac', 'yes')

		self.svn_dir = str(options.env_path('svn_dir'))
		self.trac_dir = str(options.env_path('trac_dir'))
		os.mkdir(self.svn_dir)
		os.mkdir(self.trac_dir)
Example #28
0
def directory(reposname):
	# FIXME: encoding?
	base_dir = options.env_path('svn_dir')
	reposdir = base_dir + reposname
	# We could use realpath to check, but we don't want to prevent usage of
	# symlinks in their svn directory
	if not os.path.normpath(reposdir).startswith(os.path.normpath(base_dir)):
		raise Exception('Subversion directory outside base path');

	return reposdir
Example #29
0
def _repositoriesOnDisk():
	reposdir = options.env_path('mock_dir', default="mock")
	reps = glob.glob(str(reposdir + '*.mock'))
	repositories = []
	for rep in reps:
		if os.path.isdir(rep):
			name = rep[rep.rfind('/') + 1:]
			repositories.append(unicode(name, 'utf-8'))

	return repositories
Example #30
0
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)
Example #31
0
def directory(reposname):
	# FIXME: encoding?
	base_dir = options.env_path('svn_dir')
	reposdir = base_dir + reposname
	# We could use realpath to check, but we don't want to prevent usage of
	# symlinks in their svn directory
	if not os.path.normpath(reposdir).startswith(os.path.normpath(base_dir)):
		raise Exception('Subversion directory outside base path');

	return reposdir
Example #32
0
def add(name):
	reposdir = options.env_path('svn_dir')
	newrepos = reposdir + name
	path = options.value('env_path', "/bin:/usr/bin:/usr/local/bin:/opt/local/bin")
	cmd = "PATH='%s' svnadmin create '%s'" % (path, str(newrepos))
	(exitstatus, outtext) = subprocess.getstatusoutput(cmd)
	if exitstatus != 0:
		raise PermissionError("External command 'svnadmin' failed: %s" % outtext)

	repos = Repository(name)
Example #33
0
	def remove(self):
		reposdir = options.env_path('svn_dir')
		newrepos = reposdir + self.name
		if not newrepos.absolute:
			raise Exception("Error, repository path is relative, this should be fixed")

		cmd = 'rm -rf "%s"' % newrepos
		(exitstatus, outtext) = subprocess.getstatusoutput(cmd)
		if exitstatus != 0:
			raise Exception("could not remove repository %s" % self.name)
Example #34
0
def add(name):
	reposdir = options.env_path('svn_dir')
	newrepos = reposdir + name
	path = options.value('env_path', "/bin:/usr/bin:/usr/local/bin:/opt/local/bin")
	cmd = "PATH='%s' svnadmin create '%s'" % (path, str(newrepos))
	(exitstatus, outtext) = commands.getstatusoutput(cmd)
	if exitstatus != 0:
		raise PermissionError("External command 'svnadmin' failed: %s" % outtext)

	repos = Repository(name)
Example #35
0
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)
Example #36
0
    def remove_system_hooks(self):
        from submin.models import options

        env_event_dir = options.env_path() + "hooks"
        for script in glob.glob(str(env_event_dir + "*/[3-6]*")):
            try:
                os.unlink(script)
            except OSError as e:
                print "updating hook %s failed, do you have permissions?" % script
                raise e
Example #37
0
	def remove(self):
		reposdir = options.env_path('svn_dir')
		newrepos = reposdir + self.name
		if not newrepos.absolute:
			raise Exception("Error, repository path is relative, this should be fixed")

		cmd = 'rm -rf "%s"' % newrepos
		(exitstatus, outtext) = commands.getstatusoutput(cmd)
		if exitstatus != 0:
			raise Exception("could not remove repository %s" % self.name)
Example #38
0
def _repositoriesOnDisk():
    reposdir = options.env_path('mock_dir', default="mock")
    reps = glob.glob(str(reposdir + '*.mock'))
    repositories = []
    for rep in reps:
        if os.path.isdir(rep):
            name = rep[rep.rfind('/') + 1:]
            repositories.append(unicode(name, 'utf-8'))

    return repositories
Example #39
0
    def copy_system_hooks(self, event_dir):
        from submin.models import options

        sys_event_dir = options.static_path("hooks") + "submin" + event_dir
        env_event_dir = options.env_path() + "hooks" + event_dir
        for script in glob.glob(str(sys_event_dir + "[3-6]*")):
            try:
                shutil.copy(script, str(env_event_dir))
            except IOError as e:
                print "updating hook %s failed, do you have permissions?" % script
Example #40
0
	def run(self):
		os.environ['SUBMIN_ENV'] = self.sa.env
		from submin.models import options

		if len(self.argv) < 1:
			self.sa.execute(['help', 'apacheconf'])
			return

		self.defaults = {
			'type': 'all',
		}
		cgi_bin_dir = os.path.join(self.sa.env, 'cgi-bin')
		self.init_vars = {
			'submin_env': self.canonicalize(self.sa.env),
			'www_dir': self.canonicalize(str(self.sa.basedir_www)),
			'cgi_bin_dir': self.canonicalize(str(cgi_bin_dir)),
			# Don't use options.url_path here, we need the url without
			# trailing slash.
			'submin_base_url': self.urlpath(options.value('base_url_submin')),
			'svn_base_url': self.urlpath(options.value('base_url_svn')),
			'trac_base_url': self.urlpath(options.value('base_url_trac')),
			'svn_dir': options.env_path('svn_dir'),
			'trac_dir': options.env_path('trac_dir'),
			'authz_file': options.env_path('svn_authz_file'),
		}
		self.auth_type = options.value('auth_type')

		# variables depending on auth type
		if self.auth_type == "sql":
			pass
		elif options.value('auth_type') == "htaccess":
			self.init_vars.update({
				'access file': options.value('auth_access_file'),
			})

		try:
			subcmd = getattr(self, 'subcmd_%s' % self.argv[0])
		except AttributeError:
			self.sa.execute(['help', 'apacheconf'])
			return

		subcmd(self.argv[1:])
Example #41
0
def _repositoriesOnDisk():
	"""Returns all repositories that are found on disk"""
	import glob, os.path
	reposdir = options.env_path('svn_dir')
	reps = glob.glob(str(reposdir + '*'))
	repositories = []
	for rep in reps:
		if os.path.isdir(rep):
			repositories.append(rep[rep.rfind('/') + 1:])

	return repositories
Example #42
0
def _repositoriesOnDisk():
    reposdir = options.env_path('git_dir')
    reps = glob.glob(str(reposdir + '*.git'))
    repositories = []
    for rep in reps:
        if os.path.isdir(rep):
            name = rep[rep.rfind('/') + 1:]
            name = name[:-4]  # chop off '.git'
            repositories.append(unicode(name, 'utf-8'))

    return repositories
    def remove_system_hooks(self):
        from submin.models import options

        env_event_dir = options.env_path() + "hooks"
        for script in glob.glob(str(env_event_dir + "*/[3-6]*")):
            try:
                os.unlink(script)
            except OSError as e:
                print 'updating hook %s failed, do you have permissions?' % \
                  script
                raise e
Example #44
0
def _repositoriesOnDisk():
    """Returns all repositories that are found on disk"""
    import glob, os.path
    reposdir = options.env_path('svn_dir')
    reps = glob.glob(str(reposdir + '*'))
    repositories = []
    for rep in reps:
        if os.path.isdir(rep):
            repositories.append(rep[rep.rfind('/') + 1:])

    return repositories
Example #45
0
def _repositoriesOnDisk():
	reposdir = options.env_path('git_dir')
	reps = glob.glob(str(reposdir + '*.git'))
	repositories = []
	for rep in reps:
		if os.path.isdir(rep):
			name = rep[rep.rfind('/') + 1:]
			name = name[:-4] # chop off '.git'
			repositories.append(unicode(name, 'utf-8'))

	return repositories
    def copy_system_hooks(self, event_dir):
        from submin.models import options

        sys_event_dir = options.static_path("hooks") + "submin" + event_dir
        env_event_dir = options.env_path() + "hooks" + event_dir
        for script in glob.glob(str(sys_event_dir + "[3-6]*")):
            try:
                shutil.copy(script, str(env_event_dir))
            except IOError as e:
                print 'updating hook %s failed, do you have permissions?' % \
                  script
Example #47
0
	def enableTracCommitHook(self, enable):
		"""Add or remove trac commit script to/from the post-commit hook"""
		import os

		bindir = options.static_path('hooks') + 'svn'
		fullpath = str(bindir + 'trac-post-commit-hook')
		trac_env = str(options.env_path('trac_dir') + self.name)

		new_hook = '/usr/bin/python %s -p %s -r "$2"\n' % \
				(fullpath, trac_env)

		self.rewritePostCommitHook(self.trac_signature, new_hook, enable)
Example #48
0
	def enableTracCommitHook(self, enable):
		"""Add or remove trac commit script to/from the post-commit hook"""
		import os

		bindir = options.static_path('hooks') + 'svn'
		fullpath = str(bindir + 'trac-post-commit-hook')
		trac_env = str(options.env_path('trac_dir') + self.name)

		new_hook = '/usr/bin/python %s -p %s -r "$2"\n' % \
				(fullpath, trac_env)

		self.rewritePostCommitHook(self.trac_signature, new_hook, enable)
Example #49
0
def _repositoriesOnDisk():
	"""Returns all repositories that are found on disk"""
	import glob, os.path
	reposdir = options.env_path('svn_dir')
	repositories = []
	if not os.path.lexists(reposdir):
		return []

	for rep in os.listdir(reposdir):
		if os.path.isdir((reposdir + rep).encode('utf-8')):
			repositories.append(rep)
	return repositories
Example #50
0
	def subcmd_init(self, argv):
		from submin.models import options
		from submin.subminadmin import trac
		"""Initialize trac
		Why not just distribute them with submin? Two reasons: one is because
		they might change with each version of trac, two is because those scripts
		have a different license and IANAL so this is easier (reason one should
		be enough anyway).
		"""
		tmp_trac_dir = options.env_path() + 'tmp-trac'
		tmp_deploy_dir = tmp_trac_dir + 'deploy'

		if not trac.exists():
			print "Could not find 'trac-admin' command. If you want to use Trac, please",
			print "install trac and run: `submin2-admin %s trac init`" % options.env_path()
			return

		print 'Initializing trac files. This might take a while, please wait ...'
		# first, create a temp trac env, because 'deploy' needs a working trac
		# env (sigh)
		trac.initenv(str(tmp_trac_dir), 'dummy', 'svn', '/tmp/non-existing')

		# then generate the scripts
		trac.deploy(str(tmp_trac_dir), str(tmp_deploy_dir))

		# copy them to our cgi-bin
		cgi_bin_dir = options.env_path() + 'cgi-bin'
		for root, dirs, files in os.walk(str(tmp_deploy_dir + 'cgi-bin')):
			for filename in files:
				src = os.path.join(root, filename)
				dst = os.path.join(str(cgi_bin_dir), filename)
				self.generate_Xgi_script(src, dst)
		
		# ... and remove the temporary trac env
		shutil.rmtree(str(tmp_trac_dir))

		# finally, set all permissions and ownerships
		self.sa.execute(['unixperms', 'fix'])
		print 'Done.'
		return
Example #51
0
def diagnostics():
    results = {}
    results['enabled_git'] = 'git' in options.value('vcs_plugins', '')

    if not results['enabled_git']:
        results['enabled_git_label'] = 'disabled'
        results['git_all_label'] = 'disabled'
        return results

    try:
        git_dir = options.env_path('git_dir')
    except UnknownKeyError:
        results['git_dir_set'] = False
        results['git_hooks_all_new'] = True  # because no repositories
        results['git_old_hook_repos'] = []
    else:
        results['git_dir_set'] = True
        old_repos = list(old_hook_repos(git_dir))
        results['git_hooks_all_new'] = len(old_repos) == 0
        results['git_old_hook_repos'] = old_repos

        # check dirs for correct permissions
        bad_dirs = git_repos_wrong_perms(git_dir)
        results['git_repos_correct_perms'] = len(bad_dirs) == 0
        results['git_repos_bad_dirs'] = bad_dirs

    try:
        git_ssh_host = options.value('git_ssh_host')
    except UnknownKeyError:
        results['git_hostname_ok'] = False
    else:
        results['git_hostname_ok'] = True
        if git_ssh_host in ('localhost', '127.0.0.1', '::1'):
            results['git_hostname_ok'] = False

    try:
        remote.execute("update-auth")
    except (remote.NonZeroExitStatus, UnknownKeyError) as e:
        results['git_admin_test'] = False
        results['git_admin_test_errmsg'] = str(e)
        results['git_ssh_host_internal'] = options.value(
            'git_ssh_host_internal', 'git_ssh_host_internal')
        results['git_user'] = options.value('git_user', 'git_user')
        results['git_ssh_port'] = options.value('git_ssh_port', 'git_ssh_port')
    else:
        results['git_admin_test'] = True

    wrong_perms = git_dir_wrong_perms()
    results['git_dir_perms_wrong'] = wrong_perms
    results['git_dir_perms'] = len(wrong_perms) == 0

    return add_labels(results, 'git_all', warnings, fails)
Example #52
0
	def handler(self, req, path):
		localvars = {}

		diagnostics = {}
		diagnostics.update(trac.diagnostics())
		diagnostics.update(svn.diagnostics())
		diagnostics.update(git.diagnostics())
		diagnostics.update(email.diagnostics())
		localvars['diag'] = diagnostics
		localvars['subminenv'] = options.env_path()

		formatted = evaluate_main('diagnostics.html', localvars, request=req)
		return Response(formatted)
Example #53
0
    def handler(self, req, path):
        localvars = {}

        diagnostics = {}
        diagnostics.update(trac.diagnostics())
        diagnostics.update(svn.diagnostics())
        diagnostics.update(git.diagnostics())
        diagnostics.update(email.diagnostics())
        localvars['diag'] = diagnostics
        localvars['subminenv'] = options.env_path()

        formatted = evaluate_main('diagnostics.html', localvars, request=req)
        return Response(formatted)
Example #54
0
def diagnostics():
    results = {}
    results["enabled_git"] = "git" in options.value("vcs_plugins", "")

    if not results["enabled_git"]:
        results["enabled_git_label"] = "disabled"
        results["git_all_label"] = "disabled"
        return results

    try:
        git_dir = options.env_path("git_dir")
    except UnknownKeyError:
        results["git_dir_set"] = False
        results["git_hooks_all_new"] = True  # because no repositories
        results["git_old_hook_repos"] = []
    else:
        results["git_dir_set"] = True
        old_repos = list(old_hook_repos(git_dir))
        results["git_hooks_all_new"] = len(old_repos) == 0
        results["git_old_hook_repos"] = old_repos

        # check dirs for correct permissions
        bad_dirs = git_repos_wrong_perms(git_dir)
        results["git_repos_correct_perms"] = len(bad_dirs) == 0
        results["git_repos_bad_dirs"] = bad_dirs

    try:
        git_ssh_host = options.value("git_ssh_host")
    except UnknownKeyError:
        results["git_hostname_ok"] = False
    else:
        results["git_hostname_ok"] = True
        if git_ssh_host in ("localhost", "127.0.0.1", "::1"):
            results["git_hostname_ok"] = False

    try:
        remote.execute("update-auth")
    except (remote.NonZeroExitStatus, UnknownKeyError) as e:
        results["git_admin_test"] = False
        results["git_admin_test_errmsg"] = str(e)
        results["git_ssh_host_internal"] = options.value("git_ssh_host_internal", "git_ssh_host_internal")
        results["git_user"] = options.value("git_user", "git_user")
        results["git_ssh_port"] = options.value("git_ssh_port", "git_ssh_port")
    else:
        results["git_admin_test"] = True

    wrong_perms = git_dir_wrong_perms()
    results["git_dir_perms_wrong"] = wrong_perms
    results["git_dir_perms"] = len(wrong_perms) == 0

    return add_labels(results, "git_all", warnings, fails)
Example #55
0
def execute(remote_command):
	ssh_key_path = options.env_path() + 'conf' + 'id_dsa'

	# The options provided with the -o flags are to prevent ssh trying to
	# create a '.ssh' directory in the homedir of the www user.
	cmd = 'ssh -i "%s" %s@%s -p %s -o "StrictHostKeyChecking=no"'
	cmd += ' -o "PreferredAuthentications=publickey"'
	cmd += ' -o "UserKnownHostsFile=/dev/null" %s'
	(exitstatus, outtext) = commands.getstatusoutput(cmd % (ssh_key_path,
		options.value("git_user"), options.value("git_ssh_host_internal"),
		options.value("git_ssh_port"), remote_command))

	if exitstatus != 0:
		raise NonZeroExitStatus(outtext)
Example #56
0
def export_htpasswd(*args, **kwargs):
	try:
		htpasswd_file = options.env_path("htpasswd_file")
	except UnknownKeyError:
		return

	if not os.path.exists(htpasswd_file.dirname()):
		return

	with open(htpasswd_file, "w+") as htpasswd:
		for username in user.list(FakeAdminUser()):
			u = user.User(username)
			htpasswd.write("%s:%s\n" % (username, u.get_password_hash()))

	os.chmod(htpasswd_file, 0o600)
Example #57
0
def export_htpasswd(*args, **kwargs):
    try:
        htpasswd_file = options.env_path("htpasswd_file")
    except UnknownKeyError:
        return

    if not os.path.exists(htpasswd_file.dirname()):
        return

    with open(htpasswd_file, "w+") as htpasswd:
        for username in user.list(FakeAdminUser()):
            u = user.User(username)
            htpasswd.write("%s:%s\n" % (username, u.get_password_hash()))

    os.chmod(htpasswd_file, 0o600)
Example #58
0
	def __init__(self, name):
		self.name = name
		if not self.name.endswith(".mock"):
			self.name += ".mock"

		reposdir = options.env_path('mock_dir', default='mock')
		self.dir = reposdir + self.name
		self.url = str(reposdir + self.name)

		if not os.path.exists(str(self.dir)):
			raise DoesNotExistError(str(self.dir))

		self.initialized = False
		self.dirs = self.branches()
		self.initialized = True
Example #59
0
    def __init__(self, name):
        self.name = name
        if not self.name.endswith(".mock"):
            self.name += ".mock"

        reposdir = options.env_path('mock_dir', default='mock')
        self.dir = reposdir + self.name
        self.url = str(reposdir + self.name)

        if not os.path.exists(str(self.dir)):
            raise DoesNotExistError(str(self.dir))

        self.initialized = False
        self.dirs = self.branches()
        self.initialized = True
Example #60
0
	def enableCommitEmails(self, enable):
		"""Add or remove our script to/from the post-commit hook"""
		import os

		bindir = options.static_path('hooks') + 'svn'
		fullpath = str(bindir + 'mailer.py')
		base_env = options.env_path()
		mailer_conf = str((base_env + 'conf') + 'mailer.py.conf')

		if not os.path.exists(mailer_conf):
			export_notifications() # create mailer_conf

		new_hook = '/usr/bin/python %s commit "$1" "$2" "%s"\n' % \
				(fullpath, mailer_conf)

		self.rewritePostCommitHook(self.svn_signature, new_hook, enable)