miércoles, 31 de octubre de 2007

Consultas contra el Directorio Activo desde SQL Server

grHola, ahora el "chicharron" es que el cliente quiere mantener una tabla de la base de datos de Sql Server 2005 Express, actualizada con la informacion de los usuarios del directorio activo, y pues tecnicamente, esto puede ser hecho directamente con queryes sobre el directorio activo, gracias al uso del bondadoso protocolo LDAP (Lightweight Directory Access Protocol o Protocolo de acceso liviano al Directorio), este protocolo de capa 7 del modelo OSI nos permite a nivel de aplicacion acceder a la informacion de la base de datos del directorio activo y para ello se requiere conocer una cuenta que pertenezca al dominio y obviamente el nombre o direccion IP del controlador de dominio o nombre o IP del servidor replica del directorio activo.

Sera que se pueden consultar los datos del directorio activo desde SQL Server y de la misma forma como se hacen queries estandar?, La respuesta es si y acontinuacion les dire como.
Para ello, debemos crear y configurar un servidor enlazado (Linked Server) cuya fuente de datos apuntara hacia el Directorio activo utilizando el proveedor ADsDSObject, y luego impersonamos el acceso al servidor con cualquier cuenta que pertenezca al directorio activo

1. Cree el procedimiento almacenado con el siguiente script:


-- Procedimiento para crear/borrar un servidor enlazado hacia el directorio activo
-- autor: eider mauricio aristizabal erazo
-- Para que las consultas LDAP funcionen:
-- El servidor de Sql Server debe estar instalado en un pc que pertenezca al dominio
-- Ejemplo de consulta en el directorio activo (Una vez se haya creado el servidor enlazado)
-- SELECT * FROM OpenQuery(ENLACE_DA, 'SELECT * FROM ''LDAP://IP.CONTROLADOR.DE.DOMINIO'' ')

CREATE PROCEDURE [dbo].[USP_ENLAZAR_DIRECTORIO_ACTIVO]
AS
BEGIN

IF ((SELECT COUNT(*) FROM MASTER.DBO.SYSSERVERS WHERE SRVNAME = 'ENLACE_DA') > 0)
BEGIN
EXEC sp_dropserver 'ENLACE_DA', 'droplogins'
SELECT 'EL SERVIDOR [ENLACE_DA] HA SIDO ELIMINADO'
END
ELSE
BEGIN
EXEC sp_addlinkedserver
@server = 'ENLACE_DA',
@provider = 'ADsDSOObject',
@srvproduct = 'ADsDSOObject',
@datasrc ='ADsDSOObject'

EXEC sp_addlinkedsrvlogin
'ENLACE_DA',
'false',
null,
null,
null

SELECT 'EL SERVIDOR ENLAZADO [ENLACE_DA] HA SIDO CREADO'
END
END


2. Ejecute el procedimiento almacenado que acaba de crear (Asegúrese que el resultado el procedimiento retorne el mensaje 'EL SERVIDOR ENLAZADO [ENLACE_DA] HA SIDO CREADO'):


USE [BASE_DE_DATOS]
GO

DECLARE @return_value int

EXEC
@return_value = [dbo].[USP_ENLAZAR_DIRECTORIO_ACTIVO]

SELECT
'Return Value' = @return_value
GO


3. Impersonalizar el acceso al servidor:
En el Sql Server Management Studio, navegue hasta la ubicacion, Server Objects/Linked Servers y dele clic derecho propiedades a ENLACE_DA, aparece la ventana Linked server properties - ENLACE_DA seleccione la pestaña Security y escoja la opcion Be Made using this security context, escribe un usuario del dominio bajo la sintaxis midiominio\usuario_del_dominio
Tambien se puede impersonar con el comando:


USE [BASE_DE_DATOS]
GO
EXEC
sp_addlinkedsrvlogin @rmtsrvname = N'ENLACE_DA', @locallogin = NULL , @useself = N'False', @rmtuser = N'dominio\usuario', @rmtpassword = N'password del usuario'


4. Haga una consulta del Directorio Activo:

--Primer Ejemplo
SELECT
*
FROM
OpenQuery(
ENLACE_DA,
'SELECT * FROM ''LDAP://IP.CONTROLADOR.DE.DOMINIO'''
)

--Segundo Ejemplo
SELECT
sAMAccountName, cn, displayName, mail, info, department, homephone, manager
FROM
OpenQuery(
ENLACE_DA,
'SELECT
info, sAMAccountName, cn, displayName, manager, homephone, department, company, title, samaccounttype, mail FROM ''LDAP://IP.CONTROLADOR.DE.DOMINIO'''
)


Finalmente, para ver una lista completa de los campos validos del directorio activo abra la linea de comandos y ejecute el comando:
CSVDE -f DatosDelDominio.csv

abra el archivo utilizando Microsoft Excel y sitúese sobre la primera fila, note que ésta contiene todos los campos válidos que se pueden utilizar en las consultas LDAP contra el directorio activo.
En mi caso aparecen 293 campos, genial si o que?


accountExpires

adminCount

appSchemaVersion

auditingPolicy

badPasswordTime

badPwdCount

c

cn

co

codePage

cOMClassID

comment

company

countryCode

creationTime

dc

deliveryMechanism

department

description

directReports

displayName

distinguishedName

DN

dNSHostName

dNSProperty

dnsRecord

dNSTombstoned

driverName

driverVersion

dSCorePropagationData

extensionName

flags

forceLogoff

frsComputerReference

frsComputerReferenceBL

fRSFileFilter

fRSMemberReference

fRSMemberReferenceBL

fRSPrimaryMember

fRSReplicaSetGUID

fRSReplicaSetType

fRSRootPath

fRSStagingPath

fRSVersionGUID

fRSWorkingPath

fSMORoleOwner

givenName

gPCFileSysPath

gPCFunctionalityVersion

gPCMachineExtensionNames

gPCUserExtensionNames

gPLink

gPOptions

groupType

homeMDB

homeMTA

homePhone

info

initials

installUiLevel

instanceType

internetEncoding

ipsecData

ipsecDataType

ipsecFilterReference

ipsecID

ipsecISAKMPReference

ipsecName

iPSECNegotiationPolicyAction

ipsecNegotiationPolicyReference

iPSECNegotiationPolicyType

ipsecNFAReference

ipsecOwnersReference

isCriticalSystemObject

keywords

l

lastLogoff

lastLogon

lastLogonTimestamp

lastSetTime

lastUpdateSequence

legacyExchangeDN

localeID

localPolicyFlags

location

lockoutDuration

lockOutObservationWindow

lockoutThreshold

logonCount

logonHours

machineArchitecture

mail

mailNickname

managedBy

managedObjects

manager

mAPIRecipient

masteredBy

maxPwdAge

mDBUseDefaults

member

memberOf

middleName

minPwdAge

minPwdLength

mobile

modifiedCount

modifiedCountAtLastProm

msDS-AllowedToDelegateTo

msDS-AllUsersTrustQuota

msDS-Behavior-Version

mS-DS-CreatorSID

ms-DS-MachineAccountQuota

msDs-masteredBy

msDS-PerUserTrustQuota

msDS-PerUserTrustTombstonesQuota

msDS-TombstoneQuotaFactor

msExchALObjectVersion

msExchExpansionServerName

msExchHideFromAddressLists

msExchHomeServerName

msExchMailboxGuid

msExchMailboxSecurityDescriptor

msExchMasterAccountSid

msExchMobileMailboxFlags

msExchPFTreeType

msExchPoliciesIncluded

msExchRecipientDisplayType

msExchRecipientTypeDetails

msExchRequireAuthToSendTo

msExchUserAccountControl

msExchUserCulture

msExchVersion

msieee80211-Data

msieee80211-DataType

msieee80211-ID

msiFileList

msiScriptName

msiScriptPath

mSMQDependentClientServices

mSMQDigests

mSMQDsServices

mSMQEncryptKey

mSMQOSType

mSMQRoutingServices

mSMQServiceType

mSMQSignCertificates

mSMQSignKey

mSMQSites

msNPAllowDialin

msRTCSIP-ArchiveDefault

msRTCSIP-ArchiveDefaultFlags

msRTCSIP-ArchiveFederationDefault

msRTCSIP-ArchiveFederationDefaultFlags

msRTCSIP-BackEndServer

msRTCSIP-DefPresenceSubscriptionTimeout

msRTCSIP-DefRegistrationTimeout

msRTCSIP-DefRoamingDataSubscriptionTimeout

msRTCSIP-DomainName

msRTCSIP-EnableBestEffortNotify

msRTCSIP-EnableFederation

msRTCSIP-EnterpriseServices

msRTCSIP-FederationEnabled

msRTCSIP-FrontEndServers

msRTCSIP-GlobalSettingsData

msRTCSIP-InternetAccessEnabled

msRTCSIP-MaxNumOutstandingSearchPerServer

msRTCSIP-MaxNumSubscriptionsPerUser

msRTCSIP-MaxPresenceSubscriptionTimeout

msRTCSIP-MaxRegistrationTimeout

msRTCSIP-MaxRoamingDataSubscriptionTimeout

msRTCSIP-MinPresenceSubscriptionTimeout

msRTCSIP-MinRegistrationTimeout

msRTCSIP-MinRoamingDataSubscriptionTimeout

msRTCSIP-NumDevicesPerUser

msRTCSIP-OptionFlags

msRTCSIP-PoolAddress

msRTCSIP-PoolDisplayName

msRTCSIP-PoolType

msRTCSIP-PoolVersion

msRTCSIP-PrimaryHomeServer

msRTCSIP-PrimaryUserAddress

msRTCSIP-SearchMaxRequests

msRTCSIP-SearchMaxResults

msRTCSIP-TrustedServerFQDN

msRTCSIP-TrustedServerVersion

msRTCSIP-UserEnabled

name

nextRid

nTMixedDomain

objectCategory

objectClass

objectGUID

objectSid

objectVersion

operatingSystem

operatingSystemServicePack

operatingSystemVersion

otherHomePhone

otherMailbox

ou

packageFlags

packageName

packageType

pager

physicalDeliveryOfficeName

portName

primaryGroupID

printBinNames

printCollate

printColor

printDuplexSupported

printEndTime

printerName

printKeepPrintedJobs

printLanguage

printMaxResolutionSupported

printMaxXExtent

printMaxYExtent

printMediaReady

printMediaSupported

printMemory

printMinXExtent

printMinYExtent

printOrientationsSupported

printPagesPerMinute

printRate

printRateUnit

printShareName

printSpooling

printStaplingSupported

printStartTime

priority

priorSetTime

productCode

protocolSettings

proxyAddresses

publicDelegates

publicDelegatesBL

pwdHistoryLength

pwdLastSet

pwdProperties

replUpToDateVector

reportToOriginator

repsFrom

revision

rIDAllocationPool

rIDAvailablePool

rIDManagerReference

rIDNextRID

rIDPreviousAllocationPool

rIDSetReferences

rIDUsedPool

sAMAccountName

sAMAccountType

serverName

serverReference

serverReferenceBL

serverState

serviceBindingInformation

serviceClassName

serviceDNSName

serviceDNSNameType

servicePrincipalName

shortServerName

showInAddressBook

showInAdvancedViewOnly

sn

st

streetAddress

subRefs

systemFlags

targetAddress

telephoneNumber

textEncodedORAddress

title

uASCompat

uNCName

upgradeProductCode

url

userAccountControl

userCertificate

userParameters

userPrincipalName

uSNChanged

uSNCreated

versionNumber

versionNumberHi

versionNumberLo

wellKnownObjects

whenChanged

whenCreated

wWWHomePage




Es todo, asi de facil!....




Salu2 desde Cali, Colombia

8 comentarios:

Unknown dijo...

No lo había leído todo hasta hoy... está bueníimo.. mis respetos señor ingeniero.

imcortez dijo...

Impresionante. Muy buen articulo.

Unknown dijo...

Enhorabuena!!!

Llevo varios días buscando esta información y con tu solución funciona perfectamente.

Unknown dijo...

Amigo nose si aun lees esto... pero estoy tratando de realizar una aplicacion Php que capture las cuentas de Active Directory.
Esto me sirve?

Me puedes ayudar con la configuracion , nosé cuales son los dato ( Ej: enlace_da),

Seria de gran ayuda... =)

Mi email es panicxp@hotmail.com

De antemano

Muchisimas gracias

Unknown dijo...

Hola amigo!

Sabes he podido realizar la coneccion, mostrar los datos y todo eso.
Estoy realiazndo una aplicacion Php, pero me surgio el siguiente problema:

Los usuarios actuales de AD me aparecen sin ningun problema, al modificarlos , igual... me muestra los resultados cambiados, pero, al agregar un nuevo usuario no lo muestra. =(

Sabes que puede ser?'

Fidel dijo...

hola muy buen dia,
el articulo esta por demas decir interesante y muy util,
ahora mi consulta es: se podra crear cuentas en el LDAP usando openquery?

Paul Baylis dijo...

Would you please translate into English? I need this information. Thank you.

Paul Baylis dijo...

Would you please translate into English? I need this information. Thank you.