Spec: Describe access revocation using Leave, Remove, Undo & Revoke activities (#164)

This commit is contained in:
fr33domlover 2023-01-31 14:25:52 +00:00
parent b08647d741
commit 9d37710764
3 changed files with 343 additions and 19 deletions

View file

@ -402,7 +402,9 @@ An actor that wishes to give other specific actors access to view or modify it
(or a child object of it), SHOULD do so according to the following
instructions.
### Object capabilities using Grant activities {#s2s-grant-flow}
### Object capabilities
#### Object capabilities using Grant activities {#s2s-grant-flow}
An Object Capability (or in short OCap or OCAP) is a token providing access to
certain operations on a certain resource. An actor wishing to act on a resource
@ -453,7 +455,45 @@ Requirements for the activity (referred below as *activity A*) sent in step 3:
within what the *resource actor* permits for the role specified by the
`Grant`'s [object][]
### Identifying resources and their managing actors
#### Disabling object capabilities and sending Revoke activities {#s2s-revoke}
At any point after an actor *A* publishes a [Grant][model-grant] in which it
grants some actor *B* access to a resource that actor *A* manages, actor *A*
MAY cancel that `Grant`, deciding it's no longer a valid OCAP to use via the
[capability][prop-capability] property of activies that actor *B* sends.
If actor *A* cancels such a `Grant`, it SHOULD publish and deliver, at least to
actor *B*, a [Revoke][act-revoke] activity notifying about the canceled
`Grant`. In the `Revoke` activity, actor *A* MUST provide at least one of the
following sets of properties:
1. Describe the `Grant`s being canceled:
- [object][]: the `Grant` activities being undone, i.e. the access
that they granted is now disabled
2. Describe the access being canceled:
- [origin][]: The actor whose access to the resource is being revoked, i.e.
actor *B*
- [instrument][]: The role or permission that the [origin][] actor had with
respect to accessing the resource, and which is now being taken away
- [context][]: The resource, access to which is being revoked
Actor *A* MAY provide both sets of properties. If it does, then:
- The `Revoke`'s `origin` MUST be identical to the `target` of every `Grant`
listed as an `object` in the `Revoke`
- The `Revoke`'s `instrument` MUST be identical to the `object` of every
`Grant` listed as an `object` in the `Revoke`
- The `Revoke`'s `context` MUST be identical to the `context` of every `Grant`
listed as an `object` in the `Revoke`
Once actor *A* publishes the `Revoke`, it MUST from now on refuse to execute
requests from actor *B* to access resources that actor *A* manages, coming as
activities that specify any of the canceled `Grant`s in the `capability`
property. If actor *A* receives such an activity from actor *B*, it SHOULD
publish and send back a [Reject][] activity, whose [object][] specifies the
activity that actor *B* sent.
#### Identifying resources and their managing actors
Some shared resources are themselves actors, and some shared resources aren't
actors, but they are child objects of actors. When some actor *A* wishes to
@ -472,7 +512,9 @@ Therefore any object that wishes to be specified as the [context][] of a
[Grant][act-grant] MUST either be an actor or be [managedBy][prop-managedby] an
actor.
### Initial Grant upon resource creation
### Granting access
#### Initial Grant upon resource creation
When an actor *A* requests to create a new shared resource *R*, and the
*resource actor* approves and creates it, then the *resource actor* SHOULD send
@ -489,7 +531,7 @@ specify the ID URI of the activity (published by actor *A*) that requested to
create resource *R* (typically this would be an [Offer][] activity, see
[Object Publishing and Hosting](#publishing)).
### Offering access using Invite activities
#### Offering access using Invite activities
When an actor *A* wishes to offer actor *B* access to resource *R* (where the
*resource actor* who manages *R* is neither *A* nor *B*), then actor *A* SHOULD
@ -519,7 +561,7 @@ Actor *B* can now use the URI of that new `Grant` as the
[capability][prop-capability] when it sends activities that access or
manipulate resource *R*.
### Requesting access using Join activities
#### Requesting access using Join activities
When an actor *A* wishes to request access to resource *R* (where the *resource
actor* who manages *R* isn't *A*), then actor *A* SHOULD use a
@ -607,6 +649,94 @@ So, once a `Join` is rejected (using an authorized `Reject`), it cannot be
accepted. But actor *A* MAY send a new `Join`, which could then possibly get
accepted.
### Revoking access
#### Taking away access using Remove activities
When an actor *A* wishes to cancel the membership of another actor *B* (who
isn't *A*) in a shared resource *R*, invalidating any active
[Grant][model-grant]s that the *resource actor* of *R* has granted to actor
*B*, then actor *A* SHOULD use a [Remove][] activity, and the following steps:
1. Actor *A* publishes and delivers a [Remove][], at least to actor
*B* and to the *resource actor* of *R*, with a relevant
[capability][prop-capability] (see [Modeling specification][model-remove]
for details on the properties to use)
2. The *resource actor* of *R* receives the `Remove` and:
a. Verifies the `Remove` is authorized, as described above in
[Object capabilities using Grant activities](#s2s-grant-flow)
b. Verifies that actor *B* indeed has active `Grant`s for accessing
resource *R*
c. Marks those Grants as disabled in its internal state
d. Publishes and delivers a [Revoke][model-revoke] activity, as described
above in
[Disabling object capabilities and sending Revoke activities](#s2s-revoke),
where [fulfills][prop-fulfills] specifies the `Remove`
Actor *B* SHOULD no longer use the URI of any `Grant` that has been disabled as
the [capability][prop-capability] when it sends activities that access or
manipulate resource *R*.
#### Waiving access using Leave activities
When an actor *A* wishes to cancel their membership in a shared resource *R*
(where the *resource actor* who manages *R* isn't *A*), invalidating any active
[Grant][model-grant]s that the *resource actor* of *R* has granted to actor
*A*, then actor *A* SHOULD use a [Leave][] activity, and the following steps:
1. Actor *A* publishes and delivers a [Leave][], at least to the
*resource actor* of *R* (see [Modeling specification][model-leave] for
details on the properties to use)
2. The *resource actor* of *R* receives the `Leave` and:
a. Verifies that actor *A* indeed has active `Grant`s for accessing
resource *R*
b. Marks those Grants as disabled in its internal state
c. Publishes and delivers a [Revoke][model-revoke] activity, as described
above in
[Disabling object capabilities and sending Revoke activities](#s2s-revoke),
where [fulfills][prop-fulfills] specifies the `Leave`
Actor *A* SHOULD no longer use the URI of any `Grant` that has been disabled as
the [capability][prop-capability] when it sends activities that access or
manipulate resource *R*.
#### Requesting to disable specific Grants using Undo
When an actor *A* wishes to deactivate a specific [Grant][model-grant] activity
(or multiple `Grant`s), providing access to view or manipulate some resource
*R* (where the *resource actor* of *R* isn't *A*), then actor *A* SHOULD use an
[Undo][] activity, and the following steps. The actor *B* to whom
access-to-resource-*R* was given by the `Grant` may be actor *A* itself, or
some other actor, as long as actor *A* is authorized by the *resource actor* of
*R* to deactivate that `Grant`.
NOTE: Upon a successful `Undo`, if actor *B* doesn't have any active `Grants`
left, that allow access to resource *R*, then the *resource actor* of *R* MAY
remove actor *B*'s membership in *R*, or it MAY consider actor *B* a member
without access.
1. Actor *A* publishes and delivers an [Undo][], at least to the
*resource actor* of *R* (see [Modeling specification][model-undo-grant] for
details on the properties to use)
2. The *resource actor* of *R* receives the `Undo` and:
a. Verifies the `Undo` is authorized, as described above in
[Object capabilities using Grant activities](#s2s-grant-flow)
b. Verifies that actor *B* indeed has all the active `Grant`s for accessing
resource *R*, that are listed as [object][]s of the `Undo` (if more than
one `Grant` is listed, the [target][] of all the `Grant`s MUST be
identical)
c. Marks all of those Grants as disabled in its internal state
d. Publishes and delivers a [Revoke][model-revoke] activity, at least to
actors *A* and *B*, as described above in
[Disabling object capabilities and sending Revoke activities](#s2s-revoke),
where:
- [object][] MUST specify all the deactivated `Grant`s
- [fulfills][prop-fulfills] MUST specify the `Undo`
Actor *B* SHOULD no longer use the URI of any `Grant` that has been disabled as
the [capability][prop-capability] when it sends activities that access or
manipulate resource *R*.
### Example
Aviva creates a new [Repository][type-repository] for her 3D Tree Growth
@ -866,6 +996,7 @@ Celine can now use this `Grant` to access the *treesim* repo.
[act-grant]: /vocabulary.html#act-grant
[act-push]: /vocabulary.html#act-push
[act-revoke]: /vocabulary.html#act-revoke
[type-repository]: /vocabulary.html#type-repository
[type-ticket]: /vocabulary.html#type-ticket
@ -881,15 +1012,22 @@ Celine can now use this `Grant` to access the *treesim* repo.
[model-grant]: /modeling.html#grant
[model-invite]: /modeling.html#invite
[model-join]: /modeling.html#join
[model-leave]: /modeling.html#leave
[model-push]: /modeling.html#push
[model-remove]: /modeling.html#remove
[model-revoke]: /modeling.html#revoke
[model-ticket]: /modeling.html#ticket
[model-undo-grant]: /modeling.html#undo-grant
[Accept]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-accept
[Create]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-create
[Invite]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-invite
[Join]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-join
[Leave]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-leave
[Offer]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-offer
[Reject]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-reject
[Remove]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-remove
[Undo]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-undo
[Image]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-image
[Note]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-note
@ -903,6 +1041,7 @@ Celine can now use this `Grant` to access the *treesim* repo.
[id]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-id
[inbox]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-inbox
[instrument]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-instrument
[origin]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-origin
[result]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-result
[summary]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-summary
[target]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-target

View file

@ -530,7 +530,9 @@ Example:
# Access Control
## Invite
## Giving Access
### Invite
To offer some actor access to a shared resource (such as a repository or a
ticket tracker), use an ActivityPub [Invite][] activity.
@ -572,7 +574,7 @@ Example:
}
```
## Join
### Join
To request access to a shared resource, use an ActivityPub [Join][] activity.
@ -611,7 +613,7 @@ Example:
}
```
## Grant
### Grant
To give some actor access to a shared resource, use a ForgeFed
[Grant][act-grant] activity.
@ -658,10 +660,157 @@ Example:
}
```
## Canceling Access
### Remove
To disable an actor's membership in a shared resource, invalidating their
access to it, use an ActivityPub [Remove][] activity.
Properties:
- [type][]: ["Remove"][Remove]
- [actor][]: The actor (person, bot, etc.) that is disabling access
disabled
- [object][]: The actor whose access to the resource is being taken away
- [origin][]: The resource, access to which is being taken away (for example, a
repository)
- [capability][prop-capability]: A previously published `Grant`, giving the
`actor` permission to disable the [object][] actor's access to the resource
Example:
```json
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://forgefed.org/ns"
],
"id": "https://dev.example/aviva/outbox/F941b",
"type": "Remove",
"actor": "https://dev.example/aviva",
"to": [
"https://dev.example/aviva/followers",
"https://coding.community/repos/game-of-life",
"https://coding.community/repos/game-of-life/followers",
"https://software.site/bob",
"https://software.site/bob/followers"
],
"origin": "https://coding.community/repos/game-of-life",
"object": "https://software.site/bob",
"capability": "https://coding.community/repos/game-of-life/outbox/2c53A"
}
```
### Leave
To withdraw your consent for membership in a shared resource, invalidating
your access to it, use an ActivityPub [Leave][] activity.
Properties:
- [type][]: ["Leave"][Leave]
- [actor][]: The actor (person, bot, etc.) that is requesting to disable their
own access
- [object][]: The resource, access to which is being disabled (for example, a
repository)
Example:
```json
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://forgefed.org/ns"
],
"id": "https://software.site/bob/outbox/d08F4",
"type": "Leave",
"actor": "https://software.site/bob",
"to": [
"https://coding.community/repos/game-of-life",
"https://coding.community/repos/game-of-life/followers",
"https://software.site/bob/followers"
],
"object": "https://coding.community/repos/game-of-life"
}
```
### Revoke
Another activity that can be used for disabling access is [Revoke][act-revoke].
While [Remove](#remove) and [Leave](#leave) are meant for undoing the effects
of [Invite](#invite) and [Join](#join), `Revoke` is provided as an opposite of
[Grant](#grant). See the Behavior specification for more information about the
usage of these different activity types in revocation of access to shared
resources.
Properties:
- [type][]: ["Revoke"][act-revoke]
- [actor][]: The actor (person, bot, etc.) that is revoking access
- [instrument][]: The role or permission that the [origin][] actor had with
respect to accessing the resource, and which is now being taken away
- [context][]: The resource, access to which is being revoked
- [origin][]: The actor whose access to the resource is being revoked
- [fulfills][prop-fulfills]: An activity that triggered the sending of the
`Grant`, such as a related `Remove` or `Leave`
- [object][]: specific [Grant](#grant) activities being undone, i.e. the access
that they granted is now disabled and it cannot be used anymore as the
[capability][prop-capability] of activities
Example:
```json
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://forgefed.org/ns"
],
"id": "https://coding.community/repos/game-of-life/outbox/1C0e2",
"type": "Revoke",
"actor": "https://coding.community/repos/game-of-life",
"to": [
"https://coding.community/repos/game-of-life/followers",
"https://software.site/bob",
"https://software.site/bob/followers"
],
"instrument": "https://roles.example/maintainer",
"context": "https://coding.community/repos/game-of-life",
"origin": "https://software.site/bob",
"object": "https://coding.community/repos/game-of-life/outbox/9fA8c"
}
```
### Undo a Grant {#undo-grant}
The Behavior spec describes flows in which the [Revoke](#revoke) activity is
used by resources (more accurately, by the actors managing them) to announce
that they're disabling [Grant](#grant)s that they previously sent. To allow for
a clear distinction, another activity is provided here, for *other* actors to
*request* the revocation of specific [Grant](#grant)s: The ActivityPub [Undo][]
activity.
It's likely that `Grant`s would exist behind-the-scenes in applications, and
human actors would then use activities such as `Remove` and `Leave` for
disabling access. But the ability to disable specific `Grant`s may be required
for ensuring and maintaining system security, therefore `Undo` is provided here
as well.
Properties:
- [type][]: ["Undo"][Undo]
- [actor][]: The actor (person, bot, etc.) that is revoking access
- [object][]: specific [Grant](#grant) activities being undone, i.e. the access
that they granted is now disabled and it cannot be used anymore as the
[capability][prop-capability] of activities
- [capability][prop-capability]: A previously published `Grant`, giving the
`actor` permission to disable the [object][] actor's access to the resource
[xsd:dateTime]: https://www.w3.org/TR/xmlschema11-2/#dateTime
[act-grant]: /vocabulary.html#act-grant
[act-push]: /vocabulary.html#act-push
[act-grant]: /vocabulary.html#act-grant
[act-push]: /vocabulary.html#act-push
[act-revoke]: /vocabulary.html#act-revoke
[type-branch]: /vocabulary.html#type-branch
[type-commit]: /vocabulary.html#type-commit
@ -704,10 +853,13 @@ Example:
[Create]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-create
[Invite]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-invite
[Join]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-join
[Leave]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-leave
[Note]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-note
[OrderedCollection]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-orderedcollection
[Object]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-object
[Person]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-person
[Remove]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-remove
[Undo]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-undo
[actor]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-actor
[attributedTo]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-attributedto
@ -720,6 +872,7 @@ Example:
[mediaType]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-mediatype
[name]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-name
[ordereditems]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-ordereditems
[origin]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-origin
[published]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-published
[relationship]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-relationship
[replies]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-replies

View file

@ -56,19 +56,49 @@ to a resource specified by [context][] under the role/permission specified by
"https://www.w3.org/ns/activitystreams",
"https://forgefed.org/ns"
],
"id": "https://example.dev/aviva/outbox/reBGo",
"id": "https://example.dev/myproject/outbox/reBGo",
"type": "Grant",
"actor": "https://example.dev/aviva",
"actor": "https://example.dev/myproject",
"to": [
"https://example.dev/aviva/followers",
"https://example.dev/aviva/myproject",
"https://example.dev/aviva/myproject/followers",
"https://example.dev/bob",
"https://example.dev/bob/followers"
"https://example.dev/myproject/followers",
"https://example.dev/users/aviva"
],
"object": "https://example.dev/roles/developer",
"context": "https://example.dev/aviva/myproject",
"target": "https://example.dev/bob"
"context": "https://example.dev/myproject",
"target": "https://example.dev/users/aviva"
}
```
### Revoke {#act-revoke}
**URI:** `https://forgefed.org/ns#Revoke`
**Notes:** Indicates that the [actor][] is canceling [target][]'s access to a
resource specified by [context][] under the role specified by [instrument][],
making the [Grant](#act-grant) activities specified by [object][] unusable
anymore in other activities' [capability](#prop-capability) field.
**Extends:** [Activity][]
**Example:**
```json
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://forgefed.org/ns"
],
"id": "https://example.dev/myproject/outbox/nlTxb",
"type": "Revoke",
"actor": "https://example.dev/myproject",
"to": [
"https://example.dev/myproject/followers",
"https://example.dev/users/aviva"
],
"object": "https://example.dev/myproject/outbox/reBGo",
"instrument": "https://example.dev/roles/developer",
"context": "https://example.dev/myproject",
"target": "https://example.dev/users/aviva"
}
```
@ -1594,12 +1624,14 @@ repository is a "push mirror" of).
[actor]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-actor
[content]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-content
[context]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-context
[instrument]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-instrument
[items]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-items
[mediaType]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-mediatype
[orderedItems]: https://www.w3.org/TR/activitystreams-core/#collections
[relationship]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-relationship
[source]: https://www.w3.org/TR/activitypub/#source-property
[subject]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-subject
[target]: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-target
[model-project]: /modeling.html#project
[model-repository]: /modeling.html#repository