timmcmic / DLConversionV2

MIT License
44 stars 9 forks source link

Connection to Active Directory fails if the on-prem credentials are in UPN format #51

Closed MassimoPascucci closed 2 years ago

MassimoPascucci commented 2 years ago

Everything works ok when using on-premises credentials in the following formats:

However, the script errors out when using an UPN:

Extract from the error log (anonymized):

[07/05/2022 15:57:43] - ********************************************************************************
[07/05/2022 15:57:43] - Attempting to find the AD object associated with the member.
[07/05/2022 15:57:43] - Obtaining the active directory domain for this operation.
[07/05/2022 15:57:43] - ********************************************************************************
[07/05/2022 15:57:43] - BEGIN GET-ActiveDirectoryDomainName
[07/05/2022 15:57:43] - ********************************************************************************
[07/05/2022 15:57:43] - DN to convert: *ANOYMIZED*,DC=DOMAIN,DC=LOCAL
[07/05/2022 15:57:43] - Converting the distringuished name.
[07/05/2022 15:57:43] - DC=DOMAIN
[07/05/2022 15:57:43] - DC=LOCAL
[07/05/2022 15:57:43] - The FQDN of the object based on DN: DOMAIN.LOCAL
[07/05/2022 15:57:43] - END GET-ActiveDirectoryDomainName
[07/05/2022 15:57:43] - ********************************************************************************
[07/05/2022 15:57:43] - Active Directory Domain Calculated: DOMAIN.LOCAL
[07/05/2022 15:57:43] - Attepmting to find the user via distinguished name.
get-adObject : Either the target name is incorrect or the server has rejected the client credentials.
At C:\Program Files\WindowsPowerShell\Modules\DLConversionV2\2.5.19\Get-NormalizedDN.ps1:96 char:37
+ ... ctionTest = get-adObject -filter {distinguishedname -eq $dn} -propert ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : SecurityError: (:) [Get-ADObject], AuthenticationException
    + FullyQualifiedErrorId : ActiveDirectoryCmdlet:System.Security.Authentication.AuthenticationException,Microsoft.A 
   ctiveDirectory.Management.Commands.GetADObject

Out-LogFile : Either the target name is incorrect or the server has rejected the client credentials.
At C:\Program Files\WindowsPowerShell\Modules\DLConversionV2\2.5.19\Get-NormalizedDN.ps1:141 char:21

I've tracked down the issue to lines 96 and 125 in Get-NormalizedDN.ps1:

$functionTest = get-adObject -filter {distinguishedname -eq $dn} -properties * -credential $adCredential -errorAction STOP -server $activeDirectoryDomainName

You are trying to connect to the Active Directory domain name instead of using an actual server name; this appears to fail when using an UPN for your credentials:

$activeDirectoryDomainName = 'domain.local'
$dn = 'cn=someuser,dn=domain,dn=local'

$username = 'username@domain.local'
$password = 'password'
$ssp = ConvertTo-SecureString $password -AsPlainText -Force

$adCredential = $cred New-Object System.Management.Automation.PSCredential ($username,$ssp)

get-adObject -filter {distinguishedname -eq $dn} -properties * -credential $adCredential -errorAction STOP -server $activeDirectoryDomainName
get-adObject : Either the target name is incorrect or the server has rejected the client credentials.
At line:1 char:1
+ get-adObject -filter {distinguishedname -eq $dn} -properties * -crede ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : SecurityError: (:) [Get-ADObject], AuthenticationException
    + FullyQualifiedErrorId : ActiveDirectoryCmdlet:System.Security.Authentication.AuthenticationException,Microsoft.A
   ctiveDirectory.Management.Commands.GetADObject

Instead, it works fine when using only the username or the "DOMAIN\username" syntax.

The error goes away if you use an actual domain controller name instead of the domain name; the function already has this passed in the $globalCatalogServer parameter, so it's easy to obtain; this works with all username formats:

get-adObject -filter {distinguishedname -eq $dn} -properties * -credential $adCredential -errorAction STOP -server $globalCatalogServer

MassimoPascucci commented 2 years ago

Some background; I don't know if any of this is relevant, but it might help troubleshooting:

Also, I don't know if you have a specific reason for getting the AD domain name from the DN and running Get-ADObject against it, instead of simply connecting to the specified global catalog server.

MassimoPascucci commented 2 years ago

Ok, I see you are doing this due to issue #37.

However, this breaks if credentials are provided using an UPN.

See also my comment on that issue.

timmcmic commented 2 years ago

Thanks for the continued follow up and questions.

So issue 37 stemmed from the fact that we had multiple customers reporting issues where there were multiple domains in the same forest. In once case the customer had a tree which had a disjoint name space.

When we would attempt to use the GC in the domain where the group resides - you essentially did not get a referral for all of the users properties in the other domain. This could be a function of using active directory web services.

What I found is that active directory web services and active directory will not use round robin dns when specifying a domain name - but rather a least costing method to locate a domain controller for the specific domain and will automatically do a referral on your behalf. This allows us to utilize the GC in the domain where the group resides for the bulk of operations and ensures we have a single static endpoint - yet get referrals all over the directory for groups that span domains and forests.

The customers in those situations demonstrated negligible performance differences as a result of this change - a few seconds change at best when we did measure command. It seemed like a solid trade off based on reliability.

I reviewed the post where you posted your domain structure. What you have matches the bulk of what I have for testing - and I have no issues specifying the UPN of my account.

In my case I have DOMAIN\MigrationAdmin. The on premises UPN is migrationadmin@home.local.. Now the office 365 UPN is completely difference. $cred = get-credential specifying migrationadmin@home.local and the password shows no problems in my lab executing either the get command for the forest running the script.

If you'd like you can use dlconversionv2@service.microsoft.com to share full logs or have an email conversation where information is not posted publicly.

dlconversionv2 and service dot microsoft dot com.

TIm

MassimoPascucci commented 2 years ago

Hello Tim,

I don't know the source of my authentication issues when using UPN, this is probably some quirk of my environment; anyway, that's only a minor nuisance.

What I'd like to note here is that the main issue, the one that forced you to look up the domain name for an object in order to query the correct domain controller, stems from the fact that you are not actually asking the Global Catalog service when running Get-AdObject; that requires connecting to TCP port 3268. Merely running Get-AdObject against a server which is a Global Catalog isn't enough: if you don't specifically ask for it, you'll still be talking with the standard Domain Controller service, which only knows about objects in the domain it manages.

I just personally tested this in a forest with two domains (both DCs are GCs):

$dn = 'CN=object,DC=domain1,DC=local'
$dc1 = 'dc1.domain1.local'
$dc2 = 'dc2.domain2.local'

Get-AdObject -Filter {distinguishedname -eq $dn} -Properties * -Server $dc1
Get-AdObject -Filter {distinguishedname -eq $dn} -Properties * -Server $dc2

The first one works, the second one returns no results; this is expected, because the second DC is in a different domain.

However, if we actually ask the Global Catalog service running on those servers...

Get-AdObject -Filter {distinguishedname -eq $dn} -Properties * -Server ($dc1 + ':3268')
Get-AdObject -Filter {distinguishedname -eq $dn} -Properties * -Server ($dc2 + ':3268')

...now both commands work, because a GC knows every object in the forest.

But you have to call it on the right port, otherwise you'll only talk with the DC.

Additional note: this is true even if you run the command on the server itself. Get-AdObject (or any other AD PowerShell command, really) will never automatically use the Global Catalog service, unless you specifically tell it to connect to TCP port 3268.

timmcmic commented 2 years ago

Which file are you referring to. I'm not sure I'm going to go back and change it at this point - but it's worth looking at and seeing what I had.

Looking through my notes - we didn't actually get NULL returns but rather ad call errors - but as you point out that could be because I was using just the DC call and not the GC call.

Tim

============================== Timothy J. McMichael Senior Support Escalation Engineer @.**@.> (980)-776-7465

Hours: Sunday - Wednesday 08:00 - 16:00 eastern time zone.

Manager: Tom Roughley @.**@.>)

Premier Support - (800)-936-3100 Broad Commercial Support - (800)-936-4900

==============================

From: Massimo Pascucci @.> Sent: Tuesday, May 10, 2022 4:51 PM To: timmcmic/DLConversionV2 @.> Cc: Tim McMichael @.>; Comment @.> Subject: Re: [timmcmic/DLConversionV2] Connection to Active Directory fails if the on-prem credentials are in UPN format (Issue #51)

Hello Tim,

I don't know the source of my authentication issues when using UPN, this is probably some quirk of my environment; anyway, that's only a minor nuisance.

What I'd like to note here is that the main issue, the one that forced you to look up the domain name for an object in order to query the correct domain controller, stems from the fact that you are not actually asking the Global Catalog service when running Get-AdObject; that requires connecting to TCP port 3268. Merely running Get-AdObject against a server which is a Global Catalog isn't enough: if you don't specifically ask for it, you'll still be talking with the standard Domain Controller service, which only knows about objects in the domain it manages.

I just personally tested this in a forest with two domains (both DCs are GCs):

$dn = 'CN=object,DC=domain1,DC=local'

$dc1 = 'dc1.domain1.local'

$dc2 = 'dc2.domain2.local'

Get-AdObject -Filter {distinguishedname -eq $dn} -Properties * -Server $dc1

Get-AdObject -Filter {distinguishedname -eq $dn} -Properties * -Server $dc2

The first one works, the second one returns no results; this is expected, because the second DC is in a different domain.

However, if we actually ask the Global Catalog service running on those servers...

Get-AdObject -Filter {distinguishedname -eq $dn} -Properties * -Server ($dc1 + ':3268')

Get-AdObject -Filter {distinguishedname -eq $dn} -Properties * -Server ($dc2 + ':3268')

...now both commands work, because a GC knows every object in the forest.

But you have to call it on the right port, otherwise you'll only talk with the DC.

Additional note: this is true even if you run the command on the server itself. Get-AdObject (or any other AD PowerShell command, really) will never automatically use the Global Catalog service, unless you specifically tell it to connect to TCP port 3268.

- Reply to this email directly, view it on GitHubhttps://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ftimmcmic%2FDLConversionV2%2Fissues%2F51%23issuecomment-1122847752&data=05%7C01%7Ctimmcmic%40microsoft.com%7Ca92b4b5c77ba4489d64608da32c6ccd7%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637878126668110004%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=epJfdJELr0fsqigOZkDM%2Bo6RpZFGEPdh950LFTeJNgI%3D&reserved=0, or unsubscribehttps://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FAKGTN6JAGHZZILOP7GAE7ZLVJLD3RANCNFSM5VKPRQ5Q&data=05%7C01%7Ctimmcmic%40microsoft.com%7Ca92b4b5c77ba4489d64608da32c6ccd7%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637878126668110004%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=oaEZ15MBdmT7FYcOzAZJE2qlSTjLf6AJJ1fXvJ03uy4%3D&reserved=0. You are receiving this because you commented.Message ID: @.**@.>>

MassimoPascucci commented 2 years ago

Which file are you referring to. I'm not sure I'm going to go back and change it at this point - but it's worth looking at and seeing what I had. Looking through my notes - we didn't actually get NULL returns but rather ad call errors - but as you point out that could be because I was using just the DC call and not the GC call.

You only do the "look up the domain and query its domain controller" in two lines of Get-NormalizedDN.ps1. I think you can just put -Server ($globalCatalogServer + ':3268') in both calls to Get-AdObject and get rid of the whole Get-ActiveDirectoryDomainName thing.

timmcmic commented 2 years ago

Ok let me look at it.

============================== Timothy J. McMichael Senior Support Escalation Engineer @.**@.> (980)-776-7465

Hours: Sunday – Wednesday 08:00 – 16:00 eastern time zone.

Manager: Tom Roughley @.**@.>)

Premier Support - (800)-936-3100 Broad Commercial Support - (800)-936-4900

==============================


From: Massimo Pascucci @.> Sent: Tuesday, May 10, 2022 5:25 PM To: timmcmic/DLConversionV2 @.> Cc: Tim McMichael @.>; Comment @.> Subject: Re: [timmcmic/DLConversionV2] Connection to Active Directory fails if the on-prem credentials are in UPN format (Issue #51)

Which file are you referring to. I'm not sure I'm going to go back and change it at this point - but it's worth looking at and seeing what I had. Looking through my notes - we didn't actually get NULL returns but rather ad call errors - but as you point out that could be because I was using just the DC call and not the GC call.

You only do the "look up the domain and query its domain controller" in two lines of Get-NormalizedDN.ps1. I think you can just put -Server ($globalCatalogServer + ':3268') in both calls to Get-AdObject and get rid of the whole Get-ActiveDirectoryDomainName thing.

— Reply to this email directly, view it on GitHubhttps://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ftimmcmic%2FDLConversionV2%2Fissues%2F51%23issuecomment-1122884024&data=05%7C01%7Ctimmcmic%40microsoft.com%7C3abdd79434584b55c3d008da32cba44c%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637878147468177283%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=r93n1p3CIiqvOCczJG8JeZlTuLMewj8GfWSXfszhqys%3D&reserved=0, or unsubscribehttps://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FAKGTN6MAQT52KXJZMBLN6BTVJLH5PANCNFSM5VKPRQ5Q&data=05%7C01%7Ctimmcmic%40microsoft.com%7C3abdd79434584b55c3d008da32cba44c%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637878147468177283%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=u5F76DT%2Bo6tD3MHr2OpsuvkHzN26BT9vnd7XIw0FwKg%3D&reserved=0. You are receiving this because you commented.Message ID: @.***>

timmcmic commented 2 years ago

So looking back - I went into October of last year and then February of this year.

You are correct. In my get-adobject call I neglected to specify any server or domain controller for the call. I'm going to see if I want to go back and revisit this - I know what I have no works well with no issues reported outside of this particular concern.

Tim

============================== Timothy J. McMichael Senior Support Escalation Engineer @.**@.> (980)-776-7465

Hours: Sunday - Wednesday 08:00 - 16:00 eastern time zone.

Manager: Tom Roughley @.**@.>)

Premier Support - (800)-936-3100 Broad Commercial Support - (800)-936-4900

==============================

From: Massimo Pascucci @.> Sent: Tuesday, May 10, 2022 5:26 PM To: timmcmic/DLConversionV2 @.> Cc: Tim McMichael @.>; Comment @.> Subject: Re: [timmcmic/DLConversionV2] Connection to Active Directory fails if the on-prem credentials are in UPN format (Issue #51)

Which file are you referring to. I'm not sure I'm going to go back and change it at this point - but it's worth looking at and seeing what I had. Looking through my notes - we didn't actually get NULL returns but rather ad call errors - but as you point out that could be because I was using just the DC call and not the GC call.

You only do the "look up the domain and query its domain controller" in two lines of Get-NormalizedDN.ps1. I think you can just put -Server ($globalCatalogServer + ':3268') in both calls to Get-AdObject and get rid of the whole Get-ActiveDirectoryDomainName thing.

- Reply to this email directly, view it on GitHubhttps://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ftimmcmic%2FDLConversionV2%2Fissues%2F51%23issuecomment-1122884024&data=05%7C01%7Ctimmcmic%40microsoft.com%7C3abdd79434584b55c3d008da32cba44c%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637878147468177283%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=r93n1p3CIiqvOCczJG8JeZlTuLMewj8GfWSXfszhqys%3D&reserved=0, or unsubscribehttps://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FAKGTN6MAQT52KXJZMBLN6BTVJLH5PANCNFSM5VKPRQ5Q&data=05%7C01%7Ctimmcmic%40microsoft.com%7C3abdd79434584b55c3d008da32cba44c%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637878147468177283%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=u5F76DT%2Bo6tD3MHr2OpsuvkHzN26BT9vnd7XIw0FwKg%3D&reserved=0. You are receiving this because you commented.Message ID: @.**@.>>