# Protokollverwaltung

### Logging in Azure Monitor aktivieren

Ab Version 3.0 werden SCEPman sowie der Certificate Master die Microsoft Log Ingestion API verwenden, um Protokolle in Azure Monitor zu schreiben. Dabei wird das Konzept eines Log Analytics Workspace genutzt, um die Daten zu speichern und die Analyse zu ermöglichen, sowie eine Data Collection Rule, die zwischen der App Service und dem Protokollspeicher vermittelt. Dies ermöglicht einen moderneren Ansatz, einschließlich RBAC-basierter Berechtigungen für SCEPman, um auf den LAW zuzugreifen.

Das Erstellen des Log Analytics Workspace sowie die Konfiguration der Data Collection Rule werden automatisch durchgeführt, indem `Complete-SCEPmanInstallation` des SCEPman PowerShell-Moduls ausgeführt wird.

{% hint style="info" %}
Das **Standardaufbewahrungs** zeitraum für Daten, die in einer Log Analytics-Tabelle gespeichert sind, beträgt **30 Tage**. Falls ein anderer Aufbewahrungszeitraum erforderlich ist, passen Sie die Konfiguration der Tabelle "SCEPman\_CL" entsprechend an.
{% endhint %}

#### Data Collector API erneut aktivieren

Wenn Sie aus irgendeinem Grund die vorherige API wieder verwenden möchten, können Sie dies tun, indem Sie die mit Log Ingestion verbundenen App-Service-Variablen entfernen und die Variablen erneut hinzufügen, die von der Data Collector API verwendet werden sollen.

Zu entfernende **Variablen**:

* [AppConfig:LoggingConfig:DataCollectionEndpointUri](https://app.gitbook.com/o/-LhPlvZ6dc8XcqY7tdZw/s/-LoGejQeUQcw7lqnQ3WX/~/edit/~/changes/787/scepman-configuration/application-settings/dependencies-azure-services/logging#appconfig-loggingconfig-datacollectionendpointuri)
* [AppConfig:LoggingConfig:RuleId](https://app.gitbook.com/o/-LhPlvZ6dc8XcqY7tdZw/s/-LoGejQeUQcw7lqnQ3WX/~/edit/~/changes/787/scepman-configuration/application-settings/dependencies-azure-services/logging#appconfig-loggingconfig-ruleid)

Zu hinzufügende Variablen:

* [AppConfig:LoggingConfig:WorkspaceId](https://app.gitbook.com/o/-LhPlvZ6dc8XcqY7tdZw/s/-LoGejQeUQcw7lqnQ3WX/~/edit/~/changes/787/scepman-configuration/application-settings/dependencies-azure-services/logging#appconfig-loggingconfig-workspaceid)
* [AppConfig:LoggingConfig:SharedKey](https://app.gitbook.com/o/-LhPlvZ6dc8XcqY7tdZw/s/-LoGejQeUQcw7lqnQ3WX/~/edit/~/changes/787/scepman-configuration/application-settings/dependencies-azure-services/logging#appconfig-loggingconfig-sharedkey)

SCEPman übernimmt die Einstellungen nach einem Neustart automatisch und verwendet dann wieder die Data Collector API.

## KQL-Abfragebeispiele

### Probleme mit Ihrer SCEPman-Instanz anzeigen

```kusto
SCEPman_CL
| where Level == "Warn" or Level == "Error" or Level == "Fatal"
```

### Anzahl ausgestellter Zertifikate nach Endpunkt im ausgewählten Zeitrahmen

{% hint style="success" %}
Diese Abfrage funktioniert garantiert mit SCEPman 3.0 und neuer, wenn die Log Ingestion API zum Protokollieren verwendet wird. Änderungen an SCEPman, die diese Abfrage unbrauchbar machen, gelten als Breaking Changes.
{% endhint %}

{% tabs %}
{% tab title="Log Ingestion API ( Standard )" %}

```kql
SCEPman_CL
| where Level == "Info" and Message startswith_cs "Issued a certificate with serial number"
| project Message, RequestBase = trim_end('/', replace_string(replace_string(replace_regex(RequestUrl, "(/pkiclient\\.exe)?(\\?operation=PKIOperation(&message=.+)?)?", ""),"certsrv/mscep/mscep.dll","intune"),"step/enrollment","activedirectory"))
| summarize IssuanceCount = count() by Endpoint = extract("/([a-zA-Z]+)$", 1, RequestBase)
```

{% endtab %}

{% tab title="Data Collector API ( Alt )" %}

```kusto
SCEPman_CL
| where Level == "Info" and Message startswith_cs "Issued a certificate with serial number"
| project Message, RequestBase = trim_end('/', replace_string(replace_string(replace_regex(RequestUrl_s, "(/pkiclient\\.exe)?(\\?operation=PKIOperation(&message=.+)?)?", ""),"certsrv/mscep/mscep.dll","intune"),"step/enrollment","activedirectory"))
| summarize IssuanceCount = count() by Endpoint = extract("/([a-zA-Z]+)$", 1, RequestBase)
```

{% endtab %}
{% endtabs %}

Ab SCEPman 2.8 gibt es pro ausgestelltem Zertifikat immer genau einen Protokolleintrag auf Info-Ebene, dessen Protokollnachricht mit "Issued a certificate with serial number " beginnt, gefolgt von der Seriennummer. Aufgrund des unlösbaren [Zwei-Armeen-Problem](https://en.wikipedia.org/wiki/Two_Generals'_Problem)kann es jedoch vorkommen, dass das erstellte Zertifikat den Anforderer nie erreicht oder ein anderer Fehler die eigentliche Registrierung verhindert. Ebenso kann es bei schweren Fehlern vorkommen, dass ein Protokolleintrag ohne entsprechenden Datenbankeintrag existiert oder umgekehrt.

### Unterscheidbare Zertifikate mit OCSP-Prüfung

{% tabs %}
{% tab title="Log Ingestion API ( Standard )" %}

```kusto
let map_certtype = datatable(serial_start:string, readable:string)
[
  "40", "Intune-Gerät",
  "41", "Intune-Gerät",
  "42", "Nicht konformes Intune-Gerät",
  "50", "Statisch",
  "51", "Statisch",
  "60", "Intune-Benutzer",
  "61", "Intune-Benutzer",
  "64", "Jamf-Benutzer",
  "65", "Jamf-Benutzer",
  "6C", "Jamf-Benutzer auf Gerät",
  "6D", "Jamf-Benutzer auf Gerät",
  "70", "Domänencontroller",
  "7C", "Jamf-Benutzer auf Computer",
  "7D", "Jamf-Benutzer auf Computer",
  "54", "Jamf-Computer",
  "55", "Jamf-Computer",
  "44", "Jamf-Gerät",
  "45", "Jamf-Gerät"
];
SCEPman_CL
| where LogCategory == "Scepman.Server.Controllers.OcspController" and Level == "Info"
| where Message startswith_cs "OCSP Response"
| project serial = extract("Serial Number ([A-F0-9]+)", 1, Message)
| distinct serial
| extend serial_start = substring(serial,0,2)
| join kind=leftouter map_certtype on serial_start
| summarize count() by (readable)
```

{% endtab %}

{% tab title="Data Collector API ( Alt )" %}

```kql
let map_certtype = datatable(serial_start:string, readable:string)
[
  "40", "Intune-Gerät",
  "41", "Intune-Gerät",
  "42", "Nicht konformes Intune-Gerät",
  "50", "Statisch",
  "51", "Statisch",
  "60", "Intune-Benutzer",
  "61", "Intune-Benutzer",
  "64", "Jamf-Benutzer",
  "65", "Jamf-Benutzer",
  "6C", "Jamf-Benutzer auf Gerät",
  "6D", "Jamf-Benutzer auf Gerät",
  "70", "Domänencontroller",
  "7C", "Jamf-Benutzer auf Computer",
  "7D", "Jamf-Benutzer auf Computer",
  "54", "Jamf-Computer",
  "55", "Jamf-Computer",
  "44", "Jamf-Gerät",
  "45", "Jamf-Gerät"
];
SCEPman_CL
| where LogCategory_s == "Scepman.Server.Controllers.OcspController" and Level == "Info"
| where Message startswith_cs "OCSP Response"
| project serial = extract("Serial Number ([A-F0-9]+)", 1, Message)
| distinct serial
| extend serial_start = substring(serial,0,2)
| join kind=leftouter map_certtype on serial_start
| summarize count() by (readable)
```

{% endtab %}
{% endtabs %}
