def register_interchain_auth_v1( chain_registration_body: Dict[str, str]) -> None: dcid = chain_registration_body["dcid"] key = chain_registration_body["key"] signature = chain_registration_body["signature"] # Initialize keys with chain id as public key (dont need to pull from matchmaking) requester_keys = keys.DCKeys(pull_keys=False).initialize( public_key_string=dcid, hash_type="sha256") if not requester_keys.check_signature( f"{keys.get_public_id()}_{key}".encode("utf-8"), signature): _log.info( f"invalid signature for interchain key registration from {dcid}") raise exceptions.UnauthorizedException( "Invalid signature authorization") # Authorization successful, now register actual key auth_key = api_key_model.new_from_scratch(interchain_dcid=dcid) auth_key.key = key try: api_key_dao.save_api_key(auth_key) except Exception: _log.exception("Error saving interchain auth key") raise RuntimeError("Authorization registration failure") _log.info(f"successfully registered interchain auth key with {dcid}")
def create_api_key_v1( nickname: str = "", permissions_document: Optional["permissions_doc"] = None ) -> Dict[str, Any]: """Create a new api key Returns: newly created API keys """ key = api_key_model.new_from_scratch(smart_contract=False, nickname=(nickname or "")) if permissions_document: # This permissions doc that was passed in should have had the schema validated by the webserver route key.permissions_document = permissions_document api_key_dao.save_api_key(key) return _api_key_model_to_user_dto(key, with_key=True)
def register_new_interchain_key_with_remote( interchain_dcid: str) -> api_key_model.APIKeyModel: """Make a new auth key and register it with a remote dragonchain for inter-level communication Args: interchain_dcid: chain id of the interchain sharing this key Returns: API key model for the newly shared key Raises: RuntimeError when bad response from chain or couldn't save to storage """ # We need to estabilish a shared HMAC key for this chain before we can post new_interchain_key = api_key_model.new_from_scratch( interchain_dcid=interchain_dcid) signature = keys.get_my_keys().make_signature( f"{interchain_dcid}_{new_interchain_key.key}".encode("utf-8"), crypto.SupportedHashes.sha256) new_key = { "dcid": keys.get_public_id(), "key": new_interchain_key.key, "signature": signature } try: r = requests.post( f"{matchmaking.get_dragonchain_address(interchain_dcid)}/v1/interchain-auth-register", json=new_key, timeout=30) except Exception as e: raise RuntimeError( f"Unable to register shared auth key with dragonchain {interchain_dcid}\nError: {e}" ) if r.status_code < 200 or r.status_code >= 300: raise RuntimeError( f"Unable to register shared auth key with dragonchain {interchain_dcid}\nStatus code: {r.status_code}" ) api_key_dao.save_api_key(new_interchain_key) return new_interchain_key
def populate_api_keys(self) -> None: key = api_key_model.new_from_scratch(smart_contract=True) api_key_dao.save_api_key(key) self.model.secrets["secret-key"] = key.key self.model.secrets["auth-key-id"] = key.key_id self.model.auth_key_id = key.key_id
def test_new_from_scratch_uses_interchain_dcid_for_key_id(self): model = api_key_model.new_from_scratch(interchain_dcid="banana") self.assertEqual(model.key_id, "banana") self.assertTrue(model.interchain) # Also check that the correct permissions document was created self.assertEqual(model.permissions_document, {"version": "1", "default_allow": False, "permissions": {}})
def test_new_from_scratch_generates_sc_id_if_contract(self): model = api_key_model.new_from_scratch(smart_contract=True) self.assertTrue(model.key_id.startswith("SC_"))
def test_new_from_scratch_generates_api_key_model_and_uses_default_permissions(self): model = api_key_model.new_from_scratch() self.assertIsInstance(model, api_key_model.APIKeyModel) self.assertEqual(model.permissions_document, api_key_model.DEFAULT_PERMISSIONS_DOCUMENT)