Skip to content

Commit

Permalink
Migrate serverless over to transparency-dev/serverless-log (#923)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlCutter authored Oct 18, 2023
1 parent 8a170cf commit 4ed8d2b
Show file tree
Hide file tree
Showing 106 changed files with 25 additions and 6,384 deletions.
2 changes: 1 addition & 1 deletion clone/cmd/serverlessclone/serverlessclone.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ import (
"github.com/google/trillian-examples/clone/internal/cloner"
"github.com/google/trillian-examples/clone/internal/verify"
"github.com/google/trillian-examples/clone/logdb"
"github.com/google/trillian-examples/serverless/client"
"github.com/transparency-dev/formats/log"
"github.com/transparency-dev/merkle/rfc6962"
"github.com/transparency-dev/serverless-log/client"
"golang.org/x/mod/sumdb/note"

_ "github.com/go-sql-driver/mysql"
Expand Down
18 changes: 4 additions & 14 deletions cloudbuild.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ steps:
args:
- '-exc'
- |
./scripts/presubmit.sh --cloud-build --coverage --no-linters --no-actions --no-docker --no-serverless-wasm
./scripts/presubmit.sh --cloud-build --coverage --no-linters --no-actions --no-docker
# Check re-generation didn't change anything.
echo "Checking that generated files are the same as checked-in versions."
git diff -- --exit-code
Expand All @@ -82,7 +82,7 @@ steps:
args:
- '-exc'
- |
./scripts/presubmit.sh --cloud-build --no-build --no-generate --no-actions --no-docker --no-serverless-wasm
./scripts/presubmit.sh --cloud-build --no-build --no-generate --no-actions --no-docker
waitFor: ['go-get-proto', 'go-get-proto-gen']

# Build serverless actions
Expand All @@ -92,17 +92,7 @@ steps:
args:
- '-exc'
- |
./scripts/presubmit.sh --cloud-build --no-build --no-linters --no-generate --no-docker --no-serverless-wasm
waitFor: ['go-get-proto', 'go-get-proto-gen']

# Build serverless wasm
- name: gcr.io/$PROJECT_ID/testbase
entrypoint: 'bash'
id: 'presubmit-build-serverless-wasm'
args:
- '-exc'
- |
./scripts/presubmit.sh --cloud-build --no-build --no-linters --no-generate --no-docker --no-actions
./scripts/presubmit.sh --cloud-build --no-build --no-linters --no-generate --no-docker
waitFor: ['go-get-proto', 'go-get-proto-gen']

# Build docker images
Expand All @@ -112,7 +102,7 @@ steps:
args:
- '-exc'
- |
./scripts/presubmit.sh --cloud-build --no-build --no-linters --no-generate --no-actions --no-serverless-wasm
./scripts/presubmit.sh --cloud-build --no-build --no-linters --no-generate --no-actions
waitFor: ['go-get-proto', 'go-get-proto-gen']

# Test the USB Armory code as best we can
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ require (
github.com/gorilla/mux v1.8.0
github.com/mattn/go-sqlite3 v1.14.17
github.com/perlin-network/life v0.0.0-20191203030451-05c0e0f7eaea
github.com/transparency-dev/formats v0.0.0-20230607101544-c064fae4cff6
github.com/transparency-dev/formats v0.0.0-20230914071414-5732692f1e50
github.com/transparency-dev/merkle v0.0.2
github.com/transparency-dev/serverless-log v0.0.0-20230914155322-9b6f31f76f1f
github.com/u-root/u-root v0.11.0
github.com/usbarmory/tamago v0.0.0-20221104085030-4122a878196a
golang.org/x/crypto v0.14.0
Expand Down
6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,12 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/transparency-dev/formats v0.0.0-20230607101544-c064fae4cff6 h1:Mjc7czQhATVAWBRZecClSQlWFMiW/42AZdYzp4qRnqQ=
github.com/transparency-dev/formats v0.0.0-20230607101544-c064fae4cff6/go.mod h1:Nb+V5XS9fhtScBd8Zb7BmCywNSu1eGQvJqGXodST9cw=
github.com/transparency-dev/formats v0.0.0-20230914071414-5732692f1e50 h1:FVMl+jA2NBlbUm5XjLJNMrSLqbA/SpeXhKoirj3MMwg=
github.com/transparency-dev/formats v0.0.0-20230914071414-5732692f1e50/go.mod h1:J2NdDb6IhKIvF6MwCvKikz9/QStRylEtS2mv+En+jBg=
github.com/transparency-dev/merkle v0.0.2 h1:Q9nBoQcZcgPamMkGn7ghV8XiTZ/kRxn1yCG81+twTK4=
github.com/transparency-dev/merkle v0.0.2/go.mod h1:pqSy+OXefQ1EDUVmAJ8MUhHB9TXGuzVAT58PqBoHz1A=
github.com/transparency-dev/serverless-log v0.0.0-20230914155322-9b6f31f76f1f h1:quFhOfslKXkqvTCN0s5o2G/i/DLpfKkHFL893MnLetU=
github.com/transparency-dev/serverless-log v0.0.0-20230914155322-9b6f31f76f1f/go.mod h1:wePHXib4JC193IyIQImP3oNXYpUZQWzKcF6BJ8bC8GY=
github.com/twitchyliquid64/golang-asm v0.0.0-20190126203739-365674df15fc h1:RTUQlKzoZZVG3umWNzOYeFecQLIh+dbxXvJp1zPQJTI=
github.com/twitchyliquid64/golang-asm v0.0.0-20190126203739-365674df15fc/go.mod h1:NoCfSFWosfqMqmmD7hApkirIK9ozpHjxRnRxs1l413A=
github.com/u-root/u-root v0.11.0 h1:6gCZLOeRyevw7gbTwMj3fKxnr9+yHFlgF3N7udUVNO8=
Expand Down
9 changes: 0 additions & 9 deletions scripts/presubmit.sh
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ main() {
local run_build=1
local build_actions=1
local build_docker=1
local build_serverless_wasm=1
local run_lint=1
local run_generate=1
while [[ $# -gt 0 ]]; do
Expand Down Expand Up @@ -66,9 +65,6 @@ main() {
--no-docker)
build_docker=0
;;
--no-serverless-wasm)
build_serverless_wasm=0
;;
--cloud-build)
flag_cloud_build=1
;;
Expand Down Expand Up @@ -138,11 +134,6 @@ main() {
done
fi

if [[ "${build_serverless_wasm}" -eq 1 ]]; then
echo "Building serverless wasm ===================="
GOOS=js GOARCH=wasm go build -o /tmp/main.wasm -tags wasm ./serverless/experimental/wasm/
fi

if [[ "${run_lint}" -eq 1 ]]; then
check_cmd golangci-lint \
'have you installed github.com/golangci/golangci-lint?' || exit 1
Expand Down
193 changes: 8 additions & 185 deletions serverless/README.md
Original file line number Diff line number Diff line change
@@ -1,190 +1,13 @@
Serverless Log
===============

This is some experimental tooling which allows for the maintenance and querying
of a log represented by tiles & files. These tools are built upon components
from the Trillian repo (e.g. compact ranges), but *do not* use the Trillian Log
service itself.
Most of the contents of this directory has graduated to its own repo at
<https://github.com/transparency-dev/serverless-log>.

The idea is to make logging infrastructure a bit more *nix like, and demonstrate
how to use those tools in conjunction with GitHub actions, GCP Cloud Functions,
AWS Lambda, etc. to deploy and maintain "serverless" transparency logs.
The remaining parts are:
[clone2serverless](./cmd/clone2serverless): A tool for dumping transparency
logs cloned with the [clone](/clone) tools into a locally hosted serverless
log.

The on-disk structure of the log is well defined, and can directly be made
public via HTTP[S]. Clients wishing to be convinced of consistency/inclusion are
responsible for constructing the proofs themselves by fetching the tiles
containing the required nodes.

Command-line tools usage
------------------------

A few tools are provided for manipulating the on-disk log state:
- `sequence` this assigns sequence numbers to new entries
- `integrate` this integrates any as-yet un-integrated sequence numbers into
the log state
- `client` this provides log proof verification
- `generate_keys` creates the public/private key pair for signing and
validating the log checkpoints

Examples of how to use the tools are given below, they assume that a `${LOG_DIR}`
environment variable has been set to the desired path and directory name which
should contain the log state files, e.g.:

```bash
$ export LOG_DIR="/tmp/mylog"
$ export LOG_ORIGIN="My Log"
```

`sequence` and `client` require the log public key to be provided.

This is supplied by providing the path to the key file using `--public_key`
or by setting the `SERVERLESS_LOG_PUBLIC_KEY` environment variable

`integrate` requires the log public and private keys to be provided.

These are supplied by providing the path to the key files using
`--public_key` and `--private_key` or by setting the
`SERVERLESS_LOG_PUBLIC_KEY` and `SERVERLESS_LOG_PRIVATE_KEY` environment variables.


### Generating keys
To create a new private key pair, use the `generate_keys` command with `--key_name`, a name
for the signing entity. You can output the public and private keys to files using
`--out_pub` path and filename for the public key,
`--out_priv` path and filename for the private key
and stdout, private key, then public key, over 2 lines, using `--print`

```bash
$ go run ./serverless/cmd/generate_keys --key_name=astra --out_pub=key.pub --out_priv=key
```

### Creating a new log
To create a new log state directory, use the `integrate` command with the `--initialise`
flag, and either passing key files or with environment variables set:

```bash
$ go run ./serverless/cmd/integrate --initialise --storage_dir="${LOG_DIR}" --logtostderr --public_key=key.pub --private_key=key --origin="${LOG_ORIGIN}"
```

### Sequencing entries into a log
To add the contents of some files to a log, use the `sequence` command with the
`--entries` flag set to a filename glob of files to add and either passing the public key
file or with the environment variable set:

```bash
$ go run ./serverless/cmd/sequence --storage_dir="${LOG_DIR}" --entries '*.md' --logtostderr --public_key=key.pub --origin="${LOG_ORIGIN}"
I0413 16:54:52.708433 4154632 main.go:97] 0: CONTRIBUTING.md
I0413 16:54:52.709114 4154632 main.go:97] 1: README.md
```

The tool prints out the names of added files, along with their assigned sequence
number(s) - above, the contents of `CONTRIBUTING.md` was assigned to sequence number
0.

Attempting to re-sequence the same file contents will result in the `sequence`
tool telling you that you're trying to add duplicate entries, along with their
originally assigned sequence numbers:

```bash
$ go run ./serverless/cmd/sequence --storage_dir="${LOG_DIR}" --entries 'C*' --logtostderr --public_key=key.pub --origin="${LOG_ORIGIN}"
I0413 16:58:08.956402 4155499 main.go:97] 0: CONTRIBUTING.md (dupe)
I0413 16:58:08.956938 4155499 main.go:97] 2: CONTRIBUTORS
```

Here we see that the contents of `CONTRIBUTING.md` already exists in the log at
sequence number 0, but the contents `CONTRIBUTORS` did not and was assigned a
sequence number of 2.

> :warning: </br>
> Note that duplicate suppression is not guaranteed - there are corner
> cases where a crash of the `sequence` tool could result in a duplicate entry
> being added, so it's best not to rely on uniqueness and instead consider it
> a best-effort anti-spam mitigation.
### Integrating sequenced entries
Although the entries we've added above are now assigned positions in the log, we
still need to update the proof structure state to integrate these new entries.
We use the `integrate` tool for that, again either passing key files or with the
environment variables set:

```bash
$ go run ./serverless/cmd/integrate --storage_dir="${LOG_DIR}" --logtostderr --public_key=key.pub --private_key=key --origin="${LOG_ORIGIN}"
I0413 17:03:19.239293 4156550 integrate.go:74] Loaded state with roothash
I0413 17:03:19.239468 4156550 integrate.go:113] New log state: size 0x3 hash: 615a21da1739d901be4b1b44aed9cfcfdc044d18842f554a381bba4bff687aff
```

This output says that the integration was successful, and we now have a new log
tree state which contains `0x03` entries, and has the printed log root hash.

Unless further entries are sequenced as above, re-running the `integrate` command
will have no effect:

```bash
$ go run ./serverless/cmd/integrate --storage_dir="${LOG_DIR}" --logtostderr --public_key=key.pub --private_key=key --origin="${LOG_ORIGIN}"
I0413 17:05:10.040900 4156921 integrate.go:74] Loaded state with roothash 615a21da1739d901be4b1b44aed9cfcfdc044d18842f554a381bba4bff687aff
I0413 17:05:10.040976 4156921 integrate.go:94] Nothing to do.
```

### Client

There is a simple client-side tool for querying the log, currently it supports
the following functionality:

#### Inclusion proof verification

We can verify the inclusion of a given leaf in the tree with the `client inclusion`
command:

```bash
$ go run ./serverless/cmd/client/ --logtostderr --public_key=key.pub --log_url="file:///${LOG_DIR}/" --origin="${LOG_ORIGIN}" inclusion ./CONTRIBUTING.md
I0413 17:09:48.335324 4158369 client.go:99] Leaf "./CONTRIBUTING.md" found at index 0
I0413 17:09:48.335468 4158369 client.go:119] Inclusion verified in tree size 3, with root 0x615a21da1739d901be4b1b44aed9cfcfdc044d18842f554a381bba4bff687aff
```

As expected, requesting an inclusion proof for something not in the log will fail:

```bash
$ go run ./serverless/cmd/client/ --logtostderr --log_url="file:///${LOG_DIR}/" --origin="${LOG_ORIGIN}" inclusion ./go.mod
F0413 17:13:04.148676 4158991 client.go:72] Command "inclusion" failed: "failed to lookup leaf index: leafhash unknown (open /${LOG_DIR}/leaves/67/48/64/2df7219529a9f2303e8668d60b70a6d7600f22e22fc612c26bd3c399ef: no such file or directory)"
exit status 1
```

> :frog: </br>
> Note that the `--log_url` parameter is a URL, it understands `file://`
> URLs for local filesystem access, but also works with `http[s]://` URLs too - so
> you can directly serve the filesystem contents in `${LOG_DIR}` via HTTP[S] and point
> the client at that server instead and it should work just fine.
>
> E.g.:
>
> ```bash
> $ busybox httpd -f -p 8000 -h ${LOG_DIR}
> ```
> and in another terminal:
>
> ```bash
> $ go run ./serverless/cmd/client/ --logtostderr --log_url=http://localhost:8000 --origin=${LOG_ORIGIN}" inclusion ./CONTRIBUTING.md
> I0413 17:25:05.799998 4163606 client.go:99] Leaf "./CONTRIBUTING.md" found at index 0
> I0413 17:25:05.801354 4163606 client.go:119] Inclusion verified in tree size 3, with root 0x615a21da1739d901be4b1b44aed9cfcfdc044d18842f554a381bba4bff687aff
> ```
Hosting serverless logs
--------------------------------------
In many cases we'd like to outsource the job of hosting our log to a third
party. There are many possibile ways to do this, one is to use GitHub as both
a public storage provider for serving the log state, and as hosting the process
of updating the log state.
For more details, including example GitHub Action configs, see
[here](./deploy/github).
TODO
----
- [X] Document structure, design, etc.
- [X] Integration test.
- [X] Update client to be able to read tree data from the filesystem via HTTP.
- [X] Implement & document GitHub actions components.
- [X] Support for squashing dupes.
- [ ] Maybe add configs/examples/docs for Cloud Functions, etc. too.
[serverless distributor](./deploy/github/distributor): Tooling & example
config for an experimental GitHub Actions based checkpoint distributor.
84 changes: 0 additions & 84 deletions serverless/api/layout/README.md

This file was deleted.

Loading

0 comments on commit 4ed8d2b

Please sign in to comment.