Last active
March 1, 2017 18:14
-
-
Save joshua-d-miller/d511e3390be75c9d5d7e707effd4dfed to your computer and use it in GitHub Desktop.
This script can be used an extension attribute in jamf that will determine if the User Identity Preference is present on the system with an 802.1x EAP-TLS profile. Note: Make this script have the same exclusion and target policy as your configuration profile.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# pylint: disable=C0103, W0612, E1101, E0602, E0611 | |
# pylint: disable=W0101, W0110, W0141 | |
''''Report presence of 802.1x User Identity Preference for EAP-TLS''' | |
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # | |
# | |
# This script will determined if the KeyChain item that needs created | |
# for 802.1x EAP-TLS to work on all systems with multiple items is | |
# present. This information is then reported to jamf. | |
# | |
# Joshua D. Miller - [email protected] - The Pennsylvania State University | |
# Last Updated Friday February 23, 2016 | |
# | |
# Many Many Thanks to Michael Lynn and Mosen for taking me down | |
# the rabbit hole that is PyObjC | |
# | |
# References | |
# https://gist.github.com/pudquick/8ad859f30438f3be149fe9751391d037 | |
# https://gist.github.com/pudquick/4cf32c2b403bf0be23b268d6dd3cf803 | |
# https://github.com/mosen/pudquick-pyobjc-framework-Security/ | |
# blob/master/metadata/raw/x86_64-10.12.fwinfo | |
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # | |
# Most of EAP 802.1x and Keychain PyObjC code from Michael Lynn | |
# Instructions on using SecIdentityCopyPreferred and SecIdentityPreferred | |
# provided by Mosen | |
from __future__ import print_function | |
from Foundation import NSBundle | |
import objc | |
def get_profile_uuid(): | |
'''Get the UUID of the Configuration Profiles 802.1x Identity | |
Preference''' | |
EAP8021X_bundle = NSBundle.bundleWithPath_( | |
'/System/Library/PrivateFrameworks/EAP8021X.framework') | |
E_functions = [ | |
('EAPOLControlCopyStateAndStatus', 'i*o^io^@'), | |
('EAPOLClientConfigurationCreate', '@^@'), | |
('EAPOLClientConfigurationCopyProfiles', '@@'), | |
('EAPOLClientProfileGetUserDefinedName', '@@'), | |
('EAPOLClientProfileGetID', '@@'), ] | |
objc.loadBundleFunctions(EAP8021X_bundle, globals(), E_functions) | |
maximum_interfaces = 20 | |
interfaces = map(lambda x: 'en%s' % x, range(maximum_interfaces)) | |
for i in interfaces: | |
result, status, eap_config = EAPOLControlCopyStateAndStatus( | |
i, None, None) | |
if result == 0: | |
cfg = EAPOLClientConfigurationCreate(None) | |
profiles = EAPOLClientConfigurationCopyProfiles(cfg) | |
for n in profiles: | |
display_name = EAPOLClientProfileGetUserDefinedName(n) | |
if display_name == 'Ethernet - CoE': | |
profile_id = EAPOLClientProfileGetID(n) | |
return profile_id | |
def read_identity_preference(): | |
'''Time to modify the keychain and create the identity preference we need | |
to fix Apple's issue - Still an issue as of 10.12.3''' | |
# from CoreFoundation import CFGetTypeID | |
Security_framework = NSBundle.bundleWithPath_( | |
'/System/Library/Frameworks/Security.framework') | |
# Objective C Functions we will use to read the System keychain and | |
# determine if our identity preference is present | |
keychain_functions = [ | |
('SecKeychainGetTypeID', 'I'), | |
('SecIdentityGetTypeID', 'I'), | |
('SecKeychainSetUserInteractionAllowed', 'IZ'), | |
('SecKeychainCopyDomainDefault', 'IIo^^{__CFArray}'), | |
('SecKeychainOpen', 'I*o^^{__SecKeychain=}'), | |
('SecKeychainGetStatus', 'I^{__SecKeychain=}o^I'), | |
('SecKeychainUnlock', 'I^{__SecKeychain=}I*I'), | |
('SecIdentityCopyPreferred', | |
'^{__SecIdentityRef=}^{__CFString}^{__CFArray}^{__CFArray}'), | |
('SecKeychainLock', 'I^{__SecKeychain=}'), ] | |
objc.loadBundleFunctions(Security_framework, globals(), keychain_functions) | |
# Build out our CF type signatures | |
objc.registerCFSignature( | |
'SecKeychainRef', '^{__SecKeychain=}', SecKeychainGetTypeID()) | |
objc.registerCFSignature( | |
'SecIdentityRef', '^{__SecIdentityRef=}', SecIdentityGetTypeID()) | |
kSecUnlockStateStatus = 1 | |
kSecPreferencesDomainSystem = 1 | |
user_profile_name = ('com.apple.network.eap.user' | |
'.identity.profileid.{0:}'.format(uuid)) | |
# Turn off any prompts for a user to enter a password for keychain | |
SecKeychainSetUserInteractionAllowed(False) | |
# Let's Open the System Keychain | |
err, keychains = SecKeychainCopyDomainDefault( | |
kSecPreferencesDomainSystem, None) | |
err, keychain = SecKeychainOpen('System.keychain', None) | |
# Check Status of the System Keychain (Should be locked) | |
err, status = SecKeychainGetStatus(keychain, None) | |
unlocked = status | kSecUnlockStateStatus == kSecUnlockStateStatus | |
if not unlocked: | |
# Unlock the System Keychain | |
keychain = SecKeychainUnlock(keychain, 0, None, False) | |
# Copy our Identity Preference and make the new one with | |
# the same attributes | |
keychain_item = SecIdentityCopyPreferred( | |
user_profile_name, None, None) | |
err = SecKeychainLock(keychain) | |
return keychain_item | |
if __name__ == '__main__': | |
uuid = get_profile_uuid() | |
present = read_identity_preference() | |
if present is not None: | |
print('<result>Present</result>') | |
else: | |
print('<result>Not Present</result>') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment