ネットワークルール
サンドボックスは、送信トラフィックについて独自のルールを持てます。インターネット上のどこに接続できるか、ホストにどの HTTP リクエストを送れるか、そしてどのリクエストに送信時にヘッダーを追加するかです。egress は、サンドボックスの作成時、変更時、1 回限りの実行時(POST /v1/run)に指定します。指定しなければルールはありません。次のようなオブジェクトで、この例では、サンドボックスは Python のパッケージをインストールし、自身からは見えないトークンを使って GitHub の API 経由でリポジトリを読むことができ、それ以外は何もできません(シークレット GITHUB_TOKEN は後述)。
{"default": "deny",
"allow": ["pypi.org", "files.pythonhosted.org"],
"http": [{"host": "api.github.com", "allow": [{"methods": ["GET", "HEAD"], "paths": ["/repos/*"]}]}],
"inject": [{"host": "api.github.com", "headers": {"Authorization": "Bearer ${secrets.GITHUB_TOKEN}"}}]}default:どちらのリストにもない宛先に対するallow(デフォルト)かdeny。allow、deny:それぞれ最大 1,000 エントリ。ホスト名(pypi.org)、ワイルドカード(*.github.com。その下のすべての名前で、github.com自体は含まない)、アドレスまたはアドレス範囲(140.82.112.0/20)です。denyが先に評価されるため、allowに穴を開けられます。http:最大 100 ホスト。それぞれ、送ってよいメソッドとパスを指定します。それ以外はノードが拒否します(403egress_denied)。inject:最大 100 ホスト。それぞれ、サンドボックスがそこへ送る HTTPS リクエストに追加する 1〜20 個のヘッダーを指定します。値の中の${secrets.NAME}は、送信時にシークレットの値に置き換えられます。deny_ports:最大 64 個のポート(1〜65535)。宛先やほかのルールにかかわらず、TCP でも UDP でも、サンドボックスのどの接続も届きません。ホストのパケットフィルターが最初に拒否し、プロキシに渡されることはありません。ブラウザのセッションでは、メールとマイニングプールのポートがこの方法で常に閉じられています。
glac sandboxes create --name agent --egress '{"default": "deny", "allow": ["pypi.org", "files.pythonhosted.org"]}'
glac sandboxes update agent --egress '{"allow": null}' # empties one list, keeps the rest--egress は、JSON そのもの、それを含むファイル、または標準入力を表す - を受け付けます。変更すると、指定したリストは置き換わり、null を指定したリストは空になり、それ以外はそのまま残ります。"egress": null ですべてのルールを削除します。
**ルールが適用される場所。**ルールはマシンの外のホストで適用されるため、サンドボックス内の root でも変更できません。名前は各接続が名乗るもの(TLS ハンドシェイクの名前、HTTP の Host)と照合され、DNS はルールが許す名前にしか応答しないため、default: deny なら、サンドボックスはルールが許すものにしか到達できません。どのルールでも開けない場所もあります。プライベートアドレス範囲、クラウドのメタデータアドレス、ホスト、ほかのサンドボックスです。
**IPv6 では。**専用のパブリック IPv6 アドレスを持つサンドボックス(ネットワーク)には、名前も含め、IPv6 でも同じルールが適用されます。IPv6 の TCP 接続と DNS の問い合わせは IPv4 と同じくプロキシを通り、マシンは AAAA の問い合わせにも A と同じように応答し、プロキシがサンドボックスのために張る接続は、サンドボックス専用のアドレスから出て、同じ制限に数えられます。サンドボックスが IPv6 で接続する場合はプロキシも IPv6 で接続し、250 ミリ秒後、または IPv6 が拒否されたらすぐに、同じホストへの IPv4 も並行して試みます。先につながった方が使われるため、自分で IPv4 にフォールバックするはずだったプログラムも通信できます。どちらでも通らず、マシンが名前を知らないアドレスへの接続は、1 秒以内に、TLS ハンドシェイクや HTTP リクエストがすぐにそうするように、最初に送るデータでホストを名乗る必要があり、名乗ればそのホストへつながれます。その 1 秒の間に何も送らないか、ホストを名乗らない接続は拒否されます。
**プロキシを通る接続。**ホストを指定したルールでは、IPv4 でも IPv6 でも、サンドボックスのすべての TCP 接続がマシンのエグレスプロキシを通ります。プロキシは、そのマシン上のアカウントのサンドボックスを、プランに応じた同時接続の割り当てと、新しい接続の速さ(1 秒あたり 2,000。超えた分は待たされる)に抑えます。制限を参照してください。割り当てを超えると新しい接続は拒否され、再試行できます(通常の HTTP リクエストには 503 egress_connections_full)。
**ルールで防げないもの。**1 つの証明書で多数のサイトを配信するホストには、許可された名前でハンドシェイクした後に、別のサイトを要求できます。また、トラフィックを転送する許可済みのホスト(プロキシや、誰でも書き込めるストア)は抜け道になります。allow の各エントリは、それだけの信頼を意味します。default: allow と deny のリストは、悪意のないソフトウェアを止めるもので、壁ではありません。
シークレット
シークレットは、名前で保持され、二度と表示されない値です(/v1/secrets)。送られるのは、シークレットが許可するホスト(allowed_hosts)だけで、ほかへ送ることになるルールやイメージは拒否されます(403 secret_host_not_allowed)。
glac secrets put GITHUB_TOKEN --allowed-host api.github.com # asks for the value, not echoed
printf '%s' "$TOKEN" | glac secrets put GITHUB_TOKEN - --allowed-host api.github.com
glac secrets hosts GITHUB_TOKEN api.github.com '*.githubusercontent.com'- ネットワークルールで:
${secrets.GITHUB_TOKEN}を指定したinjectのヘッダーには、送信時に値が入るため、サンドボックス内のプログラムがそれを持つことはありません。 - レジストリのログインとして:値が
username:passwordのシークレットで、プライベートイメージをプルします(image_pull_secret)。 - キューブで:
--secret VAR=NAMEは、アプリのインスタンスに値を環境変数として渡します。この場合、インスタンスは値を持ちます。
プロジェクトが保持できるシークレットの数と 1 つの最大サイズはプランで決まり、1 つのサンドボックスに渡せる合計にも上限があります。
| 無料プラン | 有料プラン | |
|---|---|---|
| 1 プロジェクトのシークレット数 | 100 | 1,000 |
| シークレットの最大サイズ | 64 KiB | 64 KiB |
| 1 サンドボックスに渡すシークレットの合計サイズ | 64 KiB | 64 KiB |
シークレットの保存、変更、削除には admin スコープを持つキーが必要です。それを持たないキーには名前は見えますが、値は見えません。