Introdução
Quando trabalhamos com aplicações distribuídas, muitas vezes
torna-se necessário “repassar” o contexto de segurança do usuário por cada
camada da aplicação até o banco de dados.
Este processo pode se tornar mais complicado na medida em
que mais camadas estão envolvidas no processo, principalmente se estas camadas
estão fisicamente separadas em computadores diferentes.
Descrição do Problema
Quando um sistema Windows Forms faz um acesso ao SQL Server
utilizando segurança integrada, este sistema utiliza o contexto de usuário que
está executando o processo (o executável Windows Forms) para tentar se
autenticar no banco de dados. A implementação deste cenário é relativamente
simples, pois o usuário já se autenticou ao efetuar o logon no Windows, e não é
necessário que sejam efetuadas maiores configurações para suportar o “repasse”
dessas credenciais para o banco de dados.
Figura 1: Aplicação Windows Forms
efetuando acesso ao SQL Server.
Mas quando trabalhamos com uma aplicação Web no lugar de
Windows Forms, a complexidade aumenta, pois agora teremos que efetuar uma
primeira autenticação do browser com o IIS, e depois uma segunda autenticação
do IIS para o SQL Server. Para este cenário, teremos que utilizar o Kerberos,
pois o NTLM não suporta o que chamamos de “delegação”, ou seja, repasse de
autenticação entre máquinas sucessivamente (a menos que tenhamos conhecimento,
via código, das variáveis usuário e senha e efetuemos um logon manual em cada
camada do processo via programação, utilizando, por exmeplo, a API LogonUser).
Poderíamos também trabalhar com Basic/Clear text, mas como este recurso não
oferece nenhuma criptografia, teríamos que utilizar SSL, tanto entre o browser
e o servidor web, quanto entre o servidor web e o de web services, caso exista.
Como sabemos que SSL não é uma boa solução quando se
trabalha com web services, e que basic/clear da acesso, via código, à senha do
usuário, acreditamos que a solução ideal seja realmente o Kerberos.
Figura 2: Aplicação Asp.Net efetuando acesso ao SQL Server.
Neste tipo de cenário, a configuração do Kerberos pode vir a
se tornar extremamente complexa, dependendo do ambiente e tipo de
aplicação.
Um exemplo disto seria supormos que provavelmente a camada
ASP.Net poderia ser dividida entre um projeto web, um web service e algumas
dll’s que fariam o acesso ao banco de dados, gerando o cenário ilustrado no
próximo exemplo:
Figura 3: Aplicação distribuída, com n camadas, efetuando acesso ao SQL
Server..
Para simplificar o processo de configuração do Kerberos para
atender a tais situações, enumeramos os passos necessários no tópico a seguir.
Possíveis Soluções
Segue abaixo um guia prático para a configuração do
Kerberos:
Passo 1: Configurando contas de usuário e máquinas no Active
Directory para que sejam “trusted for delegation”:
Abrir o Active Directory Users and Computers, escolher os
usuários que precisarão se utilizar deste recurso, abrir as propriedades e
fazer as seguintes modificações:
-Desmarcar o item “Account is sensitive and cannot be
delegated”, caso esteja marcado.
-Marcar o item “Account is trusted for delegation”, caso
esteja desmarcado.
Escolher agora os computadores envolvidos no processo de
delegação, abrir as propriedades e marcar o checkbox “Trust computer for
delegation”.
Passo 2: Sincronizando relógios:
Para o correto funcionamento do Kerberos, é necessário que a
data/hora dos computadores esteja perfeitamente sincronizada. O Kerberos
suporta uma diferença de apenas 5 minutos (valor default, pode ser modificado
via policy de domínio) na data/hora dos computadores. Sendo assim, sincronize
todos os computadores para ter certeza de que a data e hora estão compatíveis.
Tome cuidado com configuração de horário de verão e fuso horário.
Passo 3: Serviço MSSQLSERVER
Caso o seu cenário de delegação chegue ao SQL Server, ou a
algum outro serviço em especial, verifique qual o usuário com o qual este
serviço está executando (Ferramentas Administrativas/Serviços). Lembre-se que:
-A conta de usuário não pode ser uma conta local da máquina,
pois isto impedirá o cenário de delegação de funcionar corretamente.
-A conta de usuário poderá ser configurada como System
Account, isto não impedirá a delegação de ocorrer.
-Caso a conta de usuário seja uma conta de domínio,
verifique se o Passo 1 foi efetuado para esta conta, e se ela possui as devidas
permissões para que o serviço execute normalmente.
Passo 4: String de conexão
Se estivermos acessando o SQL Server e desejarmos que o
cenário de delegação se aplique até o nível do banco de dados, devemos nos
lembrar de configurar a string de conexão com o banco de dados incluindo os
seguintes dados: "Integrated Security=SSPI;Network Library=dbmssocn". O
primeiro informa que estamos trabalhando com segurança integrada, e o segundo
pede para que se use TCP/IP, necessário para o funcionamento do Kerberos.
Passo 5: Service Pack
Não insista em problemas que poderiam já estar resolvidos,
instale a última versão do Service Pack do Windows em todas as máquinas. Muitos
problemas relacionados a este cenário são corrigidos em Service Packs. O mesmo
vale para correções de Internet Explorer, SQL Server, e demais serviços
envolvidos.
Passo 6: Internet Explorer
Procure trabalhar com a última versão do Internet Explorer
(para os nossos testes de Kerberos, utilizamos a versão 5.5 ou superior).
Lembre-se de de marcar a opção “Enable Integrated Authentication (requires
restart)”, em Tools, Options, Advanced (Esta opção pode ter sido desabilitada
caso tenha sido feito um upgrade para o Internet Explorer 6.0). Caso esta opção
não apareça nas opções do seu browser, provavelmente ele é muito antigo e não
suporta Kerberos desta forma.
O Kerberos não é suportado via proxy servers, sendo assim,
temos duas opções: Desabilitar a configuração de proxy no browser ou incluir os
servidores que estaremos acessando na opção de endereços locais para efetuar
bypass.
Lembre-se: Só é possível utilizar Kerberos com Windows XP,
2000, 2003 ou superiores. Os Windows 9x e Me não são suportados neste cenário
(apesar de termos visto drivers de terceiros que prometem resolver isto para
estas plataformas, não chegamos a testa-los).
Caso, no processo de autenticação, uma janela esteja abrindo
no browser para entrada de usuário e senha, é sinal de que por algum motivo o
browser e o servidor web estão tentando se autenticar em clear text, e não em
kerberos. Reveja as configurações de ambos para que isto não ocorra.
Passo 7: Web Services
O arquivo web.config do projeto deve ter os elementos de
segurança modificados para que se force a integração entre a autenticação do
usuário e o contexto de segurança, da seguinte forma:
<identity
impersonate="true"></identity>
<authorization>
<allow users="*"/>
<deny users="?"/>
</authorization>
O elemento “identity” está habilitando a personificação de usuário, enquanto o “authorization” está permitindo o acesso de todos os usuários, exceto o anonymous.
<authorization>
<allow users="*"/>
<deny users="?"/>
</authorization>
O elemento “identity” está habilitando a personificação de usuário, enquanto o “authorization” está permitindo o acesso de todos os usuários, exceto o anonymous.
Passo 8: Site Asp.Net
Para o site Asp.Net, devemos efetuar a mesma configuração de
web.config que fizemos para os web services:
<identity
impersonate="true"></identity>
<authorization>
<allow users="*"/>
<deny users="?"/>
</authorization>
<authorization>
<allow users="*"/>
<deny users="?"/>
</authorization>
Além disso, é preciso que, na chamada aos web services, o
código Asp.Net “repasse” a autenticação que recebeu para que os web services a
recebam. Isto pode ser feito da seguinte forma:
WebServiceProxy.Service1 MeuServico; MeuServico =new WebServiceProxy.Service1(); MeuServico.Proxy=null; MeuServico.Credentials=System.Net.CredentialCache.DefaultCredentials; MeuServico.ExecutarMetodoWeb();
A linha que altera a propriedade Credentials é fundamental
nesse contexto, pois ela busca no CredentialCache a credencial usada para
autenticação na página e faz a associação desta com o proxy do Web Service a
ser executado.
Já a linha que altera a propriedade Proxy para null não é
essencial, mas serve para nos lembrar que o servidor Asp.Net não pode se valer
de um web proxy para acessar o web service, sob pena de perder o ticket
Kerberos.
Passo 9: IIS
As configurações de IIS feitas no servidor Asp.Net devem ser
as mesmas feitas no servidor de Web Services.
Basicamente, devemos abrir o IIS Manager, acessar as
propriedades das SubWebs envolvidas (tanto a do site quanto a do web service)
entrar na aba “Directory Security”, em “Authentication and access control”,
clicar em “Edit”, e desmarcar todos os check-boxes, deixando apenas o de
“Integrated Windows authentication” marcado.
É importante que apenas esse check-box esteja marcado, caso
contrário o IIS poderá decidir por tentar outro tipo de autenticação no lugar
do Kerberos.
Os servidores IIS também devem permitir que o tipo de
autenticação chamado “Negotiate” esteja habilitado. Esta é a configuração
default, mas pode ser confirmada executando-se o comando script abaixo:
cscript adsutil.vbs set
w3svc/1/NTAuthenticationProviders "Negotiate,NTLM"
Não é necessário remover o NTLM, isto impediria qualquer
Windows 9x de acessar o IIS. Como o Negotiate vem primeiro, esta será a
primeira tentativa, e só não irá ocorrer caso exista algum outro problema.
Passo 10: Setspn
Um utilitário praticamente indispensável quando se trabalha
com o Kerberos é o setspn (“SPN” vem de “Service Principal Name”).
O download pode ser feito no endereço abaixo:
Service Principal Names são usados para suportar
autenticação mutua entre uma aplicação cliente e um serviço.
O setspn tem o objetivo de auxiliar na configuração do
Active Directory (a resolução de nomes tem um papel fundamental para que o
Kerberos funcione). A idéia principal é a seguinte: Não basta que se consiga
resolver o nome da máquina para o IP, mas também o IP para o nome da máquina (e
se um nome chega a um IP, esse IP tem que resolver exatamente para o mesmo nome
original). Além disso, precisamos cadastrar alguns serviços no Active
Directory, e é aí que o setspn entra.
Para ilustrar o uso do setspn, instalei este utilitário no
meu computador e executei o seguinte comando no DOS:
setspn -L nome_da_maquina
O comando gerou o seguinte retorno:
Registered ServicePrincipalNames for
CN=nome_da_maquina,CN=Computers,DC=flag,DC=com,DC=br:
MSSQLSvc/nome_da_maquina.flag.com.br:1433
HOST/NOME_DA_MAQUINA
HOST/nome_da_maquina.flag.com.br
C:\>
O parâmetro –L listou os Service Principal Names registrados
para a minha máquina. É interessante observar que automaticamente eu já tenho o
serviço do SQL Server informado no Active Directory. Ele sabe inclusive que o
meu SQL Server está na porta 1433.
Executei este comando para mostrar que, muitas vezes,
podemos descobrir que o serviço que estamos usando não está registrado como
deveria, e nesse caso, teremos que registra-lo manualmente.
Por exemplo, suponhamos que eu tenha uma segunda instância
do SQL Server ouvindo a porta 9000. Como este serviço não apareceu quando eu
executei o parâmetro –L, terei que cadastra-lo manualmente (caso o serviço não
tenha se registrado automaticamente, pode ser um sinal de que algo errado está
acontecendo com este serviço. Se o serviço estiver rodando com uma conta local,
provavelmente ele não conseguirá efetuar o registro, e também não irá
funcionar, mesmo que eu faça o registro manualmente).
O comando para registrar o serviço do SQL Server seria
assim:
setspn -A MSSQLSvc/nome_da_maquina.flag.com.br:9000
nome_da_maquina
Verifique se o comando executou e nenhuma mensagem de erro
foi retornada. Caso uma mensagem de erro tenha ocorrido, pode ser que a conta
de usuário que esteja sendo usada não tem permissão suficiente para fazer este
registro.
Pode ser que você queira fazer o registro do serviço sem o
nome FQDN também, para garantir que a resolução ocorra tanto com o nome FQDN
quanto com o hostname, e o resultado então seria:
Registered ServicePrincipalNames for
CN=nome_da_maquina,CN=Computers,DC=flag,DC=com,DC=br:
MSSQLSvc/nome_da_maquina.flag.com.br:1433
HOST/NOME_DA_MAQUINA
HOST/nome_da_maquina.flag.com.br
MSSQLSvc/nome_da_maquina.flag.com.br:9000
MSSQLSvc/nome_da_maquina:9000
C:\>
Devemos nos lembrar que pode ser necessário o cadastro de
outros serviços também, como por exemplo:
Para Olap Server:
MSOLAPSvc/nome_da_maquina.dominio
MSOLAPSvc/nome_da_maquina
Para servidores IIS (página e web services):
HTTP/nome_da_maquina.dominio nome_da_maquina
HTTP/nome_da_maquina nome_da_maquina
É importante lembrar também que deve haver cuidado com a
replicação dos dados. Por exemplo, posso fazer este cadastro em um servidor
KDC, mas enquanto a replicação não ocorre, os outros ficam desatualizados,
podendo impedir o funcionamento do cenário de Delegação.
Como a resolução máquina/IP e IP/máquina devem estar em
sintonia, devemos também fazer um teste simples: “ping nome_da_maquina” e “ping
–a IP”. Ambos devem funcionar com sucesso, e o nome retornado pelo segundo deve
ser igual ao nome que usamos no primeiro. Da mesma forma, o IP retornado pelo
primeiro deve ser igual ao IP usado no segundo. Pode parecer um teste sem maior
importância, mas uma configuração incorreta neste ponto pode impedir totalmente
o kerberos de funcionar.
Passo 11: Se tudo mais falhar
Vivenciamos um problema real onde, mesmo seguindo todos os
itens citados anteriormente, ainda não conseguíamos fazer com que o cenário de
delegação funcionasse. Deduzimos então que deveria estar ocorrendo alguma
restrição de policy que nos impedia de fazer este cenário funcionar.
Para resolver o problema, efetuamos o seguinte teste, que
nos permitiu resolver o problema:
-Abrir o Local Security Policy do servidor SQL Server.
-Em Local Policy/User Rights Assignment, abrir as permissões
para Everyone nos itens: Access this computer from the network, Act as part of
the operating system, Create a token object, Enable computer and user accounts
to be trusted for delegation, Impersonate a client after authentication, Log on
as a service, Replace a process level token.
-Efetuar novo teste no sistema.
Após os testes funcionarem, desfazer uma a uma as alterações
efetuadas na policy, até encontrar o ponto que estava impedindo o funcionamento
do cenário de delegação.
Recomendações Finais
O cenário de delegação pode ser extremamente útil numa
intranet, mas deve ser usado com cautela. Isto porque de certa forma ele torna
a segurança do ambiente menos restritiva.
Caso um código malicioso execute em uma máquina, ele agora
poderá causar danos não só locais, mas também reutilizar o contexto de
permissão do usuário para causar danos em cascata, em uma seqüência de
máquinas, se valendo do cenário de delegação.
Algumas restrições citadas para este cenário nas
documentações do MSDN podem ser contornadas ou sequer existir, dependendo de
como configurarmos nosso ambiente, por exemplo:
-Não é necessário fazer todo acesso às máquinas pelo FQDN
(nome.domínio). Caso as entradas no SPN estejam corretas, podemos utilizar
apenas o nome da máquina, ou até nomes fictícios, cadastrados no hosts.
-Não é necessário fazer alterações no machine.config,
colocando o processo do IIS para rodar com uma conta específica de usuário.
-Podemos manter as configurações de proxy habilitadas no
browser, contanto que as máquinas que estejamos acessando estejam na lista de
bypass da configuração de proxy.