in CODING, Python

Updating the Activation and Expiration Dates of a JAMF Policy Via The API

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 will calculate the second Tuesday of the month (‘Patch Tuesday’) then assign dates for subsequent day that each policy should activate.

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 timedeltas

#!/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)