2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

「HTML共有くん」OCI 版 後編、AWS 版の仕組みを OCI でどう実現したか

2
Posted at

1. はじめに

@minorun365 さんの個人ダッシュボード「HTML共有くん」1を OCI へ移植しました。作り方は前編2に書いています。この記事では、AWS 版の仕組みを OCI でどう実現したかを書きます。AWS 版の機能をそのまま OCI の部品に置き換えて作ったところ、使えるのに要件を満たしていなかった 3 か所(PC の資格情報・成果物の隔離・共有 URL の範囲)と、あとから見つかった 1 か所(ダッシュボードの利用者の名簿)を、AWS 版の仕組み → 最初の実装 → 満たせていなかった要件 → OCI での実現、の順で並べます。3 か所は 3 章に、あとの 1 か所は見つかった時期が違うので 4.2 章に置きます。ここでいう要件は、AWS 版のリポジトリにある脅威モデル(想定する攻撃と守る対象を書いた文書。docs/threat-model.md)と、AWS 版の実装が守っているものです。

以下、@minorun365 さんの HTML共有くんを AWS 版、前編で作ったものを OCI 版と書きます。AWS 版の仕組みの説明は公開されているリポジトリ3の実装に基づき、記事の文章は設計の考え方を引くときだけ参照します。本文に出てくる構成を整理しておきます。

呼び方 構成 本記事での扱い
AWS 版 @minorun365 さんの HTML共有くん。S3・CloudFront・Lambda・DynamoDB・Cognito 各節の「AWS 版の仕組み」。実現の基準にする
OCI 版 API Gateway から Object Storage の期限つき URL(PAR。2 章で説明)へ直結。関数なし。前編で公開した構成 2 章の図(実現したあとの状態)

1.1. 結論(先出し)

  • AWS 版の端末トークンは inbox/ 限定の PAR、別オリジンでの配信は Object Storage からの直接配信(別ホスト名)、URL 単位の署名はページ単位の PAR で実現した(4.1 章の表)。ダッシュボードの利用者の名簿は専用の Identity Domain とアプリの割り当てで分けた(4.2 章)
  • 最初の実装(管理者権限の CLI・同じホスト名・プレフィックス 1 本の PAR)はどれも使えたが、要件(読み書きできる範囲・成果物の隔離・共有の範囲)を満たしていなかった。気づいたのは、AWS 版の脅威モデルを読み直したときと、できたものについて誰まで読めるのかを確かめたときで、使えるかどうかの確認では出てこなかった
  • 確かめる必要があったのは「同じ機能があるか」ではなく、権限の範囲を AWS 版と同じに絞れるかだった
  • 実現したあとも、送信元 IP の条件やセッションの期限と、発行の経路(画面からの共有 URL 発行・スマホからの PC 登録)は AWS 版と違う。前者の補い方は前編の 6.4 章、経路は関数を 1 本足すことになる(4.3 章・4.4 章)

1.2. この記事の範囲

構成と作り方は前編を見てください。この記事は、前編の構成がなぜそうなっているか(AWS 版のどの仕組みを、OCI のどの部品で実現したか)の説明です。


2. 前提となる構成

OCI 版の構成です。前編の 3.2 章と同じ図で、3 章の 3 か所と 4.2 章の名簿を実現したあとの状態を描いています。実測の環境も前編の 2 章と同じです。

OCI 版の構成図。左に「使う人」としてスマホと PC、中央に「入口(本人だけ通す)」として API Gateway と Identity Domains、右に「置き場」として Object Storage のバケット 1 つが console/ pages/ inbox/ の 3 つのプレフィックスに分かれている。スマホはログインして API Gateway を通り、API Gateway は console/ の画面と inbox/ のカードを PAR で直接読み書きする。成果物は期限つき URL で pages/ から直接配信され、PC は inbox/ だけを読み書きする別の PAR を持つ。図には「管理者権限は持たせない」「成果物は期限つき URL で直接(別のホスト名)」「pages/ の URL は 1 枚ずつ別」「閲覧専用の名簿に分けてある」の注記と、脅威モデルについての注記が入る

図の中の「管理者権限は持たせない」「成果物は期限つき URL で直接(別のホスト名)」「pages/ の URL は 1 枚ずつ別」が、それぞれ 3.1 章・3.2 章・3.3 章で実現した結果です。「閲覧専用の名簿に分けてある」は 4.2 章です。以下、一覧とインボックスの画面を管理面、成果物の HTML を閲覧面と書きます(前編と同じ呼び方です)。図の下の注記にある脅威モデルは、1 章で触れたリポジトリの docs/threat-model.md のことです。

なお、管理面の画面は AWS 版の流用に差し替えていますが(4.4 章)、図の経路は変わっていません。

ポイントは 2 点です。配信とエッジでのコード実行を 1 つで担うサービス(AWS の CloudFront に相当するもの)は OCI 自身のサービスとしては無いので(前編の 1 章)、期限つきの共有 URL は Object Storage の事前認証済リクエスト(以下 PAR)4で作ります。そして PAR は署名鍵を持ちません。鍵の管理が不要な代わりに、URL の 1 本 1 本が Object Storage 側のリソースになります(前編の 3.3 章)。この 2 点が、3.2 章・3.3 章と 4.3 章に関わってきます。


3. AWS 版の仕組みを OCI で実現した 3 か所

3 か所とも、1 章に書いた 4 つの項目の順で書きます。4.2 章の名簿も含めた対応を、先に 1 枚にしておきます。

AWS 版の仕組みと OCI での実現の対応図。何を守るかを 4 行に分ける。PC の資格情報(3.1 章)は端末トークン(ペアリング)に対し inbox/ 限定の PAR、成果物の HTML(3.2 章)は別バケット・別ディストリビューションに対し Object Storage からの直接配信、共有 URL(3.3 章)は署名付き URL(対象は URL 1 本)に対しページ単位の PAR、利用者の名簿(4.2 章)は Cognito のユーザープールに対し専用の Identity Domain と割り当て。下の注記に、どの行も機能は同じで範囲を絞る部品が違うこと、実現したあとも違うのは送信元 IP の条件・セッションの期限・発行の経路(4.3 章・4.4 章)とある

3.1. PC の資格情報(端末トークン → inbox/ 限定の PAR)

AWS 版の仕組み。 端末トークンとペアリングです。スマホでコードを発行し、PC がそれと引き換えにトークンを受け取ります。トークンで読み書きできるのは、カード(スマホと PC のやり取り 1 件分。JSON 1 つ)を扱う API のうち、PC 向けの経路(/api/device/*)だけです。

最初の実装。 PC 側から OCI CLI を呼び出す作りにしました。手元には既に管理用のプロファイルがあるので、追加の資格情報は不要だと考えたためです。最初はこの端末トークンを「OCI では不要な機能」と読んでいました。

満たせていなかった要件。 端末トークンで決まるのは「資格情報を持っているかどうか」ではなく、その資格情報で何を読み書きできるかです。管理者権限の CLI では、バケットの中身を読み書きするだけの用途に、テナンシ全体を操作できる資格情報を使うことになります。スクリプトの不具合でも、実行環境が乗っ取られた場合でも、被害の範囲がテナンシ全体になります。持っているかどうかで考えると、既に持っている環境では不要に見えてしまいます。

OCI での実現。 inbox/ プレフィックス(オブジェクト名の先頭部分)だけに絞った PAR を 1 本発行し、スクリプトはそれと curl だけで実行できるようにしました。OCI CLI も管理者権限も使いません。副産物として、削除ができなくなりました。PAR には削除の操作が無いので4、「消せないようにする」設定を書かなくても削除の権限は付きません。

3.2. 成果物の隔離(別のディストリビューション → Object Storage からの直接配信)

AWS 版の仕組み。 S3 バケットも CloudFront ディストリビューションも 2 つに分け、成果物の HTML を管理面とは別のホスト名で配っています。脅威モデルは「悪意ある成果物HTML」の項で、成果物の HTML 自体を脅威として扱っています。AI が生成したものや外部から受け取ったもので、意図しない JavaScript が含まれうるためです。

最初の実装。 ダッシュボードの画面と成果物の HTML を、どちらも同じ API Gateway の下に置きました。認証をかけたホストの内側にあるので安全だと考えていました。AWS 版が 2 つに分けている理由は、当時は構成が細かいだけだと読んでいました。

満たせていなかった要件。 要件は、成果物の HTML を管理面のセッションと API から切り離すことです(脅威モデルの「悪意ある成果物HTML」)。成果物の HTML を管理画面と同じホスト名で配ると、ブラウザは両者を同じオリジン(スキーム・ホスト名・ポートの組)として扱います。成果物の HTML に入った JavaScript が、認証済みのセッションのまま、管理画面が使う API を呼び出せます。最初の実装では、認証は外から入ってくる人に対してだけかけていて、中に置いたコンテンツが脅威になる場合を設計で考えていませんでした。

OCI での実現。 成果物は Object Storage の PAR で直接配り、管理画面だけを API Gateway から配るようにしました。この 2 つはホスト名が別になるので、置き場所を分けるだけでオリジンが分かれます。あわせて成果物の HTML には <meta http-equiv="Content-Security-Policy"> を埋め込み、埋め込み元の制限と外部通信の禁止を宣言しています(6 章の出力の先頭に見えます)。

3.3. 共有 URL の範囲(URL 単位の署名 → ページ単位の PAR)

AWS 版の仕組み。 HTML共有くんの記事には「『URLを知っている人だけ』はアクセス制御じゃない」という節があります1。そのうえで AWS 版は CloudFront の署名付き URL を使い、社内限定のときはカスタムポリシーの Resource に、それ以外は既定のポリシーで、いずれもそのページの URL 1 本を対象にしています5。カスタムポリシーの Resource にはワイルドカード文字も使えるので、プレフィックス全体に 1 本という書き方は CloudFront でもできます。ページ 1 枚に限定しているのは、AWS 版の設計の選択です。

最初の実装。 成果物を配る PAR を、pages/ プレフィックス全体に 1 本発行して使い回しました。ページ(成果物の HTML ファイル 1 つ)ごとに発行すると本数が増えるので、1 本で済ませたほうが管理が楽だと考えたためです。広い範囲も選べるのは AWS 版と同じで、私は管理が楽なほうを選んでいました。

満たせていなかった要件。 要件は、渡した URL 1 本で開けるのがそのページだけであることです(AWS 版の実装の選択)。渡した URL のスラッグ(URL に入るページ名。pages/<スラッグ>/index.html の部分)を別のページ名に書き換えると、そのページが読めます。実際に試したところ、渡したページは 200、スラッグを差し替えた別ページも 200 が返りました。存在しないスラッグは 404、プレフィックスの外は 401 です(6 章)。つまり 1 ページ分の共有 URL を渡すことは、閲覧面すべてを渡すことと同じでした。一覧の取得は禁止していましたが、スラッグは推測できるので、それでは止められません。OCI 版は、URL を知っているかどうかだけでアクセスが決まる状態でした。

OCI での実現。 ページ単位で PAR を発行するようにしました。発行時に対象のオブジェクトを 1 つ指定します。変えたあとで同じ手順で確かめると、スラッグの差し替えは 401 になりました。相対パスで隣のページを指す書き方も 401 でした。


4. 考察

4.1. 3 か所に共通していたこと

3 か所とも、機能が無かったわけではありません。必要なことはすべてできていて、権限の範囲が 1 段ずつ広かったという点で共通しています。

何を守るか AWS 版 最初の実装 OCI での実現
PC の資格情報 端末トークン(読み書きできる範囲を限定) 管理者権限の CLI inbox/ 限定の PAR
成果物の HTML 別バケット・別ディストリビューション 管理面と同じホスト名 Object Storage 直配信で別ホスト名
共有 URL 署名の対象を 1 ページに限定 プレフィックス全体に 1 本 ページ単位に 1 本

そして 3 か所とも、実際に使って確かめる作業では出てきませんでした。画面は開き、カードは往復し、共有した URL は目的のページを表示します。要件を満たしていないことは、うまくいく操作には何も影響しないためです。

見つかったきっかけは、AWS 版の脅威モデルを読み直したときと、できたものについて誰まで読めるのかを確かめたときです。移植の作業では、使えるかどうかの確認と、権限の範囲の確認は別の作業になります。

4.2. ダッシュボードの利用者の名簿(Cognito のユーザープール → 専用の Identity Domain と割り当て)

3 か所を実現したあとに、同じ種類のものがもう 1 か所見つかりました。3 章と同じ 4 つの項目で書きます。

AWS 版の仕組み。 Amazon Cognito のユーザープールに本人 1 人を置いています。セルフサインアップは無効で、サインインはパスワードとメールのワンタイムコードです。ユーザープールは「ウェブおよびモバイルアプリケーションの認証と認可のためのユーザーディレクトリ」で6、AWS アカウントの操作権限を扱う IAM とは別に用意されています。つまり AWS 版では、ダッシュボードを見られる人とクラウドを操作できる人が、最初から別の名簿で管理されています。

最初の実装。 ダッシュボードのログインに、テナンシにもともとある Identity Domain(Default)を使い、そこに OIDC(OpenID Connect)のアプリを登録しました。このドメインは、OCI コンソールのサインインに使う名簿そのものです。アプリの設定「権限付与を認可として実施」(CLI の項目名は allow-access-control)は無効のままで、ユーザーの割り当ては 0 件でした。

満たせていなかった要件。 要件は、ダッシュボードに入れる人を、OCI を操作できる人とは別の名簿で管理することです(AWS 版の実装)。この設定を無効にすると、認証されたユーザーはアプリケーションにアクセスできます7。つまり、そのドメインでサインインできる人は全員、ダッシュボードに入れます。当時このドメインにあったのは管理者と AI エージェント用の 2 ユーザーでしたが、それでも「ダッシュボードを見られる人」と「OCI を操作できる人」が同じになっていました。ダッシュボードの名簿を、クラウドの名簿で代用している状態です。きっかけは「スマホでしているログインは、OCI コンソールのログインと同じものか」という疑問でした。これも動作確認では出ません。ログインはできますし、ほかに誰がログインできるかは画面に出ないためです。

OCI での実現。 この用途だけの Identity Domain(html-share、ライセンス種別 Free)を作りました。閲覧用のユーザーを 1 人置き(表示名は Dashboard Viewer。前編の 5.6 章では dashboard ユーザーと書いています)、OIDC アプリの「権限付与を認可として実施」を有効にして、そのユーザーだけを割り当てています。前編の 2 章の検証環境にある「この用途専用に作ったドメイン」がこれです。割り当てのないユーザー(ドメインの管理者)でサインインすると「アプリケーションにアクセスする権限がありません」になります(前編の 5.6 章)。OCI でログインできる人を同じように絞るには、名簿(ドメイン)を分けるか、アプリの割り当てで絞るかの少なくとも一方が必要です。今回は両方にしました。

なお、割り当てたユーザーでも、IdP(ID プロバイダ。ここでは Identity Domains)の画面にある「マイ・アプリ」からアプリのタイルを開くと同じメッセージになります。ドメインの監査イベントでは、失敗した 4 件はいずれも相手のアプリを表す ssoRp フィールドがアプリの表示名で、ゲートウェイの URL から入った成功はすべて OAuth クライアント ID でした(6 章)。同じメッセージが経路によっても出るので、メッセージだけでは割り当ての可否を判定できません。サインインはダッシュボードの URL から行います。

4.3. 実現したあとも AWS 版と違う点

3 章の 3 か所と 4.2 章の名簿は実現できました。それでも、AWS 版と違う点はあります。実測値と対処は前編の 6.2 章から 6.4 章に書いたので、ここでは違いだけを 1 つの表にします。

何が違うか AWS 版 OCI 版 前編の章
配信元(S3 / Object Storage)を読める範囲 Origin Access Control(OAC)。CloudFront だけが S3 を読めることを IAM で保証し、取り出せる秘密が無い ゲートウェイの設定に PAR を書く。設定を読める権限(read api-deployments。read api-gateways も併せて必要)と実行ログを読める権限(read log-content)が、閲覧面と管理面を読める権限になる 前編 6.2 章
共有 URL の対象 署名の対象は URL で指定する。AWS 版は URL 1 本を対象にしているが、カスタムポリシーの Resource ならワイルドカードでプレフィックス全体も書ける5 オブジェクト 1 つにもプレフィックス全体にも発行できる。AWS 版と同じく広い範囲も選べる(3.3 章) 前編 4.1 章
送信元 IP の条件 URL ごとにカスタムポリシーの IpAddress で指定できる5 PAR に相当する項目は無い(本記事の時点)。指定できるのは対象・アクセスの種類・有効期限・一覧の可否4 前編 6.3 章
セッションの期限 署名 Cookie の期限は DateLessThan で指定し、上限の記載は無い8。30 日は AWS 版の実装の選択 maxExpiryDurationInHours は 24 を超える値を拒否する。公式に上限の記載は無く、説明は認可フローによって生成された JWT トークンをキャッシュする時間の長さ9 前編 6.3 章
URL の実体 署名は手元の計算で、サーバー側には何も増えない PAR は 1 本ごとに Object Storage のリソース。公開のたびに前回分を失効させる 前編 4.5 章・6.3 章
カードの保持期間 DynamoDB の TTL。レコードごとに期限を持てる10 ライフサイクルポリシー。接頭辞単位で同じ日数を適用し、サービスへの権限付与が別に必要11 前編 4.4 章・6.3 章

1 行目は、3 章の 3 か所と同じ構造です。設定に秘密を置く構成では、その設定を読める権限が、秘密で保護していた対象を読める権限と同じになります。OCI のポリシーではアクセスレベルが inspect、read、use、manage の順に累積し12、デプロイメント設定の取得は read に含まれます13。読める範囲が、閲覧面そのものではなく「ゲートウェイの設定を読めるか」という 1 段広いところで決まります。OAC には、そもそも取り出せる秘密がありません。テナンシの参照権限しか持たないユーザーで設定を取得できたこと(6 章)と、実行ログを ERROR にしてポリシーに条件を付ける対処は、前編の 6.2 章に書いています。

セッションの行には、測っていないことが含まれます。OCI の API が 24 を超える値を拒否することは確かめましたが(前編の 6.3 章)、実際に何時間でログインし直しになるかは測っていません。AWS 版の 30 日も、上限がそうだからではなく実装の選択です。

PAR は鍵を管理しなくてよい代わりに、URL 1 本ごとにリソースが増え、URL ごとの送信元 IP の条件は持てません。セッションの期限は PAR ではなくゲートウェイ側の設定で決まり、24 時間を超える値は受け付けられません。

AWS 版には、鍵の生成・保管・CloudFront への登録という工程があります(前編の 6.3 章)。読める範囲がどこで決まるかの違いです。

PAR だから安全、とも言えません。PAR の URL はそれ自体が資格情報で、持っている人は期限まで誰でも使えます。指定できるのは対象・アクセスの種類・有効期限・一覧の可否だけで4、利用者の識別や回数の制限はありません。渡した相手が URL を転送すれば、そのまま読めます。今回の構成で確かめられたのは、対象をページ 1 枚に限定できること(6 章)と、1 本ずつ失効できること(公開のたびに前回分を失効させる運用は前編の 4.5 章)までです。そこから先は、URL の渡し方と、URL が記録される場所(ゲートウェイの設定・実行ログ・ブラウザの履歴)の管理で決まります。設定と実行ログに記録された URL をその読み取り権限で取り出せることは、この表の 1 行目のとおりです。

AWS 版と同じにしたいとき(24 時間を超えるセッション、送信元 IP の条件、PAR を設定に置かない構成)の補い方は、前編の 6.4 章の表にまとめています。関数を挟むかポリシーの条件で絞る、Cloudflare Access を前段に置く(独自ドメインが必要)、変更したページだけ PAR を発行し直す、の 3 系統で、本記事では試していません。

4.4. 画面を AWS 版と同じにしても違う 3 点

管理面の画面を、AWS 版のリポジトリにある web/(一覧とインボックスの画面)の流用に差し替えました。見た目と操作感の差が OCI の部品から来るのか画面の作り込みから来るのかを切り分けるためで、経緯と手順は前編の 4.6 章に書きました。差し替えに必要だったのは、パスの書き換えと、画面が呼ぶ API 8 本のうち 6 本を Object Storage の読み書きに変換する JavaScript 1 ファイルです。ほかの 2 本(共有 URL の発行と PC の登録)は変換せず、使わない API として 501 を返します。ゲートウェイのルートは増えていません(前編の 4.6 章)。PAR も増えていません。

画面の構成と操作は AWS 版と同じになりました(配色だけは変えています)。画面でできることで違うのは次の 3 つで、3 つとも前編の 6.3 章に書いたものです。ここでは、権限の範囲と発行の経路で並べ直します。

何が違うか AWS 版 OCI 版 範囲・経路の違い
セッションの期限 署名 Cookie の 30 日 24 時間を超える値を受け付けない(4.3 章) 指定できる期限の長さが違う。同じにするならゲートウェイの外側の仕組みが必要(前編の 6.4 章)
画面からの共有 URL の発行 画面の操作で AWS 版の関数(Lambda)が署名する。公開範囲(送信元 IP の条件)と日数を選べる PC のスクリプト(前編 4.5 章の share.sh)で PAR を発行する 発行の経路が違う(スマホの画面からか、PC からか)。URL 1 本ごとという範囲は同じ(3.3 章)
スマホからの PC の登録 画面でコードを発行し、PC が端末トークンと引き換える。DynamoDB には端末ごとにハッシュを保存する PC 側で inbox/ 限定の PAR を発行して置く 発行の経路が違う。読み書きできる範囲は同じ(3.1 章)。端末を増やすときは PAR を PC 側で 1 本ずつ作る

共有 URL の発行と PC の登録は、作るなら関数(OCI Functions)を 1 本足すことになります。どちらもサーバー側の計算(PAR を作る署名付きの API 呼び出し、コードの発行と照合)が必要なためです。セッションの期限はゲートウェイの認証の設定で決まるので、関数を足しても延びません。同じにするならゲートウェイの外側の仕組みが必要です(前編の 6.4 章)。

PC の登録は、3.1 章と同じ場所の話です。PC の資格情報を inbox/ 限定の PAR にして読み書きできる範囲は揃いましたが、AWS 版がスマホの画面からコードを発行して端末ごとにトークンを渡すのに対し、OCI 版は PC 側で PAR を作って置くしかありません。画面を同じにすると、画面の作りの差は消え、画面でできることの違いとして、権限の範囲と発行の経路の差がこの 3 行に分かれて見えるようになりました。


5. まとめ

移植は「同じ機能がそろっているか」で進めると、使えるところまでは作れます。今回はそれで、使えるのに要件を満たしていない実装を 3 か所作り、実現したあとにも名簿の 1 か所が見つかりました。

次に同じことをするときに見る観点を 4 つ書いておきます。

  • 移植元(今回は AWS 版)にある部品を「うちの環境では不要」と判断する前に、その部品が何を決めているかを言葉にする。端末トークンを「資格情報の発行」と読むと不要に見えるが、「読み書きできる範囲の限定」と読むと必要になる
  • うまくいく操作を試すだけでは、権限の範囲の確認にならない。権限の範囲は、渡すつもりの無いものを取りに行って確かめる。ログインも同じで、ログインできたことは、ログインできる人が絞れていることの確認にならない
  • 使う部品で広い範囲も選べるとき、楽なほうを選んでいないか見直す。プレフィックス全体に 1 本、は運用が楽になる代わりに範囲が広くなる
  • 画面の作りの差と部品の差は、分けて確かめる。今回は AWS 版の画面をそのまま載せたうえで違いを数え、部品に由来する差を 3 つに絞れた(4.4 章)

権限の範囲の決まり方は部品ごとに違うので、AWS 版と同じ範囲にそろえようとすると、OCI 版では部品の組み合わせと運用が変わります。それに気づく場所が動作確認の外にある、というのが今回分かったことです。


6. 付録: 確認に使った出力

本文で実際に確かめたと書いた点について、出力を抜粋します。識別子とトークンは伏せています。

3.3 章: プレフィックス単位の PAR で、別ページが読めた
--- Step2: sample-report (original URL) ---
HTTP/1.1 200 OK
Content-Length: 3119
Content-Type: text/html
BODY_HEAD80: <!doctype html><html lang="ja"><head><meta http-equiv="Content-Security-Polic

--- Step3: sample-report url -> slug replaced with sample-cost ---
HTTP/1.1 200 OK
Content-Length: 3404
Content-Type: text/html

--- Step4: slug replaced with no-such-page ---
HTTP/1.1 404 Not Found

--- Step5: outside prefix (console/index.html) ---
HTTP/1.1 401 Unauthorized

ページ単位の PAR に変えたあと、同じ手順で確かめた結果です。

[1: sample-report URL as-is]
  status: 200
  title: <title>週次ブリーフ</title>

[2: sample-report URL with slug swapped to sample-cost]
  status: 401

[3: sample-cost URL (manifest正規)]
  status: 200
  title: <title>コストレポート</title>

[4: sample-report URL with relative path to ../sample-cost/index.html]
  status: 401
4.2 章: ダッシュボードのアプリに割り当てが無かった(最初の実装)/専用ドメインで割り当て 1 件(実現後)

最初の実装(2026-08-20 時点。Default ドメインのアプリを oci identity-domains app get で取得し、権限付与を検索した結果)。

"allow-access-control": false,
"allowed-grants": [
    "authorization_code"
],
...
## Grants search (filter: app.value eq <OIDC アプリの ID>)
"opc-total-items": "0"

実現後(2026-08-22。専用ドメイン html-share のユーザーとアプリ)。

display-name         : Dashboard Viewer
allow-access-control : True
grants total-results : 1 (filter: app.value eq <OIDC アプリの ID>)
grant-mechanism      : ADMINISTRATOR_TO_USER

ドメインの監査イベントの抜粋です。

14:28:28 JST | sso.app.access.success | ssoRp=<OAuth クライアント ID>
14:29:00 JST | sso.app.access.failure | ssoRp=HTML Share Dashboard | reason=SSO-1024 | msg=アプリケーションにアクセスする権限がありません。
sso.app.access.success events - distinct ssoRp values: {'<OAuth クライアント ID>'}
sso.app.access.failure events - distinct ssoRp values: {'HTML Share Dashboard'}
4.3 章: 参照権限しか持たないユーザーで、バックエンドの URL が読めた
## [1] api-gateway deployment get --profile DEFAULT
backend.url field present: yes
policy=lab-operators-policy
  statement: Allow group lab-operators to read all-resources in tenancy

DEFAULT プロファイルは、AI エージェント用に作った cloud-lab-agent ユーザーで、グループ lab-operators に所属しています。このグループのポリシーはテナンシ全体の read です。デプロイメントの設定取得が成功し、バックエンドの URL の項目が含まれていました。


参考

  1. AIが作ったHTMLをスマホで見たい! 個人ダッシュボード「HTML共有くん」を作った(@minorun365 さんの記事。3 章「『URLを知っている人だけ』はアクセス制御じゃない」) ↩ ↩2

  2. 「HTML共有くん」を OCI の Object Storage と API Gateway で作ってみた(前編。OCI 版の作り方) ↩

  3. minorun365/html-share(HTML共有くんのリポジトリ。本記事の AWS 版の記述は、このリポジトリの実装に基づいています) ↩

  4. 事前認証済リクエストを使用したオブジェクト・ストレージ・リソースへのアクセスの共有。Oracle Cloud Infrastructure ドキュメント。対象(バケット・オブジェクト・接頭辞)、アクセス・タイプ(読取り・書込み・読取り/書込み)、有効期限(任意の将来日時)、オブジェクト一覧の可否を指定する。バケットやオブジェクトの削除はできない ↩ ↩2 ↩3 ↩4

  5. カスタムポリシーを使用する署名付き URL の作成。Amazon CloudFront 開発者ガイド。「カスタムポリシーで指定する値」の Resource(ワイルドカード文字を使用できる)と IpAddress ↩ ↩2 ↩3

  6. Amazon Cognito ユーザープール。Amazon Cognito 開発者ガイド。冒頭の定義 ↩

  7. 機密アプリケーションの追加。Oracle Cloud Infrastructure ドキュメント。手順 6 の表「権限付与を認可として実施」(選択を解除すると、認証されたユーザーはアプリケーションにアクセスできる) ↩

  8. カスタムポリシーを使用する署名付き Cookie の設定。Amazon CloudFront 開発者ガイド。「カスタムポリシーで指定する値」の DateLessThan ↩

  9. JSONファイルの編集によるAPIデプロイメントへのトークン認証の追加。OCI API Gateway ドキュメント。validationFailurePolicy(type: OAUTH2)の maxExpiryDurationInHours ↩

  10. DynamoDB での有効期限 (TTL) の使用。Amazon DynamoDB 開発者ガイド ↩

  11. オブジェクト・ライフサイクル管理の使用。Oracle Cloud Infrastructure ドキュメント。ライフサイクル・ポリシーの実行に必要な IAM ポリシーと、接頭辞・パターンによる対象指定 ↩

  12. IAM ポリシーの動詞。Oracle Cloud Infrastructure ドキュメント(ページ名は「動詞」)。アクセス・レベルは inspect > read > use > manage の順に累積 ↩

  13. APIゲートウェイのポリシー・リファレンス。「動詞とリソース・タイプの組合せの詳細」の api-deployments(GetDeployment は read api-gateways も必要) ↩

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?