Skip to end of metadata
Go to start of metadata

Basic Connection

# note this code works up through Python 2.7--the built-in http library has been renamed in Python 3.  Additionally, the 'requests'
# library will generally provide all the required functionality for interacting with the groups service with less work
# than httplib.  
 
import httplib
import ssl

GWS_HOST  = 'iam-ws.u.washington.edu'
GWS_PORT  = 7443

KEY_FILE  = '/path/to/key_file.key'
CERT_FILE = '/path/to/cert_file.cert'
UWCA_ROOT = '/path/to/UWCA/root.cert' # https://certs.cac.washington.edu/?req=svpem

context = ssl.create_default_context()
context.load_verify_locations(UWCA_ROOT)
connection = httplib.HTTPSConnection(GWS_HOST, GWS_PORT, KEY_FILE, CERT_FILE, context=context)

# do stuff

connection.close()

# using requests in python3 
 
import requests

URL = 'https://iam-ws.u.washington.edu:7443/group_sws/v1/'

KEY_FILE  = '/path/to/key_file.key'
CERT_FILE = '/path/to/cert_file.cert'
UWCA_ROOT = '/path/to/UWCA/root.cert' # https://certs.cac.washington.edu/?req=svpem

session = requests.Session()
session.cert = (CERT_FILE, KEY_FILE)
session.verify = UWCA_ROOT
 
# do stuff

session.close()

Basic Request: Get Members doc

METHOD = 'GET'
URL  = '/group_sws/v1/'
URL += 'group/%s/member' % GROUP_NAME

connection.request(METHOD, URL)
response = connection.getresponse()

# HTTP status codes, e.g. 200, 404, etc
print response.status

# e.g. 'Group not found'
print response.reason

# must read() response before making additional request()s
body = response.read()

# using requests in python3 
 
URL += 'group/%s/member' % GROUP_NAME

response = session.get(URL)

# HTTP status codes, e.g. 200, 404, etc
print(response.status_code)

# e.g. 'Group not found'
print(response.reason)

# response body
print(response.text)

Basic Request: Delete Members doc
METHOD = 'DELETE'


#use GET to get old members
old_group_members_array = ['']
old_group_members = ','.join(old_group_members_array)
 
URL  = '/group_sws/v1/'
URL += 'group/%s/member/%s' % (GROUP_NAME, old_group_members)


connection.request(METHOD, URL)
response = connection.getresponse()


print "%d %s" % (response.status, response.reason)
# 200 Member(s) removed
# 404 Group not found

Example: Add Members to Group doc

new_group_members = ','.join(new_group_members_array)
URL  = '/group_sws/v1/'
URL += 'group/%s/member/%s' % (GROUP_NAME, new_group_members) 

connection.request('PUT', URL)
response = connection.getresponse()

print "%d %s" % (response.status, response.reason)
# 200 Member(s) added
# 404 Group not found

Example: Create Group doc

URL  = '/group_sws/v1/'
URL += 'group/%s' % GROUP_NAME

# minimum needed to create group
XHTML_TPL ="""<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
  "http://www.w3.org/TR/xhtml11/DTD/xhtml11/dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
 <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8"/>
</head>
<body>
  <div class="group">
    <span class="description">%s</span>
    <ul class="names"><li class="name">%s</li></ul>
    <ul class="admins">
        <li class="admin">NETID</li>
        <li class="admin">CERTNAME.host.washington.edu</li>
    </ul>
  </div>
</body>
</html>
"""

XHTML_BODY = XHTML_TPL % (GROUP_DESCRIPTION, GROUP_NAME)

connection.request('PUT', URL, body=XHTML_BODY)

print "%d %s" % (response.status, response.reason)

Example: Parsing XHTML for Group Members

import xml.dom.minidom

body = response.read()

group_members_array = []
dom = xml.dom.minidom.parseString(body)

# HTML <li>
listitems = dom.getElementsByTagName('li')
for member in listitems:
    m = member.firstChild
    if (m is not None and m.getAttribute('class') == 'member'):
        group_members_array.append(m.firstChild.data)

return group_members_array

Resources
http://docs.python.org/release/2.6/library/httplib.html
http://docs.python-requests.org/en/master/

4 Comments

  1. In the first example, it isn't clear where the symbol 'ssl' comes from (it's a class imported from httplib). I believe that the example should be

    context = httplib.ssl.create_default_context()

     

    1. Thanks for catching this.  The price I pay for not testing code I put here–I added code from one of our customers without regard to import statements.  Fixed.  

      1. Thanks! I did look briefly at using the requests library. It sounds like requests looks for root certs on the system (http://docs.python-requests.org/en/master/user/advanced/#ca-certificates), and it wasn't obvious how to provide root cert when setting up the connection. Do you happen to have any example code using requests?

        1. I just added some preliminary code using requests which should answer this question (you probably already figured this out but for the next folks)