Exemplo n.º 1
0
def test_invalid_cookie_cookietype():
    # This is not actually a cookie only session, but we still test the cookie part.
    options = {"session.validate_key": "hoobermas", "session.type": "cookie"}
    app = TestApp(SessionMiddleware(simple_app, **options))

    res = app.get("/")
    assert "current value is: 1" in res

    # Set an invalid cookie.
    app.set_cookie("cb_/zabbix/actionconf.php_parts", "HI")
    res = app.get("/")
    assert "current value is: 2" in res, res

    res = app.get("/")
    assert "current value is: 3" in res, res
Exemplo n.º 2
0
def test_invalid_cookie_cookietype():
    # This is not actually a cookie only session, but we still test the cookie part.
    options = {'session.validate_key':'hoobermas', 'session.type':'cookie'}
    app = TestApp(SessionMiddleware(simple_app, **options))

    res = app.get('/')
    assert 'current value is: 1' in res

    # Set an invalid cookie.
    app.set_cookie('cb_/zabbix/actionconf.php_parts', 'HI')
    res = app.get('/')
    assert 'current value is: 2' in res, res

    res = app.get('/')
    assert 'current value is: 3' in res, res
Exemplo n.º 3
0
class Saml2RequestTests(MongoTestCase):
    """Base TestCase for those tests usign saml2 that need a full environment
       setup
    """

    def setUp(self, settings={}):
        super(Saml2RequestTests, self).setUp(celery, get_attribute_manager, userdb_use_old_format=True)

        self.settings = {
            'saml2.settings_module': path.join(path.dirname(__file__),
                                               'tests/data/saml2_settings.py'),
            'saml2.login_redirect_url': '/',
            'saml2.logout_redirect_url': '/',
            'saml2.strip_saml_user_suffix': '@test',
            'auth_tk_secret': '123456',
            'testing': True,
            'jinja2.directories': 'eduiddashboard:saml2/templates',
            'jinja2.undefined': 'strict',
            'jinja2.filters': """
                route_url = pyramid_jinja2.filters:route_url_filter
                static_url = pyramid_jinja2.filters:static_url_filter
            """,
            'session.key': 'sessid',
            'session.secret': '123341234',
            'session.cookie_domain': 'localhost',
            'session.cookie_path': '/',
            'session.cookie_max_age': '3600',
            'session.cookie_httponly': True,
            'session.cookie_secure': False,
        }
        self.settings.update(settings)

        if not self.settings.get('groups_callback', None):
            self.settings['groups_callback'] = dummy_groups_callback

        self.settings['mongo_uri'] = self.mongodb_uri('')

        self.redis_instance = RedisTemporaryInstance.get_instance()
        self.settings['REDIS_HOST'] = 'localhost'
        self.settings['REDIS_PORT'] = self.redis_instance._port
        self.settings['REDIS_DB'] = '0'
        self.redis_conn = redis.Redis(host='localhost',
                port=self.redis_instance._port, db=0)

        app = saml2_main({}, **self.settings)
        self.testapp = TestApp(app)

        self.config = testing.setUp()
        self.config.registry.settings = self.settings
        self.config.registry.registerUtility(self, IDebugLogger)
        self.userdb = app.registry.settings['userdb']
        self.db = app.registry.settings['db']

    def tearDown(self):
        super(Saml2RequestTests, self).tearDown()
        for k in self.redis_conn.keys():
            self.redis_conn.delete(k)
        self.testapp.reset()

    def set_user_cookie(self, user_id):
        request = TestRequest.blank('', {})
        request.registry = self.testapp.app.registry
        remember_headers = remember(request, user_id)
        cookie_value = remember_headers[0][1].split('"')[1]
        self.testapp.set_cookie('auth_tkt', cookie_value)
        return request

    def dummy_request(self):
        request = DummyRequest()
        request.context = DummyResource()
        request.userdb = self.userdb
        request.db = self.db
        request.registry.settings = self.settings
        return request

    def get_request_with_session(self):
        queryUtility = self.testapp.app.registry.queryUtility
        session_factory = queryUtility(ISessionFactory)

        request = self.dummy_request()
        session = session_factory(request)
        session.persist()
        self.testapp.set_cookie(self.settings['session.key'], session._session.token)
        self.pol = self.config.testing_securitypolicy(
            'user', ('editors', ),
            permissive=False, remember_result=True)
        return request

    def get_fake_session_info(self, eppn=None):
        session_info = {
            'authn_info': [
                ('urn:oasis:names:tc:SAML:2.0:ac:classes:Password', [])
            ],
            'name_id': None,
            'not_on_or_after': 1371671386,
            'came_from': u'/',
            'ava': {
                'cn': ['John'],
                'objectclass': ['top', 'inetOrgPerson', 'person', 'eduPerson'],
                'userpassword': ['1234'],
                'edupersonaffiliation': ['student'],
                'sn': ['Smith'],
                'mail': ['*****@*****.**'],
                'eduPersonPrincipalName': ['hubba-bubba@test']
            },
            'issuer': 'https://idp.example.com/saml/saml2/idp/metadata.php'
        }

        if eppn is not None:
            session_info['ava']['eduPersonPrincipalName'] = eppn

        return session_info
Exemplo n.º 4
0
class LoggedInRequestTests(MongoTestCase):
    """Base TestCase for those tests that need a logged in environment setup"""

    def setUp(self, settings={}, skip_on_fail=False, std_user='******'):

        self.settings = deepcopy(SETTINGS)
        self.settings.update(settings)
        super(LoggedInRequestTests, self).setUp(celery, get_attribute_manager, userdb_use_old_format=True)

        self.redis_instance = RedisTemporaryInstance.get_instance()
        self.settings['redis_host'] = 'localhost'
        self.settings['redis_port'] = self.redis_instance._port
        self.settings['redis_db'] = '0'

        self.settings['mongo_uri'] = self.mongodb_uri('')
        try:
            app = eduiddashboard_main({}, **self.settings)
        except pymongo.errors.ConnectionFailure:
            if skip_on_fail:
                raise unittest.SkipTest("requires accessible MongoDB server on {!r}".format(
                    self.settings['mongo_uri']))
            raise

        self.testapp = TestApp(app)

        self.config = testing.setUp()
        self.config.registry.settings = self.settings
        self.config.registry.registerUtility(self, IDebugLogger)

        self.userdb = app.registry.settings['userdb']
        _userdoc = self.userdb.get_user_by_mail(std_user)
        self.assertIsNotNone(_userdoc, "Could not load the standard test user {!r} from the database {!s}".format(
            std_user, self.userdb))
        self.user = OldUser(data=_userdoc)
        self.logged_in_user = None

        #self.db = get_db(self.settings)
        self.db = app.registry.settings['mongodb'].get_database('eduid_dashboard')    # central userdb, raw mongodb
        self.userdb_new = UserDB(self.mongodb_uri(''), 'eduid_am')   # central userdb in new format (User)
        self.dashboard_db = DashboardUserDB(self.mongodb_uri('eduid_dashboard'))
        # Clean up the dashboards private database collections
        logger.debug("Dropping profiles, verifications and reset_passwords from {!s}".format(self.db))
        self.db.profiles.drop()
        self.db.verifications.drop()
        self.db.reset_passwords.drop()

        # Copy all the users from the eduid userdb into the dashboard applications userdb
        # since otherwise the out-of-sync check will trigger on every save to the dashboard
        # applications database because there is no document there with the right modified_ts
        for userdoc in self.userdb._get_all_docs():
            logger.debug("Copying user {!r}\nfrom {!r}\nto {!r}:\n{!s}".format(userdoc.get('eduPersonPrincipalName'),
                                                                               self.userdb, self.db.profiles,
                                                                               pprint.pformat(userdoc)))
            self.db.profiles.insert(userdoc)

        self.initial_verifications = (getattr(self, 'initial_verifications', None)
                                      or INITIAL_VERIFICATIONS)

        for verification_data in self.initial_verifications:
            self.db.verifications.insert(verification_data)

        logger.debug("setUp finished\n\n" + ('-=-' * 30) + "\n\n")

    def tearDown(self):
        super(LoggedInRequestTests, self).tearDown()
        logger.debug("tearDown: Dropping profiles, verifications and reset_passwords from {!s}".format(self.db))
        for userdoc in self.db.profiles.find({}):
            assert OldUser(userdoc)
        self.db.profiles.drop()
        self.db.verifications.drop()
        self.db.reset_passwords.drop()
        self.testapp.reset()

    def dummy_get_user(self, userid=''):
        return self.user

    def set_mocked_get_user(self):
        patcher = patch('eduid_userdb.dashboard.UserDBWrapper.get_user_by_eppn',
                        self.dummy_get_user)
        patcher.start()

    def dummy_request(self, cookies={}):
        request = DummyRequest()
        request.context = DummyResource()
        request.userdb = self.userdb
        request.userdb_new = self.userdb_new
        request.db = self.db
        request.registry.settings = self.settings

        def propagate_user_changes(user):
            """
            Make sure there is a request.context.propagate_user_changes in testing too.
            """
            logger.debug('FREDRIK: Testing dummy_request.context propagate_user_changes')
            return self.request.amrelay.request_sync(user)

        request.context.propagate_user_changes = propagate_user_changes

        return request

    def set_logged(self, email='*****@*****.**', extra_session_data={}):
        request = self.set_user_cookie(email)
        user_obj = self.userdb.get_user_by_mail(email, raise_on_missing=True)
        if not user_obj:
            logging.error("User {!s} not found in database {!r}. Users:".format(email, self.userdb))
            for this in self.userdb._get_all_userdocs():
                this_user = OldUser(this)
                logging.debug("  User: {!s}".format(this_user))
        # user only exists in eduid-userdb, so need to clear modified-ts to be able
        # to save it to eduid-dashboard.profiles
        user_obj.set_modified_ts(None)
        dummy = DummyRequest()
        dummy.session = {
            'eduPersonAssurance': loa(3),
            'eduPersonIdentityProofing': loa(3),
        }
        store_session_user(dummy, user_obj)
        # XXX ought to set self.user = user_obj
        self.logged_in_user = self.userdb_new.get_user_by_id(user_obj.get_id())
        dummy.session.update(extra_session_data)
        request = self.add_to_session(dummy.session)
        return request

    def set_user_cookie(self, user_id):
        request = TestRequest.blank('', {})
        request.registry = self.testapp.app.registry
        remember_headers = remember(request, user_id)
        cookie_value = remember_headers[0][1].split('"')[1]
        self.testapp.set_cookie('auth_tkt', cookie_value)
        return request

    def add_to_session(self, data):
        # Log warning since we're moving away from direct request.session access
        logger.warning('Add to session called with data: {!r}'.format(data))
        queryUtility = self.testapp.app.registry.queryUtility
        session_factory = queryUtility(ISessionFactory)
        request = self.dummy_request()
        session = session_factory(request)
        for key, value in data.items():
            session[key] = value
        session.persist()
        self.testapp.set_cookie(self.settings['session.key'], session._session.token)
        return request

    def check_values(self, fields, values, ignore_not_found=[]):
        for field in fields:
            if field.attrs['type'] == 'checkbox':
                # A webtest.app.Checkbox only has a value if it is checked (!)
                old_status = field.checked
                field.checked = True
                if field.value in values:
                    logger.debug("Checked checkbox {!r} (value {!r})".format(field.id, field.value))
                    values.remove(field.value)
                else:
                    # restore the checkbox whose value was not found in values
                    field.checked = False
        values = [x for x in values if x not in ignore_not_found]
        self.assertEqual(values, [], "Failed checking one or more checkboxes: {!r}".format(values))

    def values_are_checked(self, fields, values):
        checked = [f.value for f in fields if f.value is not None]

        self.assertEqual(values, checked)

    def sync_user_from_dashboard_to_userdb(self, user_id, old_format = True):
        """
        When there is no eduid-dashboard-amp Attribute Manager plugin loaded to
        sync users from dashboard to userdb, this crude function can do it.

        :param user_id: User id
        :param old_format: Write in old format to userdb

        :type user_id: ObjectId
        :type old_format: bool
        :return:
        """
        user = self.dashboard_db.get_user_by_id(user_id)
        logger.debug('Syncing user {!s} from dashboard to userdb'.format(user))
        test_doc = {'_id': user_id}
        user_doc = user.to_dict(old_userdb_format=old_format)
        # Fixups to turn the DashboardUser into a User
        del user_doc['terminated']
        self.userdb_new._coll.update(test_doc, user_doc, upsert=False)
Exemplo n.º 5
0
class TestCookie(unittest.TestCase):
    """Tests API functions associated with VM actions.
       Note that all tests are in-process, we don't actually start a http server.
    """
    def setUp(self):
        """Launch pserve using webtest with test settings"""
        self.appconf = get_app(test_ini)
        self.app = TestApp(self.appconf)

        # Punch in new administrator account with direct server call

        server.choose_engine("SQLite")  # Sets global var "engine" - in the
                                        # case of SQLite this is a fresh RAM
                                        # DB each time.

        # Create new user. This will implicitly generate the tables.
        id1 = server.create_user(None, "testuser", "testuser", "testuser")
        server.touch_to_add_user_group("testuser", "users")
        server.touch_to_add_password(id1, "testpass")

        id2 = server.create_user(None, "administrator", "administrator", "administrator")
        server.touch_to_add_user_group("administrator", "administrators")
        server.touch_to_add_password(id2, "adminpass")

    """Confirm lack of any cookie without authentication."""
    def test_no_cookie_without_auth(self):
        """ No cookie should be set when calling an endpoint that
            does not require authorization.
        """
        self.app.authorization = None
        r = self.app.get("/", status=200)

        self.assertEqual(r.headers.get('Set-Cookie', 'empty'), 'empty')

        #Equivalently:
        self.assertEqual(self.app.cookies, {})

    def test_no_username(self):
        """ The DB API should return a 401 unauthorised if I submit a request
            with no username / password provided.
            Similar to test_unauthenticated_api but with an extra check that no
            cookie is set.
        """
        self.app.authorization = None
        r = self.app.get("/users/testuser", status=401)

        self.assertEqual(r.headers.get('Set-Cookie', 'empty'), 'empty')


    def test_invalid_username(self):
        """ The DB API should return a 401 unauthorised if I submit a bad
            username / password combination.  And again no cookie
        """
        self.app.authorization = ('Basic', ('invaliduser', 'invalidpassword'))

        r = self.app.get("/users/testuser", status=401)
        self.assertEqual(r.headers.get('Set-Cookie', 'empty'), 'empty')

    def test_valid_cookie(self):
        """Confirm cookie returned upon authentication.
        The DB API should return a cookie if I submit a correct username
        and password. The cookie should allow me to make a successful request
        using it alone. """

        self.app.authorization = ('Basic', ('testuser', 'testpass'))
        r = self.app.get("/users/testuser", status=200)
        cookie = self.app.cookies['auth_tkt']

        self.app.reset()                         # clear cookie cache
        self.app.authorization = None            # remove auth credentials
        self.app.set_cookie("auth_tkt", cookie)  # set cookie to old value

        r = self.app.get("/users/testuser", status=200)

        #Furthermore, we should still get the same cookie on the second call
        self.assertEqual(self.app.cookies['auth_tkt'], cookie)

    def test_broken_cookie(self):
        """ The DB API should refuse to service a request with a broken cookie. """

        self.app.authorization = ('Basic', ('testuser', 'testpass'))
        r = self.app.get("/users/testuser", status=200)
        cookie = 'I am a fish'

        self.app.reset()                         # clear cookie cache
        self.app.authorization = None            # remove auth credentials
        self.app.set_cookie("auth_tkt", cookie)  # set cookie to bad value
        r = self.app.get("/users/testuser", status=401, expect_errors=False)

    def test_invalid_cookie(self):
        """ The DB API should refuse to service a request with an invalid cookie. """

        self.app.authorization = ('Basic', ('testuser', 'testpass'))
        r = self.app.get("/users/testuser", status=200)
        cookie = '94514a32a7923939584470e8fc01f9b073bc3c8171542c8b7deb0' + \
                 'dd459400945553f9ed9dGVzdHVzZXI%3D!userid_type:b64unicode'

        self.app.reset()                         # clear cookie cache
        self.app.authorization = None            # remove auth credentials
        self.app.set_cookie("auth_tkt", cookie)  # set cookie to bad value
        r = self.app.get("/users/testuser", status=401, expect_errors=False)

    def test_valid_authtkt(self):
        """Setting a cookie in the request is problematic for AJAX, so
           test that we can feed the token back in the auth_tkt header instead.
        """

        self.app.authorization = ('Basic', ('testuser', 'testpass'))
        r = self.app.get("/users/testuser", status=200)
        cookie = self.app.cookies['auth_tkt']

        self.app.reset()                         # clear cookie cache
        self.app.authorization = None            # remove auth credentials

        r = self.app.get("/users/testuser",
                         headers={'auth_tkt': cookie},
                         status=200)

        #Furthermore, we should still get the same cookie on the second call
        self.assertEqual(self.app.cookies['auth_tkt'], cookie)

    def test_broken_cookie(self):
        """ The DB API should refuse to service a request with a broken auth_tkt.
            And should return a 408 error (I think - we don't want a 401 as it causes the
            browser to prompt for a username/password which will then be remembered for
            basic auth)
        """

        self.app.authorization = ('Basic', ('testuser', 'testpass'))
        r = self.app.get("/users/testuser", status=200)
        cookie = 'I am a fish'

        self.app.reset()                         # clear cookie cache
        self.app.authorization = None            # remove auth credentials

        r = self.app.get("/users/testuser",
                         headers={'auth_tkt': cookie},
                         status=408,
                         expect_errors=False)
Exemplo n.º 6
0
class LoggedInRequestTests(MongoTestCase):
    """Base TestCase for those tests that need a logged in environment setup"""
    def setUp(self,
              settings={},
              skip_on_fail=False,
              std_user='******'):

        self.settings = deepcopy(SETTINGS)
        self.settings.update(settings)
        super(LoggedInRequestTests, self).setUp(celery,
                                                get_attribute_manager,
                                                userdb_use_old_format=True)

        self.redis_instance = RedisTemporaryInstance.get_instance()
        self.settings['redis_host'] = 'localhost'
        self.settings['redis_port'] = self.redis_instance._port
        self.settings['redis_db'] = '0'

        self.settings['mongo_uri'] = self.mongodb_uri('')
        try:
            app = eduiddashboard_main({}, **self.settings)
        except pymongo.errors.ConnectionFailure:
            if skip_on_fail:
                raise unittest.SkipTest(
                    "requires accessible MongoDB server on {!r}".format(
                        self.settings['mongo_uri']))
            raise

        self.testapp = TestApp(app)

        self.config = testing.setUp()
        self.config.registry.settings = self.settings
        self.config.registry.registerUtility(self, IDebugLogger)

        #self.db = get_db(self.settings)
        self.db = app.registry.settings['mongodb'].get_database(
            'eduid_dashboard')  # central userdb, raw mongodb
        self.userdb_new = UserDB(
            self.mongodb_uri(''),
            'eduid_am')  # central userdb in new format (User)
        self.dashboard_db = DashboardUserDB(
            self.mongodb_uri('eduid_dashboard'))
        # Clean up the dashboards private database collections
        logger.debug(
            "Dropping profiles, verifications and reset_passwords from {!s}".
            format(self.db))
        self.db.profiles.drop()
        self.db.verifications.drop()
        self.db.reset_passwords.drop()

        self.user = self.userdb_new.get_user_by_mail(std_user)
        self.assertIsNotNone(
            self.user,
            "Could not load the standard test user {!r} from the database {!s}"
            .format(std_user, self.userdb_new))
        self.logged_in_user = None

        # Copy all the users from the eduid userdb into the dashboard applications userdb
        # since otherwise the out-of-sync check will trigger on every save to the dashboard
        # applications database because there is no document there with the right modified_ts
        for userdoc in self.userdb_new._get_all_docs():
            logger.debug("COPYING USER INTO PROFILES:\n{!s}".format(userdoc))
            self.db.profiles.insert(userdoc)

        self.initial_verifications = (getattr(self, 'initial_verifications',
                                              None) or INITIAL_VERIFICATIONS)

        for verification_data in self.initial_verifications:
            self.db.verifications.insert(verification_data)

        logger.debug("setUp finished\n\n" + ('-=-' * 30) + "\n\n")

    def tearDown(self):
        super(LoggedInRequestTests, self).tearDown()
        logger.debug(
            "tearDown: Dropping profiles, verifications and reset_passwords from {!s}"
            .format(self.db))
        for userdoc in self.db.profiles.find({}):
            assert DashboardUser(data=userdoc)
        self.db.profiles.drop()
        self.db.verifications.drop()
        self.db.reset_passwords.drop()
        self.testapp.reset()

    def dummy_get_user(self, userid=''):
        return self.user

    def set_mocked_get_user(self):
        patcher = patch(
            'eduid_userdb.dashboard.UserDBWrapper.get_user_by_eppn',
            self.dummy_get_user)
        patcher.start()

    def dummy_request(self, cookies={}):
        request = DummyRequest()
        request.context = DummyResource()
        request.context.request = request
        request.userdb_new = self.userdb_new
        request.db = self.db
        request.dashboard_userdb = self.dashboard_db
        request.registry.settings = self.settings

        def propagate_user_changes(user):
            """
            Make sure there is a request.context.propagate_user_changes in testing too.
            """
            logger.debug(
                'FREDRIK: Testing dummy_request.context propagate_user_changes'
            )
            return self.request.amrelay.request_sync(user)

        request.context.propagate_user_changes = propagate_user_changes

        return request

    def set_logged(self, email='*****@*****.**', extra_session_data={}):
        request = self.set_user_cookie(email)
        user_obj = self.userdb_new.get_user_by_mail(email,
                                                    raise_on_missing=True)
        if not user_obj:
            logging.error(
                "User {!s} not found in database {!r}. Users:".format(
                    email, self.userdb))
            for this in self.userdb_new._get_all_userdocs():
                this_user = DashboardUser(this)
                logging.debug("  User: {!s}".format(this_user))
        # user only exists in eduid-userdb, so need to clear modified-ts to be able
        # to save it to eduid-dashboard.profiles
        user_obj.modified_ts = None
        dummy = DummyRequest()
        dummy.session = {
            'eduPersonAssurance': loa(3),
            'eduPersonIdentityProofing': loa(3),
            'eduPersonPrincipalName': 'hubba-bubba',
            'user_eppn': 'hubba-bubba',
        }
        store_session_user(dummy, user_obj)
        # XXX ought to set self.user = user_obj
        self.logged_in_user = self.userdb_new.get_user_by_id(user_obj.user_id)
        dummy.session.update(extra_session_data)
        request = self.add_to_session(dummy.session)
        return request

    def set_user_cookie(self, user_id):
        request = TestRequest.blank('', {})
        request.registry = self.testapp.app.registry
        remember_headers = remember(request, user_id)
        cookie_value = remember_headers[0][1].split('"')[1]
        self.testapp.set_cookie('auth_tkt', cookie_value)
        return request

    def add_to_session(self, data):
        # Log warning since we're moving away from direct request.session access
        logger.warning('Add to session called with data: {!r}'.format(data))
        queryUtility = self.testapp.app.registry.queryUtility
        session_factory = queryUtility(ISessionFactory)
        request = self.dummy_request()
        session = session_factory(request)
        for key, value in data.items():
            session[key] = value
        session.persist()
        self.testapp.set_cookie(self.settings['session.key'],
                                session._session.token)
        return request

    def check_values(self, fields, values, ignore_not_found=[]):
        for field in fields:
            if field.attrs['type'] == 'checkbox':
                # A webtest.app.Checkbox only has a value if it is checked (!)
                field.checked = True
                if field.value in values:
                    logger.debug("Checked checkbox {!r} (value {!r})".format(
                        field.id, field.value))
                    values.remove(field.value)
                else:
                    # restore the checkbox whose value was not found in values
                    field.checked = False
        values = [x for x in values if x not in ignore_not_found]
        self.assertEqual(
            values, [],
            "Failed checking one or more checkboxes: {!r}".format(values))

    def values_are_checked(self, fields, values):
        checked = [f.value for f in fields if f.value is not None]

        self.assertEqual(values, checked)

    def sync_user_from_dashboard_to_userdb(self, user_id, old_format=False):
        """
        When there is no eduid-dashboard-amp Attribute Manager plugin loaded to
        sync users from dashboard to userdb, this crude function can do it.

        :param user_id: User id
        :param old_format: Write in old format to userdb

        :type user_id: ObjectId
        :type old_format: bool
        :return:
        """
        user = self.dashboard_db.get_user_by_id(user_id)
        logger.debug('Syncing user {!s} from dashboard to userdb'.format(user))
        test_doc = {'_id': user_id}
        user_doc = user.to_dict(old_userdb_format=old_format)
        # Fixups to turn the DashboardUser into a User
        user_doc['terminated'] = True
        self.userdb_new._coll.update(test_doc, user_doc, upsert=False)
Exemplo n.º 7
0
class TestCookie(unittest.TestCase):
    """Tests API functions associated with VM actions.
       Note that all tests are in-process, we don't actually start a http server.
    """
    def setUp(self):
        """Launch pserve using webtest with test settings"""
        self.appconf = get_app(test_ini)
        self.app = TestApp(self.appconf)

        # Punch in new administrator account with direct server call

        server.choose_engine("SQLite")  # Sets global var "engine" - in the
        # case of SQLite this is a fresh RAM
        # DB each time.

        # Create new user. This will implicitly generate the tables.
        id1 = server.create_user(None, "testuser", "testuser", "testuser")
        server.touch_to_add_user_group("testuser", "users")
        server.touch_to_add_password(id1, "testpass")

        id2 = server.create_user(None, "administrator", "administrator",
                                 "administrator")
        server.touch_to_add_user_group("administrator", "administrators")
        server.touch_to_add_password(id2, "adminpass")

    """Confirm lack of any cookie without authentication."""

    def test_no_cookie_without_auth(self):
        """ No cookie should be set when calling an endpoint that
            does not require authorization.
        """
        self.app.authorization = None
        r = self.app.get("/", status=200)

        self.assertEqual(r.headers.get('Set-Cookie', 'empty'), 'empty')

        #Equivalently:
        self.assertEqual(self.app.cookies, {})

    def test_no_username(self):
        """ The DB API should return a 401 unauthorised if I submit a request
            with no username / password provided.
            Similar to test_unauthenticated_api but with an extra check that no
            cookie is set.
        """
        self.app.authorization = None
        r = self.app.get("/users/testuser", status=401)

        self.assertEqual(r.headers.get('Set-Cookie', 'empty'), 'empty')

    def test_invalid_username(self):
        """ The DB API should return a 401 unauthorised if I submit a bad
            username / password combination.  And again no cookie
        """
        self.app.authorization = ('Basic', ('invaliduser', 'invalidpassword'))

        r = self.app.get("/users/testuser", status=401)
        self.assertEqual(r.headers.get('Set-Cookie', 'empty'), 'empty')

    def test_valid_cookie(self):
        """Confirm cookie returned upon authentication.
        The DB API should return a cookie if I submit a correct username
        and password. The cookie should allow me to make a successful request
        using it alone. """

        self.app.authorization = ('Basic', ('testuser', 'testpass'))
        r = self.app.get("/users/testuser", status=200)
        cookie = self.app.cookies['auth_tkt']

        self.app.reset()  # clear cookie cache
        self.app.authorization = None  # remove auth credentials
        self.app.set_cookie("auth_tkt", cookie)  # set cookie to old value

        r = self.app.get("/users/testuser", status=200)

        #Furthermore, we should still get the same cookie on the second call
        self.assertEqual(self.app.cookies['auth_tkt'], cookie)

    def test_broken_cookie(self):
        """ The DB API should refuse to service a request with a broken cookie. """

        self.app.authorization = ('Basic', ('testuser', 'testpass'))
        r = self.app.get("/users/testuser", status=200)
        cookie = 'I am a fish'

        self.app.reset()  # clear cookie cache
        self.app.authorization = None  # remove auth credentials
        self.app.set_cookie("auth_tkt", cookie)  # set cookie to bad value
        r = self.app.get("/users/testuser", status=401, expect_errors=False)

    def test_invalid_cookie(self):
        """ The DB API should refuse to service a request with an invalid cookie. """

        self.app.authorization = ('Basic', ('testuser', 'testpass'))
        r = self.app.get("/users/testuser", status=200)
        cookie = '94514a32a7923939584470e8fc01f9b073bc3c8171542c8b7deb0' + \
                 'dd459400945553f9ed9dGVzdHVzZXI%3D!userid_type:b64unicode'

        self.app.reset()  # clear cookie cache
        self.app.authorization = None  # remove auth credentials
        self.app.set_cookie("auth_tkt", cookie)  # set cookie to bad value
        r = self.app.get("/users/testuser", status=401, expect_errors=False)

    def test_valid_authtkt(self):
        """Setting a cookie in the request is problematic for AJAX, so
           test that we can feed the token back in the auth_tkt header instead.
        """

        self.app.authorization = ('Basic', ('testuser', 'testpass'))
        r = self.app.get("/users/testuser", status=200)
        cookie = self.app.cookies['auth_tkt']

        self.app.reset()  # clear cookie cache
        self.app.authorization = None  # remove auth credentials

        r = self.app.get("/users/testuser",
                         headers={'auth_tkt': cookie},
                         status=200)

        #Furthermore, we should still get the same cookie on the second call
        self.assertEqual(self.app.cookies['auth_tkt'], cookie)

    def test_broken_cookie(self):
        """ The DB API should refuse to service a request with a broken auth_tkt.
            And should return a 408 error (I think - we don't want a 401 as it causes the
            browser to prompt for a username/password which will then be remembered for
            basic auth)
        """

        self.app.authorization = ('Basic', ('testuser', 'testpass'))
        r = self.app.get("/users/testuser", status=200)
        cookie = 'I am a fish'

        self.app.reset()  # clear cookie cache
        self.app.authorization = None  # remove auth credentials

        r = self.app.get("/users/testuser",
                         headers={'auth_tkt': cookie},
                         status=408,
                         expect_errors=False)