Skip to content
This repository has been archived by the owner on May 2, 2023. It is now read-only.

Extend README and configuration documentation. #24

Merged
merged 3 commits into from
Aug 15, 2022
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
115 changes: 85 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,100 @@

[![GoDoc](https://pkg.go.dev/badge/github.com/brave/nitriding?utm_source=godoc)](https://pkg.go.dev/github.com/brave/nitriding)

This package helps with building networked Go applications on top of AWS Nitro
This package helps with building Go-based Web applications on top of AWS Nitro
Enclaves. The package provides the following features:

1. Initialize the enclave's entropy pool.
1. Automatically obtains an HTTPS certificate (either self-signed or via [Let's
Encrypt](https://letsencrypt.org)) for clients to securely connect to your
enclave over the Internet.

2. Obtain an HTTPS certificate for clients to connect to the enclave; either
self-signed, or via Let's Encrypt.
2. Automatically exposes an HTTPS endpoint for remote attestation. After
having audited your enclave's source code, your users can conveniently
verify the enclave by using a tool like
[verify-enclave](https://github.com/brave-experiments/verify-enclave)
and running:

3. Expose an endpoint for remote attestation.
```
make verify CODE=/path/to/code/ ENCLAVE=https://example.com/attest
```

4. Start a proxy that transparently translates between IP and VSOCK.
3. Provides an API for the enclave application to securely share confidential
key material with an identical, remote enclave.

Use the following "hello world" example to get started:
4. Starts a proxy component that transparently translates between IP and VSOCK,
so you can write IP-based networking code without having to worry about
the enclave's constrained VSOCK interface.

package main
5. Automatically initializes the enclave's entropy pool using the Nitro
hypervisor.

import (
"fmt"
"log"
"net/http"
To learn more about nitriding's trust assumptions, architecture, and build
system, take a look at our [research paper](https://arxiv.org/abs/2206.04123).

"github.com/brave/nitriding"
)
## Configuration

func helloWorldHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "hello world")
}
Nitriding's
[configuration object](https://pkg.go.dev/github.com/brave-experiments/nitriding#Config)
contains comments that explain the purpose of each variable.

## Example

Use the following "hello world" example to get started. The program
instantiates a new Web server that's listening on port 8443, for the domain
example.com. It also registers an HTTP handler for the path `/hello-world`
which, when accessed, simply responds with the string "hello world".

Note that in order for this example to work, you need to set up two programs on
the parent EC2 instance:

1. [viproxy](https://github.com/brave/viproxy) by running:

```bash
export CID=5 # The CID you assigned when running "nitro-cli run-enclave --enclave-cid X ...".
export IN_ADDRS=":8443,:80,3:80"
export OUT_ADDRS="${CID}:8443,${CID}:80,127.0.0.1:1080"
viproxy
```

2. A SOCKS proxy, e.g.
[this one](https://github.com/brave-intl/bat-go/tree/nitro-utils/nitro-shim/tools/socksproxy).

That said, here is the enclave application:

func main() {
enclave := nitriding.NewEnclave(
&nitriding.Config{
FQDN: "example.com",
Port: 8080,
UseACME: false,
Debug: false,
},
)
enclave.AddRoute(http.MethodGet, "/hello-world", helloWorldHandler)
if err := enclave.Start(); err != nil {
log.Fatalf("Enclave terminated: %v", err)
}
```golang
package main

import (
"fmt"
"log"
"net/http"

"github.com/brave/nitriding"
)

func helloWorldHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "hello world")
}

func main() {
enclave := nitriding.NewEnclave(
&nitriding.Config{
FQDN: "example.com",
Port: 8443,
UseACME: true,
},
)
enclave.AddRoute(http.MethodGet, "/hello-world", helloWorldHandler)
if err := enclave.Start(); err != nil {
log.Fatalf("Enclave terminated: %v", err)
}
}
```

## Development

To test and lint the code, run:

```
make
```
49 changes: 42 additions & 7 deletions enclave.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,49 @@ type Enclave struct {

// Config represents the configuration of our enclave service.
type Config struct {
// SOCKSProxy must be set if
// 1) your enclave application should obtain a Let's Encrypt-signed
// certificate (i.e., if UseACME is set to true)
// or if
// 2) your enclave application makes HTTP requests over the Internet.
// If so, set SOCKSProxy to "socks5://127.0.0.1:1080".
Comment on lines +74 to +75
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe mention this port number must match the one given to viproxy on the host instance?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It actually doesn't have to because this variable only controls the in-enclave IP-to-VSOCK proxy. There's a viproxy instance running on both the host and inside the enclave. We should probably remove this variable from the config struct because it's confusing and there aren't many good reasons to change it.

SOCKSProxy string
FQDN string
Port int
UseACME bool
Debug bool
FdCur uint64
FdMax uint64
AppURL string

// FQDN contains the fully qualified domain name that's set in the HTTPS
// certificate of the enclave's Web server, e.g. "example.com".
FQDN string

// Port contains the TCP port that the Web server should listen on, e.g.
// 8443. Note that the Web server listens for this port on the private
// VSOCK interface. This is not an Internet-facing port.
Port int

// UseACME must be set to true if you want your enclave application to
// request a Let's Encrypt-signed certificate. If this is set to false,
// the enclave creates a self-signed certificate.
UseACME bool

// Debug can be set to true to see debug messages, i.e., if you are
// starting the enclave in debug mode by running:
Comment on lines +92 to +93
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice if the framework could ask the supervisor if it's in debug mode, but I don't see an interface for that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One could implement this by asking for an attestation document and checking if its PCR values are all zeroed out. I filed https://github.com/brave/nitriding/issues/25 for this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, clever!

//
// nitro-cli run-enclave --debug-mode ....
//
// Do not set this to true in production because printing debug messages
// for each HTTP request slows down the enclave application, and you are
// not able to see debug messages anyway unless you start the enclave using
// nitro-cli's "--debug-mode" flag.
Debug bool

// FdCur and FdMax set the soft and hard resource limit, respectively. The
// default for both variables is 65536.
FdCur uint64
FdMax uint64

// AppURL should be set to the URL of the software repository that's
// running inside the enclave, e.g., "https://github.com/foo/bar". The URL
// is shown on the enclave's index page, as part of instructions on how to
// do remote attestation.
AppURL string
}

// NewEnclave creates and returns a new enclave with the given config.
Expand Down