Beispiel #1
0
 def addSponsoredIdentity(self, idy: Identity):
     if idy.role and not Authoriser.isValidRole(idy.role):
         raise AttributeError("invalid role: {}".format(idy.role))
     if idy.identifier in self._sponsored:
         del self._sponsored[idy.identifier]
     self._sponsored[idy.identifier] = idy
     self._sendIdReq(idy)
Beispiel #2
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
Beispiel #3
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 validate(self, req: Request, config=None):
        operation = req.operation
        if operation.get(TXN_TYPE) == POOL_UPGRADE:
            origin = req.identifier
            try:
                originRole = self.idrCache.getRole(origin, isCommitted=False)
            except:
                raise UnauthorizedClientRequest(
                    req.identifier,
                    req.reqId,
                    "Nym {} not added to the ledger yet".format(origin))

            action = operation.get(ACTION)
            # TODO: Some validation needed for making sure name and version
            # present
            status = self.upgrader.statusInLedger(req.operation.get(NAME),
                                                  req.operation.get(VERSION))

            if status == START and action == START:
                raise InvalidClientRequest(
                    req.identifier,
                    req.reqId,
                    "Upgrade '{}' is already scheduled".format(
                        req.operation.get(NAME)))

            r, msg = Authoriser.authorised(POOL_UPGRADE, ACTION, originRole,
                                           oldVal=status, newVal=action)
            if not r:
                raise UnauthorizedClientRequest(
                    req.identifier,
                    req.reqId,
                    "{} cannot do {}".format(
                        Roles.nameFromValue(originRole),
                        SovrinTransactions.POOL_UPGRADE.name))
 def authErrorWhileUpdatingNode(self, request):
     origin = request.identifier
     isTrustee = self.node.secondaryStorage.isTrustee(origin)
     if not isTrustee:
         error = super().authErrorWhileUpdatingNode(request)
         if error:
             return error
     origin = request.identifier
     operation = request.operation
     nodeNym = operation.get(TARGET_NYM)
     isSteward = self.node.secondaryStorage.isSteward(origin)
     actorRole = self.node.graphStore.getRole(origin)
     _, nodeInfo = self.getNodeInfoFromLedger(nodeNym, excludeLast=False)
     typ = operation.get(TXN_TYPE)
     data = deepcopy(operation.get(DATA))
     data.pop(ALIAS, None)
     vals = []
     msgs = []
     for k in data:
         oldVal = nodeInfo[DATA][k]
         newVal = data[k]
         if oldVal != newVal:
             r, msg = Authoriser.authorised(typ,
                                            k,
                                            actorRole,
                                            oldVal=oldVal,
                                            newVal=newVal,
                                            isActorOwnerOfSubject=isSteward)
             vals.append(r)
             msgs.append(msg)
     msg = None if all(vals) else '\n'.join(msgs)
     return msg
Beispiel #6
0
    def __init__(self,
                 identifier: Identifier,
                 sponsor: Identifier = None,
                 verkey=None,
                 role=None,
                 last_synced=None,
                 seqNo=None):

        self.identifier = identifier
        self.sponsor = sponsor

        # None indicates the identifier is a cryptonym
        self.verkey = verkey

        # None indicates the identifier is a cryptonym
        # if role and role not in (SPONSOR, STEWARD):
        if not Authoriser.isValidRole(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 = seqNo
Beispiel #7
0
 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))
         )
Beispiel #9
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))
     # 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 _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)
Beispiel #11
0
 def addNymTxnToGraph(self, txn):
     origin = txn.get(f.IDENTIFIER.nm)
     role = txn.get(ROLE)
     if not Authoriser.isValidRole(role):
         raise ValueError(
             "Unknown role {} for nym, cannot add nym to graph".format(
                 role))
     verkey = txn.get(VERKEY)
     nym = txn[TARGET_NYM]
     try:
         txnId = txn[TXN_ID]
         seqNo = txn.get(F.seqNo.name)
         # Since NYM vertex has a unique index on the identifier,
         # (CID or DID) a unique constraint violation would occur if the
         # nym exists. Instead of catching an exception, a call to hasNym or
         #  getNym could be done but since NYM update txns would be less
         # common then NYM adding transactions so avoiding the cost of
         # extra db query
         try:
             self.addNym(txnId,
                         nym,
                         verkey,
                         role,
                         frm=origin,
                         reference=txn.get(REF),
                         seqNo=seqNo)
         except pyorient.PyOrientORecordDuplicatedException:
             updateData = {}
             # Since role can be None, it is only included for update if
             # it was supplied in the transaction as if ROLE was not
             # supplied in transaction, the client did not intend to update
             # the role, but if absence of role is considered None then it
             # will lead to the identity losing its role
             if ROLE in txn:
                 updateData[ROLE] = txn[ROLE]
             if VERKEY in txn:
                 updateData[VERKEY] = txn[VERKEY]
             self.updateNym(txnId, nym, seqNo, **updateData)
         else:
             # Only update edge in case of new NYM transaction
             self._updateTxnIdEdgeWithTxn(txnId, Edges.AddsNym, txn)
     except pyorient.PyOrientORecordDuplicatedException:
         logger.debug("The nym {} was already added to graph".format(nym))
     except pyorient.PyOrientCommandException as ex:
         fault(
             ex, "An exception was raised while adding "
             "nym {}: {}".format(nym, ex))
Beispiel #12
0
    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,
                    k,
                    actorRole,
                    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(self, req: Request, config=None):
        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:
            trname = SovrinTransactions.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 = SovrinTransactions.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 _validateExistingNym(self, req: Request, op, originRole, nymData):
     origin = req.identifier
     owner = self.idrCache.getOwnerFor(op[TARGET_NYM], isCommitted=False)
     isOwner = origin == owner
     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:
                     raise UnauthorizedClientRequest(
                         req.identifier,
                         req.reqId,
                         "{} cannot update {}".format(Roles.nameFromValue(originRole),
                                                      key))
Beispiel #15
0
 def _validateExistingNym(self, req: Request, op, originRole, nymData):
     origin = req.identifier
     owner = self.idrCache.getOwnerFor(op[TARGET_NYM], isCommitted=False)
     isOwner = origin == owner
     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:
                     raise UnauthorizedClientRequest(
                         req.identifier, req.reqId,
                         "{} cannot update {}".format(
                             Roles.nameFromValue(originRole), key))
 def addNymTxnToGraph(self, txn):
     origin = txn.get(f.IDENTIFIER.nm)
     role = txn.get(ROLE)
     if not Authoriser.isValidRole(role):
         raise ValueError(
             "Unknown role {} for nym, cannot add nym to graph".format(
                 role))
     nym = txn[TARGET_NYM]
     verkey = txn.get(VERKEY)
     try:
         txnId = txn[TXN_ID]
         seqNo = txn.get(F.seqNo.name)
         # Since NYM vertex has a unique index on the identifier,
         # (CID or DID) a unique constraint violattion would occur if the
         # nym exists. Instead of catching an exception, a call to hasNym or
         #  getNym could be done but since NYM update txns would be less
         # common then NYM adding transactions so avoidinhg the cost of
         # extra db query
         try:
             self.addNym(txnId,
                         nym,
                         verkey,
                         role,
                         frm=origin,
                         reference=txn.get(REF),
                         seqNo=seqNo)
         except pyorient.PyOrientORecordDuplicatedException:
             self.updateNym(txnId, nym, verkey, seqNo, role)
         else:
             # Only update edge in case of new NYM transaction
             self._updateTxnIdEdgeWithTxn(txnId, Edges.AddsNym, txn)
     except pyorient.PyOrientORecordDuplicatedException:
         logger.debug("The nym {} was already added to graph".format(nym))
     except pyorient.PyOrientCommandException as ex:
         fault(
             ex, "An exception was raised while adding "
             "nym {}: {}".format(nym, ex))
Beispiel #17
0
    def checkRequestAuthorized(self, request: Request):
        op = request.operation
        typ = op[TXN_TYPE]

        s = self.graphStore  # type: identity_graph.IdentityGraph

        origin = request.identifier

        if typ == NYM:
            try:
                originRole = s.getRole(origin)
            except:
                raise UnauthorizedClientRequest(
                    request.identifier, request.reqId,
                    "Nym {} not added to the ledger yet".format(origin))

            role = op.get(ROLE)

            nym = self.graphStore.getNym(op[TARGET_NYM])
            if not nym:
                # If nym does not exist
                r, msg = Authoriser.authorised(NYM,
                                               ROLE,
                                               originRole,
                                               oldVal=None,
                                               newVal=role)
                if not r:
                    raise UnauthorizedClientRequest(
                        request.identifier, request.reqId,
                        "{} cannot add {}".format(originRole, role))
            else:
                nym = nym.oRecordData
                subjectRole = nym.get(ROLE)
                if subjectRole != role:
                    r, msg = Authoriser.authorised(NYM,
                                                   ROLE,
                                                   originRole,
                                                   oldVal=subjectRole,
                                                   newVal=role)
                    if not r:
                        raise UnauthorizedClientRequest(
                            request.identifier, request.reqId,
                            "{} cannot update {}".format(originRole, role))

        elif typ == ATTRIB:
            if op.get(TARGET_NYM) and \
                op[TARGET_NYM] != request.identifier and \
                    not s.getSponsorFor(op[TARGET_NYM]) == origin:

                raise UnauthorizedClientRequest(
                    request.identifier, request.reqId,
                    "Only user's sponsor can add attribute for that user")

        # TODO: Just for now. Later do something meaningful here
        elif typ in [
                DISCLO, GET_ATTR, CLAIM_DEF, GET_CLAIM_DEF, ISSUER_KEY,
                GET_ISSUER_KEY
        ]:
            pass
        elif request.operation.get(TXN_TYPE) in POOL_TXN_TYPES:
            return self.poolManager.checkRequestAuthorized(request)

        elif typ == POOL_UPGRADE:
            # TODO: Refactor urgently
            try:
                originRole = s.getRole(origin)
            except:
                raise UnauthorizedClientRequest(
                    request.identifier, request.reqId,
                    "Nym {} not added to the ledger yet".format(origin))

            action = request.operation.get(ACTION)
            # TODO: Some validation needed for making sure name and version
            # present
            status = self.upgrader.statusInLedger(
                request.operation.get(NAME), request.operation.get(VERSION))

            r, msg = Authoriser.authorised(POOL_UPGRADE,
                                           ACTION,
                                           originRole,
                                           oldVal=status,
                                           newVal=action)
            if not r:
                raise UnauthorizedClientRequest(
                    request.identifier, request.reqId,
                    "{} cannot do {}".format(originRole, POOL_UPGRADE))
 def role(self, role):
     if not Authoriser.isValidRole(self.correctRole(role)):
         raise AttributeError("Invalid role {}".format(role))
     self._role = role
Beispiel #19
0
    def checkRequestAuthorized(self, request: Request):
        op = request.operation
        typ = op[TXN_TYPE]

        s = self.graphStore  # type: identity_graph.IdentityGraph

        origin = request.identifier

        if typ == NYM:
            try:
                originRole = s.getRole(origin)
            except:
                raise UnauthorizedClientRequest(
                    request.identifier, request.reqId,
                    "Nym {} not added to the ledger yet".format(origin))

            nymV = self.graphStore.getNym(op[TARGET_NYM])
            if not nymV:
                # If nym does not exist
                role = op.get(ROLE)
                r, msg = Authoriser.authorised(NYM,
                                               ROLE,
                                               originRole,
                                               oldVal=None,
                                               newVal=role)
                if not r:
                    raise UnauthorizedClientRequest(
                        request.identifier, request.reqId,
                        "{} cannot add {}".format(originRole, role))
            else:
                nymData = nymV.oRecordData
                owner = self.graphStore.getOwnerFor(nymData.get(NYM_KEY))
                isOwner = origin == owner
                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:
                                raise UnauthorizedClientRequest(
                                    request.identifier, request.reqId,
                                    "{} cannot update {}".format(
                                        originRole, key))

        elif typ == ATTRIB:
            if op.get(TARGET_NYM) and \
                op[TARGET_NYM] != request.identifier and \
                    not s.getOwnerFor(op[TARGET_NYM]) == origin:

                raise UnauthorizedClientRequest(
                    request.identifier, request.reqId,
                    "Only identity owner/guardian can add attribute "
                    "for that identity")

        # TODO: Just for now. Later do something meaningful here
        elif typ in [
                DISCLO, GET_ATTR, SCHEMA, GET_SCHEMA, ISSUER_KEY,
                GET_ISSUER_KEY
        ]:
            pass
        elif request.operation.get(TXN_TYPE) in POOL_TXN_TYPES:
            return self.poolManager.checkRequestAuthorized(request)

        elif typ == POOL_UPGRADE:
            # TODO: Refactor urgently
            try:
                originRole = s.getRole(origin)
            except:
                raise UnauthorizedClientRequest(
                    request.identifier, request.reqId,
                    "Nym {} not added to the ledger yet".format(origin))

            action = request.operation.get(ACTION)
            # TODO: Some validation needed for making sure name and version
            # present
            status = self.upgrader.statusInLedger(
                request.operation.get(NAME), request.operation.get(VERSION))

            r, msg = Authoriser.authorised(POOL_UPGRADE,
                                           ACTION,
                                           originRole,
                                           oldVal=status,
                                           newVal=action)
            if not r:
                raise UnauthorizedClientRequest(
                    request.identifier, request.reqId,
                    "{} cannot do {}".format(originRole, POOL_UPGRADE))
Beispiel #20
0
    def checkValidSovrinOperation(self, identifier, reqId, operation):
        unknownKeys = set(operation.keys()).difference(set(allOpKeys))
        if unknownKeys:
            raise InvalidClientRequest(
                identifier, reqId,
                'invalid keys "{}"'.format(",".join(unknownKeys)))

        missingKeys = set(reqOpKeys).difference(set(operation.keys()))
        if missingKeys:
            raise InvalidClientRequest(
                identifier, reqId,
                'missing required keys "{}"'.format(",".join(missingKeys)))

        if operation[TXN_TYPE] not in validTxnTypes:
            raise InvalidClientRequest(
                identifier, reqId,
                'invalid {}: {}'.format(TXN_TYPE, operation[TXN_TYPE]))

        if operation[TXN_TYPE] == ATTRIB:
            dataKeys = {RAW, ENC, HASH}.intersection(set(operation.keys()))
            if len(dataKeys) != 1:
                raise InvalidClientRequest(
                    identifier, reqId, '{} should have one and only one of '
                    '{}, {}, {}'.format(ATTRIB, RAW, ENC, HASH))
            if RAW in dataKeys:
                try:
                    data = json.loads(operation[RAW])
                    endpoint = data.get(ENDPOINT)
                    check_endpoint_valid(endpoint, required=False)

                except EndpointException as exc:
                    raise InvalidClientRequest(identifier, reqId, str(exc))
                except BaseException as exc:
                    raise InvalidClientRequest(identifier, reqId, str(exc))
                # PREVIOUS CODE, ASSUMED ANY EXCEPTION WAS A JSON ISSUE
                # except:
                #     raise InvalidClientRequest(identifier, reqId,
                #                                'raw attribute {} should be '
                #                                'JSON'.format(operation[RAW]))

            if not (not operation.get(TARGET_NYM)
                    or self.graphStore.hasNym(operation[TARGET_NYM])):
                raise InvalidClientRequest(
                    identifier, reqId, '{} should be added before adding '
                    'attribute for it'.format(TARGET_NYM))

        if operation[TXN_TYPE] == NYM:
            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))
            # Only
            if not self.canNymRequestBeProcessed(identifier, operation):
                raise InvalidClientRequest(identifier, reqId,
                                           "{} is already present".format(nym))

        if operation[TXN_TYPE] == POOL_UPGRADE:
            action = operation.get(ACTION)
            if action not in (START, CANCEL):
                raise InvalidClientRequest(
                    identifier, reqId, "{} not a valid action".format(action))
            if action == START:
                schedule = operation.get(SCHEDULE, {})
                isValid, msg = self.upgrader.isScheduleValid(
                    schedule, self.poolManager.nodeIds)
                if not isValid:
                    raise InvalidClientRequest(
                        identifier, reqId,
                        "{} not a valid schedule since {}".format(
                            schedule, msg))
Beispiel #21
0
 def role(self, role):
     if not Authoriser.isValidRole(self.correctRole(role)):
         raise AttributeError("Invalid role {}".format(role))
     self._role = role