Skip to content

Commit

Permalink
Renumber, expand store section
Browse files Browse the repository at this point in the history
  • Loading branch information
expede committed Oct 18, 2023
1 parent 12f5571 commit f9d1a1e
Showing 1 changed file with 48 additions and 39 deletions.
87 changes: 48 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ This specification defines the syntax and semantics of revoking a [UCAN Delegati

Using the [principle of least authority][POLA] such as certificate expiry and reduced capability scope SHOULD be the preferred method for securing a UCAN, but does not cover every situation. Revocation is a manual method for reversing a delegation. It cannot undo irreversible mutations (such as sending an email), but MAY limit misuse going forward. Revocation is the act of invalidating a UCAN after the fact, outside of the limitations placed on it by the UCAN's fields (such as its expiry).

Even when not in error at time of issuance, the trust relationship between a delegator and delegatee is not immutable. An agent can go rogue, keys can be compromised, and the privacy requirements of resources can (will!) change. While the UCAN Delegation approach RECOMMENDS using the [principle of least authority][POLA], unexpected conditions that require manual intervention do arise. These are exceptional cases, but are sufficiently important that a well defined method for performing revocation is nearly always desired in token and certificate systems.
Even when not in error at time of issuance, the trust relationship between a delegator and delegatee is not immutable. An agent can go rogue, keys can be compromised, and the privacy requirements of resources can (will!) change. While the UCAN Delegation approach recommends following the [principle of least authority][POLA], unexpected conditions that require manual intervention do arise. These are exceptional cases, but are sufficiently important that a well defined method for performing revocation is nearly always desired in token and certificate systems.

## 1.1 Approach
# 2 Approach

UCAN delegation is designed to be [local-first], partition-tolerant, cacheable, and latency-reducing. As such, [fail-stop] approaches are not suitable. Revocation is accomplished by delivery of an unforgeable message from a previous delegator.

Expand Down Expand Up @@ -104,36 +104,34 @@ flowchart RL
classDef revoked stroke:red,fill:#ff7676,color:red
```

# 2 Semantics
# 3 Semantics

UCAN revocation is the act of invalidating a proof in a delegation chain for some specific UCAN delegation by its CID. All UCAN capabilities are either claimed by direct authority over the resource, or by delegation chain terminating in that direct ("root") authority. Each link in a delegation chain contains an explicit issuer (delegator) and audience (delegatee).
Revocation is the act of invalidating a proof in a delegation chain for some specific UCAN delegation by its CID. All UCAN capabilities are either claimed by direct authority over the Subject, or by delegation chain terminating in that direct ("root") authority. Each link in a delegation chain contains an explicit issuer (delegator) and audience (delegatee).

Revocations MUST be immutable and irreversible. Recipients of revocations SHOULD treat them as a grow-only set (see the [eviction] section). If a revocation was issued in error, it MUST NOT be retracted — a new, unique UCAN delegation MAY be issued (e.g. by updating the nonce or changing the time bounds). This prevents confusion as the revocation moves through the network and makes [revocation stores] append-only and highly amenable to caching.
_Revocations MUST be immutable and irreversible._ Recipients of revocations SHOULD treat them as a monotonically-growing set. If a Revocation was issued in error, it MUST NOT be retracted — a new, unique UCAN delegation MAY be issued (e.g. by updating the nonce or changing the time bounds). This prevents confusion as the revocation moves through the network and makes [revocation stores] append-only and highly amenable to caching and gossip.

## 2.1 Scope
## 3.1 Scope

An issuer of a proof in a delegation chain MAY revoke access to the capabilities that it granted. Note that this is not the same as revoking the specific delegation signed by the issuer: any UCAN that contains a proof where the revoker matches the `iss` field — even transitively in the delegation chain — MAY be revoked.
An Issuer of a particaular Delegation in a proof chain MAY revoke that Delegation. Note that this is not always the same as revoking the Delegation they they Issued; any UCAN that contains a proof where the revoker matches the `iss` field — even transitively in the delegation chain — MAY be revoked.

Revocation by a particular proof does not guarantee that the principle no longer has access to the capability in question. If a principal is able to construct a valid proof chain without relying on the revoked proof, they still have access to the capability. By real-world analogy, if Mallory has two tickets to a film, and one of them is invalidated by its serial number, she is still able to present the valid ticket to see the film.

### 2.1.1 Example
Revocation of a particular proof does not guarantee that the Agent can no longer access to the capability in question. If an Agent is able to construct a valid proof chain without relying on the revoked proof, they still have access to the capability. By real-world analogy, if Mallory has two tickets to a film, and one of them is invalidated by its serial number, she is still able to present the valid ticket to see the film.

``` mermaid
flowchart TB
subgraph RA[Alice can revoke]
direction RL
AB["(Root)\niss: Alice\naud: Bob\niff[X,Y,Z]"]
AB["(Root)\niss: Alice\naud: Bob\niff: [X,Y,Z]"]
subgraph RB[Bob can revoke]
BC["iss: Bob\naud: Carol\niff [X,Y]"]
BD["iss: Bob\naud: Dan\niff[Y,Z]"]
BC["iss: Bob\naud: Carol\niff: [X,Y]"]
BD["iss: Bob\naud: Dan\niff: [Y,Z]"]
subgraph RC[Carol can revoke]
CD["iss: Carol\naud: Dan\niff[X,Y]"]
CD["iss: Carol\naud: Dan\niff: [X,Y]"]
subgraph RD[Dan can revoke]
DE["iss: Dan\naud: Erin\niff[X,Y,Z]"]
DE["iss: Dan\naud: Erin\niff: [X,Y,Z]"]
end
end
end
Expand All @@ -146,9 +144,9 @@ flowchart TB
DE -->|proof| BD
```

Here Alice is the root issuer / resource owner. Alice MAY revoke any of the UCANs in the chain, Carol MAY revoke the two innermost, and so on. If the UCAN `Carol to Dan` is revoked by Alice, Bob, or Carol, then Erin will not have a valid chain for the `X` capability, since its only proof is invalid. However, Erin can still prove the valid capability for `Y` and `Z` since the still-valid ("unbroken") chain `Alice to Bob to Dan to Erin` includes them. Note that despite `Y` being in the revoked `Carol to Dan` UCAN, it does not invalidate `Y` for Erin, since the unbroken chain also included a proof for `Y`.
Here Alice is the root Issuer. Alice MAY revoke any of the UCANs in the chain, Carol MAY revoke the two innermost, and so on. If the UCAN `Carol -> Dan` is revoked by Alice, Bob, or Carol, then Erin will not have a valid chain for the `X` capability, since its only proof is invalid. However, Erin can still prove the valid capability for `Y` and `Z` since the still-valid ("unbroken") chain `Alice to Bob to Dan to Erin` includes them. Note that despite `Y` being in the revoked `Carol -> Dan` UCAN, it does not invalidate `Y` for Erin, since the unbroken chain also included a proof for `Y`.

## 2.2 Consistency Models
## 3.2 Consistency Model

UCAN revocation is designed to work in the broadest possible scenarios, and as such needs very weak constraints. UCAN revocation MAY operate in fully eventually consistent contexts, with single sources of truth, or among nodes participating in consensus. The format of the revocation does not change in these situations; it is entirely managed by how revocations are passed around the network.
Weak assumptions enable UCAN to work with eventually consistent resources, such as [CRDT]s, [Git] forks, delay-tolerant replicated state machines, and so on.
Expand All @@ -157,31 +155,37 @@ These weak assumptions are often associated with being unable to guarantee deliv

Out of order delivery is typical of distributed systems. Further, a malicious user can otherwise delay revealing that they have a capability until the last possible moment in hopes of evading detection. Accepting revocations for resources that the agent controls prior to the delegation targeted by the revocation is received is thus RECOMMENDED.

# 3 Store

The agent that controls a resource SHOULD maintain a cache of revocations that it has seen. Agents are not limited to only storing revocations for resources that they control.
# 4 Store

During validation of a UCAN delegation chain, the [canonical CID] of each UCAN delegation MUST be checked against the cache. If there's a match, the relevant delegation MUST be ignored. Note that this MAY NOT invalidate the entire UCAN chain.
The Agent that controls a resource MUST maintain a cache of Revocations for which it is the Subject. The Agent MAY additionally cache gossiped Revocations about other Subjects as part of a [store and forward] mechanism.

## 3.1 Locality
During validation of a UCAN delegation chain, the [canonical CID] of each UCAN delegation MUST be checked against the cache. If there's a match, the relevant Delegation MUST be ignored. Note that this MAY NOT invalidate the entire UCAN chain.

Revocation caches SHOULD be kept as close to the resource they describe as possible.
``` json
// Pseudocode

Resources with a single source of truth SHOULD follow the typical approach of maintaining a revocation store at the same physical location as the resource. For example, a centralized server MAY have an endpoint that lists the revoked UCANs by [canonical CID].

For eventually consistent data structures, this MAY be achieved by including the store directly inside the resource itself. For example, a CRDT-based file system SHOULD maintain the revocation store directly at a well-known path.
const proofs = invocation.prf
const delegators = new Set(proofs.map(proof => proof.iss))

## 3.2 Eviction
proofs.forEach(delegation => {
// Is the proof in the revocation store?
store.lookup(delegation).then(revocation => {

Revocations MAY be deleted once the UCAN that they reference expires or otherwise becomes invalid through its proactive mechanisms.
// Is the revocation issuer in this proof chain?
if (delegators.has(revocation.iss)) {
throw new Error("Revoked")
}
})
})
```

A revocation store MUST keep UCAN revocations for UCANs that are otherwise still valid. For example, expired UCANs are already invalid, so a revocation MUST NOT affect this invalid status. Such revocations are redundant, and MAY be evicted from the store.
## 4.1 Locality

## 3.3 Expiry
Resources with a single source of truth SHOULD follow the typical approach of maintaining a revocation store at the same physical location as the resource. For example, a centralized server MAY have an endpoint that lists the revoked UCANs by [canonical CID].

Revocations MUST NOT expire.
For eventually consistent data structures, this MAY be achieved by including the store directly inside the resource itself. For example, a CRDT-based file system SHOULD maintain the revocation store directly at a well-known path.

## 3.4 Monotonicity
## 4.2 Monotonicity

Since Revocations MUST NOT be reverable, a new Delegation SHOULD be issued if a Revocation was issued in error.

Expand Down Expand Up @@ -218,7 +222,11 @@ flowchart LR
linkStyle 7 stroke:green
```

# 4 Delegation Ability
## 4.3 Eviction

Revocations MAY be evicted once the UCAN that they reference expires or otherwise becomes invalid through its proactive mechanisms, such as expiry (`exp`) plus some clock-skew buffer.

# 5 Delegating Revocation

The authority to revoke some Delegation MAY be itself delegated to a Principal not in the delegation chain. This is a normal delegation:

Expand Down Expand Up @@ -267,7 +275,7 @@ flowchart LR
```


# 5 Invocation Action
# 6 Invoking Revocation

A revocation Action MUST take the following shape:

Expand All @@ -279,7 +287,7 @@ A revocation Action MUST take the following shape:

Note that per [UCAN Invocation], the `nnc` field SHOULD is set to `""` since revocation is idempotent.

## 4.1 Arguments
## 6.1 Arguments

Being expressed as an Invocation means that Revocations MUST define an Action type for the command `ucan/revoke`.

Expand All @@ -288,7 +296,7 @@ Being expressed as an Invocation means that Revocations MUST define an Action ty
| `rev` | `&Delegation` | Yes | The CID of the [UCAN Delegation] that is being revoked |
| `pth` | `[&Delegation]` | No | [A delegation path] that includes the Revoker and the revoked Delegation |

### 4.1.1 Path Witness
### 6.1.1 Path Witness

Since all delegation chains MUST be rooted in a Delegation where the `iss` and `sub` fields are equal, the root Issuer is a priori in every delegation chain. This is not the case for sub-delegation. There are many paths through the authority network. For exmaple, take the following delegation network:

Expand All @@ -303,7 +311,7 @@ Mallory is not in the delegation chain of Erin. This is fine, since the semantic

Unlike Mallory, Bob, Carol, and Dan can both provide valid delegation paths that include Delegations that they have issued. Bob has two paths (`Alice -> Bob -> Dan -> Erin` or `Alice -> Bob -> Carol -> Erin`), and either will suffice.

# 5 Prior Art
# 7 Prior Art

[Revocation lists][Cert Revocation Wikipedia] are a fairly widely used concept.

Expand All @@ -319,7 +327,7 @@ While strictly speaking being about assertions rather than capabilities, [Verfia

[E][E-lang]-style [object capabilities][Robust Composition] use active network connections with [proxy agents][Robust Composition] to revoke delegations. Revocation is achieved by shutting down that proxy to break the authorizing reference. In many ways, UCAN Revocation attempts to emulate this behavior. Unlike UCAN Revocations, E-style object capabilities are [fail-stop] and thus by definition not partition tolerant.

# 6 Acknowledgements
# 8 Acknowledgements

Thank you [Blaine Cook] for the real-world feedback, ideas on future features, and lessons from other auth standards.

Expand Down Expand Up @@ -349,7 +357,7 @@ We want to especially recognize [Mark Miller] for his numerous contributions to

<!-- External Links -->

[Alan Karp]: https://github.com/alanhkarp
[Alan Karp]: https://github.com/alanhkarp
[Benjamin Goering]: https://github.com/gobengo
[Blaine Cook]: https://github.com/blaine
[Bluesky]: https://blueskyweb.xyz/
Expand Down Expand Up @@ -408,4 +416,5 @@ We want to especially recognize [Mark Miller] for his numerous contributions to
[did:key RSA]: https://w3c-ccg.github.io/did-method-key/#rsa
[external resource]: https://github.com/ucan-wg/spec#55-wrapping-existing-systems
[revocation]: https://github.com/ucan-wg/revocation
[store and forward]: https://en.wikipedia.org/wiki/Store_and_forward
[ucan.xyz]: https://ucan.xyz

0 comments on commit f9d1a1e

Please sign in to comment.