Add use-autograph flag, time autograph specific signing calls. (#7401)
* Add use-autograph flag, make use of it everywhere. This adds support for a use-autograph flag to our management commands, signing and language pack fetching to allow us to enable it gradually and to re-sign add-ons manually with autograph for testing purposes. Fixes #7380 * Use different statsd key for autograph signing. * Various cleanups and fixes * Fix command tests and others * Fix ui-tests * Unify flag usage, fix crypto tests * Fix sign_file calls * Just not use autograph for langpacks unless we switch it on for the broad mass. * Fix tests and codestyle * More codestyle...
This commit is contained in:
Родитель
f1d1289a86
Коммит
e949076363
|
@ -27,7 +27,10 @@ tasks = {
|
|||
'qs': [
|
||||
Q(_current_version__autoapprovalsummary__verdict=amo.AUTO_APPROVED)
|
||||
]},
|
||||
'sign_addons': {'method': sign_addons, 'qs': []},
|
||||
'sign_addons': {
|
||||
'method': sign_addons,
|
||||
'qs': [],
|
||||
'allowed_kwargs': ('use_autograph',)},
|
||||
'add_firefox57_tag_to_webextensions': {
|
||||
'method': add_firefox57_tag,
|
||||
'qs': [
|
||||
|
@ -61,6 +64,8 @@ class Command(BaseCommand):
|
|||
pre: a method to further pre process the pks, must return the pks (opt.)
|
||||
qs: a list of Q objects to apply to the method
|
||||
kwargs: any extra kwargs you want to apply to the delay method (optional)
|
||||
allowed_kwargs: any extra boolean kwargs that can be applied via
|
||||
additional arguments. Make sure to add it to `add_arguments` too.
|
||||
"""
|
||||
def add_arguments(self, parser):
|
||||
"""Handle command arguments."""
|
||||
|
@ -78,6 +83,12 @@ class Command(BaseCommand):
|
|||
help='Include deleted add-ons when determining which '
|
||||
'add-ons to process.')
|
||||
|
||||
parser.add_argument(
|
||||
'--use-autograph',
|
||||
action='store_true',
|
||||
dest='use_autograph',
|
||||
help='Use our new autograph signing.')
|
||||
|
||||
def handle(self, *args, **options):
|
||||
task = tasks.get(options.get('task'))
|
||||
if not task:
|
||||
|
@ -94,17 +105,22 @@ class Command(BaseCommand):
|
|||
# This is run in process to ensure its run before the tasks.
|
||||
pks = task['pre'](pks)
|
||||
if pks:
|
||||
kw = task.get('kwargs', {})
|
||||
kwargs = task.get('kwargs', {})
|
||||
if task.get('allowed_kwargs'):
|
||||
kwargs.update({
|
||||
arg: options.get(arg, None)
|
||||
for arg in task['allowed_kwargs']})
|
||||
# All the remaining tasks go in one group.
|
||||
grouping = []
|
||||
for chunk in chunked(pks, 100):
|
||||
grouping.append(
|
||||
task['method'].subtask(args=[chunk], kwargs=kw))
|
||||
task['method'].subtask(args=[chunk], kwargs=kwargs))
|
||||
|
||||
# Add the post task on to the end.
|
||||
post = None
|
||||
if 'post' in task:
|
||||
post = task['post'].subtask(args=[], kwargs=kw, immutable=True)
|
||||
post = task['post'].subtask(
|
||||
args=[], kwargs=kwargs, immutable=True)
|
||||
ts = chord(grouping, post)
|
||||
else:
|
||||
ts = group(grouping)
|
||||
|
|
|
@ -26,6 +26,12 @@ class Command(BaseCommand):
|
|||
help='The reason for the resign that we will send '
|
||||
'the developer.')
|
||||
|
||||
parser.add_argument(
|
||||
'--use-autograph',
|
||||
action='store_true',
|
||||
dest='use_autograph',
|
||||
help='Use our new autograph signing.')
|
||||
|
||||
def handle(self, *args, **options):
|
||||
if len(options['addon_id']) == 0: # Sign all the addons?
|
||||
raise CommandError(
|
||||
|
@ -39,4 +45,5 @@ class Command(BaseCommand):
|
|||
with override_settings(
|
||||
SIGNING_SERVER=full_server):
|
||||
sign_addons(
|
||||
addon_ids, force=options['force'], reason=options['reason'])
|
||||
addon_ids, force=options['force'], reason=options['reason'],
|
||||
use_autograph=options['use_autograph'])
|
||||
|
|
|
@ -49,12 +49,12 @@ def test_override_SIGNING_SERVER_setting(monkeypatch):
|
|||
|
||||
def test_force_signing(monkeypatch):
|
||||
"""You can force signing an addon even if it's already signed."""
|
||||
def not_forced(ids, force, reason):
|
||||
def not_forced(ids, force, reason, use_autograph):
|
||||
assert not force
|
||||
monkeypatch.setattr(SIGN_ADDONS, not_forced)
|
||||
call_command('sign_addons', '123')
|
||||
|
||||
def is_forced(ids, force, reason):
|
||||
def is_forced(ids, force, reason, use_autograph):
|
||||
assert force
|
||||
monkeypatch.setattr(SIGN_ADDONS, is_forced)
|
||||
call_command('sign_addons', '123', force=True)
|
||||
|
@ -62,7 +62,7 @@ def test_force_signing(monkeypatch):
|
|||
|
||||
def test_reason(monkeypatch):
|
||||
"""You can pass a reason."""
|
||||
def has_reason(ids, force, reason):
|
||||
def has_reason(ids, force, reason, use_autograph):
|
||||
assert reason == 'expiry'
|
||||
monkeypatch.setattr(SIGN_ADDONS, has_reason)
|
||||
call_command('sign_addons', '123', reason='expiry')
|
||||
|
|
|
@ -74,26 +74,28 @@ def validate(file_, listed=None, subtask=None, synchronous=False):
|
|||
return result
|
||||
|
||||
|
||||
def validate_and_submit(addon, file_, channel):
|
||||
def validate_and_submit(addon, file_, channel, use_autograph=False):
|
||||
return validate(
|
||||
file_, listed=(channel == amo.RELEASE_CHANNEL_LISTED),
|
||||
subtask=submit_file.si(addon.pk, file_.pk, channel))
|
||||
subtask=submit_file.si(
|
||||
addon.pk, file_.pk, channel, use_autograph=use_autograph))
|
||||
|
||||
|
||||
@task
|
||||
@write
|
||||
def submit_file(addon_pk, upload_pk, channel):
|
||||
def submit_file(addon_pk, upload_pk, channel, use_autograph=False):
|
||||
addon = Addon.unfiltered.get(pk=addon_pk)
|
||||
upload = FileUpload.objects.get(pk=upload_pk)
|
||||
if upload.passed_all_validations:
|
||||
create_version_for_upload(addon, upload, channel)
|
||||
create_version_for_upload(
|
||||
addon, upload, channel, use_autograph=use_autograph)
|
||||
else:
|
||||
log.info('Skipping version creation for {upload_uuid} that failed '
|
||||
'validation'.format(upload_uuid=upload.uuid))
|
||||
|
||||
|
||||
@atomic
|
||||
def create_version_for_upload(addon, upload, channel):
|
||||
def create_version_for_upload(addon, upload, channel, use_autograph=False):
|
||||
"""Note this function is only used for API uploads."""
|
||||
fileupload_exists = addon.fileupload_set.filter(
|
||||
created__gt=upload.created, version=upload.version).exists()
|
||||
|
@ -118,7 +120,8 @@ def create_version_for_upload(addon, upload, channel):
|
|||
if (addon.status == amo.STATUS_NULL and
|
||||
channel == amo.RELEASE_CHANNEL_LISTED):
|
||||
addon.update(status=amo.STATUS_NOMINATED)
|
||||
auto_sign_version(version, is_beta=version.is_beta)
|
||||
auto_sign_version(
|
||||
version, is_beta=version.is_beta, use_autograph=use_autograph)
|
||||
|
||||
|
||||
# Override the validator's stock timeout exception so that it can
|
||||
|
|
|
@ -1015,7 +1015,8 @@ class TestSubmitFile(TestCase):
|
|||
upload = self.create_upload()
|
||||
tasks.submit_file(self.addon.pk, upload.pk, amo.RELEASE_CHANNEL_LISTED)
|
||||
self.create_version_for_upload.assert_called_with(
|
||||
self.addon, upload, amo.RELEASE_CHANNEL_LISTED)
|
||||
self.addon, upload, amo.RELEASE_CHANNEL_LISTED,
|
||||
use_autograph=False)
|
||||
|
||||
@mock.patch('olympia.devhub.tasks.FileUpload.passed_all_validations',
|
||||
False)
|
||||
|
|
|
@ -323,8 +323,9 @@ class TestAddonSubmitUpload(UploadTest, TestCase):
|
|||
response, reverse('devhub.submit.finish', args=[addon.slug]))
|
||||
all_ = sorted([f.filename for f in latest_version.all_files])
|
||||
assert all_ == [u'xpi_name-0.1-linux.xpi', u'xpi_name-0.1-mac.xpi']
|
||||
mock_auto_sign_file.assert_has_calls(
|
||||
[mock.call(f, is_beta=False) for f in latest_version.all_files])
|
||||
mock_auto_sign_file.assert_has_calls([
|
||||
mock.call(f, is_beta=False, use_autograph=False)
|
||||
for f in latest_version.all_files])
|
||||
|
||||
def test_with_source(self):
|
||||
response = self.client.get(
|
||||
|
@ -1453,8 +1454,9 @@ class TestVersionSubmitUploadUnlisted(VersionSubmitUploadMixin, UploadTest):
|
|||
self).test_one_xpi_for_multiple_platforms()
|
||||
version = self.addon.find_latest_version(
|
||||
channel=amo.RELEASE_CHANNEL_UNLISTED)
|
||||
mock_auto_sign_file.assert_has_calls(
|
||||
[mock.call(f, is_beta=False) for f in version.all_files])
|
||||
mock_auto_sign_file.assert_has_calls([
|
||||
mock.call(f, is_beta=False, use_autograph=False)
|
||||
for f in version.all_files])
|
||||
|
||||
def test_no_force_beta_for_unlisted(self):
|
||||
"""No beta version for unlisted addons."""
|
||||
|
|
|
@ -550,7 +550,7 @@ def check_addon_compatibility(request):
|
|||
'new_addon_form': forms.DistributionChoiceForm()})
|
||||
|
||||
|
||||
def handle_upload(filedata, user, channel, app_id=None, version_id=None,
|
||||
def handle_upload(filedata, request, channel, app_id=None, version_id=None,
|
||||
addon=None, is_standalone=False, submit=False):
|
||||
automated_signing = channel == amo.RELEASE_CHANNEL_UNLISTED
|
||||
|
||||
|
@ -558,8 +558,8 @@ def handle_upload(filedata, user, channel, app_id=None, version_id=None,
|
|||
filedata, filedata.name, filedata.size,
|
||||
automated_signing=automated_signing, addon=addon)
|
||||
log.info('FileUpload created: %s' % upload.uuid.hex)
|
||||
if user.is_authenticated():
|
||||
upload.user = user
|
||||
if request.user.is_authenticated():
|
||||
upload.user = request.user
|
||||
upload.save()
|
||||
if app_id and version_id:
|
||||
# If app_id and version_id are present, we are dealing with a
|
||||
|
@ -573,7 +573,10 @@ def handle_upload(filedata, user, channel, app_id=None, version_id=None,
|
|||
ver = get_object_or_404(AppVersion, pk=version_id)
|
||||
tasks.compatibility_check.delay(upload.pk, app.guid, ver.version)
|
||||
elif submit:
|
||||
tasks.validate_and_submit(addon, upload, channel=channel)
|
||||
tasks.validate_and_submit(
|
||||
addon, upload, channel=channel,
|
||||
use_autograph=waffle.flag_is_active(
|
||||
request, 'activate-autograph-signing'))
|
||||
else:
|
||||
tasks.validate(upload, listed=(channel == amo.RELEASE_CHANNEL_LISTED))
|
||||
|
||||
|
@ -588,7 +591,7 @@ def upload(request, channel='listed', addon=None, is_standalone=False):
|
|||
app_id = request.POST.get('app_id')
|
||||
version_id = request.POST.get('version_id')
|
||||
upload = handle_upload(
|
||||
filedata=filedata, user=request.user, app_id=app_id,
|
||||
filedata=filedata, request=request, app_id=app_id,
|
||||
version_id=version_id, addon=addon, is_standalone=is_standalone,
|
||||
channel=channel)
|
||||
if addon:
|
||||
|
@ -1190,18 +1193,18 @@ def check_validation_override(request, form, addon, version):
|
|||
helper.actions['super']['method']()
|
||||
|
||||
|
||||
def auto_sign_file(file_, is_beta=False):
|
||||
def auto_sign_file(file_, use_autograph=False, is_beta=False):
|
||||
"""If the file should be automatically reviewed and signed, do it."""
|
||||
addon = file_.version.addon
|
||||
|
||||
if file_.is_experiment: # See bug 1220097.
|
||||
ActivityLog.create(amo.LOG.EXPERIMENT_SIGNED, file_)
|
||||
sign_file(file_)
|
||||
sign_file(file_, use_autograph=use_autograph)
|
||||
elif is_beta:
|
||||
# Beta won't be reviewed. They will always get signed, and logged, for
|
||||
# further review if needed.
|
||||
ActivityLog.create(amo.LOG.BETA_SIGNED, file_)
|
||||
sign_file(file_)
|
||||
sign_file(file_, use_autograph=use_autograph)
|
||||
elif file_.version.channel == amo.RELEASE_CHANNEL_UNLISTED:
|
||||
# Sign automatically without manual review.
|
||||
helper = ReviewHelper(request=None, addon=addon,
|
||||
|
@ -1213,10 +1216,10 @@ def auto_sign_file(file_, is_beta=False):
|
|||
ActivityLog.create(amo.LOG.UNLISTED_SIGNED, file_)
|
||||
|
||||
|
||||
def auto_sign_version(version, **kwargs):
|
||||
def auto_sign_version(version, use_autograph=False, **kwargs):
|
||||
# Sign all the unapproved files submitted, one for each platform.
|
||||
for file_ in version.files.exclude(status=amo.STATUS_PUBLIC):
|
||||
auto_sign_file(file_, **kwargs)
|
||||
auto_sign_file(file_, use_autograph=use_autograph, **kwargs)
|
||||
|
||||
|
||||
@dev_required
|
||||
|
@ -1397,7 +1400,12 @@ def _submit_upload(request, addon, channel, next_details, next_finish,
|
|||
channel == amo.RELEASE_CHANNEL_LISTED):
|
||||
addon.update(status=amo.STATUS_NOMINATED)
|
||||
# auto-sign versions (the method checks eligibility)
|
||||
auto_sign_version(version, is_beta=is_beta)
|
||||
use_autograph = waffle.flag_is_active(
|
||||
request, 'activate-autograph-signing')
|
||||
auto_sign_version(
|
||||
version,
|
||||
is_beta=is_beta,
|
||||
use_autograph=use_autograph)
|
||||
next_url = (next_details
|
||||
if channel == amo.RELEASE_CHANNEL_LISTED and not is_beta
|
||||
else next_finish)
|
||||
|
|
|
@ -4,6 +4,7 @@ import random
|
|||
from django.conf import settings
|
||||
from django.utils.translation import activate
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.test.client import RequestFactory
|
||||
from rest_framework import serializers
|
||||
|
||||
from olympia.amo.tests import user_factory, addon_factory, copy_file_to_temp
|
||||
|
@ -274,9 +275,12 @@ class GenerateAddonsSerializer(serializers.Serializer):
|
|||
# now, lets upload the file into the system
|
||||
from olympia.devhub.views import handle_upload
|
||||
|
||||
request = RequestFactory().get('/')
|
||||
request.user = user
|
||||
|
||||
upload = handle_upload(
|
||||
filedata=filedata,
|
||||
user=user,
|
||||
request=request,
|
||||
channel=amo.RELEASE_CHANNEL_LISTED,
|
||||
addon=addon,
|
||||
)
|
||||
|
|
|
@ -11,7 +11,6 @@ from django.core.files.storage import default_storage as storage
|
|||
from django.utils.encoding import force_bytes
|
||||
|
||||
import requests
|
||||
import waffle
|
||||
|
||||
from django_statsd.clients import statsd
|
||||
from requests_hawk import HawkAuth
|
||||
|
@ -61,14 +60,13 @@ def get_id(addon):
|
|||
return hashlib.sha256(guid).hexdigest()
|
||||
|
||||
|
||||
def call_signing(file_obj):
|
||||
def call_signing(file_obj, use_autograph=False):
|
||||
"""Get the jar signature and send it to the signing server to be signed."""
|
||||
# Extract jar signature.
|
||||
jar = JarExtractor(path=storage.open(file_obj.file_path))
|
||||
|
||||
log.debug(u'File signature contents: {0}'.format(jar.signatures))
|
||||
|
||||
use_autograph = waffle.switch_is_active('activate-autograph-signing')
|
||||
signed_manifest = unicode(jar.signatures)
|
||||
has_error = False
|
||||
|
||||
|
@ -86,7 +84,7 @@ def call_signing(file_obj):
|
|||
}]
|
||||
|
||||
# post the request
|
||||
with statsd.timer('services.sign.addon'):
|
||||
with statsd.timer('services.sign.addon.autograph'):
|
||||
response = requests.post(
|
||||
'{server}/sign/data'.format(server=conf['server_url']),
|
||||
json=signing_request,
|
||||
|
@ -135,7 +133,7 @@ def call_signing(file_obj):
|
|||
return cert_serial_num
|
||||
|
||||
|
||||
def sign_file(file_obj):
|
||||
def sign_file(file_obj, use_autograph=False):
|
||||
"""Sign a File.
|
||||
|
||||
If there's no endpoint (signing is not enabled), or the file is a hotfix,
|
||||
|
@ -180,7 +178,8 @@ def sign_file(file_obj):
|
|||
return
|
||||
|
||||
# Sign the file. If there's any exception, we skip the rest.
|
||||
cert_serial_num = unicode(call_signing(file_obj))
|
||||
cert_serial_num = unicode(
|
||||
call_signing(file_obj, use_autograph=use_autograph))
|
||||
|
||||
size = storage.size(file_obj.file_path)
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ def get_new_version_number(version):
|
|||
|
||||
|
||||
@task
|
||||
def sign_addons(addon_ids, force=False, **kw):
|
||||
def sign_addons(addon_ids, force=False, use_autograph=False, **kw):
|
||||
"""Used to sign all the versions of an addon.
|
||||
|
||||
This is used in the 'sign_addons' and 'process_addons --task sign_addons'
|
||||
|
@ -138,7 +138,7 @@ def sign_addons(addon_ids, force=False, **kw):
|
|||
# Need to bump the version (modify manifest file)
|
||||
# before the file is signed.
|
||||
update_version_number(file_obj, bumped_version_number)
|
||||
signed = bool(sign_file(file_obj))
|
||||
signed = bool(sign_file(file_obj, use_autograph=False))
|
||||
if signed: # Bump the version number if at least one signed.
|
||||
signed_at_least_a_file = True
|
||||
else: # We didn't sign, so revert the version bump.
|
||||
|
|
|
@ -16,11 +16,11 @@ import pytest
|
|||
import responses
|
||||
|
||||
from signing_clients.apps import SignatureInfo
|
||||
from waffle.models import Switch
|
||||
from waffle.models import Flag
|
||||
|
||||
from olympia import amo
|
||||
from olympia.addons.models import AddonUser
|
||||
from olympia.amo.tests import TestCase, create_switch
|
||||
from olympia.amo.tests import TestCase, create_flag
|
||||
from olympia.files.utils import extract_xpi
|
||||
from olympia.lib.crypto import packaged, tasks
|
||||
from olympia.versions.compare import version_int
|
||||
|
@ -86,6 +86,9 @@ class TestPackagedTrunion(TestCase):
|
|||
json={'mozilla.rsa': base64.b64encode(signature)},
|
||||
status=200)
|
||||
|
||||
def _sign_file(self, file_):
|
||||
packaged.sign_file(file_)
|
||||
|
||||
def assert_not_signed(self):
|
||||
assert not self.file_.is_signed
|
||||
assert not self.file_.cert_serial_num
|
||||
|
@ -108,7 +111,7 @@ class TestPackagedTrunion(TestCase):
|
|||
max_appversion.update(version='4', version_int=version_int('4'))
|
||||
self.file_.update(binary_components=True, strict_compatibility=True)
|
||||
self.assert_not_signed()
|
||||
packaged.sign_file(self.file_)
|
||||
self._sign_file(self.file_)
|
||||
self.assert_signed()
|
||||
|
||||
@responses.activate
|
||||
|
@ -120,7 +123,7 @@ class TestPackagedTrunion(TestCase):
|
|||
version='4', version_int=version_int('4'))
|
||||
self.file_.update(binary_components=True, strict_compatibility=True)
|
||||
self.assert_not_signed()
|
||||
packaged.sign_file(self.file_)
|
||||
self._sign_file(self.file_)
|
||||
self.assert_signed()
|
||||
|
||||
@responses.activate
|
||||
|
@ -131,7 +134,7 @@ class TestPackagedTrunion(TestCase):
|
|||
max_appversion.update(version='4', version_int=version_int('4'))
|
||||
self.file_.update(binary_components=False, strict_compatibility=False)
|
||||
self.assert_not_signed()
|
||||
packaged.sign_file(self.file_)
|
||||
self._sign_file(self.file_)
|
||||
self.assert_signed()
|
||||
|
||||
@responses.activate
|
||||
|
@ -143,7 +146,7 @@ class TestPackagedTrunion(TestCase):
|
|||
version='4', version_int=version_int('4'))
|
||||
self.file_.update(binary_components=False, strict_compatibility=False)
|
||||
self.assert_not_signed()
|
||||
packaged.sign_file(self.file_)
|
||||
self._sign_file(self.file_)
|
||||
self.assert_signed()
|
||||
|
||||
@responses.activate
|
||||
|
@ -154,7 +157,7 @@ class TestPackagedTrunion(TestCase):
|
|||
max_appversion.update(version='37', version_int=version_int('37'))
|
||||
self.file_.update(binary_components=False, strict_compatibility=False)
|
||||
self.assert_not_signed()
|
||||
packaged.sign_file(self.file_)
|
||||
self._sign_file(self.file_)
|
||||
self.assert_signed()
|
||||
|
||||
@responses.activate
|
||||
|
@ -166,7 +169,7 @@ class TestPackagedTrunion(TestCase):
|
|||
version='37', version_int=version_int('37'))
|
||||
self.file_.update(binary_components=True, strict_compatibility=True)
|
||||
self.assert_not_signed()
|
||||
packaged.sign_file(self.file_)
|
||||
self._sign_file(self.file_)
|
||||
self.assert_signed()
|
||||
|
||||
def test_get_trunion_endpoint(self):
|
||||
|
@ -177,13 +180,13 @@ class TestPackagedTrunion(TestCase):
|
|||
|
||||
def test_no_server_full(self):
|
||||
with self.settings(SIGNING_SERVER=''):
|
||||
packaged.sign_file(self.file_)
|
||||
self._sign_file(self.file_)
|
||||
self.assert_not_signed()
|
||||
|
||||
@responses.activate
|
||||
def test_sign_file(self):
|
||||
self.assert_not_signed()
|
||||
packaged.sign_file(self.file_)
|
||||
self._sign_file(self.file_)
|
||||
self.assert_signed()
|
||||
# Make sure there's two newlines at the end of the mozilla.sf file (see
|
||||
# bug 1158938).
|
||||
|
@ -197,7 +200,7 @@ class TestPackagedTrunion(TestCase):
|
|||
self.file_.update(filename=u'jétpack.xpi')
|
||||
shutil.move(src, self.file_.file_path)
|
||||
self.assert_not_signed()
|
||||
packaged.sign_file(self.file_)
|
||||
self._sign_file(self.file_)
|
||||
self.assert_signed()
|
||||
|
||||
def test_no_sign_missing_file(self):
|
||||
|
@ -205,7 +208,7 @@ class TestPackagedTrunion(TestCase):
|
|||
assert not self.file_.is_signed
|
||||
assert not self.file_.cert_serial_num
|
||||
assert not self.file_.hash
|
||||
packaged.sign_file(self.file_)
|
||||
self._sign_file(self.file_)
|
||||
assert not self.file_.is_signed
|
||||
assert not self.file_.cert_serial_num
|
||||
assert not self.file_.hash
|
||||
|
@ -215,25 +218,25 @@ class TestPackagedTrunion(TestCase):
|
|||
"""Don't sign hotfix addons."""
|
||||
for hotfix_guid in settings.HOTFIX_ADDON_GUIDS:
|
||||
self.addon.update(guid=hotfix_guid)
|
||||
packaged.sign_file(self.file_)
|
||||
self._sign_file(self.file_)
|
||||
self.assert_not_signed()
|
||||
|
||||
def test_no_sign_again_mozilla_signed_extensions(self):
|
||||
"""Don't try to resign mozilla signed extensions."""
|
||||
self.file_.update(is_mozilla_signed_extension=True)
|
||||
packaged.sign_file(self.file_)
|
||||
self._sign_file(self.file_)
|
||||
self.assert_not_signed()
|
||||
|
||||
@responses.activate
|
||||
def test_is_signed(self):
|
||||
assert not packaged.is_signed(self.file_.file_path)
|
||||
packaged.sign_file(self.file_)
|
||||
self._sign_file(self.file_)
|
||||
assert packaged.is_signed(self.file_.file_path)
|
||||
|
||||
@responses.activate
|
||||
def test_size_updated(self):
|
||||
unsigned_size = storage.size(self.file_.file_path)
|
||||
packaged.sign_file(self.file_)
|
||||
self._sign_file(self.file_)
|
||||
signed_size = storage.size(self.file_.file_path)
|
||||
assert self.file_.size == signed_size
|
||||
assert unsigned_size < signed_size
|
||||
|
@ -245,7 +248,7 @@ class TestPackagedTrunion(TestCase):
|
|||
self.file_.update(is_multi_package=True)
|
||||
self.assert_not_signed()
|
||||
|
||||
packaged.sign_file(self.file_)
|
||||
self._sign_file(self.file_)
|
||||
self.assert_not_signed()
|
||||
# The multi-package itself isn't signed.
|
||||
assert not packaged.is_signed(self.file_.file_path)
|
||||
|
@ -313,11 +316,11 @@ class TestPackagedTrunion(TestCase):
|
|||
class TestPackagedAutograph(TestPackagedTrunion):
|
||||
|
||||
def setUp(self):
|
||||
create_switch('activate-autograph-signing')
|
||||
create_flag('activate-autograph-signing')
|
||||
super(TestPackagedAutograph, self).setUp()
|
||||
|
||||
def tearDown(self):
|
||||
Switch.objects.filter(name='activate-autograph-signing').delete()
|
||||
Flag.objects.filter(name='activate-autograph-signing').delete()
|
||||
super(TestPackagedAutograph, self).tearDown()
|
||||
|
||||
def _register_urls(self):
|
||||
|
@ -330,6 +333,9 @@ class TestPackagedAutograph(TestPackagedTrunion):
|
|||
|
||||
return SignatureInfo(pkcs7)
|
||||
|
||||
def _sign_file(self, file_):
|
||||
packaged.sign_file(file_, use_autograph=True)
|
||||
|
||||
def assert_not_signed(self):
|
||||
# Overwritten to not rely on `responses` but check the real deal
|
||||
assert not self.file_.is_signed
|
||||
|
@ -349,7 +355,7 @@ class TestPackagedAutograph(TestPackagedTrunion):
|
|||
return
|
||||
|
||||
def test_call_signing(self):
|
||||
packaged.sign_file(self.file_)
|
||||
self._sign_file(self.file_)
|
||||
|
||||
signature_info = self._get_signature_info()
|
||||
|
||||
|
@ -360,7 +366,7 @@ class TestPackagedAutograph(TestPackagedTrunion):
|
|||
long_guid = 'x' * 65
|
||||
hashed = hashlib.sha256(long_guid).hexdigest()
|
||||
self.addon.update(guid=long_guid)
|
||||
packaged.sign_file(self.file_)
|
||||
self._sign_file(self.file_)
|
||||
|
||||
signature_info = self._get_signature_info()
|
||||
|
||||
|
@ -460,7 +466,7 @@ class TestTasks(TestCase):
|
|||
'src/olympia/files/fixtures/files/jetpack.xpi',
|
||||
self.file_.file_path):
|
||||
tasks.sign_addons([self.addon.pk])
|
||||
mock_sign_file.assert_called_with(self.file_)
|
||||
mock_sign_file.assert_called_with(self.file_, use_autograph=False)
|
||||
|
||||
@mock.patch('olympia.lib.crypto.tasks.sign_file')
|
||||
def test_sign_supported_applications(self, mock_sign_file):
|
||||
|
@ -471,7 +477,8 @@ class TestTasks(TestCase):
|
|||
for app in (amo.ANDROID.id, amo.FIREFOX.id):
|
||||
self.max_appversion.update(application=app)
|
||||
tasks.sign_addons([self.addon.pk])
|
||||
mock_sign_file.assert_called_with(self.file_)
|
||||
mock_sign_file.assert_called_with(
|
||||
self.file_, use_autograph=False)
|
||||
mock_sign_file.reset_mock()
|
||||
|
||||
def assert_not_signed(self, mock_sign_file, file_hash):
|
||||
|
@ -661,7 +668,7 @@ class TestTasks(TestCase):
|
|||
'src/olympia/files/fixtures/files/jetpack.xpi',
|
||||
self.file_.file_path):
|
||||
tasks.sign_addons([self.addon.pk], reason='expiry')
|
||||
mock_sign_file.assert_called_with(self.file_)
|
||||
mock_sign_file.assert_called_with(self.file_, use_autograph=False)
|
||||
|
||||
assert 'expiration' in mail.outbox[0].message().as_string()
|
||||
|
||||
|
|
|
@ -556,7 +556,7 @@ class TestReviewHelper(TestCase):
|
|||
approval_counter = AddonApprovalsCounter.objects.get(addon=self.addon)
|
||||
assert approval_counter.counter == 1
|
||||
|
||||
sign_mock.assert_called_with(self.file)
|
||||
sign_mock.assert_called_with(self.file, use_autograph=False)
|
||||
assert storage.exists(self.file.file_path)
|
||||
|
||||
assert self.check_log_count(amo.LOG.APPROVE_VERSION.id) == 1
|
||||
|
@ -584,7 +584,7 @@ class TestReviewHelper(TestCase):
|
|||
approval_counter = AddonApprovalsCounter.objects.get(addon=self.addon)
|
||||
assert approval_counter.counter == 1
|
||||
|
||||
sign_mock.assert_called_with(self.file)
|
||||
sign_mock.assert_called_with(self.file, use_autograph=False)
|
||||
assert storage.exists(self.file.file_path)
|
||||
|
||||
assert self.check_log_count(amo.LOG.APPROVE_VERSION.id) == 1
|
||||
|
@ -618,7 +618,7 @@ class TestReviewHelper(TestCase):
|
|||
# human review field should be empty.
|
||||
assert approval_counter.last_human_review is None
|
||||
|
||||
sign_mock.assert_called_with(self.file)
|
||||
sign_mock.assert_called_with(self.file, use_autograph=False)
|
||||
assert storage.exists(self.file.file_path)
|
||||
|
||||
assert self.check_log_count(amo.LOG.APPROVE_VERSION.id) == 1
|
||||
|
@ -669,7 +669,7 @@ class TestReviewHelper(TestCase):
|
|||
assert approval_counter.counter == 2
|
||||
self.assertCloseToNow(approval_counter.last_human_review)
|
||||
|
||||
sign_mock.assert_called_with(self.file)
|
||||
sign_mock.assert_called_with(self.file, use_autograph=False)
|
||||
assert storage.exists(self.file.file_path)
|
||||
|
||||
assert self.check_log_count(amo.LOG.APPROVE_VERSION.id) == 1
|
||||
|
@ -875,7 +875,7 @@ class TestReviewHelper(TestCase):
|
|||
'%s signed and ready to download' % self.preamble)
|
||||
assert 'our automatic tests and is now signed' in mail.outbox[0].body
|
||||
|
||||
sign_mock.assert_called_with(self.file)
|
||||
sign_mock.assert_called_with(self.file, use_autograph=False)
|
||||
assert storage.exists(self.file.file_path)
|
||||
|
||||
assert self.check_log_count(amo.LOG.APPROVE_VERSION.id) == 1
|
||||
|
|
|
@ -11,6 +11,7 @@ from django.utils.translation import ugettext, ugettext_lazy as _, ungettext
|
|||
|
||||
import django_tables2 as tables
|
||||
import jinja2
|
||||
import waffle
|
||||
|
||||
import olympia.core.logger
|
||||
|
||||
|
@ -611,8 +612,10 @@ class ReviewBase(object):
|
|||
assert not self.content_review_only
|
||||
|
||||
# Sign addon.
|
||||
use_autograph = waffle.flag_is_active(
|
||||
self.request, 'activate-autograph-signing')
|
||||
for file_ in self.files:
|
||||
sign_file(file_)
|
||||
sign_file(file_, use_autograph=use_autograph)
|
||||
|
||||
# Hold onto the status before we change it.
|
||||
status = self.addon.status
|
||||
|
@ -809,8 +812,10 @@ class ReviewUnlisted(ReviewBase):
|
|||
assert self.version.channel == amo.RELEASE_CHANNEL_UNLISTED
|
||||
|
||||
# Sign addon.
|
||||
use_autograph = waffle.flag_is_active(
|
||||
self.request, 'activate-autograph-signing')
|
||||
for file_ in self.files:
|
||||
sign_file(file_)
|
||||
sign_file(file_, use_autograph=use_autograph)
|
||||
|
||||
self.set_files(amo.STATUS_PUBLIC, self.files)
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ from rest_framework.response import Response
|
|||
from olympia import amo
|
||||
from olympia.access.models import Group, GroupUser
|
||||
from olympia.addons.models import Addon, AddonUser
|
||||
from olympia.amo.tests import addon_factory
|
||||
from olympia.amo.tests import addon_factory, create_flag
|
||||
from olympia.api.tests.utils import APIKeyAuthTestCase
|
||||
from olympia.applications.models import AppVersion
|
||||
from olympia.devhub import tasks
|
||||
|
@ -122,7 +122,28 @@ class TestUploadVersion(BaseUploadVersionCase):
|
|||
assert latest_version
|
||||
assert latest_version.channel == amo.RELEASE_CHANNEL_UNLISTED
|
||||
self.auto_sign_version.assert_called_with(
|
||||
latest_version, is_beta=False)
|
||||
latest_version, is_beta=False, use_autograph=False)
|
||||
|
||||
def test_addon_does_not_exist_use_autograph(self):
|
||||
guid = '@create-version'
|
||||
qs = Addon.unfiltered.filter(guid=guid)
|
||||
assert not qs.exists()
|
||||
|
||||
create_flag('activate-autograph-signing')
|
||||
|
||||
response = self.request('PUT', addon=guid, version='1.0')
|
||||
assert response.status_code == 201
|
||||
assert qs.exists()
|
||||
addon = qs.get()
|
||||
assert addon.guid == guid
|
||||
assert addon.has_author(self.user)
|
||||
assert addon.status == amo.STATUS_NULL
|
||||
latest_version = addon.find_latest_version(
|
||||
channel=amo.RELEASE_CHANNEL_UNLISTED)
|
||||
assert latest_version
|
||||
assert latest_version.channel == amo.RELEASE_CHANNEL_UNLISTED
|
||||
self.auto_sign_version.assert_called_with(
|
||||
latest_version, is_beta=False, use_autograph=True)
|
||||
|
||||
def test_new_addon_random_slug_unlisted_channel(self):
|
||||
guid = '@create-webextension'
|
||||
|
@ -193,7 +214,8 @@ class TestUploadVersion(BaseUploadVersionCase):
|
|||
assert version.statuses[0][1] == amo.STATUS_AWAITING_REVIEW
|
||||
assert version.addon.status == amo.STATUS_PUBLIC
|
||||
assert version.channel == amo.RELEASE_CHANNEL_LISTED
|
||||
self.auto_sign_version.assert_called_with(version, is_beta=False)
|
||||
self.auto_sign_version.assert_called_with(
|
||||
version, is_beta=False, use_autograph=False)
|
||||
assert not version.all_files[0].is_mozilla_signed_extension
|
||||
|
||||
def test_version_already_uploaded(self):
|
||||
|
@ -241,7 +263,8 @@ class TestUploadVersion(BaseUploadVersionCase):
|
|||
assert latest_version
|
||||
assert latest_version.channel == amo.RELEASE_CHANNEL_UNLISTED
|
||||
self.auto_sign_version.assert_called_with(
|
||||
latest_version, is_beta=False)
|
||||
latest_version, is_beta=False,
|
||||
use_autograph=False)
|
||||
|
||||
def test_version_added_is_experiment_reject_no_perm(self):
|
||||
guid = 'experiment@xpi'
|
||||
|
@ -276,7 +299,7 @@ class TestUploadVersion(BaseUploadVersionCase):
|
|||
assert latest_version
|
||||
assert latest_version.channel == amo.RELEASE_CHANNEL_UNLISTED
|
||||
self.auto_sign_version.assert_called_with(
|
||||
latest_version, is_beta=False)
|
||||
latest_version, is_beta=False, use_autograph=False)
|
||||
assert latest_version.all_files[0].is_mozilla_signed_extension
|
||||
|
||||
def test_mozilla_signed_not_allowed_not_mozilla(self):
|
||||
|
@ -313,7 +336,7 @@ class TestUploadVersion(BaseUploadVersionCase):
|
|||
assert latest_version
|
||||
assert latest_version.channel == amo.RELEASE_CHANNEL_UNLISTED
|
||||
self.auto_sign_version.assert_called_with(
|
||||
latest_version, is_beta=False)
|
||||
latest_version, is_beta=False, use_autograph=False)
|
||||
|
||||
def test_system_addon_not_allowed_not_mozilla(self):
|
||||
guid = 'systemaddon@mozilla.org'
|
||||
|
@ -351,7 +374,7 @@ class TestUploadVersion(BaseUploadVersionCase):
|
|||
latest_version = addon.find_latest_version(
|
||||
channel=amo.RELEASE_CHANNEL_UNLISTED)
|
||||
self.auto_sign_version.assert_called_with(
|
||||
latest_version, is_beta=False)
|
||||
latest_version, is_beta=False, use_autograph=False)
|
||||
|
||||
def test_version_is_beta_unlisted(self):
|
||||
addon = Addon.objects.get(guid=self.guid)
|
||||
|
@ -375,7 +398,8 @@ class TestUploadVersion(BaseUploadVersionCase):
|
|||
assert version.addon.status == amo.STATUS_NULL
|
||||
assert version.channel == amo.RELEASE_CHANNEL_UNLISTED
|
||||
assert not version.is_beta
|
||||
self.auto_sign_version.assert_called_with(version, is_beta=False)
|
||||
self.auto_sign_version.assert_called_with(
|
||||
version, is_beta=False, use_autograph=False)
|
||||
|
||||
def test_version_is_beta(self):
|
||||
assert Addon.objects.get(guid=self.guid).status == amo.STATUS_PUBLIC
|
||||
|
@ -397,7 +421,8 @@ class TestUploadVersion(BaseUploadVersionCase):
|
|||
assert version.addon.status == amo.STATUS_PUBLIC
|
||||
assert version.channel == amo.RELEASE_CHANNEL_LISTED
|
||||
assert version.is_beta
|
||||
self.auto_sign_version.assert_called_with(version, is_beta=True)
|
||||
self.auto_sign_version.assert_called_with(
|
||||
version, is_beta=True, use_autograph=False)
|
||||
|
||||
def test_invalid_version_response_code(self):
|
||||
# This raises an error in parse_addon which is not covered by
|
||||
|
@ -533,7 +558,8 @@ class TestUploadVersionWebextension(BaseUploadVersionCase):
|
|||
assert latest_version
|
||||
assert latest_version.channel == amo.RELEASE_CHANNEL_UNLISTED
|
||||
self.auto_sign_version.assert_called_with(
|
||||
latest_version, is_beta=False)
|
||||
latest_version, is_beta=False,
|
||||
use_autograph=False)
|
||||
|
||||
def test_addon_does_not_exist_webextension_with_guid_in_url(self):
|
||||
guid = '@custom-guid-provided'
|
||||
|
@ -560,7 +586,8 @@ class TestUploadVersionWebextension(BaseUploadVersionCase):
|
|||
assert latest_version
|
||||
assert latest_version.channel == amo.RELEASE_CHANNEL_UNLISTED
|
||||
self.auto_sign_version.assert_called_with(
|
||||
latest_version, is_beta=False)
|
||||
latest_version, is_beta=False,
|
||||
use_autograph=False)
|
||||
|
||||
def test_addon_does_not_exist_webextension_with_invalid_guid_in_url(self):
|
||||
guid = 'custom-invalid-guid-provided'
|
||||
|
|
|
@ -224,7 +224,7 @@ class VersionView(APIView):
|
|||
status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
file_upload = handle_upload(
|
||||
filedata=filedata, user=request.user, addon=addon, submit=True,
|
||||
filedata=filedata, request=request, addon=addon, submit=True,
|
||||
channel=channel)
|
||||
|
||||
return file_upload, created
|
||||
|
|
|
@ -249,7 +249,8 @@ def fetch_langpack(url, xpi, **kw):
|
|||
# Not `version.files.update`, because we need to trigger save
|
||||
# hooks.
|
||||
file_.update(status=amo.STATUS_PUBLIC)
|
||||
sign_file(file_)
|
||||
|
||||
sign_file(file_, use_autograph=False)
|
||||
|
||||
# Finally, set the addon summary if one wasn't provided in the xpi.
|
||||
addon.status = amo.STATUS_PUBLIC
|
||||
|
|
|
@ -134,7 +134,26 @@ class TestLangpackFetcher(TestCase):
|
|||
# automatically for legacy extensions, that includes langpacks)
|
||||
assert file_.strict_compatibility is True
|
||||
|
||||
mock_sign_file.assert_called_once_with(file_)
|
||||
mock_sign_file.assert_called_once_with(file_, use_autograph=False)
|
||||
|
||||
@mock.patch('olympia.zadmin.tasks.sign_file')
|
||||
def test_fetch_new_langpack_use_autograph(self, mock_sign_file):
|
||||
assert self.get_langpacks().count() == 0
|
||||
|
||||
self.fetch_langpacks(amo.FIREFOX.latest_version)
|
||||
|
||||
langpacks = self.get_langpacks()
|
||||
assert langpacks.count() == 1
|
||||
|
||||
addon = langpacks[0]
|
||||
file_ = addon.current_version.files.get()
|
||||
|
||||
# has_complete_metadata checks license and categories were set.
|
||||
assert addon.has_complete_metadata(), addon.get_required_metadata()
|
||||
assert file_.status == amo.STATUS_PUBLIC
|
||||
assert addon.status == amo.STATUS_PUBLIC
|
||||
|
||||
mock_sign_file.assert_called_once_with(file_, use_autograph=False)
|
||||
|
||||
@mock.patch('olympia.zadmin.tasks.sign_file')
|
||||
def test_fetch_updated_langpack(self, mock_sign_file):
|
||||
|
@ -164,7 +183,7 @@ class TestLangpackFetcher(TestCase):
|
|||
# automatically for legacy extensions, that includes langpacks)
|
||||
assert file_.strict_compatibility is True
|
||||
|
||||
mock_sign_file.assert_called_with(file_)
|
||||
mock_sign_file.assert_called_with(file_, use_autograph=False)
|
||||
|
||||
@mock.patch('olympia.zadmin.tasks.sign_file')
|
||||
def test_fetch_duplicate_langpack(self, mock_sign_file):
|
||||
|
@ -186,7 +205,8 @@ class TestLangpackFetcher(TestCase):
|
|||
amo.FIREFOX.latest_version)
|
||||
|
||||
mock_sign_file.assert_called_once_with(
|
||||
addon.current_version.files.get())
|
||||
addon.current_version.files.get(),
|
||||
use_autograph=False)
|
||||
|
||||
@mock.patch('olympia.zadmin.tasks.sign_file')
|
||||
def test_fetch_updated_langpack_beta(self, mock_sign_file):
|
||||
|
@ -208,7 +228,8 @@ class TestLangpackFetcher(TestCase):
|
|||
version = addon.versions.get(version=versions[1])
|
||||
assert version.files.all()[0].status == amo.STATUS_BETA
|
||||
|
||||
mock_sign_file.assert_called_with(version.files.get())
|
||||
mock_sign_file.assert_called_with(
|
||||
version.files.get(), use_autograph=False)
|
||||
|
||||
@mock.patch('olympia.zadmin.tasks.sign_file')
|
||||
def test_fetch_new_langpack_beta(self, mock_sign_file):
|
||||
|
|
Загрузка…
Ссылка в новой задаче