Friday 26 August 2011

Adding Joomla users with bash script

For our Intranet page we use the Joomla content management system in conjunction with IIS and the single sign on plug ins available. This gives us a very flexible Intranet page and our users love the SSO.

Obviously to enable to SSO on a product like Joomla there needs to be some configuration, especially when you use a package such as "Docman" which is a document manager with its own group system. This was becoming an administrative burden, having to run our Active Directory add user script and then go independently to the Joomla configuration, add the user them add them into the appropriate Docman group(s).

To fix this problem I put together a simple bash script that can handle the adduser task and placed the script on a Debian box with SSH enabled. Then I used the plink (command line) functionality of the famous putty SSH tool and paired it with our existing powershell add user script to trigger the Joomla add user process.


The bash script

The below script assumes the mysql server is on the local host and the table is called "joomla". You can set the mysql username and password in the top variables "mysqlusername" and "mysqlpassword". If you are not using Docman you can comment replace the follow line;

mysql --user=$username --pass=$password -e "use joomla; $string1 $string2 $string3 $string4"

with

mysql --user=$username --pass=$password -e "use joomla; $string1 $string2 $string3"


This will only add the user to Joomla instead of touch any Docman tables.

In short, the script looks for the next available ID to use, then adds the user and assigns them to the "20" or Editor group (this is the group I want my staff in, but you could change the 20 to another number such as 19 for Author or 25 for Super Administrator).

 name=$1
 username=$2
 mysqlusername=joomla
 mysqlpassword=joomla
 domain=blah.local
 email=$2@$domain
if [ -z "$2" ]; then
  echo syntax: ./joomlaadd \"real name\" \"username\"
  exit
fi

id_users=$((`mysql --user=$mysqlusername --pass=$mysqlpassword -e "use joomla; select ID from jos_users" | tail -n 1`+1))
id_core_acl_aro=$((`mysql --user=$mysqlusername --pass=$mysqlpassword -e "use joomla; select ID from jos_core_acl_aro" | tail -n 1`+1)) 
docmangrouptemp=`mysql --user=$mysqlusername --pass=$mysqlpassword -e "use joomla; select groups_members from jos_docman_groups;"`
docmangroup=`echo $docmangrouptemp | awk -F " " '{ print $2 }'`
docmangroupfinal="$docmangroup,$id_users"

echo
echo
echo Joomla + docman adduser script
echo
echo name: $name
echo username: $username
echo email: $email
echo users id will be $id_users
echo users acl aro id will be $id_core_acl_aro

echo
echo
echo adding user to joomla...
echo
echo

string1="INSERT into jos_users VALUES ('$id_users','$name','$username','$email','1','Editor','0','0','20','2010-01-01 00:00:01','0000-00-00 00:00:00','','admin_langu"
string2="INSERT into jos_core_acl_aro VALUES ('$id_core_acl_aro','users','$id_users','0','$name','0');"
string3="INSERT into jos_core_acl_groups_aro_map VALUES ('20','','$id_core_acl_aro');"
string4="REPLACE into jos_docman_groups VALUES ('4','staff','','1','$docmangroupfinal');"

mysql --user=username --pass=password -e "use joomla; $string1 $string2 $string3 $string4"

echo
echo
echo adding complete...



Triggering the script

The way you trigger the script is up to you. As I eluded to above, I am using a powershell script to do the active directory configuration, adding the users email account, setting up their home directory, adding them to the appropriate groups and allocating print credits. To trigger my script I simply added the following code to my powershell script. Obviously in my below example you need to set your password in place of "Testpassword" and replace "adduser@debianhostname" with your "username@hostname" of the server where the joomlaadd script is located.

    #adding user to joomla and docman groups
    invoke-expression '.\plink.exe -pw Testpassword adduser@debianhostname ~/joomlaadd \`"$DisplayName\`" \`"$samAccountName\`"'


For the above code to work correctly you need to have $DisplayName set as the users full name, e.g. James Trevaskis and the $samAccountName as the SAM account name you used to add them to AD. You will also need putty.exe and plink.exe available in the powershell script directory, both are available from here.

You will more than likely need to do a bit of moulding to make this code fit your requirements, but hopefully this is at least a start, so get scripting!

Tuesday 23 August 2011

Apple IOS 10.6 domain bind problems - This computer is unable to access the domain controller for an unknown reason

We have had a number of Apple IOS 10.6 machines lose connectivity with the domain. This manifests itself as users not being able to login to the computer, the screen simply just shakes and doesn't allow the login.

In the past we have simply unbind the machine from the domain, then rebind the machine, problem solved. Unfortunately this time it was not as simple and we got a very generic error message that read "This computer is unable to access the domain controller for an unknown reason", great, that doesn't sound good.

Fortunately there are some more detailed logs we can look at, but first we need to enable the debug logging to ensure we capture all the important details of the failure.


Enabling the directory services debug logs

1. Open a terminal window

2. Elevate to root privledges by typing
sudo su root

3. Type the following commands
killall -USR1 DirectoryService
tail -f /Library/Logs/DirectoryService/DirectoryService.debug.log

Now the debug logging is enabled, and the tail -f command follows the log to display the latest information live on the screen.



Detecting the problem

When we put our Directory Service into debug logging and inspected the logs, we found the following errors straight after attempting to bind the computer to the domain.

Active Directory:       Password verify for administrator@TEST.INTERNAL failed with error -1765328230
Client: Directory Utilit, PID: 222, API: dsDoPlugInCustomCall(), Active Directory Used : DAR : Node Ref = 33556364 : Request Code = 84 : Result co$
Plug-in call "dsDoPlugInCustomCall()" failed with error = -14090.
Port: 20831 Call: dsDoPlugInCustomCall() == -14090


What didn't help resolve the problem

  • Deleting the computer account in active directory, then unbinding/rebinding
  • Unbinding and rebinding to the domain
  • Recreating a fresh computer account in active directory and then rebinding
  • Ensuring the IP/Host lined up correctly with the domain DNS entries
  • Restoring a previous backup (obviously the computer password had changed in the previous backup, but restoring the backup then rebinding the machine to the domain also failed)



Fixing the problem

After doing some research I found a number of people that were experiencing the same issue and fortunately the fix is fairly easy, but hidden deep! The Kerberos config is located in /var/db/dslocal/nodes/Default/config/ and by deleting these configs, we can clear out any problematic settings and regenerated them.


1. If your system is still bound to active directory unbind it. This can be done in the Directory Utility, then clicking on directory services, and unbinding active directory.

2. Open a Terminal window

3. Elevate to root privledges by typing
sudo su root

4. Delete the Kerberos config, you can do this by typing.
Rm -f /var/db/dslocal/nodes/Default/config/Kerberos*

5. Reboot

6. Rebind to the domain. Again this is located in the Directory Utility.


This is a relatively easy fix, but without knowing exactly where to look, it can take a long time to find!

Monday 22 August 2011

Apple IOS 10.6 logon scripts

In a windows active directory enterprise environment logon scripts are critical to delivering services to users as they log on.

Unfortunately the login hook method that has worked so well in previous IOS versions is not working in 10.6, but don't fear, there is a new method based on the launch daemon that we can utilize.

In my environment I want to deliver a smbfs based network drive hosted on a windows file server and create some directories as the user logs in, this is the method I used.

1. Create a launchd plist that contains the path of the login script I plan to use. I do this by creating a .plist file in the /System/Library/LaunchAgents directory. My configuration file was called logonscript.plist and read as follows.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>logonscript</string>
<key>LaunchOnlyOnce</key>
<true/>
<key>ProgramArguments</key>
<array>
<string>open</string>
<string>/usr/bin/logonscript</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>ServiceDescription</key>
<string>logonscript</string>
</dict>
</plist>

In short all my configuration file does is launch /usr/bin/logonscript on user login, you can change that
<string>/usr/bin/logonscript</string> to anything you want.


2. Next I simply create my logonscript, my script read as follows.


echo Logging you on..
echo -


echo Connecting public drive..
mkdir ~/Desktop/public
/sbin/mount_smbfs //fileserver.blah.internal/public ~/Desktop/public
echo done..
echo -


echo Logon complete... You can now close this window..
 
While my script is very simple, the power of bash scripting would allow you to do a large number of operatings during this logon.


3. Of course lastly we need to modify the file to be executable

chmod +x /usr/bin/logonscript


You are all set, now your users can logon and automatically map the required network drives as long as you have already binded the system to active directory.

Apple IOS 10.6 SSO printing with Active Directory

Integrating Apple desktops into a windows active directory infrastructure can be extremely hard and one of the most difficult aspects is enabling single sign on (SSO). In a windows world nearly all services are single sign on and it can be inconvenient and annoying for users to have to continually enter their password.

I came across difficulties when I started to map network printers on an IOS 10.6 machine. When the printer authentication dialog appeared, the username field was already populated, but instead of being populated with the username it was populated with the users real name. This meant on almost every occassion when the popup appeared, the user left the username field alone and just entered their password resulting in a failure to print and lots of support calls to IT. The answer lies in a very simple switch we can use in combination with the scutil tool.


1. Open a terminal


2. Type the following to elevate your privileges to root.
sudo su root
3. We need to set the hostname of the system to the FQDN (fully qualified domain name), replace blah.domain.com with your actual FQDN, for example.


scutil --set HostName blah.domain.com


4. Next get a list of the printer queue names by typing the following.


lpstat -v

The list is shown as below.

sh-3.2# lpstat -v
device for PRINTQUEUE001_LibraryStudent_Kyocera400ci: smb://PRINTQUEUE.blah.internal/LibraryStudent-Kyocera400ci
device for PRINTQUEUE_LibraryStudent_Kyocera400ci:: ///dev/null


The printer queue name in this example is PRINTQUEUE_LibraryStudent_Kyocera400ci



5. Now take the printer queue name(s) and run the following command, replacing the "PRINTQUEUE_LibraryStudent_Kyocera400ci" with your queue name. You need to repeat the process for every printer queue for which you want to enable SSO.
 
lpadmin -p PRINTQUEUE_LibraryStudent_Kyocera400ci -o auth-info-required=negotiate

It really is as easy as that, now the next time your users go to print to any of those Active Directory printer queues you have enabled SSO on, they will not even be prompted.

Monday 15 August 2011

Windows 7 wireless NIC not initializing before netlogon service

This is an absolute nightmare of an issue with Windows 7 systems that many administrators seem to be dealing with, more so in schools than anywhere because of the high number of laptops connecting to the wireless network.



The problem...

This problem manifests itself in a large number of ways but the main critical problems are.

1. The wireless network doesnt initialize before the netlogon service. This causes the system to be unable to find a domain controller or the domain itself. Resultantly users can't logon or when they do logon they recieve a black windows 7 "temporary desktop". Error messages such as "There are currently no logon servers available to service the logon request" are also common on some specific network adapters.

2. The wireless network doesnt initialize before the group policy service, this causes the system to be unable to enumerate the latest group policies and can cause delays or failures in computer startup scripts.

3. The wireless network doesnt initalize before the app-v services launch, this causes App-V to be unable to connect with the App-V streaming server. In our environment this problem didn't give users any direct error message but they were unable to refresh or view App-V programs. If an administrator issued a policy refresh we recieved error logs containing the following:

3210
{tid=B78}
Attempting Transport Connection URL:
RTSP://sgprod.com:554/Visio_Standard_Mi ... 07_MNT.sft Host: sgprod.com:554 IPAddr: 192.168.100.147 Error: 1690910A-00002002


5009
{hap=1A:app=Microsoft Office Visio 2007 Std 12.0:tid=89C}
The Application Virtualization Client could not connect to stream URL 'RTSP://sgprod.com:554/Visio_Standard_Microsoft_2007_MNT/Visio_Standard_Microsoft_2007_MNT.sft' (rc 1690910A-00002002, original rc 1690910A-00002002).


3008
{hap=1A:app=Microsoft Office Visio 2007 Std 12.0:tid=89C}
The client was unable to connect to an Application Virtualization Server (rc 1690910A-00002002)



The root cause...

The problems are caused by the wireless network adapter not initializing early enough in the Windows startup sequence.

In Windows XP a group policy exists called "Computer Configuration\Administrative Templates\System\Logon\Run logon scripts synchronously" this policy would force all the computer startup scripts to complete before the machine presented a logon screen. While this policy does still exist in the group policy console, it does not work on Windows 7, 7 simply ignores this policy. Microsoft describe this as a "security upgrade", they have moved the group policies out of the userinit and into their own service.

Another great Windows XP group policy that simply doesn't work anymore is the "Computer Configuration\Administrative Templates\System\Logon\Always wait for the network at computer startup and logon" policy. This policy is meant to do just as its name suggests, force the computer to wait for the network before it allows users to logon. Neither of these policies were able to help me resolve my issues.

This problem is also more prolific in specific network adapters. In our environment we have a number of laptops with Intel 6200 wireless adapters that are causing many more problems than the broadcom and atheros chipset based adapters in other laptops.



The fixes..

After trying all the registry settings provided by other users online, a plethora of group policy options and a number of my own scripts, I found a combination of settings that worked great for me.

Fixing the netlogon service..

As the netlogon service is starting before the wlan service, we need to delay it starting until after the wireless network is online, we can do that with dependencies. If we make the netlogon service dependant on the wireless network service, then it will wait for the wireless network service to start before it initializes itself. I found this was enough to resolve all the "black screens" and "no domain logon servers available" messages I was recieving. You can achieve that by using this command.

sc config netlogon depend= wlansvc/lanmanworkstation

When you resolve the netlogon problem the group policy issues will quickly fall in line behind it. It may not run immediately at startup, but it will run shortly after, normally within a minute or two. I tested on a number of laptops by using a computer startup script to copy a simple file to the destination computer and found most laptops completed the startup script within 1-2 minutes of startup.

Fixing the App-V services..

Fixing App-V is even easier, all we need to do is set both the App-V client services to run "on demand" instead of be an "automatic" service. We can achieve that by using these two commands.

sc config sftvsa start= demand
sc config sftlist start= demand


Now App-V doesn't initalize until its needed, and this is after the wireless lan service and the netlogon service have already started. No more App-V errors!



Applying these fixes on the fly..

As I use SCCM to deploy all the images on my network I simply added all 3 of these commands to a batch file, created a SCCM package and assigned the batch file as the program of the package. Then I added the created program as part of my SCCM image deployment task sequence.



Other fixes that might work..

Other users have reported having success with upgrading network drivers for some Intel wireless NIC's. Unfortunately for my laptops with the Intel 6200 driver I am using the latest 13.5 driver (at the time of writing this article) and still having problems. Of course when I apply my above fixes, these problems go away.



The downfalls..

Unfortunately there doesn't seem to be any definitive fix for ensuring all group policies and computer startup scripts are applied and completed before the logon prompt appears, that functionality is simply gone from Windows 7. For those users relying heavily on computer startup scripts you have two options, to either plug the computer into a wired network or try to migrate as much of that functionality as possible into user logon scripts. User logon scripts always run properly if the netlogon service has been started and detected the domain before the user logs on.


Update - 04/10/2012

I have been running the netlogon dependency change in my environment for nearly 12 months now and it has been working flawlessly. I have found no side-effects and computer logon scripts/GPO have been working consistently over wireless.

Setting default Windows 7 wallpaper during deployment without enforcing it

At my workplace we decided to do some workstation branding as part of the SCCM deployment process.

We wanted to do this to deliver some of the great wallpapers that students in our ICT classes were creating as part of their photoshop skills projects.

We didn't want to enforce this wallpaper, we wanted to allow users to change the wallpaper to anything they want in the future. This was more about fun than standardization or enforcement, after all some people might want their children or their favourite pet as their wallpaper.

Unfortunately group policy doesn't cater for this type of deployment, with GPO based wallpaper settings its either an enforced wallpaper or nothing at all.

The solution ended up being a fairly easy and elegant one, instead of forcing the wallpapers via registry or default profile hacks, we simply changed Windows 7's default wallpaper to the one of our choosing.

To do this we made a batch file as follows...

---------------------------------------------------

@echo off
takeown /F "%windir%\web\wallpaper\windows\img0.jpg"
icacls "%windir%\web\wallpaper\windows\img0.jpg" /grant administrators:F
REM del /Q /F "%windir%\web\wallpaper\windows\img0.jpg"
move /Y "%windir%\web\wallpaper\windows\img0.jpg" "%windir%\web\wallpaper\windows\img0.bak" /Y
copy "sccm.jpg" "%windir%\web\wallpaper\windows\img0.jpg"
icacls "%windir%\web\wallpaper\windows\img0.jpg" /grant users:R

---------------------------------------------------

Then simply created a package containing that batch file as a program and added the program as part of our SCCM operating system deployment task sequences. This script also copies the original img0.jpg to img0.bak just in case you need to restore it in the future.

You can take this a step further and pick a random wallpaper from a network location to mix up your wallpapers throughout your environment if you want. The code would look something like this..


---------------------------------------------------

@echo off
setlocal enabledelayedexpansion
set folder=wallpapers
set count=0
set x=0

REM put all the files into a pseudo-array prefixed with "PIC_"
for /r "%folder%" %%a in (*.*) do (
    set PIC_!count!=%%~a
    set /a count+=1
)

REM Use the 'modulo' function to get a usable value from system variable %random%
set /a x="%random% %% count"

REM Pull the relevant item out of the "PIC_" 'array'
set chosen=!PIC_%x%!

echo using wallpaper %chosen%

takeown /F "c:\windows\web\wallpaper\windows\img0.jpg"
icacls "c:\windows\web\wallpaper\windows\img0.jpg" /grant administrators:F
REM del /Q /F "c:\windows\web\wallpaper\windows\img0.jpg"
move /Y "c:\windows\web\wallpaper\windows\img0.jpg" "c:\windows\web\wallpaper\windows\img0.bak"
copy "%chosen%" "c:\windows\web\wallpaper\windows\img0.jpg"
icacls "c:\windows\web\wallpaper\windows\img0.jpg" /grant users:R


---------------------------------------------------

Monday 8 August 2011

Gigabyte A75-UD4P + AMD A8-3850 + G.Skill Flare = DDR3-2700

Okay so its not really DDR3-2700 because its single channel, but its still 1350MHz on and AMD platform,

If you were to say 1350MHz memory clocks 3 months ago on AMD platform people would have laughed at you.. The combination of the Gigabyte A75-UD4P with the AMD A8 3850 (Llano core) cpu and G.Skill Flare memories make it very easy to achieve this frequency though.

I simply dropped the CPU multiplier, raised the voltage to the north bridge to around 1.4v, set vdimm at 1.74v and started to slowly increase the bus frequency. The result? 1350MHz validations... With about 1300MHz stable for 3D benchmarks. I tested the CPU on both air and on my single stage that is able to run the temperature at around -50 degrees Celsius and the results were the same, the cold temperatures didn't help.

CPUZ Validation

Yeah I know the CPUZ validation has a big invalid red cross on it, but this is what is currently happening with high memory clocked Llano setups, so there's nothing I can do to get rid of it!

Tuesday 2 August 2011

Citrix Xendesktop 5 Desktop Studio "hangs" when opening HDX Policy node

I recently came across a very inconvenient issue out of the blue with my Citrix Xendesktop 5 environment last week. Just weeks before I had made a number of adjustments to my Xendesktop HDX policies, all successfully, but upon trying to open my Xendesktop HDX policy node 2 weeks later, it just hangs forever with the loading "circle" that it normally only briefly shown as the policies load.








Checking on the policies...

My first step was to confirm there wasn't something odd occurring with the HDX policies themselves, even though there was no problem with the Xendesktop environment itself. This can be achieved by opening a PowerShell console (on the Desktop Studio box of course) and typing the following command.

add-pssnapin citrix*
$pol=Export-BrokerDesktopPolicy
$pol.Length

If the $pol.Length variable returns a non-zero value, then the policies are more than likely still there, but may still have issues.



Enabling the trace logging...

Enabling trace logging on the Desktop Studio console should give us a plethora of information, that may include the error messages associated with the "hanging" issue I am experiencing.

1. Navigate to the "C:\program files\citrix\desktop studio" folder on your Desktop Studio box and open the "MmcSnapin.dll.config"

2. Under the <appSettings> heading, add the following string
<add key="LogFileName" value="c:\DS.log" />






3. Reload the Desktop Studio console. Trace logging is now enabled..

This will log the trace to C:\DS.log




Analysing the trace..

Perhaps the hardest part of the problem is analysing the trace. Trace32 will make easy work of detecting the errors in the log and displaying it in a readable format. Trace32 is part of the SMS/SCCM suite, but it is available as part of a number of downloadable packages from the Microsoft website.

Errors are displayed in red.
Warnings are displayed in yellow.
Black text is purely informational, but can be important to understand what may be causing the red errors.







Back to the HDX Policy problem..

The error I received was a especially nasty one for any program to throw-up..

Exception has been thrown by the target of an invocation. ---> System.Runtime.InteropServices.COMException (0x800736B1): Retrieving the COM class factory for component with CLSID {54C5637D-BAC7-4C38-A2FA-E314971F6090} failed due to the following error: 800736b1.

A COMException of this type would normally indicate some type of C++ conflict, or more broadly a DLL version conflict.

After doing a snapshot backup of my Xendesktop machine I then proceeded to install all the latest versions of C++ 2005, 2008, 2010, 32bit, 64bit... Still no luck.

I needed to take some more serious action. Next I tried the backups from the last 4 weeks, 1 week old, fail, 2 weeks old, fail, 3 weeks old fail, What? I was only playing with HDX policy 2 weeks ago and I did not have these errors, yet the 2 and 3 week old backups are still failing.

Then I realized I probably didn't close my HDX policy console for the previous 2 months before that, so the problem may have occurred some 8 weeks ago without me ever noticing.


A resolution of sorts..

3 days later and still without a resolution my HDX policy changes were becoming more critical and after some help from the Citrix engineering team we were able to find a work around.

Apparantly some early beta releases of XD5 (which I am not using, I have a full production version of XD5 SP1) had some issues with 32bit versions of the HDX policy console. As a work around they loaded a blank mmc.exe (Microsoft's Management Console) and then loaded the Desktop Studio component into this shell. This "forced" Desktop Studio to launch its 64bit component and resultantly load 64bit DLL's to support it.

This workaround IS working and at this point of time I have not had an opportunity to take my Xendesktop server offline to try and resolve the 32bit console problems.

The directions from the Citrix engineers to whom I spoke was to try to do a repair install on the Desktop Studio component and hopefully it would repairs the DLL issues.

I will post an update when I try that, at least for now I can apply more great HDX policies to my environment.

Monday 1 August 2011

Creating shared calendars in exchange 2010 and assigning groups permissions

With the release of Exchange 2010 Microsoft once again made their intention of killing off the "public folder" features blatantly clear. So what does this mean for those wanting to create shared calendars? Well now there are a few hoops to jump through to achieve the goal.

The best solution seems to be to create a new mailbox, then assign permissions to that mailbox's calendar. Unfortunately you can't assign a distribution list access to a shared calendar and this is the step where those new to Exchange 2010 stumble, the answer is Universal Security groups.

Alternatively you can pipe all the distribution list members into a PowerShell script then assign then permissions to the shared calendar.

Get-distributiongroupmember –id Groupname | Add-MailboxFolderPermission -Identity “UserMailbox”  -AccessRights Owner

You would need to repeat this process when you add new users to the distribution list, not a desirable configuration.


Before we get started...

To create our new shared mailbox/calendar is made easier by using a script by Steve Goodman called New-SharedCalendar.ps1, you can grab it from Steve's blog. http://www.stevieg.org/tag/shared-mailbox/



Creating a shared Calendar in Exchange 2010

1. Create a new Universal Security group in active directory, in my case I called the group STAFFUV and then you nest the existing global or domain local security groups within this universal group. You can always just create universal groups and assign users directly to them (or use existing universal groups) but this could mean more administration on your behalf not to mention being against best pratice.

If you want to give different user groups different permissions in the calendar it might be best to create a number of universal groups, e.g. STAFFUV_reviewers STAFFUV_owners and then nest the appropriate groups within them.


2. Next we fire up an Exchange PowerShell console and create our spanking new mailbox using steve's New-SharedCalendar.sp1. This script has the ability to assign users with owner, editor or reviewer permissions.

Lets just assign an "owner" at this stage, then assign the universal groups that we want to use in step 3.

New-SharedCalendar.ps1 -Name "Test Calendar" -Owners "username"


3. We have successfully created our "Test Calendar" mailbox. Steve's script is kind enough to set that mailbox not to be automatically mapped, this is extremely important or Outlook 2007 and above will automatically map that shared mailbox when the user opens their Outlook client.

Next we need to assign permissions using our previously created universal security groups.

Add-MailboxFolderPermission -Identity "Test Calendar:Calendar" -User "STAFFUV" -AccessRights "Reviewer"

You may need to repeat the above command a number of times depending on how many universal groups you want to assign permissions to. The beauty of this process is now when add a user to STAFFUV or one of its nested groups they automatically get the access rights assigned to the universal group, no manual adding.

Breaking down the above command, firstly we have the -Identity variable where we are specifically targeting the "Test Calendar" user's calendar with the ":Calendar" syntax. Secondly we are specifying our previously created universal group "STAFFUV" as the user, and lastly we are giving the STAFFUV group the permission of "Reviewer" which is a read only permission.



Alternatively you can assign:
Owner                                                CreateItems, ReadItems, CreateSubfolders, FolderOwner, FolderContact, FolderVisible, EditOwnedItems, EditAllItems, DeleteOwnedItems, DeleteAllItems
PublishingEditor                       CreateItems, ReadItems, CreateSubfolders, FolderVisible, EditOwnedItems, EditAllItems, DeleteOwnedItems, DeleteAllItems
Editor                                                 CreateItems, ReadItems, FolderVisible, EditOwnedItems, EditAllItems, DeleteOwnedItems, DeleteAllItems
PublishingAuthor                    CreateItems, ReadItems, CreateSubfolders, FolderVisible, EditOwnedItems, DeleteOwnedItems
Author                                              CreateItems, ReadItems, FolderVisible, EditOwnedItems, DeleteOwnedItems
NonEditingAuthor                   CreateItems, ReadItems, FolderVisible
Reviewer                                          ReadItems, FolderVisible
Contributor                                   CreateItems, FolderVisible


4. You have now completed the process, give these changes some time to propagate and when you see the "Test Calendar" user appear in your global address book you can map the "Test Calendar" and proceed with your newly created shared calendar.


This certainly isn't as easy as the old point and click GUI in Exchange 2003 but the PowerShell applets give much more flexibility with automating Exchange functions during the adduser process.