Add test for multi-SP logout
[cascardo/ipsilon.git] / tests / testlogout.py
1 #!/usr/bin/python
2 #
3 # Copyright (C) 2015  Rob Crittenden <rcritten@redhat.com>
4 #
5 # see file 'COPYING' for use and warranty information
6 #
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.
11 #
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.
16 #
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/>.
19
20
21 from helpers.common import IpsilonTestBase  # pylint: disable=relative-import
22 from helpers.http import HttpSessions  # pylint: disable=relative-import
23 import os
24 import pwd
25 import sys
26 from string import Template
27
28
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'}
36
37
38 idp_a = {'hostname': '${ADDRESS}:${PORT}',
39          'admin_user': '${TEST_USER}',
40          'system_user': '${TEST_USER}',
41          'instance': '${NAME}',
42          'secure': 'no',
43          'testauth': 'yes',
44          'pam': 'no',
45          'krb': 'no',
46          'ipa': 'no',
47          'server_debugging': 'True'}
48
49
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'}
54
55
56 sp_a = {'hostname': '${ADDRESS}:${PORT}',
57         'saml_idp_metadata': 'http://127.0.0.10:45080/idp1/saml2/metadata',
58         'saml_secure_setup': 'False',
59         'saml_auth': '/sp',
60         'httpd_user': '${TEST_USER}'}
61
62
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'}
67
68
69 sp2_a = {'hostname': '${ADDRESS}:${PORT}',
70          'saml_idp_metadata': 'http://127.0.0.10:45080/idp1/saml2/metadata',
71          'saml_secure_setup': 'False',
72          'saml_auth': '/sp',
73          'httpd_user': '${TEST_USER}'}
74
75
76 def fixup_sp_httpd(httpdir):
77     location = """
78
79 Alias /sp ${HTTPDIR}/sp
80
81 <Directory ${HTTPDIR}/sp>
82     Require all granted
83 </Directory>
84
85 Alias /open ${HTTPDIR}/open
86
87 <Directory ${HTTPDIR}/open>
88 </Directory>
89 """
90     index = """WORKS!"""
91     logged_out = """Logged out"""
92
93     t = Template(location)
94     text = t.substitute({'HTTPDIR': httpdir})
95     with open(httpdir + '/conf.d/ipsilon-saml.conf', 'a') as f:
96         f.write(text)
97
98     os.mkdir(httpdir + '/sp')
99     with open(httpdir + '/sp/index.html', 'w') as f:
100         f.write(index)
101     os.mkdir(httpdir + '/open')
102     with open(httpdir + '/open/logged_out.html', 'w') as f:
103         f.write(logged_out)
104
105
106 def ensure_logout(sess, idpname, url):
107     """
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.
111
112     Returns nothing or raises exception on error
113     """
114     try:
115         page = sess.fetch_page(idpname, url, follow_redirect=False)
116         if page.result.status_code != 303:
117             raise ValueError('Still logged into url')
118     except ValueError:
119         raise
120
121     return True
122
123
124 class IpsilonTest(IpsilonTestBase):
125
126     def __init__(self):
127         super(IpsilonTest, self).__init__('testlogout', __file__)
128
129     def setup_servers(self, env=None):
130         print "Installing IDP server"
131         name = 'idp1'
132         addr = '127.0.0.10'
133         port = '45080'
134         idp = self.generate_profile(idp_g, idp_a, name, addr, port)
135         conf = self.setup_idp_server(idp, name, addr, port, env)
136
137         print "Starting IDP's httpd server"
138         self.start_http_server(conf, env)
139
140         print "Installing SP server"
141         name = 'sp1'
142         addr = '127.0.0.11'
143         port = '45081'
144         sp = self.generate_profile(sp_g, sp_a, name, addr, port)
145         conf = self.setup_sp_server(sp, name, addr, port, env)
146         fixup_sp_httpd(os.path.dirname(conf))
147
148         print "Starting SP's httpd server"
149         self.start_http_server(conf, env)
150
151         print "Installing second SP server"
152         name = 'sp2'
153         addr = '127.0.0.10'
154         port = '45082'
155         sp2 = self.generate_profile(sp2_g, sp2_a, name, addr, port)
156         conf = self.setup_sp_server(sp2, name, addr, port, env)
157         fixup_sp_httpd(os.path.dirname(conf))
158
159         print "Starting SP's httpd server"
160         self.start_http_server(conf, env)
161
162
163 if __name__ == '__main__':
164
165     idpname = 'idp1'
166     spname = 'sp1'
167     sp2name = 'sp2'
168     user = pwd.getpwuid(os.getuid())[0]
169
170     sess = HttpSessions()
171     sess.add_server(idpname, 'http://127.0.0.10:45080', user, 'ipsilon')
172     sess.add_server(spname, 'http://127.0.0.11:45081')
173     sess.add_server(sp2name, 'http://127.0.0.10:45082')
174
175     print "testlogout: 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 "testlogout: Add SP Metadata to IDP ...",
184     try:
185         sess.add_sp_metadata(idpname, spname)
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     print "testlogout: Add second SP Metadata to IDP ...",
192     try:
193         sess.add_sp_metadata(idpname, sp2name)
194     except Exception, e:  # pylint: disable=broad-except
195         print >> sys.stderr, " ERROR: %s" % repr(e)
196         sys.exit(1)
197     print " SUCCESS"
198
199     print "testlogout: Logout without logging into SP ...",
200     try:
201         page = sess.fetch_page(idpname, '%s/%s?%s' % (
202             'http://127.0.0.11:45081', 'saml2/logout',
203             'ReturnTo=http://127.0.0.11:45081/open/logged_out.html'))
204         page.expected_value('text()', 'Logged out')
205     except ValueError, e:
206         print >> sys.stderr, " ERROR: %s" % repr(e)
207         sys.exit(1)
208     print " SUCCESS"
209
210     print "testlogout: Access SP Protected Area ...",
211     try:
212         page = sess.fetch_page(idpname, 'http://127.0.0.11:45081/sp/')
213         page.expected_value('text()', 'WORKS!')
214     except ValueError, e:
215         print >> sys.stderr, " ERROR: %s" % repr(e)
216         sys.exit(1)
217     print " SUCCESS"
218
219     print "testlogout: Logout from SP ...",
220     try:
221         page = sess.fetch_page(idpname, '%s/%s?%s' % (
222             'http://127.0.0.11:45081', 'saml2/logout',
223             'ReturnTo=http://127.0.0.11:45081/open/logged_out.html'))
224         page.expected_value('text()', 'Logged out')
225     except ValueError, e:
226         print >> sys.stderr, " ERROR: %s" % repr(e)
227         sys.exit(1)
228     print " SUCCESS"
229
230     print "testlogout: Try logout again ...",
231     try:
232         page = sess.fetch_page(idpname, '%s/%s?%s' % (
233             'http://127.0.0.11:45081', 'saml2/logout',
234             'ReturnTo=http://127.0.0.11:45081/open/logged_out.html'))
235         page.expected_value('text()', 'Logged out')
236     except ValueError, e:
237         print >> sys.stderr, " ERROR: %s" % repr(e)
238         sys.exit(1)
239     print " SUCCESS"
240
241     print "testlogout: Ensure logout ...",
242     try:
243         ensure_logout(sess, idpname, 'http://127.0.0.11:45081/sp/')
244     except ValueError, e:
245         print >> sys.stderr, " ERROR: %s" % repr(e)
246         sys.exit(1)
247     print " SUCCESS"
248
249     print "testlogout: Access SP Protected Area of SP1...",
250     try:
251         page = sess.fetch_page(idpname, 'http://127.0.0.11:45081/sp/')
252         page.expected_value('text()', 'WORKS!')
253     except ValueError, e:
254         print >> sys.stderr, " ERROR: %s" % repr(e)
255         sys.exit(1)
256     print " SUCCESS"
257
258     print "testlogout: Access SP Protected Area of SP2...",
259     try:
260         page = sess.fetch_page(idpname, 'http://127.0.0.10:45082/sp/')
261         page.expected_value('text()', 'WORKS!')
262     except ValueError, e:
263         print >> sys.stderr, " ERROR: %s" % repr(e)
264         sys.exit(1)
265     print " SUCCESS"
266
267     print "testlogout: Logout from both ...",
268     try:
269         page = sess.fetch_page(idpname, '%s/%s?%s' % (
270             'http://127.0.0.11:45081', 'saml2/logout',
271             'ReturnTo=http://127.0.0.11:45081/open/logged_out.html'))
272         page.expected_value('text()', 'Logged out')
273     except ValueError, e:
274         print >> sys.stderr, " ERROR: %s" % repr(e)
275         sys.exit(1)
276     print " SUCCESS"
277
278     print "testlogout: Ensure logout of SP1 ...",
279     try:
280         ensure_logout(sess, idpname, 'http://127.0.0.11:45081/sp/')
281     except ValueError, e:
282         print >> sys.stderr, " ERROR: %s" % repr(e)
283         sys.exit(1)
284     print " SUCCESS"
285
286     print "testlogout: Ensure logout of SP2 ...",
287     try:
288         ensure_logout(sess, idpname, 'http://127.0.0.10:45082/sp/')
289     except ValueError, e:
290         print >> sys.stderr, " ERROR: %s" % repr(e)
291         sys.exit(1)
292     print " SUCCESS"