def setUp(self):
     """Register a new permission and a fake store selector."""
     zope.testing.cleanup.cleanUp()
     super(TestCheckPermissionCaching, self).setUp()
     self.factory = ObjectFactory()
     provideUtility(FakeStoreSelector, IStoreSelector)
     self.addCleanup(zope.testing.cleanup.cleanUp)
class TestWorkerProtocol(TestCaseInTempDir, PullerWorkerMixin):
    """Tests for the client-side implementation of the protocol used to
    communicate to the master process.
    """

    def setUp(self):
        TestCaseInTempDir.setUp(self)
        self.output = StringIO()
        self.protocol = PullerWorkerProtocol(self.output)
        self.factory = ObjectFactory()

    def assertSentNetstrings(self, expected_netstrings):
        """Assert that the protocol sent the given netstrings (in order)."""
        observed_netstrings = get_netstrings(self.output.getvalue())
        self.assertEqual(expected_netstrings, observed_netstrings)

    def resetBuffers(self):
        # Empty the test output and error buffers.
        self.output.truncate(0)
        self.assertEqual('', self.output.getvalue())

    def test_nothingSentOnConstruction(self):
        # The protocol sends nothing until it receives an event.
        self.branch_to_mirror = self.makePullerWorker(protocol=self.protocol)
        self.assertSentNetstrings([])

    def test_startMirror(self):
        # Calling startMirroring sends 'startMirroring' as a netstring.
        self.protocol.startMirroring()
        self.assertSentNetstrings(['startMirroring', '0'])

    def test_branchChanged(self):
        # Calling 'branchChanged' sends the arguments.
        arbitrary_args = [self.factory.getUniqueString() for x in range(6)]
        self.protocol.startMirroring()
        self.resetBuffers()
        self.protocol.branchChanged(*arbitrary_args)
        self.assertSentNetstrings(['branchChanged', '6'] + arbitrary_args)

    def test_mirrorFailed(self):
        # Calling 'mirrorFailed' sends the error message.
        self.protocol.startMirroring()
        self.resetBuffers()
        self.protocol.mirrorFailed('Error Message', 'OOPS')
        self.assertSentNetstrings(
            ['mirrorFailed', '2', 'Error Message', 'OOPS'])

    def test_progressMade(self):
        # Calling 'progressMade' sends an arbitrary string indicating
        # progress.
        self.protocol.progressMade('test')
        self.assertSentNetstrings(['progressMade', '0'])

    def test_log(self):
        # Calling 'log' sends 'log' as a netstring and its arguments, after
        # formatting as a string.
        self.protocol.log('logged %s', 'message')
        self.assertSentNetstrings(['log', '1', 'logged message'])
Example #3
0
class TestWorkerProtocol(TestCaseInTempDir, PullerWorkerMixin):
    """Tests for the client-side implementation of the protocol used to
    communicate to the master process.
    """
    def setUp(self):
        TestCaseInTempDir.setUp(self)
        self.output = StringIO()
        self.protocol = PullerWorkerProtocol(self.output)
        self.factory = ObjectFactory()

    def assertSentNetstrings(self, expected_netstrings):
        """Assert that the protocol sent the given netstrings (in order)."""
        observed_netstrings = get_netstrings(self.output.getvalue())
        self.assertEqual(expected_netstrings, observed_netstrings)

    def resetBuffers(self):
        # Empty the test output and error buffers.
        self.output.truncate(0)
        self.assertEqual('', self.output.getvalue())

    def test_nothingSentOnConstruction(self):
        # The protocol sends nothing until it receives an event.
        self.branch_to_mirror = self.makePullerWorker(protocol=self.protocol)
        self.assertSentNetstrings([])

    def test_startMirror(self):
        # Calling startMirroring sends 'startMirroring' as a netstring.
        self.protocol.startMirroring()
        self.assertSentNetstrings(['startMirroring', '0'])

    def test_branchChanged(self):
        # Calling 'branchChanged' sends the arguments.
        arbitrary_args = [self.factory.getUniqueString() for x in range(6)]
        self.protocol.startMirroring()
        self.resetBuffers()
        self.protocol.branchChanged(*arbitrary_args)
        self.assertSentNetstrings(['branchChanged', '6'] + arbitrary_args)

    def test_mirrorFailed(self):
        # Calling 'mirrorFailed' sends the error message.
        self.protocol.startMirroring()
        self.resetBuffers()
        self.protocol.mirrorFailed('Error Message', 'OOPS')
        self.assertSentNetstrings(
            ['mirrorFailed', '2', 'Error Message', 'OOPS'])

    def test_progressMade(self):
        # Calling 'progressMade' sends an arbitrary string indicating
        # progress.
        self.protocol.progressMade('test')
        self.assertSentNetstrings(['progressMade', '0'])

    def test_log(self):
        # Calling 'log' sends 'log' as a netstring and its arguments, after
        # formatting as a string.
        self.protocol.log('logged %s', 'message')
        self.assertSentNetstrings(['log', '1', 'logged message'])
 def setUp(self):
     TestCaseInTempDir.setUp(self)
     self.output = StringIO()
     self.protocol = PullerWorkerProtocol(self.output)
     self.factory = ObjectFactory()
class TestCheckPermissionCaching(TestCase):
    """Test the caching done by `LaunchpadSecurityPolicy.checkPermission`."""

    def setUp(self):
        """Register a new permission and a fake store selector."""
        zope.testing.cleanup.cleanUp()
        super(TestCheckPermissionCaching, self).setUp()
        self.factory = ObjectFactory()
        provideUtility(FakeStoreSelector, IStoreSelector)
        self.addCleanup(zope.testing.cleanup.cleanUp)

    def makeRequest(self):
        """Construct an arbitrary `LaunchpadBrowserRequest` object."""
        data = StringIO.StringIO()
        env = {}
        return LaunchpadBrowserRequest(data, env)

    def getObjectPermissionAndCheckerFactory(self):
        """Return an object, a permission and a `CheckerFactory` for them.

        :return: A tuple ``(obj, permission, checker_factory)``, such that
            ``queryAdapter(obj, IAuthorization, permission)`` will return a
            `Checker` created by ``checker_factory``.
        """
        permission = self.factory.getUniqueString()
        provideUtility(
            PermissionAccessLevel(), ILaunchpadPermission, permission)
        checker_factory = CheckerFactory()
        provideAdapter(
            checker_factory, [Object], IAuthorization, name=permission)
        return Object(), permission, checker_factory

    def test_checkPermission_cache_unauthenticated(self):
        # checkPermission caches the result of checkUnauthenticated for a
        # particular object and permission.
        request = self.makeRequest()
        policy = LaunchpadSecurityPolicy(request)
        obj, permission, checker_factory = (
            self.getObjectPermissionAndCheckerFactory())
        # When we call checkPermission for the first time, the security policy
        # calls the checker.
        policy.checkPermission(permission, obj)
        self.assertEqual(
            ['checkUnauthenticated'], checker_factory.calls)
        # A subsequent identical call does not call the checker.
        policy.checkPermission(permission, obj)
        self.assertEqual(
            ['checkUnauthenticated'], checker_factory.calls)

    def test_checkPermission_delegated_cache_unauthenticated(self):
        # checkPermission caches the result of checkUnauthenticated for a
        # particular object and permission, even if that object's
        # authorization has been delegated.
        request = self.makeRequest()
        policy = LaunchpadSecurityPolicy(request)
        # Delegate auth for Object to AnotherObject{One,Two}.
        permission = self.factory.getUniqueString()
        self.useFixture(
            ZopeAdapterFixture(Delegate, [Object], name=permission))
        # Allow auth to AnotherObjectOne.
        self.useFixture(
            ZopeAdapterFixture(
                Allow, [AnotherObjectOne], name=Delegate.permission))
        # Deny auth to AnotherObjectTwo.
        self.useFixture(
            ZopeAdapterFixture(
                Deny, [AnotherObjectTwo], name=Delegate.permission))
        # Calling checkPermission() populates the participation cache.
        objecttoauthorize = Object()
        policy.checkPermission(permission, objecttoauthorize)
        # It contains results for objecttoauthorize and the two objects that
        # its authorization was delegated to.
        cache = request.annotations[LAUNCHPAD_SECURITY_POLICY_CACHE_KEY]
        cache_expected = {
            objecttoauthorize: {permission: False},
            Delegate.object_one: {Delegate.permission: True},
            Delegate.object_two: {Delegate.permission: False},
            }
        self.assertEqual(cache_expected, dict(cache))

    def test_checkPermission_cache_authenticated(self):
        # checkPermission caches the result of checkAuthenticated for a
        # particular object and permission.
        principal = FakeLaunchpadPrincipal()
        request = self.makeRequest()
        request.setPrincipal(principal)
        policy = LaunchpadSecurityPolicy(request)
        obj, permission, checker_factory = (
            self.getObjectPermissionAndCheckerFactory())
        # When we call checkPermission for the first time, the security policy
        # calls the checker.
        policy.checkPermission(permission, obj)
        self.assertEqual(
            [('checkAuthenticated', principal.person)],
            checker_factory.calls)
        # A subsequent identical call does not call the checker.
        policy.checkPermission(permission, obj)
        self.assertEqual(
            [('checkAuthenticated', principal.person)],
            checker_factory.calls)

    def test_checkPermission_clearSecurityPolicyCache_resets_cache(self):
        # Calling clearSecurityPolicyCache on the request clears the cache.
        request = self.makeRequest()
        policy = LaunchpadSecurityPolicy(request)
        obj, permission, checker_factory = (
            self.getObjectPermissionAndCheckerFactory())
        # When we call checkPermission for the first time, the security policy
        # calls checkUnauthenticated on the checker.
        policy.checkPermission(permission, obj)
        self.assertEqual(
            ['checkUnauthenticated'], checker_factory.calls)
        request.clearSecurityPolicyCache()
        # After clearing the cache the policy calls checkUnauthenticated
        # again.
        policy.checkPermission(permission, obj)
        self.assertEqual(
            ['checkUnauthenticated', 'checkUnauthenticated'],
            checker_factory.calls)

    def test_checkPermission_setPrincipal_resets_cache(self):
        # Setting the principal on the request clears the cache of results
        # (this is important during login).
        principal = FakeLaunchpadPrincipal()
        request = self.makeRequest()
        policy = LaunchpadSecurityPolicy(request)
        obj, permission, checker_factory = (
            self.getObjectPermissionAndCheckerFactory())
        # When we call checkPermission before setting the principal, the
        # security policy calls checkUnauthenticated on the checker.
        policy.checkPermission(permission, obj)
        self.assertEqual(
            ['checkUnauthenticated'], checker_factory.calls)
        request.setPrincipal(principal)
        # After setting the principal, the policy calls checkAuthenticated
        # rather than finding a value in the cache.
        policy.checkPermission(permission, obj)
        self.assertEqual(
            ['checkUnauthenticated', ('checkAuthenticated',
                                      principal.person)],
            checker_factory.calls)

    def test_checkPermission_commit_clears_cache(self):
        # Committing a transaction clears the cache.
        request = self.makeRequest()
        policy = LaunchpadSecurityPolicy(request)
        obj, permission, checker_factory = (
            self.getObjectPermissionAndCheckerFactory())
        # When we call checkPermission before setting the principal, the
        # security policy calls checkUnauthenticated on the checker.
        policy.checkPermission(permission, obj)
        self.assertEqual(
            ['checkUnauthenticated'], checker_factory.calls)
        transaction.commit()
        # After committing a transaction, the policy calls
        # checkUnauthenticated again rather than finding a value in the cache.
        policy.checkPermission(permission, obj)
        self.assertEqual(
            ['checkUnauthenticated', 'checkUnauthenticated'],
            checker_factory.calls)
Example #6
0
 def setUp(self):
     super(TestSwiftFixture, self).setUp()
     self.swift_fixture = SwiftFixture()
     self.useFixture(self.swift_fixture)
     self.factory = ObjectFactory()
Example #7
0
class TestSwiftFixture(TestCase):
    layer = BaseLayer

    def setUp(self):
        super(TestSwiftFixture, self).setUp()
        self.swift_fixture = SwiftFixture()
        self.useFixture(self.swift_fixture)
        self.factory = ObjectFactory()

    def makeSampleObject(self, client, contents, content_type=None):
        """Create a new container and a new sample object within it."""
        cname = self.factory.getUniqueString()
        oname = self.factory.getUniqueString()
        client.put_container(cname)
        client.put_object(cname, oname, contents, content_type=content_type)
        return cname, oname

    def test_get(self):
        client = self.swift_fixture.connect()
        size = 30
        headers, body = client.get_object("size", str(size))
        self.assertEqual("0" * size, body)
        self.assertEqual(str(size), headers["content-length"])
        self.assertEqual("text/plain", headers["content-type"])

    def test_get_404(self):
        client = self.swift_fixture.connect()
        cname = self.factory.getUniqueString()
        client.put_container(cname)
        exc = self.assertRaises(swiftclient.ClientException, client.get_object,
                                cname, "nonexistent")
        self.assertEqual(404, exc.http_status)

    def test_get_403(self):
        client = self.swift_fixture.connect(key="bad key")
        exc = self.assertRaises(swiftclient.ClientException,
                                client.get_container, "size")
        # swiftclient should possibly set exc.http_status here, but doesn't.
        self.assertEqual(
            'Authorization Failure. '
            'Authorization Failed: Forbidden (HTTP 403)', exc.message)

    def test_put(self):
        client = self.swift_fixture.connect()
        message = "Hello World!"
        cname, oname = self.makeSampleObject(client, message, "text/something")
        for x in range(1, 10):
            headers, body = client.get_object(cname, oname)
            self.assertEqual(message * x, body)
            self.assertEqual(str(len(message) * x), headers["content-length"])
            self.assertEqual("text/something", headers["content-type"])
            client.put_object(cname,
                              oname,
                              message * (x + 1),
                              content_type="text/something")

    def test_get_container(self):
        # Basic container listing.
        start = datetime.utcnow().replace(microsecond=0)
        client = self.swift_fixture.connect()
        message = "42"
        cname, oname = self.makeSampleObject(client, message, "text/something")
        client.put_object(cname, oname + ".2", message)

        _, container = client.get_container(cname)
        self.assertEqual(2, len(container))
        obj = container[0]
        self.assertEqual(oname, obj["name"])
        self.assertEqual(len(message), obj["bytes"])
        self.assertEqual(md5(message).hexdigest(), obj["hash"])
        self.assertEqual("text/something", obj["content-type"])
        last_modified = datetime.strptime(obj["last_modified"],
                                          "%Y-%m-%dT%H:%M:%S.%f")  # ISO format
        self.assertThat(last_modified, Not(LessThan(start)))
        self.assertThat(last_modified, Not(GreaterThan(datetime.utcnow())))

    def test_get_container_marker(self):
        # Container listing supports the marker parameter.
        client = self.swift_fixture.connect()
        message = "Hello"
        cname, oname = self.makeSampleObject(client, message, "text/something")
        oname2 = oname + ".2"
        oname3 = oname + ".3"
        client.put_object(cname, oname2, message)
        client.put_object(cname, oname3, message)

        # List contents found after name == marker.
        _, container = client.get_container(cname, marker=oname)
        self.assertEqual(2, len(container))
        self.assertEqual(oname2, container[0]["name"])
        self.assertEqual(oname3, container[1]["name"])

    def test_get_container_end_marker(self):
        # Container listing supports the end_marker parameter.
        client = self.swift_fixture.connect()
        message = "Hello"
        cname, oname = self.makeSampleObject(client, message, "text/something")
        oname2 = oname + ".2"
        oname3 = oname + ".3"
        client.put_object(cname, oname2, message)
        client.put_object(cname, oname3, message)

        # List contents found before name == end_marker.
        _, container = client.get_container(cname, end_marker=oname3)
        self.assertEqual(2, len(container))
        self.assertEqual(oname, container[0]["name"])
        self.assertEqual(oname2, container[1]["name"])

    def test_get_container_limit(self):
        # Container listing supports the limit parameter.
        client = self.swift_fixture.connect()
        message = "Hello"
        cname, oname = self.makeSampleObject(client, message, "text/something")
        oname2 = oname + ".2"
        oname3 = oname + ".3"
        client.put_object(cname, oname2, message)
        client.put_object(cname, oname3, message)

        # Limit list to two objects.
        _, container = client.get_container(cname, limit=2)
        self.assertEqual(2, len(container))
        self.assertEqual(oname, container[0]["name"])
        self.assertEqual(oname2, container[1]["name"])

    def test_get_container_prefix(self):
        client = self.swift_fixture.connect()
        message = "Hello"
        cname, oname = self.makeSampleObject(client, message, "text/something")
        oname2 = "different"
        oname3 = oname + ".3"
        client.put_object(cname, oname2, message)
        client.put_object(cname, oname3, message)

        # List contents whose object names start with prefix.
        _, container = client.get_container(cname, prefix=oname)
        self.assertEqual(2, len(container))
        self.assertEqual(oname, container[0]["name"])
        self.assertEqual(oname3, container[1]["name"])

    def test_get_container_full_listing(self):
        client = self.swift_fixture.connect()
        message = "42"
        cname, oname = self.makeSampleObject(client, message, "text/something")

        _, container = client.get_container(cname, full_listing=True)
        self.assertEqual(1, len(container))

    def test_shutdown_and_startup(self):
        # This test demonstrates how the Swift client deals with a
        # flapping Swift server. In particular, that once a connection
        # has started failing it will continue failing so we need to
        # ensure that once we encounter a fail we open a fresh
        # connection. This is probably a property of our mock Swift
        # server rather than reality but the mock is a required target.
        size = 30

        # With no Swift server, a fresh connection fails with
        # a swiftclient.ClientException when it fails to
        # authenticate.
        self.swift_fixture.shutdown()
        client = self.swift_fixture.connect()
        self.assertRaises(swiftclient.ClientException, client.get_object,
                          "size", str(size))

        # Things work fine when the Swift server is up.
        self.swift_fixture.startup()
        headers, body = client.get_object("size", str(size))
        self.assertEqual(body, "0" * size)

        # But if the Swift server goes away again, we end up with
        # different failures since the connection has already
        # authenticated.
        self.swift_fixture.shutdown()
        self.assertRaises(ConnectionError, client.get_object, "size",
                          str(size))

        # And even if we bring it back up, existing connections
        # continue to fail
        self.swift_fixture.startup()
        self.assertRaises(ClientException, client.get_object, "size",
                          str(size))

        # But fresh connections are fine.
        client = self.swift_fixture.connect()
        headers, body = client.get_object("size", str(size))
        self.assertEqual(body, "0" * size)

    def test_env(self):
        self.assertEqual(fakeswift.DEFAULT_USERNAME,
                         config.librarian_server.os_username)
        self.assertEqual(fakeswift.DEFAULT_PASSWORD,
                         config.librarian_server.os_password)
        self.assertEqual(
            'http://localhost:{0}/keystone/v2.0/'.format(
                self.swift_fixture.daemon_port),
            config.librarian_server.os_auth_url)
        self.assertEqual(fakeswift.DEFAULT_TENANT_NAME,
                         config.librarian_server.os_tenant_name)
Example #8
0
 def setUp(self):
     TestCaseInTempDir.setUp(self)
     self.output = StringIO()
     self.protocol = PullerWorkerProtocol(self.output)
     self.factory = ObjectFactory()