⚠️ Warning: This documentation refers to the proof-of-concept implementation of Wildland client (opens new window) which is no longer maintained. We are currently working on a new Wildland client written in Rust. To learn more about Wildland and the current status of its development, please visit the Wildland.io webpage (opens new window).
# Access Control and Sharing
What's fundamental to Wildland's access control is that every manifest object (i.e. a container, storage, user or bridge object) has an owner. An owner is just a regular user who claims ownership of a manifest; thus digitally signs it using his private key.
This concept prevents these signed manifests from being tampered with and, in effect, secures the integrity of the manifest files. Every manifest file used in Wildland must be signed -- there are no exceptions to that.
# Manifests ownership
Each time you create an object, that object is signed by an owner. By default, it is signed by the default-owner, specified in
~/.config/wildland/config.yaml Wildland configuration file.
Create your own user first:
alice@wildland-client:~$ wl user create alice Generated key: 0xed4d4d28c275c4c2d611a7fac4a32193a5a85d1c9ea53dddc3110270563ceb7a # <- Alice's fingerprint No path specified, using: /users/alice Created: /home/user/.config/wildland/users/alice.user.yaml Using 0xed4d4d28c275c4c2d611a7fac4a32193a5a85d1c9ea53dddc3110270563ceb7a as @default Using 0xed4d4d28c275c4c2d611a7fac4a32193a5a85d1c9ea53dddc3110270563ceb7a as @default-owner Adding 0xed4d4d28c275c4c2d611a7fac4a32193a5a85d1c9ea53dddc3110270563ceb7a to local owners
Then, import user manifest of the user with whom you want to share your container (i.e. Bob's user manifest).
alice@wildland-client:~$ wl user im ~/Downloads/bob.user.yaml Created: /home/user/.config/wildland/users/bob.user.yaml Created: /home/user/.config/wildland/bridges/bob.bridge.yaml
alice@wildland-client:~$ wl container create mycontainer Created: /home/user/.config/wildland/containers/mycontainer.container.yaml alice@wildland-client:~$ wl container dump mycontainer object: container owner: '0xed4d4d28c275c4c2d611a7fac4a32193a5a85d1c9ea53dddc3110270563ceb7a' # <- Alice's fingerprint paths: - /.uuid/4f33d065-4cfe-438a-9541-6b8e5f130b9b backends: storage:  title: null categories:  version: '1'
Note that you cannot create a container, where the owner is a user, which you don't own.
alice@wildland-client:~$ wl container create another-container --owner bob Error: Secret key not found: 0xcb8678980faaf04cf7a88fc1310c93ace186be8de3e978c533d788435bdd2bba
# Manifests encryption
In the examples above the
wl container dump command has been used to print the container's contents. However, if you tried to simply read the container's file content, the result would be the following:
alice@wildland-client:~$ cat ~/.config/wildland/containers/mycontainer.container.yaml signature: | 0xed4d4d28c275c4c2d611a7fac4a32193a5a85d1c9ea53dddc3110270563ceb7a:gm4Pk0LvbV+u82SQZFA+nNj1e505VCbwNOQ70XGZXUWZKpqQenvcS79YiTOsnMYo34+Z+HV/1dZcYaFaZPcjDg== --- encrypted: encrypted-data: kuvZU28UpjHGCibUeXibcYMo9zCGhEoMTKXRIdxQ6SKkH7o/sMF/5U6f2iFl7jcvnEtPR2eY9r7+cTx9tAzmAs/3zBi5xpcbp11O4RMI12qu0JI5asfMoMH08HLqAAxQlt3BgUqiVWvbZ5bSUuGYnKStJV9Ur7FQjJ0m+a1VWKumOwyplEifMo4UYzHd4TLJjW2Vwzrs1Xuq4yS6ad+tE1GtSlI4K35a3x2ej2fmc5ZL4rmStvU3kV3fMizuDOtlrkzqLMfypIZu0HSbWLPsFdhRDbeAActD61LvktIkHnPTvgV1hny3Hpb0LKmb407h45fSNP9yqTk0NUM= encrypted-keys: - VkcXCwEs/dCACFcBt9sYsSAyJXhOrLo6PjWO4vhZPhcvCrxZ6QezZuq+Ju4+dJ72J1xqbjckV/LmU4eCVzbQ/vTgEuOCvaHL+cnoKUDW+IQ=
Nowhere close to a pretty output from the previous section. That is because, by default, every manifest file is encrypted using the owner's public key. In consequence, only the owner is now be able to decrypt the contents.
If the manifest was to be shared publicly, you wouldn't want to encrypt it at all. To disable this protection, use the following command:
alice@wildland-client:~$ wl container modify --no-encrypt-manifest mycontainer Saved: /home/user/.config/wildland/containers/mycontainer.container.yaml re-publishing container /.uuid/4f33d065-4cfe-438a-9541-6b8e5f130b9b... alice@wildland-client:~$ cat ~/.config/wildland/containers/mycontainer.container.yaml signature: | 0xed4d4d28c275c4c2d611a7fac4a32193a5a85d1c9ea53dddc3110270563ceb7a:SB14LrxF4Scq9uL9h0xWZ4r3SbqzXgyKNKKzcaYhlNJYMyHNRfiWE2kpBeHbwIBZuUj1FsEgV1coGoo5Jo2QDQ== --- object: container owner: '0xed4d4d28c275c4c2d611a7fac4a32193a5a85d1c9ea53dddc3110270563ceb7a' paths: - /.uuid/4f33d065-4cfe-438a-9541-6b8e5f130b9b backends: storage:  title: null categories:  version: '1' access: - user: '*'
Note that the manifest contents are now in plain text (thanks to the
access field which wasn't present in the
wl container dump from the previous section). Nonetheless, the integrity of the manifest contents is still protected by the
The same result could be achieved by using the
--no-encrypt-manifest flag when creating a container.
alice@wildland-client:~$ wl container create unencrypted-container --no-encrypt-manifest Created: /home/user/.config/wildland/containers/unencrypted-container.container.yaml alice@wildland-client:~$ cat ~/.config/wildland/containers/unencrypted-container.container.yaml signature: | 0xed4d4d28c275c4c2d611a7fac4a32193a5a85d1c9ea53dddc3110270563ceb7a:IYQZ1wRGT+kpJZ1NRp3FlxsvmaM6PzGsr8959qj+x2ozHSZ/nZ+JElJkgsVvofeCewIj1Z1rrILWZxyGrSCdCA== --- object: container owner: '0xed4d4d28c275c4c2d611a7fac4a32193a5a85d1c9ea53dddc3110270563ceb7a' paths: - /.uuid/1323436a-5044-44ef-b8cf-9ad91e3ca123 backends: storage:  title: null categories:  version: '1' access: - user: '*'
# Selective access control
The previous sections have shown that the manifest can either be encrypted by the manifest owner or unencrypted. This section shows that you can also define
access selectively, by specifying users who may read the contents of an encrypted file by using the
Note: If you have already followed Forest Creation in Quick Start Guide, the container will automatically be published to Alice's infrastructure unless the
--no-publish flag is passed.
alice@wildland-client:~$ wl container create alice-and-bob --access bob --path /very/secret Created: /home/user/.config/wildland/containers/alice-and-bob.container.yaml
Let's add some dummy storage to the container so that it's not mounting a void:
alice@wildland-client:~$ wl storage create dummy --container alice-and-bob Using container: /home/user/.config/wildland/containers/alice-and-bob.container.yaml (/.uuid/b1cffd57-f0c2-4b04-911d-5e709dd53a30) Adding storage e09e7cb0-db67-4888-9753-afd96b901a21 to container. Saved container /home/user/.config/wildland/containers/alice-and-bob.container.yaml alice@wildland-client:~$ cat ~/.config/wildland/containers/alice-and-bob.container.yaml signature: | 0xed4d4d28c275c4c2d611a7fac4a32193a5a85d1c9ea53dddc3110270563ceb7a:kMJUCbajjgAArIzLS6uzrUCVVLxRd++SfJPsFpvgwixXBX+k5YaWPKXAHT9IeK9cShZXeTeCcEnAeDfsakR7Ag== --- encrypted: encrypted-data: 7KltiablURhv/hKZROQblr4SS6QTbHwBegmuHSxb499LkeKVw/1yvDcczyJMmO5svtFJAsEkc0dOm9CvSXGzFTJSmOQk0EmnzNVeDVUmQxXmAIKtGdIzJEz+2AA1Y9R22+Ac0O32DNcnnqHGidBxfHIpGIdCWeh3uFuA+4E08Mixjw9TzpP6jmk8KMIULklcYctd1AQ0hR39VxpMkGbQswHx48YbnLmvYcbaa0cnE60ueg7lMQuk1Jhq+ekm0U7r8SQPruXbxYTbbKk2OXbFQmdZcd8NZ271She5EWwIZ2wChAzJcBcS7po4rvDnhTvhDtS+LIoqM1wVrGDdTnK5SvLam0vDIRWlEBFMWiCcjQXTL1GGNYl366bKNQyGAAQp24WGIw1ZY8EU2I6KTsSyOdDmRWKhvxOlenM8bHjQ6dIdgE6ZmrzhwGeSxFnvLXvTpJ+R9Lvxggf3bDVHG6OH encrypted-keys: - M4+7tAy26MEhEs2i7x6Xz/jthhMm+IIDHXhLM4Scg1M+lsInDktax3AznivQAxvqbDc4Gd8WHQskPDZK02y5kt9uTQ3HQNwNRBKNb+zdSBQ= - yKcdhW9/QrtCsfQuotsDBUNL+2ySoiV5WFr1vRO61iHqCrd6MLwqx0zkE4bCtYJQ8CqjCkGFklzKnPdolyYqsz+Iv9I7oAeb5CYI3gQaW98=
The container created above was created with
--access bob but the container was called
alice-and-bob. That is because Alice is the default-owner of every container (unless overridden by the
--owner flag) and every encrypted container will always be encrypted with the container owner's public key. Using the
--access bob flag merely allowed Bob additional access to the container instead of granting him exclusive access to read the contents.
The reason for such mechanics is that Alice is signing the contents of the container using her private key; hence she'd definitely like to know what she is signing, which she wouldn't know, if she wasn't able to decrypt the contents.
Note that the
encrypted-keys field has two entries which implies that there are two users, who are able to decrypt the
encrypted-data block. Is it not possible though to know to whom those encrypted keys belong.
# Sharing a container
After creating the
alice-and-bob container, Alice would now like to share this container with Bob. She would not just send the file to bob via email for two reasons:
- The container is still owned by Alice so bob wouldn't be able to make any changes to it,
- Every time alice makes some changes to that container, she would have to send it to Bob again. This would be even more difficult if the container was shared by more than just Alice and Bob.
Instead, Alice** wants to use her Forest's catalog to publish her container. A catalog is a special usecase for a Wildland container, and its purpose is to store the containers of a particular user (ie. Alice's). A catalog is automatically created and appended to a user's manifest during Forest Creation so make sure you have already set up a Forest before moving to the next section. Suggested storage would be a remote one (i.e. not
local) so that Bob can access it from his own PC (unless Alice and Bob share a local filesystem's catalog, e.g. via sshfs).
When creating Alice's forest, make sure to also include the
--access bob flag, otherwise Bob will not have access to it. You can do it like this:
alice@wildland-client:~$ wl forest create --access bob ...
See the "Infrastructure-level control" section below for more details.
# Container publishing
Alice can now publish her container to the catalog's storage:
alice@wildland-client:~$ wl container publish alice-and-bob publishing container /.uuid/b1cffd57-f0c2-4b04-911d-5e709dd53a30...
If you got the following error:
Error: Cannot find any container suitable as publishing platform:
it means that your user does not have writable storage in their
manifests-catalog. Make sure you created the Forest by following Forest Creation.
# Accessing shared container
Once Alice has shared her user manifest with Bob, he can now import her user file and access the containers shared by her. Make sure that Bob has sufficient access to read the catalog container as well as the user
manifests-catalog within Alice's user manifest.
bob@wildland-client:~$ wl user import --path /forests/alice ~/Downloads/alice.user.yaml Created: /home/user/.config/wildland/users/alice.user.yaml Created: /home/user/.config/wildland/bridges/alice.bridge.yaml
Bob can now mount the container shared by Alice:
bob@wildland-client:~$ wl container mount :/forests/alice:/very/secret: Loading containers. Loaded 1... Mounting 1 container
# Infrastructure-level control
One of the very important things to consider before exposing your Forest into the world, is to make sure that the containers (ie. your Forest) you're exposing publicly do not reveal secret credentials to unauthorized people.
In the publishing example above Alice must have had her Forest already created. Let's assume she used WebDAV as a storage template to provision her Forest. If that was the only storage she used to create her Forest, there's a great chance that if she wants to share that Forest with the world, she'll be granting read-write (RW) access to that Forest due to the fact that most WebDAV implementations are either full-read-only (full-RO) or full-RW. If that was Alice's intention to share RW access with Bob, then she wouldn't have to change anything apart from making sure that all of the container's storages are encrypted using her key (by default) as well as Bob's key.
Another scenario would be that Alice wants to share her Forest with a public audience for RO but she wants to keep the RW access to herself (obviously). In such a scenario, she would have to create her Forest using a storage template with at least two storages -- one being RO storage with
--access set to
*, and one being RW storage with access set to Alice.
In order to do that, let's pick a storage backend that natively supports RO/RW access control, for example S3, and create a template pointing to the same bucket, but with different credentials and access control. You can follow the S3 storage guide to learn how to create such a bucket.
To distinguish the new use case, in this section we'll use Caroline/Daniel instead of Alice/Bob.
caroline@wildland-client:~$ wl user create caroline Generated key: 0xeb0c9dc091eee7797e27f6ee50a6ab24c6bb38bf2ce9dff0e831825fe43d1298 No path specified, using: /users/caroline Created: /home/user/.config/wildland/users/caroline.user.yaml Using 0xeb0c9dc091eee7797e27f6ee50a6ab24c6bb38bf2ce9dff0e831825fe43d1298 as @default Using 0xeb0c9dc091eee7797e27f6ee50a6ab24c6bb38bf2ce9dff0e831825fe43d1298 as @default-owner Adding 0xeb0c9dc091eee7797e27f6ee50a6ab24c6bb38bf2ce9dff0e831825fe43d1298 to local owners
caroline@wildland-client:~$ wl template create s3 carolines-s3 \ --s3-url s3://carolines-bucket \ --access-key <RW_KEY> \ --secret-key <RW_SECRET> \ --access caroline Storage template [carolines-s3] created in /home/user/.config/wildland/templates/carolines-s3.template.jinja caroline@wildland-client:~$ wl template add s3 carolines-s3 \ --s3-url s3://carolines-bucket \ --access-key <RO_KEY> \ --secret-key <RO_SECRET> \ --access '*' \ --read-only Appended to an existing storage template [carolines-s3]
Now create a Forest using the newly created template:
caroline@wildland-client:~$ wl forest create --access '*' carolines-s3 Created base path: /.manifests/3779a663-1099-4a11-9ae3-55e27eecf15d Adding storage a3e57467-90f7-4916-92f0-d5b6479b783c to container. Saved container /home/user/.config/wildland/containers/caroline-forest-catalog.container.yaml Adding storage fb335029-125a-4a5f-bcad-7a75127c2e57 to container. Saved container /home/user/.config/wildland/containers/caroline-forest-catalog.container.yaml Saved: /home/user/.config/wildland/users/caroline.user.yaml Saved: /home/user/.config/wildland/users/caroline.user.yaml
The next step would be creating an unencrypted (as it's supposed to be publicly readable) container, using the same storage template Caroline used for her Forest. She definitely could use a different bucket to store her Forest's manifests and actual data, but for this demo we will use the same bucket.
caroline@wildland-client:~$ wl container create hello-world \ --no-encrypt-manifest \ --path /hello/world \ --template carolines-s3 Created: /home/user/.config/wildland/containers/hello-world.container.yaml Created base path: /ba4e53a2-d049-4bf9-92b4-c15f340fd28f Adding storage df71a0fb-6c3f-4658-8234-e7a5eceace14 to container. Saved container /home/user/.config/wildland/containers/hello-world.container.yaml Adding storage 9c224edb-36dc-4082-a8a3-7bfa6b8ceafb to container. Saved container /home/user/.config/wildland/containers/hello-world.container.yaml publishing container /.uuid/ba4e53a2-d049-4bf9-92b4-c15f340fd28f...
Caroline now mounts her newly created container to feed it with some data:
caroline@wildland-client:~$ wl c mount :/hello/world: Loading containers. Loaded 1... Mounting 1 container caroline@wildland-client:~$ echo 'It works!' > ~/wildland/hello/world/Hello-World.md
It's time to share the Forest with others. To do that, we need to somehow distribute Caroline's manifest publicly, similar to how Golem Foundation's Ariadne Forest is shared. Before we do that, let's take a look at Caroline's user manifest file.
caroline@wildland-client:~$ cat ~/.config/wildland/users/caroline.user.yaml signature: | 0xeb0c9dc091eee7797e27f6ee50a6ab24c6bb38bf2ce9dff0e831825fe43d1298:IANX1QStKc1F3CZe8mGDELF//bo1QzYMXX2cIQ6W/NQjaoNz+GP5aWeHK+Sf2WYTUZq0IK2F2oaanE2yBXPiDQ== --- object: user owner: '0xeb0c9dc091eee7797e27f6ee50a6ab24c6bb38bf2ce9dff0e831825fe43d1298' paths: - /users/caroline manifests-catalog: - object: link file: /.manifests.yaml storage: encrypted: encrypted-data: Otm4eFpF8Jo4OY5OJ0GmbGS6UYQjmiXfxd4EEnRSMHsAViqNCrnTF07k/1WdoXHpVitTr4ryucQZEhPsfyrmCB3oxOQJgbe9NUw24I5Lg4G+YlyasYwAWiZYjgL6/1iUj512U+6EPFkF9cf597nTWj+xS1DnrIbYVYlJ3/FJy4n5uYD1uWjeTgM8bGGL8i/orWpbiFbH3nACFgmf8pAbTvY/4QUioDoZveu8gRXIUIQvy5ftB4NYdQMJ1/e23GQamBTAyIIOsPokAJF9gEtvlE0/WygnFHb7Rsty+XF/cjq8D7FKN6NnoTuz7N66IN4beh+59L6xt48W0GUrX7BbBcGXIVrDL6D3d0FHl1K3q01UZAu6PKgwUd0GOXyOX13tW5y3ZMZ4gDrmj2KBMAxQH4PPOl4A37CPMDKquaZGvmsAxQvXkRG5vhQFWbhLqKtchaWusOaS9yI8trdUFt3B+A29xvQbHzBkdlIRwGwlg8vTyzQ5ZSD9FhAm8ucg9MHQNT9Ztnuqa4XELotEMpPV5ZDFbw+ELTiNLgjoUusSbAhCiXwyAHoaz/CeXmFN5qx5UbD78ii59i/79yoTwxYHJG3bwNNcFibGJgPtNRLawXsljbk1fFHm+GFN encrypted-keys: - OX6vj4O787WjVQL9L2YJC6ulPwi3ZvH+kCWu6jmA+X72sLTtNVrCm07rG+mumSLc667jNDky7HNmJHnuIxredpkpX67xFBf97GrABSttItQ= - object: link file: /.manifests.yaml storage: access: - user: '*' credentials: access-key: <REDACTED> secret-key: <REDACTED> read-only: true s3_url: s3://carolines-bucket/.manifests/3779a663-1099-4a11-9ae3-55e27eecf15d type: s3 with-index: false backend-id: fb335029-125a-4a5f-bcad-7a75127c2e57 manifest-pattern: type: glob path: /*.yaml pubkeys: - RWQXe4H8E4l3zz9il7pfbCMbR8uK/f//2qixKbMpsn005zRGoHkhRbC/0vOr94MM5DtErsRj8oLeVg2UCqLOhBo4 version: '1'
As you can see, the top storage is encrypted, and that's Caroline's RW storage. The RO storage is unencrypted, and for that reason it's going to be accessible by anyone who gets hold of the user's manifest.
Now let's move to Daniel's machine, who's already downloaded Caroline's user manifest.
daniel@wildland-client:~$ wl user import ~/Downloads/caroline.user.yaml \ --path /f/caroline Created: /home/user/.config/wildland/users/caroline.user.yaml WARNING:user:User 0xeb0c9dc091eee7797e27f6ee50a6ab24c6bb38bf2ce9dff0e831825fe43d1298: cannot load manifests catalog entry: Cannot decrypt manifest: decryption key unavailable Created: /home/user/.config/wildland/bridges/caroline.bridge.yaml
Note: The WARNING presented in the output above indicates that there was a RW storage which Daniel couldn't decrypt. This warning, unfortunately, is a work in progress and will be present in many commands that operate on Caroline's Forest. These warnings do not interrupt the flow of accessing the Forest.
Time to mount the Forest and see if Daniel has RO access:
daniel@wildland-client:~$ wl forest mount :/f/caroline: User 0xeb0c9dc091eee7797e27f6ee50a6ab24c6bb38bf2ce9dff0e831825fe43d1298 already exists. Forcing user import. Created: /home/user/.config/wildland/users/caroline.user.yaml WARNING:user:User 0xeb0c9dc091eee7797e27f6ee50a6ab24c6bb38bf2ce9dff0e831825fe43d1298: cannot load manifests catalog entry: Cannot decrypt manifest: decryption key unavailable Loading containers. Loaded 2... Mounting 2 containers daniel@wildland-client:~$ cd ~/wildland/f/caroline\:/hello/world/ daniel@wildland-client:~/wildland/f/caroline:/hello/world$ cat Hello-World.md It works! daniel@wildland-client:~/wildland/f/caroline:/hello/world$ echo 'Can I write here?' > daniels.md bash: daniels.md: Permission denied
Caroline has securely shared her Forest with the world!