エンド ツー エンドのキー ローテーションと監査で Azure Key Vault を設定するSet up Azure Key Vault with end-to-end key rotation and auditing

はじめにIntroduction

Key Vault を作成したら、そのコンテナーを使って、キーとシークレットを保存できます。After creating your key vault, you will be able to start using that vault to store your keys and secrets. アプリケーションでキーやシークレットを保持する必要がなくなりました。キーやシークレットは、必要に応じてキー コンテナーに要求します。Your applications no longer need to persist your keys or secrets, but rather will request them from the key vault as needed. これによりアプリケーションの動作に影響を与えずにキーとシークレットを更新できるため、キーおよびシークレット管理を取り巻く可能性の幅が広がります。This allows you to update keys and secrets without affecting the behavior of your application, which opens up a breadth of possibilities around your key and secret management.

この記事では、Azure Key Vault を使ってシークレット (ここでは、アプリケーションがアクセスする Azure Storage アカウント キー) を格納する例について説明します。This article walks through an example of using Azure Key Vault to store a secret, in this case an Azure Storage Account key that is accessed by an application. また、そのストレージ アカウント キーのスケジュールされたローテーションの実装も紹介します。It also demonstrates implementation of a scheduled rotation of that storage account key. 最後に、キー コンテナー監査ログを監視し、予期しない要求が行われたときにアラートを生成する方法のデモを見ていきます。Finally, it walks through a demonstration of how to monitor the key vault audit logs and raise alerts when unexpected requests are made.

注意

このチュートリアルの目的は、Key Vault の初期設定について詳しく説明することではありません。This tutorial is not intended to explain in detail the initial setup of your key vault. 詳細については、「 Azure Key Vault の概要」を参照してください。For this information, see Get started with Azure Key Vault. クロスプラットフォーム コマンド ライン インターフェイスの手順については、「Manage Key Vault using CLI」(CLI を使用した Key Vault の管理) を参照してください。For Cross-Platform Command-Line Interface instructions, see Manage Key Vault using CLI.

Key Vault の設定Set up Key Vault

アプリケーションが Key Vault からシークレットを取得できるようにするには、最初にシークレットを作成し、それをコンテナーにアップロードする必要があります。To enable an application to retrieve a secret from Key Vault, you must first create the secret and upload it to your vault. これを行うため、Azure PowerShell セッションを開始し、次のコマンドで Azure アカウントにサインインします。This can be accomplished by starting an Azure PowerShell session and signing in to your Azure account with the following command:

Login-AzureRmAccount

ポップアップ ブラウザー ウィンドウで、Azure アカウントのユーザー名とパスワードを入力します。In the pop-up browser window, enter your Azure account user name and password. PowerShell は、このアカウントに関連付けられているすべてのサブスクリプションを取得します。PowerShell will get all the subscriptions that are associated with this account. PowerShell は既定で最初のサブスクリプションを使用します。PowerShell uses the first one by default.

複数のサブスクリプションをお持ちの場合は、Key Vault を作成するときに使用した 1 つを指定することが必要なことがあります。If you have multiple subscriptions, you might have to specify the one that was used to create your key vault. アカウントのサブスクリプションを確認するには、次を入力します。Enter the following to see the subscriptions for your account:

Get-AzureRmSubscription

ログ記録する Key Vault に関連付けられているサブスクリプションを指定するには、次を入力します。To specify the subscription that's associated with the key vault you will be logging, enter:

Set-AzureRmContext -SubscriptionId <subscriptionID>

この記事では、ストレージ アカウント キーをシークレットとして格納しているため、そのストレージ アカウント キーを取得する必要があります。Because this article demonstrates storing a storage account key as a secret, you must get that storage account key.

Get-AzureRmStorageAccountKey -ResourceGroupName <resourceGroupName> -Name <storageAccountName>

自分のシークレット (ここではストレージ アカウント キー) を取得したら、それをセキュリティで保護された文字列に変換し、その値を使ってシークレットをキー コンテナーに作成します。After retrieving your secret (in this case, your storage account key), you must convert that to a secure string and then create a secret with that value in your key vault.

$secretvalue = ConvertTo-SecureString <storageAccountKey> -AsPlainText -Force

Set-AzureKeyVaultSecret -VaultName <vaultName> -Name <secretName> -SecretValue $secretvalue

次に、作成したシークレットの URI を取得します。Next, get the URI for the secret you created. これは、後で Key Vault を呼び出して、自分のシークレットを取得するときに使用します。This is used in a later step when you call the key vault to retrieve your secret. 次の PowerShell コマンドを実行し、ID の値をメモします。これが、シークレットの URI です。Run the following PowerShell command and make note of the ID value, which is the secret URI:

Get-AzureKeyVaultSecret –VaultName <vaultName>

アプリケーションの設定Set up the application

シークレットを格納したところで、コードを使用して、シークレットを取得して使用できます。Now that you have a secret stored, you can use code to retrieve and use it. これを実現するために必要ないくつかの手順があります。There are a few steps required to achieve this. 最も重要なのは、アプリケーションを Azure Active Directory に登録し、Key Vault にアプリケーション情報を指定して、Key Vault がアプリケーションからの要求を許可できるようにすることです。The first and most important step is registering your application with Azure Active Directory and then telling Key Vault your application information so that it can allow requests from your application.

注意

アプリケーションは、Key Vault と同じ Azure Active Directory テナントに作成する必要があります。Your application must be created on the same Azure Active Directory tenant as your key vault.

Azure Active Directory の [アプリケーション] タブを開きます。Open the applications tab of Azure Active Directory.

Azure Active Directory の [アプリケーション] を開く

[追加] を選択して、アプリケーションを Azure Active Directory に追加します。Choose ADD to add an application to your Azure Active Directory.

[追加] を選択する

アプリケーションの種類は [Web アプリケーションや Web API] のままにして、アプリケーション名を入力します。Leave the application type as WEB APPLICATION AND/OR WEB API and give your application a name.

アプリケーションに名前を付ける

アプリケーションの [サインオン URL][アプリケーション ID/URI] を指定します。Give your application a SIGN-ON URL and an APP ID URI. このデモでは、任意の値を入力できます。この値は、必要に応じて後で変更できます。These can be anything you want for this demo, and they can be changed later if needed.

必要な URI を指定する

アプリケーションが Azure Active Directory に追加されると、アプリケーション ページが表示されます。After the application is added to Azure Active Directory, you will be brought into the application page. [構成] タブをクリックし、[クライアント ID] の値を見つけてコピーします。Click the Configure tab and then find and copy the Client ID value. 後で使用できるように、クライアント ID をメモします。Make note of the client ID for later steps.

次に、アプリケーションのキーを生成して、Azure Active Directory とやり取りできるようにします。Next, generate a key for your application so it can interact with your Azure Active Directory. これは、[構成] タブの [キー] セクションで作成できます。後で使用できるように、Azure Active Directory アプリケーションから新しく生成されたキーをメモします。You can create this under the Keys section in the Configuration tab. Make note of the newly generated key from your Azure Active Directory application for use in a later step.

Azure Active Directory アプリケーション キー

Key Vault へのアプリケーションからの呼び出しを確立する前に、アプリケーションとそのアクセス許可について Key Vault に指定する必要があります。Before establishing any calls from your application into the key vault, you must tell the key vault about your application and its permissions. 次のコマンドは、Azure Active Directory アプリからコンテナーの名前とクライアント ID を取得し、アプリケーションのキー コンテナーに対する Get アクセスを許可します。The following command takes the vault name and the client ID from your Azure Active Directory app and grants Get access to your key vault for the application.

Set-AzureRmKeyVaultAccessPolicy -VaultName <vaultName> -ServicePrincipalName <clientIDfromAzureAD> -PermissionsToSecrets Get

この時点で、アプリケーション呼び出しの構築をいつでも開始できます。At this point, you are ready to start building your application calls. アプリケーションでは、Azure Key Vault および Azure Active Directory との対話に必要な NuGet パッケージをインストールする必要があります。In your application, you must install the NuGet packages required to interact with Azure Key Vault and Azure Active Directory. Visual Studio パッケージ マネージャー コンソールで、次のコマンドを入力します。From the Visual Studio Package Manager console, enter the following commands. この記事が書かれた時点で、 Azure Active Directory パッケージの最新バージョンは 3.10.305231913 です。したがって、現在の最新のバージョンを確認し、必要に応じて更新してください。At the writing of this article, the current version of the Azure Active Directory package is 3.10.305231913, so you might want to confirm the latest version and update accordingly.

Install-Package Microsoft.IdentityModel.Clients.ActiveDirectory -Version 3.10.305231913

Install-Package Microsoft.Azure.KeyVault

アプリケーション コードで、 Azure Active Directory 認証用のメソッドを保持するクラスを作成します。In your application code, create a class to hold the method for your Azure Active Directory authentication. この例では、そのクラスは Utils と呼ばれます。In this example, that class is called Utils. 次の using ステートメントを追加します。Add the following using statement:

using Microsoft.IdentityModel.Clients.ActiveDirectory;

次に、以下のメソッドを追加して、Azure Active Directory から JWT トークンを取得します。Next, add the following method to retrieve the JWT token from Azure Active Directory. 保守容易性のために、ハードコーディングされた文字列の値を Web またはアプリケーション構成に移動できます。For maintainability, you may want to move the hard-coded string values into your web or application configuration.

public async static Task<string> GetToken(string authority, string resource, string scope)
{
    var authContext = new AuthenticationContext(authority);

    ClientCredential clientCred = new ClientCredential("<AzureADApplicationClientID>","<AzureADApplicationClientKey>");

    AuthenticationResult result = await authContext.AcquireTokenAsync(resource, clientCred);

    if (result == null)

    throw new InvalidOperationException("Failed to obtain the JWT token");

    return result.AccessToken;
}

必要なコードを追加して Key Vault を呼び出し、シークレット値を取得できます。Add the necessary code to call Key Vault and retrieve your secret value. まず、次の using ステートメントを追加する必要があります。First you must add the following using statement:

using Microsoft.Azure.KeyVault;

メソッド呼び出しを追加して Key Vault を呼び出し、シークレットを取得します。Add the method calls to invoke Key Vault and retrieve your secret. このメソッドでは、前の手順で保存したシークレットの URI を提供します。In this method, you provide the secret URI that you saved in a previous step. 以前に作成した Utils クラスから GetToken メソッドを使用している点に注意してください。Note the use of the GetToken method from the Utils class created previously.

var kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(Utils.GetToken));

var sec = kv.GetSecretAsync(<SecretID>).Result.Value;

アプリケーションを実行するときに、Azure Active Directory への認証を行い、Azure Key Vault からシークレット値を取得しているはずです。When you run your application, you should now be authenticating to Azure Active Directory and then retrieving your secret value from Azure Key Vault.

Azure Automation を使用したキー ローテーションKey rotation using Azure Automation

Azure Key Vault シークレットとして格納する値のローテーション戦略は、さまざまな方法で実装できます。There are various options for implementing a rotation strategy for values you store as Azure Key Vault secrets. シークレットのローテーションは、手動プロセスの一環として行ったり、API 呼び出しを利用してプログラムによって実行したりできます。また、自動化スクリプトを使うこともできます。Secrets can be rotated as part of a manual process, they may be rotated programmatically by using API calls, or they may be rotated by way of an Automation script. この記事では、Azure PowerShell と Azure Automation を組み合わせて使用して、Azure Storage アカウントのアクセス キーを変更します。For the purposes of this article, you will be using Azure PowerShell combined with Azure Automation to change an Azure Storage Account access key. その後、その新しいキーでキー コンテナーを更新します。You will then update a key vault secret with that new key.

Azure Automation でキー コンテナーのシークレット値を設定できるようにするには、Azure Automation インスタンスを確立したときに作成された、AzureRunAsConnection という接続のクライアント ID を取得する必要があります。To allow Azure Automation to set secret values in your key vault, you must get the client ID for the connection named AzureRunAsConnection, which was created when you established your Azure Automation instance. この ID を取得するには、Azure Automation インスタンスから [アセット] を選択します。You can find this ID by choosing Assets from your Azure Automation instance. そこで [接続][AzureRunAsConnection] サービス プリンシパルの順に選択します。From there, you choose Connections and then select the AzureRunAsConnection service principle. [アプリケーション ID] をメモしてください。Take note of the Application ID.

Azure Automation クライアント ID

[アセット][モジュール] を選択します。In Assets, choose Modules. [モジュール] では、[ギャラリー] を選択し、次の各モジュールの更新バージョンを検索して、[インポート] を実行します。From Modules, select Gallery, and then search for and Import updated versions of each of the following modules:

Azure
Azure.Storage
AzureRM.Profile
AzureRM.KeyVault
AzureRM.Automation
AzureRM.Storage

注意

この記事が書かれた時点では、以下のスクリプトで更新が必要なのは上記のモジュールだけです。At the writing of this article, only the previously noted modules needed to be updated for the following script. 自動化ジョブが失敗した場合は、必要なモジュールとその依存関係がすべてインポートされていることを確認してください。If you find that your automation job is failing, confirm that you have imported all necessary modules and their dependencies.

Azure Automation 接続のアプリケーション ID を取得したら、このアプリケーションにコンテナー内のシークレットを更新するアクセス権があることを、Key Vault に通知する必要があります。After you have retrieved the application ID for your Azure Automation connection, you must tell your key vault that this application has access to update secrets in your vault. これを行うには、次の PowerShell コマンドを使用します。This can be accomplished with the following PowerShell command:

Set-AzureRmKeyVaultAccessPolicy -VaultName <vaultName> -ServicePrincipalName <applicationIDfromAzureAutomation> -PermissionsToSecrets Set

次に、Azure Automation インスタンスで [Runbook] を選択し、[Runbook の追加] を選択します。Next, select Runbooks under your Azure Automation instance, and then select Add a Runbook. [簡易作成]を選択します。Select Quick Create. Runbook に名前を付けて、Runbook の種類として [PowerShell] を選択します。Name your runbook and select PowerShell as the runbook type. 説明を追加するオプションがあります。You have the option to add a description. 最後に、[作成] をクリックします。Finally, click Create.

Runbook を作成する

新しい Runbook のエディター ペインに、次の PowerShell スクリプトを貼り付けます。Paste the following PowerShell script in the editor pane for your new runbook:

$connectionName = "AzureRunAsConnection"
try
{
    # Get the connection "AzureRunAsConnection "
    $servicePrincipalConnection=Get-AutomationConnection -Name $connectionName         

    "Logging in to Azure..."
    Add-AzureRmAccount `
        -ServicePrincipal `
        -TenantId $servicePrincipalConnection.TenantId `
        -ApplicationId $servicePrincipalConnection.ApplicationId `
        -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
    "Login complete."
}
catch {
    if (!$servicePrincipalConnection)
    {
        $ErrorMessage = "Connection $connectionName not found."
        throw $ErrorMessage
    } else{
        Write-Error -Message $_.Exception
        throw $_.Exception
    }
}

#Optionally you may set the following as parameters
$StorageAccountName = <storageAccountName>
$RGName = <storageAccountResourceGroupName>
$VaultName = <keyVaultName>
$SecretName = <keyVaultSecretName>

#Key name. For example key1 or key2 for the storage account
New-AzureRmStorageAccountKey -ResourceGroupName $RGName -Name $StorageAccountName -KeyName "key2" -Verbose
$SAKeys = Get-AzureRmStorageAccountKey -ResourceGroupName $RGName -Name $StorageAccountName

$secretvalue = ConvertTo-SecureString $SAKeys[1].Value -AsPlainText -Force

$secret = Set-AzureKeyVaultSecret -VaultName $VaultName -Name $SecretName -SecretValue $secretvalue

エディター ペインで [テスト ウィンドウ] を選択して、スクリプトをテストします。From the editor pane, choose Test pane to test your script. エラーなしでスクリプトが実行されると、[発行] を選択できます。その後、Runbook 構成ウィンドウに戻って、Runbook のスケジュールを適用できます。Once the script is running without error, you can select Publish, and then you can apply a schedule for the runbook back in the runbook configuration pane.

Key Vault 監査のパイプラインKey Vault auditing pipeline

Key Vault を設定するときに、監査をオンにして、Key Vault へのアクセス要求のログを収集できます。When you set up a key vault, you can turn on auditing to collect logs on access requests made to the key vault. これらのログは、指定された Azure Storage アカウントに保存され、抽出、監視、および分析することができます。These logs are stored in a designated Azure Storage account and can be pulled out, monitored, and analyzed. 次のシナリオでは、Azure Functions、Azure Logic Apps、および Key Vault の監査ログを利用してパイプラインを作成し、Web アプリのアプリ ID と一致するアプリがコンテナーからシークレットを取得したときに、電子メールを送信します。The following scenario uses Azure functions, Azure logic apps, and key vault audit logs to create a pipeline to send an email when an app that does match the app ID of the web app retrieves secrets from the vault.

最初に、Key Vault へのログオンを有効にする必要があります。First, you must enable logging on your key vault. これを行うには、次の PowerShell コマンドを使用します (詳細については、key-vault-logging をご覧ください)。This can be done via the following PowerShell commands (full details can be seen at key-vault-logging):

$sa = New-AzureRmStorageAccount -ResourceGroupName <resourceGroupName> -Name <storageAccountName> -Type Standard\_LRS -Location 'East US'
$kv = Get-AzureRmKeyVault -VaultName '<vaultName>'
Set-AzureRmDiagnosticSetting -ResourceId $kv.ResourceId -StorageAccountId $sa.Id -Enabled $true -Categories AuditEvent

ログオンを有効にすると、監査ログによって、指定されたストレージ アカウントへの収集が開始されます。After this is enabled, audit logs start collecting into the designated storage account. こうしたログには、いつ、だれが、どのような方法で Key Vault にアクセスしたかに関するイベントが含まれます。These logs contain events about how and when your key vaults are accessed, and by whom.

注意

Key Vault の操作を行ってから 10 分後には、ログ情報にはアクセスできます。You can access your logging information 10 minutes after the key vault operation. 通常はこれよりも早くアクセスできます。It will usually be quicker than this.

次は、Azure Service Bus キューを作成します。The next step is to create an Azure Service Bus queue. ここにキー コンテナーの監査ログがプッシュされます。This is where key vault audit logs are pushed. 監査ログ メッセージがキューにあるときは、ロジック アプリはそれらを選択して処理します。When the audit log messages are in the queue, the logic app picks them up and acts on them. 次の手順で Service Bus を作成します。Create a service bus with the following steps:

  1. Service Bus 名前空間を作成します (使用できるものが既にある場合は、手順 2 に進みます)。Create a Service Bus namespace (if you already have one that you want to use for this, skip to Step 2).
  2. Azure ポータルで Service Bus に移動して、キューを作成する名前空間を選択します。Browse to the service bus in the Azure portal and select the namespace you want to create the queue in.
  3. [新規] を選択し、[Service Bus] > [キュー] の順に選択して、必要な情報を入力します。Select New and choose Service Bus > Queue and enter the required details.
  4. 名前空間を選択し、[接続情報] をクリックして、Service Bus 接続情報を取得します。Select the Service Bus connection information by choosing the namespace and clicking Connection Information. この情報は、次のセクションで必要です。You will need this information for the next section.

次に、Azure 関数を作成して、ストレージ アカウント内で Key Vault ログをポーリングし、新しいイベントを取得します。Next, create an Azure function to poll key vault logs within the storage account and pick up new events. これが、スケジュールでトリガーされる関数です。This will be a function that is triggered on a schedule.

Azure 関数を作成するには、Azure ポータルで [新規] > [Function App] を選択します。To create an Azure function, choose New > Function App in the Azure portal. 作成中、既存のホスティング プランを使用するか、新しいプランを作成できます。During creation, you can use an existing hosting plan or create a new one. 動的ホスティングを選択することもできます。You could also opt for dynamic hosting. 関数のホスティング オプションの詳細については、「Azure Functions のスケーリング方法」をご覧ください。More details on Function hosting options can be found at How to scale Azure Functions.

Azure 関数を作成するときに、この画面にアクセスしてタイマー関数と C# を選択します。When the Azure function is created, navigate to it and choose a timer function and C#. 次に [この関数を作成する] をクリックします。Then click Create this function.

Azure Functions スタート ブレード

[開発] タブで、run.csx コードを次のコードに置き換えます。On the Develop tab, replace the run.csx code with the following:

#r "Newtonsoft.Json"

using System;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Blob;
using Microsoft.ServiceBus.Messaging;
using System.Text;

public static void Run(TimerInfo myTimer, TextReader inputBlob, TextWriter outputBlob, TraceWriter log)
{
    log.Info("Starting");

    CloudStorageAccount sourceStorageAccount = new CloudStorageAccount(new StorageCredentials("<STORAGE_ACCOUNT_NAME>", "<STORAGE_ACCOUNT_KEY>"), true);

    CloudBlobClient sourceCloudBlobClient = sourceStorageAccount.CreateCloudBlobClient();

    var connectionString = "<SERVICE_BUS_CONNECTION_STRING>";
    var queueName = "<SERVICE_BUS_QUEUE_NAME>";

    var sbClient = QueueClient.CreateFromConnectionString(connectionString, queueName);

    DateTime dtPrev = DateTime.UtcNow;
    if(inputBlob != null)
    {
        var txt = inputBlob.ReadToEnd();

        if(!string.IsNullOrEmpty(txt))
        {
            dtPrev = DateTime.Parse(txt);
            log.Verbose($"SyncPoint: {dtPrev.ToString("O")}");
        }
        else
        {
            dtPrev = DateTime.UtcNow;
            log.Verbose($"Sync point file didnt have a date. Setting to now.");
        }
    }

    var now = DateTime.UtcNow;

    string blobPrefix = "insights-logs-auditevent/resourceId=/SUBSCRIPTIONS/<SUBSCRIPTION_ID>/RESOURCEGROUPS/<RESOURCE_GROUP_NAME>/PROVIDERS/MICROSOFT.KEYVAULT/VAULTS/<KEY_VAULT_NAME>/y=" + now.Year +"/m="+now.Month.ToString("D2")+"/d="+ (now.Day).ToString("D2")+"/h="+(now.Hour).ToString("D2")+"/m=00/";

    log.Info($"Scanning:  {blobPrefix}");

    IEnumerable<IListBlobItem> blobs = sourceCloudBlobClient.ListBlobs(blobPrefix, true);

    log.Info($"found {blobs.Count()} blobs");

    foreach(var item in blobs)
    {
        if (item is CloudBlockBlob)
        {
            CloudBlockBlob blockBlob = (CloudBlockBlob)item;

            log.Info($"Syncing: {item.Uri}");

            string sharedAccessUri = GetContainerSasUri(blockBlob);

            CloudBlockBlob sourceBlob = new CloudBlockBlob(new Uri(sharedAccessUri));

            string text;
            using (var memoryStream = new MemoryStream())
            {
                sourceBlob.DownloadToStream(memoryStream);
                text = System.Text.Encoding.UTF8.GetString(memoryStream.ToArray());
            }

            dynamic dynJson = JsonConvert.DeserializeObject(text);

            //required to order by time as they may not be in the file
            var results = ((IEnumerable<dynamic>) dynJson.records).OrderBy(p => p.time);

            foreach (var jsonItem in results)
            {
                DateTime dt = Convert.ToDateTime(jsonItem.time);

                if(dt>dtPrev){
                    log.Info($"{jsonItem.ToString()}");

                    var payloadStream = new MemoryStream(Encoding.UTF8.GetBytes(jsonItem.ToString()));
                    //When sending to ServiceBus, use the payloadStream and set keeporiginal to true
                    var message = new BrokeredMessage(payloadStream, true);
                    sbClient.Send(message);
                    dtPrev = dt;
                }
            }
        }
    }
    outputBlob.Write(dtPrev.ToString("o"));
}

static string GetContainerSasUri(CloudBlockBlob blob)
{
    SharedAccessBlobPolicy sasConstraints = new SharedAccessBlobPolicy();

    sasConstraints.SharedAccessStartTime = DateTime.UtcNow.AddMinutes(-5);
    sasConstraints.SharedAccessExpiryTime = DateTime.UtcNow.AddHours(24);
    sasConstraints.Permissions = SharedAccessBlobPermissions.Read;

    //Generate the shared access signature on the container, setting the constraints directly on the signature.
    string sasBlobToken = blob.GetSharedAccessSignature(sasConstraints);

    //Return the URI string for the container, including the SAS token.
    return blob.Uri + sasBlobToken;
}

注意

上記のコードの変数を、Key Vault ログが書き込まれたストレージ アカウント、以前に作成した Service Bus、およびキー コンテナーのストレージ ログへの特定のパスを指すように置き換えます。Make sure to replace the variables in the preceding code to point to your storage account where the key vault logs are written, the service bus you created earlier, and the specific path to the key vault storage logs.

関数は Key Vault ログが書き込まれたストレージ アカウントから最新のログ ファイルを取得します。その後、そのファイルから最新のイベントを取得して、Service Bus キューにプッシュします。The function picks up the latest log file from the storage account where the key vault logs are written, grabs the latest events from that file, and pushes them to a Service Bus queue. 1 つのファイルに複数のイベントが保持されている可能性があるため、sync.txt ファイルを作成します。関数はこのファイルも参照して、取得された最後のイベントのタイム スタンプを確認します。Since a single file could have multiple events, you should create a sync.txt file that the function also looks at to determine the time stamp of the last event that was picked up. これにより、同じイベントが複数回プッシュされなくなります。This ensures that you don't push the same event multiple times. この sync.txt ファイルには、最後に発生したイベントのタイムスタンプが含まれます。This sync.txt file contains a timestamp for the last encountered event. ログは、読み込まれたときに、タイムスタンプに基づいて正しく並べ替える必要があります。The logs, when loaded, have to be sorted based on the timestamp to ensure they are ordered correctly.

この関数では、Azure Functions ですぐには使用できない追加ライブラリをいくつか参照します。For this function, we reference a couple of additional libraries that are not available out of the box in Azure Functions. ライブラリを追加するには、Azure Functions で、NuGet を使用してそのライブラリをプルするがあります。To include these, we need Azure Functions to pull them using NuGet. [ファイルを表示] オプションを選択します。Choose the View Files option.

[ファイルの表示] オプション

次に、以下のコンテンツが含まれる project.json というファイルを追加します。And add a file called project.json with following content:

    {
      "frameworks": {
        "net46":{
          "dependencies": {
                "WindowsAzure.Storage": "7.0.0",
                "WindowsAzure.ServiceBus":"3.2.2"
          }
        }
       }
    }

[保存] すると、Azure Functions によって必要なバイナリがダウンロードされます。Upon Save, Azure Functions will download the required binaries.

[統合] タブに切り替えて、関数内で使用するタイマー パラメーターにわかりやすい名前を付けます。Switch to the Integrate tab and give the timer parameter a meaningful name to use within the function. 上記のコードでは、タイマーは myTimerと呼ばれます。In the preceding code, it expects the timer to be called myTimer. CRON 式を次のように指定します: 0 * * * * * (1 分ごとに関数を実行するタイマーの場合)。Specify a CRON expression as follows: 0 * * * * * for the timer that will cause the function to run once a minute.

同じ [統合] タブで、種類が Azure Blob Storage の入力を追加します。On the same Integrate tab, add an input of the type Azure Blob Storage. これは sync.txt ファイルを指します。このファイルには、関数によって参照される最後のイベントのタイムスタンプが含まれます。This will point to the sync.txt file that contains the timestamp of the last event looked at by the function. これは関数内でパラメーター名によって使用できます。This will be available within the function by the parameter name. 上記のコードの Azure Blob Storage 入力では、パラメーター名は inputBlob です。In the preceding code, the Azure Blob Storage input expects the parameter name to be inputBlob. sync.txt ファイルが存在するストレージ アカウントを選択します (同じストレージ アカウントにすることも別のストレージ アカウントにすることもできます)。Choose the storage account where the sync.txt file will reside (it could be the same or a different storage account). パス フィールドには、ファイルが存在するパスを {container-name}/path/to/sync.txt の形式で指定します。In the path field, provide the path where the file lives in the format {container-name}/path/to/sync.txt.

種類が Azure Blob Storage の出力を追加します。Add an output of the type Azure Blob Storage output. これは、入力で定義した sync.txt ファイルを指します。This will point to the sync.txt file you defined in the input. これは、参照される最後のイベントのタイムスタンプを書き込むときに、関数によって使用されます。This is used by the function to write the timestamp of the last event looked at. 上記のコードでは、このパラメーターは outputBlob と呼ばれます。The preceding code expects this parameter to be called outputBlob.

これで関数の準備ができました。At this point, the function is ready. [開発] タブに切り替えて、コードを 保存します。Make sure to switch back to the Develop tab and save the code. 出力ウィンドウでコンパイル エラーがないかどうかを確認し、エラーがある場合は修正します。Check the output window for any compilation errors and correct them accordingly. コードをコンパイルすると、コードは 1 分ごとに Key Vault ログを確認し、新しいイベントすべてを定義済み Service Bus キューにプッシュします。If the code compiles, then the code should now be checking the key vault logs every minute and pushing any new events onto the defined Service Bus queue. 関数がトリガーされるたびに、ログ情報がログ ウィンドウに書き出されることがわかります。You should see logging information write out to the log window every time the function is triggered.

Azure Logic AppAzure logic app

次に、Azure Logic App を作成する必要があります。このアプリは、関数が Service Bus キューにプッシュするイベントを取得し、コンテンツを解析して、一致する条件に基づいて電子メールを送信します。Next you must create an Azure logic app that picks up the events that the function is pushing to the Service Bus queue, parses the content, and sends an email based on a condition being matched.

[新規] > [Logic App] の順に移動し、Logic App を作成します。Create a logic app by going to New > Logic App.

Logic App が作成されたら、そのアプリに移動し、[編集] を選択します。Once the logic app is created, navigate to it and choose edit. Logic App エディターで、[Service Bus キュー] を選択し、Service Bus 資格情報を入力して、キューに接続します。Within the logic app editor, choose Service Bus Queue and enter your Service Bus credentials to connect it to the queue.

Azure Logic App Service Bus

次に、[条件を追加] を選択します。Next choose Add a condition. 条件で高度なエディターに切り替えて次のコードを入力し、APP_ID を、Web アプリの実際の APP_ID に置き換えます。In the condition, switch to the advanced editor and enter the following code, replacing APP_ID with the actual APP_ID of your web app:

@equals('<APP_ID>', json(decodeBase64(triggerBody()['ContentData']))['identity']['claim']['appid'])

この式は、基本的に、受信イベント (Service Bus メッセージの本文) の appid が、アプリの appid でない場合に、false を返します。This expression essentially returns false if the appid from the incoming event (which is the body of the Service Bus message) is not the appid of the app.

ここで、[If no, do nothing (いいえの場合は、何もしない)] でアクションを作成します。Now, create an action under If no, do nothing.

Azure Logic App 選択アクション

アクションで、[Office 365 - send email (Office 365 - メール送信)]を選択します。For the action, choose Office 365 - send email. フィールドに入力して、定義された条件が false を返したときに送信する電子メールを作成します。Fill out the fields to create an email to send when the defined condition returns false. Office 365 がない場合は、同じ結果を実現するために他の方法を確認してください。If you do not have Office 365, you could look at alternatives to achieve the same results.

この時点では、1 分ごとに新しい Key Vault 監査ログを確認するエンド ツー エンドのパイプラインがあります。At this point, you have an end to end pipeline that looks for new key vault audit logs once a minute. これは検出した新しいログを Service Bus キューにプッシュします。It pushes new logs it finds to a service bus queue. 新しいメッセージがキューに届くと、ロジック アプリがトリガーされます。The logic app is triggered when a new message lands in the queue. イベント内の appid が呼び出し元アプリケーションのアプリケーション ID と一致しない場合、電子メールが送信されます。If the appid within the event does not match the app ID of the calling application, it sends an email.