Exemple #1
0
    def test_only_signed_when_approved_and_enabled(self, mocked_autograph):
        sign_data_mock = mocked_autograph.return_value.sign_data
        # This uses the signer, so do it first
        action = ActionFactory()
        sign_data_mock.reset_mock()

        sign_data_mock.side_effect = Exception("Can't sign yet")
        recipe = RecipeFactory(name="unchanged", action=action)
        assert not recipe.enabled
        assert not recipe.is_approved
        assert recipe.signature is None

        # Updating does not generate a signature
        recipe.revise(name="changed")
        assert recipe.signature is None

        # Approving does not sign the recipe
        rev = recipe.latest_revision
        approval_request = rev.request_approval(UserFactory())
        approval_request.approve(UserFactory(), "r+")
        recipe.refresh_from_db()
        assert recipe.signature is None
        mocked_autograph.return_value.sign_data.assert_not_called()

        # Enabling signs the recipe
        mocked_autograph.return_value.sign_data.side_effect = fake_sign
        rev.enable(UserFactory())
        recipe.refresh_from_db()
        expected_sig = fake_sign([recipe.canonical_json()])[0]["signature"]
        assert recipe.signature.signature == expected_sig
        assert mocked_autograph.return_value.sign_data.called_once()
Exemple #2
0
    def test_signatures_update_correctly_on_enable(self, mocked_autograph):
        recipe = RecipeFactory(signed=False, approver=UserFactory())
        recipe.approved_revision.enable(user=UserFactory())
        recipe.refresh_from_db()

        assert recipe.signature is not None
        assert recipe.signature.signature == fake_sign([recipe.canonical_json()])[0]["signature"]
Exemple #3
0
    def test_it_doesnt_disable_recipes(self, mock_action):
        recipe = RecipeFactory(
            action__name='test-action',
            action__implementation='old',
            enabled=True
        )
        action = recipe.action
        mock_action(action.name, 'impl', action.arguments_schema)

        call_command('update_actions')
        recipe.refresh_from_db()
        assert recipe.enabled
Exemple #4
0
    def test_enabled_updates_signatures(self, mocked_autograph):
        recipe = RecipeFactory(name="first")
        ar = recipe.latest_revision.request_approval(UserFactory())
        ar.approve(approver=UserFactory(), comment="r+")
        recipe = Recipe.objects.get()
        recipe.approved_revision.enable(UserFactory())

        recipe.refresh_from_db()
        data_to_sign = recipe.canonical_json()
        signature_of_data = fake_sign([data_to_sign])[0]["signature"]
        signature_in_db = recipe.signature.signature
        assert signature_of_data == signature_in_db
Exemple #5
0
    def test_approval_request_property(self):
        # Make sure it works when there is no approval request
        recipe = RecipeFactory(name="old")
        assert recipe.approval_request is None

        # Make sure it returns an approval request if it exists
        approval = ApprovalRequestFactory(revision=recipe.latest_revision)
        assert recipe.approval_request == approval

        # Check the edge case where there is no latest_revision
        recipe.latest_revision.delete()
        recipe.refresh_from_db()
        assert recipe.approval_request is None
Exemple #6
0
    def test_approval_request_property(self):
        # Make sure it works when there is no approval request
        recipe = RecipeFactory(name='old')
        assert recipe.approval_request is None

        # Make sure it returns an approval request if it exists
        approval = ApprovalRequestFactory(revision=recipe.latest_revision)
        assert recipe.approval_request == approval

        # Check the edge case where there is no latest_revision
        recipe.latest_revision.delete()
        recipe.refresh_from_db()
        assert recipe.approval_request is None
Exemple #7
0
        def test_it_can_change_arguments_for_recipes(self, api_client):
            recipe = RecipeFactory(arguments_json='{}')
            action = ActionFactory(name='foobarbaz',
                                   arguments_schema={
                                       'type': 'object',
                                       'properties': {
                                           'message': {
                                               'type': 'string'
                                           },
                                           'checkbox': {
                                               'type': 'boolean'
                                           },
                                       },
                                       'required': ['message', 'checkbox']
                                   })

            arguments = {
                'message': 'test message',
                'checkbox': False,
            }

            res = api_client.patch('/api/v2/recipe/%s/' % recipe.id, {
                'action_id': action.id,
                'arguments': arguments,
            })
            assert res.status_code == 200, res.json()
            recipe.refresh_from_db()
            assert recipe.arguments == arguments

            res = api_client.get('/api/v2/recipe/%s/' % recipe.id)
            assert res.status_code == 200, res.json()
            assert res.json()['arguments'] == arguments

            arguments = {
                'message': 'second message',
                'checkbox': True,
            }
            res = api_client.patch('/api/v2/recipe/%s/' % recipe.id, {
                'action_id': action.id,
                'arguments': arguments,
            })
            assert res.status_code == 200, res.json()
            recipe.refresh_from_db()
            assert recipe.arguments == arguments

            res = api_client.get('/api/v2/recipe/%s/' % recipe.id)
            assert res.status_code == 200, res.json()
            assert res.json()['arguments'] == arguments
Exemple #8
0
    def test_signatures_update_correctly_on_enable(self, mocker):
        mock_autograph = mocker.patch('normandy.recipes.models.Autographer')

        def fake_sign(datas):
            sigs = []
            for d in datas:
                sigs.append({'signature': hashlib.sha256(d).hexdigest()})
            return sigs

        mock_autograph.return_value.sign_data.side_effect = fake_sign

        recipe = RecipeFactory(enabled=False, signed=False)
        recipe.enabled = True
        recipe.save()
        recipe.refresh_from_db()

        assert recipe.signature is not None
        assert recipe.signature.signature == hashlib.sha256(recipe.canonical_json()).hexdigest()
Exemple #9
0
    def test_signatures_update_correctly_on_enable(self, mocker):
        mock_autograph = mocker.patch('normandy.recipes.models.Autographer')

        def fake_sign(datas):
            sigs = []
            for d in datas:
                sigs.append({'signature': hashlib.sha256(d).hexdigest()})
            return sigs

        mock_autograph.return_value.sign_data.side_effect = fake_sign

        recipe = RecipeFactory(enabled=False, signed=False)
        recipe.enabled = True
        recipe.save()
        recipe.refresh_from_db()

        assert recipe.signature is not None
        assert recipe.signature.signature == hashlib.sha256(
            recipe.canonical_json()).hexdigest()
Exemple #10
0
    def test_error_during_approval_rolls_back_changes(self, mocker):
        recipe = RecipeFactory(approver=UserFactory(), enabler=UserFactory())
        old_approved_revision = recipe.approved_revision
        recipe.revise(name="New name")
        latest_revision = recipe.latest_revision
        approval_request = recipe.latest_revision.request_approval(UserFactory())

        # Simulate an error during signing
        mocked_update_signature = mocker.patch.object(recipe, "update_signature")
        mocked_update_signature.side_effect = Exception

        with pytest.raises(Exception):
            approval_request.approve(UserFactory(), "r+")

        # Ensure the changes to the approval request and the recipe are rolled back and the recipe
        # is still enabled
        recipe.refresh_from_db()
        approval_request.refresh_from_db()
        assert approval_request.approved is None
        assert recipe.approved_revision == old_approved_revision
        assert recipe.latest_revision == latest_revision
        assert recipe.approved_revision.enabled
Exemple #11
0
    def test_signatures_are_updated(self, mocked_autograph, storage):
        extension = ExtensionFactory()
        fake_old_url = extension.xpi.url.replace("/media/", "/media-old/")
        action = ActionFactory(name="opt-out-study")
        recipe = RecipeFactory(
            action=action,
            arguments={addonUrl: fake_old_url},
            approver=UserFactory(),
            enabler=UserFactory(),
            signed=True,
        )
        # preconditions
        assert recipe.signature is not None
        assert recipe.signature.signature == hashlib.sha256(recipe.canonical_json()).hexdigest()
        signature_before = recipe.signature.signature

        call_command("update_addon_urls")
        recipe.refresh_from_db()

        assert recipe.signature is not None
        assert recipe.signature != signature_before
        assert recipe.signature.signature == hashlib.sha256(recipe.canonical_json()).hexdigest()
Exemple #12
0
    def test_signatures_are_updated(self, mocked_autograph):
        action = ActionFactory(name="opt-out-study")
        recipe = RecipeFactory(
            action=action,
            arguments={
                "addonUrl": "https://before.example.com/extensions/addon.xpi"
            },
            approver=UserFactory(),
            enabler=UserFactory(),
            signed=True,
        )
        # preconditions
        assert recipe.signature is not None
        assert recipe.signature.signature == hashlib.sha256(
            recipe.canonical_json()).hexdigest()
        signature_before = recipe.signature.signature

        call_command("update_addon_urls", "after.example.com")
        recipe.refresh_from_db()

        assert recipe.signature is not None
        assert recipe.signature != signature_before
        assert recipe.signature.signature == hashlib.sha256(
            recipe.canonical_json()).hexdigest()
Exemple #13
0
 def test_it_unsigns_disabled_recipes(self, mocked_autograph):
     r = RecipeFactory(enabled=False, signed=True)
     call_command('update_recipe_signatures')
     r.refresh_from_db()
     assert r.signature is None
Exemple #14
0
 def test_it_signs_unsigned_enabled_recipes(self, mocked_autograph):
     r = RecipeFactory(approver=UserFactory(), enabled=True, signed=False)
     call_command('update_recipe_signatures')
     r.refresh_from_db()
     assert r.signature is not None
Exemple #15
0
 def test_it_unsigns_disabled_recipes(self, mocked_autograph):
     r = RecipeFactory(approver=UserFactory(), signed=True)
     call_command("update_recipe_signatures")
     r.refresh_from_db()
     assert r.signature is None