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

feat!: wildcard support in capabilies #218

Merged
merged 7 commits into from
Feb 8, 2023
Merged

feat!: wildcard support in capabilies #218

merged 7 commits into from
Feb 8, 2023

Conversation

Gozala
Copy link
Collaborator

@Gozala Gozala commented Feb 8, 2023

Fixes #87

We need this to make authorization protocol able to support more granular delegations without specifying exact space DID. And we do not want to specify exact space DID to avoid having to recreate UCAN delegations chains and instead add desired proofs. Specifically consider following scenario

  1. did:key:zSpace delegates to did:mailto:web.mail:alice
  2. did:mailto:web:mail:alice authorizes did:key:zAgent
  3. did:key:zAnotherSpace delegates to did:mailto:web.mail:alice

Unless in step 2 with field is open ended like did:*, agent did:key:zAgent will not have access to new did:key:zAnotherSpace even though it would be able to get it through access/claim.

Changes here implement native support for wildcards in can and with fields and consequently address above described limitation. Furthermore it eliminates need for boilerplate capabilities we had to use

Please note that implementation correctly handles unintended escalation like:

{ can: "store/*", with: "did:*", size: 100 }
                ^
                |
{ can: "store/*", with: "did:*" }
                ^
                |
{ can:"store/add", with:"did:key:zAlice", size:200 }

To make this work when validator parses (middle) capability it inherits information from the outer (bottom) capability and comes out just like bottom one in this instance. By doing this validator correctly identifies escalation (200 > 100) in the next step.

@Gozala Gozala requested review from alanshaw and gobengo February 8, 2023 08:29
@Gozala Gozala force-pushed the feat/wildcard-caps branch from 545413d to b0dd187 Compare February 8, 2023 08:30
proofs: [proof],
})

const result = await access(await ping.delegate(), {
Copy link
Contributor

@gobengo gobengo Feb 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see https://github.com/web3-storage/ucanto/pull/218/files#r1100550414

IMHO it's not obvious to me from ucan-wg/spec that middle dev/* should authorize this, because spec doesn't say anything about special semantics for dev/* syntax

Copy link
Collaborator Author

@Gozala Gozala Feb 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So delegation chain we have here is as follows (where top on is ambient authority by ownership, which is also something UCAN spec has no opinion on)

{ with: did:key:zAli, can: * }
         ^
         :   - by Ownership to Alice
{ with: did:*, can: * }            =>  { with: did:key:zAli, can: * }
         ^
         |   - by Alice to Bob
{ with: did:*, can: dev/* }        => { with: did:key:zAli, can: dev/* }
         ^
         |   - by Bob to Mallory
{ with: did:*, can: * }            => [{ with: did:key:zAli, can: dev/* }, { with: did:key:zBob, can: * }]
         ^
         |   - by Mallory to W3
{ with: did:key:zAli, can: 'dev/ping', nb: { message: 'hello'}  }

If you follow the chain you can see all the constraints that had been imposed at every layer (spec calls it diminishing) yet despite all the the constraints bottom is still true.

Now one could argue that Bob is escalating when delegating to Mallory, yet I think it goes against intuition and there is a discussion to spec this pattern because otherwise we have keep recreating chains every time some agent gains more capabilities, for details see:
ucan-wg/spec#130
ucan-wg/spec#131

@@ -0,0 +1,109 @@
import * as API from '@ucanto/interface'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this capability2.js file imported anywhere?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is intended difference between capability.js and capability2.js (if any)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops, I did not intend to include that file

packages/validator/src/lib.js Outdated Show resolved Hide resolved
packages/validator/src/lib.js Outdated Show resolved Hide resolved
packages/validator/src/lib.js Outdated Show resolved Hide resolved
packages/validator/src/lib.js Outdated Show resolved Hide resolved
packages/validator/src/lib.js Outdated Show resolved Hide resolved
Gozala and others added 2 commits February 8, 2023 11:45
Co-authored-by: Benjamin Goering <171782+gobengo@users.noreply.github.com>
@gobengo gobengo self-requested a review February 8, 2023 20:53
@Gozala
Copy link
Collaborator Author

Gozala commented Feb 8, 2023

I have chatted with @expede about ways to express "everything, everywhere delegated or owned" resources we've decided we can express this as ucan:*. We'll likely spec ucan: protocol in more detail, but right now I just updated implementation replacing generic URI pattern with only ucan:* form. We can add support for other forms once they get speced.

@Gozala Gozala merged commit 545d9c2 into main Feb 8, 2023
@github-actions github-actions bot mentioned this pull request Feb 8, 2023
Copy link
Member

@alanshaw alanshaw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this is awesome 🎉

Comment on lines +679 to +681
* resolveAbility('ucan:*', 'https://example.com', null) // => 'https://example.com'
* resolveAbility('did:*', 'did:key:zAlice', null) // => null
* resolveAbility('did:key:zAlice', 'did:key:zAlice', null) // => did:key:zAlice
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be resolveResource in these examples not resolveAbility?

@github-actions github-actions bot mentioned this pull request Feb 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support can: store/* like patterns in validators
3 participants