はじめに
株式会社ネクストスケープ Chief Technology Office所属の小野塚です。
今までAIに作ってもらう、もしくはAIに共有するファイル形式としてはMarkdownファイルで望ましいとされてきました。
AIに読み取ってもらうのは確かにそうなのですが、ここ最近Markdownファイルだと読みづらいということが社内に限らずX等でもつぶやかれるようになってきまして、私自身も自分でしっかり読む資料、もしくはお客さまに共有する資料はHTMLに変換していました。
更に最近ではこういったHTMLの資料を社内やお客様にも共有させたいという意見がありまして、これを社内・社外への正式な共有基盤に発展させたいという話がでてきていました。
この共有基盤の仕組み、世の中には色々なサービスが提供されていますし、我々であれば得意とするAzure周り、例えばStatic AppService等を使ったり、色々な実現方法がありますが、ちょうど私が担当している案件でCloudFlareを扱う予定のものがあり、このCloudFlareを用いてこの共有の仕組みが作れないかを調べてみました。
学習を兼ねたお試し実装であるため、セキュリティ面等で不十分な部分があるかもしれません。こういったシステム構成・サービス・機能があるという、あくまで一例かつ参考として見ていただければと思います。
同様の仕組みを考えていらっしゃる方々の一助となれば幸いです。また、今回の仕組みであれば全て無料で実現できますので興味のある方はお試しください。
今回1人・1クライアント分の最小構成で動作確認しましたが、実際当社の運用では「自分が担当しているA社の資料は他の社員に見せたくないし、逆に他の社員が担当しているC社の資料は自分にも見えなくていい」という、社員×クライアントの組み合わせごとの相互不可視化が必要になると思います。
この記事の後半に、運用に耐えうるかのチェックも兼ねて構成方針と運用ルールも考えてみました。
GitHub ActionsとCloudflare Pages
次に今回で使用するGitHub ActionsとCloudflare Pagesについて簡単に触れておきたいと思います(既にご存じの方は飛ばしていただければと。。)。
GitHub ActionsはGitHubに標準で組み込まれている自動化の仕組みで、「リポジトリにpushされたら〇〇を実行する」といった処理を、決まったYAMLファイルを置くだけで動かせます。
今回はこれを使い、pushされたHTMLファイルをCloudflare Pagesへ自動で送り込む係にします。
Cloudflare PagesはCloudflareが提供する静的サイトのホスティングサービスで、GitHub Actionsから送られてきたファイルをそのまま公開してくれます。
サーバーの用意や証明書の設定は不要で、無料枠でも独自の`xxxx.pages.dev`というURLがすぐ発行されます。
今回はここに、後述のCloudflare Access(アクセス制御の仕組み)を組み合わせることで、「誰でも見られる公開サイト」ではなく「許可した人だけが見られる社内外共有サイト」として使います。
何故CloudFlareか
似たような静的サイトのホスティングとしてはGitHub Pages等もありまして、今回GitHubをすでに使っている以上、そちらの方が素直に見えるかもしれません。
実際、社内限定で見せるだけならGitHub Pagesでも十分で、GitHub Organization機能を使えばリポジトリのメンバーだけに公開範囲を絞ることもできます。
ただしGitHub Pagesの公開範囲の制御は基本的に「公開」か「GitHubアカウントを持つ組織メンバーに限定」の二択で、社外のクライアントに見せようとすると、相手にもGitHubアカウントを作ってもらい、リポジトリやOrganizationへの招待を受けてもらう必要が出てくるため、お客さまに毎回GitHubアカウントの用意をお願いするのはあまり現実的ではなさそうです。
Cloudflare Pages+Accessであれば、閲覧者はGitHubアカウント不要で、メールアドレス宛のワンタイムPINだけで認証でき、社内はドメイン単位、社外はメールアドレス個別指定、というように閲覧範囲を柔軟に分けられることもあり、今回のように社内外どちらにも資料を渡す前提であれば、Cloudflareを選ぶ方がセキュリティ的にも良さそうです。
ここで使うCloudflare Accessは、Cloudflareの「Zero Trust」という機能群のうちの一つです。
ちなみに。。Zero Trust(ゼロトラスト)という言葉は皆さんも聞いたことがあるかもしれません。「社内ネットワークの中にいるから安全」という従来の境界型防御の考え方をやめて、社内・社外を問わず誰がどこからアクセスしてきても毎回きちんと認証・認可する、というセキュリティの考え方のことです。
Zero Trustの機能群には社内ネットワークへの安全なリモートアクセス(VPNの代替)や通信のフィルタリングなど色々含まれていまして、今回使うのはそのうちWebサイトやアプリの手前に認証ゲートを置く「Access」の部分だけになります。
作ったものの全体像
やりたいことはシンプルで、AIに直接HTMLファイルを作ってもらい、それをGitHubにpushするとGitHub Actionsにより自動でCloudflare Pagesに公開され、閲覧するにはCloudflare Accessの認証を通す、という一連の流れとなります。
社内はメールドメインで許可し、社外のクライアントは個別のメールアドレスを許可リストに入れる形にしました。認証にGitHubアカウントは不要で、メールアドレスに届くワンタイムPINだけでログインできますのでお客さま側に余計な負担をかけずに済みます。

ステップ1: GitHubリポジトリの用意
まずはリポジトリを作成し、AIに作ってもらったHTMLファイルと、pushした内容をそのままCloudflare Pagesにデプロイするだけの簡単なGitHub Actionsワークフローをpushします。
ステップ2: Cloudflare Pagesにデプロイ
次にCloudflareダッシュボードで新規Pagesプロジェクトを作成します。
詳しい手順・流れは割愛しますが、プロジェクト名を決めて仮ファイルを1つアップロードし、無事 xxxx.pages.dev のURLがデプロイできました。

GitHub側にAPIトークン・Account ID・プロジェクト名をSecrets/Variablesとして登録すれば、以降はpushするたびにGitHub Actionsが自動でHTMLをCloudflare Pagesに反映してくれるようになります。
さらっと流していますが、正直この部分が一番手間がかかる部分でした。といっても手順を把握していれば1時間もかからず終わるものなのですが、トークンの発行や設定の手間、あとは私の手違いでデプロイするファイルが足りていなかったりで多少試行錯誤してしまいました。。(逆に言えばその程度の作業が手間と思えるほど「全体的には」簡単な作業と言えます)
ステップ3: Cloudflare Zero Trust(Access)の設定
いよいよCloudFlare Acccess、認証部分に進みます。
「Zero Trust」を開いてFreeプランを選択します。
まずは以下の画面でGet started。

次に最初にZero Trustを始める場合はプランを選ぶ必要があります。
今回はFree、無料版で大丈夫です。

Access controls → Applications から新規アプリケーションを作成し、種別は「Self-hosted」を選択。

公開先のドメインは、先ほど作成したPagesプロジェクトの nds-html-share.pages.dev が候補に自動で出てきたので、それを選択するだけで済みました。

アクセスポリシーを2本立てる
アクセスポリシーですが、最初に説明した通り、社内用とクライアント用でポリシーを分けます。
まずは以下の画面で「Create new policy」。

社内ポリシーは 社内メールアドレスのドメイン@nextscape.net を許可、クライアント用ポリシーは個別のメールアドレスを指定する形にします。
例えば以下の画面、「Policy rules」においてincludeで「Emails ending in」を選び、その下の入力欄に「@nextscape.net」を選びます。

1つ作成できていることが確認できたら再度「Create new policy」を選んでもう1つ社外向けのポリシーを作ります。

プレビューで2つのポリシーが両方とも同じ公開先に紐づいていることを確認し、アプリケーションを作成。

動作確認
シークレットウィンドウで実際にCloudFlare Pagesの対象のURLを開いてみまして、私の会社のメールアドレスによる認証を経てドキュメントが表示されました。

ところが、次にクライアント用のメールアドレス(今回は自身の個人メールアドレス)で再度ログインを試したところ「Cloudflare sign-in is restricted to members of the account」と表示され、ワンタイムPINの入力画面自体が出てきません。
Zero Trustの「Identity providers」を確認すると、デフォルトで「Cloudflare」というログイン方法だけが登録されており、これが本来のフォールバックである「One-time PIN」の表示を妨げていました。

上記画面で「Add an identity provider」をクリック、その次の画面から明示的に「One-time PIN」を追加します。
以下のように「One-time PIN」が追加されました。 
これで無事、クライアント用メールアドレスでもワンタイムPINでログインできるようになったはずなので試してみます。以下のように「Email」の項目が追加されていますので、ここから個人メールアドレスでログインすると無事対象のページが表示されました。

複数人・複数クライアントで使うときの構成
ここまでは「1人・1クライアント」の最小構成ですが、実際の社内利用を考えると、社員それぞれが別々のクライアントとやり取りしていて、互いの資料を見せたくないケースがほとんどのはずかと思います。
ここで整理しておきたいのは、守るべきレイヤーが2つあるという点です。
1つ目は「公開されたHTMLを誰が見られるか」で、これはCloudflare Accessで実現できます。
同じPagesプロジェクトの中でも、URLのパスごとに別々のApplicationとポリシーを設定すれば、パスごとに閲覧できる人を分けられます。
2つ目は「HTMLファイルそのものを誰が見られるか」で、これはGitHubリポジトリの権限の話になります。GitHubのアクセス権はリポジトリ単位が基本で、フォルダ単位の権限分けはできません。
つまり1つのリポジトリの中でフォルダだけ分けても、そのリポジトリに書き込み権限を持つ人全員が、他の担当者のHTML原稿をgit上でそのまま読めてしまいます。普段の運用を考えると無用な共有は避けたいです。
なので、社員同士やクライアント間で本当にお互いの資料を見えなくしたいなら、フォルダ分けではなく「担当者×クライアントの組み合わせごとにリポジトリを分ける」方が良さそうな気がします(実際は会社によっても違いますし、あくまで案ですが。。)。
その場合は今回の手順(GitHubリポジトリ作成→Cloudflare Pages作成→APIトークン発行→Secrets登録→Access Application作成→ポリシー設定)を、組み合わせごとにそのまま繰り返すだけで対応できます。
運用ルール(案)
更にリポジトリをプロジェクトで分けて複数人で回すことを前提に、最低限決めておきたいルールをちょっと考えてみましたので書いておきます。
1. 命名規則
リポジトリ名・Cloudflare Pagesプロジェクト名は「クライアント名-プロジェクト名」で統一する(例: share-companyname-projectname)
2. リポジトリは担当者×クライアントの組み合わせで1つ
1つのリポジトリに複数クライアントの資料を混在させない。GitHub側の権限は「担当者本人+IT管理者」のみに絞る。
3. Cloudflare Access側もリポジトリと1対1で対応させる
Applicationのポリシーは「社内担当者本人のメール(または@nextscape.netに加えて担当者を明示的にIncludeする条件)」+「そのクライアントの個別メールアドレス」の2本立てを基本形にする。
4. ポリシーの追加・変更はIT管理者経由の申請制にする
Free/Proプランでは、Cloudflare Access自体の管理権限を「この担当者はこのポリシーだけ編集可能」のように細かく分けられない(それができるのはEnterpriseプラン相当)。
なので当面は、担当者がクライアントの窓口変更などでメールアドレスを追加したい場合、IT管理者に依頼してダッシュボード側で反映する運用にする。
5. 案件終了・担当者交代時は速やかに棚卸しする
クライアントとの契約が終わったらApplicationごと削除するかポリシーからメールアドレスを外す。担当者が変わったら、リポジトリのGitHub権限とAccessポリシーの両方を合わせて更新する。ややアナログチックですが、棚卸しのために「リポジトリ名・担当者・クライアント名・作成日」を一覧化した台帳を1つ作っておくと管理しやすいかもしれません。
まとめ
「AIが作ったHTMLをpush→自動デプロイ→認証済みURLで共有」という一連の運用が、無料枠の範囲でひとまず動くところまで確認できました。
複数人での本格運用にあたっては、リポジトリとCloudflare Accessを担当者×クライアント単位で1対1に保つことと、ポリシー変更を誰が担うかを決めておくことが肝になりそうです。
MarkdownファイルでそのままGitにpushし、内部でHTMLに変換する仕組みを作ってみるのも面白いかもしれません。また、社内のSSO(Google WorkspaceやMicrosoft Entra ID)と連携させることができればなお良いかなと思いますが、まずはここまでとさせてください。
当社ネクストスケープはこのように生成AIをはじめとした新しい技術・知識を日々取り入れており、Webサイト、スマホアプリ、Hololensアプリの開発をはじめ、CMSを利用したサイトの新規構築やリニューアルなど、お客様のニーズに幅広く対応いたします。お困りのことがございましたら、いつでもお気軽にお問い合わせください。
(以下当社お問合せフォーム)
当社では一緒に働いてくれる仲間を募集しています。是非以下のサイトよりお申込みください。