Infraestrutura Ágil

Soluções e métodos inteligentes para sua infra

JBOSS NTLM auth com apache e winbind

| Comments

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

1
2
3
4
5
6
7
8
9
10
11
12
[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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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

1
2
3
4
<!-- 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

1
2
3
4
<!-- 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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#!/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

  • http://bloke.org/linux/ntlm-authentication-active-directory-on-apache-linux/
  • http://adldap.sourceforge.net/wiki/doku.php?id=mod_auth_ntlm_winbind

Comments