3 # Copyright (C) 2015 Rob Crittenden <rcritten@redhat.com>
5 # see file 'COPYING' for use and warranty information
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
21 from helpers.common import IpsilonTestBase # pylint: disable=relative-import
22 from helpers.http import HttpSessions # pylint: disable=relative-import
26 from string import Template
29 idp_g = {'TEMPLATES': '${TESTDIR}/templates/install',
30 'CONFDIR': '${TESTDIR}/etc',
31 'DATADIR': '${TESTDIR}/lib',
32 'HTTPDCONFD': '${TESTDIR}/${NAME}/conf.d',
33 'STATICDIR': '${ROOTDIR}',
34 'BINDIR': '${ROOTDIR}/ipsilon',
35 'WSGI_SOCKET_PREFIX': '${TESTDIR}/${NAME}/logs/wsgi'}
38 idp_a = {'hostname': '${ADDRESS}:${PORT}',
39 'admin_user': '${TEST_USER}',
40 'system_user': '${TEST_USER}',
41 'instance': '${NAME}',
47 'server_debugging': 'True'}
50 sp_g = {'HTTPDCONFD': '${TESTDIR}/${NAME}/conf.d',
51 'SAML2_TEMPLATE': '${TESTDIR}/templates/install/saml2/sp.conf',
52 'SAML2_CONFFILE': '${TESTDIR}/${NAME}/conf.d/ipsilon-saml.conf',
53 'SAML2_HTTPDIR': '${TESTDIR}/${NAME}/saml2'}
56 sp_a = {'hostname': '${ADDRESS}:${PORT}',
57 'saml_idp_metadata': 'http://127.0.0.10:45080/idp1/saml2/metadata',
58 'saml_secure_setup': 'False',
60 'httpd_user': '${TEST_USER}'}
63 sp2_g = {'HTTPDCONFD': '${TESTDIR}/${NAME}/conf.d',
64 'SAML2_TEMPLATE': '${TESTDIR}/templates/install/saml2/sp.conf',
65 'SAML2_CONFFILE': '${TESTDIR}/${NAME}/conf.d/ipsilon-saml.conf',
66 'SAML2_HTTPDIR': '${TESTDIR}/${NAME}/saml2'}
69 sp2_a = {'hostname': '${ADDRESS}:${PORT}',
70 'saml_idp_metadata': 'http://127.0.0.10:45080/idp1/saml2/metadata',
71 'saml_secure_setup': 'False',
73 'httpd_user': '${TEST_USER}'}
76 def fixup_sp_httpd(httpdir):
79 Alias /sp ${HTTPDIR}/sp
81 <Directory ${HTTPDIR}/sp>
85 Alias /open ${HTTPDIR}/open
87 <Directory ${HTTPDIR}/open>
91 logged_out = """Logged out"""
93 t = Template(location)
94 text = t.substitute({'HTTPDIR': httpdir})
95 with open(httpdir + '/conf.d/ipsilon-saml.conf', 'a') as f:
98 os.mkdir(httpdir + '/sp')
99 with open(httpdir + '/sp/index.html', 'w') as f:
101 os.mkdir(httpdir + '/open')
102 with open(httpdir + '/open/logged_out.html', 'w') as f:
106 def ensure_logout(session, idp_name, spurl):
108 Fetch the secure page without following redirects. If we get
109 a 303 then we should be redirected to the IDP for authentication
110 which means we aren't logged in.
112 Returns nothing or raises exception on error
115 logout_page = session.fetch_page(idp_name, spurl,
116 follow_redirect=False)
117 if logout_page.result.status_code != 303:
118 raise ValueError('Still logged into url')
125 class IpsilonTest(IpsilonTestBase):
128 super(IpsilonTest, self).__init__('testlogout', __file__)
130 def setup_servers(self, env=None):
131 print "Installing IDP server"
135 idp = self.generate_profile(idp_g, idp_a, name, addr, port)
136 conf = self.setup_idp_server(idp, name, addr, port, env)
138 print "Starting IDP's httpd server"
139 self.start_http_server(conf, env)
141 print "Installing SP server"
145 sp = self.generate_profile(sp_g, sp_a, name, addr, port)
146 conf = self.setup_sp_server(sp, name, addr, port, env)
147 fixup_sp_httpd(os.path.dirname(conf))
149 print "Starting SP's httpd server"
150 self.start_http_server(conf, env)
152 print "Installing second SP server"
156 sp2 = self.generate_profile(sp2_g, sp2_a, name, addr, port)
157 conf = self.setup_sp_server(sp2, name, addr, port, env)
158 fixup_sp_httpd(os.path.dirname(conf))
160 print "Starting SP's httpd server"
161 self.start_http_server(conf, env)
164 if __name__ == '__main__':
169 user = pwd.getpwuid(os.getuid())[0]
171 sess = HttpSessions()
172 sess.add_server(idpname, 'http://127.0.0.10:45080', user, 'ipsilon')
173 sess.add_server(spname, 'http://127.0.0.11:45081')
174 sess.add_server(sp2name, 'http://127.0.0.10:45082')
176 print "testlogout: Authenticate to IDP ...",
178 sess.auth_to_idp(idpname)
179 except Exception, e: # pylint: disable=broad-except
180 print >> sys.stderr, " ERROR: %s" % repr(e)
184 print "testlogout: Add SP Metadata to IDP ...",
186 sess.add_sp_metadata(idpname, spname)
187 except Exception, e: # pylint: disable=broad-except
188 print >> sys.stderr, " ERROR: %s" % repr(e)
192 print "testlogout: Add second SP Metadata to IDP ...",
194 sess.add_sp_metadata(idpname, sp2name)
195 except Exception, e: # pylint: disable=broad-except
196 print >> sys.stderr, " ERROR: %s" % repr(e)
200 print "testlogout: Logout without logging into SP ...",
202 page = sess.fetch_page(idpname, '%s/%s?%s' % (
203 'http://127.0.0.11:45081', 'saml2/logout',
204 'ReturnTo=http://127.0.0.11:45081/open/logged_out.html'))
205 page.expected_value('text()', 'Logged out')
206 except ValueError, e:
207 print >> sys.stderr, " ERROR: %s" % repr(e)
211 print "testlogout: Access SP Protected Area ...",
213 page = sess.fetch_page(idpname, 'http://127.0.0.11:45081/sp/')
214 page.expected_value('text()', 'WORKS!')
215 except ValueError, e:
216 print >> sys.stderr, " ERROR: %s" % repr(e)
220 print "testlogout: Logout from SP ...",
222 page = sess.fetch_page(idpname, '%s/%s?%s' % (
223 'http://127.0.0.11:45081', 'saml2/logout',
224 'ReturnTo=http://127.0.0.11:45081/open/logged_out.html'))
225 page.expected_value('text()', 'Logged out')
226 except ValueError, e:
227 print >> sys.stderr, " ERROR: %s" % repr(e)
231 print "testlogout: Try logout again ...",
233 page = sess.fetch_page(idpname, '%s/%s?%s' % (
234 'http://127.0.0.11:45081', 'saml2/logout',
235 'ReturnTo=http://127.0.0.11:45081/open/logged_out.html'))
236 page.expected_value('text()', 'Logged out')
237 except ValueError, e:
238 print >> sys.stderr, " ERROR: %s" % repr(e)
242 print "testlogout: Ensure logout ...",
244 ensure_logout(sess, idpname, 'http://127.0.0.11:45081/sp/')
245 except ValueError, e:
246 print >> sys.stderr, " ERROR: %s" % repr(e)
250 print "testlogout: Access SP Protected Area of SP1...",
252 page = sess.fetch_page(idpname, 'http://127.0.0.11:45081/sp/')
253 page.expected_value('text()', 'WORKS!')
254 except ValueError, e:
255 print >> sys.stderr, " ERROR: %s" % repr(e)
259 print "testlogout: Access SP Protected Area of SP2...",
261 page = sess.fetch_page(idpname, 'http://127.0.0.10:45082/sp/')
262 page.expected_value('text()', 'WORKS!')
263 except ValueError, e:
264 print >> sys.stderr, " ERROR: %s" % repr(e)
268 print "testlogout: Logout from both ...",
270 page = sess.fetch_page(idpname, '%s/%s?%s' % (
271 'http://127.0.0.11:45081', 'saml2/logout',
272 'ReturnTo=http://127.0.0.11:45081/open/logged_out.html'))
273 page.expected_value('text()', 'Logged out')
274 except ValueError, e:
275 print >> sys.stderr, " ERROR: %s" % repr(e)
279 print "testlogout: Ensure logout of SP1 ...",
281 ensure_logout(sess, idpname, 'http://127.0.0.11:45081/sp/')
282 except ValueError, e:
283 print >> sys.stderr, " ERROR: %s" % repr(e)
287 print "testlogout: Ensure logout of SP2 ...",
289 ensure_logout(sess, idpname, 'http://127.0.0.10:45082/sp/')
290 except ValueError, e:
291 print >> sys.stderr, " ERROR: %s" % repr(e)
295 # Test IdP-initiated logout
296 print "testlogout: Access SP Protected Area of SP1...",
298 page = sess.fetch_page(idpname, 'http://127.0.0.11:45081/sp/')
299 page.expected_value('text()', 'WORKS!')
300 except ValueError, e:
301 print >> sys.stderr, " ERROR: %s" % repr(e)
305 print "testlogout: Access SP Protected Area of SP2...",
307 page = sess.fetch_page(idpname, 'http://127.0.0.10:45082/sp/')
308 page.expected_value('text()', 'WORKS!')
309 except ValueError, e:
310 print >> sys.stderr, " ERROR: %s" % repr(e)
314 print "testlogout: Access the IdP...",
316 page = sess.fetch_page(idpname, 'http://127.0.0.10:45080/%s' % idpname)
317 page.expected_value('//div[@id="welcome"]/p/text()',
318 'Welcome %s!' % user)
319 except ValueError, e:
320 print >> sys.stderr, " ERROR: %s" % repr(e)
324 print "testlogout: IdP-initiated logout ...",
326 page = sess.fetch_page(idpname,
327 'http://127.0.0.10:45080/%s/logout' % idpname)
328 page.expected_value('//div[@id="content"]/p/a/text()', 'Log In')
329 except ValueError, e:
330 print >> sys.stderr, " ERROR: %s" % repr(e)
334 print "testlogout: Ensure logout of SP1 ...",
336 ensure_logout(sess, idpname, 'http://127.0.0.11:45081/sp/')
337 except ValueError, e:
338 print >> sys.stderr, " ERROR: %s" % repr(e)
342 print "testlogout: Ensure logout of SP2 ...",
344 ensure_logout(sess, idpname, 'http://127.0.0.10:45082/sp/')
345 except ValueError, e:
346 print >> sys.stderr, " ERROR: %s" % repr(e)
350 print "testlogout: Access the IdP...",
352 page = sess.fetch_page(idpname,
353 'http://127.0.0.10:45080/%s/login' % idpname)
354 page.expected_value('//div[@id="welcome"]/p/text()',
355 'Welcome %s!' % user)
356 except ValueError, e:
357 print >> sys.stderr, " ERROR: %s" % repr(e)
361 print "testlogout: IdP-initiated logout with no SP sessions...",
363 page = sess.fetch_page(idpname,
364 'http://127.0.0.10:45080/%s/logout' % idpname)
365 page.expected_value('//div[@id="logout"]/p//text()',
366 'Successfully logged out.')
367 except ValueError, e:
368 print >> sys.stderr, " ERROR: %s" % repr(e)