Office 365 管理 API を使って SharePoint Online の監査ログを取得する
はじめに
いままでずっと SharePoint Online の監査ログの生データは取得できないと思っていたのですが、実は Office 365 管理 API というものを使えば取得できるのだそうです。Office 365 管理 API は SharePoint、Exchange、Teams、Power Platform などのさまざまな監査ログを取得できるのですが、特に利用状況の監視目的で SharePoint Online の監査ログを取りたいという要望は非常に多いため、この方法を使えば解決できるのはないかと思います。
なお今回は以下の記事を参考にしています。
サンプル コード
実行手順
Office 365 管理 API でログを取得するには以下の手順が必要になります。
- アクセス トークンを取得する
- サブスクリプションを作成する
- コンテンツの URL を取得する
- コンテンツを取得する
アクセス トークンを取得する
Office 365 管理 API を使用するためには、はじめに Azure AD にアプリを登録する必要があります。API のアクセス許可 では Office 365 Management APIs - アプリケーションのアクセス許可 - ActivityFeed.Read を追加します。
またアプリケーション シークレットも取得しておきます。
Office 365 管理 API は Azure AD の v2.0 エンドポイントに対応していないので MSAL を使うことができません。ADAL を使ってもいいのですが、面倒なので、今回は直接 HttpClient
で取りに行くようにします。といっても Client Credentials Grant なのでそれほど難しくはありません。
private static void AcquireToken()
{
var httpRequestUrl = $"https://login.microsoftonline.com/{TenantId}/oauth2/token";
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, httpRequestUrl);
var httpRequestContent = new FormUrlEncodedContent(new Dictionary<string, string>()
{
{ "grant_type", "client_credentials" },
{ "resource", Resource },
{ "client_id", ClientId },
{ "client_secret", ClientSecret }
});
httpRequestMessage.Content = httpRequestContent;
var httpResponseMessage = HttpClient.SendAsync(httpRequestMessage).GetAwaiter().GetResult();
var httpResponseContent = httpResponseMessage.Content.ReadAsStringAsync().GetAwaiter().GetResult();
var httpResponseJson = JsonConvert.DeserializeObject<JToken>(httpResponseContent);
AccessToken = httpResponseJson.Value<string>("access_token");
}
サブスクリプションを作成する
Office 365 管理 API のコンテンツ タイプ (Audit.SharePoint
) に対してサブスクリプションを作成します。Webhook も登録できるようなのですが、今回は省略します。PublisherIdentifier
は任意の GUID を指定してください。
private static void CreateSubscription()
{
var httpRequestUrl = $"https://manage.office.com/api/v1.0/{TenantId}/activity/feed/subscriptions/start" +
$"?contentType=Audit.SharePoint" +
$"&PublisherIdentifier={PublisherIdentifier}";
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, httpRequestUrl);
httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken);
var httpResponseMessage = HttpClient.SendAsync(httpRequestMessage).GetAwaiter().GetResult();
var httpResponseContent = httpResponseMessage.Content.ReadAsStringAsync().GetAwaiter().GetResult();
}
コンテンツの URL を取得する
ログを取得する時間を指定してコンテンツ データのダウンロード先の URL を取得します。時間は 24 時間以内で過去 7 日以内である必要があります。今回は 1 日前のデータを取得するように指定します。
private static void GetContentUri()
{
var startTime = DateTime.Today.AddDays(-1).ToUniversalTime().ToString("yyyy-MM-dd'T'HH:mm:ss");
var endTime = DateTime.Today.AddSeconds(-1).ToUniversalTime().ToString("yyyy-MM-dd'T'HH:mm:ss");
var httpRequestUrl = $"https://manage.office.com/api/v1.0/{TenantId}/activity/feed/subscriptions/content" +
$"?contentType=Audit.SharePoint" +
$"&PublisherIdentifier={PublisherIdentifier}" +
$"&startTime={startTime}" +
$"&endTime={endTime}";
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, httpRequestUrl);
httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken);
var httpResponseMessage = HttpClient.SendAsync(httpRequestMessage).GetAwaiter().GetResult();
var httpResponseContent = httpResponseMessage.Content.ReadAsStringAsync().GetAwaiter().GetResult();
var httpResponseJson = JsonConvert.DeserializeObject<JArray>(httpResponseContent);
ContentUri = httpResponseJson[0].Value<string>("contentUri");
}
コンテンツを取得する
取得した URL から JSON 形式のコンテンツを取得します。
private static void GetContents()
{
var httpRequestUrl = ContentUri;
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, httpRequestUrl);
httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken);
var httpResponseMessage = HttpClient.SendAsync(httpRequestMessage).GetAwaiter().GetResult();
var httpResponseContent = httpResponseMessage.Content.ReadAsStringAsync().GetAwaiter().GetResult();
var httpResponseJson = JsonConvert.DeserializeObject<JArray>(httpResponseContent);
Console.WriteLine(JsonConvert.SerializeObject(httpResponseJson, Formatting.Indented));
}
実行結果
以下のような JSON が出力されます。サンプルはファイルのダウンロードですが、それだけではなく、いろいろな種類のログが取得できます。
[
{
"CreationTime": "2020-09-01T14:00:03",
"Id": "bea6430c...",
"Operation": "FileDownloaded",
"OrganizationId": "92dbed3f...",
"RecordType": 6,
"UserKey": "i:0h.f|membership|{{user-principal-name}}",
"UserType": 0,
"Version": 1,
"Workload": "OneDrive",
"ClientIP": "203.0.113.1",
"ObjectId": "https://{{tenant-name}}-my.sharepoint.com/personal/{{user-principal-name}}/Documents/fitbit.json",
"UserId": "{{user-principal-name}}",
"CorrelationId": "1aba0151...",
"EventSource": "SharePoint",
"ItemType": "File",
"ListId": "ccf377fa...",
"ListItemUniqueId": "3afd549b...",
"Site": "0815189e...",
"WebId": "15cdf073...",
"HighPriorityMediaProcessing": false,
"SourceFileExtension": "json",
"SiteUrl": "https://{{tenant-name}}-my.sharepoint.com/personal/{{user-principal-name}}/",
"SourceFileName": "fitbit.json",
"SourceRelativeUrl": "Documents"
},
...
]
何が取得できるかについては以下が参考になります。
おわりに
Office 365 管理 API に関する情報は以下にまとまっています。
オンプレの SharePoint で監査ログを取っていろいろやっていたことを、SharePoint Online に移行しても同じことをやりたい、というときにぜひ使っていただきたいと思います。
Discussion