Recent Updates RSS Toggle Comment Threads | Keyboard Shortcuts

  • Vickash 09:00 on January 16, 2012 Permalink | Reply  

    More Secure Passwords In AppleScript 

    Sometimes an Applescript might require user authentication. For example, this will happen if using do shell script to run a UNIX command that needs administrator access:

    do shell script "chown -R Vickash " & quoted form of "/Users/Vickash/Desktop/My Files" with administrator privileges
    

    A dialog box appears prompting the user for their password before the shell script executes. This is fine if your script is always run manually by the user. However, for Folder Actions, or any type of script that runs on a trigger, this can be a problem. What if the user isn’t at the machine when the script is triggered? And if the script runs frequently, do you really want to ask the user for a password each and every time?

    If you’ve come across this problem, you know that one possible solution is to put the login credentials inline. However, the security problem here is obvious; anyone looking at the source code has the user’s login credentials:

    do shell script "chown -R Vickash " & quoted form of "/Users/Vickash/Desktop/My Files" user name "Vickash" password "this is a test" with administrator privileges
    

    Ideally, the password would be stored elsewhere, in an encrypted form, and only accessed by the script when necessary. Luckily, OS X provides an app called Keychain Access (check your Utilities folder) for storing credentials in encrypted form.

    Using Keychains

    Your default keychain is at ~/Library/Keychains/login.keychain, and holds things like Safari’s saved passwords. It’s protected with your login password by default. To keep things clean, I recommend creating a new keychain specifically for storing generic password items that you want Applescript to access. Here’s how:

    1) Open Keychain Access.app and go to File > New Keychain… You can name the keychain whatever you want and store it wherever you want, but take note of it’s full path. You’ll need that for the script to access it later.

    Step 1 - Create A New Keychain

    2) When creating a new keychain, you’ll need to set a password. This is separate from the credentials you want to save within the keychain; it’s a password that restricts access to the keychain itself. Think of it like a LastPass or 1Password master password. This is the password your user will need to type the first time the script runs to allow the script access to the keychain and the credentials within.

    Step 2 - Set the Keychain's Password

    3) Once the keychain is created, create a generic password item by clicking on the “add” button below the empty list. Put in the credentials that you would have typed inline before, and give the item a name. I’ve called it “Admin” here. It doesn’t matter much what you call it, but you’ll need to know the name for the script to find the right item.

    Step 3 - Create the Keychain Item

    By doing this, you’ve now used the keychain’s encryption to protect the username and password that would have been typed as plain text in the script before. Now we need to set the script up to access the keychain.

    4) To make things even more convenient I recommend changing the keychain’s settings so that it doesn’t automatically lock on sleep or after a period of inactivity. You can adjust this to suit your needs, but the idea is that the user allows the script access to the keychain once, the first time the script runs, and then doesn’t need to again until the user logs out.

    Step 4 - Edit the Keychain's Settings


    Step 5 - Keychain Settings

    Accessing the Keychain from AppleScript

    We’ve solved half the problem. The password is stored in an encrypted form on disk rather than in plaintext. But now we need some way to pull those credentials out of the keychain and use them in our script.

    Apple used to provide a standard extension for this. You’d call tell application "Keychain Scripting" and be able to access the keychains, but I’m not sure that’s still exists in Lion, and it had major performance issues before that.

    Daniel Jalkut at Red Sweater Software has written a tiny scriptable app called “Usable Keychain Scripting” for Lion and Pre-Lion systems. It’s free, I’ve used it, and it works great. If you don’t have a problem with installing something extra to get your scripts to run, head over to his blog and check it out.

    If you’d like your scripts to be dependent only on the keychain, like I needed on a couple occasions, I’ve come up with a pure AppleScript workaround. On OS X there’s a shell command called security that can be used from the terminal to access keychains.

    You can read more about the security command here, but the main thing we’re interested in is its find-generic-password option. When using this option and passing in the keychain path, and keychain item name we’re searching for, it returns the full details for the password item as text.

    Running

    security 2>&1 find-generic-password -gs "Admin" "/Users/Vickash/Library/Keychains/ScriptingDemo.keychain"
    

    Returns

    keychain: "/Users/Vickash/Library/Keychains/ScriptingDemo.keychain"
    class: "genp"
    attributes:
        0x00000007 <blob>="Admin"
        0x00000008 <blob>=<NULL>
        "acct"<blob>="Vickash"
        "cdat"<timedate>=0x32303132303131353136343231355A00  "20120115164215Z00"
        "crtr"<uint32>=<NULL>
        "cusi"<sint32>=<NULL>
        "desc"<blob>=<NULL>
        "gena"<blob>=<NULL>
        "icmt"<blob>=<NULL>
        "invi"<sint32>=<NULL>
        "mdat"<timedate>=0x32303132303131353136343231355A00  "20120115164215Z00"
        "nega"<sint32>=<NULL>
        "prot"<blob>=<NULL>
        "scrp"<sint32>=<NULL>
        "svce"<blob>="Admin"
        "type"<uint32>=<NULL>
    password: "this is a test"
    

    Now, it’s obvious that the only two lines we care about are "acct"<blob>="Vickash" and password: "this is a test". By executing the shell command via AppleScript, and writing a separate subroutine to extract the data we need, I’ve come up with the following:

    on extractData(theText, theFieldName, theEndDelimiter, spaces)
        set theDataStart to the offset of theFieldName in theText
        if theDataStart = 0 then
            return ""
        else
            set theDataStart to theDataStart + (length of theFieldName) + spaces
            set theData to text theDataStart through end of theText
            set theDataEnd to ((offset of theEndDelimiter in theData) - 1)
            set theData to text 1 through theDataEnd of theData
        end if
    end extractData
    
    on getCredentials of theKeychainItem from theKeychain
        set theKeychainPath to (POSIX path of theKeychain) as text
        try
            set theKeychainAlias to (POSIX file theKeychainPath) as alias
            set theKeychainPath to (POSIX path of theKeychainAlias)
        on error
            return "The keychain file was not found at the specified location: " & theKeychain as text
        end try
        try
            set theResult to do shell script "security 2>&1 find-generic-password -gs " & quoted form of theKeychainItem & " " & quoted form of theKeychainPath
            set theAccount to extractData(theResult, "\"acct\"<blob>=\"", "\"", 0)
            set thePassword to extractData(theResult, "password: \"", "\"", 0)
            return {account:theAccount, password:thePassword}
        on error
            return "The generic password item was not found in the keychain. Please verify its name: " & theKeychainItem
        end try
    end getCredentials
    

    Practical Use

    Copy these subroutines into your script. Now, whenever your script script needs to get credentials from a keychain, do something like:

    set theCredentials to getCredentials of "Admin" from "/Users/Vickash/Library/Keychains/ScriptingDemo.keychain"
    

    This will return an AppleScript record, in my case:

    theCredentials {account: "Vickash", password: "this is a test"}
    

    Now that the script has the login credentials stored in a record, I can execute the command that would have required manual authentication like:

    do shell script "chown -R Vickash " & quoted form of "/Users/Vickash/Desktop/My Files" user name (account of theCredentials) password (password of theCredentials) with administrator privileges
    

    Which is much more secure than:

    do shell script "chown -R Vickash " & quoted form of "/Users/Vickash/Desktop/My Files" user name "Vickash" password "this is a test" with administrator privileges
    

    Notes

    Keep in mind that the first time the script runs it will prompt you for the keychain password to unlock it. Put the password in and click “Always Allow” to give the script continuous access to the keychain. If you’ve used the settings I recommended, the keychain won’t relock until it’s manually relocked via the Keychain Access app, or until the user logs out.

    The getCredentials handler returns text, rather than a record, on error, so you can write your script to catch this and display a dialog box.

     
  • Vickash 15:59 on January 2, 2012 Permalink | Reply
    Tags: Applescript, Automation, Growl   

    A Simpler Way To Use Growl With Applescript 

    Introduction

    Growl is a great pop-up notifier that many Mac applications integrate with. If you write Applescripts for yourself or others, it’s useful for displaying pop-up notifications, rather than dialog boxes, notifying users when a script runs on a schedule, or a trigger, or even to send users reminders.

    However, Growl suffers from a wordy AppleScript implementation. Each time you want to send a new notification, you have to register your application with Growl, register the notification with Growl, and then display it. Also, there are a bunch of version-incompatible ways to access the scriptable Growl object.

    This is an attempt to wrap all of this wordiness up into a single AppleScript handler which will let you create Growl notifications with a single line.

    How To Set It Up

    Step 1: Make sure you have Growl version >= 1.2.2 on your Mac. This might work with older versions, but I haven’t tested it.

    Step 2: Copy the following property and handler into the Applescript that you want to send Growl notifications from:

      property allNotifications : {}
      on growl(theTitle, theContent)
        if allNotifications does not contain theTitle then
            set allNotifications to allNotifications & theTitle
        end if
        set myName to path to me as text
        set TID to text item delimiters
        set text item delimiters to ":"
        set myName to the last text item of myName
        set text item delimiters to TID
        tell application id "com.Growl.GrowlHelperApp"
            register as application myName ¬
                all notifications allNotifications ¬
                default notifications allNotifications ¬
                icon of application "AppleScript Editor"
            notify with name theTitle title theTitle description theContent application name myName
        end tell
      end growl
    

    Step 3: When you want your script to send a notification, call the growl handler, passing in the notification title and content as arguments:

      growl("Notification Title", "This is the content of the notification.")
    

    That’s it!

    How It Works

    The allNotifications property is a list of all the notifications your script has already registered with Growl. Each time you call the growl handler, it checks to see if the title you passed in is in the list. If it isn’t, it gets added to the list, and registered with Growl.

    Next, we get the file path to your script and extract the filename. This is used as the “application name” to register the script with Growl. The register line does the registering, telling it to use AppleScript Editor’s icon for the notification. The notify line displays the actual notification.

    Notes

    1) allNotifications is an AppleScript property, which persists across runs, but resets to an empty list when you edit or recompile the script. This means that, if you’ve set up custom styles or priorities in Growl for your script’s notifications, they get reset if you edit or recompile.

    In most cases, this won’t matter, but if it does to you, you can modify the handler to store the list of notifications in a text file in the same folder as the script, and read it in on each run. Overkill for my needs, but definitely a workable solution.

    2) You can replace “AppleScript Editor” with the name of any app whose icon you’d like to use for the notification.

    3) You’ll notice that I’ve addressed the Growl application by its id and not by its name. This is because:

    tell application "Growl" works with version 1.3 and up only, but

    tell application "GrowlHelperApp" works with version 1.2.2 and lower only.

    I’ve found that by avoiding names altogether, and addressing it via id, the script works with all versions. Scripts you create with this handler should work regardless of which version of Growl is installed on the user’s system.

    More About Growl

    Growl used to be an OS X preference pane, but with version 1.3, it moved to the Mac App Store, so it’s now a $1.99, 64-bit, Lion-only application. Version 1.2.2 is still available for free at http://www.growl.info. It states compatibility with 10.5 and 10.6, but works fine on 10.7 as well. Version 1.3 adds some nice features, and I like that it’s an application rather than a preference pane, but the core functionality of both is mostly identical for now.

     
    • Zettt 09:28 on January 8, 2012 Permalink | Reply

      Vickash, I found your blog by search for AppleScript centric blogs on Google to subscribe to and found yours.
      You don’t actually need to use text item delimiters to get the script’s name. There’s a one-liner that does that. Unfortunately I can’t find it anymore in my scripts & snippets archive nor on the web. I’m sorry. Hope you find this little tip still helpful.

      • Vickash 09:10 on January 10, 2012 Permalink | Reply

        Thanks Zettt. I can never remember the shorter version when I need it, but after messing around for a minute I did. It’s:

        get name of (info for (path to me))

        • Zettt 09:39 on January 10, 2012 Permalink

          Yes, that’s it! Thanks for the feedback. *writes down snippet dilligently*

  • Vickash 20:59 on November 4, 2010 Permalink | Reply  

    Random Shot Of The Day: Going Home 

    Riche and I went to PhotoPlusExpo in New York for the weekend. We spent our time learning from some of the best photographers in the world, running around the expo floor, shopping a bit, and causing general mayhem. See Riche’s Vimeo profile for more on that last one.

    Going Home

    Camera: Nokia E72, Plane: Boeing 737-800, Seat: 15F.

     
  • Vickash 12:48 on November 2, 2010 Permalink | Reply  

    Rapture By Tom Lowe @ TimeScapes 

    I just saw this on Vincent Laforet’s blog and had to repost it. I first heard about this in the Canon booth at PhotopPlusExpo over the weekend. Alex Buono was speaking about using Canon DSLRs for video production on SNL, and cited it as a source of inspiration.

    Awesome motion time-lapse and over-cranked slow-motion shots, all set to a perfect soundtrack. Click the Vimeo link in the video below to watch it in HD. Download it and watch it on your HDTV. Project it on your wall or something. Get the picture as big as you can and turn up the volume. Then check out the TimeScapes project.

     
  • Vickash 16:22 on September 9, 2010 Permalink | Reply  

    Random Shot Of The Day: Headphones 

    Headphones

    Sennheiser HD202 Headphones

     
    • Wizzythestick 17:05 on October 26, 2010 Permalink | Reply

      Hi Vickash,
      Lovely blog and great pictures. I especially like the phone camera pics:-) you might be on to something there. Just one complaint/question. So now that I found you how do I follow? Where is your RSS feed button?

      • vixm 10:35 on November 2, 2010 Permalink | Reply

        Thanks Wizzy! Hmm..RSS…good question. I didn’t really think about it. I assumed WordPress would put an RSS button somewhere on the site itself.

        In Safari, you browse to the site and the RSS button shows up in the address bar, and it should in Firefox too. But just in case, you can use this link:

        feed://vickash.com/feed/

  • Vickash 19:01 on September 2, 2010 Permalink | Reply  

    Random Shot Of The Day: 250K 

    I spend way too much time driving…but I used a few seconds at a stoplight and my E72 to capture this today.

    250K

    250K

     
  • Vickash 22:49 on August 17, 2010 Permalink | Reply  

    Random Shot Of The Day: SLRs Still Take Pictures? 

    I’ve been working with so much video lately, I almost forgot that SLRs still take pictures. Here’s the first shot I’ve taken with my new Sigma 24mm f/1.8 Prime Lens. Just available light in my room with a sneak peak of something new we’re working on onscreen.

    An Apple A Day...

    An Apple A Day...

     
  • Vickash 08:00 on July 30, 2010 Permalink | Reply  

    Random Shot Of The Day: Ryan 

    My cousin is spending a couple days with us. And he gets bored easily, so we did a little photo shoot to keep him busy.

    Ryan

    Ryan

     
  • Vickash 21:00 on July 20, 2010 Permalink | Reply  

    Random Shot of The Day: Veer & Navisha 

    Here’s a preview of our HDSLR wedding coverage. Check it out on the Vimeo site to see it in HD!

     
  • Vickash 13:35 on April 28, 2010 Permalink | Reply  

    Random Shot Of The Day: Icy Blue 

    Took this with my sister’s Nokia 5730 the other night. Used my E72 to light up the glass.

    Icy Blue

    Icy Blue

     
c
compose new post
j
next post/next comment
k
previous post/previous comment
r
reply
e
edit
o
show/hide comments
t
go to top
l
go to login
h
show/hide help
shift + esc
cancel
Follow

Get every new post delivered to your Inbox.