diff options
author | Stevan Radaković <stevan.radakovic@linaro.org> | 2013-03-20 12:15:13 +0100 |
---|---|---|
committer | Stevan Radaković <stevan.radakovic@linaro.org> | 2013-03-20 12:15:13 +0100 |
commit | ba7c038a979cda38ed0497b2c7950e8023793e89 (patch) | |
tree | 465d2798f7f70dbe4979bbd805bc989943356ebf | |
parent | 078981901a4c8c74505bb1a6b52b35bacff8b03f (diff) |
System sync added.
-rw-r--r-- | INSTALL | 7 | ||||
-rw-r--r-- | scripts/ldap_sync.py | 135 |
2 files changed, 132 insertions, 10 deletions
@@ -47,6 +47,7 @@ Dependencies * build-essential * git * mercurial (v2.4.1, not in Ubuntu repositories, need to install via pip) + * members * pgadmin3 * postgresql-9.1 * postgresql-server-dev-9.1 @@ -401,8 +402,10 @@ Upgrading the Rhodecode instance The rhodecode-setup script also supports update of the Rhodecode to the specific tag or branch, while doing the reinstallation of the Rhodecode -automatically. Downgrade of the database is not supported by the Rhodecode -tools, so bare this in mind when updating to an older version/tag/branch. +automatically. + +IMPORTANT: Database downgrade is not supported by the Rhodecode tools, +so bare this in mind when updating to an older version/tag/branch. To update the system to a specific tag/branch run the following command from the rhodecode-config base directory: diff --git a/scripts/ldap_sync.py b/scripts/ldap_sync.py index e592211..09a2d6a 100644 --- a/scripts/ldap_sync.py +++ b/scripts/ldap_sync.py @@ -11,19 +11,21 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +import json import ldap import logging import logging.config +import os +import subprocess import urllib2 import uuid -import json from ConfigParser import ConfigParser config = ConfigParser() -config.read('sync.conf') +config.read('sync.conf.tmp') -logging.config.fileConfig('sync.conf') +logging.config.fileConfig('sync.conf.tmp') logger = logging.getLogger() @@ -43,6 +45,60 @@ class UserNotInGroupError(Exception): ''' User is not a member of the target group. ''' +class SystemCommand(): + + @classmethod + def execute(cls, cmd_args, with_sudo=True): + """Runs the command passed.""" + if not isinstance(cmd_args, list): + cmd_args = list(cmd_args) + if with_sudo: + cmd_args.insert(0, "sudo") + + with open(os.devnull, 'w') as tempf: + process = subprocess.Popen(cmd_args, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, shell=True, + env=os.environ) + (stdout, stderr) = process.communicate() + + if process.returncode != 0: + logger.warn("Error executing command: '%s'. Reason: %s." % + (" ".join(cmd_args), stderr)) + else: + logger.debug("Sucess executing command %s. Output: %s" % (cmd_args, + stdout)) + + return stdout + + @classmethod + def add_group(cls, groupname): + cmd_args = ["groupadd", groupname] + cls.execute(cmd_args) + + @classmethod + def add_user(cls, username): + cmd_args = ["adduser", "--disabled-password", + "--quiet", "--gecos", "''", username] + cls.execute(cmd_args) + + @classmethod + def add_user_to_group(cls, groupname, username): + cmd_args = ["gpasswd", "-a", username, groupname] + cls.execute(cmd_args) + + @classmethod + def remove_user_from_group(cls, groupname, username): + cmd_args = ["gpasswd", "-d", username, groupname] + cls.execute(cmd_args) + + @classmethod + def get_group_members(cls, groupname): + cmd_args = ["members --all %s" % groupname] + output = cls.execute(cmd_args, with_sudo=False) + users = output.split() + return users + + class RhodecodeAPI(): def __init__(self, url, key): @@ -155,6 +211,20 @@ class LdapClient(): return groups + def get_users(self): + """Get all the users in form of dict {username: ssh_key,...}.""" + searchFilter = "(uid=*)" + result = self.client.search_s(self.base_dn, ldap.SCOPE_SUBTREE, + searchFilter) + + users = {} + for user in result: + # Ignore users who don't have the SSH key. + if 'sshPublicKey' in user[1]: + users[user[1]['uid'][0]] = user[1]['sshPublicKey'][0] + + return users + def get_group_users(self, groups, group): """Returns all the users belonging to a single group. @@ -191,11 +261,27 @@ class LdapSync(): self.rhodecode_api = RhodecodeAPI(config.get("ldap_config", "api_url"), config.get("ldap_config", "api_key")) + def get_ldap_groups(self): + """Fetch the LDAP groups if they are not already present.""" + try: + return self.ldap_groups + except: + self.ldap_groups = self.ldap_client.get_groups() + return self.ldap_groups + + def get_ldap_users(self): + """Fetch the LDAP users if they are not already present.""" + try: + return self.ldap_users + except: + self.ldap_users = self.ldap_client.get_users() + return self.ldap_users + def update_groups_from_ldap(self): """Add all the groups from LDAP to Rhodecode.""" logger.info("Start importing groups to Rhodecode.") added = existing = 0 - groups = self.ldap_client.get_groups() + groups = self.get_ldap_groups() for group in groups: try: self.rhodecode_api.create_group(group) @@ -209,9 +295,9 @@ class LdapSync(): "Added: %s, Existing: %s." % (added, existing)) def update_memberships_from_ldap(self, group): - """Update memberships in rhodecode based on the LDAP groups.""" - groups = self.ldap_client.get_groups() - group_users = self.ldap_client.get_group_users(groups, group) + """Update rhodecode memberships based on the LDAP groups.""" + group_users = self.ldap_client.get_group_users(self.get_ldap_groups(), + group) # Delete memberships first from each group which are not part # of the group any more. @@ -246,12 +332,45 @@ class LdapSync(): "added to the group %s. Reason: %s" % (member, group, e)) + def update_system_groups(self): + """Add all LDAP groups to system.""" + for group in self.get_ldap_groups(): + SystemCommand.add_group(group) + + def update_system_memberships(self): + """Update system memberships based on the LDAP groups.""" + group_users = self.ldap_client.get_group_users(self.get_ldap_groups(), + group) + + # Delete memberships first from each group which are not part + # of the group any more. + logger.debug("Remove memberships for users not in LDAP group.") + + system_members = SystemCommand.get_group_members(group) + + for system_member in system_members: + if system_member not in group_users: + SystemCommand.remove_user_from_group(group, system_member) + + # Add memberships. + for member in group_users: + SystemCommand.add_user_to_group(group, member) + + def update_system(self): + """Update system groups and memberships.""" + sync.update_system_groups() + sync.update_system_memberships() + + if __name__ == '__main__': sync = LdapSync() sync.update_groups_from_ldap() - groups = sync.ldap_client.get_groups() + groups = sync.get_ldap_groups() for group in groups: sync.update_memberships_from_ldap(group) + + # Update system group, users and memberships + sync.update_system() |