def validate(self, req: Request): status = None operation = req.operation typ = operation.get(TXN_TYPE) if typ not in self.operation_types: return origin = req.identifier try: origin_role = self.idrCache.getRole(origin, isCommitted=False) except BaseException: raise UnauthorizedClientRequest( req.identifier, req.reqId, "Nym {} not added to the ledger yet".format(origin)) r = False if typ == POOL_RESTART: action = operation.get(ACTION) r, msg = Authoriser.authorised(typ, origin_role, field=ACTION, oldVal=status, newVal=action) elif typ == VALIDATOR_INFO: r, msg = Authoriser.authorised(typ, origin_role) if not r: raise UnauthorizedClientRequest( req.identifier, req.reqId, "{} cannot do action with type = {}".format( Roles.nameFromValue(origin_role), typ))
def _validate_schema(self, req: Request): # we can not add a Schema with already existent NAME and VERSION # sine a Schema needs to be identified by seqNo identifier = req.identifier operation = req.operation schema_name = operation[DATA][NAME] schema_version = operation[DATA][VERSION] schema, _, _, _ = self.getSchema( author=identifier, schemaName=schema_name, schemaVersion=schema_version, with_proof=False ) if schema: raise InvalidClientRequest(identifier, req.reqId, '{} can have one and only one SCHEMA with ' 'name {} and version {}' .format(identifier, schema_name, schema_version)) try: origin_role = self.idrCache.getRole( req.identifier, isCommitted=False) or None except BaseException: raise UnknownIdentifier( req.identifier, req.reqId) r, msg = Authoriser.authorised(typ=SCHEMA, actorRole=origin_role) if not r: raise UnauthorizedClientRequest( req.identifier, req.reqId, "{} cannot add schema".format( Roles.nameFromValue(origin_role)) )
def test_pool_upgrade_wrong_new_name(role, is_owner): assert not Authoriser.authorised(typ=POOL_UPGRADE, field=ACTION, actorRole=role, oldVal="start", newVal="aaa", isActorOwnerOfSubject=is_owner)[0]
def __init__(self, identifier: Identifier, trust_anchor: Identifier=None, verkey=None, role=None, last_synced=None, seq_no=None): """ :param identifier: :param trust_anchor: :param verkey: :param role: If role is explicitly passed as `null` then in the request to ledger, `role` key would be sent as None which would stop the Identity's ability to do any privileged actions. If role is not passed, `role` key will not be included in the request to the ledger :param last_synced: :param seq_no: """ self.identity = DidIdentity(identifier, verkey=verkey) self.trustAnchor = trust_anchor # if role and role not in (TRUST_ANCHOR, STEWARD): if not Authoriser.isValidRole(self.correctRole(role)): raise AttributeError("Invalid role {}".format(role)) self._role = role # timestamp for when the ledger was last checked for key replacement or # revocation self.last_synced = last_synced # sequence number of the latest key management transaction for this # identifier self.seqNo = seq_no
def test_node_wrong_new_service_name(role, is_owner): assert not Authoriser.authorised(typ=NODE, actorRole=role, field=SERVICES, oldVal="[]", newVal="aaa", isActorOwnerOfSubject=is_owner)[0]
def _validate_schema(self, req: Request): # we can not add a Schema with already existent NAME and VERSION # sine a Schema needs to be identified by seqNo identifier = req.identifier operation = req.operation schema_name = operation[DATA][NAME] schema_version = operation[DATA][VERSION] schema, _, _, _ = self.getSchema(author=identifier, schemaName=schema_name, schemaVersion=schema_version) if schema: raise InvalidClientRequest( identifier, req.reqId, '{} can have one and only one SCHEMA with ' 'name {} and version {}'.format(identifier, schema_name, schema_version)) try: origin_role = self.idrCache.getRole(req.identifier, isCommitted=False) or None except BaseException: raise UnknownIdentifier(req.identifier, req.reqId) r, msg = Authoriser.authorised(typ=SCHEMA, actorRole=origin_role) if not r: raise UnauthorizedClientRequest( req.identifier, req.reqId, "{} cannot add schema".format( Roles.nameFromValue(origin_role)))
def __init__(self, identifier: Identifier, endorser: Identifier = None, verkey=None, role=None, last_synced=None, seq_no=None): """ :param identifier: :param endorser: :param verkey: :param role: If role is explicitly passed as `null` then in the request to ledger, `role` key would be sent as None which would stop the Identity's ability to do any privileged actions. If role is not passed, `role` key will not be included in the request to the ledger :param last_synced: :param seq_no: """ self.identity = DidIdentity(identifier, verkey=verkey) self.endorser = endorser # if role and role not in (ENDORSER, STEWARD): if not Authoriser.isValidRole(self.correctRole(role)): raise AttributeError("Invalid role {}".format(role)) self._role = role # timestamp for when the ledger was last checked for key replacement or # revocation self.last_synced = last_synced # sequence number of the latest key management transaction for this # identifier self.seqNo = seq_no
def _authorised_for_schemas(role, is_owner): return Authoriser.authorised(typ=SCHEMA, field=ROLE, actorRole=role, oldVal=None, newVal=None, isActorOwnerOfSubject=is_owner)
def _validateExistingNym(self, req: Request, op, originRole, nymData): unauthorized = False reason = None origin = req.identifier owner = self.idrCache.getOwnerFor(op[TARGET_NYM], isCommitted=False) isOwner = origin == owner if not originRole == TRUSTEE and not isOwner: reason = '{} is neither Trustee nor owner of {}' \ .format(origin, op[TARGET_NYM]) unauthorized = True if not unauthorized: updateKeys = [ROLE, VERKEY] for key in updateKeys: if key in op: newVal = op[key] oldVal = nymData.get(key) if oldVal != newVal: r, msg = Authoriser.authorised(NYM, key, originRole, oldVal=oldVal, newVal=newVal, isActorOwnerOfSubject=isOwner) if not r: unauthorized = True reason = "{} cannot update {}".\ format(Roles.nameFromValue(originRole), key) break if unauthorized: raise UnauthorizedClientRequest( req.identifier, req.reqId, reason)
def _validate_claim_def(self, req: Request): # we can not add a Claim Def with existent ISSUER_DID # sine a Claim Def needs to be identified by seqNo ref = req.operation[REF] try: txn = self.ledger.getBySeqNo(ref) except KeyError: raise InvalidClientRequest( req.identifier, req.reqId, "Mentioned seqNo ({}) doesn't exist.".format(ref)) if txn['txn']['type'] != SCHEMA: raise InvalidClientRequest( req.identifier, req.reqId, "Mentioned seqNo ({}) isn't seqNo of the schema.".format(ref)) try: origin_role = self.idrCache.getRole(req.identifier, isCommitted=False) or None except BaseException: raise UnknownIdentifier(req.identifier, req.reqId) # only owner can update claim_def, # because his identifier is the primary key of claim_def r, msg = Authoriser.authorised(typ=CLAIM_DEF, actorRole=origin_role, isActorOwnerOfSubject=True) if not r: raise UnauthorizedClientRequest( req.identifier, req.reqId, "{} cannot add claim def".format( Roles.nameFromValue(origin_role)))
def test_pool_upgrade_wrong_new_name(role, is_owner): assert not Authoriser.authorised(typ=POOL_UPGRADE, actorRole=role, field=ACTION, oldVal="start", newVal="aaa", isActorOwnerOfSubject=is_owner)[0]
def _validateExistingNym(self, req: Request, op, originRole, nymData): unauthorized = False reason = None origin = req.identifier owner = self.idrCache.getOwnerFor(op[TARGET_NYM], isCommitted=False) isOwner = origin == owner if not originRole == TRUSTEE and not isOwner: reason = '{} is neither Trustee nor owner of {}' \ .format(origin, op[TARGET_NYM]) unauthorized = True if not unauthorized: updateKeys = [ROLE, VERKEY] for key in updateKeys: if key in op: newVal = op[key] oldVal = nymData.get(key) if oldVal != newVal: r, msg = Authoriser.authorised( NYM, key, originRole, oldVal=oldVal, newVal=newVal, isActorOwnerOfSubject=isOwner) if not r: unauthorized = True reason = "{} cannot update {}".\ format(Roles.nameFromValue(originRole), key) break if unauthorized: raise UnauthorizedClientRequest(req.identifier, req.reqId, reason)
def test_node_demote(role, is_owner): authorized = (role == STEWARD and is_owner) or (role == TRUSTEE) assert authorized == Authoriser.authorised(typ=NODE, field=SERVICES, actorRole=role, oldVal="[VALIDATOR]", newVal="[]", isActorOwnerOfSubject=is_owner)[0]
def test_node_not_allowed_role_error(): expected_msg = "TRUSTEE not in allowed roles ['STEWARD']" assert expected_msg == Authoriser.authorised(typ=NODE, actorRole=TRUSTEE, field=BLS_KEY, oldVal=None, newVal="some_value", isActorOwnerOfSubject=False)[1]
def test_node_change_client_port(role, is_owner, old_values): authorized = (role == STEWARD and is_owner) assert authorized == Authoriser.authorised(typ=NODE, field=CLIENT_PORT, actorRole=role, oldVal=old_values, newVal="value2", isActorOwnerOfSubject=is_owner)[0]
def test_remove_trust_anchor(role, is_owner): authorized = (role == TRUSTEE) assert authorized == Authoriser.authorised(typ=NYM, actorRole=role, field=ROLE, oldVal=TRUST_ANCHOR, newVal=None, isActorOwnerOfSubject=is_owner)[0]
def test_pool_restart_start(role, is_owner): authorized = role in (TRUSTEE, TGB) assert authorized == Authoriser.authorised(typ=POOL_RESTART, field=ACTION, actorRole=role, oldVal="aaa", newVal="start", isActorOwnerOfSubject=is_owner)[0]
def test_remove_steward(role, is_owner): authorized = (role == TRUSTEE) assert authorized == Authoriser.authorised(typ=NYM, actorRole=role, field=ROLE, oldVal=STEWARD, newVal=None, isActorOwnerOfSubject=is_owner)[0]
def test_make_trustee(role, is_owner): authorized = (role == TRUSTEE) assert authorized == Authoriser.authorised(typ=NYM, actorRole=role, field=ROLE, oldVal=None, newVal=TRUSTEE, isActorOwnerOfSubject=is_owner)[0]
def test_make_trust_anchor(role, is_owner): authorized = role in (TRUSTEE, STEWARD) assert authorized == Authoriser.authorised(typ=NYM, actorRole=role, field=ROLE, oldVal=None, newVal=TRUST_ANCHOR, isActorOwnerOfSubject=is_owner)[0]
def test_pool_restart_start(role, is_owner): authorized = role == TRUSTEE assert authorized == Authoriser.authorised(typ=POOL_RESTART, field=ACTION, actorRole=role, oldVal="aaa", newVal="start", isActorOwnerOfSubject=is_owner)[0]
def test_change_verkey(role, is_owner, old_values): authorized = is_owner assert authorized == Authoriser.authorised(typ=NYM, actorRole=role, field=VERKEY, oldVal=old_values, newVal="value2", isActorOwnerOfSubject=is_owner)[0]
def test_node_change_bls_keys(role, is_owner, old_values): authorized = (role == STEWARD and is_owner) assert authorized == Authoriser.authorised(typ=NODE, field=BLS_KEY, actorRole=role, oldVal=old_values, newVal="value2", isActorOwnerOfSubject=is_owner)[0]
def test_node_change_alias(role, is_owner, old_values): authorized = False # alias can not be changed assert authorized == Authoriser.authorised(typ=NODE, actorRole=role, field=ALIAS, oldVal=old_values, newVal="value2", isActorOwnerOfSubject=is_owner)[0]
def test_pool_config_change(role, is_owner, old_values): authorized = role in (TRUSTEE, TGB) assert authorized == Authoriser.authorised(typ=POOL_CONFIG, actorRole=role, field=ACTION, oldVal=old_values, newVal="value2", isActorOwnerOfSubject=is_owner)[0]
def test_client_can_send_claim_def(): Authoriser.auth_map = generate_auth_map(Authoriser.ValidRoles, False) r, msg = Authoriser.authorised(typ=CLAIM_DEF, actorRole=None, field="name", isActorOwnerOfSubject=True) assert r and not msg
def test_node_enable(role, is_owner): authorized = (role == STEWARD and is_owner) assert authorized == Authoriser.authorised(typ=NODE, field=SERVICES, actorRole=role, oldVal=None, newVal="[VALIDATOR]", isActorOwnerOfSubject=is_owner)[0]
def test_client_cant_send_claim_def(): Authoriser.auth_map = generate_auth_map(Authoriser.ValidRoles, True) r, msg = Authoriser.authorised(typ=CLAIM_DEF, actorRole=None, field="name", isActorOwnerOfSubject=True) assert not r and "None role not in allowed roles" in msg
def test_node_enable(role, is_owner): authorized = (role == STEWARD and is_owner) assert authorized == Authoriser.authorised(typ=NODE, actorRole=role, field=SERVICES, oldVal=None, newVal="[VALIDATOR]", isActorOwnerOfSubject=is_owner)[0]
def test_node_change_client_port(role, is_owner, old_values): authorized = (role == STEWARD and is_owner) assert authorized == Authoriser.authorised(typ=NODE, actorRole=role, field=CLIENT_PORT, oldVal=old_values, newVal="value2", isActorOwnerOfSubject=is_owner)[0]
def test_node_change_bls_keys(role, is_owner, old_values): authorized = (role == STEWARD and is_owner) assert authorized == Authoriser.authorised(typ=NODE, actorRole=role, field=BLS_KEY, oldVal=old_values, newVal="value2", isActorOwnerOfSubject=is_owner)[0]
def test_pool_upgrade_start(role, is_owner): authorized = role in (TRUSTEE, TGB) assert authorized == Authoriser.authorised(typ=POOL_UPGRADE, field=ACTION, actorRole=role, oldVal=None, newVal="start", isActorOwnerOfSubject=is_owner)[0]
def test_node_only_owner_error(): expected_msg = "Only owner is allowed" assert expected_msg == Authoriser.authorised(typ=NODE, actorRole=STEWARD, field=BLS_KEY, oldVal=None, newVal="some_value", isActorOwnerOfSubject=False)[1]
def test_node_change_alias(role, is_owner, old_values): authorized = False # alias can not be changed assert authorized == Authoriser.authorised(typ=NODE, field=ALIAS, actorRole=role, oldVal=old_values, newVal="value2", isActorOwnerOfSubject=is_owner)[0]
def test_pool_upgrade_cancel(role, is_owner): authorized = role is TRUSTEE assert authorized == Authoriser.authorised( typ=POOL_UPGRADE, actorRole=role, field=ACTION, oldVal="start", newVal="cancel", isActorOwnerOfSubject=is_owner)[0]
def test_pool_config_change(role, is_owner, old_values): authorized = role is TRUSTEE assert authorized == Authoriser.authorised( typ=POOL_CONFIG, actorRole=role, field=ACTION, oldVal=old_values, newVal="value2", isActorOwnerOfSubject=is_owner)[0]
def test_node_demote(role, is_owner): authorized = (role == STEWARD and is_owner) or (role == TRUSTEE) assert authorized == Authoriser.authorised( typ=NODE, actorRole=role, field=SERVICES, oldVal="[VALIDATOR]", newVal="[]", isActorOwnerOfSubject=is_owner)[0]
def _doStaticValidationNym(self, identifier, reqId, operation): role = operation.get(ROLE) nym = operation.get(TARGET_NYM) if not nym: raise InvalidClientRequest( identifier, reqId, "{} needs to be present".format(TARGET_NYM)) if not Authoriser.isValidRole(role): raise InvalidClientRequest(identifier, reqId, "{} not a valid role".format(role))
def validate(self, req: Request): status = None operation = req.operation typ = operation.get(TXN_TYPE) if typ not in [POOL_UPGRADE, POOL_CONFIG]: return origin = req.identifier try: originRole = self.idrCache.getRole(origin, isCommitted=False) except BaseException: raise UnauthorizedClientRequest( req.identifier, req.reqId, "Nym {} not added to the ledger yet".format(origin)) if typ == POOL_UPGRADE: currentVersion = Upgrader.getVersion() targetVersion = req.operation[VERSION] if Upgrader.compareVersions(currentVersion, targetVersion) < 0: # currentVersion > targetVersion raise InvalidClientRequest( req.identifier, req.reqId, "Upgrade to lower version is not allowed") trname = IndyTransactions.POOL_UPGRADE.name action = operation.get(ACTION) # TODO: Some validation needed for making sure name and version # present txn = self.upgrader.get_upgrade_txn( lambda txn: txn.get( NAME, None) == req.operation.get( NAME, None) and txn.get(VERSION) == req.operation.get(VERSION), reverse=True) if txn: status = txn.get(ACTION, None) if status == START and action == START: raise InvalidClientRequest( req.identifier, req.reqId, "Upgrade '{}' is already scheduled".format( req.operation.get(NAME))) elif typ == POOL_CONFIG: trname = IndyTransactions.POOL_CONFIG.name action = None status = None r, msg = Authoriser.authorised( typ, ACTION, originRole, oldVal=status, newVal=action) if not r: raise UnauthorizedClientRequest( req.identifier, req.reqId, "{} cannot do {}".format( Roles.nameFromValue(originRole), trname))
def validate(self, req: Request): status = None operation = req.operation typ = operation.get(TXN_TYPE) if typ not in [POOL_UPGRADE, POOL_CONFIG]: return origin = req.identifier try: originRole = self.idrCache.getRole(origin, isCommitted=False) except BaseException: raise UnauthorizedClientRequest( req.identifier, req.reqId, "Nym {} not added to the ledger yet".format(origin)) if typ == POOL_UPGRADE: currentVersion = Upgrader.getVersion() targetVersion = req.operation[VERSION] if Upgrader.compareVersions(currentVersion, targetVersion) < 0: # currentVersion > targetVersion raise InvalidClientRequest( req.identifier, req.reqId, "Upgrade to lower version is not allowed") trname = IndyTransactions.POOL_UPGRADE.name action = operation.get(ACTION) # TODO: Some validation needed for making sure name and version # present txn = self.upgrader.get_upgrade_txn( lambda txn: txn.get( NAME, None) == req.operation.get( NAME, None) and txn.get(VERSION) == req.operation.get(VERSION), reverse=True) if txn: status = txn.get(ACTION, None) if status == START and action == START: raise InvalidClientRequest( req.identifier, req.reqId, "Upgrade '{}' is already scheduled".format( req.operation.get(NAME))) elif typ == POOL_CONFIG: trname = IndyTransactions.POOL_CONFIG.name action = None status = None r, msg = Authoriser.authorised( typ, originRole, field=ACTION, oldVal=status, newVal=action) if not r: raise UnauthorizedClientRequest( req.identifier, req.reqId, "{} cannot do {}".format( Roles.nameFromValue(originRole), trname))
def _doStaticValidationNym(self, identifier, reqId, operation): role = operation.get(ROLE) nym = operation.get(TARGET_NYM) if not nym: raise InvalidClientRequest(identifier, reqId, "{} needs to be present". format(TARGET_NYM)) if not Authoriser.isValidRole(role): raise InvalidClientRequest(identifier, reqId, "{} not a valid role". format(role))
def _validateNewNym(self, req: Request, op, originRole): role = op.get(ROLE) r, msg = Authoriser.authorised(NYM, ROLE, originRole, oldVal=None, newVal=role) if not r: raise UnauthorizedClientRequest( req.identifier, req.reqId, "{} cannot add {}".format(Roles.nameFromValue(originRole), Roles.nameFromValue(role)))
def _validateNewNym(self, req: Request, op, originRole): role = op.get(ROLE) r, msg = Authoriser.authorised(NYM, ROLE, originRole, oldVal=None, newVal=role) if not r: raise UnauthorizedClientRequest( req.identifier, req.reqId, "{} cannot add {}".format( Roles.nameFromValue(originRole), Roles.nameFromValue(role)) )
def _doStaticValidationNym(self, identifier, reqId, operation): role = operation.get(ROLE) nym = operation.get(TARGET_NYM) if not nym: raise InvalidClientRequest( identifier, reqId, "{} needs to be present".format(TARGET_NYM)) if not Authoriser.isValidRole(role): raise InvalidClientRequest(identifier, reqId, "{} not a valid role".format(role)) # TODO: This is not static validation as it involves state s, reason = self.canNymRequestBeProcessed(identifier, operation) if not s: raise InvalidClientRequest(identifier, reqId, reason)
def authErrorWhileUpdatingNode(self, request): origin = request.identifier isTrustee = self.idrCache.hasTrustee(origin, isCommitted=False) if not isTrustee: error = super().authErrorWhileUpdatingNode(request) if error: return error origin = request.identifier operation = request.operation nodeNym = operation.get(TARGET_NYM) data = operation.get(DATA, {}) error = self.dataErrorWhileValidatingUpdate(data, nodeNym) if error: return error isStewardOfNode = self.isStewardOfNode( origin, nodeNym, isCommitted=False) actorRole = self.idrCache.getRole(origin, isCommitted=False) nodeInfo = self.getNodeData(nodeNym, isCommitted=False) data = deepcopy(data) data.pop(ALIAS, None) vals = [] msgs = [] for k in data: oldVal = nodeInfo.get(k, None) if nodeInfo else None newVal = data[k] if k == SERVICES: if not oldVal: oldVal = [] if not newVal: newVal = [] if oldVal != newVal: r, msg = Authoriser.authorised(NODE, actorRole, field=k, oldVal=oldVal, newVal=newVal, isActorOwnerOfSubject=isStewardOfNode) vals.append(r) msgs.append(msg) msg = None if all(vals) else '\n'.join(msgs) return msg
def _validate_claim_def(self, req: Request): # we can not add a Claim Def with existent ISSUER_DID # sine a Claim Def needs to be identified by seqNo try: origin_role = self.idrCache.getRole( req.identifier, isCommitted=False) or None except BaseException: raise UnknownIdentifier( req.identifier, req.reqId) # only owner can update claim_def, # because his identifier is the primary key of claim_def r, msg = Authoriser.authorised(typ=CLAIM_DEF, actorRole=origin_role, isActorOwnerOfSubject=True) if not r: raise UnauthorizedClientRequest( req.identifier, req.reqId, "{} cannot add claim def".format( Roles.nameFromValue(origin_role)) )
def _authorised_for_claim_def(role, is_owner): return Authoriser.authorised(typ=CLAIM_DEF, actorRole=role, isActorOwnerOfSubject=is_owner)
def _authorised_for_schemas(role): return Authoriser.authorised(typ=SCHEMA, actorRole=role)
def role(self, role): if not Authoriser.isValidRole(self.correctRole(role)): raise AttributeError("Invalid role {}".format(role)) self._role = role
def test_claim_def_adding_with_some_field(): r, msg = Authoriser.authorised(typ=CLAIM_DEF, actorRole=TRUSTEE, field="name", isActorOwnerOfSubject=True) assert r and not msg