Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 47 additions & 1 deletion crates/mtc_worker/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,52 @@
# Merkle Tree CA Worker

A Rust implementation of a [Merkle Tree CA][] for deployment on [Cloudflare Workers](https://workers.cloudflare.com/).
A Rust implementation of a [Merkle Tree CA](https://github.com/davidben/merkle-tree-certs/) (MTCA) for deployment on [Cloudflare Workers](https://workers.cloudflare.com/).

Much of the API and the internal architecture of the Merkle Tree CA is shared by the [Static CT Log](../ct_worker/README.md). This Worker also implements issuance of Merkle Tree Certificates (MTCs). The issuance API should be considered unstable. For now, its primary purpose is to support an experimental deployment of the MTC specification.

## Development

`node` and `npm` are required to run the Worker locally. First, use `npm` to install `wrangler`:

```bash
npm install -g wrangler@latest
```

Then use `wrangler` to run the Worker locally from this directory:

```bash
npx wrangler dev -e=dev
```

The Worker doesn't implement a full-blown MTCA. Instead, it implements what we call a **bootstrap MTCA**. For every MTC requested, the requester must provide a **bootstrap certificate**. A bootstrap certificate is a standard X.509 certificate chain that must have a path to a root certificate trusted by `mtc_worker`. By default, the root store used is the intersection of Chrome's and Mozilla's trust stores.

To test the basic functionality, run the following script from this directory:

```bash
./test-dev.sh
```

This script does the following:

1. Fetch a bootstrap certificate chain.

1. Submit the bootstrap certificate chain to the MTCA running locally.

1. Wait for the next landmark to be minted. The landmark interval is defined in [`config.dev.json`](./config.dev.json).

1. Request the signatureless MTC from the MTCA running locally

### Overriding the trust store

It may be useful to provide your own roots for testing. To do so:

1. Build the Worker with the `"dev-bootstrap-roots"` feature. Note that `wrangler` invokes `cargo` with a custom build script, so the simplest thing to do is to edit the `Cargo.toml` file by adding `"dev-boostrap-roots"` to the default feature set.

1. Append your roots to [`dev-bootstrap-roots.pem`](./dev-bootstrap-roots.pem).

## Deployment

See the [`ct_worker` documentation](../ct_worker/README.md#deployment-to-a-custom-domain) for deployment to a custom domain.

## License

Expand Down
52 changes: 52 additions & 0 deletions crates/mtc_worker/test-dev.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/bin/bash

set -e

bootstrap_cert_hostname="cloudflareresearch.com"
landmark_interval_secs=`jq '.logs.dev2.landmark_interval_secs' config.dev.json`
submission_url=`jq -r '.logs.dev2.submission_url' config.dev.json`

# Get a bootstrap certificate chain.
bootstrap_cert_chain=`mktemp`
echo | openssl s_client \
-connect ${bootstrap_cert_hostname}:443 \
-servername ${bootstrap_cert_hostname} \
-showcerts 2>/dev/null |\
sed -n '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p' \
> ${bootstrap_cert_chain}

spki_der=`openssl x509 -in ${bootstrap_cert_chain} -pubkey -noout |\
openssl pkey -pubin -inform pem -outform der | base64`

add_entry_req=`cat ${bootstrap_cert_chain} |\
while (set -o pipefail;
openssl x509 -outform DER 2>/dev/null |\
base64); do :; done |\
sed '/^$/d' | sed 's/.*/"&"/' | jq -sc '{"chain":.}'`

# Add entry for the bootstrap certificate.
add_entry_resp=`curl -f --no-progress-meter -X POST \
-H "Content-Type: application/json" \
-d ${add_entry_req} \
"${submission_url}add-entry"`

leaf_index=`echo ${add_entry_resp} | jq '.leaf_index'`
echo "Leaf index: ${leaf_index}"

# Wait for the next landmark to be minted.
echo "Waiting ${landmark_interval_secs}s for the next landmark"
sleep ${landmark_interval_secs}

get_cert_req="{\"leaf_index\":${leaf_index},\"spki_der\":\"${spki_der}\"}"

# Fetch the completed MTC.
get_cert_resp=`curl -f --no-progress-meter -X POST \
-H "Content-Type: application/json" \
-d ${get_cert_req} \
"${submission_url}get-certificate"`

landmark_id=`echo ${get_cert_resp} | jq '.landmark_id'`
echo "Landmark id: ${landmark_id}"

echo ${get_cert_resp} | jq -r '.data' | base64 -d |\
openssl x509 -inform DER -outform PEM