0
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?

Azure Functionsでテナント作成からAPI構築まで!前編ではGit/CORS/Blob/KeyVault連携など全部解説

Last updated at Posted at 2025-07-09

① 目的

AzureでAPIサーバーをAzureの機能(PaaS)で開発して動作させるまでの、ハンズオン形式の手順書です。
Azureのアプリの開発エンジニアが少ないことを想定して、基本的な使い方から説明しています。
Dockerで定番のLAMP環境構成を採用しなかったのは、次の記事で紹介予定のマルチテナントアプリ構成を実現しやすいためです。
前半は初心者向けで、まず動くAPIアプリを作っていきます。後半の概要は、記事の最後を読んでください。

Windows端末で操作の手順書です。macユーザーが読むことも考慮していますが、私はmacユーザーではないのでこの手順書で十分かどうかはあまり考慮していません。Linuxクライアント端末からの手順は掲載していません。
私は全ての権限が付いているユーザーで操作しながら作成したので、必要な権限の検証が不十分です。

② AzureとAWSの比較とハンズオンの構築費用

AzureとAWSのどちらでアプリを開発すべきかということですが、AWSの方が技術を習得するためのナレッジが多く、圧倒的な人気とシェアがあります。
どちらもクラウド基盤でおおむね同じ要件を実現可能ですが、UIや内部的な設定方法など構築手順が大きく異なり、案件の性格も異なります。
Azureアプリは、官公庁や金融など外部要件が厳しいウォーターフォール型案件に偏重しており、AWSは幅広く案件が存在します。

• 今回のハンズオンの構成の規模別料金比較です。

安いほう 規模感と説明 API実行回数/日
AWS テスト段階や社内ユース 1〜1,000回程度
AWS 小規模本番 1,000〜10,000回程度
同等, Azure 中規模商用 10,000〜200,000回程度
Azure 大規模API基盤 200,000〜1,000万回
Azure 超大規模・グローバル 1000万回以上/日

上記表で、金額に与えるインパクトが大きい要因は、関数とVM(アプリサーバー)の料金プランです。
AWS LambdaとAuzre Functionsでどのような料金プランが用意されているかの説明です。

• coldスタンバイ
使ってないときはシャットダウンして、毎回異なるインスタンスを起動するのでIPが変わるのがcoldです。
AzureはcoldスタンバイのAppServiceプランが存在しません。
AWSは最小0円から従量課金制です。追加で4,300円のProvisioned Concurrencyプランを追加すると、hotスタンバイになります。固定IPではありませんが、API(Lambda)だけ起動し続けるので応答速度はなります。

• hotスタンバイ
Azureの最小コストは1.2万円ぐらい。AWSの最小コストは2万円ぐらい。
信頼性が必要なアプリでは、ホワイトリスト方式でIPアドレスの疎通を許可している場合や、監査要件で固定IPが指定されてるためです。
AWSは料金プランを変更するだけで、[開発環境プラン→本番cold→本番hot]へ自由に変更できます。
Azureは環境の作り直しが必要になります。具体的には、AppService(この手順のFunctions作成の項目に相当)の作り直しと、それに伴うルーティングの再設定が必要です。

まとめると以下の表になります。

cold hot(固定IPなし) hot
Azure 0~従量課金 なし 12000円~
AWS 0~従量課金 4,300円~(Provisioned Concurrency) 20000円~

ちなみに、AWSでcoldを回避する方法はFargate/EC2のように他にも用意されています。

• 今回のハンズオンは月額10円に収まりました。
※Azure SQL Databaseは月額費用が掛かってしまうのですが、記事が長くなりすぎたので今回はハンズオン計算対象外です。
スモールスタート段階での料金比較を具体的に計算します。
1日当たり1000回程度利用される本番環境のプランの金額は以下のようになります。
Azureは、プラン変更のみで本番環境にスケールアップ可能な料金プランを選んでいます。

Azure(APIを1日当たり1000回程度利用)

Azureリソース名 Azureプラン名(本番移行可能なプラン) 月額
Functions Premium Plan 約24,000円/月〜(常時稼働・スケーリング前提)
App Service Web App(同一 Premium Plan 上) 追加コスト 0円(同一プラン内で共存)
Blob ストレージ Standard General Purpose v2(LRS) 利用量に応じて従量課金(数円〜数百円)
Application Insights Basic 約600円/月〜(ログ量依存)
Azure SQL Database Standard S0 約1,500円/月〜(DTUベース)

AWS(APIを1日当たり1000回程度利用)

AWSリソース名 AWSプラン名 月額
Lambda Lambda + Provisioned Concurrency (2 GB) 4,300円
EC2 EC2 t3.micro (固定IP可) 1,150円
S3 S3 Standard 1 TB × ¥3/GB 3050円(従量課金)
CloudWatch CloudWatch Logs + Insights 300円〜600円(従量課金)
RDS RDS MySQL t3.micro + ストレージ 2,000円(半固定+従量課金)

③ リソース作成時の補足

• リソースの選択方法は複数あります。初めて使うリソースはAzure Portalの検索窓に入力して候補を選んでください。
使用したリソースはトップ画面などにリコメンド表示されて選択できるようになります。
image.png

• 新規作成や設定変更を行ったときは、画面右上のベルマークが処理中に変わります。通知を開いて処理完了を待つことを推奨します。処理に10分や30分程度かかることがあります。
ブラウザの更新を行うと進捗が確認できなくなります。また、処理が失敗した場合の原因を確認できなくなります。
処理が成功する前に次の作業をすると、影響が出て失敗する可能性があるので待ってほしいという意図もあります。
image.png

④ サブスクリプション購入

  1. 規定のディレクトリ[サブスクリプション > 追加]を選択して、従量課金制を選択してクレジットカード課金画面に推移します。
    ※規定のディレクトリとは、Azureにログインしたときのデフォルトのテナントを指します。
    ※無料試用版を選ばない理由は、ハンズオンで紹介する構成のテスト使用をしても数円~数十円と安く私は7円でした。
    また、無料使用期間を過ぎると成果物のリソースを利用可能なまま移し替えができないので、本番稼働へスライドしづらいためです。
    image.png

  2. テクニカルサポートの選択画面では、「テクニカルサポートはありません」を選択してください。
    後から変更可能です。
    Azureの構築で分からないことを、Azureのサポート要員に問い合わせできる機能についての選択画面です。
    image.png

ちなみに、サポートへの問い合わせ機能はAzurePortalの右上の?です。
問い合わせには、サービス サポート共同作成者(Support Request Contributor)ロールが必要です。
image.png

  1. 完了後はサブスクリプション一覧に"Pay-As-You-Go"が追加されます。
    image.png

無料試用版でもハンズオンする場合は、ところどころ読み替えが必要で、一部機能が使えずにハンズオンについてこれない可能性があります。
"Pay-As-You-Go" = 従量課金制
"Free Trial" = 無料試用版
※無料試用版の金額が7.26円になっていますが、制限された範囲内の使い方のうち200ドル分は値引きされます。

⑤ テナント(Entra ID)作成手順

テナントを複数作成することで、サーバーを個別に作成するイメージで環境を分離できます。
同じテナントで作業したい場合は、この作業は必須ではありません。
テナントにサブスクリプションが紐づくのですが、さきに一つ目のサブスクリプションを作成する必要があるので前の手順が存在しています。

  1. [Entra ID > テナントの管理 > 作成]でテナントの作成を開く
    image.png

  2. Microsoft Entra IDを選択します。
    image.png

※テナントの種類は以下の4種類があります。

種類 基本料金 ユーザー数ベースの課金 備考
Microsoft Entra ID(Free) 0円 基本機能のみ。Graph API / SSO / ユーザー登録などに制限なし。
Azure AD B2C 初期無料、以後ログイン回数ベース課金 月間ログイン回数やMAU(アクティブユーザー数)で課金。ユーザー登録数そのものではない。
Microsoft Entra 外部 ID 基本無料、招待ユーザー数や認証数で課金 外部ユーザー(B2B)を招待し、条件付きアクセスやMFAを適用する場合のみコスト発生。内部ユーザーには課金なし。
Microsoft Entra ID P1 / P2 約450~800円/ユーザー/月 条件付きアクセス・ID保護・ライフサイクル自動化などが対象。Graph APIで高度な操作をする場合に必要。

※テナント作成時には選択できません。後から「テナントに対して購入して割り当てる」形式です。

※いろいろ操作環境構築済みのテナントや外部テナントでの操作では、"Microsoft Entra ID"を選択できない場合があります。"Microsoft Entra 外部 ID"を選択するか、原因追及してください。

  1. 次の構成の画面で詳細を設定して作成します。
    組織名: 任意のサーバー名
    初期ドメイン名: 世界中の全Azureドメイン名の中で重複しない名前を設定します
    国: データセンターの場所です
    image.png

  2. ログイン中のユーザーが複数テナントに登録されている場合は、右上[歯車]からテナント切替ができます。
    テナントを作成したユーザーは、新しいテナントのすべての権限を持つユーザーとして自動登録されるので、テナント作成時点で表示されます。
    image.png

ちなみに、[Entra ID > 概要]のライセンスに、Microsoft Entra ID Freeと書いてあればテナントの種類がMicrosoft Entra IDであるという意味です。
Freeというのは、Microsoft Entra IDで作成したあとに、P1 / P2の課金がされていないという意味です。
image.png

⑥ UIの初期設定

[右上の歯車 > 外観]から設定できます。
[スタートアップ]ディレクトリを設定しておくことで操作が捗ります。

項目名 内容
メニューの動作 ポップアップ / ドッキング を選択可能。画面が小さい場合は「ポップアップ」推奨。
サービスメニューの動作 折りたたみ済み / 展開済み を選択可能。画面が小さい場合は「折りたたみ済み」推奨。
テーマ 自動 / 明 / 暗 を選択可能。
スタートアップページ ホーム / ダッシュボード を選択可能。ダッシュボードはカスタマイズ可能。
スタートアップディレクトリ 複数テナントがある場合に表示され、ログイン時に初期表示されるテナントを指定できる。

image.png

⑦ リソースグループ作成

  1. [リソースグループ > 作成]からリソースグループを作成します。
    ※リソースグループとは、アプリサーバーのコンテナの役割に近いです。
    最初に作成するリソースグループやリソースの情報は変更できないものばかりなので、注意してください。
  • 設定値の補足
    リソースグループ名: 任意です。Microsoftの構成例では、リソースグループということを表現するために末尾に-rgと命名します。
    タグ: 作成したものを後で機械的に抽出する場合に使用します。チームの運用方針がある場合に設定します。
    リージョン: 任意です。APIを利用する地域から近いところを指定すると応答速度が速くなります。Japan Eastは人気エリアなので作成に失敗したり、安い料金プランではAppService作成時にマシン不足で失敗することがあります。日本リージョンを選びたい場合は、練習ではJapanWestで統一することを推奨します。
    image.png

⑧ Functionsとストレージアカウント作成

手順の前の説明は、AzureのUIがイケていないために失敗するポイントを説明しています。
Functionsはリソースの中でも特に複雑です。

目指す構成と現在地です。
既にこのハンズオンで紹介済みのものに[済み]と表記して、この手順で作るものに[この手順]と記載しました。

┌─ 済み:Entra ID(ユーザー管理)
├─ 済み:テナント(Azure Active Directory)
│   ├─ 済み:サブスクリプション(課金)
│   │   ├─ 済み:リソースグループ(論理的なリソースのまとまり)
│   │   │   ├─ この手順:App Service(Web App / API App のホスティング基盤)
│   │   │   │   └─ この手順:Functions(配下に関数をたくさん作成します)
│   │   │   │       ├─ この手順:ストレージアカウント(Functionsに付属するストレージ)
│   │   │   │       └─ この手順:Application Insights(Functionsの監視やログ)
│   │   │   ├─ Azure SQL Database(構造化DBで課金を管理する)
│   │   │   │       └─ Key Vault(接続文字列や資格情報を安全に保管)
│   │   │   ├─ Blob ストレージ(API出力ファイル保管用のストレージ, ストレージアカウントの機能)
│   │   │   │       └─ Key Vault(接続文字列などの機密情報を安全に管理)

構成内容の説明と、存在する課金プランの例です。

要素 種類(階層) 課金プランの例
サブスクリプション 課金・契約の最上位単位 Free Trial / Pay-As-You-Go / CSP / EA など
App Service アプリ実行基盤(ホスティング) Free / Basic / Standard / Premium V2/V3 / Isolated
Functions App Service の下層機能 Dynamic (Consumption) / Premium / App Service Plan
Azure SQL Database データベースサービス DTU-based / vCore-based / Serverless
Blob ストレージ ストレージリソース Hot / Cool / Archive(使用量ベース課金)
Application Insights 監視・ロギングツール 従量課金(データ取り込み量と保持期間に応じて課金)

• リソースやリソースグループなど、名前などの基本情報を変更する場合は作り直しになります。
• サブスクリプションをFree Trialで作成すると、機能が制限されるので本番環境としては通用しません。
課金をFree Trialから変更できないので、配下のリソースグループ以降が作り直しになります。

• ハンズオン手順は、App Servceを作成してからFunctions(関数アプリ)を"従量課金"で作成する手順です。
固定料金無しで、ほぼ無料で開発できます。
これを、Functions作成を先にするとApp Serviceが自動作成されて、プランはDynamicになります。
DynamicからBasicやPremiumにアップグレードできないので、App Serviceを意図して先に作ることを推奨します。

表示順 ホスティング プラン表示名 対応する価格プラン(SKU名などの例)
フレックス従量課金(Flex) Free/Flex(※従量課金、SKU指定なし)
従量課金(Consumption) Dynamic(Free/従量課金、SKU指定なし)
Functions Premium EP1 / EP2 / EP3(Premium plan)
App Service Free / Basic B1 / Standard S1 / Premium P1v3
Container Apps 環境 SKU指定なし(vCPU・メモリベースの従量課金)

Functions作成画面のApp Serviceの料金プランの選択肢です。
この画面では、上記表のうちどのプランが作成されるか理解できません。
そのため業務では先にAppServiceを作成します。
image.png

• ストレージアカウントの専用作成画面では、スペック選択, セキュリティ, 削除日数など細かく設定項目があります。
しかし、Functions作成画面でストレージアカウントを自動作成する場合は、名前ぐらいしか設定できません。
Functions作成時に割り当てたストレージアカウントを変更することはUIではできません。手間がかかります。

• 作成したリソースなどを削除するときは、基本的に依存関係にあるものが同時に削除されません。
テスト作成と削除を繰り返したときは、リソースグループの画面を確認して、台帳を作成したほうがいいかもしれません。

  1. [Functions(日本語表示だと関数アプリ) > 作成]を選択して、従量課金を選択します。
    日本語表示だと関数アプリと表現されます。
    ※フレックス従量課金は、料金が高い代わりにFunctionsの利用が活発になってもスケールアウト(処理機能増加)によって動的に対応する機能です。
    image.png

  2. Functionsの詳細設定をします。
    今回は、App Service, ストレージアカウントを自動的に作成します。普通の手順では推奨しません。
    Application Insightsも有効にします。
    image.png

  • 設定値の補足
    関数アプリ名: Azure全体でユニークな名前にする必要があります。命名規則は[環境名+サーバー名]を推奨します。ハイフンを使用可能です。
    オペレーティングシステム: MicrosoftはLinuxの選択を推奨しています。legacyと表示されていますが最新のDebianというLinuxOSです。
    ランタイムスタック: 今回は今回はPowerShellCoreを選択します。動作コードを用意しているためです。Custom Handlerとは、選択不可能な言語で開発する場合に選択します。
    リージョン: 任意です。JapanEastを選んでエラーになる場合はAzureのマシン不足なので他を選んでください。
    image.png
  1. Storageタブでストレージアカウントを作成します。
    ストレージの名前は、Azureの中でユニークである必要があります。
    推奨する命名規則は[環境名+サーバー名+storage]です。環境名とはprod, stg, devなどです。名前が長くなるのを避けるために、本番(prod)環境のリソース名の場合はprodと記載しない命名規則も一般的です。
    例: devdemoappstorage

基本的に1つのFunctionに対してストレージアカウントを個別に作成します。思わぬバグを回避するためです。
Fuctionはスクリプトファイルで、Functions実行にかかわる一時ファイルやログ管理をするフォルダと空き容量が必要になるので、このストレージアカウント(フォルダ)で管理する仕組みです。
image.png

  1. 他はデフォルト値で作成します。
    Application Insightsという監視ログ機能は無料枠に収まるので、有効のままで問題ありません。
    image.png

Application Insightsは無料枠が "5GB/月" あり、少し使う程度では超えることがありません。
image.png

  1. 補足
    ストレージアカウントを専用画面から別途作成して、作成したストレージアカウントからFunctionsを作成する逆の手順も可能です。
    リソースグループ, ストレージアカウント名, リージョンを設定すると、上記手順で作成したものと同等の設定で作成できます。
    データ保護のタブで論理削除の日数は、意図的に削除した後に、内部的にどれぐらい保存するかという意味です。
    image.png

⑨ Azure Portal上でFunctionのコーディング

Functionsを体験するために、簡単なコードを動かします。
推奨するVisualStudioCodeでコーディングはこの後のハンズオンで紹介します。

  1. [Functions(関数アプリ) > 作成したFunctions]を選択して、AzurePortalで作成の項目にある[関数の作成]を選択します。
    image.png

  2. Functionsのテンプレートは [HTTP trigger]を選択します。
    image.png

  3. 関数名は任意です。アンダーバーとハイフンが使えます。
    Authorization levelはFunctionを選択します。
    image.png

Authorization levelの説明です。これらのキーは流出しないように気を付けてください。

レベル 意味 主な用途 セキュリティ強度
Function 関数ごとのアクセスキー(code=xxxxx)が必要 通常の外部公開API
Anonymous インターネット上に公開して自由にアクセス可能 テスト, 社内用モック
Admin Function全体の管理者キーが必要 Azure内部ネットワークで完結する管理用途
  1. 関数の画面を開くとコード入力画面が表示されます。
    Functions作成時にPowerShellを選んでいるので、以下の文字列"HelloWorld"をGETするコードを入力します。
param($Request)

Push-OutputBinding -Name Response -Value @{
    StatusCode = 200
    Body       = "HelloWorld"
}

引数が無いのに "param($Request)"を書く理由は、APIの処理を実行するためのトリガーの役割をしているためです。
内部的にはAPIの処理を受け付けて、情報がNULLのJSONを受け取ったという処理になっています。

[テスト/実行]を選択して、AzurePortal上でコードをテスト実行します。
HTTPメソッド: 引数が無いプログラムなのでGETを選択します。
キー: 任意です。本番運用では基本的にdefaultを選択します。
image.png

  1. 入力タブ右下の[実行]を選択すると、出力タブにHTTPステータスコードと返り値が表示されます。
    image.png

  2. [関数のURLの取得]を選択して、任意のAPIのURLをコピーします。
    image.png

キーの種類の説明は以下のとおりです。

キー種別 説明 権限範囲 用途
ホストキー(Host Key) Function App 全体で共通 全関数 管理系関数, 複数関数を連携する
関数キー(Function Key) 特定関数だけにアクセス可能 1つの関数 通常の API 呼び出し
マスターキー(_master) 完全な管理キー 管理API含む全機能 管理者による管理操作
  1. コピーした任意のキーのURLをブラウザで開くと返り値を確認できます。
    インターネット上にAPIが存在することを確認できます。
    image.png

⑩ Functionsで引数付きスクリプトのコーディング

  1. 同じ手順で新しい関数を作成して、以下の設定をしてください。
    3つの数字をPOSTすると、合計値を返却するコードです。
param($Request)
try {
    $A = [int]$Request.Body.A
    $B = [int]$Request.Body.B
    $C = [int]$Request.Body.C
    $result = $A + $B + $C
    Push-OutputBinding -Name Response -Value @{
        StatusCode = 200
        Body       = @{ result = $result }
    }
}
catch {
    Push-OutputBinding -Name Response -Value @{
        StatusCode = 500
        Body       = @{ error = $_.Exception.Message }
    }
}

○ HTTPメソッド: 引数があるプログラムなのでPOSTを選択します。
○ 本文: JSON形式で複数の引数を渡します。

○ JSONの例

{
  "A": 10,
  "B": 20,
  "C": 30
}

image.png

  1. [実行]を選択すると、HTTPステータスコードと返り値が表示されます。
    image.png

11. PostmanでAPIテスト

Postmanとは、APIのテストを多機能に実施できるツールです。CSVファイルなどを引数として扱えたり、複雑なAPIを細かいログで確認できます。
今回のハンズオンでは紹介しませんが、同じく有名なのがSwaggerというAPIツールです。APIのコードを仕様書として見やすく保存して実行できます。現場では両方とも使われます。

  1. Postmanの公式サイト "https://www.postman.com/downloads/" へアクセスして、OSに合うインストーラーをダウンロードしてください。
    image.png

  2. インストーラーの起動後の初回画面で[Sign up(新規登録)]を選択して、Googleアカウントや任意のメールアドレスでアカウント登録してください。

  3. Postmanを実行できたら、[+タブ]を押してAPIのテスト画面を開きます。
    左側が[Workspace]で、右側が作業スペースです。
    image.png

  4. 動作テスト前に、Functionsの関数の画面でログを表示しておくと、Function内部のエラー状況をリアルタイムに表示できます。
    ログはとても長いので、分析には生成AIの利用をお勧めします。
    image.png

  5. GETの動作テストをします。
    GETを選択して、前の手順で作成したHelloWorldを表示するAPIの任意のURLを入力して、[Send]を押してください。
    緑色のステータスコード(200 OK)と、返り値が右下に表示されます。
    image.png

  6. POSTの動作テストをします。
    POSTを選択して、前の手順で作成した引数を合計するAPIの任意のURLを入力してください。
    image.png

Bodyタブに移動して、rawを選択してJSONを選択します。引数のJSONを入力してください。
[Send]を押してください。
緑色のステータスコード(200 OK)と、返り値が右下に表示されます。
image.png

6. VSCodeでFunctionsをコーディングする

  1. 公式サイト "https://code.visualstudio.com/" からインストーラをダウンロードします。
    image.png

macOSの場合は、Homebrew経由でインストールが推奨されます。
Homebrewが無い場合はインストールします。

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Homebrewのインストール先フォルダに、Homebrewでインストールしたものが配置されます。
配置先は brew --prefix で確認できます。
配置先のディレクトリを、他のユーザーに rx(read, execute) 権限をつけると、他のユーザーも利用できます。

HomebrewでVSCodeをインストールします。

brew install --cask visual-studio-code
  1. VSCodeを起動できたら、Extensions(拡張機能)から「Azure Functions」を検索してインストールしてください。
    image.png

  2. インストールが完了すると、Azureのアイコンが左メニューに表示されます。[Sign in to Azure]を選択します。
    image.png

  3. 別ウィンドウでログイン画面が表示されます。
    ※テナントの種類や多要素認証設定によって、実際の画面が異なる場合があります。
    image.png

  4. ログインしたら、[RESOURCES > サブスクリプション > Function App > Function名 > Files]を開きます。
    Files "Read-only" となっており、操作権限が制限されていることが分かります。
    image.png

Files "Read-only" でなければ、VSCodeだけで一部編集したり、Functionsのすべてのデータを丸ごとダウンロードするなど直感的な操作が可能です。
しかし、今回の構築例はAppServiceが安価なDynamicです。
Dynamicや試用プランのConsumptionプランは、読み取り専用を変更できません。編集やデプロイは以降の手順で行う必要があります。

Read-only になっているロジックは、WEBSITE_RUN_FROM_PACKAGE=1 が有効になり、VSCodeで簡単に修正する仕組み(ZIPマウント) を利用するための、wwwrootへの書き込み権限が無いためです。
image.png

もし本番環境レベルの Premiumプラン, Dedicatedプランの場合は、以下のようにIAMロールを割り当てたユーザーは、Read-only を書き込み権限に変更できます。

[Functions > アクセス制御(IAM) > ロールの割り当ての追加]を選択します。
image.png

以下のいずれかのロールを割り当てると、Files の "Read-only" が解消されて、VSCodeから簡単にコードの修正ができるようになります。

ロール名(英語) 日本語表記 説明
Contributor 共同作成者 すべての Azure リソースの作成・編集・削除が可能(RBAC上、所有者を除いて最大権限)。ただし、アクセス許可の付与はできない。
Function App Contributor 関数アプリ共同作成者 Azure Functions に限定して、作成・編集・削除が可能。他のリソース(例:Storage、App Service)には影響しない。
Website Contributor Web サイト共同作成者 App Service/Function App に対する WebDeploy(ZIP デプロイ) 等の権限がある。コードの配置はできるが、設定変更などは不可。

image.png

  1. Functionsの画面で、[… > アプリコンテンツのダウンロード]を選択してください。
    前述のとおり Functions を Visual Studio Code で直接編集したりダウンロードできないので、ローカルに Functions の中身を Zip でダウンロードします。
    image.png

Portal からダウンロードした Zip ファイルの中身の例です。
image.png

  1. インストーラから VSCode を起動できたら、[File > Open Folder] を選択して、前の手順でダウンロードした Zip を解凍した Function のフォルダを指定してください。
    image.png

  2. 読み込みが完了したら run.ps1 を開いてください。
    image.png

私のコードがカラフルなのは、拡張機能で PowerShell をインストール済みのためです。
一般的には他の言語を選ぶと思うので、拡張機能のインストールは省略します。

  1. 最後の行にコメントを書くなど編集を加えると、左上のファイルアイコンに①と表示されます。
    これは保存されていない編集中のファイルが存在していることを表現しています。
    Ctrl+Sで上書き保存すると数字バッジが消えます。
    image.png

Windows PCのローカルの PowerShell で確認すると日本語が文字化けしており、UTF-8で保存されていることが分かります。
Azureにデプロイすると正常に表示されます。
image.png

  1. [サブスクリプション(Pay-As-You-Go) > Function App > 関数名] を右クリックして、[Deploy to Function App] を選択します。
    image.png

初回はダウンロード資材のフォルダを選択します。

  1. VSCode のプロジェクトとして登録するか確認されるので、Yes を押します。
    Yes を押さないと Deploy ができないので必ず押してください。
    image.png

Azure にデプロイするかの確認画面です。Deploy を押します。
image.png

※次回からは [Deploy to Function App] を選択するとすぐに Deploy ボタンが出るように省略されます。
image.png

  1. Azure Portal で関数を確認すると反映が確認できます。
    image.png

  2. VSCode で開いていたフォルダを確認すると、[.vscode] というフォルダが作成されています。
    VSCode のプロジェクトとして登録したために作成されたものです。
    image.png

  3. VSCode から [Deploy to Function App] 機能でデプロイすると、Azure Portal 上では関数が読み取り専用になって修正できなくなります。
    この状態だと、VSCodeからのデプロイのみを受け付ける設定です。
    image.png

なぜこうなるかというと、[Deploy to Function App] のデプロイは、以下のコードと同じ動作で、Zip形式で展開してpushするという動作です。
Zipデプロイだとロックがかかる仕様です。

func azure functionapp publish <APP_NAME>

pushするときにロックを回避する場合には、以下のように Zip を使わない通常デプロイで push する必要があります。

func azure functionapp publish <APP_NAME> --nozip

Azure Portal の関数の読み取り専用を解除する場合は、[Functions > 環境変数 > WEBSITE_RUN_FROM_PACKAGE] の値を 0 に変更してください。
image.png

7. KuduでFunctionの修正を確認する

Visual Studio で Functions の関数を Push して確認する場合、Kudu で元データを確認するのが一番確実です。
Azure Portal と比較して反映までタイムラグが無く、最終更新日時が確認できるためです。

しかし過半数の現場では Azure を開発するときに Kudu を使わないので、この項目は読まなくても問題ありません。
Kudu は Azure 専用の Web アプリで、Kudu でしかできないという機能はないので、学習コストをかけても無駄になる可能性があるのです。

  1. ブラウザで Kudu にアクセスします。<FunctionApp名> を書き換えてください。
    https://<FunctionApp名>.scm.azurewebsites.net/DebugConsole

ポータルに配置されているリンクから開くことも可能です。
image.png

  1. Kudu の画面のフォルダから [site > wwwroot > 関数名のフォルダ] を開きます。
    image.png

image.png

  1. run.ps1 の修正画面を開いて中を確認できます。
    image.png

この画面でコードを編集する運用は、ログが残らないので推奨されません。
image.png

  1. 補足
    Kudu でよく使う画面の説明は以下のとおりです。
    image.png

  2. Zip 形式でダウンロードすることも可能です。
    これは Azure Portal の [アプリコンテンツのダウンロード] でダウンロードしたものとほぼ同等です。
    run.ps1 が、前の手順で開発した関数です。
    image.png

8. 個人開発におけるgitによるバージョン管理

この項目ではローカル Git での開発方法を紹介しています。Github との連携は記載しません。
チーム開発では Web 上の Github と連携して、競合に気を付けたりコメントやブランチ管理のルールが現場ごとに存在します。

  1. Git 公式サイト "https://git-scm.com/" からインストーラをダウンロードします。
    image.png

mac の場合は、Homebrew でのインストールが推奨されます。

brew install git

mac にはデフォルトで git のインストール機能 "Xcode Command Line Tools(CLT)" が入っています。
ほとんどのプログラマーは、上記コマンドで git 単体のインストールを実施して、Xcode Command Line Tools の Git は使いません。
Xcode Command Line Tools は Git とその他ツールの総称です。
この Git はバージョンが端末依存で古いままですが、後から単体インストールした Git はバージョンアップ可能で、Homebrew でインストールするとパスが優先されるので競合が起こらず利用できます。
また、Xcode Command Line Tools の他ツールへの影響がほぼありません。

  1. git を起動できたら、作業ディレクトリに移動します。以降すべてのコマンド操作はこのディレクトリで実行してください。
cd <ディレクトリのフルパス>
  1. 作業ディレクトリに .git という名前の隠しフォルダを作成します。git で操作する実体を格納するフォルダです。
    これは初期化コマンドと言われ、.git フォルダを初期化するときもこのコマンドを使います。
git init

image.png

  1. git 使用時に履歴に残す名前とメールアドレスを設定します。
    Web 上の Github と連携する場合には、Github に登録済みのメールアドレスを設定します。
    連携しない場合にはダミーのメールアドレスで問題ありません。
git config --global user.name "<編集者の名前>"
git config --global user.email "<mail@test.com>"

設定値を確認するコマンドです。

git config --global user.name
git config --global user.email

ここまでで初期設定が完了です。

  1. Commit(現在のディレクトリの内容を git に保存)します。"." はルートディレクトリを意味します。
git add .
git commit -m "初回コミット"

image.png

以降は VSCode のターミナルで git 操作ができます。git は閉じても構いません。

  1. Git init から commit まで実行したフォルダを VSCode で開きます。
    VSCode の画面左の [Source Control] アイコンを選択すると、画面左下の①に上記手順の Commit の内容が確認できます。
    以下の git コマンドと似たようなデータです。
git log --oneline

左下の①を押すと commit したファイル一覧が表示されます。
表示されたファイルを選択すると内容が read-only で右側に表示されます。
②のファイルアイコンを選択すると、ディレクトリのすべてのファイルが画面右側に read-only で表示されます。
image.png

  1. Git init から commit まで実行したフォルダを VSCode で開きます。
    VSCode で run.ps1 の 19 行目を修正して、Ctrl + S で保存します。
    image.png

  2. 上書き保存したあとに commit していないファイルがある場合、VSCode の画面左の [Source Control] アイコンに数字が表示されます。
    CHANGES にコメントを入れて commit を選択すると、以下の git コマンドが実行されます。

git add .
git commit -m "CHANGESの文字"

image.png

[✓ Commit] の右側のリストで、Commit の方法を選択できます。

UIの表示 実行される git コマンド 備考
Commit git add .
git commit -m "..."
通常の commit。
Commit (Amend) git add .
git commit --amend -m
直前の commit を上書き。
Commit & Push git add .
git commit
使わない。Push は VSCode でなく Functions に任せる。
Commit & Synk git add .
git commit, pull, push
Pull は権限不足で失敗する場合あり。
  1. commit が成功すると、左下の commit 履歴が表示されて、修正したファイルが表示されます。
    選択すると diff を確認できます。
    image.png

  2. VSCode の UI に無い git 操作は、Terminal から実行できます。
    [Terminal > New Terminal] を開きます。
    image.png

  3. .git が存在するフォルダへ移動して、Terminal から git コマンドを実行できます。
    例えば以下のコマンドを実行すると、直前の commit を削除して、run.ps1 ファイルの編集内容も元に戻ります。

git reset --hard HEAD~1

image.png

本格的なバージョン管理で頻繁に使う git コマンド

コマンド 処理動作
git log バージョン履歴の詳細(作者、日付、コメントなど)を表示
git checkout <commitID> <ファイル名> 特定ファイルのみを指定した過去バージョンに戻す(履歴は維持)
git reset --hard <commitID> 指定バージョンに完全に切り戻す(履歴も作業中ファイルも消える)
git reset HEAD <ファイル名> git add のステージ操作のみを取り消す(ファイル変更はそのまま)
git checkout -- <ファイル名> 直前の commit 内容にファイルを戻す(履歴は消えない)

9. Blobストレージの作成

API から画像やファイルなどを出力して Blob に保存し、利用者が Blob からファイルをダウンロードする仕組みを構築します。
Blob はストレージアカウントの機能ですが、ストレージアカウントを作成したあとでないと Blob コンテナは設定できません。

  1. [ストレージアカウント > 作成] を選択します。
    設定項目は以下の値以外はデフォルト値で構いません。
  • リソースグループ: Functions と同じもの推奨
  • ストレージアカウント名: Azure に存在しない一意の名前
  • リージョン: Functions と同じリージョン
    image.png
  1. [作成したストレージアカウント > データストレージ > コンテナー > +コンテナー] を選択します。
    名前を付けて保存します。
  • 名前: 任意
  • 匿名アクセスレベル: プライベート(規定値)
    image.png
  1. VSCode の使い方で説明した手順で、Functions の情報一式をダウンロードします。
    ダウンロード済みであればそのフォルダを使ってください。
    image.png

  2. Functions の情報一式のフォルダを解凍して開き、プロジェクトルートに requirements.psd1 を作成し、以下の内容を記述します。

@{
  'Az.Storage' = '5.*'
}

この設定ファイルが存在することで、Functions起動時にBlob操作機能を追加するためのAzモジュールがインストールされます。
プロジェクトルートというのは、ダウンロードしたフォルダのルートです。ディレクトリ構成は具体的に以下のようになります。

ディレクトリ構成の例

<Functions名>/              ← プロジェクトと呼ばれる
├── host.json               ← 関数アプリ全体の設定(トリガーの制御やログ出力レベルなど)
├── requirements.psd1       ← 必要な PowerShell モジュールを定義する依存ファイル
├── local.settings.json     ← ローカル実行時の環境変数や接続文字列を定義(Azure にはデプロイされない)
├── profile.ps1             ← オプション(主に環境変数などを設定)
├── <関数名>/                ← 関数(Function)が格納されるフォルダ
│   ├── function.json       ← 関数ごとのバインディング定義ファイル
│   └── run.ps1             ← 関数の本体(PowerShell)

image.png

local.settings.jsonの作成は任意です。Azure開発をハックする上級者向けなので今回は不要です。
local.settings.jsonにAzure上のBlobやDBの宛先を設定すると連携できます。VSCode上の動作テストで、Azureのリソースをフルに連携できます。
例えば、以下のようにUseDevelopmentStorage=trueを設定すると、実際のAzure Storageを使わない一時的なローカル開発用ストレージを用意することができます。

image.png

Azureの既存リソースにアクセス可能な設定ファイルが一緒にダウンロードされず、local.settings.jsonのように別途設定が必要になるかというと、Azureのリソースへのアクセスキーは機密情報なので、ダウンロードできない仕様になっているためです。

  1. 関数名を右クリックして、[Deploy to Function App...]を選択して、デプロイが成功した画面です。
    私は反映までに5分ぐらいかかりました。反映されない場合は、Filesを右クリックしてRefreshを選択してください。
    image.png

  2. [Functions > 更新] を選択して再起動します。
    これにより requirements.psd1 で指定した Az モジュールがインストールされます。
    image.png

10. アクセスキー管理用のKey Vault(キーボルト)作成

KeyVault関係の手順は飛ばしても問題ありません。ひととおりハンズオンが終わってからこの手順に戻ってきても構いません。
セキュリティ意識の高い企業では、以下のような理由でKey Vaultをほぼ使用します。

理由 説明
セキュリティ要件 アクセスキー、DB接続文字列、APIキー、証明書、パスワードなどを暗号化して保管。
コードや構成ファイルに認証情報を書かずに済む。自動ローテーションにも対応。
Azure RBAC またはアクセスポリシーでアクセス制御。
監査対応 SOC2, ISO 27001, HIPAA などの準拠に必須となるセキュリティ要件に対応。
DevOpsとの親和性 GitHub Actions や Azure DevOps パイプラインで環境変数として注入可能。
多人数開発 チーム間で接続情報を共有せず、誰がどの情報にアクセスできるかを制御可能。
監査ログ Azure Monitor に操作ログが記録される。

※Key Vaultは環境単位(開発・本番)に1つあれば十分。
※小規模利用でのコストは微小。

項目 価格
シークレット取得 ¥0.377 / 10,000回取得
シークレット書き込み ¥1.88 / 10,000回書き込み

手順

  1. [キーコンテナ(Key Vault) > +作成] を選択します。
    image.png

Azure Key Vault マネージド HSM との機能差は以下の通り。

  • Key Vault:接続文字列・パスワード・APIキー・証明書などを安全に保管・参照
  • マネージドHSM:ハードウェアレベルの鍵管理。今回は利用しない。
  1. リソースグループとリージョン以外は初期値のままでOK。
    リージョンはFunctionsと同一にすること。異なると仕様エラーとなる場合があります。
    image.png

  2. Key Vaultを利用するユーザーにIAMロールを付与します。
    作業ユーザーが権限保持者ならこの手順はスキップ可。

[キーコンテナ > アクセス制御(IAM) > ロールの割り当ての追加]
→ 作業するユーザーにKey Vault操作権限を割り当てる必要あり。

※Entra ID(旧Azure AD)ではなく、AzureリソースのIAMロールを割り当てる点に注意。
image.png

  1. [ロール > 特権管理者ロール > キー コンテナー管理者] を選択します。
    image.png

※「所有者」ロールはIAMロールの追加操作が可能なだけで、Key Vaultの操作はできません。
Key Vaultのデータ操作には別途ロールが必要です。

チーム開発で割り当てる代表的なIAMロール

利用者区分 日本語ロール名(英語) 権限内容
管理者 所有者(Owner) IAMロールの追加・削除・作成が可能。ただしKey Vaultのデータ操作権限は無い。
管理者 ユーザーアクセス管理者(User Access Administrator) IAMロールの割り当て可能。データ操作は不可。
管理者/開発者 キー コンテナー管理者(Key Vault Administrator) Key Vault 内すべてのデータ操作が可能(IAM操作は不可)
開発担当者 キー コンテナー共同作成者(Contributor) シークレットやキー、証明書の作成・取得・削除・更新が可能
アプリ実行者 キー コンテナー シークレット担当者(Secrets Officer) シークレットの読み書き可能(削除不可)
アプリ実行者 キー コンテナー シークレットユーザー(Secrets User) シークレットの読み取りのみ可能

万能ユーザーにする場合は「管理者」または「責任者」の名前を含むロールをすべて付与。

公式ガイド:
https://learn.microsoft.com/ja-jp/azure/key-vault/general/rbac-guide?tabs=azure-cli

※RBAC(Role-Based Access Control)とは、Azureのロールベース制御のことです。

  1. IAMロールの割り当て状況は [ロールの割り当て] 画面で確認できます。
    image.png

  2. [ストレージアカウント > セキュリティとネットワーク > アクセスキー] を選択して、
    "接続文字列"(key1またはkey2)をコピーします。

key1 / key2 は同一の機能で、交互にローテーション可能な設計。
接続文字列は Azure 構成で利用し、キー単体はSASトークン生成などで使用されます。
image.png

[キーの交換] を実施すると、キー値が更新されてセキュリティ事故を防止できます。

7. [キーコンテナ > オブジェクト > シークレット > +生成/インポート]を選択します。

image.png

ちなみに、前の手順で職務ロールを設定していないユーザーだと、以下のエラーが発生してキーの生成をしても失敗します。
image.png

8. キーの設定画面に値を入力します。

image.png

  • 名前: 任意です。多くの構築例では StorageConnectionString のように、「リソース名+ConnectionString」という命名規則で紹介されています。
  • 値: コピーしたストレージアカウントのアクセスキーの接続文字列
  • その他の項目: デフォルト値

11. Functionsの環境変数のシークレットキーをKeyVaultで管理する

環境変数の定期バックアップしてリソースのシークレット値をKeyVaultに格納するメリットをまとめた表です。

種類 メリット
セキュリティ強化 限られたユーザーのみがシークレット値の閲覧をできるので、情報漏洩のリスクが減る。
最小権限の実現 RBACでリソースがアクセス可能な接続文字列を設定できるので、細かなアクセス制御が可能になる。
ローテーション性向上 シークレット値をローテーションしても、アプリケーション側の設定変更やハードコーディングが不要。※キャッシュ対策は要注意
監査ログが残る シークレットへのアクセス履歴を Azure Monitor や Activity Log で監視して、セキュリティ監査に対応できる。
IaCで参照が容易 TerraformなどのIaCでKey Vault の参照を記述するだけでルーティングができる。
誤操作対策 環境変数の誤削除、Key Vault にシークレットが残っていれば再参照するだけで即復旧可能。

  1. 次の作業では、キー コンテナー シークレット担当者(Key Vault Secrets Officer)または キー コンテナー シークレット ユーザー(Key Vault Secrets User) のIAMロールが必要です。設定方法は紹介済みなので省略します。

FunctionsとKey VaultをマネージドIDで連携して、前の手順で登録したストレージアカウントのアクセスキーを取得する仕組みを構築します。

  1. [Functions(関数アプリ) > 設定 > ID > 状態(システムマネージドID)をオン > 保存]を選択
    image.png

  2. マネージドIDの有効化が完了した画面です。
    ※ここに表示されるオブジェクトIDは基本的に使いません。問題発生時のログ調査や、Functionsの設定をスクリプトで変える保守運用の自動化目的で使われることがある程度です。
    image.png

  3. [KeyVault > アクセス制御 (IAM) > ロールの割り当ての追加]を選択します。
    image.png

  4. Functionsにロールを割り当てます。
    ロール: キー コンテナー シークレット ユーザー(Key Vault Secrets User)
    アクセスの選択先: マネージド ID
    メンバー: +メンバーを選択する > 画面右のマネージドIDの選択 > マネージドIDに対象Functionsを選択
    image.png

ちなみに、2024/4以前はこの画面でFunctionsとKeyVaultの連携設定をしていました。現在は画面自体が不要です。
現在はKeyVaultをデフォルト設定で作成して、[KeyVault > アクセス ポリシー]を選択すると、権限が足りないというエラーが表示されますが、それで正常です。
image.png

  1. [Function > 設定 > 環境変数]を選択します。
    image.png

上記画像のとおり、リソース作成時に自動的に作られた環境変数がすでに存在します。
悪用される可能性がある環境変数は★印をつけたものです。このシークレット値をKeyVaultへ格納することが推奨されます。
それ以外はKeyVaultにシークレット値を登録するとバグります。内部的に、FunctionsがKeyVaultを読み込む前に取得する値になっているためです。

名前(環境変数名) 説明
★APPLICATIONINSIGHTS_CONNECTION_STRING Application Insights にログを送るための接続文字列です。
★AzureWebJobsStorage Functionsのストレージアカウントの接続文字列です。トリガー, ログ, タイマー, バインディングなどに使用されます。Functionsの動作に必須です。
FUNCTIONS_EXTENSION_VERSION 使用している Functions ランタイムのバージョンです。
FUNCTIONS_WORKER_RUNTIME pythonやC#などFunctions の言語を定義します。
★WEBSITE_CONTENTAZUREFILECONNECTIONSTRING Functionsのファイルコンテンツを保存するためのストレージ接続文字列です。Kudu やファイルベースの展開などで利用されます。
WEBSITE_CONTENTSHARE 上記ファイル保存用ストレージアカウントのファイル共有名です。
  1. 右上の[CloudShell]のアイコンを選択してください。PowerShellに切り替えてください。
    CloudShell右側に全画面表示ボタンがあります。
    image.png

  2. 以下のスクリプトを全行コピーして、CloudShell上で右クリックしてプレーンテキストで張り付けると処理が始まります。
    ハードコーディング箇所はありません。
    AzureCLIコマンドで、環境変数をバックアップするスクリプトです。

$functionApps = Get-AzWebApp | Where-Object { $_.Kind -like "*functionapp*" }

foreach ($app in $functionApps) {
    $resourceGroup = $app.ResourceGroup
    $functionApp = $app.Name

    Write-Output "取得中: $functionApp ($resourceGroup)"

    $appSettings = Get-AzWebApp -ResourceGroupName $resourceGroup -Name $functionApp

    $fileName = "${functionApp}-appsettings.json"
    $outputPath = "$HOME/$fileName"

    $appSettings.SiteConfig.AppSettings |
        ConvertTo-Json -Depth 5 |
        Out-File -FilePath $outputPath -Encoding UTF8

    Write-Output "保存完了: $outputPath"
}

image.png

スクリプト実行結果に赤文字が含まれている場合はエラーが起きています。
UIやKuduには、環境変数の一括ダウンロード機能が無いのでこの手順を実施しています。
UIは個別ダウンロードのみで、Kuduはアクセス権限に制限があってメタデータは閲覧しかできません。

  1. 今回は出力結果をダウンロードして確認します。
    CloudShell画面の[ファイルの管理]を選択して、スクリプト実行結果のパスを入力してください。
    複数のFunctionsが存在する場合は、それぞれのFunctions名でJSONが作成されます。
    image.png

ブラウザ右下にダウンロード可能なファイルの直リンクが表示されます。
image.png

  1. 中身は以下のようなJSONです。
    image.png

白文字で塗りつぶした値は、流出すると悪用される可能性があるアクセスキーが平文で直書きされています。
ファイルは慎重に扱ってください。

  1. [KeyVault > シークレット > +生成/インポート]を選択します。
    image.png

ちなみに、"シークレット"とは、シークレットな環境変数と理解してください。
その上の"キー"は、暗号キーを扱います。本項目とは関係ありません。

  1. 前の手順で出力したJSONの情報をそれぞれ登録します。
  • 名前:任意。推奨する命名規則は、環境名 + アプリ名 + JSONファイルの"Name"
    ※上記の命名規則だとどのリソースに紐づいているか理解できます。将来的に削除するときに分類できます。
    ※私は本番環境の場合に環境名を省略するため、画像の書き方になっています。
  • 値:JSONファイルの"Value"
    image.png

セキュリティや監査が重視される現場では、KeyVaultのシークレットキーに命名規則があります。
もっと細かく、タグにシークレット値の種類(password, keyなど)を書いたり、コンテンツの種類にリソース名を書いたりすることが多いです。

しかし現場の実体は、厳重に命名規則を設けても、不要な環境変数の削除作業を行わないケースが多々あります。
誤削除はリスクが高いですが、削除せずに放置してもシステム障害は起こらないためです。

  1. 登録完了した例です。シークレットの名前を選択してください。
    image.png

現在のバージョンを選択してください。
image.png

ちなみに、シークレット値をローテーションする場合にバージョンを複数登録します。

  1. シークレット識別子をコピーします。
    シークレット識別子はWeb上からアクセス可能ですが、AzureにログインしたうえでKeyVaultのアクセス権限が必要なので、流出しても安全です。
    image.png

  2. [Functions > 設定 > 環境変数]を選択して、値を変更します。

  • 名前: 変更しない
  • 値: @Microsoft.KeyVault(SecretUri=<コピーしたシークレット識別子>)
    image.png

値を変更した例です。
image.png

シークレット識別子からバージョン名を省略すると、最新バージョンが常に適用されます。
image.png

  1. 適用を選択すると前の画面に戻りますが、この画面でまた適用を選択してください。
    複数環境変数を一つずつ適用していくことを推奨します。
    どれか一つでも間違っていると反映されずにエラーになるのですが、原因切り分けが面倒なためです。
    image.png

  2. 成功すると、ソースがAppServiceからキーコンテナに変更になります。
    image.png

  3. 動作テストをする場合は、前の手順で作成した関数を実行してください。

12. AzureのCORS(コルス)設定

次の手順で作成するWebアプリは、AzureのFunctionsへHTTPリクエストを送信します。
画像はこれから作成するWebアプリからPOSTしたエラーです。このエラーを回避する設定をします。
AzureのCORSがデフォルト値だと、[Chrome > F12 > Network]を開きながらHTMLからPOSTしたときに、"CORS error"が発生します。
image.png

このWebアプリはデスクトップ上から実行しています。[console]を選択して、window.location.originというJavascriptを実行して確認すると、送信元のOriginが表示されます。
file:// と表示されており、スキームしか存在しない送信元であることが確認できます。
image.png

CORSは特定の以下3つの判定で全てNGだった時にHTTPリクエストを中止する、一般的なブラウザのセキュリティ機能です。

判定 判定内容 エラーにならない場合の理由
① クロスオリジン判定 ブラウザがヘッダー情報を確認して、送信元と宛先を確認します。Originが同じではない場合(クロスオリジンのとき)次の判定に進みます。 送信元と宛先が完全に同じなら、悪さをしないということで、APIが実行されます。
② シンプル判定 ブラウザがHTMLを確認して、古典的でシンプルなHTTPリクエストではない場合は、次の判定に進むためにサーバーにPreflight(OPTIONS)リクエストを送信します。 シンプルなHTTPリクエストは悪用につながりにくいと考えているので、APIが実行されます。
③ CORS設定値判定 サーバーが送信元のOriginからのリクエスト受け付けを許可しているか確認します。許可していない場合は、エラーコード[400, 403, CORS error]を追加して、Preflightレスポンスを返却します。 ホワイトリスト方式で登録済みの送信元の場合は、APIを呼び出すプログラムの中身がどうであれAPIを実行するという設定になっているので、APIは実行されます。
  • エラーの場合、ブラウザのログに表示されます。
  • OKであればHTTPリクエストが送受信されます。

エラー画像の赤枠内では、index.htmlファイルの26行目でJavascriptのfetch機能があるため、②シンプル判定から③CORS設定値判定に進み、PreflightチェックでCORSエラー(400エラー)が返却されたので、ブラウザがHTTPリクエスト処理を停止したことが分かります。

https://example.com:8080というOriginを例に、3つの要素について説明します。
image.png

Originとは、[スキーム][ドメインまたはIP][port]すべてのことです。
送信元と送信先サーバーの3つの要素のいずれかが異なることを、クロスオリジンと表現します。

  • Webサーバーの暗号化設定の有無によって、[https]または[http]が異なります。
  • 受け渡すデータの種類によって、port番号[:8080]が異なります。

CORSはブラウザの利用者を守る仕組みです。
利用者が悪意あるスクリプトによって、他のサイトやAPIに誘導されたり、認証情報を抜かれるリスクを減らします。

そのためCORSを無効にしないことが推奨されています。
CORSを無効にするとは、サーバー側のOrigin判定を全て許可するということです。

ブラウザの機能なので、POSTMANやバックエンドプログラムからの悪意あるスクリプト実行は防げません。
特定の攻撃に対して効果があるといった程度のものです。

サーバー運用側から見ると、ブラウザを使った低レベルで悪意があるDOS攻撃やスクレイピングなどによる、嫌がらせのようなレスポンスが減る可能性があるというぐらいで、セキュリティとしてはほぼ機能しません。

port番号レベルでの細かい設定まで必要なので、設定変更で影響範囲にCORSが含まれる場合には動作テストを行ってください。

VSCodeで作成したWebアプリのテスト実行のために、[スキーム][ドメインまたはIP][port]を全て用意するためには、サーバー上でhtmlファイルを動作させる必要があります。
以降の手順では、VSCodeの拡張機能で、ローカルのHTTPサーバー上でhtmlファイルを実行する設定です。

  1. VSCodeの拡張機能を選択して、「Live Server」をインストールします。
    image.png

インストール中に出てくるこの画面ではTrustを選択します。
Trust Workspace(Workspaceを信頼)とは、実行するコードを拡張機能が信頼するかという質問です。Trustを選択しないと、全ての動作が有効になりません。
image.png

  1. 任意のファイル名で拡張子.htmlファイルを作成します。内容は空で構いません。
    画像は、デスクトップ上にフォルダを作成して格納した例です。
    image.png

  2. HTMLファイルをVSCodeで開くと、拡張機能をインストールしたことで表示されるようになった右下の[Go Live]を選択します。
    ※サーバーを終了するときは、もう一度選択します。
    image.png

image.png

  1. ブラウザでHTMLが実行されます。
    Chromeの場合は、[Chrome > F12 > DevToolsのconsole]を選択して、window.location.originを実行します。表示されたOriginをコピーします。
    image.png

  2. [Functions > API > CORS]を選択して、コピーしたOriginをペーストします。
    VSCodeのLiveServerのOriginからのHTTPリクエストをAzure側で許可する設定が完了です。
    image.png

ちなみに、画像のように"*"を設定すると、全ての送信元からの接続を許可するので、CORS設定を無効化しているのと同義になります。
image.png

  1. CORSを設定したあとに動作不具合が起こる場合は、Functionsを再起動することで解決する可能性があります。
    ※再起動はその他様々なバグ解消のために使います。
    image.png

13. Functions(PowerShell)からBlobにファイルを出力するWebアプリの開発例

以下のような処理を実現するアプリのコードを用意しました。

① HTMLフォームで[名前, タイトル, 内容]をPOST処理します。POSTでは一般的にJSONファイルが送信されます。
② 値を受け取ったFunctions(PowerShell)が[処理日時, タイトル, 処理結果]のCSVを作成して、Blobに一時保存します。
③ Functionsが10分間ダウンロード可能なSAS URLを生成します。
④ HTMLフォームを起動しているブラウザでCSVがダウンロード可能になります。

※これをベースに機能を増やすと、問い合わせアプリ, 申請管理アプリ, 予約注文アプリなどが作れます。
例えば申請管理アプリだと、入力データをDBに保存して、申請を処理する担当者が閲覧できるUIを別途作成します。ユーザーには申請完了のPDFを返却します。

  1. .html拡張子のファイルを作成してください。拡張子より前のファイル名は任意です。

  2. HTMLファイルのコード例です。
    ハードコーディング箇所は変数apiUrlです。POST先のファンクションキーを書きます。
    image.png

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>CSV受信テスト</title>
</head>
<body>
  <h1>CSV受信テスト</h1>
  <form id="dataForm">
    <label>名前: <input type="text" name="name" required></label><br>
    <label>タイトル: <input type="text" name="title" required></label><br>
    <label>内容: <textarea name="content" required></textarea></label><br>
    <button type="submit">送信</button>
  </form>

  <script>
    document.getElementById("dataForm").addEventListener("submit", async function (e) {
      e.preventDefault();
      const formData = new FormData(this);
      const json = {};
      formData.forEach((value, key) => json[key] = value);

      // ▼ 関数のファンクションキーを書きます
      const apiUrl = "<関数のファンクションキー>";

      try {
        const response = await fetch(apiUrl, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify(json)
        });

        const result = await response.json();
        if (result.downloadUrl) {
          window.location.href = result.downloadUrl;
        } else {
          alert("CSVのダウンロードURLが返されませんでした。");
        }
      } catch (err) {
        alert("通信エラーが発生しました: " + err.message);
      }
    });
  </script>
</body>
</html>
  1. Functionsに、新しい関数を作成してください。今回もプログラムの種類はPowerShellです。
    image.png

  2. 関数のコード例です。ハードコーディング箇所は変数$containerNameです。
    前の手順で作成した、Functionの環境変数に登録済みのBlobの名前を書きます。

param($Request, $TriggerMetadata)

# POSTされたJSONから"タイトル"を取得
$title = $Request.Body.title

# JSTでの現在時刻を取得
$nowJst = (Get-Date).ToUniversalTime().AddHours(9).ToString("yyyy-MM-dd HH:mm:ss")

# CSVデータを構築
$csvContent = "処理日,タイトル,処理結果`n"
$csvContent += "$nowJst,$title,受け取り済み"

# ファイル名を現在時刻から生成
$blobName = "report_$($nowJst -replace '[: ]', '_').csv"

# ストレージ接続とBlobアップロード
$storageConnectionString = $env:AzureWebJobsStorage
$storageContext = New-AzStorageContext -ConnectionString $storageConnectionString

# ▼ Blobコンテナ名を書く
$containerName = "<Blobコンテナ名>"

# コンテナ作成(存在する場合はスキップ)
New-AzStorageContainer -Name $containerName -Context $storageContext -ErrorAction SilentlyContinue | Out-Null

# 一時ファイルにCSVを書き出し
$tempFile = [System.IO.Path]::GetTempFileName()
Set-Content -Path $tempFile -Value $csvContent -Encoding UTF8

# Blobにアップロード(MIMEタイプ指定)
Set-AzStorageBlobContent -Context $storageContext `
    -Container $containerName `
    -File $tempFile `
    -Blob $blobName `
    -Force `
    -Properties @{"ContentType" = "text/csv"} | Out-Null

# SASトークン(10分間有効)を生成
$expiry = (Get-Date).ToUniversalTime().AddMinutes(10)
$sas = New-AzStorageBlobSASToken -Container $containerName -Blob $blobName `
    -Permission r -ExpiryTime $expiry -FullUri -Context $storageContext

# クライアントに返す
Push-OutputBinding -Name Response -Value @{
    StatusCode = 200
    Body = @{ downloadUrl = $sas }
}

14. HTMLと関数の動作テスト

  1. デバッグしやすいように、Azure Functionsの画面で、関数のログ画面を開いておくことを推奨します。
    image.png

  2. index.html を VSCode の Live Server から開きます。
    デバッグしやすいように、Chrome の場合は [F12 > Network] を開いておくことを推奨します。

  3. HTML に値を入力して「送信」を選択します。
    image.png

  4. POST 結果の JSON 確認をする場合は、fetch 行の Name を選択してください。
    image.png

Payload を選択すると、HTTP リクエストの JSON が表示されます。
白く塗りつぶしたところは、関数の接続キーが表示されます。
image.png

  1. 関数のログ画面を開いている場合は、成功時に Executed "Functions.<関数名>" (Succeeded) と一番下に表示されます。
    ログに赤文字が表示される場合はエラーです。
    今回の黄色文字には、将来的に Az コマンドに修正が入る可能性があるという注意書きです。
    image.png

  2. CSV のダウンロードが自動で実行されたら、CSV の中身が正しいことを確認してください。
    image.png

  3. 10分経つとダウンロードリンクが失効します。
    ダウンロードページのリンクをブラウザに入力すると、再ダウンロードできるか確認できます。
    image.png

ダウンロードリンクからのダウンロードが失効したときの、ブラウザの画面例です。
uploading...0

15. 最後に(前半)

以下の掲載は執筆中です。私の勉強も兼ねているので内容は増減します。

  • Azure SQL Databaseの作成
  • Stripeによる課金ロジックの作成
  • Azureマルチテナントの構築
  • 課金とマルチテナント構成のフロントエンド構築
  • TerraformとGithubによるIaC化と環境のコピー
0
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
0
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?