-
Notifications
You must be signed in to change notification settings - Fork 2
rfc: on-demand service authorization #68
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
Open
alanshaw
wants to merge
2
commits into
main
Choose a base branch
from
ash/rfc/service-authz
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,169 @@ | ||
| # Authorizing access to services | ||
|
|
||
| refs https://github.com/storacha/RFC/pull/67 | ||
|
|
||
| ## Problem | ||
|
|
||
| We've recently deployed UCAN authorized retrievals, which has triggered a number of realizations WRT authorizing access to services with UCANs. | ||
|
|
||
| For example, `space/index/add` causes the Indexing Service to fetch an index and add the hashes to it's IPNI chain (for internal network resolution). It is not authorized to fetch the index, so it can not fetch it! | ||
|
|
||
| This is just one of a number of authorizations needed within the network. It is not only authorized data retrievals that this problem affects. We authroize the upload service, indexing service and storage nodes to perform invocation on each other as well. The crux is that in order to execute a UCAN invocation, the issuer needs to prove they are authorized to perform the task. For that they need a delegation. | ||
|
|
||
| Authorizing services to talk to each other is happening more and more often as wel build out the network. Our current approach is to pre-authorize services, storing long lived delegations for use when needed. This is problematic because of a few reasons: | ||
|
|
||
| 1. Adding additional capabilities requires a service re-deployment or additonal orchestration to distribute new delegations. It can sometimes be a very manual and error prone process to ensure the right DIDs are used and the correct abilities are specified. | ||
| 1. The only way to prevent access (for example in a security breach) is to use revocations, which is considered a last resort. Ideally UCAN delegations should be issued when needed and be short lived so that we do not need to rely on revocations as heavily as we currently do. | ||
| 1. When we do not use pre-authorized delegations, it is cumbersome to attach additional required delegations to an invocation and extract them when the invocation is received. | ||
|
|
||
| ## Proposal | ||
|
|
||
| ### Authorize Access on Demand | ||
|
|
||
| The Upload Service already has a capability called `access/authorize`, which is used in the existing email-based authorization flow to request access to a space for an account (`did:mailto:`). | ||
|
|
||
| This RFC proposes we implement a very similar capability on Storage Nodes (Piri) and the Indexing Service. | ||
|
|
||
| You invoke `access/authorize` to obtain a delegation for the requested capabilities. | ||
|
|
||
| `access/authorize` is self signed, it does not need a delegation to invoke. It is up to the executor to decide whether they want to issue a delegation. | ||
|
|
||
| The caveats for `access/authorize` include the capability(s) requested (`can`, and optional `nb`) and an optional `cause` | ||
|
|
||
| ### Add `blob/retrieve` "service" capability | ||
|
|
||
| I'm proposing `blob/retrieve` as a new capability that allows retrieving a blob in full. It will be used for internal operations like replication, repair, indexing and filecoin onboarding - egress MUST NOT be recorded for these invocations. | ||
|
|
||
| #### What can use this for? | ||
|
|
||
| ##### Authroizing Storage Nodes to `blob/retrieve` on Storage Nodes | ||
|
|
||
| This is for replication purposes. The cause field will allow the receipient to validate the retrieval is for the purpose of replication. The cause should be the `blob/replica/allocate` invocation. | ||
|
|
||
| e.g. | ||
|
|
||
| ```js | ||
| { | ||
| iss: 'did:key:zStorageNodeAlice', | ||
| aud: 'did:key:zStorageNodeBob', | ||
| att: [{ | ||
| can: 'access/authorize', | ||
| with: 'did:key:zStorageNodeAlice', | ||
| nb: { | ||
| // requested capabilities | ||
| // Note: `with` is implied (did:key:zStorageNodeBob) | ||
| att: [{ | ||
| can: 'blob/retrieve', | ||
| nb: { | ||
| // can be specific or open ended | ||
| } | ||
| }] | ||
| } | ||
| }], | ||
| // invocation that caused the authorize request (attached to the invocation) | ||
| // i.e. `blob/replica/allocate` | ||
| cause: { "/": "bafy..." } | ||
| } | ||
| ``` | ||
|
|
||
| ##### Authroizing the Upload Service to `blob/allocate`, `blob/accept`, `blob/replica/allocate` on Storage Nodes | ||
|
|
||
| Upload Service just needs the storage node DID and URL. It can optionally store a delegation until it expires. | ||
|
|
||
| Storage Nodes will be set up to issue the delegation by allow-listing `did:web:up.storacha.network`. | ||
|
|
||
| e.g. | ||
|
|
||
| ```js | ||
| { | ||
| iss: 'did:web:up.storacha.network', | ||
| aud: 'did:key:zStorageNode', | ||
| att: [{ | ||
| can: 'access/authorize', | ||
| with: 'did:web:up.storacha.network', | ||
| nb: { | ||
| // requested capabilities | ||
| // Note: `with` is implied (did:key:zStorageNode) | ||
| att: [{ | ||
| can: 'blob/allocate', | ||
| nb: { | ||
| // can be specific or open ended | ||
| } | ||
| }, { | ||
| can: 'blob/accept', | ||
| nb: { | ||
| // can be specific or open ended | ||
| } | ||
| }, { | ||
| can: 'blob/replica/allocate', | ||
| nb: { | ||
| // can be specific or open ended | ||
| } | ||
| }], | ||
| // invocation that caused the authorize request (attached to the invocation) | ||
| // i.e. `space/blob/add` | ||
| cause: { "/": "bafy..." } | ||
| } | ||
| }], | ||
| exp: 12345 // now + 1 day or something? | ||
| } | ||
| ``` | ||
|
|
||
| ##### Authroizing Roundabout to `blob/retrieve`🆕 on Storage Nodes | ||
|
|
||
| Roundabout is used by Filecoin SPs to fetch data for inclusion in Filecoin deals. | ||
|
|
||
| e.g. | ||
|
|
||
| ```js | ||
| { | ||
| iss: 'did:web:roundabout.web3.storage', | ||
| aud: 'did:key:zStorageNode', | ||
| att: [{ | ||
| can: 'access/authorize', | ||
| with: 'did:web:roundabout.web3.storage', | ||
| nb: { | ||
| // requested capabilities | ||
| // Note: `with` is implied (did:key:zStorageNode) | ||
| att: [{ | ||
| can: 'blob/retrieve', | ||
| nb: { | ||
| // can be specific or open ended | ||
| } | ||
| }] | ||
| } | ||
| }] | ||
| } | ||
| ``` | ||
|
|
||
| ##### Authroizing the Indexing Service to `blob/retrieve`🆕 on Storage Nodes | ||
|
|
||
| Typically the indexing service requires a delegation to retrieve indexes on behalf of the user, however when content is _first_ uploaded and an index added, the indexing service needs to retrieve the index, cache the hashes and add them to it's own IPNI chain. At this point a `blob/retrieve` invocation might be appropriate. | ||
|
|
||
| Storage Nodes will be set up to issue the delegation by allow-listing `did:web:indexer.storacha.network`. | ||
|
|
||
| e.g. | ||
|
|
||
| ```js | ||
| { | ||
| iss: 'did:web:indexer.storacha.network', | ||
| aud: 'did:key:zStorageNode', | ||
| att: [{ | ||
| can: 'access/authorize', | ||
| with: 'did:web:indexer.storacha.network', | ||
| nb: { | ||
| // requested capabilities | ||
| // Note: `with` is implied (did:key:zStorageNode) | ||
| att: [{ | ||
| can: 'blob/retrieve', | ||
| nb: { | ||
| // can be specific or open ended | ||
| } | ||
| }], | ||
| // invocation that caused the authorize request (attached to the invocation) | ||
| // i.e. `assert/index` | ||
| cause: { "/": "bafy..." } | ||
| } | ||
| }] | ||
| } | ||
| ``` | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the current replication protocol contains a
blob/replica/transferinvocation, which is issued as a fork in the receipt forblob/replica/allocate. was the intent there to have that be actually send from the node that will receive the replica to the source node in order to replicate? If so maybe for at least that case no new capability is needed. I never was quite sure what blob/replica/transfer was for (other than maybe it was to simply track the copying)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is for tracking the copying.
The storage node has no authority to invoke
blob/replica/transferon the node hosting the data, so we still need to get a delegation for doing so.