Skip to content

groupcache Example

groupcache is a memcached-like library written in GO: it implements a peer-to-peer caching service. We use groupcache to show how to build a little more complex GO program with SCONE.

Typically, one would build a container image for groupcache with a Dockerfile. Since our emphasis is to explain how to build such programs, we first show the individual steps to compile and execute groupcache and second, please read how to build container images with a multi-stage build.

Note

You might want to read how to compile GO programs with SCONE first.

Building groupcache - without shielding

First, start a crosscompiler container. Determine which SGX device to mount with function determine_sgx_device:

determine_sgx_device
docker run $MOUNT_SGXDEVICE -it  registry.scontain.com/sconecuratedimages/crosscompilers

Second, install the go command to simplify the building of groupcache:

apk update
apk add go git curl

Now you can build the groupcache library as follows:

go get -compiler gccgo -u github.com/golang/groupcache

Note that flag -compiler gccgo is required to ensure that the scone-gccgo is used to compile groupcache.

That's it!

Example

OK, we should show how to use group cache. We show this for a simple application from fiorix:

cat > groupcache.go << EOF
// Simple groupcache example: https://github.com/golang/groupcache
// Running 3 instances:
// go run groupcache.go -addr=:8080 -pool=http://127.0.0.1:8080,http://127.0.0.1:8081,http://127.0.0.1:8082
// go run groupcache.go -addr=:8081 -pool=http://127.0.0.1:8081,http://127.0.0.1:8080,http://127.0.0.1:8082
// go run groupcache.go -addr=:8082 -pool=http://127.0.0.1:8082,http://127.0.0.1:8080,http://127.0.0.1:8081
// Testing:
// curl localhost:8080/color?name=red
package main

import (
    "errors"
    "flag"
    "log"
    "net/http"
    "strings"
    "context"
    "github.com/golang/groupcache"
)

var Store = map[string][]byte{
    "red":   []byte("#FF0000"),
    "green": []byte("#00FF00"),
    "blue":  []byte("#0000FF"),
}

var Group = groupcache.NewGroup("foobar", 64<<20, groupcache.GetterFunc(
    func(ctx context.Context, key string, dest groupcache.Sink) error {
        log.Println("looking up", key)
        v, ok := Store[key]
        if !ok {
            return errors.New("color not found")
        }
        dest.SetBytes(v)
        return nil
    },
))

func main() {
    addr := flag.String("addr", ":8080", "server address")
    peers := flag.String("pool", "http://localhost:8080", "server pool list")
    flag.Parse()
    http.HandleFunc("/color", func(w http.ResponseWriter, r *http.Request) {
        color := r.FormValue("name")
        var b []byte
        err := Group.Get(nil, color, groupcache.AllocatingByteSliceSink(&b))
        if err != nil {
            http.Error(w, err.Error(), http.StatusNotFound)
            return
        }
        w.Write(b)
        w.Write([]byte{'\n'})
    })
    p := strings.Split(*peers, ",")
    pool := groupcache.NewHTTPPool(p[0])
    pool.Set(p...)
    http.ListenAndServe(*addr, nil)
}
EOF

Let's compile this with scone-gccgo:

export SCONE_HEAP=1G
go build -compiler gccgo -buildmode=exe -gccgoflags -g groupcache.go

Run groupcache in the background:

./groupcache -addr=:8080 -pool=http://127.0.0.1:8080 &

And let's query groupcache:

curl localhost:8080/color?name=green
#00FF00
curl localhost:8080/color?name=red
#FF0000

Shielding

While the above code runs inside of an enclave, there are multiple security issues if that code would run in an untrusted environment:

  • The peers communicate via http instead of https. This means that executing in an enclave does not improve the security since an attacker can just look into the network traffic of groupcache.

    • The use of https instead of http would require a certificate and a private key.
  • The arguments (i.e., -addr and -pool) are passed via command line, i.e., we can neither trust the integrity nor the confidentiality of these arguments.

  • This groupcache service logs error messages on stderr.

  • How can we be sure if the code runs indeed in an enclave? After all, SCONE supports simulation mode.

Alternative: Manual Modifications

One could manually modify the program to use https instead of http, one could encrypt the output with AES. However, this would require that we have to change groupcache not only to encrypt all output but also to manage the key for encrypting the output.

The private key of the certificate is typically stored in an unencrypted file and protected via the access control of the file system. Since we do not trust the operating system, we would need to encrypt the private key in the file system.

We would need to attest the groupcache and after successful attestation pass the encryption keys and the arguments to groupcache via a secure channel.

Alternative: SCONE shielding

Many programs would require such or similar changes as groupcache. Hence, SCONE provides a way to shield programs without the need to modify these programs.

This main advantages of that approach is that

  • one does not have to put in the engineering to modify the code - which is difficult and bug-prone

  • one can easily keep up with upstream code changes without the need to continuously patch the upstream code

  • one does not risk a lock-in by having SGX-specific or SCONE-specific code modifications

We will show in later sections how we can shield this application with the help of SCONE such that

  • no source code changes are necessary, and

  • we only need to define a description what shields should be activated

In this way, we can address all of the above issues that we described.