Exemple #1
0
 def test_setting_signature_doesnt_change_canonical_json(self):
     recipe = RecipeFactory(name='unchanged', signed=False)
     serialized = recipe.canonical_json()
     recipe.signature = SignatureFactory()
     recipe.save()
     assert recipe.signature is not None
     assert recipe.canonical_json() == serialized
Exemple #2
0
 def test_setting_signature_doesnt_change_canonical_json(self):
     recipe = RecipeFactory(name="unchanged", signed=False)
     serialized = recipe.canonical_json()
     recipe.signature = SignatureFactory()
     recipe.save()
     assert recipe.signature is not None
     assert recipe.canonical_json() == serialized
Exemple #3
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 #4
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 #5
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 #6
0
 def test_canonical_json(self):
     recipe = RecipeFactory(
         action=ActionFactory(name="action"),
         arguments_json='{"foo": 1, "bar": 2}',
         extra_filter_expression="2 + 2 == 4",
         name="canonical",
         filter_object_json=None,
     )
     # Yes, this is really ugly, but we really do need to compare an exact
     # byte sequence, since this is used for hashing and signing
     filter_expression = "2 + 2 == 4"
     expected = (
         "{"
         '"action":"action",'
         '"arguments":{"bar":2,"foo":1},'
         '"filter_expression":"%(filter_expression)s",'
         '"id":%(id)s,'
         '"name":"canonical",'
         '"revision_id":"%(revision_id)s"'
         "}"
     ) % {
         "id": recipe.id,
         "revision_id": recipe.revision_id,
         "filter_expression": filter_expression,
     }
     expected = expected.encode()
     assert recipe.canonical_json() == expected
Exemple #7
0
 def test_canonical_json(self):
     recipe = RecipeFactory(
         action=ActionFactory(name="action"),
         arguments_json='{"foo": 1, "bar": 2}',
         extra_filter_expression="2 + 2 == 4",
         name="canonical",
         filter_object_json=None,
     )
     # Yes, this is really ugly, but we really do need to compare an exact
     # byte sequence, since this is used for hashing and signing
     filter_expression = "2 + 2 == 4"
     expected = ("{"
                 '"action":"action",'
                 '"arguments":{"bar":2,"foo":1},'
                 '"filter_expression":"%(filter_expression)s",'
                 '"id":%(id)s,'
                 '"name":"canonical",'
                 '"revision_id":"%(revision_id)s"'
                 "}") % {
                     "id": recipe.id,
                     "revision_id": recipe.revision_id,
                     "filter_expression": filter_expression,
                 }
     expected = expected.encode()
     assert recipe.canonical_json() == expected
Exemple #8
0
 def test_canonical_json(self):
     recipe = RecipeFactory(
         action=ActionFactory(name='action'),
         arguments_json='{"foo": 1, "bar": 2}',
         channels=[ChannelFactory(slug='beta')],
         countries=[CountryFactory(code='CA')],
         enabled=False,
         extra_filter_expression='2 + 2 == 4',
         locales=[LocaleFactory(code='en-US')],
         name='canonical',
     )
     # Yes, this is really ugly, but we really do need to compare an exact
     # byte sequence, since this is used for hashing and signing
     filter_expression = (
         "(normandy.locale in ['en-US']) && (normandy.country in ['CA']) && "
         "(normandy.channel in ['beta']) && (2 + 2 == 4)")
     expected = ('{'
                 '"action":"action",'
                 '"arguments":{"bar":2,"foo":1},'
                 '"enabled":false,'
                 '"filter_expression":"%(filter_expression)s",'
                 '"id":%(id)s,'
                 '"is_approved":false,'
                 '"last_updated":"%(last_updated)s",'
                 '"name":"canonical",'
                 '"revision_id":"%(revision_id)s"'
                 '}') % {
                     'id': recipe.id,
                     'revision_id': recipe.revision_id,
                     'last_updated':
                     recipe.last_updated.strftime('%Y-%m-%dT%H:%M:%S.%fZ'),
                     'filter_expression': filter_expression
                 }
     expected = expected.encode()
     assert recipe.canonical_json() == expected
Exemple #9
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 #10
0
    def test_signature_is_updated_if_autograph_available(self, mocked_autograph):
        recipe = RecipeFactory(name="unchanged", approver=UserFactory(), enabler=UserFactory())
        original_signature = recipe.signature
        assert original_signature is not None

        recipe.revise(name="changed")

        assert recipe.latest_revision.name == "changed"
        assert recipe.signature is not original_signature
        expected_sig = fake_sign([recipe.canonical_json()])[0]["signature"]
        assert recipe.signature.signature == expected_sig
Exemple #11
0
    def test_signature_is_updated_if_autograph_available(self, mocked_autograph):
        recipe = RecipeFactory(name="unchanged", approver=UserFactory(), enabler=UserFactory())
        original_signature = recipe.signature
        assert original_signature is not None

        recipe.revise(name="changed")

        assert recipe.latest_revision.name == "changed"
        assert recipe.signature is not original_signature
        expected_sig = fake_sign([recipe.canonical_json()])[0]["signature"]
        assert recipe.signature.signature == expected_sig
Exemple #12
0
    def test_signature_is_updated_if_autograph_available(
            self, mocked_autograph):
        recipe = RecipeFactory(name='unchanged')
        original_signature = recipe.signature
        assert original_signature is not None

        recipe.revise(name='changed')

        assert recipe.name == 'changed'
        assert recipe.signature is not original_signature
        expected_sig = hashlib.sha256(recipe.canonical_json()).hexdigest()
        assert recipe.signature.signature == expected_sig
Exemple #13
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 #14
0
    def test_signature_is_updated_if_autograph_available(self, mocked_autograph):
        recipe = RecipeFactory(name='unchanged')
        original_signature = recipe.signature
        assert original_signature is not None

        recipe.name = 'changed'
        recipe.save()

        assert recipe.name == 'changed'
        assert recipe.signature is not original_signature
        expected_sig = hashlib.sha256(recipe.canonical_json()).hexdigest()
        assert recipe.signature.signature == expected_sig
Exemple #15
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 #16
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 #17
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 #18
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 #19
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 #20
0
 def test_signature_is_correct_on_creation_if_autograph_available(self, mocked_autograph):
     recipe = RecipeFactory()
     expected_sig = hashlib.sha256(recipe.canonical_json()).hexdigest()
     assert recipe.signature.signature == expected_sig
Exemple #21
0
 def test_signed_true(self):
     r = RecipeFactory(signed=True)
     assert r.signature is not None
     assert r.signature.signature == hashlib.sha256(r.canonical_json()).hexdigest()
     assert isinstance(r.signature.timestamp, datetime)
Exemple #22
0
 def test_signed_true(self):
     r = RecipeFactory(signed=True)
     assert r.signature is not None
     assert r.signature.signature == hashlib.sha256(
         r.canonical_json()).hexdigest()
     assert isinstance(r.signature.timestamp, datetime)
Exemple #23
0
 def test_signature_is_correct_on_creation_if_autograph_available(
         self, mocked_autograph):
     recipe = RecipeFactory()
     expected_sig = hashlib.sha256(recipe.canonical_json()).hexdigest()
     assert recipe.signature.signature == expected_sig
Exemple #24
0
 def test_signature_is_correct_on_creation_if_autograph_available(
         self, mocked_autograph):
     recipe = RecipeFactory(approver=UserFactory(), enabler=UserFactory())
     expected_sig = fake_sign([recipe.canonical_json()])[0]["signature"]
     assert recipe.signature.signature == expected_sig
Exemple #25
0
 def test_signature_is_correct_on_creation_if_autograph_available(self, mocked_autograph):
     recipe = RecipeFactory(approver=UserFactory(), enabler=UserFactory())
     expected_sig = fake_sign([recipe.canonical_json()])[0]["signature"]
     assert recipe.signature.signature == expected_sig