Linux SVNServer搭建,并支持https访问
1.Subversion安装过程
参考http://blog.csdn.net/zhaiqi618/article/details/5741060
安装包下载地址,SVN版本1.6.12:
http://the.earth.li/pub/subversion/summersoft.fay.ar.us/pub/subversion/latest/1.6.12/rhel5/x86_64/
neon-0.28.4-1.x86_64.rpm28-Mar-200918:57267K
sqlite-3.5.9-2.x86_64.rpm28-Mar-200918:51547K
subversion-1.6.12-1.rhel5.x86_64.rpm19-Jun-201019:583.6M
mod_dav_svn-1.6.12-1.rhel5.x86_64.rpm19-Jun-201019:58261K
前两个是依赖包,第三个是主安装包,第四个是用于支持http访问的包(参考文章中还安装了dev包,本人实践中未安装,不影响使用)
安装过程如下:
首先检查SVN版本并卸载旧的版本
以root用户上传svn安装包到服务器并尝试安装。
[root@testbed1svn]#rpm-qa|grepsubversion
[root@testbed1bin]#rpm-esubversion-1.4.2-4.el5
error:"subversion-1.4.2-4.el5"specifiesmultiplepackages
[root@testbed1bin]#rpm-e--allmatchessubversion-1.4.2-4.el5
[root@testbed1svn]#rpm-ivhsubversion-1.6.12-1.rhel5.x86_64.rpm
error:Faileddependencies:
libneon.so.27()(64bit)isneededbysubversion-1.6.12-1.x86_64
neon>=0.26.1isneededbysubversion-1.6.12-1.x86_64
sqlite>=3.4isneededbysubversion-1.6.12-1.x86_64
此时直接安装subversion提示包依赖未满足,于是要升级neon及sqlite
先升级sqlite,请注意,rpm管理本身对sqlite有依赖,所以不能卸载sqlite,如果卸载,会出现rpm命令不可用的问题,最好直接升级至最新版本的sqlite。
[root@testbed1svn]#rpm-Uvhsqlite-3.5.9-2.x86_64.rpm
Preparing...###########################################[100%]
1:sqlite###########################################[100%]
[root@testbed1svn]#rpm-Uvhneon-0.28.4-1.x86_64.rpm
Preparing...###########################################[100%]
1:neon###########################################[100%]
[root@testbed1svn]#rpm-ivhsubversion-1.6.12-1.rhel5.x86_64.rpm
Preparing...###########################################[100%]
1:subversion###########################################[100%]
[root@testbed1svn]#rpm-Uvhmod_dav_svn-1.6.12-1.rhel5.x86_64.rpm
Preparing...###########################################[100%]
1:mod_dav_svn###########################################[100%]
最后安装验证
[root@testbed1~]#svnserve--version
svnserve,version1.6.12(r955767)
compiledJun192010,10:46:32
Copyright(C)2000-2009CollabNet.
Subversionisopensourcesoftware,seehttp://subversion.tigris.org/
ThisproductincludessoftwaredevelopedbyCollabNet(http://www.Collab.Net/).
Thefollowingrepositoryback-end(FS)modulesareavailable:
*fs_base:ModuleforworkingwithaBerkeleyDBrepository.
*fs_fs:Moduleforworkingwithaplainfile(FSFS)repository.
CyrusSASLauthenticationisavailable.
2.建立版本库,并实现svn://方式访问
本段参考:http://www.linuxde.net/2011/06/138.html
#mkdir/svndata创建svn数据目录(目录可自行制定)
#svnadmincreate/svndata/kumingkuming就是版本库的名字,可以改变!
配置svn配置文件(为了方便管理,这里多个库调用相同的配置文件。)
#每个版本库创建之后都会生成svnserve.conf主配文件
#vim/svndata/kuming/conf/svnserve.conf
[general]
anon-access=none
auth-access=write
password-db=/svndata/conf/passwd
authz-db=/svndata/conf/authz
realm=kuming
#mkdir/svndata/conf
#vim/svndata/conf/passwd//svn用户配置文件
[users]
user1=password1
user2=password2
user3=password3
user4=password4
#vim/svndata/conf/authz//svn权限控制配置文件
[groups] #设置组
group1=user1,user2 #多用户用逗号隔开
[/] #根目录权限设置(就是“kuming”这个文件夹)
user3=rw #用户1权限是:可读写
user4=r #用户2权限是:可读,不可写
user= #什么都没写代表没有任何权限
@group1=rw #设置组权限
[kuming:/123] #设置根目录下“123”文件夹的权限
#说明“123”这个文件件怎么创建?这是在SVN服务器配置好之后,创建一个权限很高的用户在客户端登录SVN
#然后创建一个文件夹“123”。
启动服务器
#svnserve-d-r/svndata
-d表示以daemon方式(后台运行)运行
-r/svndata指定根目录是/svndata
关闭SVN服务器
#killallsvnserve
#psaux|grepsvnserve查看服务,端口:3690
客户端使用的软件是TortoiseSVN,浏览方法:打开版本库浏览器输入:svn://ip-addr/kuming/文件夹名
至此已经基本实现一个SVNServer,但此时只能使用svn://协议访问,且对版本库中路径的访问授权策略很简单,很难满足实际需求。如想要给某用户只访问子目录/aaa/bbb/ccc的权限,必须给其访问父目录的权限,即必须至少给其根目录的读权限,但实际中我们不希望这样,因为我们不想让该用户访问其它目录,虽然可以通过复杂的策略达到目的,但不利于维护。比如随着时间发展,当增加新目录时,必须针对新目录写相应的授权策略。
好消息是,如果使用http协议访问SVN,则不会出现上面的情况。即给某用户访问某子目录的权限时不需要给其父目录的访问权限。下面介绍如何实现http访问SVN。
3.配置httpd,实现http访问
参考http://svnbook.red-bean.com/nightly/en/svn.serverconfig.httpd.html#svn.serverconfig.httpd.authn.digest
http://www.ibm.com/developerworks/cn/java/j-lo-apache-subversion/
接下来就是配置Apache的httpd.conf文件,让Apache在启动的时候加载dav模块。
需要添加的内容如下:
LoadModuledav_modulemodules/mod_dav.so
LoadModuledav_svn_modulemodules/mod_dav_svn.so
<Location/kuming>
DAVsvn
SVNPath/svndata/kuming
</Location>
首先需要启用dav_module,然后加载dav_svn_module。Location标签指出访问的URL以及在服务器上的实际位置。配置完毕后重新启动Apache(servicehttpdrestart),打开浏览器,输入http://服务器IP/kuming即可访问SVN服务器。
如果想要指定多个版本库,可以用多个Location标签,也可以使用SVNParentPath代替SVNPath,例如在/svndata下有多个版本库repos1,repos2等等,用如下方式指定:
<Location/svn>
DAVsvn
SVNParentPath/svndata
</Location>
"SVNParentPath/svndata"表示/etc/svn下的每个子目录都是一个版本库。可以通过http://服务器IP/svn/repos1,http://服务器IP/svn/repos2来访问。
此时任何人都可以访问版本库(http://方式不使用svn://方式的用户认证机制,且不需要启动svnserve),并且有完全的写操作权限。也就是说任何人都可以匿名读取,修改,提交,以及删除版本库中的内容。下面介绍如何进行认证,参考:http://svnbook.red-bean.com/nightly/en/svn.serverconfig.httpd.html#svn.serverconfig.httpd.authn.digest
上面的官网中提到两种认证方式,Basicauthentication和Digestauthentication。此处直接介绍第二种方式,
<Location/svn>
DAVsvn
SVNParentPath/svndata
#Authentication:Digest
AuthName"Subversionrepository"
AuthTypeDigest
AuthDigestProviderfile
AuthUserFile/etc/svn-auth.htdigest
#Authorization:Authenticatedusersonly
Requirevalid-user
</Location>
Thepasswordfilecanbecreatedasfollows:(以下命令中"Subversionrepository"就是上面的AuthName)
$###Firsttime:use-ctocreatethefile
$htdigest-c/etc/svn-auth.htdigest"Subversionrepository"harry
AddingpasswordforharryinrealmSubversionrepository.
Newpassword:*****
Re-typenewpassword:*****
$htdigest/etc/svn-auth.htdigest"Subversionrepository"sally
AddingusersallyinrealmSubversionrepository
Newpassword:*******
Re-typenewpassword:*******
$
重启apache服务即可实现以http方式访问SVN时进行认证。此时仅实现了对用户的认证,还未实现对目录的授权。
4.配置路径访问策略
可以使用Apache的mod_authz_svn模块对每个目录进行认证操作。修改httpd.conf文件,添加
LoadModuleauthz_svn_modulemodules/mod_authz_svn.so
现在可以在Location标签中使用authz的功能了。一个基本的authz配置如下:
<Location/svn>
DAVsvn
SVNParentPath/svndata
#Authentication:Digest
AuthName"Subversionrepository"
AuthTypeDigest
AuthDigestProviderfile
AuthUserFile/etc/svn-auth.htdigest
AuthzSVNAccessFile/svndata/conf/authz
#Authorization:Authenticatedusersonly
Requirevalid-user
</Location>
AuthzSVNAccessFile指向的是authz的策略文件,详细的权限控制可以在这个策略文件中指定。
此时已经实现认证及授权功能,当策略文件中有以下策略时
[/branches/dev/subfolder]
user0=rw
用户user0只能访问subfolder目录及其子目录,这样基本满足开发需要,但还不完美,且还未实现如文章标题所写的https方式访问。
5.用SSL实现安全的网络传输
参考:http://www.ibm.com/developerworks/cn/java/j-lo-apache-subversion/
SSL的证书和密钥
首先,我们需要找到openssl程序及其配置文件openssl.cnf,运行如下命令来生成128位的RSA私有密钥文件
my-server.key:(以下openssl命令建议使用绝对路径/usr/bin/openssl,因为有此软件包也包含openssl命令)
opensslgenrsa-des3-outmy-server.key1024
Loading'screen'intorandomstate-done
GeneratingRSAprivatekey,1024bitlongmodulus
.....++++++
........++++++
eis65537(0x10001)
Enterpassphraseforserver.key:********
Verifying-Enterpassphraseforserver.key:********
命令运行期间需要用户输入并确认自己的密码。
现在,我们需要SSL的认证证书,证书是由CA(certificateauthority)发放并且认证的。一般情况下,如果Subversion的用户不是太多,安全情况不是很复杂,我们也可以生成一个自签名的认证证书,从而省去了向CA申请认证的麻烦。如下命令:
(以下openssl可使用绝对路径/usr/bin/openssl,openssl.cnf文件也可使用绝对路径/etc/ssl/openssl.cnf或/usr/lib/ssl/openssl.cnf,根据实际情况选择)
opensslreq-new-keymy-server.key-x509-outmy-server.crt-configopenssl.cnf
CountryName(2lettercode)[GB]:
StateorProvinceName(fullname)[Berkshire]:
LocalityName(eg,city)[Newbury]:
OrganizationName(eg,company)[MyCompanyLtd]:
OrganizationalUnitName(eg,section)[]:
CommonName(eg,yournameoryourserver'shostname)[]:此处输入主机名
EmailAddress[]:
以上两个命令都需要用户输入那个key文件的密码,以及一些网络设置信息,如域名,邮箱等等,这里输入的服务器域名应该与Apache配置文件当中的一致。现在,我们可以在Apache的conf目录下新建一个ssl目录,将my-server.key和my-server.crt文件都移动到ssl目录里面。然后修改ssl.conf文件,将SSLCertificateKeyFile和SSLCertificateFile项指向这两个文件。(原文如此,实际中不需要)
如果Apache的module目录里面没有mod_ssl.so文件,可以将事先准备好的文件拷贝过去。然后,我们可以设置Apache的配置文件httpd.conf,将ssl模块加入其中:
LoadModulessl_modulemodules/mod_ssl.so
然后,在配置文件httpd.conf的最后,加上如下SSL相关配置项:
SSLMutexdefault
SSLRandomSeedstartupbuiltin
SSLSessionCachenone
ErrorLoglogs/SSL.log
LogLevelinfo
<VirtualHostip地址:443>
SSLEngineOn
SSLCertificateFileconf/ssl/my-server.crt
SSLCertificateKeyFileconf/ssl/my-server.key
</VirtualHost>
这样,基本的设置工作就完成了。重新启动Apache服务器,现在可以用https协议代替http协议来访问版本库了。如果要限定版本库只能用https访问,我们可以在Apache配置文件当中Subversion部分加上“SSLRequireSSL”。如下:
<Location/svn>
DAVsvn
SVNParentPath/svndata
#Authentication:Digest
AuthName"Subversionrepository"
AuthTypeDigest
AuthDigestProviderfile
AuthUserFile/etc/svn-auth.htdigest
AuthzSVNAccessFile/svndata/conf/authz
SSLRequireSSL
#Authorization:Authenticatedusersonly
Requirevalid-user
</Location>
此时目录授权可以实现如下要求,当策略文件中有以下策略时
[/branches/dev/subfolder]
user0=rw
用户user0只能访问subfolder目录及其子目录,不能访问父目录且看不到父目录其它子目录。
6.系统权限问题
目前为止还没完,因为linux文件系统权限问题,在提交代码时有可能遇到类似如下错误:
Can'topenfile'/xx/xxx/db/txn-current-lock':Permissiondenied
这可能是因为SVN库文件是使用root用户创建的,apache应用无写权限请尝试执行chmod-Ro+w/xx/xxx命令(其中/xx/xxx是SVN仓库文件地址),立即生效。如果问题还未解决,请google其它解决方案。
7.证书与主机名不匹配问题
如果查看/var/log/httpd/ssl_error_log文件,发现如下错误日志
RSAservercertificateCommonName(CN)`localhost.localdomain'doesNOTmatchservername!?
可能是因为mod_ssl模块默认加载了/etc/pki/tls/certs/localhost.crt证书,解决方法是修改conf.d/ssl.conf配置文件,将其中virtualhost部分配置删除,重启httpd服务即可。
参考:http://stackoverflow.com/questions/19153353/see-server-name-according-to-ssl-certificates
8.启动时免输密码
当配置使用ssl方式启动httpd服务后,每次启动都需要输入密码,这样就不能使服务开机自启动。
一种解决方法是生成免密码的key文件,方法如下:
/path/to/opensslrsa-in/path/to/originalkeywithpass.key-out/path/to/newkeywithnopass.key
使用新的key文件就无需输入密码启动了。
参考:https://wiki.apache.org/httpd/RemoveSSLCertPassPhrase
参考文章中还有另一种解决方式,基本原理是在服务启动要求密码时以脚本方式自动响应一个密码,从而实现无需手动输入密码的目的。