Einrichten von Azure Key Vault mit Schlüsselrotation und ÜberwachungSet up Azure Key Vault with key rotation and auditing

EinführungIntroduction

Nach dem Erstellen eines Schlüsseltresors können Sie Schlüssel und Geheimnisse in diesem Tresor speichern.After you have a key vault, you can start using it to store keys and secrets. Ihre Schlüssel und Geheimnisse müssen in Ihren Anwendungen nicht mehr dauerhaft gespeichert werden, sondern können bei Bedarf aus dem Tresor angefordert werden.Your applications no longer need to persist your keys or secrets, but can request them from the vault as needed. Dadurch können Sie Schlüssel und geheime Schlüssel ohne Auswirkungen auf das Verhalten Ihrer Anwendung aktualisieren, was eine Vielzahl von Möglichkeiten für die Verwaltung von Schlüsseln und geheimen Schlüsseln eröffnet.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.

Wichtig

Die Beispiele in diesem Artikel werden lediglich zur Veranschaulichung bereitgestellt.The examples in this article are provided for illustration purposes only. Sie sind nicht für Produktionszwecke vorgesehen.They are not intended for production use.

In diesem Artikel wird Folgendes beschrieben:This article walks through:

  • Ein Beispiel für die Verwendung von Azure Key Vault zum Speichern eines Geheimnisses.An example of using Azure Key Vault to store a secret. In diesem Tutorial handelt es sich bei dem gespeicherten Geheimnis um den Azure Storage-Kontoschlüssel, auf den eine Anwendung zugreift.In this tutorial, the secret stored is the Azure Storage Account key accessed by an application.
  • Außerdem wird die Implementierung einer geplanten Rotation dieses Speicherkontoschlüssels demonstriert.It also demonstrates implementation of a scheduled rotation of that storage account key.
  • Es wird erläutert, wie die Überwachungsprotokolle des Schlüsseltresors überwacht und wie bei unerwarteten Anforderungen Warnungen ausgelöst werden.It demonstrates how to monitor the key vault audit logs and raise alerts when unexpected requests are made.

Hinweis

In diesem Tutorial werden nicht die Einzelheiten der erstmaligen Einrichtung Ihres Schlüsseltresors behandelt.This tutorial is not intended to explain in detail the initial setup of your key vault. Weitere Informationen hierzu finden Sie unter Erste Schritte mit dem Azure-Schlüsseltresor.For this information, see Get started with Azure Key Vault. Anleitungen für die plattformübergreifende Befehlszeilenschnittstelle finden Sie unter Verwalten von Schlüsseltresor mit CLI.For Cross-Platform Command-Line Interface instructions, see Manage Key Vault using CLI.

Einrichten von Key VaultSet up Key Vault

Damit eine Anwendung einen geheimen Schlüssel aus Key Vault abrufen kann, müssen Sie zuerst den geheimen Schlüssel erstellen und ihn in den Tresor hochladen.To enable an application to retrieve a secret from Key Vault, you must first create the secret and upload it to your vault. Starten Sie hierfür eine Azure PowerShell-Sitzung, und melden Sie sich mit dem folgenden Befehl bei Ihrem Azure-Konto an:This can be accomplished by starting an Azure PowerShell session and signing in to your Azure account with the following command:

Connect-AzureRmAccount

Geben Sie im Popup-Browserfenster den Benutzernamen und das Kennwort Ihres Azure-Kontos ein.In the pop-up browser window, enter your Azure account user name and password. PowerShell ruft alle Abonnements ab, die diesem Konto zugeordnet sind.PowerShell will get all the subscriptions that are associated with this account. PowerShell verwendet standardmäßig das erste Abonnement.PowerShell uses the first one by default.

Wenn Sie über mehrere Abonnements verfügen, müssen Sie unter Umständen das Abonnement angeben, das zum Erstellen des Schlüsseltresors verwendet wurde.If you have multiple subscriptions, you might have to specify the one that was used to create your key vault. Geben Sie Folgendes ein, um die Abonnements für Ihr Konto anzuzeigen:Enter the following to see the subscriptions for your account:

Get-AzureRmSubscription

Geben Sie Folgendes ein, um das Abonnement anzugeben, das dem zu protokollierenden Schlüsseltresor zugeordnet ist:To specify the subscription that's associated with the key vault you will be logging, enter:

Set-AzureRmContext -SubscriptionId <subscriptionID>

Da in diesem Artikel das Speichern eines Speicherkontoschlüssels als geheimer Schlüssel demonstriert wird, müssen Sie diesen Speicherkontoschlüssel abrufen.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>

Nachdem Sie Ihren geheimen Schlüssel (in diesem Fall Ihren Speicherkontoschlüssel) abgerufen haben, müssen Sie ihn in eine sichere Zeichenfolge konvertieren und anschließend einen geheimen Schlüssel mit diesem Wert in Ihrem Schlüsseltresor erstellen.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

Rufen Sie als Nächstes den URI für den erstellten geheimen Schlüssel ab.Next, get the URI for the secret you created. Dieser wird in einem späteren Schritt verwendet, wenn Sie den Schlüsseltresor zum Abrufen des geheimen Schlüssels aufrufen.This is used in a later step when you call the key vault to retrieve your secret. Führen Sie den folgenden PowerShell-Befehl aus, und notieren Sie den Wert „ID“, bei dem es sich um den URI des geheimen Schlüssels handelt:Run the following PowerShell command and make note of the ID value, which is the secret URI:

Get-AzureKeyVaultSecret –VaultName <vaultName>

Einrichten der AnwendungSet up the application

Da Sie nun über einen gespeicherten geheimen Schlüssel verfügen, können Sie diesen mithilfe von Code abrufen und verwenden.Now that you have a secret stored, you can use code to retrieve and use it. Hierfür sind mehrere Schritte erforderlich.There are a few steps required to achieve this. Der erste und wichtigste Schritt ist die Registrierung Ihrer Anwendung in Azure Active Directory. Danach müssen Sie an Key Vault Informationen zu Ihrer Anwendung übermitteln, damit der Schlüsseltresor Anforderungen von Ihrer Anwendung empfangen kann.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.

Hinweis

Ihre Anwendung muss mit demselben Azure Active Directory-Mandanten wie Ihr Schlüsseltresor erstellt werden.Your application must be created on the same Azure Active Directory tenant as your key vault.

  1. Navigieren Sie zu Azure Active Directory.Navigate to Azure Active Directory.
  2. Wählen Sie App-Registrierungen aus.Choose App registrations
  3. Wählen Sie Registrierung einer neuen Anwendung aus, um Ihrer Azure Active Directory-Instanz eine Anwendung hinzuzufügen.Choose New application registration to add an application to your Azure Active Directory.

    „Anwendungen“ in Azure Active Directory öffnen

  4. Behalten Sie im Abschnitt Erstellen den Anwendungstyp Webanwendung und/oder Web-API bei, und geben Sie der Anwendung einen Namen.In the Create section Leave the application type as WEB APPLICATION AND/OR WEB API and give your application a name. Geben Sie für die Anwendung eine Anmelde-URL ein.Give your application a SIGN-ON URL. Diese Angabe ist für diese Demo beliebig.This can be anything you want for this demo.

    Erstellen der Anwendungsregistrierung

  5. Nachdem Azure Active Directory die Anwendung hinzugefügt wurde, gelangen Sie auf die Anwendungsseite.After the application is added to Azure Active Directory, you will be brought into the application page. Wählen Sie Einstellungen und dann Eigenschaften aus.Select Settings and then select properties. Kopieren Sie den Wert für Anwendungs-ID.Copy the Application ID value. Er wird in späteren Schritten benötigt.It will be needed in later steps.

Generieren Sie dann einen Schlüssel für die Anwendung, damit diese mit Azure Active Directory interagieren kann.Next, generate a key for your application so it can interact with your Azure Active Directory. Sie können einen Schlüssel erstellen, indem Sie zum Abschnitt Schlüssel unter Einstellungen navigieren.You can create a key under by navigating to the Keys section under Settings. Notieren Sie in Ihrer Azure Active Directory-Anwendung den neu generierten Schlüssel für die Verwendung in einem späteren Schritt.Make note of the newly generated key from your Azure Active Directory application for use in a later step. Beachten Sie, dass der Schlüssel nicht mehr verfügbar ist, nachdem Sie aus diesem Abschnitt navigieren.Notice that the key will not be available after you navigate out of this section.

Azure Active Directory-App-Schlüssel

Bevor Ihre Anwendung Aufrufe an den Schlüsseltresor durchführen kann, müssen Sie den Schlüsseltresor über Ihre Anwendung und deren Berechtigungen informieren.Before establishing any calls from your application into the key vault, you must tell the key vault about your application and its permissions. Der folgende Befehl verwendet den Namen des Schlüsseltresors und die Anwendungs-ID aus Ihrer Azure Active Directory-App und gewährt dem Schlüsseltresor für die Anwendung den Zugriff zum Abrufen.The following command takes the vault name and the application 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

An diesem Punkt können Sie beginnen, Anwendungsaufrufe zu erstellen.At this point, you are ready to start building your application calls. In Ihrer Anwendung müssen Sie die NuGet-Pakete installieren, die für die Interaktion mit Azure Key Vault und Azure Active Directory benötigt werden.In your application, you must install the NuGet packages required to interact with Azure Key Vault and Azure Active Directory. Geben Sie in der Paket-Manager-Konsole von Visual Studio die folgenden Befehle ein.From the Visual Studio Package Manager console, enter the following commands. Bei der Erstellung dieses Artikels lautete die aktuelle Version des Azure Active Directory-Pakets 3.10.305231913. Prüfen Sie, ob es eine neuere Version gibt, und führen Sie ggf. eine entsprechende Aktualisierung durch.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

Erstellen Sie in Ihrem Anwendungscode eine Klasse, die die Methode für Ihre Azure Active Directory-Authentifizierung enthalten soll.In your application code, create a class to hold the method for your Azure Active Directory authentication. In diesem Beispiel heißt diese Klasse Utils.In this example, that class is called Utils. Fügen Sie die folgende using-Anweisung hinzu:Add the following using statement:

using Microsoft.IdentityModel.Clients.ActiveDirectory;

Fügen Sie als Nächstes die folgende Methode hinzu, um das JWT-Token aus Azure Active Directory abzurufen.Next, add the following method to retrieve the JWT token from Azure Active Directory. Zur besseren Verwaltbarkeit können Sie die hartcodierten Zeichenfolgenwerte in Ihre Web- oder Anwendungskonfiguration verschieben.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;
}

Fügen Sie den erforderlichen Code zum Aufrufen von Key Vault und Abrufen des Werts Ihres geheimen Schlüssels hinzu.Add the necessary code to call Key Vault and retrieve your secret value. Zuerst müssen Sie die folgende „using“-Anweisung hinzufügen:First you must add the following using statement:

using Microsoft.Azure.KeyVault;

Fügen Sie die Methodenaufrufe zum Aufrufen von Key Vault und Abrufen Ihres geheimen Schlüssels hinzu.Add the method calls to invoke Key Vault and retrieve your secret. In dieser Methode geben Sie den URI Ihres geheimen Schlüssels an, den Sie in einem vorherigen Schritt gespeichert haben.In this method, you provide the secret URI that you saved in a previous step. Beachten Sie die Verwendung der GetToken-Methode in der zuvor erstellten Utils-Klasse.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;

Wenn Sie Ihre Anwendung ausführen, müssen Sie sich jetzt bei Azure Active Directory authentifizieren und dann den Wert Ihres geheimen Schlüssels aus Azure Key Vault abrufen.When you run your application, you should now be authenticating to Azure Active Directory and then retrieving your secret value from Azure Key Vault.

Schlüsselrotation mithilfe von Azure AutomationKey rotation using Azure Automation

Es gibt verschiedene Optionen für die Implementierung einer Strategie für die Rotation von Werten, die Sie als geheime Azure Key Vault-Schlüssel speichern.There are various options for implementing a rotation strategy for values you store as Azure Key Vault secrets. Die Rotation geheimer Schlüssel kann im Rahmen eines manuellen Prozesses, programmgesteuert mithilfe von API-Aufrufen oder mithilfe eines Automatisierungsskripts erfolgen.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. Für diesen Artikel nutzen Sie Azure PowerShell zusammen mit Azure Automation, um einen Zugriffsschlüssel für das Azure Storage-Konto zu ändern.For the purposes of this article, you will be using Azure PowerShell combined with Azure Automation to change an Azure Storage Account access key. Anschließend aktualisieren Sie einen geheimen Schlüssel im Schlüsseltresor mit diesem neuen Schlüssel.You will then update a key vault secret with that new key.

Damit Azure Automation geheime Schlüsselwerte in Ihrem Schlüsseltresor festlegen kann, müssen Sie die Client-ID der Verbindung namens „AzureRunAsConnection“ abrufen, die erstellt wurde, als Sie Ihre Azure Automation-Instanz erstellt haben.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. Sie können diese ID abrufen, indem Sie in Ihrer Azure Automation-Instanz Assets auswählen.You can find this ID by choosing Assets from your Azure Automation instance. Dort wählen Sie Verbindungen und dann den Dienstprinzipal AzureRunAsConnection aus.From there, you choose Connections and then select the AzureRunAsConnection service principle. Notieren Sie den Wert von Anwendungs-ID.Take note of the Application ID.

Azure Automation-Client-ID

Wählen Sie in Assets die Option Module aus.In Assets, choose Modules. In Module wählen Sie dann Katalog aus. Anschließend suchen Sie nach aktualisierten Versionen der einzelnen Module, die Sie importieren: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

Hinweis

Zum Zeitpunkt der Erstellung dieses Artikels mussten nur die zuvor genannten Module für das folgende Skript aktualisiert werden.At the writing of this article, only the previously noted modules needed to be updated for the following script. Wenn Sie feststellen, dass Ihr Automatisierungsauftrag fehlschlägt, überprüfen Sie, ob Sie alle erforderlichen Module und ihre Abhängigkeiten importiert haben.If you find that your automation job is failing, confirm that you have imported all necessary modules and their dependencies.

Nachdem Sie die Anwendungs-ID für Ihre Azure Automation-Verbindung abgerufen haben, müssen Sie Ihren Schlüsseltresor informieren, dass diese Anwendung Zugriff zum Aktualisieren geheimer Schlüssel in Ihrem Tresor hat.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. Dies kann mit dem folgenden PowerShell-Befehl erreicht werden:This can be accomplished with the following PowerShell command:

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

Als Nächstes wählen Sie die Ressource Runbooks unter Ihrer Azure Automation-Instanz und dann Runbook hinzufügen aus.Next, select Runbooks under your Azure Automation instance, and then select Add a Runbook. Wählen Sie Schnellerfassung.Select Quick Create. Benennen Sie Ihr Runbook, und wählen Sie als Runbooktyp PowerShell aus.Name your runbook and select PowerShell as the runbook type. Optional können Sie eine Beschreibung hinzufügen.You have the option to add a description. Klicken Sie abschließend auf Erstellen.Finally, click Create.

Runbook erstellen

Im Editorbereich Ihres neuen Runbooks fügen Sie das folgende PowerShell-Skript ein: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..."
    Connect-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

Im Editorbereich können Sie Testbereich wählen, um Ihr Skript zu testen.From the editor pane, choose Test pane to test your script. Sobald das Skript ohne Fehler ausgeführt wird, können Sie die Option Veröffentlichen auswählen. Im Konfigurationsbereich für das Runbook können Sie dann einen Zeitplan dafür auswählen.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.

Überwachungspipeline für den SchlüsseltresorKey Vault auditing pipeline

Bei der Einrichtung eines Schlüsseltresors können Sie die Überwachung aktivieren, um Protokolle zu Zugriffsanforderungen zu sammeln, die an Ihren Schlüsseltresor gerichtet wurden.When you set up a key vault, you can turn on auditing to collect logs on access requests made to the key vault. Diese Protokolle werden in einem festgelegten Azure Storage-Konto gespeichert und können dann abgerufen, überwacht und analysiert werden.These logs are stored in a designated Azure Storage account and can be pulled out, monitored, and analyzed. Im folgenden Szenario werden Azure-Funktionen, Azure-Logik-Apps und Key Vault-Überwachungsprotokolle zum Erstellen einer Pipeline verwendet, die eine E-Mail sendet, sobald geheime Schlüssel aus dem Tresor von einer App abgerufen werden, die nicht der App-ID der Web-App entspricht.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.

Zunächst müssen Sie die Protokollierung für Ihren Schlüsseltresor aktivieren.First, you must enable logging on your key vault. Dies kann über die folgenden PowerShell-Befehle erfolgen (Details finden Sie unter Key Vault-Protokollierung):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

Wenn diese Option aktiviert ist, beginnen Überwachungsprotokolle mit dem Sammeln von Daten im vorgesehenen Speicherkonto.After this is enabled, audit logs start collecting into the designated storage account. Diese Protokolle enthalten Ereignisse dazu, wie, wann und von wem auf Ihre Schlüsseltresore zugegriffen wurde.These logs contain events about how and when your key vaults are accessed, and by whom.

Hinweis

Sie können auf Ihre Protokollinformationen zehn Minuten nach dem Schlüsseltresorvorgang zugreifen.You can access your logging information 10 minutes after the key vault operation. In der Regel ist dies schon früher möglich.It will usually be quicker than this.

Der nächste Schritt besteht im Erstellen einer Azure Service Bus-Warteschlange.The next step is to create an Azure Service Bus queue. In diese werden die Überwachungsprotokolle für den Schlüsseltresor übertragen.This is where key vault audit logs are pushed. Wenn sich die Überwachungsprotokollmeldungen in der Warteschlange befinden, ruft die Logik-App diese ab und reagiert entsprechend.When the audit log messages are in the queue, the logic app picks them up and acts on them. Führen Sie die folgenden Schritte aus, um einen Service Bus zu erstellen:Create a service bus with the following steps:

  1. Erstellen Sie einen Service Bus-Namespace (falls ein solcher bereits vorhanden ist, den Sie verwenden möchten, fahren Sie mit Schritt 2 fort).Create a Service Bus namespace (if you already have one that you want to use for this, skip to Step 2).
  2. Wechseln Sie im Azure-Portal zum Service Bus, und wählen Sie den Namespace aus, in dem die Warteschlange erstellt werden soll.Browse to the service bus in the Azure portal and select the namespace you want to create the queue in.
  3. Wählen Sie Ressource erstellen > Unternehmensintegration > Service Bus aus, und geben Sie dann die erforderlichen Details ein.Select Create a resource, Enterprise Integration, Service Bus, and then enter the required details.
  4. Wählen Sie die Service Bus-Verbindungsinformationen aus, indem Sie den Namespace auswählen und auf Verbindungsinformationen klicken.Select the Service Bus connection information by choosing the namespace and clicking Connection Information. Sie benötigen diese Informationen für den nächsten Teil.You will need this information for the next section.

Als Nächstes erstellen Sie eine Azure-Funktion zum Abfragen der Schlüsseltresorprotokolle im Speicherkonto und Auswählen neuer Ereignisse.Next, create an Azure function to poll key vault logs within the storage account and pick up new events. Dies ist eine Funktion, die gemäß einem Zeitplan ausgelöst wird.This will be a function that is triggered on a schedule.

Um eine Azure-Funktion zu erstellen, wählen Sie Ressource erstellen aus, suchen im Marketplace nach Funktions-App und klicken dann auf Erstellen.To create an Azure function, choose Create a resource, search the marketplace for Function App, and click Create. Während der Erstellung können Sie einen vorhandenen Hostingplan verwenden oder einen neuen erstellen.During creation, you can use an existing hosting plan or create a new one. Sie können sich auch für dynamisches Hosten entscheiden.You could also opt for dynamic hosting. Weitere Informationen zu Optionen für das Hosten von Funktionen finden Sie unter Skalieren von Azure Functions.More details on Function hosting options can be found at How to scale Azure Functions.

Nachdem die Azure-Funktion erstellt wurde, navigieren Sie zu der Funktion. Wählen Sie eine Timerfunktion und C# aus.When the Azure function is created, navigate to it and choose a timer function and C#. Klicken Sie dann auf Diese Funktion erstellen.Then click Create this function.

Blatt „Start“ von Azure Functions

Ersetzen Sie auf der Registerkarte Entwickeln den Code von „run.csx“ durch Folgendes: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;
}

Hinweis

Stellen Sie sicher, dass die Variablen im vorangegangenen Code so ersetzt werden, dass sie auf Ihr Speicherkonto, in das die Schlüsseltresorprotokolle geschrieben werden, auf den zuvor erstellten Service Bus und auf den spezifischen Pfad zu den Speicherprotokollen für den Schlüsseltresor zeigen.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.

Die Funktion verwendet die neueste Protokolldatei im Speicherkonto, in das Schlüsseltresorprotokolle geschrieben werden, ruft die neuesten Ereignisse aus dieser Datei ab und überträgt sie in eine Service Bus-Warteschlange.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. Da eine einzelne Datei mehrere Ereignisse enthalten kann, sollten Sie die Datei „sync.txt“ erstellen, die die Funktion ebenfalls untersucht, um den Zeitstempel des letzten ausgewählten Ereignisses zu bestimmen.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. Dadurch wird sichergestellt, dass Sie dasselbe Ereignis nicht mehrmals in die Warteschlange übertragen.This ensures that you don't push the same event multiple times. Diese Datei „sync.txt“ enthält einen Zeitstempel des letzten eingetretenen Ereignisses.This sync.txt file contains a timestamp for the last encountered event. Die geladenen Protokolle müssen basierend auf dem Zeitstempel sortiert werden, um sicherzustellen, dass sie in die richtige Reihenfolge gebracht werden.The logs, when loaded, have to be sorted based on the timestamp to ensure they are ordered correctly.

Hierfür verweisen wir auf verschiedene zusätzliche Bibliotheken, die in Azure Functions nicht standardmäßig verfügbar sind.For this function, we reference a couple of additional libraries that are not available out of the box in Azure Functions. Um sie einzubeziehen, muss Azure Functions sie über NuGet abrufen.To include these, we need Azure Functions to pull them using NuGet. Wählen Sie die Option Dateien anzeigen aus.Choose the View Files option.

Option „Dateien anzeigen“

Fügen Sie eine Datei namens „project.json“ mit folgendem Inhalt hinzu:And add a file called project.json with following content:

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

Dadurch wird Azure Functions beim Speichern die erforderlichen Binärdateien herunterladen.Upon Save, Azure Functions will download the required binaries.

Wechseln Sie zur Registerkarte Integrieren , und versehen Sie den Parameter „Timer“ mit einem aussagekräftigen Namen, der in der Funktion verwendet werden soll.Switch to the Integrate tab and give the timer parameter a meaningful name to use within the function. Im obigen Code wird erwartet, dass der Timer myTimerheißt.In the preceding code, it expects the timer to be called myTimer. Geben Sie einen CRON-Ausdruck wie folgt an: 0 * * * * * für den Timer, der bewirkt, dass die Funktion einmal pro Minute ausgeführt wird.Specify a CRON expression as follows: 0 * * * * * for the timer that will cause the function to run once a minute.

Fügen Sie auf der Registerkarte Integrieren auch eine Eingabe des Typs Azure Blob Storage hinzu.On the same Integrate tab, add an input of the type Azure Blob Storage. Diese verweist auf die Datei „sync.txt“, die den Zeitstempel des letzten Ereignisses enthält, das von der Funktion untersucht wurde.This will point to the sync.txt file that contains the timestamp of the last event looked at by the function. Diese Information wird in der Funktion mithilfe des Parameternamens verfügbar gemacht.This will be available within the function by the parameter name. Im obigen Code erwartet die Azure Blob Storage-Eingabe, dass der Parametername inputBlob ist.In the preceding code, the Azure Blob Storage input expects the parameter name to be inputBlob. Wählen Sie das Speicherkonto aus, das die Datei „sync.txt“ enthält (dabei kann es sich um dasselbe oder ein anderes Speicherkonto handeln).Choose the storage account where the sync.txt file will reside (it could be the same or a different storage account). Geben Sie im entsprechenden Feld den Pfad zu der Datei in diesem Format an: {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.

Fügen Sie eine Ausgabe des Typs Azure Blob Storage hinzu.Add an output of the type Azure Blob Storage output. Diese zeigt auf die Datei „sync.txt“, die Sie in der Eingabe definiert haben.This will point to the sync.txt file you defined in the input. Dies wird von der Funktion zum Schreiben des Zeitstempels des letzten untersuchten Ereignisses verwendet.This is used by the function to write the timestamp of the last event looked at. Der obige Code erwartet, dass dieser Parameter outputBlobheißt.The preceding code expects this parameter to be called outputBlob.

An diesem Punkt ist die Funktion fertig.At this point, the function is ready. Wechseln Sie zurück zur Registerkarte Entwickeln, und speichern Sie den Code.Make sure to switch back to the Develop tab and save the code. Überprüfen Sie das Ausgabefenster auf Kompilierungsfehler, und korrigieren Sie diese entsprechend.Check the output window for any compilation errors and correct them accordingly. Falls die Kompilierung erfolgt, sollte der Code nun die Schlüsseltresorprotokolle minütlich überprüfen und alle neuen Ereignisse in die definierte Service Bus-Warteschlange übertragen.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. Immer wenn die Funktion ausgelöst wird, sollten Protokollinformationen im Protokollfenster ausgegeben werden.You should see logging information write out to the log window every time the function is triggered.

Azure-Logik-AppAzure logic app

Als Nächstes müssen Sie eine Azure-Logik-App erstellen, die die Ereignisse verarbeitet, die die Funktion in die Service Bus-Warteschlange überträgt, den Inhalt analysiert und basierend auf einer erfüllten Bedingung eine E-Mail sendet.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.

Erstellen Sie eine Logik-App über Neu > Logik-App.Create a logic app by going to New > Logic App.

Sobald die Logik-App erstellt wurde, navigieren Sie zu ihr und wählen Bearbeitenaus.Once the logic app is created, navigate to it and choose edit. Wählen Sie im Logik-App-Editor Service Bus-Warteschlange aus, und geben Sie Ihre Service Bus-Anmeldeinformationen ein, um sie mit der Warteschlange zu verbinden.Within the logic app editor, choose Service Bus Queue and enter your Service Bus credentials to connect it to the queue.

Service Bus für Azure-Logik-App

Wählen Sie anschließend Bedingung hinzufügen aus.Next choose Add a condition. Wechseln Sie in der Bedingung zum erweiterten Editor. Geben Sie den folgenden Code ein, und ersetzen Sie die APP_ID durch die tatsächliche APP_ID Ihrer Web-App: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'])

Dieser Ausdruck gibt false zurück, wenn die appid im eingehenden Ereignis (dem Text der Service Bus-Nachricht) nicht die appid der App ist.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.

Erstellen Sie jetzt unter Falls nein, nichts tun eine Aktion.Now, create an action under If no, do nothing.

Azure-Logik-App, Aktion wählen

Wählen Sie als Aktion Office 365 – E-Mail senden.For the action, choose Office 365 - send email. Füllen Sie die Felder aus, um eine E-Mail zu erstellen, wenn die definierte Bedingung false zurückgibt.Fill out the fields to create an email to send when the defined condition returns false. Wenn Sie Office 365 nicht haben, können Sie eine Alternative wählen, um dieselben Ergebnisse zu erzielen.If you do not have Office 365, you could look at alternatives to achieve the same results.

An diesem Punkt haben Sie eine lückenlose Pipeline, die einmal pro Minute eine Überprüfung auf neue Schlüsseltresor-Überwachungsprotokolle vornimmt.At this point, you have an end to end pipeline that looks for new key vault audit logs once a minute. Die gefundenen neuen Protokolle werden in eine Service Bus-Warteschlange verschoben.It pushes new logs it finds to a service bus queue. Die Logik-App wird ausgelöst, wenn eine neue Nachricht in der Warteschlange eintrifft.The logic app is triggered when a new message lands in the queue. Wenn die appid innerhalb des Ereignisses nicht der App-ID der aufrufenden Anwendung entspricht, wird eine E-Mail gesendet.If the appid within the event does not match the app ID of the calling application, it sends an email.