Change references to authkrb plugin to authgssapi
[cascardo/ipsilon.git] / tests / testmapping.py
1 #!/usr/bin/python
2 # Copyright (C) 2015 Ipsilon Project Contributors
3
4 from helpers.common import IpsilonTestBase  # pylint: disable=relative-import
5 from helpers.http import HttpSessions  # pylint: disable=relative-import
6 import os
7 import sys
8 import pwd
9 from string import Template
10
11 # Test Attribute Mapping and Allowed Attributes and their per-SP
12 # overrides.
13
14
15 idp_g = {'TEMPLATES': '${TESTDIR}/templates/install',
16          'CONFDIR': '${TESTDIR}/etc',
17          'DATADIR': '${TESTDIR}/lib',
18          'HTTPDCONFD': '${TESTDIR}/${NAME}/conf.d',
19          'STATICDIR': '${ROOTDIR}',
20          'BINDIR': '${ROOTDIR}/ipsilon',
21          'WSGI_SOCKET_PREFIX': '${TESTDIR}/${NAME}/logs/wsgi'}
22
23
24 idp_a = {'hostname': '${ADDRESS}:${PORT}',
25          'admin_user': '${TEST_USER}',
26          'system_user': '${TEST_USER}',
27          'instance': '${NAME}',
28          'secure': 'no',
29          'testauth': 'yes',
30          'pam': 'no',
31          'gssapi': 'no',
32          'ipa': 'no',
33          'server_debugging': 'True'}
34
35
36 sp_g = {'HTTPDCONFD': '${TESTDIR}/${NAME}/conf.d',
37         'SAML2_TEMPLATE': '${TESTDIR}/templates/install/saml2/sp.conf',
38         'SAML2_CONFFILE': '${TESTDIR}/${NAME}/conf.d/ipsilon-saml.conf',
39         'SAML2_HTTPDIR': '${TESTDIR}/${NAME}/saml2'}
40
41
42 sp_a = {'hostname': '${ADDRESS}:${PORT}',
43         'saml_idp_metadata': 'http://127.0.0.10:45080/idp1/saml2/metadata',
44         'saml_secure_setup': 'False',
45         'saml_auth': '/sp',
46         'saml_nameid': '${NAMEID}',
47         'httpd_user': '${TEST_USER}'}
48
49 sp_list = [
50     {'name': 'sp1', 'addr': '127.0.0.11', 'port': '45081'},
51 ]
52
53
54 def convert_to_dict(envlist):
55     values = {}
56     for pair in envlist.split('\n'):
57         if pair.find('=') > 0:
58             (key, value) = pair.split('=', 1)
59             if key.startswith('MELLON_') and not key.endswith('_0'):
60                 values[key] = value
61     return values
62
63
64 def check_info_plugin(s, idp_name, urlbase, expected):
65     """
66     Logout, login, fetch SP page to get the info variables and
67     compare the MELLON_ ones to what we expect.  IDP and NAMEID are
68     ignored.
69     """
70
71     # Log out
72     page = s.fetch_page(idp_name, '%s/%s?%s' % (
73         urlbase, 'saml2/logout',
74         'ReturnTo=%s/open/logged_out.html' % urlbase))
75     page.expected_value('text()', 'Logged out')
76
77     # Fetch the page (with implicit login)
78     page = s.fetch_page(idp_name, '%s/sp/' % spurl)
79
80     # Confirm that the expected values are in the output and that there
81     # are no unexpected MELLON_ vars, and drop the _0 version.
82     data = convert_to_dict(page.text)
83
84     data.pop('MELLON_IDP')
85     data.pop('MELLON_NAME_ID')
86
87     for key in expected.keys():
88         item = data.pop('MELLON_' + key)
89         if item != expected[key]:
90             raise ValueError('Expected %s, got %s' % (expected[key], item))
91
92     if len(data) > 0:
93         raise ValueError('Unexpected values %s' % data)
94
95
96 def fixup_sp_httpd(httpdir):
97     location = """
98
99 AddOutputFilter INCLUDES .html
100
101 Alias /sp ${HTTPDIR}/sp
102
103 <Directory ${HTTPDIR}/sp>
104     Require all granted
105     Options +Includes
106 </Directory>
107
108 Alias /open ${HTTPDIR}/open
109
110 <Directory ${HTTPDIR}/open>
111 </Directory>
112
113 """
114     index = """
115 <!--#printenv  -->
116 """
117     logged_out = """Logged out"""
118
119     t = Template(location)
120     text = t.substitute({'HTTPDIR': httpdir})
121     with open(httpdir + '/conf.d/ipsilon-saml.conf', 'a') as f:
122         f.write(text)
123
124     os.mkdir(httpdir + '/sp')
125     with open(httpdir + '/sp/index.html', 'w') as f:
126         f.write(index)
127     os.mkdir(httpdir + '/open')
128     with open(httpdir + '/open/logged_out.html', 'w') as f:
129         f.write(logged_out)
130
131
132 class IpsilonTest(IpsilonTestBase):
133
134     def __init__(self):
135         super(IpsilonTest, self).__init__('testmapping', __file__)
136
137     def setup_servers(self, env=None):
138         print "Installing IDP server"
139         name = 'idp1'
140         addr = '127.0.0.10'
141         port = '45080'
142         idp = self.generate_profile(idp_g, idp_a, name, addr, port)
143         conf = self.setup_idp_server(idp, name, addr, port, env)
144
145         print "Starting IDP's httpd server"
146         self.start_http_server(conf, env)
147
148         for spdata in sp_list:
149             addr = spdata['addr']
150             port = spdata['port']
151             name = spdata['name']
152
153             print "Installing SP server %s" % name
154             sp_prof = self.generate_profile(sp_g, sp_a, name, addr, str(port))
155             conf = self.setup_sp_server(sp_prof, name, addr, str(port), env)
156             fixup_sp_httpd(os.path.dirname(conf))
157
158             print "Starting SP's httpd server"
159             self.start_http_server(conf, env)
160
161
162 if __name__ == '__main__':
163
164     idpname = 'idp1'
165     user = pwd.getpwuid(os.getuid())[0]
166     sp = sp_list[0]
167     spurl = 'http://%s:%s' % (sp['addr'], sp['port'])
168
169     # Set global mapping and allowed attributes, then test fetch from
170     # SP.
171     sess = HttpSessions()
172     sess.add_server(idpname, 'http://127.0.0.10:45080', user, 'ipsilon')
173     sess.add_server(sp['name'], spurl)
174
175     print "testmapping: Authenticate to IDP ...",
176     try:
177         sess.auth_to_idp(idpname)
178     except Exception, e:  # pylint: disable=broad-except
179         print >> sys.stderr, " ERROR: %s" % repr(e)
180         sys.exit(1)
181     print " SUCCESS"
182
183     print "testmapping: Add SP Metadata to IDP ...",
184     try:
185         sess.add_sp_metadata(idpname, sp['name'])
186     except Exception, e:  # pylint: disable=broad-except
187         print >> sys.stderr, " ERROR: %s" % repr(e)
188         sys.exit(1)
189     print " SUCCESS"
190
191     try:
192         print "testmapping: Test default mapping and attrs ...",
193         expect = {
194             'fullname': 'Test User %s' % user,
195             'surname': user,
196             'givenname': 'Test User',
197             'email': '%s@example.com' % user,
198             'groups': user,
199         }
200         check_info_plugin(sess, idpname, spurl, expect)
201     except Exception, e:  # pylint: disable=broad-except
202         print >> sys.stderr, " ERROR: %s" % repr(e)
203         sys.exit(1)
204     print " SUCCESS"
205
206     print "testmapping: Set default global mapping ...",
207     try:
208         sess.set_attributes_and_mapping(idpname,
209                                         [['*', '*'],
210                                          ['fullname', 'namefull']])
211     except Exception, e:  # pylint: disable=broad-except
212         print >> sys.stderr, " ERROR: %s" % repr(e)
213         sys.exit(1)
214     else:
215         print " SUCCESS"
216
217     try:
218         print "testmapping: Test global mapping ...",
219         expect = {
220             'fullname': 'Test User %s' % user,
221             'namefull': 'Test User %s' % user,
222             'surname': user,
223             'givenname': 'Test User',
224             'email': '%s@example.com' % user,
225             'groups': user
226         }
227         check_info_plugin(sess, idpname, spurl, expect)
228     except Exception, e:  # pylint: disable=broad-except
229         print >> sys.stderr, " ERROR: %s" % repr(e)
230         sys.exit(1)
231     else:
232         print " SUCCESS"
233
234     print "testmapping: Set default allowed attributes ...",
235     try:
236         sess.set_attributes_and_mapping(idpname, [],
237                                         ['namefull', 'givenname', 'surname'])
238     except Exception, e:  # pylint: disable=broad-except
239         print >> sys.stderr, " ERROR: %s" % repr(e)
240         sys.exit(1)
241     else:
242         print " SUCCESS"
243
244     try:
245         print "testmapping: Test global allowed attributes ...",
246         expect = {
247             'namefull': 'Test User %s' % user,
248             'surname': user,
249             'givenname': 'Test User',
250         }
251         check_info_plugin(sess, idpname, spurl, expect)
252     except Exception, e:  # pylint: disable=broad-except
253         print >> sys.stderr, " ERROR: %s" % repr(e)
254         sys.exit(1)
255     else:
256         print " SUCCESS"
257
258     print "testmapping: Set SP allowed attributes ...",
259     try:
260         sess.set_attributes_and_mapping(idpname, [['*', '*']],
261                                         ['wholename', 'givenname', 'surname',
262                                         'email', 'fullname'], sp['name'])
263     except Exception, e:  # pylint: disable=broad-except
264         print >> sys.stderr, " ERROR: %s" % repr(e)
265         sys.exit(1)
266     else:
267         print " SUCCESS"
268
269     try:
270         print "testmapping: Test SP allowed atributes ...",
271         expect = {
272             'fullname': 'Test User %s' % user,
273             'surname': user,
274             'givenname': 'Test User',
275             'email': '%s@example.com' % user,
276         }
277         check_info_plugin(sess, idpname, spurl, expect)
278     except Exception, e:  # pylint: disable=broad-except
279         print >> sys.stderr, " ERROR: %s" % repr(e)
280         sys.exit(1)
281     else:
282         print " SUCCESS"
283
284     print "testmapping: Set SP attribute mapping ...",
285     try:
286         sess.set_attributes_and_mapping(idpname,
287                                         [['*', '*'],
288                                          ['fullname', 'wholename']],
289                                         ['wholename', 'givenname',
290                                          'surname',
291                                          'email', 'fullname'],
292                                         sp['name'])
293     except Exception, e:  # pylint: disable=broad-except
294         print >> sys.stderr, " ERROR: %s" % repr(e)
295         sys.exit(1)
296     else:
297         print " SUCCESS"
298
299     try:
300         print "testmapping: Test SP attribute mapping ...",
301         expect = {
302             'wholename': 'Test User %s' % user,
303             'fullname': 'Test User %s' % user,
304             'surname': user,
305             'givenname': 'Test User',
306             'email': '%s@example.com' % user,
307         }
308         check_info_plugin(sess, idpname, spurl, expect)
309     except Exception, e:  # pylint: disable=broad-except
310         print >> sys.stderr, " ERROR: %s" % repr(e)
311         sys.exit(1)
312     else:
313         print " SUCCESS"
314
315     print "testmapping: Drop SP attribute mapping ...",
316     try:
317         sess.set_attributes_and_mapping(idpname, [],
318                                         ['givenname', 'surname', 'email',
319                                          'fullname'], sp['name'])
320     except Exception, e:  # pylint: disable=broad-except
321         print >> sys.stderr, " ERROR: %s" % repr(e)
322         sys.exit(1)
323     else:
324         print " SUCCESS"
325
326     try:
327         print "testmapping: Test SP attr mapping with default allowed...",
328         expect = {
329             'fullname': 'Test User %s' % user,
330             'surname': user,
331             'givenname': 'Test User',
332             'email': '%s@example.com' % user,
333         }
334         check_info_plugin(sess, idpname, spurl, expect)
335     except Exception, e:  # pylint: disable=broad-except
336         print >> sys.stderr, " ERROR: %s" % repr(e)
337         sys.exit(1)
338     else:
339         print " SUCCESS"
340
341     print "testmapping: Drop SP allowed attributes ...",
342     try:
343         sess.set_attributes_and_mapping(idpname, [], [], sp['name'])
344     except Exception, e:  # pylint: disable=broad-except
345         print >> sys.stderr, " ERROR: %s" % repr(e)
346         sys.exit(1)
347     else:
348         print " SUCCESS"
349
350     try:
351         print "testmapping: Test mapping, should be back to global...",
352         expect = {
353             'namefull': 'Test User %s' % user,
354             'surname': user,
355             'givenname': 'Test User',
356         }
357         check_info_plugin(sess, idpname, spurl, expect)
358     except Exception, e:  # pylint: disable=broad-except
359         print >> sys.stderr, " ERROR: %s" % repr(e)
360         sys.exit(1)
361     else:
362         print " SUCCESS"