Showing posts with label Lync. Show all posts
Showing posts with label Lync. Show all posts

Friday, 11 April 2014

Automatically Populate Contacts For All Lync 2013 Users

**** UPDATE January 2015: Apologies to anyone who has been trying unsuccessfully to use the script with Exchange 2013.  It only works when contacts are stored in Lync, not in the Exchange 2013 unified contact store.  I'm not sure when I'll have time to have a look at fixing it. ****

**** UPDATE:  v1.1 of the script fixes a problem where the script would crash when attempting to update a Lync account that hadn't been logged onto before (and had no user data).  The script skips these accounts and will process them as normal once they've been logged onto at least once. ****

As a follow-up to my previous post Automatically Populate Contacts For All Lync Users which was written for Lync 2010, I've rewritten the script for Lync 2013. As per the Lync 2010 script, these were the criteria:
  • A script that can be run as a scheduled task or manually
  • Full automation so that new Lync users automatically:
    • are added to everyone's contacts
    • have their address book fully populated
  • No reliance on a dedicated template Lync user for exporting contacts
  • No interference with existing contacts/groups, just adding the missing ones
  • An up-to-date backup of all users' homed resource data
  • The ability to exclude particular users from receiving all contacts
  • The ability to exclude particular users from being added to all address books
  • The ability to define a list of particular users to be added to all address books (instead of adding all Lync users)
  • A testing mode so that results can be checked without making any changes to Lync
  • Logging with email notifications
  • No notifications or popups in clients when contacts are added
The Lync 2010 version of the script relied on the dbimpexp.exe tool but this functionality has been moved into Lync 2013 PowerShell commands (*-csuserdata).  The 2013 script is cleaner in the way it manipulates the XML.

Instructions for deploying the script are included in the script. If you want to run it as a scheduled task, follow the instructions in the Lync 2010 blog.

The script can be downloaded here:

UpdateLync2013Contacts.ps1 (zipped)


This post in its entirety is the copyright of Roland Paix. I don't mind if you link to it but if you copy any of the content you must provide a link to the post and credit me appropriately.

Wednesday, 2 October 2013

Lync 2013 external access to Exchange Web Services (EWS) via TMG

***** UPDATED as I realised the procedure wasn't quite right *****

I recently deployed Lync 2013 with external access at a client who runs Exchange 2010 with external access via TMG.  During initial testing all was well but later testing showed that both the Lync mobile client and Lync 2013 full client couldn't connect to EWS externally.

I'd already created pass-through rules for autodiscover and EWS (more on that later) and I was pretty sure Lync was setup correctly.

The front end's Lync Server event log was showing error ID 32054 for the LS Storage Service:

Storage Service had an EWS Autodiscovery failure.

StoreWebException: code=ErrorEwsAutodiscover, reason=GetUserSettings failed, smtpAddress=test@domain.public, Autodiscover Uri=https://autodiscover.domain.public/autodiscover/autodiscover.svc, Autodiscover WebProxy=<NULL>, WebExceptionStatus=TrustFailure ---> System.Net.WebException: The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.
.......(truncated)
Cause: Autodiscovery Uri was not correctly configured or unreachable, that there is a problem with the Proxy, or other errors.
Resolution:
Check event details.  Check autodiscovery Uri is properly configured and reachable. Check that proxy setting is properly configured and reachable.  Validate Lync to Exchange Autodiscovery configuration by following the trouble shooting guide. If problem persists, notify your organization's support team with the event details.


Watching the TMG logs I noticed that connection attempts to Autodiscover were initially anonymous, unauthenticated and successful, followed by another successful connection but with a http response of 405 "method not allowed".  There were no subsequent EWS connections.

Then I randomly tried to connect from a different external location and everything worked, the Lync client successfully connected to EWS and all meetings and conversations appeared!!!

I started to realise there may be multiple issues so I looked at the front end server's event logs again.  The front end server was attempting to update my Lync account's presence information by connecting to a CAS.  The SIP domain uses the public namespace as Exchange (e.g. domain.public) which is different from the AD forest domain name (e.g. domain.internal).  The event log error showed me that the front end server was trying to connect to autodiscover using the public domain.

It seemed to be connecting but failing so I checked and there was a DNS record internally for autodiscover using the public domain (autodiscover.domain.public).  Then I realised that the CAS server certificate didn't include autodiscover.domain.public.  Why would it?  No prior need for it internally!  I re-issued the Enterprise CA certificates to the CAS servers and included all the public names on it, too.  Ta-da!  No more 32054 errors.

Back to TMG.  I'd correctly planned and deployed new rules for autodiscover and EWS using the web listener I'd created for Lync as it doesn't require authentication and the edge firewall will already have TCP 443 passing through to it.

Here's my method for this:
  1. Assign a new public IP address for Autodiscover/EWS and route/NAT it through to TMG on TCP 443
  2. Create a new public DNS A record for EWS (e.g. ews.domain.public), pointing to the newly-assigned IP
  3. Add the new IP (or NATd IP) to TMG's external NIC
  4. Create a new TMG web listener for EWS:
    1. Require SSL
    2. Listen on the EWS IP
    3. Use the Exchange certificate
    4. No authentication
  5. Create a new TMG Exchange 2010 web client access rule above the existing Exchange rules:
    1. Use Outlook Anywhere with additional folders
    2. Use the EWS web listener
    3. Use two public names: autodiscover.domain.public and ews.domain.public
    4. Set the authentication delegation to 'No delegation, but client may authenticate directly'
    5. Set the users to 'All Users'
    6. Remove all paths except for /ews/* and /AutoDiscover/*
  6. Change the Exchange web services virtual directories' external URL to use the new public name ews.domain.public (e.g. to change all CAS servers: Get-WebServicesVirtualDirectory | Set-WebServicesVirtualDirectory -ExternalUrl https://ews.domain.public/EWS/Exchange.asmx)
  7. Change the autodiscover public DNS record autodiscover.domain.public to use the same IP as ews.domain.public
Back to the problem, in TMG I watched the logs while I tested logging on to various Lync clients externally.  I had one of those 'I'm so dumb' flashes: TMG was configured to send traffic to a web farm of two CAS servers.  One was responding correctly, the other wasn't.

I looked at the rogue CAS and couldn't see any issues in the logs or any other signs that it wasn't working properly so I used the EMC to reset the Autodiscover virtual directory then ran iisreset /noforce.

That was it, all my external Lync 2013 clients were now able to access EWS and display meetings and conversations, no matter which CAS they hit.  Mucho happy me!


This post in its entirety is the copyright of Roland Paix. I don't mind if you link to it but if you copy any of the content you must provide a link to the post and credit me appropriately.

Thursday, 20 December 2012

Automatically Populate Contacts For All Lync Users

*** Update: This script is for Lync 2010. If you're looking for the Lync 2013 version please go to Automatically Populate Contacts For All Lync 2013 Users ***

I recently found myself looking for a way to populate all Lync users' address books with all Lync users.  This came about because open federation was in use and security requirements dictated that only users in people's contacts lists could see presence information.  I needed a way to ensure that all Lync users in the organisation were in everyone's Lync contacts.

After enabling privacy mode (http://technet.microsoft.com/en-us/library/gg399028.aspx) I tried adding a group containing all users to my Lync contacts but this didn't work. The context of the contact in this case is the group rather than the users in the group so nobody could see my presence (they have to be users directly in my contacts list to be able to see my presence).

So I googled around a bit and found a few scripts that people have created to add contacts such as this one by Jeff Guillet:

http://www.expta.com/2011/01/introducing-lyncaddcontacts.html

It didn't quite do what I wanted it to and it's written in vbscript rather than powershell so I decided to write my own.

Here's what I set out to achieve:

  • A script that can be run as a scheduled task or manually
  • Full automation so that new Lync users automatically:
    • are added to everyone's contacts
    • have their address book fully populated
  • No reliance on a dedicated template Lync user for exporting contacts
  • No interference with existing contacts/groups, just adding the missing ones
  • An up-to-date backup of all users' homed resource data
  • The ability to exclude particular users from receiving all contacts
  • The ability to exclude particular users from being added to all address books
  • The ability to define a list of particular users to be added to all address books (instead of adding all Lync users)
  • A testing mode so that results can be checked without making any changes to Lync
  • Logging with email notifications
  • No notifications or popups in clients when contacts are added
I wrote the script in PowerShell 2.0 as that's what is currently running on my Lync 2010 server.  The script is suitable for smaller environments but could run in larger ones if you're patient and take into account address book limitations.  I'd like to rewrite the script in PowerShell 3.0 sometime and make use of workflows which would speed up the processing a lot.

The script uses the Lync tool DBImpExp.exe to export each users' homed resource data, compare it to a list of users that should be in everyone's address book and update each address book with the missing contacts.

To use the script, download it to a front end server to C:\Scripts\ (or wherever you prefer).  Edit the script and customise the variables per your requirements.

The account used to run the script must be a member of the RTCUniversalServerAdmins group and must have write permission to your working folder.

To run the script as a scheduled task I strongly recommend you create and use a dedicated service account.  You must allow the account to log on as a batch job on the Lync front end server.

You could use the following task settings:

Name:  Update Lync Contacts
Description:  This script updates all Lync users' address books with all Lync users.
Trigger:  Daily @5am
Action:  Start a program
Program:  PowerShell.exe
Arguments:  -NonInteractive -WindowStyle Hidden -command "& 'C:\Scripts\UpdateLyncContacts.ps1'"

Once the scheduled task is created open it and set:

<General> Security options:
- Set it to run using your dedicated service account
- Run whether user is logged on or not
- Run with highest privileges

<Settings>:
- Allow task to be run on demand
- Stop the task if it runs longer than: 1 hour

If you download and use the script please ensure that it is suitable and configured correctly for your environment.  I'd love to know if you use it so please leave me a comment if you do.  Also note that I accept no liability or responsibility if it doesn't work as expected!

The script can be downloaded here:




This post in its entirety is the copyright of Roland Paix. I don't mind if you link to it but if you copy any of the content you must provide a link to the post and credit me appropriately.

Monday, 26 November 2012

Connecting Lync 2010 with a Cisco 3925 ISR

I've recently finished a deployment of Lync 2010 enterprise voice using a Cisco 3925 ISR as an IP gateway.  I struggled to find information on configuring the Cisco side so I thought I'd post my experience here.

The ISR was already in use as a PSTN gateway using the built-in Cisco Unified Communications Manager Express (CUCME) with voicemail being handled by the Cisco Unity Express module.  Staff have Cisco SCCP IP phones and Lync was deployed as an alternative phone system using a subset of the extension numbers.  Let's say that the extension numbers 600 - 699 are configured on the ISR.  I've sent extensions 670 - 679 from the ISR to Lync instead of to Cisco phones.

Although I do some Cisco networking it's mostly switching and firewalls and I don't have a lot of experience with voice.  I find it a little terrifying to be honest!  My goal in making changes to the ISR was to have no interruptions to service and to make as few changes to the existing configuration as possible.

The first thing to do is to update the Lync topology.  Create a PSTN gateway listening on TCP 5060 and using the IP address of your ISR (probably the Loopback0 interface):


PSTN Gateway
Associate the PSTN gateway with your mediation server/pool and enable TCP 5068.  TCP must be used as TLS isn't compatible between the ISR and Lync.


Mediation Server
Don't forget to publish the topology and update your servers using the Deployment Wizard.

The next step is to configure the voice routing and policies.  This can be daunting.  Or, it can really easy if you let someone else do the hard work!  Head on over to www.lyncoptimizer.com and run through the steps and you'll end up with a PowerShell script that you run in the Lync shell.  Depending on the choices you made this script will create:
  • A site dial plan
  • Normalisation rules
  • Site and user voice policies
  • PSTN usage records
  • Voice routes
  • Gateway trunk
  • Trunk translation rules
Big thanks to Ken Lasko for this amazing and useful tool.

Now, in my particular deployment the ISR normalisation is based on extensions (6xx) while Lync is based around E.164 numbers.  This means that you need to create some new rules so that Lync users can dial extensions without having to enter the full number.

Edit your site (or pool) dial plan and create a new normalisation rule to translate the extension numbers that get dialed (e.g. 678) to a full E.164 number.  Mark it as an internal extension.

New Normalisation Rule


Move the new normalisation rule to the top of the list.  It's a good idea to create a voice routing test case to prove that the normalisation works.

Jump over to your trunk configuration and edit your gateway's trunk.  Check that the Encryption support level is set to Optional and that Refer support is disabled.

Create a new associated translation rule to remove the leading digits to expose your internal extensions:


New Trunk Translation Rule
Move the new rule to the top of the list and commit the changes.

You may also want to configure the Call Park and Unassigned Numbers features now.  I won't include details on how to do that here as this post is already getting longer than I'd anticipated.

One more thing to configure and this time it's in the Lync Management shell.  You need to disable the trunk's RTCP session timers to avoid an issue of calls between Cisco users and Lync users dropping after 30 minutes:

Set-CsTrunkConfiguration –Identity [name of your trunk] -EnableSessionTimer $false –RTCPActiveCalls $false –RTCPCallsOnHold $false 

Alright, enough about Lync, let's get to the juicy stuff: configuring the Cisco ISR.

Like I said earlier, I'm not an expert here and a lot of things I discovered through trial and error (never a good idea on a production system but I only broke it once for a minute!).  So be warned: these changes are your responsibility and the configuration examples I've listed may not work with your system!!!

The first thing is to add your Lync mediation server to the list of trusted IP addresses that can talk to the ISR.  This may not be necessary if this feature isn't already turned on.

voice service voip
 ip address trusted list
  ipv4 [Mediation server's IP address]


Now check that SIP control is bound to CUCME.  This one cost me a day of my life:

voice service voip
  sip
   bind control source-interface Loopback0
 


You need to create voice translation rules and profiles so that the ISR sends E.164 numbers to Lync instead of extensions.  The examples below are normalising extensions 670-679 to +61712345670 - +61712345679 for calls placed from ISR users to Lync users.  The reverse happens when Lync users call ISR extensions; we want the Lync user's calling number to be normalised so that it appears as a 3-digit extension on the Cisco phones.
 

voice translation-rule 5
 rule 1 /^\(67.\)$/ /+61712345\1/

voice translation-rule 6
 rule 1 /^.61712345\(67.\)$/ /\1/

voice translation-profile ToLync
 translate called 5

voice translation-profile FromLync
 translate calling 6


Now create a dial peer for the Lync server.  This will be used for both inbound and outbound calls to/from Lync.
 

dial-peer voice 5 voip
 tone ringback alert-no-PI
 description ** SIP Trunk to Lync **
 translation-profile incoming FromLync
 translation-profile outgoing ToLync
 answer-address .6171234567.
 destination-pattern 67.
 notify redirect ip2pots
 session protocol sipv2
 session target ipv4:[Mediation server's IP address]:5068
 session transport tcp
 voice-class sip rel1xx disable

 voice-class sip block 183 sdp present
 dtmf-relay rtp-nte
 codec g711ulaw
 fax protocol none
 no vad
 no supplementary-service sip refer

 

Here's some info on some of the entries:

tone ringback alert-no-PI voice-class sip block 183 sdp present voice-class sip rel1xx disable

These are used to help with ringback (the ringing sound you hear when you've dialed a number and are waiting for it to be answered) for the Cisco phones.

The man whose blog you want to read about these and other Lync goodness is Chris Norman's (VoIPNorm):

voipnorm.blogspot.com.au/2012/09/updated-ringback-info-important.html

-UPDATE-

Chris has updated his info on Cisco ISR/Lync integration:

http://voipnorm.blogspot.com.au/2013/06/updated-again-important-settings-to.html

-/UPDATE-

If you read Chris' post you'll notice I disabled rel1xx and sip refer at the dial peer level rather than at the higher voice service voip level.  This is in keeping with my desire to limit changes that affect the existing services.  I've no idea if what I've done is right or not but it seems to work.

 answer-address .6171234567.
 destination-pattern 67.


These two lines are used to associate the numbers with Lync.  The answer-address line identifies the calling number of the Lync user when they dial out and associates it with the dial peer.  This works in my deployment because the incoming called-number . line was already configured on the inbound POTS dial peer like so:

dial-peer voice 11 pots
 incoming called-number .
 direct-inward-dial
 port 0/0/0:15
 

I may have had to remove it, add the answer-address line then add the incoming called-number line back again before the ISR figured it all out.  My memory is blurry.

The destination-pattern 67.  line sends all calls to extensions 670 - 679 to Lync.


no supplementary-service sip refer

This is where to disable refer support.  You can also disable it globally at the voice service voip level.

Hopefully that provides enough information for those of you configuring ISRs that use CUCME.

When I find time I'll post about configuring media bypass and Exchange UM with the ISR as well.



This post in its entirety is the copyright of Roland Paix. I don't mind if you link to it but if you copy any of the content you must provide a link to the post and credit me appropriately.