Skip to content

Instantly share code, notes, and snippets.

@zakes-it
Created July 23, 2019 22:28
Show Gist options
  • Save zakes-it/723ea10afc3fe24783c71919b0efec62 to your computer and use it in GitHub Desktop.
Save zakes-it/723ea10afc3fe24783c71919b0efec62 to your computer and use it in GitHub Desktop.
provides Active Directory binding and group conditions data for Munki
#!/usr/bin/python
"""
Provides Munki with the following custom conditions related to Active Directory:
adBound: boolean for if the computer is bound to AD
adDomain: the fully qualified Active Directory Domain name or an empty
string if not bound
adConnected: boolean for if the computer can communicate with the domain
adUserGroups: a list of AD security groups the currently logged in user is a
member of. List will be empty if the computer is not bound or no user is
logged in.
"""
import os
import sys
from SystemConfiguration import SCDynamicStoreCreate, SCDynamicStoreCopyValue
from OpenDirectory import ODNode, ODSession, kODRecordTypeUsers, \
kODRecordTypeGroups
sys.path.append('/usr/local/munki')
import munkilib.munkicommon as munkicommon, munkilib.FoundationPlist as FoundationPlist
def get_bind_info():
"""Returns Active Directory domain details or None if the computer is not bound"""
net_config = SCDynamicStoreCreate(None, "net", None, None)
try:
ad_info = dict(SCDynamicStoreCopyValue(net_config,
'com.apple.opendirectoryd.ActiveDirectory'))
except:
#not bound
return None
return ad_info
def connect_node(ad_info):
adpath = '{0}/{1}'.format(ad_info['NodeName'], ad_info['DomainNameDns'])
node, error = ODNode.nodeWithSession_name_error_(
ODSession.defaultSession(), adpath, None)
return node
def get_groups(nodename):
consoleuser = munkicommon.getconsoleuser()
if consoleuser:
node, error = ODNode.nodeWithSession_name_error_(ODSession.defaultSession(), '/Local/Default', None)
record, error = node.recordWithRecordType_name_attributes_error_(kODRecordTypeUsers, consoleuser, None, None)
groups, error = record.valuesForAttribute_error_("dsAttrTypeNative:cached_groups", None)
adgroups = [FoundationPlist.readPlistFromString(data)["dsAttrTypeStandard:RealName"][0] for data in groups]
else:
adgroups = []
return adgroups
def write_to_plist():
managedinstalldir = FoundationPlist.readPlist('/Library/Preferences/ManagedInstalls.plist')['ManagedInstallDir']
conditionalsplist = managedinstalldir + '/ConditionalItems.plist'
if os.path.exists(conditionalsplist):
conditionals = FoundationPlist.readPlist(conditionalsplist)
else:
conditionals = dict()
conditionals['adBound'] = bound
conditionals['adDomain'] = domain
conditionals['adConnected'] = connected
conditionals['adUserGroups'] = adgroups
FoundationPlist.writePlist(conditionals, conditionalsplist)
ad_info = get_bind_info()
if ad_info:
bound = True
domain = ad_info['DomainForestName']
node = connect_node(ad_info)
if node:
connected = True
else:
connected = False
adgroups = get_groups(ad_info['DomainNameFlat'])
else:
bound = False
domain = ""
connected = False
adgroups = []
write_to_plist()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment