Skip to content

Commit 175a449

Browse files
authored
Client auth (#5)
* handles oauth * update input parameter * re-use input variables * auth_type input * simplify dupe check and fixed some typos and logging * doublequotes * just one auth method * nitpicking * expire time different in oauth * token is a different key too * forgot to return the token?
1 parent 10ff3d4 commit 175a449

3 files changed

Lines changed: 57 additions & 36 deletions

File tree

.github/workflows/pythonapp.yml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ name: Python application
55

66
on:
77
push:
8-
branches: [ master ]
8+
#branches: [ master ]
99
paths:
1010
- '**/*.py'
1111
pull_request:
@@ -19,11 +19,9 @@ jobs:
1919
runs-on: ubuntu-latest
2020

2121
steps:
22-
- uses: actions/checkout@v2
23-
- name: Set up Python 3.8
22+
- uses: actions/checkout@v3
23+
- name: Set up Python
2424
uses: actions/setup-python@v1
25-
with:
26-
python-version: 3.8
2725
- name: Install dependencies
2826
run: |
2927
python -m pip install --upgrade pip

action.py

Lines changed: 51 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,21 @@
1313
logger.add(sys.stdout, colorize=True, level="INFO", format="<blue>{time:HH:mm:ss!UTC}</blue>: <lvl>{message}</lvl>")
1414

1515

16-
#function to get the token given the url, usrername and password
16+
#function to get the token
1717
@logger.catch
18-
def get_jamf_token(url, username, password):
19-
token_request = requests.post(url=f"{url}/uapi/auth/tokens", auth = (username, password))
18+
def get_jamf_token(url, auth_type, username, password):
19+
if auth_type == "auth":
20+
token_request = requests.post(url=f"{url}/uapi/auth/tokens", auth=(username,password))
21+
elif auth_type =='oauth':
22+
data = {"client_id": username,"client_secret": password, "grant_type": "client_credentials"}
23+
token_request = requests.post(url=f"{url}/api/oauth/token", data=data)
2024
if token_request.status_code == requests.codes.ok:
21-
logger.success(f"got the token! it expires in: {token_request.json()['expires']}")
22-
return token_request.json()['token']
25+
if auth_type == "auth":
26+
logger.success(f"got the token! it expires in: {token_request.json()['expires']}")
27+
return token_request.json()['token']
28+
elif auth_type == "oauth":
29+
logger.success(f"got the token! it expires in: {token_request.json()['expires_in']}")
30+
return token_request.json()['access_token']
2331
elif token_request.status_code == requests.codes.not_found:
2432
logger.error('failed to retrieve a valid token, please check the url')
2533
raise Exception("failed to retrieve a valid token, please check the credentials")
@@ -31,10 +39,11 @@ def get_jamf_token(url, username, password):
3139
logger.error(token_request.text)
3240
raise Exception("failed to retrieve a valid token, please check the credentials")
3341

42+
3443
#function to invalidate a token so it can't be use after we're done
3544
@logger.catch
3645
def invalidate_jamf_token(url, token):
37-
header = { "Authorization": f"Bearer {token}" }
46+
header = {"Authorization": f"Bearer {token}"}
3847
token_request = requests.post(url=f"{url}/uapi/auth/invalidateToken", headers=header)
3948
if token_request.status_code == requests.codes.no_content:
4049
logger.success("token invalidated succesfully")
@@ -43,10 +52,11 @@ def invalidate_jamf_token(url, token):
4352
logger.warning("failed to invalidate the token, maybe it's already expired?")
4453
logger.warning(token_request.text)
4554

55+
4656
#function to create a new script
4757
@logger.catch
4858
def create_jamf_script(url, token, payload):
49-
header = { "Authorization": f"Bearer {token}" }
59+
header = {"Authorization": f"Bearer {token}"}
5060
script_request = requests.post(url=f"{url}/uapi/v1/scripts", headers=header, json=payload)
5161
if script_request.status_code == requests.codes.created:
5262
logger.success("script created")
@@ -61,7 +71,7 @@ def create_jamf_script(url, token, payload):
6171
#function to update an already existing script
6272
@logger.catch
6373
def update_jamf_script(url, token, payload):
64-
header = { "Authorization": f"Bearer {token}" }
74+
header = {"Authorization": f"Bearer {token}"}
6575
script_request = requests.put(url=f"{url}/uapi/v1/scripts/{payload['id']}", headers=header, json=payload)
6676
if script_request.status_code in [requests.codes.accepted, requests.codes.ok]:
6777
logger.success("script was updated succesfully")
@@ -72,9 +82,10 @@ def update_jamf_script(url, token, payload):
7282
logger.warning(script_request.text)
7383
sys.exit(1)
7484

85+
7586
@logger.catch
7687
def delete_jamf_script(url, token, id):
77-
header = { "Authorization": f"Bearer {token}" }
88+
header = {"Authorization": f"Bearer {token}"}
7889
script_request = requests.delete(url=f"{url}/uapi/v1/scripts/{id}", headers=header)
7990
if script_request.status_code in [requests.codes.ok, requests.codes.accepted, requests.codes.no_content]:
8091
logger.success("script was deleted succesfully")
@@ -89,7 +100,7 @@ def delete_jamf_script(url, token, id):
89100
#retrieves all scripts in a json
90101
@logger.catch
91102
def get_all_jamf_scripts(url, token, scripts = [], page = 0):
92-
header = { "Authorization": f"Bearer {token}" }
103+
header = {"Authorization": f"Bearer {token}"}
93104
page_size=50
94105
params = {"page": page, "page-size": page_size, "sort": "name:asc"}
95106
script_list = requests.get(url=f"{url}/uapi/v1/scripts", headers=header, params=params)
@@ -116,15 +127,15 @@ def get_all_jamf_scripts(url, token, scripts = [], page = 0):
116127
#search for the script name and return the json that for it
117128
@logger.catch
118129
def find_jamf_script(url, token, script_name, page = 0):
119-
header = { f"Authorization": "Bearer {token}" }
130+
header = {"Authorization": f"Bearer {token}"}
120131
page_size=50
121132
params = {"page": page, "page-size": page_size, "sort": "name:asc"}
122133
script_list = requests.get(url=f"{url}/uapi/v1/scripts", headers=header, params=params)
123134
if script_list.status_code == requests.codes.ok:
124135
script_list = script_list.json()
125136
logger.info(f"we have searched {len(script_list['results'])+page} of {script_list['totalCount']} results")
126137
script_search = jmespath.search(f"results[?name == '{script_name}']", script_list)
127-
if len(script_search) == 1 :
138+
if len(script_search) == 1:
128139
logger.info('found the script, returning it')
129140
return script_search[0]
130141
elif len(script_search) == 0 and (page*page_size) < script_list['totalCount']:
@@ -139,10 +150,11 @@ def find_jamf_script(url, token, script_name, page = 0):
139150
logger.error(script_list.text)
140151
raise Exception("failed to find the script, please investigate!")
141152

153+
142154
#function to find a EA script using the filename as the script name
143155
@logger.catch
144156
def find_ea_script(ea_name):
145-
ea_script = requests.get(url=f"{url}/JSSResource/computerextensionattributes/name/{ea_name}", auth=(username,password))
157+
ea_script = requests.get(url = f"{url}/JSSResource/computerextensionattributes/name/{ea_name}", auth=(username,password))
146158
if ea_script.status_code == requests.codes.ok:
147159
return ea_script.json()['computer_extension_attribute']
148160
elif ea_script.status_code == requests.codes.not_found:
@@ -152,19 +164,21 @@ def find_ea_script(ea_name):
152164
logger.error("encountered an error retriving the extension attribute, stopping")
153165
logger.error(ea_script.text)
154166
raise Exception("encountered an error retriving the extension attribute, stopping")
155-
167+
168+
156169
#function to create EA script
157170
@logger.catch
158171
def create_ea_script(payload, id):
159172
headers = {"Accept": "text/xml", "Content-Type": "text/xml"}
160-
ea_script = requests.post(url=f"{url}/JSSResource/computerextensionattributes/id/{id}", json=payload, auth=(username,password))
173+
ea_script = requests.post(url = f"{url}/JSSResource/computerextensionattributes/id/{id}", json=payload, auth=(username,password))
161174
if ea_script.status_code == requests.codes.ok:
162175
return "success"
163176
else:
164177
logger.error("encountered an error creating the extension attribute, stopping")
165178
logger.error(ea_script.text)
166179
raise Exception("encountered an error creating the extension attribute, stopping")
167180

181+
168182
#function to update existin EA script
169183
@logger.catch
170184
def update_ea_script(payload, id):
@@ -177,6 +191,7 @@ def update_ea_script(payload, id):
177191
logger.error(ea_script.text)
178192
raise Exception("encountered an error creating the extension attribute, stopping")
179193

194+
180195
#function to compare sripts and see if they have changed. If they haven't, no need to update it
181196
@logger.catch
182197
def compare_scripts(new, old):
@@ -191,6 +206,7 @@ def compare_scripts(new, old):
191206
logger.warning("scripts are different")
192207
return False
193208

209+
194210
#retrieves list of files given a folder path and the list of valid file extensions to look for
195211
@logger.catch
196212
def find_local_scripts(script_dir, script_extensions):
@@ -202,16 +218,18 @@ def find_local_scripts(script_dir, script_extensions):
202218
logger.info(script_list)
203219
return script_list
204220

221+
205222
#strips out the path and extension to get the scripts name
206223
@logger.catch
207224
def get_script_name(script_path):
208225
return script_path.split('/')[-1].rsplit('.', 1)[0]
209226

227+
210228
@logger.catch
211229
def push_scripts():
212230
#grab the token from jamf
213231
logger.info('grabing the token from jamf')
214-
token = get_jamf_token(url, username, password)
232+
token = get_jamf_token(url,auth_type, username, password)
215233
logger.info('checking the list of local scripts to upload or create')
216234
scripts = {}
217235
#this retrives the full path of the scripts we're trying to sync from github
@@ -220,19 +238,15 @@ def push_scripts():
220238
scripts['github_simple_name'] = []
221239
for script in scripts['github']:
222240
scripts['github_simple_name'].append(get_script_name(script).lower())
223-
224-
logger.info('doublechecking for duplicate names')
225-
dupes = False
241+
logger.info('doublechecking for duplicate script names')
226242
for count, script in enumerate(scripts['github_simple_name']):
227243
if scripts['github_simple_name'].count(script) >= 2:
228-
dupes = True
229-
logger.error("conflicting script name")
230-
logger.error(scripts['github'][count])
231-
if dupes == True:
232-
sys.exit(1)
244+
logger.error(f"the script name {script} is duplicated {scripts['github_simple_name'].count(script)} times, please give it a unique name")
245+
#logger.error(scripts['github'][count])
246+
sys.exit(1)
233247
#continue if no dupes are found
234-
logger.success("found no duplicate script names, we can continue")
235-
logger.info('now checking against jamf for the list of scripts')
248+
logger.success("nice, no duplicate script names, we can continue")
249+
logger.info('now checking jamf for its list of scripts')
236250
scripts['jamf'] = get_all_jamf_scripts(url, token)
237251
logger.info("setting all script names to lower case to avoid false positives in our search.")
238252
logger.info("worry not, this won't affect the actual naming :)")
@@ -287,17 +301,24 @@ def push_scripts():
287301

288302
logger.info("expiring the token so it can't be used further")
289303
invalidate_jamf_token(url, token)
290-
logger.success("finished with the scripts, are there any EA scripts?!")
304+
logger.success("finished with the scripts")
291305

292306

293307
def push_ea_scripts():
294308
return ""
295309

310+
296311
#run this thing
297312
if __name__ == "__main__":
298313
logger.info('reading environment variables')
299314
url = os.getenv('INPUT_JAMF_URL')
315+
auth_type = os.getenv("INPUT_JAMF_AUTH_TYPE")
316+
if auth_type not in ["auth","oauth"]:
317+
logger.error("please use 'auth' or 'oauth' as they auth_type")
318+
#if using oauth, we're just going to re-use the same variables as they are similar enough.
319+
#client_id is username
300320
username = os.getenv('INPUT_JAMF_USERNAME')
321+
#client_secret is password
301322
password = os.getenv('INPUT_JAMF_PASSWORD')
302323
script_dir = os.getenv('INPUT_SCRIPT_DIR')
303324
ea_script_dir = os.getenv('INPUT_EA_SCRIPT_DIR')
@@ -313,12 +334,12 @@ def push_ea_scripts():
313334
logger.info(f"workspace dir is: {workspace_dir}")
314335
logger.info(f"script_dir is: {script_dir}")
315336
logger.info(f"branch is set to: {branch}")
316-
logger.info(f"script_deltion is: {delete}")
337+
logger.info(f"script_deletion is: {delete}")
317338
logger.info(f"scripts_extensions are: {script_extensions}")
318339
if enable_prefix == 'false':
319340
logger.warning('prefix is disabled')
320341
else:
321-
logger.warning('prefix is enabled')
342+
logger.warning(f"prefix enabled, using: {branch.split('/')[-1]}")
322343
#run the block to push the "normal" scripts to jamf
323344
push_scripts()
324345
#check to see if we have an EA scripts to push over
@@ -328,5 +349,4 @@ def push_ea_scripts():
328349
else:
329350
logger.warning("no EA script folder set, skipping")
330351

331-
logger.success("we're done!")
332-
352+
logger.success("we're done!")

action.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ inputs:
1111
jamf_password:
1212
description: 'password to auth against jamf'
1313
required: true
14+
jamf_auth_type:
15+
description: 'auth for traditional username/pwd or oauth for clientid an secret'
16+
default: auth
1417
script_dir:
1518
description: >
1619
the directory where the scripts to process are defaults to the github.workspace environment variable

0 commit comments

Comments
 (0)