Haiku #187

You can come in and

So can you. But no, not you .

Client version rules.


Well, it's Monday, and the author of today's haiku is home at last. OK, actually he got home late Saturday afternoon, but he never truly felt at home: after all, both Saturday and Sunday the sun was shining and the weather was warm. When he woke up this morning, however, he looked out the bedroom window and saw that the sky was a familiar, and comforting, shade of gray, with not a ray of sunshine to be seen. That was the moment when he realized that he was really home.




At any rate, the author of today's haiku definitely enjoyed his time in Park City, UT, even if he had to put up with blue skies and sunshine every day that he was there. On the other hand, it definitely is possible to have too much of a good thing, and the author of today's haiku realized that it just isn't right to have fun and enjoy yourself day after day after day.


Which, in case you're wondering, is his answer to the question, "If it was so much fun in Park City, then why did you come back?"

No, hey, just kidding. Granted, he won't be riding bikes or climbing mountains every day now that he's back in Seattle. But that doesn't mean he won't still have all the fun he can handle. After all, the topic of today's haiku is the CsClientVersionPolicyRule cmdlets (Get-CsClientVersionPolicyRule, New-CsClientVersionPolicyRule, Remove-CsClientVersionPolicyRule, and Set-CsClientVersionPolicyRule).


Note. Talk about having too much of a good thing, eh?


As devoted readers of the Lync Server PowerShell blog know, client version policies are used to determine the client applications that users can (or cannot) use to log on to Lync Server. Can your users log on to Lync Server using Office Communicator 2007? Well, that depends on your client version policies. If you have a client version policy that expressly allows users to log on using Communicator 2007 then the answer is yes. And what if you have a client version policy that expressly forbids users from logging on using Communicator 2007? In that case, the answer is "Not yes."


Note. OK, technically the whole thing can get a bit more complicated than that. For example, what if you don't have a client policy that doesn’t mention Communicator 2007 at all? Well, in that case, you can do things like configure Lync Server to allow (or prohibit) any client application not covered by a client version policy. But we aren't going to talk about that today; for that discussion, see Haiku #125


What we are going to talk about today are policy settings that do explicitly deal with a specific client application. If you want to expressly allow (or not allow) users to log on with a specific client application then you need to create a client version policy rule for that application and then assign that rule to the appropriate client version policy.


OK, that isn't 100 percent true: when you install Lync Server, by default you get a global client version policy that includes rules for 19 of the more common client applications (different versions of Office Communicator, different flavors of Office Communicator/Lync Phone Edition, and so on). That means you probably won't have to create a new rule: more often than not, you'll only have to modify an existing rule.


But let's pretend your company has created its own client application, and you need to create a new client version policy rule that will allow users to log on using that application. How are you going to do that? Like this:


$x = [guid]::NewGuid()


New-CsClientVersionPolicyRule -Parent global -RuleId $x -MajorVersion 1 -UserAgent LitwareincClient –CompareOp GEQ –Action Allow


So what have we done here? Well, in the first command, we've created a new GUID and stored that GUID in a variable named $x. Why did we do that? That's easy: because the Identity for a client version policy rule is composed of the scope where the rule is to be assigned plus a unique GUID. In other words, the Identity of a client version policy rule looks something like this:




The best way to create a unique GUID for use with a client version policy rule is to let Windows PowerShell create that GUID for you.


Note. In case you're wondering, the scope part of the Identity simply refers to the policy that the new rule should be added to (that is, the global part of global/4730866f-8594-431b-ad57-6f1c798ce0d8).


In our second command, we then use New-CsClientVersionPolicyRule to create the new rule and add that rule to the global policy (use the Parent parameter to indicate the policy the rule should be added to). As you can see, we use the variable $x (the GUID we just created) as the parameter value for the RuleID parameter; we also set the MajorVersion of the rule to 1 and the UserAgent to LitwareincClient. Why? Well, we want to allow anyone who has version 1 of the application LitwareincClient to log on to Lync Server; to do that, we need to specify the version number and the user agent (which is simply the designation used by the client application).


So is that all we have to do? Almost. We also need to do two things. First, we want people to be able to log on using version 1.01 of the application, as well as version 1.02, 1.4, 2.0, 3.9, and so on. (Granted, none of those versions exist yet, but it never hurts to plan ahead.) Therefore, we set the CompareOp parameter to GEQ, which simply means "greater than or equal to." (For a complete list of comparison operators, see the help topic for New-CsClientVersionPolicyRule.) Suppose a user tries to log on using version 1.2 of LitwareincClient. Will they be able to log on to Lync Server? You bet; after all, version 1.2 is greater than (or equal to) version 1. And what if they try to log on using version 0.9? That's not going to work: version 0.9 is not greater than (or equal to) version 1.


Note. As we mentioned earlier, it can get a little more complicated than either yes you can log on or no you can't log on. But for now we're going to ignore all those complications.


But wait, we're not done just yet. We want people who are running LitwareincClient to be able to log on to Lync Server; therefore, we need to set the Action property to Allow. And what if we didn't want them to be able to log on to Lync Server? In that case, we would set the Action property to Block, like so:



New-CsClientVersionPolicyRule -Parent global -RuleId $x -MajorVersion 1 -UserAgent LitwareincClient –CompareOp GEQ –Action Block


Etc., etc.


And here's a cool little trick. Suppose you have a bunch of different client version policies. (Which is possible: policies can be created at the site scope as well as the service scope.) What if you want to add this new rule to all your client version policies? Is there a way to do that? Of course there is:


$x = [guid]::NewGuid()


Get-CsClientVersionPolicy | ForEach-Object {New-CsClientVersionPolicyRule -Parent $_.Identity -RuleId $x -MajorVersion 1 -UserAgent LitwareincClient –CompareOp GEQ –Action Allow}


All we've done here is use the Get-CsClientVersionPolicy cmdlet to return a collection of all our existing client version policies. We've then piped that collection to the ForEach-Object cmdlet, and asked ForEach-Object to add the new rule to each policy in the collection. The trick to making this work? We set the value of the Parent parameter to $_.Identity; that tells ForEach-Object to use the Identity of the client version policy (whichever policy ForEach-Object happens to be working with at the moment) as the new rule's parent.


It's a tiny bit clunky, but it works around the fact that you can't directly pipe data to New-CsClientVersionPolicyRule.


Got all that? OK. Now suppose you later change your mind and need to modify this rule; for example, suppose you now want to block the use of LitwareincClient. In that case, it's Set-CsClientVersionPolicyRule to the rescue:


Get-CsClientVersionPolicyRule | Where-Object {$_.UserAgent -eq "LitwareincClient"} | Set-CsClientVersionPolicyRule -Action "Block"


Note that we cheated a little bit here. If we wanted to, we could have used a command like this one to modify the rule:


Set-CsClientVersionPolicyRule –Identity "global/4730866f-8594-431b-ad57-6f1c798ce0d8" -Action "Block"


Oddly enough, however, we had no desire to type in global/4730866f-8594-431b-ad57-6f1c798ce0d8 as the Identity of the rule we need to change. Therefore, we simply used Get-CsClientVersionPolicyRule to return all the rules, then piped that collection of rules to the Where-Object cmdlet. We then used Where-Object to pick out only those rules that have a UserAgent equal to LitwareincClient, then piped that filtered collection to Set-CsClientVersionPolicyRule.


And sure, we could get a little more specific if we wanted to, or needed to. For example, this command will only modify LitwareincClient applications found in the global policy:


Get-CsClientVersionPolicyRule | Where-Object {$_.UserAgent -eq "LitwareincClient" –and $_.Identity –match "^global"} | Set-CsClientVersionPolicyRule -Action "Block"


To do that, we simply added another stipulation to Where-Object:


Where-Object {$_.UserAgent -eq "LitwareincClient" –and $_.Identity –match "^global"}


Now we want only those rules where the UserAgent is equal to LitwareincClient and the Identity matches ^global. That's a regular expression that tells PowerShell to match only rules where the Identity begins with (^) the string value global.


Note. Why didn't we just match the value of the Parent property? That's easy: rules don't actually have a Parent property. The Parent parameter is a little shortcut way to specify the Identity for a new rule, but that Identity – as we've already seen – will end up being something like global/4730866f-8594-431b-ad57-6f1c798ce0d8. And the only way to get at the global portion of that Identity is to use a method similar to the one we just showed you.


And if you change your mind and decide you don't need this rule after all, well, you can also get rid of it using Remove-CsClientVersionPolicyRule:


Get-CsClientVersionPolicyRule | Where-Object {$_.UserAgent -eq "LitwareincClient"} | Remove-CsClientVersionPolicyRule


So is there even more to the CsClientVersionPolicyRule cmdlets than what we just showed you? Maybe. But, like we said, you can have too much of a good thing. With that in mind, we'll see everyone tomorrow.