📜 ⬆️ ⬇️

Automation SVN + Apache + LDAP

According to the above mentioned bundle, a lot of things are written, however, I always felt some inconveniences when setting up a new repository: it was necessary to start a new location in the configuration file, create a repository using svnadmin, restart apache. When such work has to be done once a month is tolerable, however, when such work has to be done several times a week, you should think about automating this process. Actually it is about this and goes under the cut.


Looking ahead, I want to start with the configuration of apache itself.

Main configuration file /etc/httpd/conf/httpd.conf
...... # Load config files from the config directory "/etc/httpd/conf.d". # Include conf.d/*.conf ...... 

Actually everything is clear here (this is the default location of configs when installing apache from standard CentOS 5.6 repositories)
')
File /etc/httpd/conf.d/subversion.conf
 LoadModule dav_svn_module modules/mod_dav_svn.so LoadModule authz_svn_module modules/mod_authz_svn.so LoadModule authnz_ldap_module modules/mod_authnz_ldap.so <VirtualHost *:5553> ServerName svn.company.ru ServerAdmin svn_admin@company.ru DocumentRoot /opt/svn/repo LimitRequestBody 2147483647 CustomLog /var/log/httpd/subversion.log combined ErrorLog /var/log/httpd/subversion-error.log <IfModule rewrite_module> RewriteLogLevel 0 RewriteEngine On RewriteCond "%{REQUEST_METHOD}" !"^(GET|POST|HEAD)$" RewriteCond "%{REQUEST_FILENAME}" "^/([^/\.]+)$" RewriteCond "/opt/svn/repo/%1" -d RewriteRule "^/([^/\.]+)$" "/$1/" [passthrough] </IfModule> Include conf.d/subversion.d/*.conf </VirtualHost> 

This configuration file describes the repository configuration itself. It is worth noting that we put all the locales in the configuration files in the conf.d / subversion.d directory. Why is this necessary? First of all, it is easier for us to keep track of which repositories are included, and secondly, we get rid of parsing the config when the script is run (see below).
File /etc/httpd/conf.d/subversion.d/example_repo.conf
 <Location "/example_repo/"> DAV svn SVNPath /opt/svn/repo/example_repo SVNListParentPath on AuthType Basic AuthName "SVN Server" AuthBasicProvider ldap AuthzLDAPAuthoritative Off AuthLDAPBindDN "cn=ldpcat,cn=users,dc=company,dc=ru" AuthLDAPBindPassword "12345678" AuthLDAPURL ldap://ldap.company.ru:389/ou=user,dc=company,dc=ru?sAMAccountName?sub?(objectClass=*) AuthBasicAuthoritative off <Limit GET PROPFIND> Require valid-user </Limit> <Limit GET PROFIND PROPPATCH DELETE MERGE PUT POST MKCOL MKACTIVITY COPY MOVE LOCK UNLOCK> Require ldap-group cn=example_group,ou=user,dc=company,dc=ru </Limit> </Location> 

Here we specify the name and location of the repository, we specify with which account we will look at the AD directory (yes, in this case, AD is used), the password for this account, the string and the filter for the search. Further, using the directory, we indicate that viewing the repository is allowed to all users authorized in the domain (however, you can specify a specific group in the domain). Next, the next directory, we specify which group of users in the domain (in this case, this example_group) is allowed to perform all other actions with the repository.

With the apache configuration, everything is clear, now let's start implementing the script with which we will create new repositories. The script should
  1. Create an empty repository
  2. Create configuration file for repository
  3. Send to the members of the group entitled to make changes to the repository, an information letter


Let's get started


I used python version 2.7 installed from sources with the options --prefix = / opt / python2.7 --with-threads --enable-unicode = ucs4 --includedir = / usr / include --disable-ipv6. It will also be necessary to install the python-ldap module (I used setuptools). Below is the actual script itself.
 #!/usr/bin/env python2.7 # -*- coding: utf-8 -*- import os import ldap import ldap.sasl import sys import smtplib from email.mime.text import MIMEText server_init_file = '/etc/init.d/httpd' apache_config_dir = '/etc/httpd/conf.d/subversion.d/' repo_path = '/opt/svn/repo/' user_owner_repo = 'apache' group_owner_repo = 'apache' mail_server = 'mail.company.ru' mail_smtp_port = 25 mail_from = 'redmine@company.ru' list_mail = [ ] root_svn_url = 'http://svn.company.ru/' if len(sys.argv)<=2: print u"   " print u"           " print u": addsvnrepo example_repo example_group" sys.exit() server = 'ldap://ldap' user_id = 'ldpcat' pw = '12345678' dn_search = 'OU=User,DC=company,DC=ru' repo_name = sys.argv[1] group_commit = sys.argv[2] if repo_name != None: print "  "+repo_name else: sys.exit() def main(): try: con = ldap.initialize(server) con.set_option(ldap.OPT_REFERRALS, 0) con.simple_bind_s(user_id, pw) print ' ' except ldap.INVALID_CREDENTIALS: print "    " sys.exit() except ldap.LDAPError, e: if type(e.message) == dict and e.message.has_key('desc'): print 'Error - ' + e.message['desc'] else: print 'Error - ' + str(e) sys.exit() finally: print '' search(con, group_commit) repo_create() config_write() server_reload() mailer() def search(con, group_commit): try: base_dn = 'dc=company,dc=ru' filter = "(memberOf=CN="+group_commit+","+dn_search+")" attrs = ['mail'] timeout = 3 results = con.search_s(base_dn, ldap.SCOPE_SUBTREE, filter, attrs) for dn,entry in results: if dn != None: list_mail.extend(entry['mail']) con.unbind() print list_mail print u" " except ldap.LDAPError, e: print 'Error - ' + str(e) sys.exit() def mailer(): text = u' ' text2 = repo_name text3 = u' .\n    ' text4 = root_svn_url+repo_name text5 = u'/\n  !\n' text_s = text+text2+text3+text4+text5 subj = u'  '+repo_name msg = MIMEText(text_s, "", "cp1251") msg['Subject'] = subj msg['From'] = mail_from msg['To'] = ', '.join( list_mail ) print u"  " print msg['To'] s = smtplib.SMTP(mail_server, mail_smtp_port) s.sendmail(msg['From'], list_mail, msg.as_string()) s.quit() print u"...." def repo_create(): svnadmin_create_msg = result = os.popen("svnadmin create "+repo_path+repo_name).read() print svnadmin_create_msg chmod_msg = result = os.popen("chown -R "+user_owner_repo+":"+group_owner_repo+" "+repo_path+repo_name).read() print chmod_msg def config_write(): if os.path.exists(apache_config_dir+repo_name+".conf") : print u"   " sys.exit() else: print "  ......" f1 = open(apache_config_dir+repo_name+".conf", 'w') f = open(apache_config_dir+"skeleton.tpl", 'r') body_config = f.read() f.close() f1.write(body_config.format(repo_name, repo_path, group_commit, server, dn_search)) f1.close() def server_reload(): print u' apache.......' reload_msg = result = os.popen(server_init_file+" restart").read() print reload_msg if __name__=="__main__": main() 


Apparently from a script, I pushed each action on separate functions. I want to note that the configuration file for the repository is created from the skeleton.tpl template, which must be placed inside the /etc/httpd/conf.d/subversion.d directory. Template content
 <Location "/{0}/"> DAV svn SVNPath {1}{0} SVNListParentPath on AuthType Basic AuthName "SVN Server" AuthBasicProvider ldap AuthzLDAPAuthoritative Off AuthLDAPBindDN "cn=ldpcat,cn=users,dc=company,dc=ru" AuthLDAPBindPassword "12345678" AuthLDAPURL {3}/{4}?sAMAccountName?sub?(objectClass=*) AuthBasicAuthoritative off <Limit GET PROPFIND> Require valid-user </Limit> <Limit PROPPATCH DELETE MERGE PUT POST MKCOL MKACTIVITY COPY MOVE LOCK UNLOCK> Require ldap-group cn={2},{4} </Limit> </Location> 


Actually everything. However, users must provide a list of repositories through which they can get into any repository and download the file from there. This is done in the file /etc/httpd/conf.d/subversion.conf by adding the directive SVNListParentPath On. However, it is necessary for the menu page to look corporate. And I called python again. In the initialization script apache /etc/init.d/httpd, in the function start (), added the line
/opt/svn/repo/svn_gen > /opt/svn/repo/index.html

File / opt / svn / repo / svn_gen
 #!/usr/bin/env python2.7 import os sdir='/opt/svn/repo/' r, d, f = os.walk(sdir).next() lb=len(d) y=0 addrrepo='http://svn.company.ru/' print "<ul>" while y<lb: print "<li>" print "<a href='" print addrrepo+d[y] print "/" print "'" print ">" print d[y] print "</a>" print "<br \>" y=y+1 else: print "</ul>" print "<hr /" print '<h2>PopoWeb Server running on BolgenOS Server 1.6(fundamentally new system of Denis Popov)</ h2>' 

Here I specifically removed the links to css, so as not to give out the organization in which I work (the colors are painfully recognizable), but as you understand, you can implement the page to your liking. In this case, you can also use the template, but the svn_gen script was written before I was tired of adding repositories with handles.

What I would like to implement in the future

PS Link to the archive with scripts and heatplug addsvnrepo.tar
PSS The code is not perfect, so I’m glad to accept any comments.

Source: https://habr.com/ru/post/126338/


All Articles