Everything is Gray

A place to put stuff.

AutoPkgr - a Front End for AutoPkg

| Comments

Recently, a couple coworkers of mine and I released AutoPkgr, a GUI front end for AutoPkg. AutoPkg is an extremely powerful command-line tool that allows IT administrators to automate OS X software packaging and distribution. AutoPkgr extends this functionality by adding the following key features:

  • Easy tracking of which specific AutoPkg recipes you care about.
  • Automatic scheduled checks for new downloads that are available as part of the AutoPkg recipes you subscribe to.
  • Email notifications when new items are downloaded.

AutoPkgr

It’s been a ton of fun developing AutoPkgr, and best of all the response from the community has been fantastic.

Here’s to making awesome tools and sharing them.

Complex LDAP Queries With Ldapsearch and Python-ldap

| Comments

I recently needed to test a complex LDAP query in a Python script I was writing. I realized shortly after beginning to construct the query that I had never done anything more than a simple a=b or a=b* before, (where * is the wildcard). The solution is rather simple, albeit awkward due to the position of the binary operators. You’ll notice in the examples below that the operators are positioned before each operand. So rather than a & b, you would write &(a)(b).

To test the query I used the trusty ldapsearch utility. For example, to find the email addresses of all users in the “Example” OU that 1) have a nickname beginning with “M”, 2) are full time employees, and 3) their department number doesn’t start with “5” or their login shell is /bin/bash, use the following command:

ldapsearch -LLL -x -H ldap://ldap.example.com -b "ou=Example,dc=example,dc=com" '(&(nickname=M*)(employeeType=fulltime)(|(!(departmentNumber=5*))(loginShell=/bin/bash)))' mail | awk '/mail: / { print $2 }'

To perform the same query in Python, try the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import ldap
import sys

LDAP_URI = 'ldap://ldap.example.com'
SEARCH_BASE = 'ou=Example,dc=example,dc=com'
QUERY = '(&(nickname=M*)(employeeType=fulltime)(|(!(departmentNumber=5*))(loginShell=/bin/bash)))'


def ldap_search(ldap_uri, base, query):
  '''
  Perform an LDAP query.
  '''
    emails = []

    try:
        l = ldap.initialize(ldap_uri)
        l.protocol_version = ldap.VERSION3

        search_scope = ldap.SCOPE_SUBTREE
        retrieve_attributes = None

        ldap_result_id = l.search(
            base,
            search_scope,
            query,
            retrieve_attributes
        )
        result_set = []
        while 1:
            result_type, result_data = l.result(ldap_result_id, 0)
            if (result_data == []):
                break
            else:
                if result_type == ldap.RES_SEARCH_ENTRY:
                    result_set.append(result_data)

        if len(result_set) == 0:
            print('No results found.')
            return

        count = 0
        for i in range(len(result_set)):
            for entry in result_set[i]:
                try:
                    email = entry[1]['mail'][0]
                    count += 1
                    emails.append(email)
                except:
                    pass

    except ldap.LDAPError, e:
        print('LDAPError: %s.' % e)

    finally:
        l.unbind_s()
        print(emails)


def main():
    ldap_search(LDAP_URI, SEARCH_BASE, QUERY)


if __name__ == '__main__':
    sys.exit(main())

Happy LDAP’ing.

Python One-Liner for Determining Java Vendor

| Comments

Here’s a Python one-liner that prints the Java vendor on OS X clients, (e.g., Apple or Oracle).

1
python -c 'import os,plistlib; jv = plistlib.readPlist(os.path.join(os.path.realpath("/Library/Internet Plug-Ins/JavaAppletPlugin.plugin"), "Contents/Info.plist"))["CFBundleIdentifier"].split(".")[1]; print jv.capitalize()'

Why?

…Because we can.

Querying AD Group Membership Status With Ldapsearch

| Comments

Here’s a way to query Active Directory for group membership status with the ldapsearch utility. In my case, this was used to check if a user is authorized before attempting to mount an SMB share at login on OS X clients. The -Q option causes ldapsearch to use SASL quiet mode and not prompt for a password, which works if a Kerberos ticket is present.

    #!/bin/bash

    console_user="$(/usr/bin/stat -f%Su /dev/console)"
    ldap_uri="ldap://example.com"
    search_base="DC=example,DC=com"
    group="Some Group"
    is_member_of_group=`/usr/bin/ldapsearch -LLL -Q -H "$ldap_uri" -b "$search_base" "sAMAccountName=$console_user" sAMAccountName | $grep "OU=$group"` # -Q prevents the authentication prompt, works if kerberos ticket exists

    if [[ "${#is_member_of_group}" -ne "0" ]]; then
        echo "$console_user is a member of $group."
        # Do something about it
    else
        echo "$console_user is NOT a member of $group."
        # Do something else
    fi

    exit $?

Ghost in the Cloud: Deploying the JSS on Amazon EC2

| Comments

The fine folks at JAMF Software have posted a video of the talk I gave at this year’s JNUC. I had a great time in Minneapolis and hope to attend again next year.

The slides for this talk are available on my GitHub if you want to follow along.

It’s not uncommon in the “lean startup” world for a company to have a strong aversion to onsite infrastructure. This presents IT administrators with the challenge of hosting and scaling their infrastructure elsewhere. Although there are many similarities between hosting the JSS locally and in “the cloud”, there are some key differences to be aware of to ensure a successful deployment.

Option (Left|right) Arrow Navigation in iTerm2

| Comments

Today I decided to switch to iTerm2 on OS X. Shortly after making this decision I was frustrated by not being able to “jump” between words with the option-arrow shortcut. Fortunately, the solution is rather simple — just modify the option-left/right arrow shortcuts in Preferences > Profiles > Keys. The “Action” should be “Send Escape Sequence” + b for jumping backwards and f for jumping forward, (e.g., ^[b, and ^[f).

I know I’ve tried iTerm in the past, and I’m pretty sure not being able to do this right away kept me from continuing to use the tool. After making this change everything has been swell, though.

iTerm2 Preferences

Determining Guest Login Status

| Comments

The other day I was presented with the challenge of determining whether Guest login was enabled on 150+ Macs. Fortunately, my client was using the Casper Suite, so I was able to whip up an Extension Attribute rather quickly. Here’s what I came up with to get the status:

cURL Speed Test

| Comments

Have you ever needed to run a quick download speed test, but were too lazy to open up a new browser window and use one of the Web-based tools? Or perhaps you just prefer to use the command-line like me. Never fear, because appending this line to your ~/.bash_profile will allow you test your download speed from within your login shell by simply typing speedtest.