Archive

Posts Tagged ‘Mac Sysadmin’

Scripting Remote Desktop Bookmarks

February 29, 2016 Leave a comment

A few years ago I was searching for a way to easily create bookmarks in Microsoft Remote Desktop 8 on the Mac. Prior to version 8 you could drop an .RDP file on a machine and that was really all you needed to do to give your users the ability to connect to servers. Granted, you can still use this method, it’s just a bit sloppier, in my opinion.

So I went searching for a way to script the bookmarks, and that led me to my good friend Ben Toms’ (@macmuleblog) blog. I found his post, “HOW TO: CREATE A MICROSOFT REMOTE DESKTOP 8 CONNECTION” and started experimenting. After some trial and error, I discovered that using PlistBuddy to create the bookmarks just wasn’t being consistent. So I looked into using the defaults command instead. I finally was able to settle on the following script:

#!/bin/sh
# date: 18 Jun 2014
# Name: RDC-Connection.sh
# Author: Steve Wood (swood@integer.com)
# updated: 29 Feb 2016 - included line to add remote program to start on connection for @gmarnin
# grab the logged in user's name
loggedInUser=`/bin/ls -l /dev/console | /usr/bin/awk '{ print $3 }'`
# global
RDCPLIST=/Users/$loggedInUser/Library/Containers/com.microsoft.rdc.mac/Data/Library/Preferences/com.microsoft.rdc.mac.plist
myUUID=`uuidgen`
LOGPATH='/private/var/inte/logs'
# set variables
connectionName="NAME YOUR CONNECTION"
hostAddress="SERVERIPADDRESS"
# if you need to put an AD domain name, put it in the userName variable, otherwise leave blank
userName='DOMAINNAME\'
userName+=$loggedInUser
resolution="1280 1024"
colorDepth="32"
fullScreen="FALSE"
scaleWindow="FALSE"
useAllMonitors="TRUE"
set -xv; exec 1> $LOGPATH/rdcPlist.txt 2>&1
defaults write $RDCPLIST bookmarkorder.ids -array-add "'{$myUUID}'"
defaults write $RDCPLIST bookmarks.bookmark.{$myUUID}.label -string "$connectionName"
defaults write $RDCPLIST bookmarks.bookmark.{$myUUID}.hostname -string $hostAddress
defaults write $RDCPLIST bookmarks.bookmark.{$myUUID}.username -string $userName
defaults write $RDCPLIST bookmarks.bookmark.{$myUUID}.resolution -string "@Size($resolution)"
defaults write $RDCPLIST bookmarks.bookmark.{$myUUID}.depth -integer $colorDepth
defaults write $RDCPLIST bookmarks.bookmark.{$myUUID}.fullscreen -bool $fullScreen
defaults write $RDCPLIST bookmarks.bookmark.{$myUUID}.scaling -bool $scaleWindow
defaults write $RDCPLIST bookmarks.bookmark.{$myUUID}.useallmonitors -bool $useAllMonitors
#comment out the following if you do not need to execute a program on start of connection
# You can adjust the string to be any app that is installed.
defaults write $RDCPLIST bookmarks.bookmark.{$myUUID}.remoteProgram -string "C:\\\\Program Files\\\\\\\\Windows NT\\\\Accessories\\\\wordpad.exe"
chown -R "$loggedInUser:staff" /Users/$loggedInUser/Library/Containers/com.microsoft.rdc.mac
view raw gistfile1.txt hosted with ❤ by GitHub

You can find that code in my GitHub repo here.

RDC URI Attribute Support

I had posted that script up on JAMF Nation back in June 2014 when someone had asked about deploying connections. Recently user @gmarnin posted to that thread asking if anyone knew how to add an alternate shell key to the script. After no response, he reached out to me on the Twitter (I’m @stevewood_tx in case you care). So, I dusted off my script, fired up my Mac VM, and started experimenting.

The RDC GUI does not allow for a place to add these URI Attributes. I read through that web page and Marnin forwarded me this one as well. Marnin explained that he was able to get it to work when he exported the bookmark as an .RDP file and then used a text editor to add the necessary “alternate shell:s:” information. Armed with this knowledge, I went to the VM and started testing.

First I created a bookmark in a fresh installation of RDC. I had no bookmarks at all. After creating a bookmark I jumped into Terminal and did a read of the plist file and came up with this:

YosemiteVM:Preferences integer$ defaults read /Users/integer/Library/Containers/com.microsoft.rdc.mac/Data/Library/Preferences/com.microsoft.rdc.mac.plist
{
QmoteUUIDKey = "ff870b10-7e8e-47c2-98bd-f14f3f0cd1b0";
"bld_number" = 26665;
"bookmarklist.expansionStates" = {
GENEREAL = 1;
};
"bookmarkorder.ids" = (
"{2a3925d6-659e-456e-ab03-86919b30b54b}"
);
"bookmarks.bookmark.{2a3925d6-659e-456e-ab03-86919b30b54b}.fullscreenMode" = "@Variant(\177\017FullscreenMode\001)";
"bookmarks.bookmark.{2a3925d6-659e-456e-ab03-86919b30b54b}.hostname" = "termserv.company.com";
"bookmarks.bookmark.{2a3925d6-659e-456e-ab03-86919b30b54b}.label" = Test;
"bookmarks.bookmark.{2a3925d6-659e-456e-ab03-86919b30b54b}.username" = "";
"connectWindow.geometry" = <01d9d0cb 00010000 000001b4 000000a0 000003b9 0000033f 000001b4 000000fc 000003b9 0000033f 00000000 0000>;
"connectWindow.windowState" = <000000ff 00000000 fd000000 00000002 06000002 44000000 04000000 04000000 08000000 08fc0000 00010000 00020000 00010000 000e0074 006f006f 006c0042 00610072 01000000 00ffffff ff000000 00000000 00>;
lastdevinfoupd = 1456781093;
lastdevresourceupd = 1456781153;
"preferences.ignoredhosts" = (
"10.93.209.210:3389"
);
"preferences.resolutions" = (
"@Size(640 480)",
"@Size(800 600)",
"@Size(1024 768)",
"@Size(1280 720)",
"@Size(1280 1024)",
"@Size(1600 900)",
"@Size(1920 1080)",
"@Size(1920 1200)"
);
"show_whats_new_dialog" = 0;
"stored_version_number" = "8.0.26665";
tlmtryOn = 1;
}
view raw gistfile1.txt hosted with ❤ by GitHub

Now that we had a baseline, I exported the bookmark to the desktop of the VM, edited it to add the “alternate shell” bits, and then re-imported it into RDC as a new bookmark. I then tested to make sure it would work as advertised. After some trial and error, I was able to get the exact syntax for the “alternate shell” entry to work. Now I just needed to see what changes were made in the plist file. A quick read showed me the following:

YosemiteVM:Preferences integer$ defaults read /Users/integer/Library/Containers/com.microsoft.rdc.mac/Data/Library/Preferences/com.microsoft.rdc.mac.plist
{
QmoteUUIDKey = "ff870b10-7e8e-47c2-98bd-f14f3f0cd1b0";
"bld_number" = 26665;
"bookmarklist.expansionStates" = {
GENEREAL = 1;
};
"bookmarkorder.ids" = (
"{2a3925d6-659e-456e-ab03-86919b30b54b}"
);
"bookmarks.bookmark.{2a3925d6-659e-456e-ab03-86919b30b54b}.fullscreenMode" = "@Variant(\177\017FullscreenMode\001)";
"bookmarks.bookmark.{2a3925d6-659e-456e-ab03-86919b30b54b}.hostname" = "termserv.company.com";
"bookmarks.bookmark.{2a3925d6-659e-456e-ab03-86919b30b54b}.label" = Test;
"bookmarks.bookmark.{2a3925d6-659e-456e-ab03-86919b30b54b}.username" = "";
"bookmarks.bookmark.{2a3925d6-659e-456e-ab03-86919b30b54b}.remoteProgram" = "C:\\\\Program Files\\\\\\\\Windows NT\\\\Accessories\\\\wordpad.exe";
"connectWindow.geometry" = <01d9d0cb 00010000 000001b4 000000a0 000003b9 0000033f 000001b4 000000fc 000003b9 0000033f 00000000 0000>;
"connectWindow.windowState" = <000000ff 00000000 fd000000 00000002 06000002 44000000 04000000 04000000 08000000 08fc0000 00010000 00020000 00010000 000e0074 006f006f 006c0042 00610072 01000000 00ffffff ff000000 00000000 00>;
lastdevinfoupd = 1456781093;
lastdevresourceupd = 1456781153;
"preferences.ignoredhosts" = (
"10.93.209.210:3389"
);
"preferences.resolutions" = (
"@Size(640 480)",
"@Size(800 600)",
"@Size(1024 768)",
"@Size(1280 720)",
"@Size(1280 1024)",
"@Size(1600 900)",
"@Size(1920 1080)",
"@Size(1920 1200)"
);
"show_whats_new_dialog" = 0;
"stored_version_number" = "8.0.26665";
tlmtryOn = 1;
}
view raw gistfile1.txt hosted with ❤ by GitHub

The key is the line that has “remoteProgram” as part of the entry. You have to get the full path on the Windows machine to the application you want to run on connection to the server. Once you know that path, you can adjust your bookmark script however you need.

The script I posted above, and is linked in my GitHub repo, contains the line to add that Remote Program (alternate shell). If you do not need it, just comment it out of the script.

 

Upgrading Adobe Flash Player

December 18, 2015 1 comment

Recently on JAMF Nation there was a discussion about the Adobe Flash Player Distribution site going away. This site is where admins can go to get a copy of Flash that can then be legally distributed to their fleet of machines. The discussion started out to be about the change Adobe recently made to the URL for this site, but quickly turned to a discussion around distribution of Flash via Casper.

While I have signed up for the Adobe distribution site, I currently utilize a PKG file that comes from AutoPKGr (I replaced my Jenkins install with AutoPKGr last year sometime). Utilizing AutoPKGr makes my life easier, because I do not have to do anything except update my policy to replace the actual PKG file. I’m not going to go into setting up AutoPKGr for use with Casper, there have been plenty of discussions on that, but rather I am going to list out my procedures for processing Flash upgrades.

It’s Upgrade Day

I typically find out that there is a Flash upgrade from JAMF Nation. Someone typically posts that there is a Flash update almost immediately upon release. Once I’ve verified that the update has been uploaded to my JSS by AutoPKGr, I will go update my policy, changing out the PKG file.

As you will see, the policy is set to trigger on “Recurring Check-In” because I don’t care if a web browser is open or not. Flash can be installed while browsers are open, the users just have to restart the browsers that are open after the update. We’ll handle letting them know via a CocoaDialog script.

There are a few pre-requisite items we need to have in place for this process to work. First, we need to have a way to grab the Flash version off of the machines in our fleet. Second, we need to have a Smart Group that will capture all of the machines that are out of spec. This will allow us to scope our policy to those machines.

Grab the Version

I utilize an Extension Attribute to grab the version of Flash and store it in the database. While it can be argued that utilizing an EA to grab the version is not efficient, since the EA will run every time a Recon runs, there really isn’t another reliable method for grabbing the version.

So, setup an EA to grab the version of Flash. My EA is named “AdobeFlashVersion” and utilizes the following BASH script:

#!/bin/bash
FlashVersion=$(defaults read /Library/Internet\ Plug-Ins/Flash\ Player.plugin/Contents/Info.plist CFBundleShortVersionString)
echo "<result>$FlashVersion</result>"
exit 0
view raw gistfile1.txt hosted with ❤ by GitHub

That’s pretty straight forward. Now that we have the version, we can build our Smart Group.

Screen Shot 2015-12-18 at 5.38.04 PM.png

As you can see, just pick your EA name out of the list of criteria to search for, and enter the version you are searching for using the “is not” operator.

Policy Time

Now that we’ve got our Smart Group collecting machines that are out of date, we can build our policy to install the update. We will name our policy “Update Flash Player” and place it in whichever category makes sense to your deployment of Casper.

I have my update policy set to run at “Recurring Check-in”, which means that machines will update as soon as they contact the JSS. The frequency is set to “Once per computer”, since we only need it to run one time.

General

We’ll click on Packages next so that we can add our Flash package. Click on Configure to get a list of all packages in the JSS:

 

Screen Shot 2015-12-18 at 5.32.24 PM.png

We should now have a list of all packages that the JSS knows about. Locate our latest Flash Player package and click Add to add it to the policy:

Screen_Shot_2015-12-18_at_5_32_29_PM.png

I utilize a script that runs after Flash has been installed to notify end users to restart any open web browsers. My script uses CocoaDialog to make these notifications, but you can use the built in notification process that Casper has. The script I utilize is below:

#!/bin/sh
CD="/path/to/cocoaDialog.app/Contents/MacOS/cocoaDialog"
# pass the title, text, and Icon via $4, $5, $6, and timeout via $7
cdTitle=$4
cdText=$5
# what icon to use
# if no icon is given, set a default
if [[ -z "$6" ]]; then
cdIcon="/private/var/inte/icons/globeDownload.icns"
else
cdIcon=$6
fi
if [[ -z "$7" ]]; then
cdTimeout="--no-timeout"
else
cdTimeout="--timeout $7"
fi
bubble=`$CD bubble --title "$cdTitle" $cdTimeout --text "$cdText" --icon-file $cdIcon`
exit 0
view raw gistfile1.txt hosted with ❤ by GitHub

Now that we’ve added that script to our policy, we will add a line to the Files & Processes tab to set Flash to not auto update.

FilesAndProcesses.png

That line of information in the Execute Command box simply adds a line to a file called mms.cfg to tell Flash Player to not try to auto update. The line is:

touch /Library/Application\ Support/Macromedia/mms.cfg | echo "AutoUpdateDisable=1" > /Library/Application\ Support/Macromedia/mms.cfg
view raw gistfile1.txt hosted with ❤ by GitHub

The final thing for us to do is to add our Scope. Just click on the Scope tab at the top and add our Update Flash Smart Group:

Screen Shot 2015-12-18 at 6.01.26 PM.png

 

That’s all there is. Now that we have our update policy in place, each time there’s a new version we just have a few simple steps to update our end users:

  1. Get the new Flash package into the JSS
  2. Change our Smart Group to look for the new version number
  3. Change our policy to remove the old version and add the new version
  4. Finally, Flush All on the policy logs so everyone in the Smart Group gets the update.

 

I have been utilizing this method for updating Flash for well over a year now, and I have not had any troubles at all.

I hope this quick article has helped you out.

 

Categories: Tech Tags: , , ,

Meet My New Assistant – Jenkins

October 31, 2013 Leave a comment

Continuing with my posts on automation, or at least the automation of package building, I’d like to introduce you to my new assistant, Jenkins.  Jenkins is a continuous integration server.  Continuous Integration, or CI, is defined by Wikipedia as:

Continuous integration (CI) is the practice, in software engineering, of merging all developer working copies with a shared mainline several times a day.

To put it plainly, or to put it into the perspective of a Mac sysadmin, Jenkins can be used to run shell commands at a given interval, or to run several commands in series.  We can then use CRON like scheduling within Jenkins to run these commands at a given time each day, each week, or whatever interval you give.

Jenkins will require the use of the Java 6 JRE on the machine you run it on.  You can go out to the Jenkins CI web site (http://jenkins-ci.org/) to download the installer for Mac.  Once you have downloaded the software, while logged in as an admin on the machine, run the Jenkins installer PKG.  After the installation has completed, either restart the computer, or open a Terminal window and load the LaunchDaemon:

launchctl load /Library/LaunchDaemon/org.jenkins-ci.plist

If Java is not installed you may be prompted to load Java.  After completing these steps, open a web browser and navigate to the home page for Jenkins:

http://localhost:8080

You should hopefully see the Jenkins dashboard, which looks similar to this:

JenkinsHome

NOTE:  If you receive an error about the home folder, try restarting the computer.

You can also check this web site for more info:  https://wiki.jenkins-ci.org/display/JENKINS/Thanks+for+using+OSX+Installer

If you successfully loaded the Jenkins dashboard, then you are all set to start using the power of a CI server.  I utilize Jenkins to work with my AutoPkg installation (on the same machine) so that I can build packages while I sleep.

Next up we’ll look at integrating Jenkins and AutoPkg.