Skip to content

Commit

Permalink
Gateway: Render private bucket content via access tokens (#357)
Browse files Browse the repository at this point in the history
* docs: fix a couple nits

Signed-off-by: Sander Pick <[email protected]>

* buckets: add access token to private bucket links

Signed-off-by: Sander Pick <[email protected]>

* mod: update threads

Signed-off-by: Sander Pick <[email protected]>

* docs: update readme with access role info

Signed-off-by: Sander Pick <[email protected]>

* docs: update readme with more links to godocs

Signed-off-by: Sander Pick <[email protected]>

* gateway: pass token through to bucket UI

Signed-off-by: Sander Pick <[email protected]>
  • Loading branch information
sanderpick authored Sep 24, 2020
1 parent 400329a commit 3101199
Show file tree
Hide file tree
Showing 21 changed files with 257 additions and 156 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2019 textile.io
Copyright (c) 2018-2020 textile.io

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
73 changes: 61 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
[![GitHub action](https://github.com/textileio/textile/workflows/Tests/badge.svg?style=popout-square)](https://github.com/textileio/textile/actions)
[![standard-readme compliant](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=popout-square)](https://github.com/RichardLitt/standard-readme)

> Textile services and buckets lib written in Go
> Textile hub services and buckets lib
Textile connects and extends [Libp2p](https://libp2p.io/), [IPFS](https://ipfs.io/), and [Filecoin](https://filecoin.io/). Three interoperable technologies makeup Textile:

Expand Down Expand Up @@ -42,6 +42,7 @@ Join us on our [public Slack channel](https://slack.textile.io/) for news, discu
* [Resetting bucket contents](#resetting-bucket-contents)
* [Watching a bucket for changes](#watching-a-bucket-for-changes)
* [Protecting a file with a password](#protecting-a-file-with-a-password)
* [Sharing bucket files and folders](#sharing-bucket-files-and-folders)
* [Creating a Filecoin bucket archive](#creating-a-filecoin-bucket-archive)
* [Multi-writer buckets](#multi-writer-buckets)
* [Deleting a bucket](#deleting-a-bucket)
Expand Down Expand Up @@ -101,7 +102,7 @@ go get ./cmd/hub

**Note**: `hub` _includes_ `buck` as a subcommand: `hub buck`. This is because `hubd` hosts `buckd`, along with other services.

`hub` is built in part on the gRPC client, which can be imported to an existing project:
`hub` is built in part on the [gRPC client](https://pkg.go.dev/github.com/textileio/textile/api/hub/client), which can be imported to an existing project:

```
import "github.com/textileio/textile/api/hub/client"
Expand Down Expand Up @@ -132,7 +133,7 @@ cd textile
go get ./cmd/buck
```

`buck` is built in part on the gRPC client, which can be imported in an existing project:
`buck` is built in part on the [gRPC client](https://pkg.go.dev/github.com/textileio/textile/api/buckets/client), which can be imported in an existing project:

```
import "github.com/textileio/textile/api/buckets/client"
Expand All @@ -144,6 +145,8 @@ import "github.com/textileio/textile/api/buckets/client"
import "github.com/textileio/textile/buckets/local"
```

The full spec is available [here](https://pkg.go.dev/github.com/textileio/textile/buckets/local).

## Getting Started

### The Hub
Expand Down Expand Up @@ -173,11 +176,14 @@ Available Commands:
login Login
logout Logout
orgs Org management
pow Interact with Powergate
threads Thread management
update Update the hub CLI
version Show current version
whoami Show current user
Flags:
--api string API target (default "api.textile.io:443")
--api string API target (default "api.hub.textile.io:443")
-h, --help help for hub
-o, --org string Org username
-s, --session string User session token
Expand All @@ -201,10 +207,10 @@ BUCK_LOG_DEBUG=true
Copy [this compose file](https://github.com/textileio/textile/blob/master/cmd/buckd/docker-compose.yml) and run it with the following command.

```
docker-compose -f docker-compose.yml up
docker-compose -f docker-compose.yml up
```

Congrats! You now have Buckets running locally.
Congrats! Now you have Buckets running locally.

The Docker Compose file starts an IPFS node, which is used to pin bucket files and folders. You could point `buckd` to a different (possibly remote) IPFS node by setting the `BUCK_ADDR_IPFS_API` variable to a different multiaddress.

Expand Down Expand Up @@ -271,9 +277,9 @@ The first URL is the link to the ThreadDB instance. Internally, a collection nam

The second URL is the bucket's unique IPNS address, which is auto-updated when you add, modify, or delete files.

If you have configured the daemon with DNS settings, you will see a third URL that links to the bucket's WWW address, where it is rendered like as a static website / client-side application. See `buckd --help` for more info.
If you have configured the daemon with DNS settings, you will see a third URL that links to the bucket's WWW address, where it is rendered as a static website / client-side application. See `buckd --help` for more info.

**Note**: If your bucket is private (encrypted), these links will 404 on the gateway. This behavior is temporary while ThreadDB ACLs are [still under development](https://github.com/textileio/go-threads/issues/295).
**Important**: If your bucket is private (encrypted), an access token (JWT) will be appended to these links. This token represents your _identity_ across ***all buckets*** and should not be shared without caution.

`buck init` created a configuration folder in `mybucket` called `.textile`. This folder is somewhat like a `.git` folder, as it contains information about the bucket's remote address and local state.

Expand Down Expand Up @@ -562,7 +568,7 @@ buck encrypt hello.txt supersecret > secret.txt
`encrypt` only works on local files. You'll have to use `push` to sync the new file to the remote.

```
hub buck push --yes
buck push --yes
+ secret.txt: bafkreiayymufgaut3wrfbzfdxiacxn64mxijj54g2osyk7qnco54iftovi
> bafybeidhffwg5ucwktn7iwyvnkhxpz7b2yrh643bo74cjvsbquzpdgpcd4
```
Expand All @@ -576,6 +582,51 @@ hello world

Looks like it worked!

### Sharing bucket files and folders

Bucket contents can be shared with other Hub accounts and users using the `buck roles` command. Each file and folder in a bucket maintains a set of public-key based access roles: `None`, `Reader`, `Writer`, and `Admin`. Only the `Admin` role can add and remove files and folders from a shared path. See `hub buck roles grant --help` for more about each role. For most applications, access roles only makes sense in the context of the Hub.

By default, public buckets have two roles located at the top-level path:

```
hub buck roles ls
IDENTITY ROLE
* Reader
bbaareibzpb44ahd7oieqevvlqajidd4jajcvx2vdvti6bpw5wkqolwwerm Admin
> Found 2 access roles
```

Since access roles are inherited down a bucket path, the single admin role grants the owner full access to all current and future files and folders. The default (`*`) `Read` role indicates that the entire bucket is open to the world. This is merely a reflection of the fact that the underlying UnixFS directory behind public (non-encrypted) buckets are discoverable on the IPFS Network.

Private buckets are not open to the world and are created with only the single admin role. However, we can still grant default (`*`) `Read` access to individual files, folders, or the entire bucket posteriori.

```
hub buck roles grant "*" myfolder
Use the arrow keys to navigate: ↓ ↑ → ←
? Select a role:
None
▸ Reader
Writer
Admin
```

We can now see a new role added to `myfolder`.

```
hub buck roles ls myfolder
IDENTITY ROLE
* Reader
> Found 1 access roles
```

Similarly, grant the `None` role to revoke access.

Manipulating access roles for a single Hub account or user (public key) can be cumbersome with the `buck` CLI. Applications in need of this level of granular access control should do so programmatically using the [Go client](https://pkg.go.dev/github.com/textileio/textile/api/buckets/client), [JavaScript client](https://textileio.github.io/js-hub/docs/hub.buckets).

### Creating a Filecoin bucket archive

Bucket archiving requires a Powergate to be running in `buckd`. If you're curious how to do this, take a look at [this Docker Compose file](https://github.com/textileio/textile/blob/master/integrationtest/pg/docker-compose.yml).
Expand All @@ -599,7 +650,7 @@ You should see a success message if you proceed.
This means that archiving has been initiated. It may take some time to complete...

```
hub buck archive status
buck archive status
> Archive is currently executing, grab a coffee and be patient...
```

Expand Down Expand Up @@ -823,8 +874,6 @@ for s := range state {

Similarly, use `WatchSentbox` to watch a sentbox.



## Developing

The easiest way to develop against `hubd` or `buckd` is to use the Docker Compose files found in `cmd`. The `-dev` flavored files do not persist repos via Docker Volumes, which may be desirable in some cases.
Expand Down
7 changes: 4 additions & 3 deletions api/buckets/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,11 @@ func (c *Client) Root(ctx context.Context, key string) (*pb.RootResponse, error)
})
}

// Links returns a list of links that can be used to view the bucket.
func (c *Client) Links(ctx context.Context, key string) (*pb.LinksResponse, error) {
// Links returns a list of bucket path URL links.
func (c *Client) Links(ctx context.Context, key, pth string) (*pb.LinksResponse, error) {
return c.c.Links(ctx, &pb.LinksRequest{
Key: key,
Key: key,
Path: pth,
})
}

Expand Down
2 changes: 1 addition & 1 deletion api/buckets/client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ func TestClient_Links(t *testing.T) {
buck, err := client.Create(ctx)
require.NoError(t, err)

links, err := client.Links(ctx, buck.Root.Key)
links, err := client.Links(ctx, buck.Root.Key, "")
require.NoError(t, err)
assert.NotEmpty(t, links.Url)
assert.NotEmpty(t, links.Ipns)
Expand Down
Loading

0 comments on commit 3101199

Please sign in to comment.