Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

get cred events from an issuer's TEL? #672

Open
dhh1128 opened this issue Feb 8, 2024 · 23 comments · May be fixed by #887
Open

get cred events from an issuer's TEL? #672

dhh1128 opened this issue Feb 8, 2024 · 23 comments · May be fixed by #887

Comments

@dhh1128
Copy link
Contributor

dhh1128 commented Feb 8, 2024

This issue tracks a question from @rubelhassan, @Arsh-Sandhu , and me. We are looking for an efficient way to discover that a particular issuer has issued or revoked credentials, and what the SAIDs and approximate issuance/revocation times of those credentials is. Our assumption was that we could contact the witness that services the issuer's AID, and get a series of events from the TEL that each contain the SAID of a given credential, or similar. What we have discovered is that this doesn't work. We seem to have a way to ask the question, but the answer to the question always seems to be "this TEL has no events" -- and we are wondering if this is by design, or if we are doing something wrong.

I will append a series of messages from Discord, reproducing some conversation that has occurred in that channel.

@dhh1128
Copy link
Contributor Author

dhh1128 commented Feb 8, 2024

First post on Discord, from Rubel:

I have a query regarding the retrieval of TELs. Scenario: I want to monitor credentials (iss, rev) that are issued to an AID (holder/issuer). I tried to obtain the TELs using witness endpoint but the response contained KELs only. Could anyone suggest what could be the possible ways to do that? I'd highly appreciate your insights and response.

@dhh1128
Copy link
Contributor Author

dhh1128 commented Feb 8, 2024

After a few suggestions, another comment from Rubel:

As you suggested, I've tried to fetch TELs for the issuer (using issuer AID)
but got no traces of iss events or ACDC chains in the response. From the
log of keria I see that TEL events were sent to witnesses:

Sending TEL events to witnesses

url: http://127.0.0.1:5642/oobi/<aid>/witness/<wit-aid>
env: keripy (development), keria (development)
wits: [wan, wil, wes] 

@dhh1128
Copy link
Contributor Author

dhh1128 commented Feb 8, 2024

To which @rodolfomiranda replied:

You should see interaction events with anchors for the registry
creation and every credential issued. You wont see the TEL, but
an anchoring event.

@dhh1128
Copy link
Contributor Author

dhh1128 commented Feb 8, 2024

@nkongsuwan:

I have been wondering about this question for a while as well. If a credential
is revoked, then a SAID of the revocation-TEL event will be anchored to the
KEL's interaction. How can you tell if a particular interaction event corresponds
to a revocation?

My guess is to look at i and s in the interaction event.

This should work only if there is one issuance or one revocation per one
interaction event. If a bunch of ACDC issuances and revocations are batched into
a single interaction event, then the issuer also needs a mechanism to publish the
TEL (or some sort of cryptographic proofs) so a verifier can tell if a specific ACDC
is revoked. 

@dhh1128
Copy link
Contributor Author

dhh1128 commented Feb 8, 2024

@rubelhassan:

I understand that TELs are not directly accessible currently, and we can get the ixn anchors from KELs that only include i, s, and d. How to look up TELs using anchor information, is there a specific function or endpoint in KERI designed for this purpose?

@dhh1128
Copy link
Contributor Author

dhh1128 commented Feb 8, 2024

@pfeairheller :

You use a qry message with a route of /tels

@dhh1128
Copy link
Contributor Author

dhh1128 commented Feb 8, 2024

@rubelhassan:

I think you mean something like this - httping.createCESRRequest(msg, client, dest=wit, path="/qry/tels") in that case, issuer.pre, issuer.regk, vcid are required for the query msg. But I was looking for TELs by issuer AID where only AID and wits are known to me. I'm a little bit confused, could you please explain? Sorry for my limited knowledge here.

@dhh1128
Copy link
Contributor Author

dhh1128 commented Feb 8, 2024

@rubelhassan:

Hi all, I'd like to ask a scenario-based question. I've created a Keripy agent to obtain KELs and TELs from the AIDs (external). Now let's say there's an AID-x that has issued credentials to AID-Y and AID-Z. Now I want to query KELs, TELs of AID-X also creds. Here are the steps I followed to achieve this:
TL;DR: I was able to get KELs but not TELs. Sorry for posting a long query.

Resolved oobi with AID-X and agent
hby.db.oobis.pin(keys=(oobi,), val=obr)#agent's hby

Implemented a QueryDoer class to communicate with an aid's witnesses. The class is as follows:
class QueryDoer(doing.DoDoer): #full code attached in the snipped
    def __init__(self, hby, rgy, alias, pre, anchor, **kwa):
        self.mbd = indirecting.MailboxDirector(hby=self.hby, topics=["/replay", "/receipt", "/reply", "/credential"],
                                               verifier=self.vry)
    def queryDo(self, tymth, tock=0.0, **opts):
        if anchor is not None:
            doer = querying.AnchorQuerier(hby=self.hby, hab=self.hab, pre=self.pre, anchor=anchor)
            # also tried WitInq telquery directly
        else:
            doer = querying.QueryDoer(hby=self.hby, hab=self.hab, pre=self.pre, kvy=self.mbd.kvy)

I created QueryDoer instance, which invokes queryDo after initialization.
qryDoer = QueryDoer(hby=hby, rgy=rgy, alias=alias, pre=aid, anchor=anchor)

I queried KELs by AID-X, I got KELs successfully.
hby.db.clonePreIter(pre=aid)

In this step I tried to get TELs of AID-X using anchor found in KELs, but got empty response.
tvy.reger.clonePreIter(pre=anchor['i']) 

I checked ragers of wits of AID-X which contain TELs but using agent I coundn't get them.
Finally when I tried to find cred issued by AID-X, which is also empty.
cred = tvy.reger.cloneCred(anchor['i'])

I appreciate your feedback if there's anything I might have missed or if you have any suggestions for alternative
approaches. 

class QueryDoer(doing.DoDoer):
    def __init__(self, hby, rgy, alias, pre, anchor, **kwa):
        doers = []
        # init properties skipped
        self.hbyDoer = habbing.HaberyDoer(habery=self.hby)

@dhh1128
Copy link
Contributor Author

dhh1128 commented Feb 8, 2024

@kentbull :

So are you asking how to retrieve TELs from the LMDB database for a given Agent / keystore?

@dhh1128
Copy link
Contributor Author

dhh1128 commented Feb 8, 2024

@dhh1128 :

@Rubel , I am just running down a mental checklist of things that
could explain why code in keripy works, and code you wrote does
not. One potential source of differences is the witnesses that were
used. Does your code use exactly the same witnesses that the
reference code does?

@dhh1128
Copy link
Contributor Author

dhh1128 commented Feb 8, 2024

We discussed this briefly on the community call today. We got to the place described in the first post on this issue -- not sure whether we're trying to pursue a dead end.

Phil's comment seems to suggest that it should be possible, but our testing did not produce useful results...

@kentbull
Copy link
Contributor

kentbull commented Feb 8, 2024

So are you asking how to retrieve TELs from the LMDB database for a given Agent / keystore?

Yes, that is what I was asking, which is a part of, though not everything, that Rubel was asking.

@pfeairheller
Copy link
Member

All of the current code for querying for TELs assumes you have a credential so you can use the registry SAID and the credential SAID to query for the TEL events related to that credential. We do not have a use case for querying for all TEL events from an issuer or from a registry.

If you have such a use case, please propose an API change to the qry events and we can discuss it on Tuesday and figure out who wants to address this with a PR.

@nkongsuwan
Copy link
Contributor

After listening and reading all the discussions in the past two weeks, my summary on this is that we need an option for issuers to publish their TELs to their witnesses so that the TELs are publicly discoverable, making them public TELs.

This should not be the default option as there are privacy implications for publishing the TELs of which ACDCs are issued to natural persons.

A good example use case is in the vLEI ecosystem where Qualified vLEI Issuers (QVI) issue ACDCs to legal entities. These ACDCs only contain public information of legal entities so they can be made public. This capability would allow anyone to monitor QVIs’ activities, without relying on GLEIF’s centralized API services.

@pfeairheller
Copy link
Member

Great summary @nkongsuwan , I agree with this assessment

@dhh1128
Copy link
Contributor Author

dhh1128 commented Feb 13, 2024

If we pursue this design goal, then a relevant question in my mind is: How does an AID's controller signal the intention that a TEL should be public? Is this a choice that must be made when the AID is first created? Or can it be made and unmade multiple times, over the lifecycle of an AID?

@dhh1128
Copy link
Contributor Author

dhh1128 commented Feb 13, 2024

If it's made when the AID is first created, does the publicness of the TEL get declared in an inception event? Or should an AID be able to make different publicness decisions about different credential registries, and have those decisions bind to the event that announces the credential registry?

@rubelhassan
Copy link
Contributor

rubelhassan commented Feb 13, 2024

Additionally, if the creds and tels are public, will it require a new API to be implemented to query an AID's credentials?

@nkongsuwan
Copy link
Contributor

If we pursue this design goal, then a relevant question in my mind is: How does an AID's controller signal the intention that a TEL should be public? Is this a choice that must be made when the AID is first created? Or can it be made and unmade multiple times, over the lifecycle of an AID?

I don’t think this choice should be made when the AID is first created as an AID may issue a variety of ACDCs, some public and some private. For example, a QVI may issue an ECR credential (via ECR AUTH from LE) which is private. Perhaps, this may be declared in key events that anchor registry creation. In the example of vLEI, a QVI may use different registries for different types of credentials.

@SmithSamuelM
Copy link
Collaborator

By design the only thing that a KEL publicizes is key state. Key state includes current signing keys, current signing key threshold, next key threshold next key digest list and backer threshold and backer identifiers. Seals that are anchored in a KEL are by design hidden. they are just hashes and maybe a reference to someother key.

This means that the AID itself has no mechanism for publishing anything about any TELs and any data that is anchored to its key state via a seal. As it should not. The publicity state of what is being sealed is sealed item dependent. Lets call these the Seal target. I.e. the seal target’s publicity is target dependent. This means any mix of public or private target’s is possible.

So given that the KEL itself cannot publicize a Seal Target how does it get published?

The primary mechanism is by an API or service endpoint. Service endpoints are can have routes attached to them via a route path string like “/public/tels”. and in some cases a return route path string like “/process/tels” This enables two things.

  • peer-to-peer asynchronous connections can be connected when query to a route includes a return route for the response that comes back asynchronously
  • synchronous protocols don’t need the return route but the route maps nicely to ReST APIs as a resource path.

These endpoints are discoverable dynamically via OOBIs. The endpoint can then be self-discoverable by publishing the routes is responds to, such as OpenAPI if its rest or the equivalent of a directory of routes (say at route “/“) of routes it responds to.

The querymessages in KERI support parametrized queries to a given endpoints route so they are perfectly generalizable.

The matching reply messages can return arbitrary field map documents so they are perfectly generalizable.

Likewise for the prod and bare messages except that these two are meant only for seal targets. That does not preclude query/reply from being associated with seal targets. But the former may employ different semantics. So far we don’t have any of the former supported but because a seal target is more secure than Bada/Run it makes sense to bifurcate based on its enhanced security posture. So maybe down the road.

Now given OOBIs for endpoints and routes for what get served up by those endpoints, a given AID controller now has perfect flexibility in what and when it wants to publicise. If it decides to make something public it attaches it to a route. If later it decides ot not publicize it. then it unattaches it. Nothing changes in the KEL.

If what it wants to publicise is a TEL then all it needs to do is create a route that corresponds to one of the following:

  • single TEL
  • a family of TELs
  • parametrized TELs
  • all TELs
  • Tels with restricted (i.e. permitted) access and an access authentication and authorization mechanism.

Authentication and Authorization

Basically unlike federated identity, KERI and ACDCs have simplified this proble, while also removing the security problems that make it such difficult problem.

Authorization starts with a white lists of trusted AIDs as trust anchors or root-of-trust
Thes trust anchors can use a combination of ACDCs and Delegated AIDs to create delegable issuances of authority. That authority can be attenuated to certain roles.

Now authentication happens upon presentations of a delegation and then authorization against the white list of trust-anchors and whatever delegable authority is allowed. Primary authentication is by verifying signatures against the current key state of the AID controller making the presentation and against ACDCs delegating authority from white listed trust anchors.

Nobearer tokens, no ephemeral tokens, no trusted third party identity providers. Each AID controller is its own identity provider. Trust anchors are not identity providers. They are not involved in the authentication process. They issue credentials which can be verified without necessarily contacting the issuer. Dynamically revocable credentials just need to have their TELs publicized to a watcher network that a verifier can access.

One can confuse a trust anchor with an identity provide, please don’t. The security role they play is materially different. They provide reputational trust not attributional trust. An identity provider provides attributional trust as a proxy for the user. In KERI the user always provides their own attributional trust. They sometimes need a reference (letter of reference) so that they can inherit or borrow enough reputation from a trust anchor to enable access. Its a completely different trust model than federated identity.

@dhh1128
Copy link
Contributor Author

dhh1128 commented Feb 21, 2024

Just a sanity check, the following sentence comes from section 6.7.1 of the vLEI OOR EGF:

GLEIF MUST monitor the QVI Transaction Event Logs (TELs) to detect the issuance
of OOR vLEI Credentials which were not reported using the vLEI Reporting API.

@SmithSamuelM
Copy link
Collaborator

SmithSamuelM commented Feb 21, 2024 via email

@pfeairheller
Copy link
Member

I believe the solution here, that Sam is referring to is a bespoke service from witnesses that represent a discovery service for published credentials. This cleanly separates what should be a simple publication of issued public credentials from Witnesses.

I think Sam described above how that service can be designed and accessed via end roles and OOBIs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants