def _send_request(self, suffix, data=None, contentType=None): if self.url.startswith("http://"): url = "{}/{}".format(self.url, suffix) else: url = "http://{}/{}".format(self.url, suffix) headers = {} if contentType is not None: headers['Content-Type'] = contentType try: if data is not None: result = requests.post(url, headers=headers, data=data) else: result = requests.get(url, headers=headers) if not result.ok: raise CapBACClientException("Error {}: {}".format( result.status_code, result.reason)) except requests.ConnectionError as err: raise CapBACClientException( 'Failed to connect to {}: {}'.format(url, str(err))) except BaseException as err: raise CapBACClientException(err) return result.text
def list(self,device): if len(device) > MAX_URI_LENGTH: raise CapBACClientException( 'Invalid URI: max length exceeded, should be less than {}' .format(MAX_URI_LENGTH)) result = self._send_request( "state?address={}".format( self._get_address(device))) try: encoded_entries = yaml.safe_load(result)["data"] data_list = [ cbor.loads(base64.b64decode(entry["data"])) for entry in encoded_entries ] return json.dumps({ x:y[x] for y in data_list for x in y }, indent=4, sort_keys=True) except BaseException: return None
def validate(self,token): try: token = json.loads(token) except: raise CapBACClientException('Invalid access token: serialization failed') return self.validate_from_dict(token)
def revoke(self, token): try: token = json.loads(token) except: raise CapBACClientException('Invalid revocation token: serialization failed') return self.revoke_from_dict(token)
def issue(self, token, is_root): try: token = json.loads(token) except: raise CapBACClientException('Invalid token: serialization failed') return self.issue_from_dict(token, is_root)
def _check_format(dictionary,name,dictionary_format,subset=None): if subset is None: subset = set(dictionary_format) for label in subset: if label not in dictionary: raise CapBACClientException("Invalid {}: {} missing ({})" .format(name,label,dictionary_format[label]['description'])) feature = dictionary[label] if 'allowed values' in dictionary_format[label]: if feature not in dictionary_format[label]['allowed values']: raise CapBACClientException( "Invalid {}: {} value should be one the following: {}" .format(name,label,dictionary_format[label]['allowed values'])) elif 'allowed types' in dictionary_format[label]: if type(feature) not in dictionary_format[label]['allowed types']: raise CapBACClientException( "Invalid {}: {} type not allowed".format(name,label)) elif type(feature) == str: # string allowed by default if 'len' in dictionary_format[label]: if len(feature) != dictionary_format[label]['len']: raise CapBACClientException( "Invalid {}: {} length should be {}" .format(name,label,dictionary_format[label]['len'])) elif 'max_len' in dictionary_format[label]: if len(feature) > dictionary_format[label]['max_len']: raise CapBACClientException( "Invalid {}: {} length should less than {}" .format(name,label,dictionary_format[label]['max_len'])) else: raise CapBACClientException( "Invalid {}: {} should be a string".format(name,label)) for label in dictionary: if label not in subset: raise CapBACClientException("Invalid {}: unexpected label {}".format(name,label))
def sign(self, token): try: token = json.loads(token) except: raise CapBACClientException('Invalid token: serialization failed') token = self.sign_dict(token) return json.dumps(token)
def __init__(self, url, keyfile=None): self.url = url if keyfile is not None: try: with open(keyfile) as fd: private_key_str = fd.read().strip() fd.close() except OSError as err: raise CapBACClientException( 'Failed to read private key: {}'.format(str(err))) try: private_key = Secp256k1PrivateKey.from_hex(private_key_str) except ParseError as e: raise CapBACClientException( 'Unable to load private key: {}'.format(str(e))) self._signer = CryptoFactory( create_context('secp256k1')).new_signer(private_key)
def issue_from_dict(self,token, is_root): # check the formal validity of the incomplete token subset = set(CAPABILITY_FORMAT) - {'II','SI','VR'} if is_root: subset -= {'IC','SU'} _check_format(token,'capabiliy token',CAPABILITY_FORMAT,subset) for access_right in token['AR']: _check_format(access_right,'capability token: access right',ACCESS_RIGHT_FORMAT) # time interval logical check try: not_before = int(token['NB']) not_after = int(token['NA']) except: raise CapBACClientException('Invalid capability: timestamp not a number') if not_before > not_after: raise CapBACClientException("Invalid capability: incorrect time interval") now = int(time.time()) if now > not_after: raise CapBACClientException("Capability already expired") if is_root: token['IC'] = None token['SU'] = self._signer.get_public_key().as_hex() # add signature token= self.sign_dict(token) # now the token is complete payload = cbor.dumps({ 'AC': "issue", 'OB': token }) return self._send_transaction(payload, token['DE'])