> Source: https://www.ymotongpoo.com/works/goblog-ja/module-mirror-launch/


# モジュールミラーとチェックサムデータベースを公開しました

[Module Mirror and Checksum Database Launched](https://go.dev/blog/module-mirror-launch) by Katie Hockman

モジュール[ミラー](https://proxy.golang.org)、[インデックス](https://index.golang.org)、[チェックサムデータベース](https://sum.golang.org)が本番運用の準備が整ったことを、私たちは喜んでお知らせします。`go` コマンドは、[Go 1.13のモジュールユーザー](/doc/go1.13#introduction)に対してデフォルトでモジュールミラーとチェックサムデータベースを使用します。これらのサービスに関するプライバシー情報については[proxy.golang.org/privacy](https://proxy.golang.org/privacy)を、これらのサーバーの利用を無効化する方法や別のサーバーを利用する方法などの設定の詳細については[goコマンドのドキュメント](/cmd/go/#hdr-Module_downloading_and_verification)を参照してください。非公開のモジュールに依存している場合は、[環境設定に関するドキュメント](/cmd/go/#hdr-Module_configuration_for_non_public_modules)を参照してください。

この記事では、これらのサービスとそれらを利用する利点について説明し、Gophercon 2019での[Go Module Proxy: Life of a Query](https://youtu.be/KqTySYYhPUE)というトークの内容の一部をまとめます。トーク全体に興味がある方は[録画](https://youtu.be/KqTySYYhPUE)をご覧ください。

## モジュールミラー

[モジュール](/blog/versioning-proposal)とは、まとめてバージョン管理されるGoパッケージの集合であり、各バージョンの内容はイミュータブルです。このイミュータブルという性質によって、キャッシュや認証のための新しい可能性が生まれます。`go get` がモジュールモードで実行されると、要求されたパッケージを含むモジュールと、そのモジュールによって導入される新しい依存関係の両方を取得し、必要に応じて[go.mod](/cmd/go/#hdr-The_go_mod_file)と[go.sum](/cmd/go/#hdr-Module_downloading_and_verification)ファイルを更新しなければなりません。バージョン管理システムからモジュールを取得するのは、レイテンシとシステム上のストレージの観点でコストがかかることがあります。`go` コマンドは、たとえビルドされることのない推移的な依存関係であっても、そのバージョンを解決するためだけに、依存先リポジトリの全コミット履歴を取得せざるを得ないことがあるのです。

この解決策は、`go` コマンドのニーズによりよく適合したAPIを話すモジュールプロキシを使うことです（`go help goproxy` を参照してください）。`go get` がプロキシを使ってモジュールモードで実行されると、必要な特定のモジュールのメタデータやソースコードだけを要求し、それ以外は気にしないことで、より高速に動作します。以下は、`go` コマンドが `go get` でプロキシを利用する際に、バージョンの一覧を要求し、続いて最新のタグ付きバージョンのinfo、mod、zipファイルを要求する例です。

![proxy-protocol](./proxy-protocol.png)

モジュールミラーは、メタデータとソースコードを自身のストレージシステムにキャッシュする特殊な種類のモジュールプロキシであり、元の場所からはもう入手できなくなったソースコードを提供し続けることができます。これによってダウンロードを高速化でき、依存関係が消えてしまうことからあなたを守ります。詳しくは[Go Modules in 2019](/blog/modules2019)を参照してください。

Goチームは[proxy.golang.org](https://proxy.golang.org)で提供されるモジュールミラーを維持しており、Go 1.13以降では `go` コマンドがモジュールユーザーに対してデフォルトでこれを使用します。それより前のバージョンの `go` コマンドを使っている場合は、ローカル環境で `GOPROXY=https://proxy.golang.org` を設定することでこのサービスを利用できます。

## チェックサムデータベース

モジュールは `go.sum` ファイルを導入しました。これは、各依存関係が最初にダウンロードされたときの、ソースコードと `go.mod` ファイルのSHA-256ハッシュの一覧です。`go` コマンドはこれらのハッシュを使って、同じバージョンに対して異なるコードを渡してくるオリジンサーバーやプロキシの不正な振る舞いを検出できます。

この `go.sum` ファイルの限界は、完全に _あなた自身_ の最初の利用時の信頼に基づいて動作している点です。これまで見たことのないバージョンの依存関係をモジュールに追加すると（既存の依存関係をアップグレードする場合などに起こり得ます）、`go` コマンドはそのコードを取得し、その場で `go.sum` ファイルに行を追加します。問題は、その `go.sum` の行が他の誰かのものと照合されていないということです。たとえばプロキシがあなたを狙って意図的に悪意のあるコードを提供していたなどの理由で、`go` コマンドが他の誰かのために生成したばかりの `go.sum` の行とは異なっている可能性があるのです。

Goの解決策は、[チェックサムデータベース](https://go.googlesource.com/proposal/+/master/design/25530-sumdb.md#checksum-database)と呼ばれる `go.sum` の行のグローバルな情報源を用意することです。これにより、`go` コマンドが誰の `go.sum` ファイルにも常に同じ行を追加することが保証されます。`go` コマンドは新しいソースコードを受け取るたびに、そのコードのハッシュをこのグローバルデータベースと照合してハッシュが一致することを確認でき、あるバージョンについて誰もが同じコードを使っていることを保証できます。

チェックサムデータベースは[sum.golang.org](https://sum.golang.org)によって提供されており、[Trillian](https://github.com/google/trillian)に支えられたハッシュの[Transparent Log](https://research.swtch.com/tlog)（あるいは「マークル木」）の上に構築されています。マークル木の主な利点は改ざんが困難であり、不正な振る舞いが検出されずに済んでしまうことを許さない性質を持っている点で、これによって単純なデータベースよりも信頼性が高くなっています。`go` コマンドはモジュールの `go.sum` ファイルに新しい行を追加する前に、この木を使って「包含性 (inclusion)」の証明と「一貫性 (consistency)」の証明を確認します。前者はあるレコードがログの中に存在することを示す証明であり、後者は木が改ざんされていないことを示す証明です。以下はそのような木の例です。

![tree](./tree.png)

チェックサムデータベースは、`go` コマンドが `go.sum` の行を要求し検証するために使う[一連のエンドポイント](https://go.googlesource.com/proposal/+/master/design/25530-sumdb.md#checksum-database)をサポートしています。`/lookup` エンドポイントは「署名付きツリーヘッド (STH)」と要求された `go.sum` の行を提供します。`/tile` エンドポイントは、`go` コマンドが証明に使用できる、木の断片である _タイル_ を提供します。以下は、`go` コマンドがあるモジュールバージョンの `/lookup` を行い、続いて証明に必要なタイルを要求することで、チェックサムデータベースとやり取りする例です。

![sumdb-protocol](./sumdb-protocol.png)

このチェックサムデータベースによって、`go` コマンドは本来であれば信頼できないプロキシを安全に利用できるようになります。その上に監査可能なセキュリティ層が存在するため、プロキシやオリジンサーバーが、意図的であれ、恣意的であれ、あるいは偶発的であれ、誤ったコードを提供し始めれば、必ず検出されます。モジュールの作者であっても、ある日から次の日にかけてタグを付け替えたり、特定のバージョンに紐づくビットを変更したりすれば、その変更は検出されてしまいます。

Go 1.12以前を使っている場合は、[gosumcheck](https://godoc.org/golang.org/x/mod/gosumcheck)を使って `go.sum` ファイルを手動でチェックサムデータベースと照合できます。

```shell-session
$ go get golang.org/x/mod/gosumcheck
$ gosumcheck /path/to/go.sum
```

`go` コマンドによる検証に加えて、サードパーティの監査者はログを走査して不正なエントリがないかを調べることで、チェックサムデータベースの説明責任を担うこともできます。監査者たちは協力し合い、木が成長していく過程でその状態について情報交換 (gossip) することで、それが改ざんされていないことを確認できます。私たちはGoコミュニティがこうした監査者を運用してくれることを望んでいます。

## モジュールインデックス

モジュールインデックスは[index.golang.org](https://index.golang.org)によって提供されており、[proxy.golang.org](https://proxy.golang.org)を通じて利用可能になった新しいモジュールバージョンの公開フィードです。これは特に、[proxy.golang.org](https://proxy.golang.org)で利用可能なものの独自のキャッシュを保持したいツール開発者や、人々が使っている最新のモジュールの情報を追い続けたいツール開発者にとって役立ちます。

## フィードバックやバグ報告

これらのサービスによってモジュールを使う際の体験がより良いものになることを願っています。問題に遭遇したり、フィードバックがあったりした場合には、ぜひ[issueを立てて](/issue/new?title=proxy.golang.org)ください！

By Katie Hockman

