Instalando o Subversion integrado com o Trac Autenticando em htaccess ou em AD

No mundo dos softwares open-source, o Concurrent Versions System (CVS) foi a ferramenta escolhida para controle de versão por muitos anos. E com razão. O próprio CVS é um software open-source também, e seu modus operandi não-restritivo e o suporte a operações de rede permitiram que diversos programadores distribuídos geograficamente compartilhassem seus trabalhos. Ele atende à natureza colaborativa do mundo open-source como um todo. O CVS e seu modelo de desenvolvimento semi- caótico se tornou um marco da cultura open-source.

Mas o CVS também tinha seus defeitos, e simplesmente corrigir estes defeitos prometia ser um enorme esforço. Chega o Subversion. Desenvolvido para ser um sucessor do CVS, os criadores do Subversion pretendiam ganhar a simpatia dos usuários CVS de duas maneiras—criando um sistema open-source com o projeto (e a “aparência”) semelhante ao do CVS, e tentando evitar muitos de seus conhecidos defeitos. Por mais que o resultado não seja necessariamente a próxima grande evolução no projeto de controle de versão, o Subversion é muito poderoso, muito usável, e muito flexível. E agora muitos projetos open-source, quase todos recém-iniciados, preferem agora o Subversion ao CVS.

Trac é uma simples ferramenta, open source e de interface web para controle de mudanças em projetos de desenvolvimento de software. O objetivo do software é ajudar o desenvolvedor a rastrear essas mudanças, entender o porque de cada uma e qual o seu impacto no projeto como um todo.

O software foi desenvolvido na linguagem de programação Python e está disponível sob uma licença GPL desde meados de 2005. Desde a versão 0.9, é disponibilizado sob uma licença BSD modificada.

Entre os diversos usuários do software temos o Laboratório de Propulsão a Jato da NASA, que usa a ferramenta para controle de vários projetos. Uma lista mais completa de usuários do Trac pode ser obtida no seu próprio site.

Prepare o seu sistema com o seguinte script http://wiki.douglasqsantos.com.br/doku.php/confinicialsqueeze_en para que não falte nenhum pacote ou configuração.

Vamos atualizar primeiramente os repositórios

aptitude update && aptitude dist-upgrade -y

Vamos instalar alguns pacotes necessários

aptitude install python-setuptools trac subversion libapache2-svn libapache2-mod-python -y

Agora vamos carregar os módulos necessários para o apache

a2enmod authz_svn
a2enmod dav_fs
a2enmod ssl
a2enmod dav
a2enmod dav_svn
a2enmod ldap
a2enmod authnz_ldap

Agora vamos criar um template para os projetos do svn

mkdir -p /var/svn/tmpproject/{branches,tags,trunk}

Vamos montar o virtual host com autenticação em htacces, porém se quiser utilizar a autenticação via AD faço o Virtual host mais a frente

vim /etc/apache2/sites-available/svn
<VirtualHost *:80>
  ServerName svn.douglasqsantos.com.br
  Redirect / https://svn.douglasqsantos.com.br/
</VirtualHost>

<VirtualHost *:443>
 ServerAdmin admin@douglasqsantos.com.br
 ServerName svn.douglasqsantos.com.br

 <Location />
    DAV svn
    SVNParentPath /var/svn
    AuthType Basic
    AuthName "Servidor Subversion"
    AuthUserFile /var/svn/passwd
    SVNListParentPath on
    AuthzSVNAccessFile /var/svn/authz
    Require valid-user
    SSLRequireSSL
</Location>

 ErrorLog ${APACHE_LOG_DIR}/svn_error.log
 LogLevel warn
 CustomLog ${APACHE_LOG_DIR}/svn_access.log combined
 ServerSignature Off
 SSLEngine On
 SSLCertificateFile /etc/apache2/ssl/apache.pem
 SSLCertificateKeyFile /etc/apache2/ssl/apache.key
</VirtualHost>

Agora vamos criar a base de dados dos usuários e senhas

htpasswd -cm /var/svn/passwd douglas
New password: #senha
Re-type new password: #senha
Adding password for user douglas

Opcional Agora vamos montar o Virtual Host autenticando no AD

Temos que fazer um acerto no arquivo do cliente ldap

vim /etc/ldap/ldap.conf
#No final do arquivo
REFERRALS off

Virtual host autenticando no AD

vim /etc/apache2/sites-available/svn
<VirtualHost *:80>
  ServerName svn.douglasqsantos.com.br
  Redirect / https://svn.douglasqsantos.com.br/
</VirtualHost>

<VirtualHost *:443>
 ServerAdmin admin@douglasqsantos.com.br
 ServerName svn.douglasqsantos.com.br

 <Location />
    # Habilita o repositorio
    DAV svn
    # caminho para o repositorio
    SVNParentPath "/var/svn"
    # Permitir a listagem dos projetos na raiz
    SVNListParentPath on
    #Arquivo de controle dos repositorios
    AuthzSVNAccessFile /var/svn/authz
    # identificação repositorio
    AuthName "Servidor Subversion"
    #Provedor de Autenticação
    AuthBasicProvider ldap
    #Tipo de autenticação
    AuthType Basic
    # Esta on porque se a autenticacao via ldap falhar, nao deve pesquisar outras bases
    AuthzLDAPAuthoritative off
    # URL da base LDAP. O ?sAMAccountName especifica o atributo a pesquisar (sAMAccountName)
    AuthLDAPURL "ldap://10.0.0.22:389/DC=douglasqsantos,DC=com,DC=br?sAMAccountName?sub?(objectClass=user)" NONE
    # Informa que atributo usar para verificar se o usuario faz parte do grupo ou nao
    AuthLDAPGroupAttribute memberOf
    # especifica que a busca deve ser feita por usuario, e nao pelo DN
    AuthLDAPGroupAttributeIsDN off
    # Usuário que vai fazer a pesquisa no AD
    AuthLDAPBindDN "CN=apache,CN=Builtin,DC=douglasqsantos,DC=com,DC=br"
    # Senha do usuário que vai efetuar a pesquisa no AD
    AuthLDAPBindPassword "Apa134*"
    # Usar o nome do usuário quando for verificar se o usuário pertence ao grupo
    AuthLDAPGroupAttributeIsDN on
    # Atributos do AD para verificar se o usuário pertence ao grupo
    AuthLDAPGroupAttribute member
    # Restrições de Acesso
    require valid-user
    # Força o uso do SSL
    SSLRequireSSL
  </Location>

 ErrorLog ${APACHE_LOG_DIR}/svn_error.log
 LogLevel warn
 CustomLog ${APACHE_LOG_DIR}/svn_access.log combined
 ServerSignature Off
 SSLEngine On
 SSLCertificateFile /etc/apache2/ssl/apache.pem
 SSLCertificateKeyFile /etc/apache2/ssl/apache.key
</VirtualHost>

Agora algumas considerações sobre a autenticação no AD

  1. O Ad do Windows Server 2008 não deixa efetuar consulta anômina na base por isso temos que utilizar um usuário para efetuar a consulta.
  2. O usuário foi criado na pasta Builtin da instalação padrão do AD
  3. O nome do usuário usado no exemplo é apache
  4. A senha do usuário apache usada no exemplo é Apa134*
  5. Caso tenha criado o usuário em outro lugar na estrutura do ad tem que passa o caminho completo ou utilizar como abaixo
  6. trocar AuthLDAPBindDN “CN=apache,CN=Builtin,DC=douglasqsantos,DC=com,DC=br” por AuthLDAPBindDN “apache@douglasqsantos.com.br”
  7. Não esqueça de trocar os valores de acordo com a necessidade

Agora vamos acertar as chaves para o apache trabalhar com https

Agora vamos criar o diretório para armazenar as chaves

mkdir /etc/apache2/ssl
cd /etc/apache2/ssl

Agora vamos gerar as chaves

openssl req -new -x509 -days 365 -nodes -out apache.pem -keyout apache.key
Generating a 1024 bit RSA private key
..............++++++
...........................................++++++
writing new private key to 'apache.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:BR
State or Province Name (full name) [Some-State]:Parana
Locality Name (eg, city) []:Curitiba
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Douglas
Organizational Unit Name (eg, section) []:Douglas
Common Name (eg, YOUR name) []:apache.douglasqsantos.com.br
Email Address []:douglas@douglasqsantos.com.br

Agora vamos subir o virtual host do svn e vamos baixar os virtuais hosts default

a2ensite svn
a2dissite default
a2dissite default-ssl

Vamos criar o nosso projeto

svnadmin create /var/svn/myproject --fs-type fsfs

Agora vamos importar o nosso template

svn import /var/svn/tmpproject file:///var/svn/myproject -m "initial import"

Agora vamos acertar as permissões do projeto

find /var/svn/myproject -type f -exec chmod 660 {} \;
find /var/svn/myproject -type d -exec chmod 2770 {} \;
chown -R root.www-data /var/svn/myproject

Agora vamos acertar as permissões de controle de acesso aos repositórios

vim /var/svn/authz
[myproject:/]
douglas = rw

Agora vamos reiniciar o nosso apache e testar o svn

/etc/init.d/apache2 restart

Caso não tenha um dns para resolver o virtual host podemos acertar o /etc/hosts do cliente da seguinte forma

vim /etc/hosts
ip_servidor      svn.douglasqsantos.com.br   svn
ip_servidor      www.douglasqsantos.com.br  trac

Agora para testar acesse https://svn.douglasqsantos.com.br/myproject, aqui informe ou o usuário que foi criado com o htpasswd ou o usuário do AD

Agora vamos fazer um teste de checkout do repositório

svn co https://svn.douglasqsantos.com.br/myproject
Erro validando o certificado de servidor para 'https://svn.douglasqsantos.com.br:443':
 - O certificado não foi emitido por uma autoridade confiável. Use sua
   impressão digital para validar o certificado manualmente
 - O nome do servidor do certificado não bate.
Informações do certificado:
 - Nome do servidor: apache.douglasqsantos.com.br
 - Validade: de Mon, 17 Oct 2011 19:28:24 GMT até Tue, 16 Oct 2012 19:28:24 GMT
 - Emissor: Douglas, Douglas, Curitiba, Parana, BR
 - Impressão digital: 58:17:34:0c:8c:ca:d6:c8:0c:65:72:23:97:e1:a0:3c:1c:01:aa:8f
(R)ejeitar, aceitar (t)emporariamente ou aceitar (p)permanente? p
Área de autenticação: <https://svn.douglasqsantos.com.br:443> Servidor Subversion
Senha para 'root': 
Área de autenticação: <https://svn.douglasqsantos.com.br:443> Servidor Subversion
Usuário: douglas
Senha para 'douglas': 

-----------------------------------------------------------------------
ATENÇÃO Sua senha para autenticação no domínio:

   <https://svn.douglasqsantos.com.br:443> Servidor Subversion

só pode ser armazenada em disco criptografado Recomenda-se configurar
seu sistema de modo que o Subversion possa armazenar senhas criptografadas, se
possível. Veja a documentação para maiores detalhes.
Você pode evitar futuras aparições deste aviso, definindo o valor
da opção 'store-plaintext-passwords' para 'sim' ou 'não' em '/root/.subversion/servers'.
-----------------------------------------------------------------------
Armazenar senha descriptografada (sim/não)? não
A    myproject/trunk
A    myproject/branches
A    myproject/tags
Gerado cópia de trabalho para revisão 1.

Como pode ser notado o nosso svn está ok, agora vamos a implementação do trac

Temos que fazer um acerto no apache

vim /etc/apache2/ports.conf
[...]
NameVirtualHost *:443

Vamos criar o virtual host com a autenticação simples porém só vai funcionar se você gerou a autenticação simples para o svn

vim /etc/apache2/sites-available/trac
<VirtualHost *:80>
  ServerName www.douglasqsantos.com.br
  Redirect / https://www.douglasqsantos.com.br/
</VirtualHost>

<VirtualHost *:443>
 ServerAdmin admin@douglasqsantos.com.br
 ServerName www.douglasqsantos.com.br

<Location "/trac">
    SetHandler mod_python
    PythonHandler trac.web.modpython_frontend
    PythonOption TracEnvParentDir /var/trac/
    PythonOption TracUriRoot /trac
    AuthType Basic
    AuthName "Trac"
    AuthUserFile /var/svn/passwd
    Require valid-user
    # Faz negociação no uso do SSL
    SSLOptions +OptRenegotiate
</Location>

 ErrorLog ${APACHE_LOG_DIR}/trac_error.log
 LogLevel warn
 CustomLog ${APACHE_LOG_DIR}/trac_access.log combined
 ServerSignature Off
 SSLEngine On
 SSLSessionCacheTimeout 600
 SSLCertificateFile /etc/apache2/ssl/apache.pem
 SSLCertificateKeyFile /etc/apache2/ssl/apache.key
</VirtualHost>

Se preferir a autenticação do trac no AD faça o seu virtual host da seguinte forma

vim /etc/apache2/sites-available/trac
<VirtualHost *:80>
  ServerName www.douglasqsantos.com.br
  Redirect / https://www.douglasqsantos.com.br/trac
</VirtualHost>

<VirtualHost *:443>
 ServerAdmin admin@douglasqsantos.com.br
 ServerName www.douglasqsantos.com.br

<Location "/">
    SetHandler mod_python
    PythonHandler trac.web.modpython_frontend
    PythonOption TracEnvParentDir /var/trac/
    PythonOption TracUriRoot /trac
</Location>

#utilizando uma er para quando tiver um campo de login utilizar o login via AD
<LocationMatch "/[^/]+/login">
   # identificação repositorio
    AuthName "Servidor Trac"
    #Provedor de Autenticação
    AuthBasicProvider ldap
    #Tipo de autenticação
    AuthType Basic
    # Esta on porque se a autenticacao via ldap falhar, nao deve pesquisar outras bases
    AuthzLDAPAuthoritative off
    # URL da base LDAP. O ?sAMAccountName especifica o atributo a pesquisar (sAMAccountName)
    AuthLDAPURL "ldap://10.0.0.22:389/DC=douglasqsantos,DC=com,DC=br?sAMAccountName?sub?(objectClass=user)" NONE
    # Informa que atributo usar para verificar se o usuario faz parte do grupo ou nao
    AuthLDAPGroupAttribute memberOf
    # especifica que a busca deve ser feita por usuario, e nao pelo DN
    AuthLDAPGroupAttributeIsDN off
    # Usuário que vai fazer a pesquisa no AD
    AuthLDAPBindDN "CN=apache,CN=Builtin,DC=douglasqsantos,DC=com,DC=br"
    # Senha do usuário que vai efetuar a pesquisa no AD
    AuthLDAPBindPassword "Apa134*"
    # Usar o nome do usuário quando for verificar se o usuário pertence ao grupo
    AuthLDAPGroupAttributeIsDN on
    # Atributos do AD para verificar se o usuário pertence ao grupo
    AuthLDAPGroupAttribute member
    # Restrições de Acesso
    require valid-user
    # Faz negociação no uso do SSL
    SSLOptions +OptRenegotiate
    </LocationMatch>
 ErrorLog ${APACHE_LOG_DIR}/trac_error.log
 LogLevel warn
 CustomLog ${APACHE_LOG_DIR}/trac_access.log combined
 ServerSignature Off
 SSLEngine On
 SSLSessionCacheTimeout 600
 SSLCertificateFile /etc/apache2/ssl/apache.pem
 SSLCertificateKeyFile /etc/apache2/ssl/apache.key
</VirtualHost>                                

Agora vamos criar o diretório para os projetos do trac

mkdir /var/trac

Agora vamos criar o nosso projeto no trac

trac-admin /var/trac/myproject initenv
Creating a new Trac environment at /var/trac/myproject

Trac will first ask a few questions about your environment 
in order to initialize and prepare the project database.

 Please enter the name of your project.
 This name will be used in page titles and descriptions.

Project Name [My Project]> MyProject #Nome do projeto
 
 Please specify the connection string for the database to use.
 By default, a local SQLite database is created in the environment
 directory. It is also possible to use an already existing
 PostgreSQL database (check the Trac documentation for the exact
 connection string syntax).

Database connection string [sqlite:db/trac.db]>  #ENTER
 
 Please specify the type of version control system,
 By default, it will be svn.

 If you don't want to use Trac with version control integration,
 choose the default here and don't specify a repository directory.
 in the next question.

Repository type [svn]> #ENTER

 Please specify the absolute path to the version control
 repository, or leave it blank to use Trac without a repository.
 You can also set the repository location later.

Path to repository [/path/to/repos]> /var/svn/myproject #Caminho do projeto no svn
[...]
Project environment for 'MyProject' created.

You may now configure the environment by editing the file:

  /var/trac/myproject/conf/trac.ini

If you'd like to take this new project environment for a test drive,
try running the Trac standalone web server `tracd`:

  tracd --port 8000 /var/trac/myproject

Then point your browser to http://localhost:8000/myproject.
There you can also browse the documentation for your installed
version of Trac, including information on further setup (such as
deploying Trac to a real web server).

The latest documentation can also always be found on the project
website:

  http://trac.edgewall.org/

Congratulations

Agora vamos acertar as permissões do projeto no trac

find /var/trac/myproject -type f -exec chmod 660 {} \;
find /var/trac/myproject -type d -exec chmod 2770 {} \;
chown -R root.www-data /var/trac/myproject

Agora vamos habilitar o nosso virtual host do trac

a2ensite trac

Agora vamos reiniciar o nosso apache

/etc/init.d/apache2 restart

Agora vamos dar acesso de ADM no projeto para o usuário douglas

trac-admin /var/trac/myproject
Welcome to trac-admin 0.11.7
Interactive Trac administration console.
Copyright (c) 2003-2009 Edgewall Software

Type:  '?' or 'help' for help on commands.

Trac [/var/trac/myproject]> permission add douglas TRAC_ADMIN
Trac [/var/trac/myproject]> quit

Agora para testar o projeto acesse https://www.douglasqsantos.com.br/trac/myproject

Para listar todos os projetos acesse https://www.douglasqsantos.com.br/trac

Para listar as possíveis permissões para os projetos

trac-admin /var/trac/myproject
Trac [/var/trac/myproject]> permission list

User           Action         
------------------------------
anonymous      BROWSER_VIEW   
anonymous      CHANGESET_VIEW 
anonymous      FILE_VIEW      
anonymous      LOG_VIEW       
anonymous      MILESTONE_VIEW 
anonymous      REPORT_SQL_VIEW
anonymous      REPORT_VIEW    
anonymous      ROADMAP_VIEW   
anonymous      SEARCH_VIEW    
anonymous      TICKET_VIEW    
anonymous      TIMELINE_VIEW  
anonymous      WIKI_VIEW      
authenticated  TICKET_CREATE  
authenticated  TICKET_MODIFY  
authenticated  WIKI_CREATE    
authenticated  WIKI_MODIFY    
douglas        TRAC_ADMIN     


Available actions:
 BROWSER_VIEW, CHANGESET_VIEW, CONFIG_VIEW, EMAIL_VIEW, FILE_VIEW,
 LOG_VIEW, MILESTONE_ADMIN, MILESTONE_CREATE, MILESTONE_DELETE,
 MILESTONE_MODIFY, MILESTONE_VIEW, PERMISSION_ADMIN, PERMISSION_GRANT,
 PERMISSION_REVOKE, REPORT_ADMIN, REPORT_CREATE, REPORT_DELETE,
 REPORT_MODIFY, REPORT_SQL_VIEW, REPORT_VIEW, ROADMAP_ADMIN, ROADMAP_VIEW,
 SEARCH_VIEW, TICKET_ADMIN, TICKET_APPEND, TICKET_CHGPROP, TICKET_CREATE,
 TICKET_EDIT_CC, TICKET_EDIT_DESCRIPTION, TICKET_MODIFY, TICKET_VIEW,
 TIMELINE_VIEW, TRAC_ADMIN, WIKI_ADMIN, WIKI_CREATE, WIKI_DELETE,
 WIKI_MODIFY, WIKI_VIEW

Trac [/var/trac/myproject]> quit

Agora adicione as seguintes linhas no final do arquivo /var/trac/myproject/conf/trac.ini

vim /var/trac/myproject/conf/trac.ini
[...]
trac.versioncontrol.api.repositorymanager = enabled
tracopt.versioncontrol.svn.* = enabled
tracopt.ticket.commit_updater.* = enabled

Agora no track vá em Admin/repositories:

  • Em Add repository:
    • Name: nome do repositório: myproject
    • Type: svn
    • Directory: /var/svn/myproject
    • Agora selecione add

Agora na linha de comando vamos ter que mandar sincronizar o repositório:

ENV=/var/trac/myproject
trac-admin $ENV repository resync "*"
Resyncing repository history for myproject... 
1 revision cached.
Concluído.

Agora temos o svn aparecendo no painel do trac.

Agora vamos criar um script para atualizar o repositório no trac quando ele tiver um update

vim /var/svn/myproject/hooks/post-commit
#!/bin/sh

trac-admin /var/trac/myproject changeset added "$1" "$2"

Agora vamos dar permissão para o nosso script

chmod 755 /var/svn/myproject/hooks/post-commit

Agora a cada commit no svn o trac vai receber a atualização.

Commit do SVN com Referência a ticket do Trac

Agora vamos implementar a opção de ao ser efetuado o commit no svn podemos interagir com os tickets do trac.

Vamos criar uma a estrutura de diretório para armazenar o nosso script

mkdir -p /usr/share/trac/contrib

Agora vamos acessar o novo diretório e vamos obter o script

cd /usr/share/trac/contrib
wget -c http://wiki.confianceit.com.br/Downloads/scripts/trac-post-commit-hook

Agora em nosso projeto vamos ajustar o script de post-commit

vim /var/svn/myproject/hooks/post-commit
#!/bin/sh

REPOS="$1"
REV="$2"
LOG=`svnlook log -r $REV $REPOS`
AUTHOR=`svnlook author -r $REV $REPOS`
TRAC_ENV="/var/trac/myproject"

 /usr/bin/python /usr/share/trac/contrib/trac-post-commit-hook \
  -p "$TRAC_ENV" -r "$REV" -u "$AUTHOR" -m "$LOG"


trac-admin /var/trac/myproject changeset added "$1" "$2"

Agora vamos dar a permissão de execução para o script

chmod 755 /var/svn/myproject/hooks/post-commit

Agora podemos mandar fechar tickets ou interagir com eles como na seguinte documentação: http://trac.edgewall.org/wiki/TimeTracking#UsingaSubversioncommithookoptional

Para fechar o ticket 5 por exemplo podemos mandar o seguinte commit.

svn commit -m 'Fechando o ticket, closes #5' 

Referências