def expired(self, receipt): if settings.WEBAPPS_RECEIPT_EXPIRED_SEND: receipt['exp'] = (calendar.timegm(gmtime()) + settings.WEBAPPS_RECEIPT_EXPIRY_SECONDS) cef(self.environ, self.addon_id, 'sign', 'Expired signing request') return json.dumps({'status': 'expired', 'receipt': sign(receipt)}) return json.dumps({'status': 'expired'})
def create_test_receipt(root, status): time_ = calendar.timegm(time.gmtime()) detail = absolutify(reverse('receipt.test.details')) receipt = { 'detail': absolutify(detail), 'exp': time_ + (60 * 60 * 24), 'iat': time_, 'iss': settings.SITE_URL, 'nbf': time_, 'product': { 'storedata': urlencode({'id': 0}), 'url': root, 'type': 'test' }, 'reissue': detail, 'typ': 'purchase-receipt', 'user': { 'type': 'directed-identifier', 'value': 'none' }, 'verify': absolutify(reverse('receipt.test.verify', kwargs={'status': status})) } if settings.SIGNING_SERVER_ACTIVE: return sign(receipt) else: return jwt.encode(receipt, get_key(), u'RS512')
def create_test_receipt(root, status): time_ = calendar.timegm(time.gmtime()) detail = absolutify(reverse('receipt.test.details')) receipt = { 'detail': absolutify(detail), 'exp': time_ + (60 * 60 * 24), 'iat': time_, 'iss': settings.SITE_URL, 'nbf': time_, 'product': { 'storedata': urlencode({'id': 0}), 'url': root, }, 'reissue': detail, 'typ': 'test-receipt', 'user': { 'type': 'directed-identifier', 'value': 'none' }, 'verify': absolutify(reverse('receipt.test.verify', kwargs={'status': status})) } if settings.SIGNING_SERVER_ACTIVE: return sign(receipt) else: return jwt.encode(receipt, get_key(), u'RS512')
def create_receipt(installed_pk): installed = Installed.objects.get(pk=installed_pk) addon_pk = installed.addon.pk verify = '%s%s' % (settings.WEBAPPS_RECEIPT_URL, addon_pk) detail = reverse('account.purchases.receipt', args=[addon_pk]) reissue = installed.addon.get_purchase_url('reissue') time_ = calendar.timegm(time.gmtime()) receipt = dict(typ='purchase-receipt', product={'url': installed.addon.origin, 'storedata': urlencode({'id': int(addon_pk)})}, user={'type': 'directed-identifier', 'value': installed.uuid}, iss=settings.SITE_URL, nbf=time_, iat=time_, exp=(time_ + settings.WEBAPPS_RECEIPT_EXPIRY_SECONDS), detail=absolutify(detail), verify=absolutify(verify), reissue=absolutify(reissue)) if settings.SIGNING_SERVER_ACTIVE: # The shiny new code. return sign(receipt) else: # Our old bad code. return jwt.encode(receipt, get_key(), u'RS512')
def receipt_signer(): destination = getattr(settings, "SIGNING_SERVER", None) if not destination: return "", "Signer is not configured." # Just send some test data into the signer. now = int(time.time()) not_valid = settings.SITE_URL + "/not-valid" data = { "detail": not_valid, "exp": now + 3600, "iat": now, "iss": settings.SITE_URL, "product": {"storedata": "id=1", "url": u"http://not-valid.com"}, "nbf": now, "typ": "purchase-receipt", "reissue": not_valid, "user": {"type": "directed-identifier", "value": u"something-not-valid"}, "verify": not_valid, } try: result = receipt.sign(data) except SigningError as err: msg = "Error on signing (%s): %s" % (destination, err) return msg, msg try: cert, rest = receipt.crack(result) except Exception as err: msg = "Error on cracking receipt (%s): %s" % (destination, err) return msg, msg # Check that the certs used to sign the receipts are not about to expire. limit = now + (60 * 60 * 24) # One day. if cert["exp"] < limit: msg = "Cert will expire soon (%s)" % destination return msg, msg cert_err_msg = "Error on checking public cert (%s): %s" location = cert["iss"] try: resp = requests.get(location, timeout=5, stream=False) except Exception as err: msg = cert_err_msg % (location, err) return msg, msg if not resp.ok: msg = cert_err_msg % (location, resp.reason) return msg, msg cert_json = resp.json() if not cert_json or "jwk" not in cert_json: msg = cert_err_msg % (location, "Not valid JSON/JWK") return msg, msg return "", "Signer working and up to date"
def receipt_signer(): destination = getattr(settings, 'SIGNING_SERVER', None) if not destination: return '', 'Signer is not configured.' # Just send some test data into the signer. now = int(time.time()) not_valid = (settings.SITE_URL + '/not-valid') data = {'detail': not_valid, 'exp': now + 3600, 'iat': now, 'iss': settings.SITE_URL, 'product': {'storedata': 'id=1', 'url': u'http://not-valid.com'}, 'nbf': now, 'typ': 'purchase-receipt', 'reissue': not_valid, 'user': {'type': 'directed-identifier', 'value': u'something-not-valid'}, 'verify': not_valid } try: result = receipt.sign(data) except SigningError as err: msg = 'Error on signing (%s): %s' % (destination, err) return msg, msg try: cert, rest = receipt.crack(result) except Exception as err: msg = 'Error on cracking receipt (%s): %s' % (destination, err) return msg, msg # Check that the certs used to sign the receipts are not about to expire. limit = now + (60 * 60 * 24) # One day. if cert['exp'] < limit: msg = 'Cert will expire soon (%s)' % destination return msg, msg cert_err_msg = 'Error on checking public cert (%s): %s' location = cert['iss'] try: resp = requests.get(location, timeout=5, stream=False) except Exception as err: msg = cert_err_msg % (location, err) return msg, msg if not resp.ok: msg = cert_err_msg % (location, resp.reason) return msg, msg cert_json = resp.json() if not cert_json or not 'jwk' in cert_json: msg = cert_err_msg % (location, 'Not valid JSON/JWK') return msg, msg return '', 'Signer working and up to date'
def expired(self): receipt_cef.log(self.environ, self.addon_id, 'verify', 'Expired receipt') if settings.WEBAPPS_RECEIPT_EXPIRED_SEND: self.decoded['exp'] = (calendar.timegm(gmtime()) + settings.WEBAPPS_RECEIPT_EXPIRY_SECONDS) # Log that we are signing a new receipt as well. receipt_cef.log(self.environ, self.addon_id, 'sign', 'Expired signing request') return {'status': 'expired', 'receipt': sign(self.decoded)} return {'status': 'expired'}
def sign(data): """ Returns a signed receipt. If the seperate signing server is present then it will use that. Otherwise just uses JWT. :params receipt: the receipt to be signed. """ if settings.SIGNING_SERVER_ACTIVE: return receipt.sign(data) else: return jwt.encode(data, get_key(), u'RS512')
def create_receipt(installed, flavour=None): assert flavour in [None, 'developer', 'reviewer'], ('Invalid flavour: %s' % flavour) webapp = installed.addon time_ = calendar.timegm(time.gmtime()) typ = 'purchase-receipt' product = { 'storedata': urlencode({'id': int(webapp.pk)}), # Packaged and hosted apps should have an origin. If there # isn't one, fallback to the SITE_URL. 'url': webapp.origin or settings.SITE_URL } # Generate different receipts for reviewers or developers. expiry = time_ + settings.WEBAPPS_RECEIPT_EXPIRY_SECONDS if flavour: if not (acl.action_allowed_user(installed.user, 'Apps', 'Review') or webapp.has_author(installed.user)): raise ValueError('User %s is not a reviewer or developer' % installed.user.pk) # Developer and reviewer receipts should expire after 24 hours. expiry = time_ + (60 * 60 * 24) typ = flavour + '-receipt' verify = absolutify(reverse('receipt.verify', args=[webapp.guid])) else: verify = settings.WEBAPPS_RECEIPT_URL reissue = absolutify(reverse('receipt.reissue')) receipt = dict( exp=expiry, iat=time_, iss=settings.SITE_URL, nbf=time_, product=product, # TODO: This is temporary until detail pages get added. detail=absolutify(reissue), # Currently this is a 404. reissue=absolutify(reissue), # Currently this is a 404. typ=typ, user={ 'type': 'directed-identifier', 'value': installed.uuid }, verify=verify) if settings.SIGNING_SERVER_ACTIVE: # The shiny new code. return sign(receipt) else: # Our old bad code. return jwt.encode(receipt, get_key(), u'RS512')
def create_receipt(installed_pk, flavour=None): assert flavour in [None, 'developer', 'reviewer'], ('Invalid flavour: %s' % flavour) installed = Installed.objects.get(pk=installed_pk) webapp = installed.addon origin = (settings.SITE_URL if webapp.is_packaged else webapp.origin) time_ = calendar.timegm(time.gmtime()) product = {'url': origin, 'storedata': urlencode({'id': int(webapp.pk)})} # Generate different receipts for reviewers or developers. expiry = time_ + settings.WEBAPPS_RECEIPT_EXPIRY_SECONDS if flavour: if not (acl.action_allowed_user(installed.user, 'Apps', 'Review') or webapp.has_author(installed.user)): raise ValueError('User %s is not a reviewer or developer' % installed.user.pk) if flavour == 'reviewer': expiry = time_ + (60 * 60 * 24) product['type'] = flavour verify = absolutify(reverse('receipt.verify', args=[webapp.app_slug])) else: verify = settings.WEBAPPS_RECEIPT_URL detail = reverse('account.purchases.receipt', args=[webapp.pk]) reissue = webapp.get_purchase_url('reissue') receipt = dict(detail=absolutify(detail), exp=expiry, iat=time_, iss=settings.SITE_URL, nbf=time_, product=product, reissue=absolutify(reissue), typ='purchase-receipt', user={ 'type': 'directed-identifier', 'value': installed.uuid }, verify=verify) if settings.SIGNING_SERVER_ACTIVE: # The shiny new code. return sign(receipt) else: # Our old bad code. return jwt.encode(receipt, get_key(), u'RS512')
def create_receipt(installed, flavour=None): assert flavour in [None, 'developer', 'reviewer'], ( 'Invalid flavour: %s' % flavour) webapp = installed.addon time_ = calendar.timegm(time.gmtime()) typ = 'purchase-receipt' product = {'storedata': urlencode({'id': int(webapp.pk)}), # Packaged and hosted apps should have an origin. If there # isn't one, fallback to the SITE_URL. 'url': webapp.origin or settings.SITE_URL} # Generate different receipts for reviewers or developers. expiry = time_ + settings.WEBAPPS_RECEIPT_EXPIRY_SECONDS if flavour: if not (acl.action_allowed_user(installed.user, 'Apps', 'Review') or webapp.has_author(installed.user)): raise ValueError('User %s is not a reviewer or developer' % installed.user.pk) # Developer and reviewer receipts should expire after 24 hours. expiry = time_ + (60 * 60 * 24) typ = flavour + '-receipt' verify = absolutify(reverse('receipt.verify', args=[webapp.guid])) else: verify = settings.WEBAPPS_RECEIPT_URL reissue = absolutify(reverse('receipt.reissue')) receipt = dict(exp=expiry, iat=time_, iss=settings.SITE_URL, nbf=time_, product=product, # TODO: This is temporary until detail pages get added. detail=absolutify(reissue), # Currently this is a 404. reissue=absolutify(reissue), # Currently this is a 404. typ=typ, user={'type': 'directed-identifier', 'value': installed.uuid}, verify=verify) if settings.SIGNING_SERVER_ACTIVE: # The shiny new code. return sign(receipt) else: # Our old bad code. return jwt.encode(receipt, get_key(), u'RS512')
def create_receipt(installed_pk, flavour=None): assert flavour in [None, 'developer', 'reviewer'], ( 'Invalid flavour: %s' % flavour) installed = Installed.objects.get(pk=installed_pk) webapp = installed.addon origin = (settings.SITE_URL if webapp.is_packaged else webapp.origin) time_ = calendar.timegm(time.gmtime()) typ = 'purchase-receipt' product = {'url': origin, 'storedata': urlencode({'id': int(webapp.pk)})} # Generate different receipts for reviewers or developers. expiry = time_ + settings.WEBAPPS_RECEIPT_EXPIRY_SECONDS if flavour: if not (acl.action_allowed_user(installed.user, 'Apps', 'Review') or webapp.has_author(installed.user)): raise ValueError('User %s is not a reviewer or developer' % installed.user.pk) # Developer and reviewer receipts should expire after 24 hours. expiry = time_ + (60 * 60 * 24) typ = flavour + '-receipt' verify = absolutify(reverse('receipt.verify', args=[webapp.guid])) else: verify = settings.WEBAPPS_RECEIPT_URL detail = reverse('account.purchases.receipt', args=[webapp.pk]) reissue = webapp.get_purchase_url('reissue') receipt = dict(detail=absolutify(detail), exp=expiry, iat=time_, iss=settings.SITE_URL, nbf=time_, product=product, reissue=absolutify(reissue), typ=typ, user={'type': 'directed-identifier', 'value': installed.uuid}, verify=verify) if settings.SIGNING_SERVER_ACTIVE: # The shiny new code. return sign(receipt) else: # Our old bad code. return jwt.encode(receipt, get_key(), u'RS512')
def create_receipt(installed_pk, flavour=None): assert flavour in [None, 'author', 'reviewer'], ( 'Invalid flavour: %s' % flavour) installed = Installed.objects.get(pk=installed_pk) addon_pk = installed.addon.pk time_ = calendar.timegm(time.gmtime()) product = {'url': installed.addon.origin, 'storedata': urlencode({'id': int(addon_pk)})} # Generate different receipts for reviewers or authors. if flavour in ['author', 'reviewer']: if not (acl.action_allowed_user(installed.user, 'Apps', 'Review') or installed.addon.has_author(installed.user)): raise ValueError('User %s is not a reviewer or author' % installed.user.pk) expiry = time_ + (60 * 60 * 24) product['type'] = flavour verify = absolutify(reverse('reviewers.receipt.verify', args=[installed.addon.app_slug])) else: expiry = time_ + settings.WEBAPPS_RECEIPT_EXPIRY_SECONDS verify = '%s%s' % (settings.WEBAPPS_RECEIPT_URL, addon_pk) detail = reverse('account.purchases.receipt', args=[addon_pk]) reissue = installed.addon.get_purchase_url('reissue') receipt = dict(detail=absolutify(detail), exp=expiry, iat=time_, iss=settings.SITE_URL, nbf=time_, product=product, reissue=absolutify(reissue), typ='purchase-receipt', user={'type': 'directed-identifier', 'value': installed.uuid}, verify=absolutify(verify)) if settings.SIGNING_SERVER_ACTIVE: # The shiny new code. return sign(receipt) else: # Our old bad code. return jwt.encode(receipt, get_key(), u'RS512')
def signer(): destination = getattr(settings, 'SIGNING_SERVER', None) if not destination: return True, 'Signer is not configured.' # Just send some test data into the signer. now = int(time.time()) not_valid = (settings.SITE_URL + '/not-valid') data = {'detail': not_valid, 'exp': now + 3600, 'iat': now, 'iss': settings.SITE_URL, 'product': {'storedata': 'id=1', 'url': u'http://not-valid.com'}, 'nbf': now, 'typ': 'purchase-receipt', 'reissue': not_valid, 'user': {'type': 'directed-identifier', 'value': u'something-not-valid'}, 'verify': not_valid } try: result = receipt.sign(data) except receipt.SigningError, err: return False, 'Error on signing (%s): %s' % (destination, err)
def test_timeout(self, req): req.side_effect = Timeout req.return_value = self.get_response(200) sign('x')
def test_error(self, req): req.return_value = self.get_response(403) sign('x')
def test_some_unicode(self, get): get.return_value = self.get_response(200) sign({'name': u'Вагиф Сәмәдоғлу'})
def test_good(self, req): req.return_value = self.get_response(200) sign('x')
def test_other(self, urlopen): urlopen.return_value = self.get_response(206) sign('x')
def test_called(self, get): get.return_value = self.get_response(200) sign('my-receipt') eq_(get.call_args[1]['data'], 'my-receipt')
def test_error(self, urlopen): urlopen.return_value = self.get_response(403) sign('x')
def test_some_unicode(self, urlopen): sign({'name': u'Вагиф Сәмәдоғлу'})
def test_called(self, get): get.return_value = self.get_response(200) sign("my-receipt") eq_(get.call_args[1]["data"], "my-receipt")
def test_called(self, urlopen): urlopen.return_value = self.get_response(200) sign('my-receipt') eq_(urlopen.call_args[0][0].data, 'my-receipt')
def test_good(self, urlopen): urlopen.return_value = self.get_response(200) sign('x')
def test_some_unicode(self, urlopen): urlopen.return_value = self.get_response(200) sign({'name': u'Вагиф Сәмәдоғлу'})
def test_called(self, urlopen): sign('my-receipt') eq_(urlopen.call_args[0][0].data, 'my-receipt')
def test_other(self, req): req.return_value = self.get_response(206) sign('x')
def test_some_unicode(self, mock_post): mock_post.return_value = self.get_response(200) sign({'name': u'Вагиф Сәмәдоғлу'})
def expired(self, receipt): if settings.WEBAPPS_RECEIPT_EXPIRED_SEND: receipt["exp"] = calendar.timegm(gmtime()) + settings.WEBAPPS_RECEIPT_EXPIRY_SECONDS receipt_cef.log(self.environ, self.addon_id, "sign", "Expired signing request") return json.dumps({"status": "expired", "receipt": sign(receipt)}) return json.dumps({"status": "expired"})
def test_some_unicode(self, get): get.return_value = self.get_response(200) sign({"name": u"Вагиф Сәмәдоғлу"})