TT Lab
はじめる
学ぶ 学習パス コース

閉域網のミラーとプライベート CA

Go モジュール:ファイルプロキシと vendor で閉域網ビルド

TT Labで続きを見る

目標

Goモジュールを、接続された側で新しいモジュールキャッシュに取得してファイルプロキシに移し、エアギャップ環境側で、GOPROXY=file://とvendorの2つの道でビルドします。go.sumを持ち込みマニフェストとして使う方法と、GOFLAGSの1行がvendorを無視させてしまう落とし穴を、直接確認します。

なぜ重要なのか

Goは、デフォルトでproxy.golang.orgから取得して、sum.golang.orgにハッシュを問い合わせます。エアギャップ環境では、どちらも届きません。モジュールキャッシュのcache/downloadは、それ自体がプロキシプロトコルの形をしているので、移すだけでプロキシになり、go.sumが完全なら、チェックサムデータベースに問い合わせる必要がありません。このPodは、インターネット(80/443)に届くので、ダウンロード側の役割を果たし、エアギャップ環境側の確認は、採点が、外部へ向かうHTTP(S)を閉じたプロキシに向けてふさいだ状態で行います。

ステップ

  1. /root/goair/appにモジュールexample.com/airgap-helloを作成して、rsc.io/quote v1.5.2のquote.Hello()を出力するmain.goを書いてください。新しいモジュールキャッシュとしてGOMODCACHE=/root/goair/outside-cacheを指定して取得し、go mod tidyまで行ってください。
  2. /root/goair/outside-cache/cache/downloadの内容を、/srv/goproxyに移してください。
  3. エアギャップ環境側の設定/root/goair/inside.envに、GOPROXY=file:///srv/goproxyとGOFLAGS=-mod=readonlyを書いてください。
  4. その設定を読み込んで、外部をふさいだ状態で、新しいモジュールキャッシュ/root/goair/inside-cacheでビルドして、/root/goair/bin/hello-proxyを作成してください。
  5. /root/goair/appで、vendorディレクトリを作成してください。
  6. イメージのGOFLAGS=-mod=modをそのままにして、GOPROXY=offと空のモジュールキャッシュでビルドしてみてください。失敗メッセージを/root/goair/gomod-trap.txtに保存します。
  7. GOPROXY=offで、vendorだけでビルドして、/root/goair/bin/hello-vendorを作成してください。
  8. go.sumから、モジュールzipのハッシュの行(/go.modが付かない行)を、모듈 버전 해시の形式に移した(プレースホルダーはモジュール、バージョン、ハッシュです)持ち込み記録/root/goair/intake.txtを書いてください。各ハッシュは、/srv/goproxyの.ziphashと同じである必要があります。

参考

ダウンロード側: 新しいモジュールキャッシュで依存関係を取得する

/root/goair/appにモジュールexample.com/airgap-helloとmain.goを作成して、GOMODCACHE=/root/goair/outside-cacheでrsc.io/quote v1.5.2を取得し、go mod tidyまで行ってください。

go mod initでモジュールを作成し、go getでバージョンを正確に取得します。新しいキャッシュディレクトリをGOMODCACHEとして指定すれば、今回取得したものだけが、その中に積まれます。tidyは、使われている依存関係を、直接の依存として整理します。

モジュールキャッシュをファイルプロキシに移す

/root/goair/outside-cache/cache/downloadの内容を、/srv/goproxyに移してください。

モジュールキャッシュのcache/downloadの下は、すでにプロキシプロトコルの形(@v/list、.info、.mod、.zip)です。ディレクトリ構造をそのまま維持してコピーしてください。展開済みのソースがあるキャッシュの、ほかのディレクトリは必要ありません。

エアギャップ環境側のGo環境ファイル

/root/goair/inside.envに、GOPROXY=file:///srv/goproxyとGOFLAGS=-mod=readonlyを書いてください。

シェルがそのまま読める、名前=値の行です。fileスキームの後ろには、絶対パスが来るので、スラッシュが3つになります。-mod=readonlyは、ビルドがgo.modを勝手に直せないようにします。

外部をふさいで、ファイルプロキシでビルドする

inside.envを読み込んで、外部をふさいだ状態で、新しいモジュールキャッシュ/root/goair/inside-cacheでビルドして、/root/goair/bin/hello-proxyを作成してください。

環境ファイルをexportされる形で読み込んだあと、GOMODCACHEを新しいディレクトリとして指定し、外部のアドレスは、閉じたプロキシに向けてください。すでに取得してあるキャッシュでビルドすると、プロキシを試したことになりません。

2つ目の道: vendor

/root/goair/appで、vendorディレクトリを作成してください。

go modのサブコマンドの中に、依存関係のソースをリポジトリの中にコピーするものがあります。結果として、vendor/modules.txtができるかを見てください。

vendorがあるのに失敗するビルド

イメージのGOFLAGS=-mod=modをそのままにして、GOPROXY=offと空のモジュールキャッシュでビルドしてみて、失敗メッセージを/root/goair/gomod-trap.txtに保存してください。

このステップは、失敗を記録するステップです。go env GOFLAGSで、今の値を先に見てください。-mod=modがvendorをどう扱うかを、読み物の内容から思い出せば、メッセージが理解できます。

GOPROXY=offで、vendorでビルドする

GOPROXY=offで、vendorだけでビルドして、/root/goair/bin/hello-vendorを作成してください。

vendorを使わせる-modの値があります。環境のGOFLAGSを上書きするか、コマンドラインで直接指定してください。モジュールキャッシュが空でも、できる必要があります。

go.sumで持ち込み記録を書く

go.sumのモジュールzipのハッシュの行を、모듈 버전 해시の形式に移した(プレースホルダーはモジュール、バージョン、ハッシュです)/root/goair/intake.txtを書いてください。各ハッシュは、/srv/goproxyの.ziphashと同じである必要があります。

go.sumの行は、モジュール、バージョン、h1:ハッシュの3つの列です。バージョンの後ろに/go.modが付いた行は、go.modファイルのハッシュなので、zipとは違います。プロキシディレクトリの.ziphashファイルと、1行ずつ照合してみてください。