【Azure】Microsoft Entra IDで認可してBlob Storageを操作してみた

Azure Functions などのコンピュートリソースを用意しないで、直接 Blob Storage にファイルをアップロードする方法は無いものか、と考えていたのですが、Microsoft Entra ID で認可できればいいみたいでした。

別解として SAS トークンを利用した認可もありますが、どうやら Entra ID が推奨みたいです。

Azure Blob Storage と JavaScript または TypeScript の概要 - Azure Storage
Azure Blob Storage で動作する JavaScript または TypeScript アプリケーションの開発を開始します。 この記事では、プロジェクトを設定し、Azure Blob Storage エンドポイントへのアクセス...

というわけで、今回は Microsoft Entra ID で認可して Blob Storage にファイルをアップロードするところまでやってみます。

本記事紹介している方法は、Microsoft Entra ID やストレージアカウントの RBAC の設定が甘いと思われます。本番環境で利用する場合は十分なレビューが必要です。

構成

Microsoft Entra ID での認証自体は Remix で作った Web アプリを経由させ、Blob Storage へのアップロードはブラウザから直接行うようにします。登場人物をまとめた図は以下です。

ブラウザからMicrosoft Entra IDで認証してBlob Storageにファイルをアップロードするまでの構成図

Microsoft Entra 管理センター

Microsoft Entra 管理センターにて、アプリの登録を行います。アプリの登録ではアプリを一意に示す ID とアプリ自体の認証情報を作成します。

手順は以下を参考に。

クイック スタート: Web アプリへのサインインと API の呼び出しを行う - Node.js - Microsoft identity platform
このクイックスタートでは、Node.js Web アプリと Node.js 用 Microsoft Authentication Library (MSAL) を使用して認証を実装する方法について学習します。

アプリの登録が完了すると、概要ペインからクライアント ID とテナント ID を取得できます。

今回は Web アプリ (機密クライアント) を選択したので、クライアントシークレットを生成します。

パブリックおよび機密のクライアント アプリ (MSAL) - Microsoft identity platform
Microsoft Authentication Library (MSAL) でのパブリック クライアント アプリケーションと機密クライアント アプリケーションについて説明します。

ログイン正常完了時にトークンを送る先をリダイレクト URI として追加します。

ストレージアカウント

Microsoft Entra ID で認証されたユーザーに Blob Storage の操作を許可します。これを実現するには、ロールベースのアクセス制御である Azure RBAC を利用します。

まずは Azure portal から任意のストレージアカウントとコンテナーを作成します。作成できたら、アクセス制御 (IAM) ペインから 追加タブ > ロールの割り当ての追加 を選択します。

ロールの割り当ての追加

データ共同作業者を選択して次へを選択します。

許可するユーザーを追加してレビューと割り当てを選択します。

Remix アプリ

Remix で作ったものは GitHub にアップしてます。

GitHub - ShotaroMuraoka/azure-entra-auth-blob-storage
Contribute to ShotaroMuraoka/azure-entra-auth-blob-storage development by creating an account on GitHub.

以降はポイントのみを説明していきます。

ライブラリ

Remix で Microsoft Entra ID を使った認証と Blob Storage の操作を行うのに以下のライブラリを利用しています。

  • remix-auth: 3.7.0
  • remix-auth-microsoft: 2.0.1
  • remix-auth-oauth2: 1.11.0
  • @azure-storage-blob: 12.26.0

環境変数

.env を作成し、取得した ID とクライアントシークレット、ストレージアカウント名などを記載します。

ENTRA_CLIENT_ID={クライアントID}
ENTRA_CLIENT_SECRET={クライアントシークレット}
ENTRA_REDIRECT_URI=http://localhost:5173/auth/microsoft/callback
ENTRA_TENANT_ID={テナントID}
AZURE_STORAGE_ACCCOUNT={ストレージアカウント名}
AZURE_BLOB_CONTAINER={コンテナー名}

認証・認可

remix-auth-microsoft では MicrosoftStrategy が用意されているので、それを利用した Authenticator を作っています。

ここでは、scope に Azure Storage のアクセストークンの要求を追加しています。

let microsoftStrategy = new MicrosoftStrategy(
  {
    clientId: process.env.ENTRA_CLIENT_ID || "",
    clientSecret: process.env.ENTRA_CLIENT_SECRET || "",
    redirectUri: process.env.ENTRA_REDIRECT_URI || "",
    tenantId: process.env.ENTRA_TENANT_ID || "",
    scope: [
      "openid",
      "email",
      "profile",
      "https://storage.azure.com/user_impersonation",
    ], // optional
    prompt: "login", // optional
  },

取得したアクセストークンはセッション情報に書き出されるので、loader でフロントエンドに渡しています。

export async function loader({ request }: LoaderFunctionArgs) {
  const user = await authenticator.isAuthenticated(request);
  if (!user) {
    throw new Response("Unauthorized", { status: 403 });
  }

  const accessToken = user.accessToken;
  const storageAccount = process.env.AZURE_STORAGE_ACCCOUNT;
  const blobContainer = process.env.AZURE_BLOB_CONTAINER
  return { accessToken, storageAccount, blobContainer };
}

アクセストークンは @azure-storage-blob が提供するクライアントの生成に利用しています。

const blobServiceClient = createBlobServiceClient(
  accessToken,
  storageAccount,
);

const containerClient = blobServiceClient.getContainerClient(blobContainer);
const blockBlobClient = containerClient.getBlockBlobClient(file.name);

try {
  const response = await blockBlobClient.uploadBrowserData(file, {
    blobHTTPHeaders: { blobContentType: file.type },
  });
  console.log("upload succeeded", response.requestId);
  alert("ファイルアップロード完了");
} catch (error) {
  console.error("upload failed", error);
  alert("ファイルアップロード失敗");
}

動作確認

アプリを起動します。

# npm run dev 

ブラウザで http://localhost:5173/login にアクセスします。

ログインボタンを押下すると、Microsoft のサインイン画面にリダイレクトされます。

ストレージアカウントで許可したユーザーの認証情報を入力してログインに成功すると、ダッシュボード画面にリダイレクトします。初回ログイン時にのみ、Azure Storage へのアクセス許可を聞かれます。

任意のファイルを選択して Upload ボタンを押下します。ファイルのアップロードが成功するとメッセージが表示されます。

Blob コンテナーを見てみると、ファイルがアップロードされていることが確認できます。

おわりに

普段、Azure や Entra ID を利用する機会が無いので、難易度が高かったです。次は SAS トークンを試してみようと思います。

タイトルとURLをコピーしました