I am slowly building an application in Python to automatically update the patch management of the JSS.
The first step in this is that the system I inherited uses 6 policies to trigger monthly updates. The way this works is as follows (convoluted but its what I inherited and I haven’t got round to simplifying it!):
- A smart group scopes an IP range or Network Segment
- The policy runs a script called ‘MonthlyUpdates’ that triggers the jamf policy event ‘MonthlyUpdates’
- The policy has an activation and expiration date
I wrote a Python3 script to interact with the API to update ‘activation’ and ‘expiration’ dates on each of the policies. It
As soon as I had finished, I could see where it could be improved such as the policy ID could be in a list and instead use a loop to calculate the
#!/usr/local/bin/python
import requests
import calendar
from datetime import datetime, timedelta
### Settings
now = datetime.today()
# Settings for the request
base_url = 'https://[JSS.URL]/'
policy_url = 'JSSResource/policies/id/'
jss_url = base_url + policy_url
headers = {"Authorization": "Basic [enter base16 password]", "Content-Type": "text/xml"}
# JSS Policy ID's
policy_1 = '594' # Updates - 1 - Alpha Test
policy_2 = '612' # Updates - 2 - Beta Test
policy_3 = '615' # Updates - 3 - Mon
policy_4 = '598' # Updates - 4 - Tues
policy_5 = '600' # Updates - 5 - Weds
policy_6 = '599' # Updates - 6 - Thurs
policy_7 = '1067' # Updates - 7 - Test
# Calculates the date of Patch Tuesday
def patch_tuesday(year, month):
c = calendar.Calendar(firstweekday=calendar.MONDAY)
monthcal = c.monthdatescalendar(year,month)
patch_day = [day for week in monthcal for day in week if \
day.weekday() == calendar.TUESDAY and \
day.month == month][1]
return patch_day
# Does a timedelta from Patch Tuesday
def calculate_patch_dates(patch_date, post_days):
new_patch_date = patch_date + timedelta(days=post_days)
return new_patch_date
# Does the request to the JSS API to update the policy date
def send_request(url, start_date, end_date):
# Request
data = "<policy><general><date_time_limitations><activation_date>{0} 18:00:00</activation_date><expiration_date>{1} 18:00:00</expiration_date></date_time_limitations></general></policy>".format(start_date, end_date)
print(data)
url = jss_url + url
print(url)
try:
response = requests.put(url=url, headers=headers, data=data)
print('Response HTTP Status Code: {status_code}'.format(status_code=response.status_code))
print('Response HTTP Response Body: {content}'.format(content=response.content))
except requests.exceptions.RequestException:
print('HTTP Request failed')
### OPERATIONS
# Get the date of Patch Tuesday for that month
patch_date = patch_tuesday(now.year, now.month)
# Calculate the days of each patch cycle after
patch_alpha = calculate_patch_dates(patch_date, 1)
patch_beta = calculate_patch_dates(patch_date, 2)
patch_mon = calculate_patch_dates(patch_date, 5)
patch_tues = calculate_patch_dates(patch_date, 6)
patch_weds = calculate_patch_dates(patch_date, 7)
patch_thurs = calculate_patch_dates(patch_date, 8)
patch_fri = calculate_patch_dates(patch_date, 28)
'''
Update each policy with its start date and the following policies start date so each policy should run for 24 hours
'''
# Updates - 1 - Alpha Test
send_request(policy_1, patch_alpha, patch_beta)
# Updates - 2 - Beta Test
send_request(policy_2, patch_beta, patch_mon)
# Updates - 3 - Mon
send_request(policy_3, patch_mon, patch_tues)
# Updates - 4 - Tues
send_request(policy_4, patch_tues, patch_weds)
# Updates - 5 - Weds
send_request(policy_5, patch_weds, patch_thurs)
# Updates - 6 - Thurs
send_request(policy_6, patch_thurs, patch_fri)