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

Oficiais específicos

Outros