Here are my scripts to fix accounts affected by an extraneous apostrophe in the Authentication Authority after being migrated from mobile to local, as written up in Rich's blog post. While I've successfull rolled them out in our environment, I had to remove some site specific logic before publishing them here, so make sure you test them carefully.
Last active
June 19, 2018 02:56
-
-
Save MagerValp/293ad5a311eaa685dd8ee8380e8dccb8 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 | |
# -*- coding: utf-8 -*- | |
from __future__ import unicode_literals | |
from __future__ import print_function | |
from __future__ import division | |
import io | |
import sys | |
import codecs | |
if sys.stdout.encoding != "UTF-8": | |
sys.stdout = codecs.getwriter("utf-8")(sys.stdout, "strict") | |
if sys.stderr.encoding != "UTF-8": | |
sys.stderr = codecs.getwriter("utf-8")(sys.stderr, "strict") | |
import os | |
import sys | |
import argparse | |
from OpenDirectory import ODSession, ODNode, ODQuery, kODRecordTypeUsers, kODAttributeTypeRecordName, kODAttributeTypeStandardOnly, kODMatchEqualTo, kODRecordTypeUsers | |
def main(argv): | |
p = argparse.ArgumentParser() | |
p.add_argument("username") | |
args = p.parse_args([x.decode("utf-8") for x in argv[1:]]) | |
username = args.username | |
node, error = ODNode.nodeWithSession_name_error_(ODSession.defaultSession(), "/Local/Default", None) | |
if not node: | |
print("Couldn't open local node: {}".format(error.localizedDescription())) | |
return os.EX_UNAVAILABLE | |
query, error = ODQuery.queryWithNode_forRecordTypes_attribute_matchType_queryValues_returnAttributes_maximumResults_error_(node, kODRecordTypeUsers, kODAttributeTypeRecordName, kODMatchEqualTo, username, kODAttributeTypeStandardOnly, 0, None) | |
if not query: | |
print("Couldn't query local node: {}".format(error.localizedDescription())) | |
return os.EX_UNAVAILABLE | |
result, error = query.resultsAllowingPartial_error_(False, None) | |
if not result: | |
print("Couldn't find user: {}".format(error.localizedDescription())) | |
return os.EX_UNAVAILABLE | |
userrecord = result[0] | |
authauth = userrecord.valuesForAttribute_error_("dsAttrTypeStandard:AuthenticationAuthority", None)[0].mutableCopy() | |
if not authauth.containsObject_("'"): | |
print("{} looks fine".format(username)) | |
return 0 | |
print("Fixing AuthenticationAuthority for {}".format(username)) | |
authauth.removeObject_("'") | |
for i in xrange(authauth.count()): | |
if authauth[i].endswith("'"): | |
fixed = authauth[i].substringToIndex_(authauth[i].length() - 1) | |
authauth.replaceObjectAtIndex_withObject_(i, fixed) | |
result, error = userrecord.setValue_forAttribute_error_(authauth, "dsAttrTypeStandard:AuthenticationAuthority", None) | |
if not result: | |
print("Couldn't set attribute: {}".format(error.localizedDescription())) | |
return os.EX_UNAVAILABLE | |
print("Fixed AuthenticationAuthority for {}".format(username)) | |
return 0 | |
if __name__ == '__main__': | |
sys.exit(main(sys.argv)) |
This file contains hidden or 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
#!/bin/bash | |
allgood="true" | |
result="" | |
while read -r user; do | |
authauth=$(dscl . -read /Users/"$user" AuthenticationAuthority) | |
if [[ "$authauth" == *\'* ]]; then | |
allgood="false" | |
result="$result bad:$user" | |
else | |
result="$result good:$user" | |
fi | |
done < <(dscl . -list /Users | egrep -v '^_') | |
if [[ "$allgood" == "true" ]]; then | |
result="All good" | |
fi | |
echo "<result>${result# }</result>" |
This file contains hidden or 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 | |
# -*- coding: utf-8 -*- | |
# | |
# Check that the Authentication Authority of migrated AD accounts is good. | |
from __future__ import unicode_literals | |
from __future__ import print_function | |
from __future__ import division | |
import io | |
import sys | |
import codecs | |
if sys.stdout.encoding != "UTF-8": | |
sys.stdout = codecs.getwriter("utf-8")(sys.stdout, "strict") | |
if sys.stderr.encoding != "UTF-8": | |
sys.stderr = codecs.getwriter("utf-8")(sys.stderr, "strict") | |
import plistlib | |
import os | |
from Foundation import CFPreferencesCopyAppValue | |
import subprocess | |
def dscl(args): | |
cmd = ["/usr/bin/dscl", "."] + args | |
return subprocess.check_output(cmd) | |
def list_users(): | |
users = [] | |
out = dscl(["-list", "/Users"]) | |
for username in out.splitlines(): | |
if username.startswith("_"): | |
continue | |
users.append(username) | |
return users | |
def read_authauth(username): | |
return dscl(["-read", | |
"/Users/{}".format(username), | |
"AuthenticationAuthority"]) | |
def main(argv): | |
managedinstalldir = CFPreferencesCopyAppValue("ManagedInstallDir", "ManagedInstalls") | |
plist_path = os.path.join(managedinstalldir, "ConditionalItems.plist") | |
try: | |
conditions = plistlib.readPlist(plist_path) | |
except IOError: | |
conditions = {} | |
try: | |
result = [] | |
all_good = True | |
for username in list_users(): | |
if "'" in read_authauth(username): | |
all_good = False | |
result.append("bad:{}".format(username)) | |
else: | |
result.append("good:{}".format(username)) | |
if all_good: | |
conditions["authauth"] = "All good" | |
else: | |
conditions["authauth"] = " ".join(result) | |
except (IndexError, AttributeError): | |
return os.EX_SOFTWARE | |
except subprocess.CalledProcessError as e: | |
print("{}".format(e), file=sys.stderr) | |
return os.EX_UNAVAILABLE | |
plistlib.writePlist(conditions, plist_path) | |
return 0 | |
if __name__ == '__main__': | |
sys.exit(main(sys.argv)) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment