Fala galera!
Tudo bem com vocês ?
Neste post eu vou demonstrar a vocês como consultar informações do Active Directory (AD) pelo SQL Server utilizando um simples Linked Server e a interface ADSI (Active Directory Service Interfaces). Mais uma vez, a Microsoft vem fornecendo recursos para que o SQL Server consiga se integrar com cada vez mais ferramentas e interfaces e se tornando uma solução ainda mais completa a cada versão.
No meu trabalho, utilizo esse recurso para fazer a carga diária de uma tabela no banco com todos os usuários e algumas informações deles do AD, facilitando assim, consultas e manipulação desses dados em relatórios.
Como criar o Linked Server
Para que seja possível acessar os dados do Active Directory, você precisará criar um Linked Server utilizando o provider “OLE DB Provider for Microsoft Directory Services”, conforme a tela abaixo:
Caso você seja um fã de linha de código (como eu), você também pode criar o linked server utilizando T-SQL:
USE [master]
GO
EXEC master.dbo.sp_addlinkedserver @server = N'ADSI', @srvproduct=N'', @provider=N'ADsDSOObject'
GO
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname=N'ADSI',@useself=N'True',@locallogin=NULL,@rmtuser=NULL,@rmtpassword=NULL
GO
EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'collation compatible', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'data access', @optvalue=N'true'
GO
EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'dist', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'pub', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'rpc', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'rpc out', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'sub', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'connect timeout', @optvalue=N'0'
GO
EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'collation name', @optvalue=NULL
GO
EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'lazy schema validation', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'query timeout', @optvalue=N'0'
GO
EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'use remote collation', @optvalue=N'true'
GO
EXEC master.dbo.sp_serveroption @server=N'ADSI', @optname=N'remote proc transaction promotion', @optvalue=N'true'
GO
Como consultar informações do Active Directory
Uma vez que você tenha criado o seu Linked Server utilizando ADSI, vamos começar a consultar as informações do AD.
Código-fonte para consultar usuários
SELECT
userPrincipalName,
SamAccountName,
displayName,
givenName,
sn,
physicalDeliveryOfficeName,
mail,
telephoneNumber,
Title,
department,
company,
manager,
mobile
FROM OPENQUERY (ADSI, '
SELECT
userPrincipalName,
SamAccountName,
displayName,
givenName,
sn,
physicalDeliveryOfficeName,
mail,
telephoneNumber,
Title,
department,
company,
manager,
mobile
FROM
''LDAP://dirceuresende.local:389''
WHERE
objectCategory = ''Person''
AND objectClass = ''User''
') AS Resultado
ORDER BY displayname
Resultado
Código-fonte para consultar computadores
SELECT
[Name],
[Location],
[Description],
whenCreated,
whenChanged,
logoncount
FROM OPENQUERY (ADSI, '
SELECT
Name,
Location,
Description,
whenCreated,
whenChanged,
logoncount
FROM
''LDAP://dirceuresende.local:389''
WHERE
objectClass = ''Computer''
') AS Resultado
ORDER BY [name]
Resultado
Limitações do ADSI
A medida que você começar a utilizar o ADSI, vai perceber que ele tem algumas limitações. Uma delas, é que ao realizar consultas que retornem mais de 901 registros, você verá a mensagem de erro abaixo:
Msg 7330, Level 16, State 2, Line 1 Cannot fetch a row from OLE DB provider “ADSDSOObject” for linked server “ADSI”.
Para contornar essa limitação, você pode criar uma tabela para receber os dados, realizar um TOP 901 e ir percorrendo os registros e gravando nessa tabela. Para facilitar a sua vida, já vou deixar o script pronto para vocês:
IF (OBJECT_ID('tempdb..#Usuarios_AD') IS NOT NULL) DROP TABLE #Usuarios_AD
CREATE TABLE #Usuarios_AD (
displayName nvarchar (4000) COLLATE SQL_Latin1_General_CP1_CI_AI NULL,
SamAccountName nvarchar (4000) COLLATE SQL_Latin1_General_CP1_CI_AI NULL,
userPrincipalName nvarchar (4000) COLLATE SQL_Latin1_General_CP1_CI_AI NULL,
givenName nvarchar (4000) COLLATE SQL_Latin1_General_CP1_CI_AI NULL,
sn nvarchar (4000) COLLATE SQL_Latin1_General_CP1_CI_AI NULL,
Title nvarchar (4000) COLLATE SQL_Latin1_General_CP1_CI_AI NULL,
department nvarchar (4000) COLLATE SQL_Latin1_General_CP1_CI_AI NULL,
company nvarchar (4000) COLLATE SQL_Latin1_General_CP1_CI_AI NULL,
physicalDeliveryOfficeName nvarchar (4000) COLLATE SQL_Latin1_General_CP1_CI_AI NULL,
mail nvarchar (4000) COLLATE SQL_Latin1_General_CP1_CI_AI NULL,
telephoneNumber nvarchar (4000) COLLATE SQL_Latin1_General_CP1_CI_AI NULL,
mobile nvarchar (4000) COLLATE SQL_Latin1_General_CP1_CI_AI NULL,
manager nvarchar (4000) COLLATE SQL_Latin1_General_CP1_CI_AI NULL,
postOfficeBox varchar (10) COLLATE SQL_Latin1_General_CP1_CI_AI NULL
)
IF (OBJECT_ID('tempdb..#Usuarios_AD_Temp') IS NOT NULL) DROP TABLE #Usuarios_AD_Temp
SELECT displayName, SamAccountName, userPrincipalName, givenName, sn, Title, department, company, physicalDeliveryOfficeName, mail, telephoneNumber, mobile, manager
INTO #Usuarios_AD_Temp
FROM #Usuarios_AD
DECLARE
@Ds_Ultimo_Login VARCHAR(100) = 'a',
@Query VARCHAR(MAX)
WHILE(@Ds_Ultimo_Login IS NOT NULL)
BEGIN
TRUNCATE TABLE #Usuarios_AD_Temp
SET @Query = '
SELECT
userPrincipalName,
SamAccountName,
displayName,
givenName,
sn,
physicalDeliveryOfficeName,
mail,
telephoneNumber,
Title,
department,
company,
manager,
mobile
FROM
''''LDAP://dirceuresende.local:389''''
WHERE
objectCategory = ''''Person''''
AND objectClass = ''''User''''
AND SamAccountName > ''''' + @Ds_Ultimo_Login + '''''
ORDER BY
SamAccountName
'
SET @Query = '
INSERT INTO #Usuarios_AD_Temp (displayName, SamAccountName, userPrincipalName, givenName, sn, Title, department, company, physicalDeliveryOfficeName, mail, telephoneNumber, mobile, manager)
SELECT TOP 901 displayName, SamAccountName, userPrincipalName, givenName, sn, Title, department, company, physicalDeliveryOfficeName, mail, telephoneNumber, mobile, manager
FROM OPENQUERY([ADSI], ''' + @Query + ''')'
EXEC(@Query)
INSERT INTO #Usuarios_AD(displayName, SamAccountName, userPrincipalName, givenName, sn, Title, department, company, physicalDeliveryOfficeName, mail, telephoneNumber, mobile, manager)
SELECT DISTINCT displayName, SamAccountName, userPrincipalName, givenName, sn, Title, department, company, physicalDeliveryOfficeName, mail, telephoneNumber, mobile, manager
FROM #Usuarios_AD_Temp
SET @Ds_Ultimo_Login = NULL
SELECT TOP 1 @Ds_Ultimo_Login = SamAccountName FROM #Usuarios_AD_Temp ORDER BY SamAccountName DESC
END
SELECT * FROM #Usuarios_AD
Uma outra limitação que ocorre nas consultas utilizando o ADSI, é que ao tentar consultar informações de campos preenchidos com dados multivalorados (Ex: postOfficeBox), você irá receber essa mensagem de erro:
Msg 7346, Level 16, State 2, Line 1
Cannot get the data of the row from the OLE DB provider “ADsDSOObject” for linked server “ADSI”. Could not convert the data value due to reasons other than sign mismatch or overflow.
Infelizmente, não conheço solução para essa situação que não seja utilizar CLR (C#) ou PowerShell 🙁
Bom, é isso aí pessoal!
Espero que tenham gostado desse post.
Um abraço e até a próxima.
sql server tsql select query consultar ler retrieve get list ad active directory users groups computers
sql server tsql select query consultar ler retrieve get list ad active directory users groups computers



Comentários (0)
Carregando comentários…