Azure AD Connect – “The specified domain does not exist or cannot be contacted” when adding an untrusted AD forest

I ran into a little issue while on site with a customer who required AAD Connect to be configured for use in a multi-forest environment with three forests. There was a forest trust between two of the forests, however the third forest did not have any trusts in place. Prior to implementing this solution, we ran up a test environment to do a run through and document the steps required for an implementation plan.

The test environment consisted of three Windows Server 2012 AD forests all at 2012 functional level – kloudy.net, kloudysky.net and kloudless.net and a single Office 365 tenant, MyHappyKloudTenant.onmicrosoft.com.

I installed the AAD Connect application into the kloudy.net forest, and proceeded to run through the wizard. All was well until I came to adding the untrusted forest, kloudless.net to the “configured directory” list. I could add the trusted forest (kloudysky.net) easily enough, however when I attempted to add kloudless.net I received the helpful little error message “The specified domain does not exist or cannot be contacted”.

“That’s interesting” I thought. I know I created the domain, so it exists. And I can ping the domain using the FQDN, so it’s definitely resolvable and contactable.

Specified domain does not exist

Authenticating to the forest with either the NetBIOS name format, KLOUDLESS\jason or the user principal name (UPN) format, jason@kloudless.net ended up with the same error “The specified domain does not exist or cannot be contacted”. After some poking around (and input from a helpful architect on site) a solution was found.

In the USERNAME field, use the FQDN of the authenticating domain instead of the NetBIOS name, so in my case it was kloudless.net\jason instead of KLOUDLESS\jason

Now, my colleagues have suggested that this issue may be an environmental one relating to name resolution, and I tend to agree.

In my case, each domain had its own integrated DNS with secondary zones for each of the other domain names, so kloudy.net had integrated DNS with secondary zones for kloudless.net and kloudysky.net. And so forth for each of the forests. Name resolution was functional to all domains from all domains.

Either way, in the case of my test environment, using the FQDN of the authenticating forest provides the outcome we were looking for, and I hope that if you happen to come across this issue, I’ve saved you a little bit of time.

Jason

Consideration for multi-forest synchronisation with a resource Exchange forest

Azure AD Connect has come a long way from the early days of DirSync, and multi-forest directory synchronisation is a great step forward, with the ability to synchronise an account forest and Exchange resource forest to Office 365 meeting the needs of many organisations.

Joining linked mailboxes

To provide synchronisation of an account forest and an Exchange resource forest AAD Connect matches accounts across forests using the same attribute used by Exchange, matching the linked mailbox account’s msExchMasterAccount attribute value with the objectSID value of the account in the other forest to join them. I’ve represented this flow here:

Linked mailbox matched with authentication account

This joining process is great for ensuring a single identity is synchronised to Azure AD where you have linked mailboxes going on and this works for most organisations out there.

Houston, we have a problem.

I’m going to draw out a scenario:

AAD Connect is installed and configured to synchronise two AD domains as shown above, and Exchange hybrid is configured with the on-premises Exchange Organisation in the resource forest. All the on-premises mailboxes have been moved to Exchange Online, and an Exchange 2013 server remains on-premises to provide administrative capability(when an account in Azure AD is synchronised from on-premises, the on-premises user object is the source of authority and so it is not possible to update values such proxy addresses in Azure AD).

Now. A new starry-eyed employee joins the organisation, at which point an account is created in the account forest, let’s call it newEmployee@account.local. As part of the on-boarding process, a linked mailbox would have been traditionally created in the resource domain as newEmployee@resource.local.

However, with Exchange Online in place, it doesn’t make sense to create a linked mailbox on-premises, only to move it to the cloud once it’s created. So the account in the resource domain is created as a remote mailbox, either through the Exchange 2013 control panel, or using the Exchange PowerShell cmdlet New-RemoteMailbox.

Then we wait for AAD Connect to work its magic…

…and two accounts appear in Office 365. One with a mailbox, and the other without. The new employee is also unable to connect to their new Exchange Online mailbox as access is denied. This obviously is not a good place to have arrived at!

Looking at the linked mailbox joining process in AAD Connect I discussed earlier, you may be able to see why this is occurring. A remote mailbox is not the same as a linked mailbox. As a result,  Azure AD Connect does not join the accounts newEmployee@account.local and newEmployee@resource.local with the result that two accounts are created in Azure AD.

What are the options?

There are two ways forward for you from here:

  1. Continue to create a linked mailbox on-premises and then move the on-premises linked mailbox to Exchange Online as a second step
  2. Modify the newEmployee@resource.local account through some ADSIEdit jiggery-pokery.

Now I’m going to stop here and recommend you stick with the first approach here. It requires an extra step, but so does the second option. Option 1 is also a solution which allows for account and mailbox creation using your existing administrative tools. Getting at AD object attributes, which used to be hidden in your management tools, is a lot easier these days. That doesn’t make it any safer to do without a good understanding of what it is you’re planning to do.

I was presented with an additional complication recently, where a customer had an incumbent vendor providing a managed service for email and charged extra for every mailbox created in the on-premises Exchange environment. Not wanting to give away more money than they needed to, the customer did not want to create a linked mailbox first when on-boarding new users.

Luckily the customer I was working with has FIM in place allowing them to populate AD user object attributes consistently and correctly (this ain’t something I’d be wanting to do manually).

Given AAD Connect matches accounts with the msExchMasterAccountSID and objectSID values, you can manually update newEmployee@resource.local so that it’s msExchMasterAccountSID equals the objectSID for newEmployee@account.local and all will be good right?

Well, the answer is no…

It turns out that AAD Connect checks that the AD object is a linked mailbox before it attempts to match its msExchMasterAccountSID value. This is done using the recipientTypeDetails attribute (a value of 2 designates a linked mailbox).

Account matching process

So, there are two attributes which need to be updated on the resource forest account, they are:

  1. msExchangeMasterAccountSID with the objectSID of the authentication account
  2. recipientTypeDetails with a value of 2

Once you’ve got these being updated you should be set.

Jason.

Office 365 PowerShell and Modularised code.

I’m going to preface this article by saying “This is not a guide to resolve a specific problem, but rather a discussion on how to work through a problem/issue which requires a script to resolve”.

Often when you first look at some of these problems they seem incredibly difficult and you can rapidly end up down a rabbit hole you didn’t intend to. (I was going to quote Yoda during the Dark Side cave scene in Empire Strikes Back, but decided against proving myself to be of a certain techie stereotype. Probably even knowing that the scene exists puts me in that category but what can you do? 🙂 )

There’s a certain company in Sydney who I’ve been working with quite closely on and off for the past year or so who have had some significant wins with Office 365. The biggest to date is the implementation of a new Intranet, built on SharePoint Online, which provided targeted information to different parts of the business and consolidated multiple legacy Intranets. It was a great bit of development work by our Kloud Application Development team.

As I’m an infrastructure guy, however (and quietly jealous that I don’t know how to use Azure Stream Analytics to do funky demonstrations like the Event Hubs MeetUp in October) I’m not going to go into that particular solution.

What I will cover through is the slight issue we came across when starting the Office 365 adventure with the Intranet. There’s a quirky little behaviour which needs to be addressed if you don’t want your service desk answering calls about why “Outlook” doesn’t work.

If you assign an Enterprise (E) or Kiosk (K) license to a person, with all Office 365 services enabled (the default behaviour when you assign a license) and said person then opens up their brand new sparkly Intranet, they will see an Office 365 ribbon across the top of the page, you know the one? If you have an E license assigned, with all services enabled, it will looks a bit like this:

Office 365 ribbon

So what happens when I click on the Outlook link and my mailbox is on-premises? Well, you will see a sad message telling you that something went wrong while accessing your mailbox.

I haz the sadz

The “More details…” URL doesn’t really help the end user much either and so the service desk call is made. Two interesting things I’ve learnt about service desk calls:

  1. The IT department doesn’t like receiving them. Service desk call == Effort required to fix an incident/problem == IT revenue)
  2. The business doesn’t like making them. Think of IT as the equivalent of domestic plumbing: When it all works you don’t notice and get on with your day. When it stops working, it can get a little smelly, which tends to put you in a bad mood to start with. Then you have to wait for the guy to come out and figure out what’s wrong, and fix it. All the while using jargon that makes no sense at all and was undoubtedly created to hoodwink you.

But I digress.

Outlook in the Office 365 ribbon – How do we get rid of it? The answer is pretty simple, and you probably already see where I’m coming from. You need to disable the Exchange Online service. Joel Neff wrote a blog about this a while back on licensing with PowerShell and it’s pretty much what we did to ensure that Exchange Online was disabled when assigning licenses to staff.

This whole Outlook thing still presented me with a problem though. While the company had been assigning licenses with Exchange Online disabled, it needed to be re-enabled when the mailbox was moved from the on-premises Exchange environment to Exchange Online. And we had the following issues/constraints to deal with:

  • We needed to move a minimum of 300 mailboxes per week and the IT engineer wasn’t (understandably) keen on having to click in multiple locations to change licenses and then initiate a move (or vice versa)
  • Not all accounts had Exchange disabled, some were already enabled due to what I will call an “organic pilot”
  • There were a few other license options which may, or may not, have been enabled, depending on the above mentioned pilot
  • We were dealing with K1, E1 and E3 licenses
  • SharePoint Online was live and hosting the Intranet, and I didn’t particularly want to be responsible for a disruption to a highly visible service.

So I bashed out a PowerShell script! The thing with PowerShell scripts is they can become very complicated, very quickly. Further, if you end up writing a single block of script, it’s not particularly re-usable later on. This is why, when I write scripts, I take a letter from my Developer friend’s book, and take the approach of breaking the problem down into discrete (re-usable) processes. Think of it as a High Level Design for the script.

I started with this:
Flow Diagram

Luckily I’ve already got a function for connecting to Exchange Online and O365 from my PowerShell profile, so they’re covered. The move mailbox bit is pretty straight forward too, the New-MoveRequest Cmdlet is all I need, something like:

New-MoveRequest `
 -Identity $upn
 -RemoteHostName $onPremEWS `
 -SuspendWhenReadyToComplete `
 -BatchName $batchName `
 -Remote `
 -RemoteCredential $ExchCred `
 -TargetDeliveryDomain $targetDeliveryDomain `
 -BadItemLimit $badItemCount `

There’s no particular reason or benefit to make this Cmdlet into a function, so it’ll get thrown in the main part of the script somewhere or other. The one comment I would make though is: make sure you define $batchName at the top of your script, before running through each user. Otherwise you’ll potentially have a new batch name for each mailbox move request which, take it from me, is utterly useless.

I’m now left with two processes to figure out: 1) Getting the mailbox list; 2) Assign the Exchange Online (EOL) service

Getting the mailbox list

To get the mailbox list to move I decided that the data being imported needed to be in CSV format. Largely because it’s easier for BAs and PMs to collect and massage business data in Excel, which is easily exportable as a CSV file, and if there’s a someone else willing to do some of the leg work I generally feel inclined to acquiesce!

As per our (and Microsoft’s) recommendation, the company had updated their on-premises AD UPNs to match their email addresses so all that was really needed in the CSV file was the email address of the mailboxes to be moved. The mail address is unique, so no chance of getting the wrong mailbox, and it matches the UPN, also unique and used to find Azure AD accounts.

There are a few approaches to consuming this information, you could:

  • Use the Import-CSV Cmdlet
  • Create a parameter for the script (good for one or two SMTP addresses, but not great for a bulk import
  • Build the script to, once loaded, read the information through the pipeline
  • Use a combination of the above
  • Some other way I haven’t thought of.

The easiest by far appears to be to import the addresses in through use of Import-CSV. So if we just use this Cmdlet at the top of the script pointing it to a predefined location, we’re covered. Some of the other ways may be more appropriate for your situation, but for me, I like easy.

Moving on then.

Assign the EOL Service

Assigning the EOL license is difficult, but not impossible, with Joel’s Blog as a guide, you can put together a function which outputs the particular license options you want and then apply it to the user account.

In my particular case though some accounts had more than just the Exchange Online service disabled, and were a mix of E1, E3 and K1 licenses. I needed to build a license options object which was unique to the individual mailbox, enabling Exchange and leaving everything else untouched. Ahh, the real world, sooo much more problematic than what I was told when I left school…

To sort this conundrum out required some thinking and I came up with the following. Breaking out the original process “Assign EOL License” I ended up with:

Flow diagram

If after interrogating the Azure AD user object licence, we find that Exchange is already enabled. How do we figure out if it’s disabled? We interrogate the $MSOLUser.Licenses.ServiceStatus. This took me forever to figure out how to do. The problem is that ServiceStatus is an array of objects, it formats beautifully on screen but getting at what I wanted was a different matter.

If you ever need to do this, I’ll save you the time. I ended up with the following:

$disabledPlans = $msolUser.Licenses.ServiceStatus | where {(($_. provisioningStatus -eq "disabled") -and ($_.ServicePlan.ServiceName -like "*EXCHANGE*"))}

What I’m doing here is passing each object in the Licenses.ServiceStatus attribute to a Where-Object cmdlet which does a logic test on the object. If the logic test is true then $disabled will equal that object. If no object matches the logic test, then $disabled will be $null.

To put the logic test together, we’re looking for a disabled service ($_.provisioningStatus -eq “disabled”) but specifically the Exchange service. Remembering that each different license SKU will have a different ServiceName (e.g. EXCHANGE_S_DESKLESS for K1 licenses and EXCHANGE_S_STANDARD for E1 licenses) the approach I took to catch all different Exchange ServiceNames (and allow for future ones) was to use the logic test ($_.ServicePlan.ServiceName -like “*EXCHANGE*”).

If $disabled is equal to $null then we’ll make the Assign EOL License function return the $null value. At the next process, building the license object, if $null is returned, we don’t need a new license object, because Exchange is already enabled.

Otherwise we have more work to do to build a new license, and move onto the “Find the existing disabled services” process. As the output will be used to form the new license object it needs to not include the Exchange service. We just need to tweak the logic test above to get what we want. Something like ($_.ServicePlan.ServiceName -notlike “*EXCHANGE*”).

And we end up with:

$disabledPlans = ($msolUser.Licenses.ServiceStatus | where {(($_.provisioningStatus -eq "disabled") -and ($_.ServicePlan.ServiceName <strong>-notlike</strong> "*EXCHANGE*"))})

Going back to Joel’s blog there’s now enough information to create a specific license object and assign it to the mailbox during the mailbox move process!

Now the basics are in place, I’d think about adding a few extra useful functions like error handling and logging 🙂

PowerShell and Office 365

While there is a plethora of articles written about PowerShell, Hey, Scripting Guy!, where I regularly seem to end up at while trying to figure out how to do something new/different, I’m often asked about PowerShell when I’m working with customers. You see, if you’re like me, you’ve spent most of your IT life working in a Graphical User Interface (GUI). It’s comfortable, it’s often intuitive and you can click around ’till you find what you’re looking for if you’re not entirely sure. While UNIX and Networking Admins may have been laughing at us all this time, we secretly knew that the GUI made our lives easier than theirs, as they scrolled through man pages billions of lines long. The problem now though, is there’s a bunch of stuff to do with the Office 365 platform which can only be done with PowerShell. And PowerShell is a Command Line Interface! What’s with that? Why is Microsoft making our lives as hard as the UNIX guy?

These are both very good questions in my opinion, and I should know as I just asked them. Sure reaching back into the dim dark ages there’ve been CLI tools in the Windows world since, well since Windows. Batch scripts come to mind. Which by the way I hated having to do anything with. I found batch scripting confusing and (a lot) intimidating quite frankly. I digress. There’re some day to day tasks which administrators in companies using Office 365 have to do in PowerShell, and guys like me, who’ve lived their lives in GUI land are a little bit confronted by the blue box with white writing, you can’t just click around to find stuff.

There are some things we can do and remember however, which will make our PowerShell experience easier and less of a headache. The first is the PowerShell profile, which is discussed in some detail by The Scripting Guys here, you’ll also find a lot more by banging in “PowerShell profile” into Google. I am (if I haven’t said this before) first and foremost, a lazy individual. I don’t like doing things more than once and I find typing things out tedious, yes I see the irony. As a result of my innate laziness, one of the first things I did when I was told I had to use PowerShell, was look at this profile thing.

Just a quick recap on what the Internet has taught me about PowerShell profiles:

  1. They exist
  2. Their path is stored in a variable called $profile whenever you open a shell. (something like C:\Users\Jason\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1 in my case)
  3. They can store functions.
  4. You need to create the Microsoft.PowerShell_profile.ps1 file yourself.

Why is this so neat? You can store functions! Repeatable bits of code you seem to be continually typing into that blasted blue box! Think the following:

  1. Loading Modules and PSSnapins (think Add-PSSnapIn Microsoft.Exchange.Management.PowerShell.E2010 for those Exchange Admins out there)
  2. Creating a remote session into Exchange Online
  3. Changing federated domain names for a user’s UPN

BTW, since Windows 8 and Windows Server 2012, modules load automatically when you start to type a cmdlet from the shell (brilliance)!

Some ideas for a PowerShell profile:

$myFunctions = "Load-Module","Connect-O365","Connect-EOL"

# $myFunctions

Function Load-MyModule ($modName)
{
    if (-not(Get-Module -Name $modName))
    {
       if (Get-Module -ListAvailable | ?{$_.name -eq $modName})
       {
           Import-Module -Name $modName
           Write-Host "$modName has been loaded successfully" -ForegroundColor White
       }
       else
       {
           Write-Host "It's not going to work fella. $modName is not installed" -ForegroundColor Red
       }
    }
}

Function Connect-O365
{
    # This seems a bit redundant. It just loads the MSOnline module first.
    Load-Module "MSOnline"
    Try
    {
        Connect-MsolService -Credential (Get-Credential)
    }
    Catch
    {
        Write-Host "Couldn't connect to Office 365 Azure AD. Please speak to your Administrator." -ForegroundColor Red
    }
}

Function Connect-EOL
{
    $session = New-PSSession -ConfigurationName Microsoft.Exchange `
                             -ConnectionUri "https://ps.outlook.com/powershell/" `
                             -Credential (Get-Credential) `
                             -Authentication "Basic" `
                             –AllowRedirection

     Import-PSSession $session –AllowClobber
}

It’s not uncommon to come across scripts on the Internet using swizzle sticks, whizz bangers and a bunch of other stuff which is tricky to figure out. The thing is though, for your everyday use? It doesn’t always have to be complicated. While what you see above may seem basic and not particularly robust functions, they simplify stuff. The thing that scripts have always had over the GUI? They allow repeatable tasks to be completed over and over and over and over again without the risk of RSI. Often putting them together in the first place will take a serious amount of time (especially when starting out) but the investment is often worth it.

I hope this get you thinking about what else you may want to do with the blue box with white writing. Next time I’ll give you my take on renaming UPNs with federated domains.

I Keep Getting Prompted to Authenticate in SharePoint Online!

Every once in a while I come across a problem which is vexing and irritating and equally, an absolute joy when it is finally resolved.

The Scene

This particular issue had been on-going for some time with one of my customers with reports coming in from various people saying that they were being prompted to authenticate when opening an Office document in SharePoint Online. “I’ve already logged in so why do I keep getting these prompts?!” – It’s a fair question, especially since the organisation had implemented AD FS to reduce the frequency of authentication dialogue boxes. It seemed that Microsoft was not only being overprotective but overbearing as well. Here’s the dialogue I’m talking about by the way:

Figure 1 – Overprotective

Along with this issue, the customer had started to map network drives to SharePoint. Let’s face it, it’s easier to manage files in a folder structure than in the SPO web interface, and with improvements over the last few years with SharePoint mapping network drives actually works, or at least is should work. While it was working some of the time, there were reports of access issues to these mapped drives, and a different dialogue box which while uglier, on first glance appeared more promising from a technical perspective. A recommendation for a fix and a reference to a KB article!

Figure 2 – Ugly but useful

There are a plethora of articles, wikis, forum posts, etc out there which all talk about adding your SharePoint Online sites to your browser’s Trusted Sites list. The referenced KB article covers it off nicely, and I’ve added the link in case you’ve not come across it, here.

In my particular case the SharePoint Online domains were all happily existing in the IE Trusted Sites list (I checked about 30 times during my investigations)

I’ve mentioned that AD FS is in play, further a redirection URL http://Intranet.KloudySky.com.au is used with a Smart Link in this particular environment to provide a more seamless login experience. Until very recently you were not able to customise the Office 365 Portal page, https://login.microsoftonline.com. Check out this article for more info on how to brand the Sign-In Page with company branding.

While you can now brand the Sign-In page to your heart’s content (if you have an Azure subscription along with your O365 subscription), you’ll need to type in your UPN at least once (normally not an experience IT wants to establish for a new Intranet rollout), and so smart links are not yet dead.

There’s a couple of good resources for creating SmartLinks, including one written by a Kloudy here and a good Office365 community article here which discusses some of the components of the link.

The Solution

I’ve set the scene, and for most of you you’ve probably bypassed everything above and come straight to this point. For those of you who took the slow route of reading from the top; Thanks for sticking around!

The problem I was seeing was due to a very simple issue really. You need to check the check box which says “Keep me signed in”. It even says so in the ugly helpful dialogue box above. The thing is, if you’re using AD FS and SmartLinks you don’t actually hit the Office 365 login page and so don’t get the opportunity to sign in. We need to pass the “Keep me signed in” option to the AD FS server somehow, and the only way to do that is to encode it in the URL.

How do we do that? As it turns out there’s a way!

At the end of the SmartLink is the LoginOptions attribute.

LoginOption=3 will pass the “Keep me signed in” option as off (Not checked)

LoginOption=1 will pass the “Keep me signed in” option as on (Checked)

Don’t keep me signed in. Boo!!!
https://myadfs.Kloudysky.com.au/adfs/ls/?wa=wsignin1.0&wtrealm=urn:federation:MicrosoftOnline&wctx=%5BwctxValue%5D%26wreply%3Dhttps%253A%252F%252FKloudySky%252Esharepoint%252Ecom%252F%255Fforms%252Fdefault%252Easpx%26lc%3D1033%26id%3D123456%26%26LoginOptions%3D3

Keep me signed in. Yay!!!
https://myadfs.Kloudysky.com.au/adfs/ls/?wa=wsignin1.0&wtrealm=urn:federation:MicrosoftOnline&wctx=%5BwctxValue%5D%26wreply%3Dhttps%253A%252F%252FKloudySky%252Esharepoint%252Ecom%252F%255Fforms%252Fdefault%252Easpx%26lc%3D1033%26id%3D123456%26%26LoginOptions%3D1

I only made this change on the Internal SmartLinks by the way. I’ve left the SmartLinks published to the Internet with LoginOptions=3, we don’t really want people on untrusted PCs and devices to remain logged into Office 365 services.

 

I’d like to make a big thankyou to Carolyn at Microsoft PSS for helping me resolve this issue.