-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathAdd SecureToken to Target User.sh
More file actions
228 lines (167 loc) · 9.2 KB
/
Add SecureToken to Target User.sh
File metadata and controls
228 lines (167 loc) · 9.2 KB
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
#!/bin/sh
###
#
# Name: Add SecureToken to Target User.sh
# Description: This script adds a SecureToken to the target local user to prepare the Mac for enabling FileVault. Prompts for password of SecureToken admin (gets SecureToken Admin Username from Jamf Pro script parameter) and target user. This workflow is required to authorize programmatically-created user accounts (that were not already explicitly given a SecureToken) to enable or use FileVault and unlock disk encryption on APFS-formatted startup volumes.
# https://github.com/wavebirddash/add-securetoken-to-target-user
#
# MIT License
#
# Copyright © 2017 Mario Panighetti
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Author: Mario Panighetti
# Created: 2017-10-04
# Last Modified: 2026-01-12
# Version: 4.1.1
#
###
########## variable-ing ##########
# Jamf Pro script parameter: "Target Username"
# (optional) A local user account requiring SecureToken. If undefined, script will default to the logged-in user as the target.
targetUsername="${4}"
# Jamf Pro script parameter: "SecureToken Admin Username"
# A local administrator account with SecureToken access.
secureTokenAdmin="${5}"
macOSVersionMajor=$(/usr/bin/sw_vers -productVersion | /usr/bin/awk -F . '{print $1}')
macOSVersionMinor=$(/usr/bin/sw_vers -productVersion | /usr/bin/awk -F . '{print $2}')
macOSVersionBuild=$(/usr/bin/sw_vers -productVersion | /usr/bin/awk -F . '{print $3}')
# Need default password values so the initial logic loops will properly fail when validating passwords. You can store the actual credentials here to skip password prompts entirely, but for security reasons this is not generally recommended. Please don't actually use "foo" as a password, for so many reasons.
secureTokenAdminPass="foo"
targetUserPassword="foo"
passwordPrompt="foo"
########## function-ing ##########
# Exits with error if any required Jamf Pro arguments are undefined.
check_jamf_pro_arguments () {
if [ -z "$secureTokenAdmin" ]; then
echo "❌ ERROR: Undefined Jamf Pro argument, unable to proceed."
exit 74
fi
}
# Exits if macOS version predates the use of SecureToken functionality.
check_macos_version () {
# Exit if macOS < 10.
if [ "$macOSVersionMajor" -lt 10 ]; then
echo "macOS version ${macOSVersionMajor} predates the use of SecureToken functionality, no action required."
exit 0
# Exit if macOS 10 < 10.13.
elif [ "$macOSVersionMajor" -eq 10 ]; then
if [ "$macOSVersionMinor" -lt 13 ]; then
echo "macOS version ${macOSVersionMajor}.${macOSVersionMinor} predates the use of SecureToken functionality, no action required."
exit 0
# Exit if macOS 10.13 < 10.13.4.
elif [ "$macOSVersionMinor" -eq 13 ] && [ "$macOSVersionBuild" -lt 4 ]; then
echo "macOS version ${macOSVersionMajor}.${macOSVersionMinor}.${macOSVersionBuild} predates the use of SecureToken functionality, no action required."
exit 0
fi
fi
}
# Sets target username to defined value from script parameter, or defaults to logged-in user if undefined.
check_target_username () {
if [ -z "$targetUsername" ]; then
echo "Target Username undefined. Defaulting to logged-in user..."
loggedInUser=$(/usr/bin/stat -f%Su "/dev/console")
# Exit if root is the current logged-in user, or no logged-in user is detected.
if [ "$loggedInUser" = "root" ] || [ -z "$loggedInUser" ]; then
echo "Nobody is logged in."
exit 0
else
targetUsername="$loggedInUser"
fi
elif id -u "$targetUsername"; then
echo "Confirmed target user exists on this Mac."
else
echo "❌ ERROR: User not found on this Mac, unable to proceed: ${targetUsername}"
exit 1
fi
echo "Target Username: ${targetUsername}"
}
# Exits if target user already has SecureToken.
check_securetoken_target_user () {
if /usr/sbin/sysadminctl -secureTokenStatus "$targetUsername" 2>&1 | /usr/bin/grep -q "ENABLED"; then
echo "${targetUsername} already has a SecureToken, no action required."
exit 0
fi
}
# Exits with error if $secureTokenAdmin does not have SecureToken (unless running macOS 10.15 or later, in which case exit with explanation).
check_securetoken_admin () {
if /usr/sbin/sysadminctl -secureTokenStatus "$secureTokenAdmin" 2>&1 | /usr/bin/grep -q "DISABLED" ; then
if [ "$macOSVersionMajor" -gt 10 ] || [ "$macOSVersionMajor" -eq 10 ] && [ "$macOSVersionMinor" -gt 14 ]; then
echo "⚠️ Neither ${secureTokenAdmin} nor ${targetUsername} has a SecureToken, but in macOS 10.15 or later, a SecureToken is automatically granted to the first user to enable FileVault (if no other users have SecureToken), so this may not be necessary. Try enabling FileVault for ${targetUsername}. If that fails, see what other user on the system has SecureToken, and use its credentials to grant SecureToken to ${targetUsername}."
exit 0
else
echo "❌ ERROR: ${secureTokenAdmin} does not have a valid SecureToken, unable to proceed. Please update Jamf Pro policy to target another admin user with SecureToken."
exit 1
fi
else
echo "✅ Verified ${secureTokenAdmin} has SecureToken."
fi
}
# Prompts for local password.
local_account_password_prompt () {
passwordPrompt=$(/usr/bin/osascript -e "set user_password to text returned of (display dialog \"${2}\" default answer \"\" with hidden answer)")
if [ -z "$passwordPrompt" ]; then
echo "❌ ERROR: A password was not entered for ${1}, unable to proceed. Please rerun policy; if issue persists, a manual SecureToken add will be required to continue."
exit 1
fi
}
# Validates provided password.
local_account_password_validation () {
if /usr/bin/dscl "/Local/Default" authonly "${1}" "${2}" > "/dev/null" 2>&1; then
echo "✅ Password successfully validated for ${1}."
else
echo "❌ ERROR: Failed password validation for ${1}. Please reenter the password when prompted."
fi
}
# Adds SecureToken to target user.
securetoken_add () {
/usr/sbin/sysadminctl \
-adminUser "${1}" \
-adminPassword "${2}" \
-secureTokenOn "${3}" \
-password "${4}"
# Verify successful SecureToken add.
secureTokenCheck=$(/usr/sbin/sysadminctl -secureTokenStatus "${3}" 2>&1)
if echo "$secureTokenCheck" | /usr/bin/grep -q "DISABLED"; then
echo "❌ ERROR: Failed to add SecureToken to ${3}. Please rerun policy; if issue persists, a manual SecureToken add will be required to continue."
exit 126
elif echo "$secureTokenCheck" | /usr/bin/grep -q "ENABLED"; then
echo "Successfully added SecureToken to ${3}."
else
echo "❌ ERROR: Unexpected result, unable to proceed. Please rerun policy; if issue persists, a manual SecureToken add will be required to continue."
exit 1
fi
}
########## main process ##########
# Check script prerequisites.
check_jamf_pro_arguments
check_macos_version
check_target_username
check_securetoken_target_user
check_securetoken_admin
# Add SecureToken to target user.
until /usr/sbin/sysadminctl -secureTokenStatus "$targetUsername" 2>&1 | /usr/bin/grep -q "ENABLED"; do
# Get $secureTokenAdmin password.
echo "${targetUsername} missing SecureToken, prompting for credentials..."
until /usr/bin/dscl "/Local/Default" authonly "$secureTokenAdmin" "$secureTokenAdminPass" > "/dev/null" 2>&1; do
local_account_password_prompt "$secureTokenAdmin" "Please enter password for ${secureTokenAdmin}. User's credentials are needed to grant a SecureToken to ${targetUsername}."
secureTokenAdminPass="$passwordPrompt"
local_account_password_validation "$secureTokenAdmin" "$secureTokenAdminPass"
done
# Get target user's password.
until /usr/bin/dscl "/Local/Default" authonly "$targetUsername" "$targetUserPassword" > "/dev/null" 2>&1; do
local_account_password_prompt "$targetUsername" "Please enter password for ${targetUsername} to add SecureToken."
targetUserPassword="$passwordPrompt"
local_account_password_validation "$targetUsername" "$targetUserPassword"
done
# Add SecureToken using provided credentials.
securetoken_add "$secureTokenAdmin" "$secureTokenAdminPass" "$targetUsername" "$targetUserPassword"
done
# Echo successful result.
echo "✅ Verified SecureToken is enabled for ${targetUsername}."
exit 0