Update Copyright header point to COPYING file
[cascardo/ipsilon.git] / tests / testlogout.py
1 #!/usr/bin/python
2 #
3 # Copyright (C) 2015 Ipsilon project Contributors, for license see COPYING
4
5 from helpers.common import IpsilonTestBase  # pylint: disable=relative-import
6 from helpers.http import HttpSessions  # pylint: disable=relative-import
7 import os
8 import pwd
9 import sys
10 from string import Template
11
12
13 idp_g = {'TEMPLATES': '${TESTDIR}/templates/install',
14          'CONFDIR': '${TESTDIR}/etc',
15          'DATADIR': '${TESTDIR}/lib',
16          'HTTPDCONFD': '${TESTDIR}/${NAME}/conf.d',
17          'STATICDIR': '${ROOTDIR}',
18          'BINDIR': '${ROOTDIR}/ipsilon',
19          'WSGI_SOCKET_PREFIX': '${TESTDIR}/${NAME}/logs/wsgi'}
20
21
22 idp_a = {'hostname': '${ADDRESS}:${PORT}',
23          'admin_user': '${TEST_USER}',
24          'system_user': '${TEST_USER}',
25          'instance': '${NAME}',
26          'secure': 'no',
27          'testauth': 'yes',
28          'pam': 'no',
29          'gssapi': 'no',
30          'ipa': 'no',
31          'server_debugging': 'True'}
32
33
34 sp_g = {'HTTPDCONFD': '${TESTDIR}/${NAME}/conf.d',
35         'SAML2_TEMPLATE': '${TESTDIR}/templates/install/saml2/sp.conf',
36         'SAML2_CONFFILE': '${TESTDIR}/${NAME}/conf.d/ipsilon-saml.conf',
37         'SAML2_HTTPDIR': '${TESTDIR}/${NAME}/saml2'}
38
39
40 sp_a = {'hostname': '${ADDRESS}:${PORT}',
41         'saml_idp_metadata': 'http://127.0.0.10:45080/idp1/saml2/metadata',
42         'saml_secure_setup': 'False',
43         'saml_auth': '/sp',
44         'httpd_user': '${TEST_USER}'}
45
46
47 sp2_g = {'HTTPDCONFD': '${TESTDIR}/${NAME}/conf.d',
48          'SAML2_TEMPLATE': '${TESTDIR}/templates/install/saml2/sp.conf',
49          'SAML2_CONFFILE': '${TESTDIR}/${NAME}/conf.d/ipsilon-saml.conf',
50          'SAML2_HTTPDIR': '${TESTDIR}/${NAME}/saml2'}
51
52
53 sp2_a = {'hostname': '${ADDRESS}:${PORT}',
54          'saml_idp_metadata': 'http://127.0.0.10:45080/idp1/saml2/metadata',
55          'saml_secure_setup': 'False',
56          'saml_auth': '/sp',
57          'httpd_user': '${TEST_USER}'}
58
59
60 def fixup_sp_httpd(httpdir):
61     location = """
62
63 Alias /sp ${HTTPDIR}/sp
64
65 <Directory ${HTTPDIR}/sp>
66     Require all granted
67 </Directory>
68
69 Alias /open ${HTTPDIR}/open
70
71 <Directory ${HTTPDIR}/open>
72 </Directory>
73 """
74     index = """WORKS!"""
75     logged_out = """Logged out"""
76
77     t = Template(location)
78     text = t.substitute({'HTTPDIR': httpdir})
79     with open(httpdir + '/conf.d/ipsilon-saml.conf', 'a') as f:
80         f.write(text)
81
82     os.mkdir(httpdir + '/sp')
83     with open(httpdir + '/sp/index.html', 'w') as f:
84         f.write(index)
85     os.mkdir(httpdir + '/open')
86     with open(httpdir + '/open/logged_out.html', 'w') as f:
87         f.write(logged_out)
88
89
90 def ensure_logout(session, idp_name, spurl):
91     """
92     Fetch the secure page without following redirects. If we get
93     a 303 then we should be redirected to the IDP for authentication
94     which means we aren't logged in.
95
96     Returns nothing or raises exception on error
97     """
98     try:
99         logout_page = session.fetch_page(idp_name, spurl,
100                                          follow_redirect=False)
101         if logout_page.result.status_code != 303:
102             raise ValueError('Still logged into url')
103     except ValueError:
104         raise
105
106     return True
107
108
109 class IpsilonTest(IpsilonTestBase):
110
111     def __init__(self):
112         super(IpsilonTest, self).__init__('testlogout', __file__)
113
114     def setup_servers(self, env=None):
115         print "Installing IDP server"
116         name = 'idp1'
117         addr = '127.0.0.10'
118         port = '45080'
119         idp = self.generate_profile(idp_g, idp_a, name, addr, port)
120         conf = self.setup_idp_server(idp, name, addr, port, env)
121
122         print "Starting IDP's httpd server"
123         self.start_http_server(conf, env)
124
125         print "Installing SP server"
126         name = 'sp1'
127         addr = '127.0.0.11'
128         port = '45081'
129         sp = self.generate_profile(sp_g, sp_a, name, addr, port)
130         conf = self.setup_sp_server(sp, name, addr, port, env)
131         fixup_sp_httpd(os.path.dirname(conf))
132
133         print "Starting SP's httpd server"
134         self.start_http_server(conf, env)
135
136         print "Installing second SP server"
137         name = 'sp2'
138         addr = '127.0.0.10'
139         port = '45082'
140         sp2 = self.generate_profile(sp2_g, sp2_a, name, addr, port)
141         conf = self.setup_sp_server(sp2, name, addr, port, env)
142         fixup_sp_httpd(os.path.dirname(conf))
143
144         print "Starting SP's httpd server"
145         self.start_http_server(conf, env)
146
147
148 if __name__ == '__main__':
149
150     idpname = 'idp1'
151     spname = 'sp1'
152     sp2name = 'sp2'
153     user = pwd.getpwuid(os.getuid())[0]
154
155     sess = HttpSessions()
156     sess.add_server(idpname, 'http://127.0.0.10:45080', user, 'ipsilon')
157     sess.add_server(spname, 'http://127.0.0.11:45081')
158     sess.add_server(sp2name, 'http://127.0.0.10:45082')
159
160     print "testlogout: Authenticate to IDP ...",
161     try:
162         sess.auth_to_idp(idpname)
163     except Exception, e:  # pylint: disable=broad-except
164         print >> sys.stderr, " ERROR: %s" % repr(e)
165         sys.exit(1)
166     print " SUCCESS"
167
168     print "testlogout: Add SP Metadata to IDP ...",
169     try:
170         sess.add_sp_metadata(idpname, spname)
171     except Exception, e:  # pylint: disable=broad-except
172         print >> sys.stderr, " ERROR: %s" % repr(e)
173         sys.exit(1)
174     print " SUCCESS"
175
176     print "testlogout: Add second SP Metadata to IDP ...",
177     try:
178         sess.add_sp_metadata(idpname, sp2name)
179     except Exception, e:  # pylint: disable=broad-except
180         print >> sys.stderr, " ERROR: %s" % repr(e)
181         sys.exit(1)
182     print " SUCCESS"
183
184     print "testlogout: Logout without logging into SP ...",
185     try:
186         page = sess.fetch_page(idpname, '%s/%s?%s' % (
187             'http://127.0.0.11:45081', 'saml2/logout',
188             'ReturnTo=http://127.0.0.11:45081/open/logged_out.html'))
189         page.expected_value('text()', 'Logged out')
190     except ValueError, e:
191         print >> sys.stderr, " ERROR: %s" % repr(e)
192         sys.exit(1)
193     print " SUCCESS"
194
195     print "testlogout: Access SP Protected Area ...",
196     try:
197         page = sess.fetch_page(idpname, 'http://127.0.0.11:45081/sp/')
198         page.expected_value('text()', 'WORKS!')
199     except ValueError, e:
200         print >> sys.stderr, " ERROR: %s" % repr(e)
201         sys.exit(1)
202     print " SUCCESS"
203
204     print "testlogout: Logout from SP ...",
205     try:
206         page = sess.fetch_page(idpname, '%s/%s?%s' % (
207             'http://127.0.0.11:45081', 'saml2/logout',
208             'ReturnTo=http://127.0.0.11:45081/open/logged_out.html'))
209         page.expected_value('text()', 'Logged out')
210     except ValueError, e:
211         print >> sys.stderr, " ERROR: %s" % repr(e)
212         sys.exit(1)
213     print " SUCCESS"
214
215     print "testlogout: Try logout again ...",
216     try:
217         page = sess.fetch_page(idpname, '%s/%s?%s' % (
218             'http://127.0.0.11:45081', 'saml2/logout',
219             'ReturnTo=http://127.0.0.11:45081/open/logged_out.html'))
220         page.expected_value('text()', 'Logged out')
221     except ValueError, e:
222         print >> sys.stderr, " ERROR: %s" % repr(e)
223         sys.exit(1)
224     print " SUCCESS"
225
226     print "testlogout: Ensure logout ...",
227     try:
228         ensure_logout(sess, idpname, 'http://127.0.0.11:45081/sp/')
229     except ValueError, e:
230         print >> sys.stderr, " ERROR: %s" % repr(e)
231         sys.exit(1)
232     print " SUCCESS"
233
234     print "testlogout: Access SP Protected Area of SP1...",
235     try:
236         page = sess.fetch_page(idpname, 'http://127.0.0.11:45081/sp/')
237         page.expected_value('text()', 'WORKS!')
238     except ValueError, e:
239         print >> sys.stderr, " ERROR: %s" % repr(e)
240         sys.exit(1)
241     print " SUCCESS"
242
243     print "testlogout: Access SP Protected Area of SP2...",
244     try:
245         page = sess.fetch_page(idpname, 'http://127.0.0.10:45082/sp/')
246         page.expected_value('text()', 'WORKS!')
247     except ValueError, e:
248         print >> sys.stderr, " ERROR: %s" % repr(e)
249         sys.exit(1)
250     print " SUCCESS"
251
252     print "testlogout: Logout from both ...",
253     try:
254         page = sess.fetch_page(idpname, '%s/%s?%s' % (
255             'http://127.0.0.11:45081', 'saml2/logout',
256             'ReturnTo=http://127.0.0.11:45081/open/logged_out.html'))
257         page.expected_value('text()', 'Logged out')
258     except ValueError, e:
259         print >> sys.stderr, " ERROR: %s" % repr(e)
260         sys.exit(1)
261     print " SUCCESS"
262
263     print "testlogout: Ensure logout of SP1 ...",
264     try:
265         ensure_logout(sess, idpname, 'http://127.0.0.11:45081/sp/')
266     except ValueError, e:
267         print >> sys.stderr, " ERROR: %s" % repr(e)
268         sys.exit(1)
269     print " SUCCESS"
270
271     print "testlogout: Ensure logout of SP2 ...",
272     try:
273         ensure_logout(sess, idpname, 'http://127.0.0.10:45082/sp/')
274     except ValueError, e:
275         print >> sys.stderr, " ERROR: %s" % repr(e)
276         sys.exit(1)
277     print " SUCCESS"
278
279     # Test IdP-initiated logout
280     print "testlogout: Access SP Protected Area of SP1...",
281     try:
282         page = sess.fetch_page(idpname, 'http://127.0.0.11:45081/sp/')
283         page.expected_value('text()', 'WORKS!')
284     except ValueError, e:
285         print >> sys.stderr, " ERROR: %s" % repr(e)
286         sys.exit(1)
287     print " SUCCESS"
288
289     print "testlogout: Access SP Protected Area of SP2...",
290     try:
291         page = sess.fetch_page(idpname, 'http://127.0.0.10:45082/sp/')
292         page.expected_value('text()', 'WORKS!')
293     except ValueError, e:
294         print >> sys.stderr, " ERROR: %s" % repr(e)
295         sys.exit(1)
296     print " SUCCESS"
297
298     print "testlogout: Access the IdP...",
299     try:
300         page = sess.fetch_page(idpname, 'http://127.0.0.10:45080/%s' % idpname)
301         page.expected_value('//div[@id="welcome"]/p/text()',
302                             'Welcome %s!' % user)
303     except ValueError, e:
304         print >> sys.stderr, " ERROR: %s" % repr(e)
305         sys.exit(1)
306     print " SUCCESS"
307
308     print "testlogout: IdP-initiated logout ...",
309     try:
310         page = sess.fetch_page(idpname,
311                                'http://127.0.0.10:45080/%s/logout' % idpname)
312         page.expected_value('//div[@id="content"]/p/a/text()', 'Log In')
313     except ValueError, e:
314         print >> sys.stderr, " ERROR: %s" % repr(e)
315         sys.exit(1)
316     print " SUCCESS"
317
318     print "testlogout: Ensure logout of SP1 ...",
319     try:
320         ensure_logout(sess, idpname, 'http://127.0.0.11:45081/sp/')
321     except ValueError, e:
322         print >> sys.stderr, " ERROR: %s" % repr(e)
323         sys.exit(1)
324     print " SUCCESS"
325
326     print "testlogout: Ensure logout of SP2 ...",
327     try:
328         ensure_logout(sess, idpname, 'http://127.0.0.10:45082/sp/')
329     except ValueError, e:
330         print >> sys.stderr, " ERROR: %s" % repr(e)
331         sys.exit(1)
332     print " SUCCESS"
333
334     print "testlogout: Access the IdP...",
335     try:
336         page = sess.fetch_page(idpname,
337                                'http://127.0.0.10:45080/%s/login' % idpname)
338         page.expected_value('//div[@id="welcome"]/p/text()',
339                             'Welcome %s!' % user)
340     except ValueError, e:
341         print >> sys.stderr, " ERROR: %s" % repr(e)
342         sys.exit(1)
343     print " SUCCESS"
344
345     print "testlogout: IdP-initiated logout with no SP sessions...",
346     try:
347         page = sess.fetch_page(idpname,
348                                'http://127.0.0.10:45080/%s/logout' % idpname)
349         page.expected_value('//div[@id="logout"]/p//text()',
350                             'Successfully logged out.')
351     except ValueError, e:
352         print >> sys.stderr, " ERROR: %s" % repr(e)
353         sys.exit(1)
354     print " SUCCESS"