アクセス制御
デプロイにアクセスできる人を決めます。アプリのユーザーのログインとは別の機能です。
公開前のデプロイを保護したり、特定の人にだけ見せたりするときに使ってください。アクセス方式は次の 4 つです。
runlot access set public # 誰でもアクセスできる(デフォルト)
runlot access set org # この組織のメンバーだけがアクセスできる
runlot access set password # 共有パスワードを知っている人だけがアクセスできる
runlot access set app # このアプリにサインインした人だけがアクセスできるrunlot access # 現在の設定を確認する
runlot access --jsonこれらのコマンドの実行には admin ロールが必要です。
password モード
runlot access set password --password 'my-secret'--password を省略すると、ターミナルでパスワードの入力を求められます。保護されたデプロイにアクセスすると、アプリより先にパスワード入力画面が表示されます。
org モード
組織のメンバーは、ダッシュボードのログインでそのままアクセスできます。組織のメンバーでないユーザーには 403 が返ります。
app モード
runlot access set app # このアプリにサインインした人だけがアクセス可能このプロジェクトの有効なログインセッションを持つリクエストだけがコードに届きます。それ以外にはプラットフォームが応答します。
| リクエスト | 応答 |
|---|---|
HTML を求めるブラウザの GET・HEAD | /__runlot/auth/sign-in?next=<path> への 302 |
| その他のリクエスト | 401、{"error":{"code":"sign_in_required"}} |
/__runlot/auth/* | サインインできるよう常に通過 |
| バイパスキー付きのリクエスト | org・password と同じく通過 |
- 静的ファイルも例外ではありません。保護されたアプリの JavaScript バンドルも保護対象です。
- パスルールは通過したリクエストにそのまま適用され、範囲を狭めるだけです。
appにはプロジェクトのログイン機能がオンである必要があります。オフの場合は409 login_requiredを返します。モードがappの間はログイン機能をオフにできず (409 access_mode_app)、先に別のモードに変更する必要があります。- セッション Cookie のないリクエストは、プロジェクトを起動せずにフロントで拒否します。Cookie のあるリクエストは、データベースでセッションを確認するためプロジェクトを起動します。
ワーカーでアクセス情報を読む
フロント側で確認したアクセス情報は、リクエストヘッダーとしてワーカーに渡されます。
| ヘッダー | 値 |
|---|---|
Runlot-Access-Mode | public · org · password · app · bypass |
Runlot-Access-Subject | ユーザー ID(モードによって異なります) |
Runlot-Access-Email | ログインに使ったメールアドレス(org モード) |
Runlot-Access-Org-Role | admin · member · viewer(org モード) |
提供しているヘルパーで読み取れます。
import { identity, isSignedIn } from "@runlot/access";
const who = identity(request);
// { mode: "org", subject: "…", email: "[email protected]", orgRole: "admin" }
if (who.orgRole !== "admin") return new Response(null, { status: 403 });クライアントが送った runlot-* ヘッダーはフロント側ですべて削除され、確認済みの値だけがあらためて追加されます。そのため、クライアントがこれらの値を偽装することはできません。
フロントを介さずに実行するローカル環境では、mode は public になり、残りの値は null です。
CI から迂回する
自動化された処理が保護されたデプロイを確認する必要があるときに使えます。
runlot access bypass --newシークレットは一度だけ表示されます。表示されたあとに再確認する方法はありません。
curl -H "Runlot-Access-Bypass: <secret>" https://my-app.me.runlot.app/healthrunlot access bypass --revoke権限のないリクエストはプロジェクトを起動しません
アクセス権限はプロジェクトを起動する前に確認します。権限のないリクエストが来ても、自動停止したプロジェクト は起動されず、そのリクエストは使用量にも含まれません。
パスごとのルール
runlot.json でパスごとにモードをさらに絞り込めます。ルールはデプロイと一緒に動くので、以前のデプロイに戻すとルールも戻ります。
{
"access": [
{ "path": "/admin/*", "require": { "orgRole": "admin" } },
{ "path": "/internal/*", "require": { "emailDomain": ["acme.com", "acme.co.kr"] } }
]
}pathは完全一致のパス、または/*で終わるプレフィックスです。プレフィックスはそれ自体も含みます(/admin/*は/adminも含む)。*はほかの位置には使えません。require.orgRoleは最低限の組織ロールです:viewer、member、admin。require.emailDomainはドメイン 1 つまたはリストです。指定した条件はすべて満たす必要があり、パスが一致するルールもすべて満たす必要があります。{}はモードがすでに許可した人をすべて許可します。- ルールが拒否したリクエストには
403を返します。ルールは最大 64 個です。 - ルールは絞り込むだけです。 モードが閉じているパスを開くことはできません。
- モードが
publicのときルールは無視されます。 その場合runlot deployが警告します。ルールを適用するにはorg、password、appのいずれかに切り替えてください。 appモードでは、ルールにorgRoleやemailDomainを要求できません。 アプリにログインした人は組織ロールも Runlot のメールも持たないため、そのようなルールは決して満たされません。appのプロジェクトにそのルールを含めてデプロイすること、またライブのデプロイにそのルールがあるままappに切り替えることは、どちらも409 access_mode_app_rulesで拒否されます。requireが空のルールは問題ありません。- 共有パスワードで入った訪問者やバイパスシークレットを使ったリクエストは、組織ロールとメールを持たないため、
requireが空のルールだけを満たします。
現在の制限
password モードは繰り返しの誤入力を制限します。連続して何度も失敗すると、しばらくの間それ以降の試行に 429 Too Many Requests を返します。推測を遅らせるだけなので、短いパスワードや推測しやすいパスワードは使わないでください。