• Office 365–With Mac OS X Lion, Microsoft Office 2011 and Lync 2011 for Mac

    Many of the customers I work with are currently making their way through an Office 365 technical pilot that needs to include Mac OS X machines as well as various versions of Windows.  The Windows stuff seems fairly well documented and since we now have a GA release of Lync 2011 for Mac OS X I thought I would write a post about using OS X with Office 365…

    Note:  Most of this is documented on the following page, however it does not include Lync or any screenshots..

    Software requirements for Mac OS X and Office 365

    There are some things that you need to know before rushing out to connect your Max OS X machines to Office 365.  Firstly you will need a version of Outlook that supports Exchange Web Services (EWS).  Older versions of Outlook for Mac used WebDAV which is not provided in Exchange Server 2010 and therefore is also not available in Office 365.  Plus there are some minimum versions of Mac OS X and Browsers that are supported…

    • Microsoft Office for Mac 2011 Service Pack 1+
    • Microsoft Lync for Mac 2011
    • Microsoft Office for Mac 2008 12.2.9+
    • Microsoft Entourage 2008 for Mac, Web Services Edition
    • Mac OS X 10.5.8+
    • Safari 4 or 5
    • Firefox 3.5 or 4
    • Chrome 3

    Note: If you are using an internal CA for any of your Exchange or ADFS servers you must import the root CA certificate onto your Mac before working through these steps…

    For the purposes of this article I will concentrate on Office 2011 since it represents the best end user experience and it is also the version I have the most experience with (and happen to have handy!).

    Connecting to Office 365 Web Portal

    OK, so this bit isn't very exciting however it is always my first step since it proves that my Office 365 account credentials are good and that the Mac has connectivity to the Office 365 service and ADFS.

    1. Open your browser (In this example I am using Safari 5)
    2. Navigate to https://portal.microsoftonline.com
    3. Login with your Office 365 user credentials
    4. Click on the Outlook link to connect to Outlook Web Access
    5. Select the Language and Time Zone preferences (if prompted)

    image

    image

    image

    Assuming everything went well, you should now be looking at your Office 365 users Outlook Web Access page via OS X Safari!  For some of my customers this is actually “good enough”, however for the large majority they need the rich experience provided by Outlook and Lync on their Mac… so we need to continue on Smile

    Connecting Outlook 2011 for Mac to Office 365

    Ok, so we have already connected to OWA via Safari so the next thing to do is configure Outlook.  When you start Outlook for Mac 2011 the first thing it will ask you to do is to Add Account

    • Click the checkbox to make Outlook the default application for e-mail, calendar and contacts then click Add Account

    image

    • Once the Add an Account page is displayed, click on Exchange Account
    • Fill in your account details on the Exchange Account Information Page, ensure that Configure Automatically is checked and then click on Add Account

    image

    • Outlook will warn you that your AutoDiscover request has been redirected to a different server
    • Ensure that the Always use my response for this server checkbox is checked and click on Allow

    image

    • At this point Outlook will reconfigure itself to connect to your Office 365 mailbox by using the data from AutoDiscover
    • I typically also change the Account Description on the next page to show that it is an Office 365 Account

    image

    • Close the Accounts Window and Outlook should show as connected and begin synchronising your mailbox content…

    image

    Connecting Lync 2011 for Mac to Office 365

    I have to admit that despite being a Microsoft Employee I am also a Mac user (occasionally anyway) and for me Lync was the missing piece of the puzzle for making a Mac a usable experience.

    Anyway, enough of that lets move on to connecting Lync…

    • Start Lync for Mac 2011
    • The first thing that Lync will ask is to set it as the default application for presence – if you want presence information then select Use Lync
    • The next screen will be the Lync for Mac 2011 login screen
    • Click on the Advanced icon at the bottom

    image

    • Click on the Advanced button at the bottom of the Lync client
    • Set Internal Server name to sipdir.online.lync.com:443
    • Set External Server name to sipdir.online.lync.com:443
    • Click OK

    image

    • Enter your login account details and password
    • Check the Remember my password checkbox and click Sign In

    image

    • If everything went to plan, you should now see your Microsoft Lync for Mac 2011 client open up and show as connected!
    • I suspect this isn't actually that exciting to everyone, but I (and some of my customers) have been waiting for nearly a year to get this far!

    image

    The screenshot below shows my OS X Lion desktop connected to Microsoft Office 365 via a federated Active Directory account… and who says Microsoft and Apple cant work together!

    image

    Conclusion

    As a regular Mac and Windows user it is vital to me that my systems are able to collaborate and share data effectively.  It is also vital that I am able to communicate and collaborate effectively with my colleagues running Windows or Mac machines.  I have to say that prior to having Lync my Mac experience was definitely lacking… however now I can connect Outlook and Lync to Office 365 I am able to function just as effectively on my Mac as I am on my Windows 7 machine.  Being able to join conference calls, share my desktop etc even when I am on my Mac is a huge improvement to my productivity…

    Having worked with a few customers who have a Mac OS X community to support I have to say that connecting them to Office 365 has been relatively painless…  in fact it is arguably easier to connect a Mac running Office 2011 to Office 365 than Windows; largely since OS X doesn't require any patch updates or the Windows Live Sign In Assistant to connect reliably.  The biggest problem area that I have seen is that organisations who have chosen to use their internal CA to issue certificates for their internal Exchange and ADFS services, must remember to import the root CA certificate on every new Mac that is deployed… failure to do this leaves the machine unable to authenticate to ADFS and AutoDiscover failing to configure Outlook.

    Overall though I have to say that this is great work from both the Office 365 and Office 2011 for Mac teams…!

  • Office 365 - Non-Federated Identity, Password never expires

    The Microsoft Online Services Module allows you manage your tenant directly and in some cases change settings you can’t change in GUI (note this can only be achieved if you’re managing accounts that have been created in the tenant e.g. not created using Dirsync/ADFS).  To access Remote PowerShell to the Service Portal you will need to install the following prerequisites:-

    • Operating system: Use Windows 7 or Windows Server 2008 R2.
    • Microsoft .NET Framework: You must turn on the Microsoft .NET Framework 3.51 feature in Windows 7 or Windows Server 2008 R2.
    • Windows PowerShell 2.0 and AD FS 2.0: In order to run the cmdlets to set up single sign-on, you must turn on the Windows PowerShell 2.0 feature, and you must have administrator privileges on the AD FS 2.0 server. We recommend that you use remote access to the AD FS 2.0 server when you run the cmdlets; to do this you must use Windows PowerShell remoting.
    • All Office 365 software updates: From the Office 365 downloads page, install the required updates. To access the Office 365 downloads page, sign in to the Office 365 portal, and, under Resources, click Downloads. These updates are required because the features in Office 365 will not work properly without the appropriate versions of operating systems, browsers, and software.
    • Sign-In Assistant

    Download the Microsoft Online Services Module

    The Microsoft Online Services Module for Windows PowerShell is a download that comes with Office 365. This tool installs a set of cmdlets to Windows PowerShell (you run those cmdlets to set up single sign-on for Office 365).

    In this case i want stop user(s) from being prompted to change their password. In order to do this you can run the Microsoft Online Services Module from the shortcut menu and connect to your Office 365 Tenant by running the following commands:-

    • Connect-MSOLService –Credential $MSOLCred –Verbose

    You will need to enter your tenant credentials, once you have done this you can check what the current settings are by running

    • get-MsolUser –UserPrincipalName <UPNName> | fl

    Note that PasswordNeverExpires is set to false, you can then change the setting for either that individual user or all users

    • All users - Get-MsolUser | Set-MsolUser –PasswordNeverExpires $True
    • Individual user - Set-msoluser –UserPrincipalName <UPNName> -PasswordNeverExpires $True

    Run the this command again to ensure that the settings have taken effect and that PasswordNeverExpires is set to True

    • get-MsolUser –UserPrincipalName <UPNName> | fl

    Also if you don’t want the user t be prompted when they login you can run the following command

    • Set-MsolUserPassword –userPrincipalName <UPNName> -NewPassword "P@ssword" -ForceChangePassword $false

    If you want to know a list of commands run

    • get-command –module msonline

    This is the output (so as you can see its a pretty powerful tool, for example you can automate the provisioning of licenses for example):-

    Add-MsolGroupMember

    Add-MsolRoleMember

    Confirm-MsolDomain

    Connect-MsolService

    Convert-MsolDomainToFederated

    Convert-MsolDomainToStandard

    Convert-MsolFederatedUser

    Get-MsolAccountSku

    Get-MsolCompanyInformation

    Get-MsolContact

    Get-MsolDomain

    Get-MsolDomainFederationSett.

    Get-MsolDomainVerificationDns

    Get-MsolFederationProperty

    Get-MsolGroup

    Get-MsolGroupMember

    Get-MsolPartnerContract

    Get-MsolPartnerInformation

    Get-MsolRole

    Get-MsolRoleMember

    Get-MsolSubscription

    Get-MsolUser

    Get-MsolUserRole

    New-MsolDomain

    New-MsolFederatedDomain

    New-MsolGroup

    New-MsolLicenseOptions

    New-MsolUser

    Remove-MsolContact

    Remove-MsolDomain

    Remove-MsolFederatedDomain

    Remove-MsolGroup

    Remove-MsolGroupMember

    Remove-MsolRoleMember

    Remove-MsolUser

    Set-MsolADFSContext

    Set-MsolCompanyContactInform.

    Set-MsolCompanySettings

    Set-MsolDirSyncEnabled

    Set-MsolDomain

    Set-MsolDomainAuthentication

    Set-MsolDomainFederationSett.

    Set-MsolGroup

    Set-MsolPartnerInformation

    Set-MsolUser

    Set-MsolUserLicense

    Set-MsolUserPassword

    Set-MsolUserPrincipalName

    Update-MsolFederatedDomain

     

    Written by Daniel Kenyon-Smith

  • Exchange Server 2010 Cross Forest Delegation

    This has been an interesting bit of work for me.  I have been working with a customer who really needed to provide their users with the ability to manage calendars across different Exchange organisations.  When they initially presented this requirement to me, my first thought was that we would be able to provide cross-forest availability sharing but that cross-forest delegation was not going to be possible…

    So, as with most projects like this I began by asking my colleagues and quickly discovered that some thought it was possible and some thought it wasn't.  This at least gave me the incentive to dig a little deeper to determine what we could and couldn't achieve.  This digging discovered a few articles about ILM FP1 SP1 and FIM that showed a check box called “support cross-forest delegation (Exchange 2007 or 2010 only)”…

    image

    A little more research suggested that given a few pre-requisites it should be possible to achieve cross-forest delegation for Outlook users.  This article will briefly go through the required steps and link to further information to assist with configuration…

    Prerequisite requirements

    To get cross-forest delegation to work the following prerequisites must be met…

    • Forest Trust between Forests
    • Cross-Forest Availability Configured
    • GALSYNC configured with either ILM FP1 SP1 or FIM 2010 (or manual cross-forest mail contacts created)
    • Exchange Server 2007 SP1+
    • Outlook 2007 SP1+

     

    Forest Trust

    Before we continue we need to establish a forest trust between the forests…

    Cross-Forest Availability

    The next step is to establish cross-forest availability.  This provides users availability data between exchange organisations.

    Note:  The documentation in TechNet regarding cross-forest availability is particularly difficult to follow.  Where the examples contain reference to the “Client Access Servers” group you must either create this group and add in your CAS servers or simply use “Exchange Servers” instead.  Additionally the steps assume that your CAS servers are using public certificates that are trusted – if you are using an internal PKI CA you must ensure that all of your CAS servers trust the root CA.

    Here is my short-cut version of that guidance…

    Run In the source forest

    • Add-AvailabilityAddressSpace -ForestName "targetforest.com" -AccessMethod PerUserFB -UseServiceAccount $true

    Run In the target forest

    • Get-ClientAccessServer | Add-AdPermission -AccessRights ExtendedRight -ExtendedRights "ms-exch-epi-token-serialization" -User "Source Forest\Exchange Servers"

    Note: You must perform these steps in both forests for a 2-way configuration

    Configuring cross-forest Autodiscover

    • $a = Get-Credential <Enter Administrator credentials in the remote forest when prompted>
    • Export-AutoDiscoverConfig -DomainController <Local GC> -TargetForestDomainController <Target GC> -TargetForestCredential $a -MultipleExchangeDeployments $true

    So, by the time we get here it should be possible to lookup availability data for a user in the other forest.

    GALSYNC

    This is where the secret sauce happens for cross-forest delegation.  Basically we are going to use FIM in this example to read in mailbox objects from each forest and create contacts in the target forest to build a common GAL for both Exchange Organisations. 

    The official guidance for configuring this is available here, however I have included my steps as well below

    The steps I follow are as follows…

    Note:  I generally create an OU in each forest called Contacts to receive contacts from FIM.  These steps assume that you have created this OU already.

    1. Open Synchronisation Service Manager (FIM)
    2. Click on Management Agents
    3. On the Actions Menu, click Create
    4. Select Active Directory global address list (GAL) from the Management Agent drop down
    5. Enter a name for this MA and click Next
    6. Enter the forest name and credentials that this MA will retrieve information for and click next
    7. In Select directory partitions enable the checkbox for the root of the forest
    8. Click on Containers
    9. Deselect all OU’s and manually select OU’s that contain mailboxes + ensure that the Contacts OU is checked and click ok
    10. Click Next
    11. Click Target, Click Container and Check the Contacts OU and click Ok
    12. Click Source, Add Containers and check all OU’s that contain mailboxes, then click OK
    13. Under Exchange configuration, click Edit, Add in the SMTP namespace you want the contacts to use that are created for this forest, click Add and finally OK
    14. Check Route mail through this forest for all contacts created from contacts in this forest
    15. Check Support cross-forest delegation (Exchange 2007 or 2010 only)
    16. Click Next
    17. Click Next until the Configure Extensions page is displayed
    18. In the Exchange 2010 RPS URI: Enter http://<CAS Server>/Powershell
    19. Click Finish

    Repeat these steps for all forests.

    Note:  By default ILM and FIM have provisioning disabled, to enable provisioning click on Tools, Options and check the Enable Provisioning Rules Extension checkbox.

    Once all MA’s have been created run the following profiles (Right click on the MA, select RUN)

    1. Full Import (Staging Only)
    2. Full Synchronization
    3. Export
    4. Delta Import

    Finally check the contacts OU in each forest to ensure that FIM has populated it with contacts from the remote organisation.  If there are problems, the first thing to do is check the event logs on the FIM server to begin troubleshooting…

    User Experience

    By this point you should now have a common global address list amongst your Exchange Organisations and if you look into the Contacts OU it should be populated with contacts from the remote organisations.  If you look in the Exchange Management Console you should see that the contacts have been created as a Recipient Type of Cross-forest mail contact.  This recipient type means that you can use this contact to assign delegate permissions.

    image

    In my lab I have two Exchange Organisations in two Forests

    • org4.lab (org4user1)
    • org5.lab (org5user1)

    As a test I am going to delegate calendar editor permissions over org4user1’s to remote user org5user1.  I did this simply by opening the delegates tab on org4user1’s mailbox and tagged in the contact for Org5user1. 

    image

    I then logged on to the org5user1’s mailbox and attempted to open org4user1’s calendar.  This worked as expected, so I then attempted to make changes to the shared calendar, again which worked as expected! result Smile

    image

    Manually Creating a cross-forest mail contact

    So this is an interesting exercise (interesting is relative here obviously, but lets go with it for now!).  My current customer does not have FIM or ILM deployed to synchronise contacts between forests, however they wanted to enable cross forest delegation for a few users.  We have a project planned to deploy FIM to solve this issue strategically but due to the importance of some of the users affected they really pushed me to come up with a temporary solution for cross-forest delegation.

    My solution to this was to perform all of the configuration for cross-forest availability and then to manually create the cross-forest mail contacts in the target forest.  The challenge of course was how to create a cross-forest mail contact!

    After some investigation the following attributes looked to be of interest…

    • mAPIRecipient = TRUE
    • msExchMasterAccountSID = objectSID from Mailbox
    • msExchOriginatingForest = Target Forest FQDN
    • msExchRecipientDisplayType = –1073741818
    • msExchRecipientTypeDetails = 32768
    • proxyAddresses = X500: + LegacyExchangeDN from Mailbox; existing addresses

    Here is an example…

    Source Mailbox Attributes for Org4User1@org4.lab

    • legacyExchangeDN: /o=Org4/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients/cn=Org 4 User 1;
    • mail: Org4User1@org4.lab;
    • mailNickname: Org4User1;
    • objectSid: S-1-5-21-1575148580-663765585-2685387708-1129;

    Cross-forest mail contact attributes for Org4User1@org4.lab

    • legacyExchangeDN: /o=Org5/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients/cn=Org 4 User 1;
    • mail: Org4User1@org4.lab;
    • mailNickname: Org4User1;
    • mAPIRecipient: TRUE;
    • msExchMasterAccountSid: S-1-5-21-1575148580-663765585-2685387708-1129;
    • msExchOriginatingForest: org4.lab;
    • msExchRecipientDisplayType: -1073741818;
    • msExchRecipientTypeDetails: 32768;
    • proxyAddresses (2): X500:/o=Org4/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients/cn=Org 4 User 1; SMTP:Org4User1@org4.lab;
    • targetAddress: SMTP:Org4User1@org4.lab;

     

    Conclusion for Cross Forest Delegation in Exchange Server

    I must admit that I did feel like I had missed a day at school when I first started this.  For me this is a huge feature area that is pretty poorly documented and even the fact that you can do cross-forest delegation is relegated to a one liner in TechNet under the cross forest implementation section.

    However, the user experience is absolutely great once this is configured and in fact it is difficult to tell which organisation a user is from simply by the features you have enabled, i.e it doesn't really matter to a user where the people are that they are collaborating with, everything just works.

    This functionality was first made available in ILM FP1 SP1 and works with Exchange 2007 SP1 and Exchange 2010.  The clients need to be Outlook 2007 or above.

  • Automating Jetstress…

    One of the things I like about Jetstress is that it tends to identify failing or failed components before the servers go live.  Its not all about how many IOPS a storage array can provide, sometimes its just as important to prove the stability of the infrastructure and not just its peak performance.

    So, we all know that Jetstress is a great tool.  It helps us prove our storage design and is also really good for finding problems in a storage deployment before it goes live.  The problem is that it takes a while to initialize and run – and quite often on a large project different people will configure the test slightly differently, even with clear documentation.

    On my current project I was faced with the requirement of deploying and therefore jetstress testing,  20 CCR clusters, which meant 40 jetstress tests!.  Along with all of the other deployment “stuff” this wasn't going to leave me with much time…. not to mention that setting up jetstress and watching it run for a few hours is like watching paint dry…

    This is where I decided I would look at automating the jetstress process from end to end.  I already had a pretty solid automated build process (I will blog about this in the next few weeks), so I just needed to tag in the jetstress bits prior to installing Exchange and I would be all set…

    Jetstress process outline

    Before I could begin automating things I needed to determine exactly what I needed to automate…

    1. Create Jetstress directories
    2. Install Jetstress
    3. Copy over ESE DLL files
    4. Start Jetstress to register the DLL files
    5. Close Jetstress
    6. Start Jetstress Again
    7. Configure test
    8. Initialize databases
    9. Run Test
    10. Copy output files centrally
    11. Remove test databases
    12. Uninstall jetstress

    Pre-Requisites

    In addition to the actual functions, I also had some pre-requisites…

    1. Disks need to be ready
    2. Need to have a copy of the intended ESE Dll’s
    3. Need to have exported the Jetstress XML config file from the GUI
    4. Must have powershell installed

    Phase 1 (Steps 1 – 3)

    The first phase is where we create the directory structure, install jetstress and copy over the ESE dll files we need to use.

    Step 1 – Create Jetstress directories

    To do this I decided to use powershell.  To make things really easy I wrote some code to query the jetstress xml file and look at the directories specified within it.  This would allow me to use the process with any jetstress configuration file without needing to update any code.  Copy the following lines of code and save it as create_jetstress_dirs.ps1

    create_jetstress_dirs.ps1

    ###### BEGIN COPY UNDERNEATH THIS LINE ############

    ################################################################### #
    #    Read a JetStress Config File and Create the required dirs 
    # 
    #    Written: Neil Johnson (neiljohn@microsoft.com) 
    # 
    ################################################################### 

    if ($args[0])
    {
       
    $configfile = $args[0]
    }
    else
    {
       
    $configfile = ".\jetstress.xml"
    }

    if (!(Test-Path -path "$configfile")) 
    { 
       
    throw "No Config File Found - create_jetstress_dirs.ps1 <path_to_config_file>"
    } 

    $jetstress = Get-Content $configfile

    foreach ($line in $jetstress)  
    {  
       
    if ($line -match "<path>" -or $line -match "<logpath>")  
       
    {  
           
    $path_array = $line.split('<>'); 
           
    $path = $path_array[2] 
             
           
    if ((Test-Path -path $path)) 
           
    { 
               
    write-host -f green "$path already exists" 
                 
           
    } 
           
    else 
           
    { 
               
    write-host -f yellow "Creating $path..." 
               
    $nul = New-Item "$path" -type directory -force 

           
    } 
             
       
    }  
         
    }
     
    ###### BEGIN COPY ABOVE THIS LINE ############
    Step 2 – Install Jetstress

    Jetstress supports silent installation, so installing it is as simple as running the following command from a batch file or powershell script…

    start /wait msiexec /i c:\jetstress\jetstress.msi /quiet
    Step 3 – Copy over ESE DLL files

    Jetstress simply uses the Exchange ESE dll files to create and control the databases for testing.  As such it requires a copy of the ESE dll files before it can begin.  The following files are required for jetstress to function…

    • ese.dll
    • eseperf.dll
    • eseperf.hxx
    • eseperf.ini

    I recommend copying these files from a production server that will be running the same version of Exchange into a directory you can keep for later use.

    Now we have our ESE DLL files and a copy of jetstress installed, we just need to copy them into the jetstress installation directory…

    xcopy C:\JetStress\ESE\SP1-RU5-x64\*.* "C:\Program Files\Exchange Jetstress" /y

    So, with phase 1 complete, we have a batch file that looks like this…

    @echo off
    set configfile=c:\jetstress\jetstress.xml
    cd c:\jetstress
    powershell -file c:\jetstress\create_jetstress_dirs.ps1 %configfile%
    start /wait msiexec /i c:\jetstress\jetstress.msi /quiet
    xcopy C:\JetStress\ESE\SP1-RU5-x64\*.* "C:\Program Files\Exchange Jetstress" /y

    Phase 2 - (Steps 4 - 9)

    So this bit took me quite a while to get working exactly as I wanted.  Essentially on first run JetStress will register the ESE files and performance counters with the operating system.  If you are doing this via the GUI, it simply asks you to close and re-open JetStress after it has registered the DLL files.  In the command line things are more complicated…

    By default when you run JetStressCmd.exe it will register the DLL files and then spawn off a second copy of the process in a new window.  This upsets the natural flow of my batch file because essentially the original JetStress process has now terminated so the batch file continues and in my case reboots! – I needed to run JetStress then carry on and do other things.  The way I got around this behaviour was to initially begin JetStress with the /? switch – this forces the registration of the DLL files, but allows my batch file to continue as expected…

    cd "C:\Program Files\Exchange Jetstress" 
    JetStressCmd.exe /? 
    JetstressCmd.exe /c c:\jetstress\jetstress.xml /timeout 2H0M0S /new
     

    So, our batch file now looks like this…

    @echo off
    set configfile=c:\jetstress\jetstress.xml
    cd c:\jetstress
    powershell -file c:\jetstress\create_jetstress_dirs.ps1 %configfile%
    start /wait msiexec /i c:\jetstress\jetstress.msi /quiet
    xcopy C:\JetStress\ESE\SP1-RU5-x64\*.* "C:\Program Files\Exchange Jetstress" /y
    cd "C:\Program Files\Exchange Jetstress" 
    JetStressCmd.exe /? 
    JetstressCmd.exe /c c:\jetstress\jetstress.xml /timeout 2H0M0S /new
     

    Phase 3 - (Steps 10 - 12)

    So, after roughly 4 hours we have completed our JetStress test – the next step is to copy the results and logs into a directory we can harvest later on.  For my deployment I chose c:\jetstress\jetstress_results – however given sufficient permissions you could choose to directly copy the results to a shared location on a server somewhere.  With hindsight this is the route I should have chosen for this deployment and I will aim to do this for the next one.

    We are ideally looking to retain copies of the HTML, BLG, LOG and XML files that exist within the JetStress installation directory.  Assuming you have installed into the default directory  the following lines of batch file will gather the results…

    mkdir c:\jetstress\jetstress_results
    xcopy "c:\program files\exchange JetStress\*.html" c:\jetstress\jetstress_results\ /y
    xcopy "c:\program files\exchange JetStress\*.blg" c:\jetstress\jetstress_results\ /y
    xcopy "c:\program files\exchange JetStress\*.log" c:\jetstress\jetstress_results\ /y
    xcopy "c:\program files\exchange JetStress\*.xml" c:\jetstress\jetstress_results\ /y

    The next step is to uninstall JetStress from the server ready for its Exchange installation.  The following lines of batch file will uninstall JetStress and remove any files that are left in that directory…

    start /wait msiexec /uninstall c:\jetstress\jetstress.msi /quiet
    cd c:\jetstress
    rmdir "C:\Program Files\Exchange Jetstress" /Q /S

    The next thing left to do is remove the JetStress test databases and directories.  For that we will use a slightly modified version of our earlier powershell script.

    remove_jetstress_dirs.ps1

    ###### BEGIN COPY UNDERNEATH THIS LINE ############

    ################################################################### #
    #    Read a JetStress Config File and Delete the required dirs 
    # 
    #    Written: Neil Johnson (neiljohn@microsoft.com) 
    # 
    ################################################################### 

    if ($args[0])
    {
       
    $configfile = $args[0]
    }
    else
    {
       
    $configfile = ".\jetstress.xml"
    }

    if (!(Test-Path -path "$configfile")) 
    { 
       
    throw "No Config File Found - remove_jetstress_dirs.ps1 <path_to_config_file>"
    } 

    $jetstress = Get-Content $configfile

    foreach ($line in $jetstress)  
    {  
       
    if ($line -match "<path>" -or $line -match "<logpath>")  
       
    {  
           
    $path_array = $line.split('<>'); 
           
    $path = $path_array[2] 
             
           
    if ((Test-Path -path $path)) 
           
    { 
               
    write-host -f yellow "Removing $path" 
               
    $nul = remove-Item "$path" -force -recurse
           
    } 
           
    else 
           
    { 
               
    write-host -f green "$path already removed"

           
    } 
             
       
    }  
         
    }

    ###### BEGIN COPY ABOVE THIS LINE ############

    After this point we have completed our jetstress test and we are ready to move on.  I simply saved this batch file as c:\jetstress\runjetstress.cmd and called it from powershell at the point in my automated build where I wanted to run it.

    So our final automated jetstress batch file looks like this…

    @echo off
    set configfile=c:\jetstress\jetstress.xml
    cd c:\jetstress
    powershell -file c:\jetstress\create_jetstress_dirs.ps1 %configfile%
    start /wait msiexec /i c:\jetstress\jetstress.msi /quiet
    xcopy C:\JetStress\ESE\SP1-RU5-x64\*.* "C:\Program Files\Exchange Jetstress" /y
    cd "C:\Program Files\Exchange Jetstress" 
    JetStressCmd.exe /? 
    JetstressCmd.exe /c %configfile% /timeout 2H0M0S /new
    mkdir c:\jetstress\jetstress_results
    xcopy "c:\program files\exchange JetStress\*.html" c:\jetstress\jetstress_results\ /y
    xcopy "c:\program files\exchange JetStress\*.blg" c:\jetstress\jetstress_results\ /y
    xcopy "c:\program files\exchange JetStress\*.log" c:\jetstress\jetstress_results\ /y
    xcopy "c:\program files\exchange JetStress\*.xml" c:\jetstress\jetstress_results\ /y
    start /wait msiexec /uninstall c:\jetstress\jetstress.msi /quiet
    cd c:\jetstress
    rmdir "C:\Program Files\Exchange Jetstress" /Q /S
    powershell -file c:\jetstress\remove_jetstress_dirs.ps1 %configfile%
     

    So, there you have it – a totally automated and predictable method of running JetStress on your production servers.  So far I have been using this process for the last six months and it has proven to be incredibly robust.

    One last thing, I also chose to parse the results HTML file to attempt to determine if the test had passed or failed.  The following powershell shows how I did this…

        if ((test-path("c:\jetstress\jetstress_results"))) 
       
    {
           
    write-host -f green "$phase - JetStress Test Completed: " -nonewline
           
    $result_file = dir c:\jetstress\jetstress_results\stress*.html
           
    $results = get-content $result_file
            
           
    if ($results -match "<td class=`"success`">Pass</td>")
           
    {
               
    write-host -f green "PASSED"
           
    }
           
    else
           
    {
               
    write-host -f red "FAILED"
           
    }
                
       
    }

    Posted by Neil Johnson, MCS UK, MCM Exchange 2007

  • Office 365 – Hybrid Configuration Wizard (HCW)

    Whilst working on a few O365 engagements over the last month or so I have seen various issues that have been caused by on-premise infrastructure/setup and which have not allowed the HCW (which was introduced in Exchange 2010 SP2) to complete successfully. These issues range from not correctly publishing autodiscover to not having the correct patches/updates installed, so I thought I’d share my experiences.

     

    HCW Issues:-

    I have seen issues with the HCW failing on Get-FederationInformation, this can be caused by various things such as:-

    ·         The customer did not publish the autodiscover endpoints correctly to allow O365 to make federated autodiscover lookups

    ·         There is pre-authentication set on the TMG/ISA or UAG. By connecting to https://autodiscover.company.com/autodiscover/autodiscover.xml for example as shown in Figure 1 - Autodiscover pre-auth authenticating - UAG and Figure 2 - Autodiscover pre-auth authenticating - TMG, you can see that UAG/TMG is prompting for pre-auth instead of the auth being directly on exchange, as shown in Figure 3 - No pre-authentication

    clip_image002

    Figure 1 - Autodiscover pre-auth authenticating - UAG

    clip_image004

    Figure 2 - Autodiscover pre-auth authenticating - TMG

    clip_image006

    Figure 3 - No pre-authentication

    ·         You can also run the command in powershell with the –verbose switch to get more detail, such as get-federationinformation……-verbose

    ·         If you are using TMG you can follow this article for configuring TMG with hybrid setups

    ·         You can also check autodiscover and other O365 endpoints (such as AD FS) have been published and are reachable from the internet using the ExRCA

     

    Another issue I have seen is with certificates and as you run through the HCW, under Manage Hybrid Configuration – Mail Flow Security, you are asked to select the certificate that will be used for TLS mail flow between on-prem on and the cloud. If you are using a wildcard cert such as *.company.com then you will need to ensure you are running at least Exchange 2010 SP2 RU1. If you are not running SP2 RU1 then you most probably see an empty box when you get to the certificate page as shown in Figure 4 - HCW certificate blank below.

     

    clip_image007

    Figure 4 - HCW certificate blank

    Of course you need to also ensure the certificate has been installed onto the exchange hybrid server(s) via the EMC or powershell, you can check using get-exchangecertificate from powershell.

     

    Hybrid steps

    Below are the detailed steps that run behind the scenes when you start the hybrid wizard:-

     

    Create Federation Delegation and Organizational Relationships

    Creates a new Delegation Federated Trust to 'Microsoft Federation Gateway'

    Creates new 'On Premises to Exchange Online Organization Relationship'

    Creates new 'Exchange Online to on premises Organization Relationship'

    Enables MRSProxy on the Exchange 2010 Hybrid Servers

    Configure the 'On Premises to Exchange Online Organization Relationship' to set:-

    MailboxMoveEnabled 'True'

    FreeBusyAccessEnabled 'True'

    FreeBusyAccessLevel 'LimitedDetails' –

    ArchiveAccessEnabled 'True'

    MailTipsAccessEnabled 'True'

    MailTipsAccessLevel 'All'

    DeliveryReportEnabled  'True'

    TargetOwaURL 'http://outlook.com/owa/<company.com>

    Configure the 'Exchange Online to on premises Organization Relationship' to set:-

    FreeBusyAccessEnabled 'True'

    FreeBusyAccessLevel 'LimitedDetails'

    MailTipsAccessEnabled 'True'

    MailTipsAccessLevel 'All'

    DeliveryReportEnabled 'True'

     

    Create Send and Receive Connectors

    HCW creates a new On Premise Send Connector -Name 'Outbound to Office 365' and below is the full output from the send connector created by the HCW:-

     

    AddressSpaces                : {smtp:TenantName.mail.onmicrosoft.com;1}

    AuthenticationCredential     :

    Comment                      :

    ConnectedDomains             : {}

    ConnectionInactivityTimeOut  : 00:10:00

    DNSRoutingEnabled            : True

    DomainSecureEnabled          : False

    Enabled                      : True

    ErrorPolicies                : DowngradeAuthFailures

    ForceHELO                    : False

    Fqdn                         : Company.com

    HomeMTA                      : Microsoft MTA

    HomeMtaServerId              : ServerName

    Identity                     : Outbound to Office 365

    IgnoreSTARTTLS               : False

    IsScopedConnector            : False

    IsSmtpConnector              : True

    LinkedReceiveConnector       :

    MaxMessageSize               : 10 MB (You can increase from 10MB which is the default in 2007 and 2010 to 25MB which is set in the service)

    Name                         : Outbound to Office 365

    Port                         : 25

    ProtocolLoggingLevel         : None

    RequireOorg                  : False

    RequireTLS                   : True

    SmartHostAuthMechanism       : None

    SmartHosts                   : {}

    SmartHostsString             :

    SmtpMaxMessagesPerConnection : 20

    SourceIPAddress              : 0.0.0.0

    SourceRoutingGroup           : Exchange Routing Group (DWBGZMFD01QNBJR)

    SourceTransportServers       : {ServerName}

    TlsAuthLevel                 : DomainValidation

    TlsDomain                    : outlook.com

    UseExternalDNSServersEnabled : False

     

     

    HCW creates a new On Premise Receive Connector 'Inbound from Office 365' on each of the Hybrid HT servers and below is the full output from the receive connector created by the HCW:-

     

    AuthMechanism                           : Tls, Integrated, BasicAuth, BasicAuthRequireTLS

    Banner                                  :

    BinaryMimeEnabled                       : True

    Bindings                                : {LocalIP:25}

    ChunkingEnabled                         : True

    DefaultDomain                           :

    DeliveryStatusNotificationEnabled       : True

    EightBitMimeEnabled                     : True

    BareLinefeedRejectionEnabled            : False

    DomainSecureEnabled                     : False

    EnhancedStatusCodesEnabled              : True

    LongAddressesEnabled                    : False

    OrarEnabled                             : False

    SuppressXAnonymousTls                   : False

    AdvertiseClientSettings                 : False

    Fqdn                                    : Company.com

    Comment                                 :

    Enabled                                 : True

    ConnectionTimeout                       : 00:10:00

    ConnectionInactivityTimeout             : 00:05:00

    MessageRateLimit                        : unlimited

    MessageRateSource                       : IPAddress

    MaxInboundConnection                    : 5000

    MaxInboundConnectionPerSource           : 20

    MaxInboundConnectionPercentagePerSource : 2

    MaxHeaderSize                           : 64 KB (65,536 bytes)

    MaxHopCount                             : 60

    MaxLocalHopCount                        : 12

    MaxLogonFailures                        : 3

    MaxMessageSize                          : 28 MB (29,360,128 bytes)

    MaxProtocolErrors                       : 5

    MaxRecipientsPerMessage                 : 200

    PermissionGroups                        : AnonymousUsers

    PipeliningEnabled                       : True

    ProtocolLoggingLevel                    : None

    RemoteIPRanges                          : {RemoteIP Ranges}

    RequireEHLODomain                       : False

    RequireTLS                              : True

    EnableAuthGSSAPI                        : False

    ExtendedProtectionPolicy                : None

    LiveCredentialEnabled                   : False

    TlsDomainCapabilities                   : {outlook.com:AcceptOorgProtocol}

    Server                                  : LocalServerName

    SizeEnabled                             : Enabled

    TarpitInterval                          : 00:00:05

    MaxAcknowledgementDelay                 : 00:00:30

    AdminDisplayName                        :

    ExchangeVersion                         : 0.1 (8.0.535.0)

    Name                                    : Inbound from Office 365

    DistinguishedName                       : CN=Inbound from Office 365,CN=SMTP Receive Connectors,CN=Protocols,etc…

    Identity                                : LocalServerName\Inbound from Office 365

    Guid                                    : 9feef51e-1bd9-4aa4-9202-0614a1fcc0dd

    ObjectCategory                          : company.com/Configuration/Schema/ms-Exch-Smtp-Receive-Connector

    ObjectClass                             : {top, msExchSmtpReceiveConnector}

    OriginatingServer                       : ServerName

    IsValid                                 : True

     

    There are also some connectors created in Forefront Online Protection for Exchange (FOPE). The connector created in FOPE will be called ‘Hybrid Mail Flow Inbound Connector’ and will have the following settings (assuming you are routing mail back on-premise):-

     

    Description: The Hybrid Mail Flow inbound connector was created when hybrid mail flow was configured. This connector cannot be modified.
    Sender Domains: *.*
    Sender IP Addresses
    Transport Layer Security (TLS) Settings: Forced TLS, and certificate matches specified domain

    The recipient certificate matches: mail.company.com

    Filtering Settings: Add these IP addresses to the safelist and only accept mail from these IP addresses for the domains specified above
    IP Reputation Filtering: Disabled
    Spam Filtering: Disabled
    Policy Rules: Disabled

     

    The other connector created in FOPE will be called ‘Hybrid Mail Flow Outbound Connector’ and will have the following settings:-

     

    Description: The Hybrid Mail Flow outbound connector was created when hybrid mail flow was configured. This connector cannot be modified.
    Recipient Domains: mail.company.com,*.*
    Message Delivery Settings:

    Fully Qualified Domain Name: mail.company.com

    Transport Layer Security (TLS) Settings: Forced TLS, and certificate matches specified domain

    The recipient certificate matches: mail.company.com

     

    Create Remote Domains

    Create new Remote Domain 'Hybrid Domain – company.com' set with:-

    TrustedMailInbound 'True'

    Create new Remote Domain 'Hybrid Domain - TenantName.mail.onmicrosoft.com' set with:-

     TrustedMailOutbound 'True'

    TargetDeliveryDomain 'True'

    AllowedOOFType 'InternalLegacy'

    AutoReplyEnabled 'True'

    AutoForwardEnabled 'True'

    DeliveryReportEnabled 'True'

    DisplaySenderName 'True'

    NDREnabled 'True'

    TNEFEnabled 'True'

    Create new Remote Domain 'Hybrid Domain - mail.company.com '

    DomainName 'mail.company.com'

    TrustedMailInbound 'True

     

    Setup Hybrid Mailflow

    Set Hybrid Mailflow to:-

    SecureMailEnabled 'True'

    CentralizedTransportEnabled 'True'

    OnPremisesFQDN 'mail.company.com '

    CertificateSubject 'mail.company.com '

    InboundIPs <>

    OutboundDomains <>

     

     Set Address Policies

    Update Default Recipient Policy to add <alias>@TenantName.mail.microsoft.com

    Apply the updated Default Recipient Policy immediately

     

     

    Written by Daniel Kenyon-Smith