예제 #1
0
 def heartbeat(self, method, id, **kwargs):
     """
     .. py:func:: heartbeat(method, id, **kwargs)
     
     Registers a kiosks IP address, software version and uptime in the datastore.
     
     :param method: The name of the requested json method (should be equal to 'heartbeat')
     :param id: Unused
     :param **kwargs: Keyword arguments to the function. Should have non-unicode keys.
     :rtype dict: The response object. 
     Expects the following in kwargs:
     kiosk-id : The unique kiosk identifier
     uptime: A string representing the time elapsed since the script executed.
     sw_version: Version of the datalogger software running on the device.
     time: The UTC time on the datalogger.
     
     Expects the following headers:
     X-eko-signature: RSA signed hash of request body.
     """
     # extract arguments
     dieid = kwargs['kiosk-id']
     logging.debug('Device with id : %s has a pulse from %s.' % (dieid, self.request.remote_addr))
     
     uptime = kwargs['uptime']
     sw_version = kwargs['sw-version']
     local_inetadr = kwargs['rwanda-ip']
     time = kwargs['time']
     
     # find the kiosk from the kiosk id
     kiosk = Kiosk.kiosk_from_dieid(dieid)
     
     if not kiosk:
         logging.warn('Unrecognised kiosk attempted %s (IP: %s, sw_version: %s, dieid: %s).' % (method, self.request.remote_addr, sw_version, dieid))
         return self._standard_error_response(method, id, 'Not recognised', 20, 'Kiosk not registered with system.')
     
     # log this event
     logging.info('Receiving kiosk heartbeat from kiosk %s at IP %s' % (kiosk.name, self.request.remote_addr))
     
     hash, signature = self._extract_signature_hdr()
    
     if not signature[0]:
         # prepare error response
         return self._standard_error_response(method, id, 'Signature Absent', 10, 'Verification signature not present.')
     
     pubkey = self._get_public_key(kiosk)
     
     if not pubkey:
         return self._standard_error_response(method, id, 'Signature Fail', 11, 'Unable to create public key from config.')
     
     
     if pubkey and signature:
         if pubkey.verify(hash, signature):
             #message is authentic
             self._create_heartbeat(kiosk, uptime, sw_version, time, self.request.remote_addr, local_inetadr)
             data = {}
             data['result'] = 'Success'
             data['error'] = None
             data['id'] = id
             return data
         else:
             return self._standard_error_response(method, id, 'Signature Incorrect', 12, 'Verification signature failed check.')
예제 #2
0
 def post(self):
     
     logging.debug('Running File Upload Handler')
     
     bconv = BaseConverter('0123456789abcdef')
     
     dieid = self.request.get('kiosk-id')
     if not dieid:
         self.error(403)
         self.response.write('No device id provided.\n')
         logger.warn('Device attempted contact without die id from ip %s.' % self.request.remote_addr)
         return
         
     logging.info("File upload incoming from kiosk : %s" % dieid)
     
     kiosk = Kiosk.kiosk_from_dieid(dieid)
     
     if not kiosk:
         self.error(400)
         self.response.write('Kiosk is unregistered on system.\n')
         logging.warn('Unregistered kiosk on ip %s with dieid %s.' % (self.request.remote_addr, dieid))
         return
         
     logging.debug("Encoded sig: %s." % self.request.headers['X-eko-signature'])
     
     # look for the signature
     try:
         signature = bconv.to_decimal(self.request.headers['X-eko-signature'])
         logging.debug("Decoded sig: %s." % str(signature))
         challenge = self.request.headers['X-eko-challenge']
         logging.debug("Challenge: %s." % challenge)
         # signature should be uuid we sent kiosk signed with the public key
         verify = self._verify_client(kiosk, signature, challenge)
     except:
         logging.exception("Authentication signature not found.\n")
         verify = False
     
     # auth failed
     if not verify:
         logging.error("Kiosk id %s did not pass id check." % dieid)
         self.response.write('Unable to verify identity of kiosk.\n')
         return
     
     # a uuid that identifies this data packet on the remote device
     client_ref       = self.request.headers['X-eko-challenge']
     if not client_ref:
         logging.error("No client reference provided.")
         self.response.write('Client Error: No reference provided.')
         return
     
     # the type of data being sent (logs, readings, etc...)
     type             = self.request.get('type')
     # version of the client
     software_version = self.request.get('software_version')
     # manifest
     try:
         manifest = self.get_uploads(field_name='manifest')[0]
         logging.debug("Manifest uploaded, size: %s" % str(manifest.size))
     except:
         logging.exception("Manifest missing from upload data.")
         self.response.write('Manifest Not Found\n')
     
     # payload
     try:
         payload = self.get_uploads(field_name='payload')[0]
     except:
         logging.exception("Payload missing from upload data.")
         self.response.write('Payload Not Found\n')
     
     sync = SyncSession.get_by_clientref(client_ref)
     if not sync:
         logging.error("Upload attempt without requesting sync session.")
         self.response.write('Upload request improperly handled.')
         return
     sync.kiosk = kiosk
     sync.data_type = type
     sync.payload_size = 0
     
     # payload size + manifest size
     if payload:
         sync.payload_size += payload.size
     if manifest:
         sync.payload_size += manifest.size
     
     sync.payload = payload
     sync.manifest = manifest
     
     sync.software_version = software_version
     
     #sync.client_ip = self.request.remote_addr
     sync.end_date = datetime.utcnow()
     
     try:
         sync.put()
         logging.debug("Sync packet succesfully added to datastore")
         self.response.write('Success\n')
     except:
         logging.exception("Adding sync packet failed.")
         self.response.write('Failure\n')
     return
예제 #3
-1
 def testUpdatingCachedEntityFromDb(self):
     """Get a entity from db, change it and put back. Then get it from cache and compare."""
     aq = db.GqlQuery("SELECT * FROM Kiosk WHERE dieid = :1", 'A')
     a = aq.get()
     ## we set the value in memcache
     memcache.set(a.dieid, a, namespace="kiosks")
     a.name = "Baz"
     a.put()
     b = Kiosk.kiosk_from_dieid('A')
     self.assertEqual(a.name, b.name)
     self.assertEqual(1, aq.count())
예제 #4
-1
 def get_messages(self, method, id, **kwargs):
     """
     .. py:func:: get_messages(method, id, **kwargs)
     
     Returns all server messages that are pending for the kiosk.
     
     :param method: The name of the requested json method (should be equal to 'get_messages')
     :param id: Unused
     :param **kwargs: Keyword arguments to the function. Should have non-unicode keys.
     :rtype dict: The response object. 
     Expects the following in kwargs:
     kiosk-id : The unique kiosk identifier
     
     Expects the following headers:
     X-eko-signature: RSA signed hash of request body.
     """
     
     dieid = kwargs['kiosk-id']
     
     logging.debug('device with id : %s is requesting incoming messages.' % dieid)
     
     # grab kiosk, internally utilises memcache
     kiosk = Kiosk.kiosk_from_dieid(dieid)
     
     if not kiosk:
         logging.warn('Unrecognised kiosk attempted to fetch server messages (IP: %s, dieid %s).' % (self.request.remote_addr, dieid))
         return self._standard_error_response(method, id, 'Not recognised', 20, 'Kiosk not registered with system.')
     
     logging.info('Receiving message fetch request from kiosk %s at IP %s' % (kiosk.name, self.request.remote_addr))
     
     hash, signature = self._extract_signature_hdr()
     
     if not signature[0]:
         # prepare error response
         return self._standard_error_response(method, id, 'Signature Absent', 10, 'Verification signature not present.')
     
     pubkey = self._get_public_key(kiosk)
     
     if not pubkey:
         return self._standard_error_response(method, id, 'Signature Fail', 11, 'Unable to create public key from config.')
     
     
     if pubkey and signature[0]:
         if pubkey.verify(hash, signature):
             #message is authentic
             messages = self._get_server_messages(kiosk)
             data = {}
             data['result'] = messages
             data['error'] = None
             data['id'] = id
             return data
         else:
             return self._standard_error_response(method, id, 'Signature Incorrect', 12, 'Verification signature failed check.')
예제 #5
-1
 def get(self):
     upload_url = blobstore.create_upload_url('/api/upload')
     challenge = str(uuid1().get_hex())
     self.response.headers['X-eko-challenge'] = challenge
     dieid = self.request.get('kiosk-id')
     kiosk = Kiosk.kiosk_from_dieid(dieid)
     
     # we create a sync session
     sess = SyncSession()
     sess.client_ref = challenge
     sess.client_ip = self.request.remote_addr
     sess.kiosk = kiosk
     sess.start_date = datetime.utcnow()
     sess.put()
     
     self.response.headers['client-ip'] = self.request.remote_addr
     self.response.write(upload_url)
     return
예제 #6
-1
 def get(self, dieid):
     user = users.get_current_user()
     ctx = self.get_ctx(user)
     if user:
         kiosk = Kiosk.kiosk_from_dieid(dieid)
         if not kiosk:
             self.error(404)
             return
         ctx['kiosk'] = kiosk
         helper = KioskFeedHelper(user)
         ctx['heartbeat'] = helper.getMostRecentHeartbeat(kiosk)
         twomonthsago = datetime.utcnow() - timedelta(days=60)
         logging.debug("SyncSessions since %s." % (twomonthsago.strftime("%d%b%Y")))
         syncsessions = memcache.get(dieid, namespace='syncsessions')
         if not syncsessions:
             syncsessions = kiosk.syncsession_set.fetch(100)
             logging.debug("%d syncsessions fetched." % len(syncsessions))
             memcache.set(dieid, syncsessions, 60*60, namespace="syncsessions")
         ctx['sync_sessions'] = syncsessions
         
     else:
         self.redirect(users.create_login_url(self.request.uri))
     self.render_response('sync_list.html', **ctx)
예제 #7
-1
 def _commit_to_store(self, data):
     k = Kiosk()
     k.populate_from_dict(data)
     k.put()
     self.session.add_flash('Kiosk record created for %s at %s' % (data['name'], data['loc']), 'ok')
예제 #8
-1
 def create_dummy_kiosk(self):
     user = users.get_current_user()
     k = Kiosk()
     k.dieid = "A"
     k.name = "Foo"
     k.hardware = "Bar"
     k.admin = user
     k.put()
     #
     self.a = k
     k1 = Kiosk()
     k1.dieid = "B"
     k1.name = "Foo"
     k1.hardware = "Bar"
     k1.admin = user
     k1.put()
     self.b = k1
     return (k, k1)
예제 #9
-1
 def post_messages(self, method, id, **kwargs):
     """
     .. py:func:: post_messages(method, id, **kwargs)
     
     Registers a message from a kiosk in the datastore.
     
     :param method: The name of the requested json method (should be equal to 'post_messages')
     :param id: Unused
     :param **kwargs: Keyword arguments to the function. Should have non-unicode keys.
     :rtype dict: The response object. 
     
     Expects the following in kwargs:
     kiosk-id : The unique kiosk identifier
     message: A text message.
     origin: The origin of the message (subsystem).
     date: The UTC time on the datalogger that the message originated.
     
     [session-ref] : An optional reference to a upload session.
     
     Expects the following headers:
     X-eko-signature: RSA signed hash of request body.
     """
     # extract arguments
     dieid = kwargs['kiosk-id']
     logging.debug('Device with id : %s has a pulse from %s.' % (dieid, self.request.remote_addr))
     
     messages = kwargs['messages']
     
     # find the kiosk from the kiosk id
     logging.debug('device with id : %s has a pulse.' % dieid)
     kiosk = Kiosk.kiosk_from_dieid(dieid)
     
     
     if not kiosk:
         logging.warn('Unrecognised kiosk attempted %s (IP: %s, dieid: %s).' % (method, self.request.remote_addr, dieid))
         return self._standard_error_response(method, id, 'Not recognised', 20, 'Kiosk not registered with system.')
     
     # log this event
     logging.info('Receiving %d kiosk messages from kiosk %s at IP %s' % (len(messages), kiosk.name, self.request.remote_addr))
     
     hash, signature = self._extract_signature_hdr()
    
     if not signature[0]:
         # prepare error response
         return self._standard_error_response(method, id, 'Signature Absent', 10, 'Verification signature not present.')
     
     pubkey = self._get_public_key(kiosk)
     
     if not pubkey:
         return self._standard_error_response(method, id, 'Signature Fail', 11, 'Unable to create public key from config.')
     
     
     if pubkey and signature:
         if pubkey.verify(hash, signature):
             #message is authentic
             for message in messages:
                 self._create_clientmsg(kiosk, message, self.request.remote_addr)
             data = {}
             data['result'] = 'Success'
             data['error'] = None
             data['id'] = id
             return data
         else:
             return self._standard_error_response(method, id, 'Signature Incorrect', 12, 'Verification signature failed check.')