JBOSS NTLM auth com apache e winbind
Recentemente comecei um projeto em um cliente novo em Brasília, este cliente tinha alguns ambientes legados que utilizam autenticação NTLM no JBOSS usando o APACHE + MOD_WINBIND + SAMBA + WINBIND + KERBEROS.
É uma configuração que eu não escolheria devido a sua complexidade, mas é o que o cliente tem, e é o que funciona para ele hoje, portanto, criei uma VM limpa e testei o conceito, aproveitando para documentar já que não existia documentação.
Eu particularmente utilizaria algo mais simples como APACHE + MOD_KERBEROS + KERBEROS, e espero poder cobrir isso em um post em breve assim que migrarmos esse modelo antigo de autenticação.
A VM em que testei roda o CentOS 6.5, 64 bits, criei a VM utilizando vagrant e virtualbox com uma box da puppetlabs.
O JBOSS utilizado para este teste é o 4.0.5.GA.
1. instalação
1.1 install::samba
instale o samba e suas dependências
yum install samba samba-client samba-winbind samba-winbind-krb5-locator
1.2 install::kerberos
instale o kerberos
yum install krb5-libs krb5-workstation
1.3 install::apache
instale o apache para utilizarmos como reverse proxy e camada de autenticação
yum install httpd httpd-devel
1.4. install::mod_ntlm
nao use o pacote da distribuição, ele por alguma razão não funcionou nos meus testes, tive que usar o módulo do git.samba.org mesmo.
fazendo download
voce pode fazer o download do módulo já compilado se desejar
cd /tmp
wget http://gutocarvalho.net/misc/jboss4/mod_auth_ntlm_winbind.so
acerte a permissão
chmod 755 mod_auth_ntlm_winbind.so
copie o binário para o destino
cp mod_auth_ntlm_winbind.so /usr/lib64/httpd/modules
compilando
caso não queria usar o binário, compile a partir do fonte, para isto acesse o diretório temporário
cd /tmp
crie um diretório chamado
mkdir ntlm
entre no diretório ntlm
cd ntlm
pegue o modulo no repositório svn
git clone git://git.samba.org/jerry/mod_auth_ntlm_winbind.git
compile o módulo
gcc mod_auth_ntlm_winbind.c
instale o módulo
apxs2 -DAPACHE2 -c -i mod_auth_ntlm_winbind.c
o arquivo do módulo será instalado em
/usr/lib64/httpd/modules/mod_auth_ntlm_winbind.so
1.5 install::java
instale o java, ele é dependência para o funcionamento do JBOSS
yum install java-1.6.0-openjdk
1.6 install::jboss
entre no diretório opt
cd /opt
faça download do jboss4
wget http://gutocarvalho.net/misc/jboss4/jboss-4.0.5.GA.zip
descompacte o jboss
tar zxvf jboss-4.0.5.GA.zip
crie o grupo jboss
groupadd jboss
crie o usuário jboss
useradd -s /bin/bash -g jboss jboss
ajuste a permissão
chown -R jboss.jboss /opt/jboss-4.0.5.GA
crie um link simbólico
ln -s /opt/jboss /opt/jboss-4.0.5.GA
2. configuração
2.1 config::samba
entre no diretório do samba
cd /etc/samba
edite o arquivo
vim /etc/samba/smb.conf
adicione o código abaixo
[global]
workgroup = XXXXX
realm = XXXXX.GOV.BR
preferred master = no
security = ADS
encrypt passwords = yes
winbind separator = \\
idmap uid = 10000-20000
idmap gid = 10000-20000
[homes]
valid users = %S
2.2 config::kerberos
entre no diretório /etc
cd /etc/
edite o arquivo krb5.conf
vim /etc/krb5.conf
adicione o conteúdo abaixo
[logging]
default = FILE:/var/log/krb5libs.log
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/kadmind.log
[libdefaults]
default_realm = XXX.GOV.BR
# dns_lookup_realm = true
# dns_lookup_kdc = false
[realms]
XXX.GOV.BR = {
kdc = yyy.xxx.gov.br
}
[domain_realms]
.xxx.gov.br = XXX.GOV.BR
2.3 config::apache
acesse o diretório /etc/httpd/conf.d/
cd /etc/httpd/conf.d/
edite o arquivo aplicacao.conf
vim /etc/httpd/conf.d/aplicacao.conf
adicione o conteúdo abaixo
LoadModule auth_ntlm_winbind_module modules/mod_auth_ntlm_winbind.so
ProxyPass /app ajp://10.10.2.106:8009/app
<Location /app>
AuthName "XXX"
NTLMAuth on
NTLMAuthHelper "/usr/bin/ntlm_auth --helper-protocol=squid-2.5-ntlmssp"
NTLMBasicAuthoritative on
AuthType NTLM
Require valid-user
NegotiateAuth on
NegotiateAuthHelper "/usr/bin/ntlm_auth --helper-protocol=gss-spnego"
AuthType Negotiate
</Location>
ErrorLog /var/log/httpd/jboss4-error.log
ServerSignature Off
</VirtualHost>
2.4 config::jboss
acesse o diretório do jbossweb
cd /opt/jboss/server/default/deploy/jbossweb-tomcat55.sar
edite o arquivo server.xml
vim server.xml
altere as configurações de AJP para que a autenticação NTLM funcione, mude de
<!-- A AJP 1.3 Connector on port 8009 -->
<Connector port="8009" address="${jboss.bind.address}"
emptySessionPath="true" enableLookups="false" redirectPort="8443"
protocol="AJP/1.3"/>
para
<!-- A AJP 1.3 Connector on port 8009 -->
<Connector port="8009" address="${jboss.bind.address}"
emptySessionPath="true" enableLookups="false" tomcatAuthentication="false" redirectPort="8443"
protocol="AJP/1.3"/>
Crie o arquivo de init do jboss em /etc/init.d, esse arquivo foi retirado do módulo puppet-example42-jboss, ajuste a linha 31 com o ip correto da sua máquima.
#!/bin/sh
# File Managed by Puppet
# jboss Startup script for JBoss Instance default
#
# chkconfig: - 85 15
# description: Jboss is an Application Server
### BEGIN INIT INFO
# Provides: jboss
# Required-Start: $local_fs $remote_fs $network
# Required-Stop: $local_fs $remote_fs $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start/stop jboss service
### END INIT INFO
# define where jboss is - this is the directory containing directories log, bin, conf etc
JBOSS_HOME=${JBOSS_HOME:-"/opt/jboss"}
# define the user under which jboss will run, or use 'RUNASIS' to run as the current user
JBOSS_USER=${JBOSS_USER:-"jboss"}
# make sure java is in your path
JAVAPTH=${JAVAPTH:-"/usr/local/jdk/bin"}
# configuration to use, usually one of 'minimal', 'default', 'all'
JBOSS_CONF=${JBOSS_CONF:-"default"}
# if JBOSS_HOST specified, use -b to bind jboss services to that address
JBOSS_BIND_ADDR=${JBOSS_HOST:-"-b 10.10.2.73"}
# define the classpath for the shutdown class
JBOSSCP=${JBOSSCP:-"$JBOSS_HOME/bin/shutdown.jar:$JBOSS_HOME/client/jnet.jar"}
# define the script to use to start jboss
JBOSSSH=${JBOSSSH:-"$JBOSS_HOME/bin/run.sh -c $JBOSS_CONF $JBOSS_BIND_ADDR"}
# Lock and Pid files
LOCKFILE=/var/lock/jboss
PIDFILE=/var/run/jboss.pid
if [ "$JBOSS_USER" = "RUNASIS" ]; then
SUBIT=""
else
SUBIT="su - $JBOSS_USER -c "
fi
if [ -n "$JBOSS_CONSOLE" -a ! -d "$JBOSS_CONSOLE" ]; then
# ensure the file exists
touch $JBOSS_CONSOLE
if [ ! -z "$SUBIT" ]; then
chown $JBOSS_USER $JBOSS_CONSOLE
fi
fi
if [ -n "$JBOSS_CONSOLE" -a ! -f "$JBOSS_CONSOLE" ]; then
echo "WARNING: location for saving console log invalid: $JBOSS_CONSOLE"
echo "WARNING: ignoring it and using /dev/null"
JBOSS_CONSOLE="/dev/null"
fi
#define what will be done with the console log
JBOSS_CONSOLE=${JBOSS_CONSOLE:-"/dev/null"}
# Jboss Start command
# Custom, per instance, run.conf configured via Puppet
JBOSS_CMD_START="cd $JBOSS_HOME/bin; $JBOSSSH"
if [ -z "`echo $PATH | grep $JAVAPTH`" ]; then
export PATH=$PATH:$JAVAPTH
fi
if [ ! -d "$JBOSS_HOME" ]; then
echo JBOSS_HOME does not exist as a valid directory : $JBOSS_HOME
exit 1
fi
status () {
pslist=$( ps -ef | fgrep run.sh | fgrep java | fgrep $JBOSS_USER | fgrep default | awk '{print $2}' | tr '\n' ' ' | sed -e s/\ $// )
if [ -n "$pslist" ]; then
echo "jboss (pid $pslist) is running result: 0"
return 0
fi
if [ -f $PIDFILE ]; then
echo "jboss dead but pid file exists result: 1"
return 1
fi
if [ -f $LOCKFILE ]; then
echo "jboss dead but subsys locked result: 2"
return 2
fi
echo "jboss is stopped result: 3"
return 3
}
start () {
if [ -f $LOCKFILE ]; then
status
exit
fi
cd $JBOSS_HOME/bin
echo JBOSS_CMD_START = $JBOSS_CMD_START
if [ -z "$SUBIT" ]; then
eval $JBOSS_CMD_START >${JBOSS_CONSOLE} 2>&1 &
if [ "$?" -eq 0 ]; then
touch $LOCKFILE
fi
else
$SUBIT "$JBOSS_CMD_START >${JBOSS_CONSOLE} 2>&1 &"
if [ "$?" -eq 0 ]; then
touch $LOCKFILE
fi
fi
}
stop () {
[ "$1" -eq "$1" ] 2> /dev/null && timeout=$1 || timeout=0
pslist=$( ps -ef | fgrep run.sh | fgrep java | fgrep $JBOSS_USER | fgrep default | awk '{print $2}' | tr '\n' ' ' | sed -e s/\ $// )
if [ ! -z "$pslist" ]; then
kill $pslist
seconds=0
while [ "$(ps -A -o pid= | grep -q $pslist ; echo $?)" = "0" ]; do
echo "JBoss still running..."
sleep 1
seconds=$(expr $seconds + 1)
if [ $seconds -ge $timeout ] && [ $timeout -gt 0 ]
then
kill -9 $pslist
break
fi
done
rm -f $LOCKFILE
echo "JBoss stopped!"
fi
}
case "$1" in
start)
start
;;
stop)
stop $2
;;
restart)
stop $2
start
;;
status)
status
;;
*)
echo "usage: $0 (start|stop [timeout in seconds]|restart [timeout in seconds]|status|help)"
esac
3. pós configuração
3.1 posconfig::samba
ative o samba no boot
chkconfg smb on
reinicie o samba
service smb restart
coloque a maquina no domínio
net ads join -U usuário
obtenha um ticket kerberos
kinit usuario.sobrenome
edite /etc/nsswitch.conf e modifique
passwd: compat
group: compat
para
passwd: compat winbind
group: compat winbind
3.2 posconfig::apache
ative a autenticação ntlm no selinux (caso ele esteja ativado)
setsebool -P allow_httpd_mod_auth_ntlm_winbind on
ative o boleando para permitir o funcionamento do proxy no apache
setsebool -P httpd_can_network_connect 1
adicione o apache ao grupo do winbind
gpasswd -a apache wbpriv
ative o httpd no boot
chkconfig httpd on
reinicie o httpd
service httpd restart
3.3 posconfig::jboss
ajuste a permissão do script de inicialização do jboss
chmod 755 /etc/init.d/jboss
ative o jboss no boot
chkconfig jboss on
inicie o jboss
/etc/init.d/jboss start
4. testes
4.1 testes::ntlm_auth
teste a autenticação localmente para garantir que está funcionando.
/usr/bin/ntlm_auth --username usuario --domain=XXX
5.2 testes::jboss
Faça o deploy de uma aplicação como por exemplo o ntlmtest e verifique se a autenticação NTLM está funcionando.
Esse último passo é bastante particular da sua aplicação, o apache só vai permtir que usuários válidos acessem o /app, contudo, como sua aplicação vai utilizar as credenciais é contigo e com sua app ;)
6. referências
Oficiais
- http://httpd.apache.org/docs/
- http://jbossas.jboss.org/docs
- http://www.samba.org/samba/docs/man/Samba3-HOWTO/
- http://web.mit.edu/kerberos/
Oficiais específicos
- http://web.mit.edu/kerberos/krb5-latest/doc/admin/conf_files/krb5_conf.html
- https://www.samba.org/samba/docs/man/Samba-HOWTO-Collection/winbind.html
- http://www.tldp.org/HOWTO/html_single/Kerberos-Infrastructure-HOWTO/
Outros