Proxying a checksum database API
If you run go get github.com/mycompany/secret-repo@v1.0.0
and that module version is not yet in your go.sum
file, Go will by default send a request to https://sum.golang.org/lookup/github.com/mycompany/secret-repo@v1.0.0
. That request will fail because the Go tool requires a checksum, but sum.golang.org
doesn’t have access to your private code.
The result is that (1) your build will fail, and (2) your private module names have been sent over the internet to an opaque public server that you don’t control.
You can read more about this
sum.golang.org
service here
Proxying a checksum DB
Many companies use Athens to host their private code, but Athens is not only a module proxy. It’s also a checksum database proxy. That means that anyone inside of your company can configure go
to send these checksum requests to Athens instead of the public sum.golang.org
server.
If the Athens server is configured with checksum filters, then you can prevent these problems.
If you run the below command using Go 1.13 or later:
$ GOPROXY=<athens-url> go build .
… then the Go tool will automatically send all checksum requests to <athens-url>/sumdb/sum.golang.org
instead of https://sum.golang.org
.
By default, when Athens receives a /sumdb/...
request, it automatically proxies it to https://sum.golang.org
, even if it’s a private module that sum.golang.org
doesn’t and can’t know about. So if you are working with private modules, you’ll want to change the default behavior.
If you want Athens to not send some module names up to the global checksum database, set those module names in the
NoSumPatterns
value inconfig.toml
or using theATHENS_GONOSUM_PATTERNS
environment variable.
The following sections will go into more detail on how checksum databases work, how Athens fits in, and how this all impacts your workflow.
How to set this all up
Before you begin, you’ll need to run Athens with configuration values that tell it to not proxy certain modules. If you’re using config.toml
, use this configuration:
NoSumPatterns = ["github.com/mycompany/*", "github.com/secret/*"]
And if you’re using an environment variable, use this configuration:
$ export ATHENS_GONOSUM_PATTERNS="github.com/mycompany/*,github.com/secret/*"
You can use any string compatible with
path.Match
in these environment variables
After you start Athens up with this configuration, all checksum requests for modules that start with github.com/mycompany
or github.com/secret
will not be forwarded, and Athens will return an error to the go
CLI tool.
This behavior will ensure that none of your private module names leak to the public internet, but your builds will still fail. To fix that problem, set another environment variable on your machine (that you run your go
commands)
$ export GONOSUMDB="github.com/mycompany/*,github.com/secret/*"
Now, your builds will work and you won’t be sending information about your private codebase to the internet.
I’m confused, why is this hard?
When the Go tool has to download new code that isn’t currently in the project’s go.sum
file, it tries its hardest to get a checksum from a server it trusts, and compare it to the checksum in the actual code it downloads. It does all of this to ensure provenance. That is, to ensure that the code you just downloaded wasn’t tampered with.
The trusted checksums are all stored in sum.golang.org
, and that server is centrally controlled.
These build failures and potential privacy leaks can only happen when you try to get a module version that is not already in your
go.sum
file.
Athens does its best to respect and use the trusted checksums while also ensuring that your private names don’t get leaked to the public server. In some cases, it has to choose whether to fail your build or leak information, so it chooses to fail your build. That’s why everybody using that Athens server needs to set up their GONOSUMDB
environment variable.
We believe that along with good documentation - which we hope this is! - we have struck the right balance between convenience and privacy.