Microsoft Office 365 Endpoints V1 (Python)

Tonight I’m having a brief look at Microsoft Office 365 Endpoints; https://support.office.com/en-us/article/managing-office-365-endpoints-99cab9d4-ef59-4207-9f2b-3728eb46bf9a?ui=en-US&rs=en-US&ad=US#ID0EACAAA=4._Web_service in my current favourite programming language – Python. My target is to be able to generate the various Endpoint details into an updating PAC or WPAD file. Then I will look at the same in PowerShell.

  • I’ve used the SMTP knowledge I got from my Pollen project
  • I would use Cron to schedule the program to run regularly

Microsoft very kindly already included a Python (and PowerShell) script on the above website; so all I’m doing is modifying it/altering it to do what I need – in this early version that is to output the various data into some files (CSV format for now) and e-mail me when updates are available.

#!/usr/bin/python3
# original source from https://support.office.com/en-us/article/managing-office-365-endpoints-99cab9d4-ef59-4207-9f2b-3728eb46bf9a?ui=en-US&rs=en-US&ad=US#ID0EACAAA=4._Web_service
# modified by geektechstuff

import json
import os
import urllib.request
import uuid
import smtplib

from email_settings import (
smtp_server,
port,
login_user,
login_pass,
from_address,
to_address
)

# helper to call the webservice and parse the response
def webApiGet(methodName, instanceName, clientRequestId):
    ws = "https://endpoints.office.com"
    requestPath = ws + '/' + methodName + '/' + instanceName + '?clientRequestId=' + clientRequestId
    request = urllib.request.Request(requestPath)
    with urllib.request.urlopen(request) as response:
        return json.loads(response.read().decode())


# path where client ID and latest version number will be stored
datapath = '/Users/gary/Downloads/' + '/endpoints_clientid_latestversion.txt'

# URL List for Proxy Server, outputs as CSV
url_list = '/Users/gary/Downloads/365_url_list.csv'

# IPv4 List for Firewall, outputs as CSV
ip_list = '/Users/gary/Downloads/365_ip_list.csv'

# fetch client ID and version if data exists; otherwise create new file
if os.path.exists(datapath):
    with open(datapath, 'r') as fin:
        clientRequestId = fin.readline().strip()
        latestVersion = fin.readline().strip()
else:
    clientRequestId = str(uuid.uuid4())
    latestVersion = '0000000000'
    with open(datapath, 'w') as fout:
        fout.write(clientRequestId + '\n' + latestVersion)

# call version method to check the latest version, and pull new data if version number is different
version = webApiGet('version', 'Worldwide', clientRequestId)
if version['latest'] > latestVersion:
    print('New version of Office 365 worldwide commercial service instance endpoints detected')

    # write the new version number to the data file
    with open(datapath, 'w') as fout:
        fout.write(clientRequestId + '\n' + version['latest'])

    # invoke endpoints method to get the new data
    endpointSets = webApiGet('endpoints', 'Worldwide', clientRequestId)

    # filter results for Allow and Optimize endpoints, and transform these into tuples with port and category
    flatUrls = []
    for endpointSet in endpointSets:
        if endpointSet['category'] in ('Optimize', 'Allow'):
            category = endpointSet['category']
            urls = endpointSet['urls'] if 'urls' in endpointSet else []
            tcpPorts = endpointSet['tcpPorts'] if 'tcpPorts' in endpointSet else ''
            udpPorts = endpointSet['udpPorts'] if 'udpPorts' in endpointSet else ''
            flatUrls.extend([(category, url, tcpPorts, udpPorts) for url in urls])

    flatIps = []
    for endpointSet in endpointSets:
        if endpointSet['category'] in ('Optimize', 'Allow'):
            ips = endpointSet['ips'] if 'ips' in endpointSet else []
            category = endpointSet['category']
            # IPv4 strings have dots while IPv6 strings have colons
            ip4s = [ip for ip in ips if '.' in ip]
            tcpPorts = endpointSet['tcpPorts'] if 'tcpPorts' in endpointSet else ''
            udpPorts = endpointSet['udpPorts'] if 'udpPorts' in endpointSet else ''
            flatIps.extend([(category, ip, tcpPorts, udpPorts) for ip in ip4s])

    print('IPv4 Firewall IP Address Ranges')
    print(','.join(sorted(set([ip for (category, ip, tcpPorts, udpPorts) in flatIps]))))
    # outputs the details to the ip_list variable
    with open(ip_list, 'w') as data_write:
        data_write.write(','.join(sorted(set([ip for (category, ip, tcpPorts, udpPorts) in flatIps]))))

    print('URLs for Proxy Server')
    print(','.join(sorted(set([url for (category, url, tcpPorts, udpPorts) in flatUrls]))))
    # outputs the details to the url_list variable
    with open(url_list, 'w') as data_write:
        data_write.write(','.join(sorted(set([ip for (category, ip, tcpPorts, udpPorts) in flatUrls]))))

    # smtp aka email settings
    smtpObj = smtplib.SMTP_SSL(smtp_server, port)
    smtpObj.login(login_user, login_pass)
    smtpObj.sendmail(from_address, to_address,
                     'From: geektechstuff@DOMAIN\nSubject: 365 EndPoints Updated\n\n')
    smtpObj.quit()

else:
    print('Office 365 worldwide commercial service, no updates detected.')

 

One thought on “Microsoft Office 365 Endpoints V1 (Python)

Comments are closed.