# Wildland sharing
## What is sharing in Wildland?
*Sharing* is granting an *access* to the *resource* for the entity identified with a key (can be a user, machine, script).
:::info
:question: Do we want to differentiate between sharing a *view* and *a snapshot* of the resource? If we share a container, **do we want to create a new container or storage that will be shared instead of the original one?** (I assume not; files would often need to be unnecessarily copied if that would be the case)
See why it is a valid question: we agreed that *read-only sharing of the forest* is in fact *read-only sharing of all the forest's containers metadata*. Newly created containers belonging to the forest will not be shared automatically for the people we shared the forest in the past.
:::
The opposite of sharing is *revoking* which is equally important term as sharing from the implementation point of view, thus it needs to be discussed together with sharing.
### What is an access?
There are 2 fundamental types of *accesses*:
1. *read-only (RO)*
1. *read-write (RW)*
All type of storages must support *read-write* access. *read-only* is not obligatory for every type of storage, as some may not support it. We may want to add more type of accesses in the future if there will be storages that implement those, i.e. *append-only*.
:::info
:question: Do we want to assume that every storage support *both* read-only and read-write? I guess we may want to support storages that don't offer read-only on the infrastructural/credentials level.
:::
### What is a resource?
Shared *resource* can be:
1. container, or actually its:
- metadata
- storage
1. directory
1. file
1. forest
Sharing any of those resources reduces to sharing container(s) under the hood, thus to fully describe Wildland's *sharing* concept, it is sufficient to understand:
1. how sharing a single container works,
1. how sharing of directory, file and forest maps into sharing a single container.
We will start with discussing sharing of the fundamental concept, which is sharing a container. Sharing of rest of the resources can be built on top of that.
## Sharing a container
A container represents either an encrypted directory, or a file on the remote storages (e.g. S3, Google Drive, Dropbox) mounted under set of paths. It is important to notice that sharing a container is thus *not* sharing a directory or file alone. Sharing a container is actually sharing an encrypted directory/file *with/without* its metadata that determines where to mount a file/directory and how to decrypt it. Containers metadata comprises of container's owner, mount paths among the others.
Both of container's metadata and container's storage credentials can be shared independently in *read-only (RO)* or *read-write (RW)* mode. There are actually 8 combinations of accesses for container sharing:
| | Metadata | Files on the storage | Comment |
| - | -------- | -------------------- | --------------------------------------------------------------------- |
| 1 | RO | RO | typically this is what we mean by sharing a 'RO container' |
| 2 | RO | RW | typically this is what we mean by sharing a 'RW container' |
| 3 | RW | RO | if we want other people to modify our paths but not the files |
| 4 | RW | RW | admin mode; oftentimes forest's `master` have this access combination |
| 5 | RO | - | files not shared at all - neither RO nor RW; just RO metadata |
| 6 | RW | - | files not shared at all - neither RO nor RW; just RW metadata |
| 7 | - | RO | metadata not shared at all - just RO credentials to the storage |
| 8 | - | RW | metadata not shared at all - just RW credentials to the storage |
Below we will introduce how scenarios 1-4 are implemented. Rest of the access scenarios (4-8) are analogous.
:::info
:question: RO/RW access for files kept in storage is implemented by encryption of the credentials that determine whether storage is RO/RW. Who is responsible for accepting or denying metadata modifications based on the forest's `signers`? ACB?
:::
:::info
:question: Are we going to mount individual storages under UUID different paths as it was in deprecated Wildland client? If we have syncer invariant, there is *theoretically* no point in mounting all storages under different paths.
:::
### Sharing a container with read-only (RO) both metadata and files
If a container is shared with read-only for both metadata and files, user needs to be able to decrypt:
- container's metadata (i.e. container's owner, paths, type)
- encryption key that is used to decrypt individual files kept in the storage
- *at least one* (possibly all:question:) container's storage that have read-only credentials and no RW storage is decryptable
:::info
:question: We need storage controller to give us read-only storage if all of the storages assigned to the container are RW, right? Once we have it, we (who?) need to copy shared files to the storage (how? it is read-only!) -- this is kind-of snapshot sharing. Possibly we want to always have one read-only storage in the container?
:::
:::info
:question: The person we share container with, knows the symmetric key that we are using for RW storage as well. She doesn't know credentials to RW storage though. But still... not feeling 100% safe as we are leaking a symmetric key here.
:::
#### Sharing algorithm
Scenario: *A* wants to share container *C* with *B* in with *read-only access for both metadata and files* kept in *C*.
Additionally, let's denote:
- *pub~B~* is *B*'s public key
- *S~c-meta~* is a symmetric key that *C*'s metadata are encrypted with
- *S~files~* is a symmetric key that files kept in container *C* are encrypted with
- *S~RO-storage~* is a symmetric key that read-only storage credentials are encrypted with
Algorithm:
- *A* needs to append:
- *pub~B~(S~C-meta~)* to the *C*'s metadata access list
- *pub~B~(S~files~)* to the *C*'s access list that determine who is able to decrypt file kept in *C*'s storages
- *pub~B~(S~RO-storage~)* to the any/all (:question:) of the *C*'s read-only storage access list(s)
:::info
:question: If we don't have read-only storage in the container, we need to request one from storage controller and copy the files there, effectively creating and sharing a snapshot, right?
:::
#### Revoking algorithm
Scenario: *A* wants to revoke *B*'s read-only access to *C*'s metadata and files.
Algorithm:
- *A* needs to remove:
- *pub~B~(S~C-meta~)* from the *C*'s metadata access list
- *pub~B~(S~files~)* from the *C*'s access list that detabitw|19ermine who is able to decrypt file kept in *C*'s storages
- *pub~B~(S~RO-storage~)* from all the *C*'s storage access lists
:::info
:question: How can we know which items from the `access` list to remove if they are all encrypted? We don't know which item belongs to which user/key.
:::
- *A* needs to pick new *S'~C-meta~* and re-encrypt *C*'s metadata
- *A* needs to encrypt *S'~C-meta~* with every public key from *C*'s metadata access list
- *A* needs to update credentials of the storages that were shared (storage controller help needed here:question:)
- *A* needs to pick new *S'~RO-storage~* and re-encrypt storages' credentials
- *A* needs to encrypt *S'~RO-storage~* with every public key from re-encrypted storages access list
Note here that we don't need to re-encrypt all of the revoked storages, as we are revoking access to the storages by updating their credentials. The files themselves can be still encrypted with the key that was already revealed for the revoked user.
### Sharing a container with read-only (RO) metadata and read-write (RW) files
The process of sharing and revoking a container with read-only (RO) metadata and read-write (RW) files is completely analogous to sharing a container with read-only (RO) both metadata and files.
It may be worth to notice that the person that the container was shared with, is able to overwrite or delete any of the sharer's files/directories. Any files modifications are be replicated on all of the RW storages attached to the shared container.
### Sharing a container with read-write (RW) metadata and read-only (RO) files
Container's metadata can be modified only if container's owner is in the forest's `signers` list.
:::info
:question: Who is going to decide if I can overwrite container's paths?
Example: if I'm listed in forest's `signers` list, then I'm allowed to modify any containers' metadata and save it in ACB. Will ACB verify the signature before saving? I assume yes, otherwise I would be able to overwrite any container's metadata.
:::
### Sharing a container with read-write (RW) both metadata and files
The process of sharing and revoking a container with read-write (RW) both metadata and files is completely analogous to sharing a container with read-write (RW) metadata and read-only (RO) files.
## Sharing a directory
Any directory within any storage can be represented by a container using container's `subdir` property, thus in order to share subdirectory of the container, we need to create another container pointing with `subdir` to the subdirectory we want to share. Now we just need to share the newly created container.
:::info
:question: How do we want to prevent accessing directories above the `subdir`? The person I shared my container's `subdir` with, can access any directory above `subdir` as she knows all the credentials and symmetric key that the storage is encrypted with.
:::
## Sharing a file
Sharing a file is analogous to sharing a directory, as a container can represent a single file.
## Sharing a forest
Read-only forest sharing is read-only (RO) sharing of its containers' metadata. Files are not shared at all.
Read-write forest sharing is not mapped on any container-related operation. Instead, it means updating the forest's `master`.
:::info
:question: We agreed that read-only forest sharing is actually read-only sharing of its containers' metadata. On the other hand, sharing a read-only container typically means sharing a read-only storage (no matter if metadata are RO or RW). This feels inconsistent.
:::
## Quirks
1. How do we want to make it possible to share a single directory from given container? I assume we need to create another *read-only* container for the copy of the given directory? *Read-only* in the sense that the person we shared the container with, will be not able to modify files of the original container.
1. Do we want to make RO and RW storages of the given container be in sync? (if not, then read-only sharing is effectively sharing a snapshot) Do we wanto to drop syncer invariant?
1. Let's say we have a container with one read-only storage. We will not be able to share it with read-write storage access, right? (or do we want to copy into another storage that will be read-write?)
1. How will be able to track who I shared my container with?
1. How can I track all containers that were shared with me?
1. What do we actually mean by mirrored forest concept? Is it still a valid idea?