This commit is contained in:
Isaiah Williams 2019-12-10 17:39:32 -06:00 коммит произвёл GitHub
Родитель f8ec1f46fd
Коммит 7660dae8e0
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 223 добавлений и 41 удалений

Просмотреть файл

@ -26,53 +26,39 @@ Gets the sign-in activities for the specified user.
### Example 1
```powershell
PS C:\> Get-PartnerUserSignInActivity -UserId '3dd89389-b34c-4f5a-975d-516df5694d7e'
```
Gets the sign-in activities for the specified user.
### Example 2
```powershell
PS C:\> Get-PartnerUserSignInActivity -StartDate (Get-Date).AddDays(-7) -UserId '3dd89389-b34c-4f5a-975d-516df5694d7e'
```
Gets the sign-in activities from the past seven days for the specified user.
### Example 3
### Example 2
```powershell
PS C:\> $users = Get-PartnerUser
PS C:\> $activities = $users.ForEach({Get-PartnerUserSignInActivity -StartDate (Get-Date).AddDays(-7) -UserId $_.Id})
PS C:\> $activities | ? {$_.AuthenticationDetails | ? {$_.Succeeded -eq $true}}
PS C:\> Get-PartnerUserSignInActivity -StartDate (Get-Date).AddDays(-7) -UserId '3dd89389-b34c-4f5a-975d-516df5694d7e' | ? {$_.AuthenticationDetails | ? {$_.Succeeded -eq $true}}
```
Gets the sign-in activities from the past seven days that have successfully authenticated.
Gets the successful sign-in activities from the past seven days for the specified user.
### Example 3
```powershell
PS C:\> Get-PartnerUserSignInActivity -StartDate (Get-Date).AddDays(-7) -UserId '3dd89389-b34c-4f5a-975d-516df5694d7e' | ? {$_.AuthenticationDetails | ? {$_.Succeeded -eq $true}} | ? {$_.MfaDetail -eq $null}
```
Gets the successful sign-in activities from the past seven days for the specified user that were not challenged by multi-factor authentication.
### Example 4
```powershell
PS C:> $users = Get-PartnerUser
PS C:> $activities = $users.ForEach({Get-PartnerUserSignInActivity -EndDate (Get-Date) -StartDate (Get-Date).AddDays(-7) -UserId $_.Id})
PS C:> $activities | ? {$_.AuthenticationDetails | ? {$_.Succeeded -eq $true}} | ? {$_.ResourceId -eq 'fa3d9a0c-3fb0-42cc-9193-47c7ecd2edbd'}
PS C:\> $signIns = Get-PartnerUserSignInActivity -StartDate (Get-Date).AddDays(-7) | ? {$_.AuthenticationDetails | ? {$_.Succeeded -eq $true}} | ? {$_.MfaDetail -eq $null}
```
Gets the sign-in activities from the past seven days where the resource being accessed was the Partner Center API.
Gets the successful sign-in activities all users from the past seven days in your partner tenant that were not challenged by multi-factor authentication.
### Example 5
```powershell
PS C:\> $users = Get-PartnerUser
PS C:\> $activities = $users.ForEach({Get-PartnerUserSignInActivity -StartDate (Get-Date).AddDays(-7) -UserId $_.Id})
PS C:\> $activities | ? {$_.AuthenticationDetails | ? {$_.Succeeded -eq $true}} | ? {$_.MfaDetail -eq $null}
PS C:\> $signIns = Get-PartnerUserSignInActivity -StartDate (Get-Date).AddDays(-7)
PS C:\> $signIns | ? {$_.AuthenticationDetails | ? {$_.Succeeded -eq $true}} | ? {$_.MfaDetail -eq $null} | ? {$_.ResourceId -eq 'fa3d9a0c-3fb0-42cc-9193-47c7ecd2edbd'}
```
Gets the sign-in activities from the past seven days that have successfully authenticated, but have not utilized multi-factor authentication.
### Example 6
```powershell
PS C:> $users = Get-PartnerUser
PS C:> $activities = $users.ForEach({Get-PartnerUserSignInActivity -EndDate (Get-Date) -StartDate (Get-Date).AddDays(-7) -UserId $_.Id})
PS C:> $activities | ? {$_.AuthenticationDetails | ? {$_.Succeeded -eq $true}} | ? {$_.MfaDetail -eq $null} | ? {$_.ResourceId -eq 'fa3d9a0c-3fb0-42cc-9193-47c7ecd2edbd'}
```
Gets the sign-in activities from the past seven days where the resource being accessed was the Partner Center API and the sign-in activity was not challenged for multi-factor authentication.
Gets the successful sign-in activities from the past seven days, where the resource being assessed was the Partner Center API and were not challenged by multi-factor authentication.
## PARAMETERS

Просмотреть файл

@ -4,13 +4,16 @@
namespace Microsoft.Store.PartnerCenter.PowerShell.Commands
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Management.Automation;
using System.Net;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Graph;
using Models.Authentication;
using System.Collections.Generic;
using Network;
using System.Threading.Tasks;
[Cmdlet(VerbsCommon.Get, "PartnerUserSignInActivity"), OutputType(typeof(SignIn))]
public class GetPartnerUserSignInActivity : PartnerAsyncCmdlet
@ -20,6 +23,26 @@ namespace Microsoft.Store.PartnerCenter.PowerShell.Commands
/// </summary>
private const string RequestFromNonPremiumTenant = "Authentication_RequestFromNonPremiumTenantOrB2CTenant";
/// <summary>
/// Represents the default amount of time used when calculating a random delta in the delay between retries.
/// </summary>
private static readonly TimeSpan DefaultClientBackoff = TimeSpan.FromSeconds(10.0);
/// <summary>
/// Represents the default maximum amount of time used when calculating the exponential delay between retries.
/// </summary>
private static readonly TimeSpan DefaultMaxBackoff = TimeSpan.FromSeconds(30.0);
/// <summary>
/// Represents the default minimum amount of time used when calculating the exponential delay between retries.
/// </summary>
private static readonly TimeSpan DefaultMinBackoff = TimeSpan.FromSeconds(1.0);
/// <summary>
/// The queue of paged Microsoft Graph request operations.
/// </summary>
private static readonly Queue<IBaseRequest> PagedRequests = new Queue<IBaseRequest>();
/// <summary>
/// Gets or sets the end date portion of the query.
/// </summary>
@ -72,25 +95,89 @@ namespace Microsoft.Store.PartnerCenter.PowerShell.Commands
if (!string.IsNullOrEmpty(filter))
{
queryOptions = new List<QueryOption>
{
new QueryOption("$filter", $"({filter})")
};
{
new QueryOption("$filter", $"({filter})")
};
}
collection = await client.AuditLogs.SignIns.Request(queryOptions).Top(500).GetAsync(CancellationToken).ConfigureAwait(false);
signIns = new List<SignIn>(collection.CurrentPage);
while (collection.NextPageRequest != null)
try
{
collection = await collection.NextPageRequest.GetAsync(CancellationToken).ConfigureAwait(false);
signIns.AddRange(collection.CurrentPage);
}
collection = await client.AuditLogs.SignIns.Request(queryOptions).Top(500).GetAsync(CancellationToken).ConfigureAwait(false);
signIns = new List<SignIn>(collection.CurrentPage);
while (collection.NextPageRequest != null)
{
collection = await collection.NextPageRequest.GetAsync(CancellationToken).ConfigureAwait(false);
signIns.AddRange(collection.CurrentPage);
}
}
catch (ServiceException ex)
{
if (!ex.Error.Code.Equals(RequestFromNonPremiumTenant))
{
throw;
}
signIns = await GetSignInActivitiesAsync(client).ConfigureAwait(false);
}
WriteObject(signIns, true);
}, true);
}
private async Task<List<SignIn>> GetSignInActivitiesAsync(IGraphServiceClient client)
{
BatchRequestContent batchRequestContent;
BatchResponseContent batchResponseContent;
IGraphServiceUsersCollectionPage userCollection;
List<SignIn> signIns;
List<User> users;
string filter = string.Empty;
userCollection = await client.Users.Request().Top(500).GetAsync().ConfigureAwait(false);
users = new List<User>(userCollection.CurrentPage);
while (userCollection.NextPageRequest != null)
{
userCollection = await userCollection.NextPageRequest.GetAsync().ConfigureAwait(false);
users.AddRange(userCollection.CurrentPage);
}
if (StartDate != null)
{
filter = AppendValue(filter, $"createdDateTime ge {StartDate.Value.ToString("yyyy-MM-ddTHH:mm:ssZ")}");
}
if (EndDate != null)
{
filter = AppendValue(filter, $"createdDateTime le {EndDate.Value.ToString("yyyy-MM-ddTHH:mm:ssZ")}");
}
signIns = new List<SignIn>();
foreach (IEnumerable<User> batch in Batch(users, 5))
{
batchRequestContent = new BatchRequestContent();
foreach (User user in batch)
{
batchRequestContent.AddBatchRequestStep(client.AuditLogs.SignIns.Request(new List<QueryOption>
{
new QueryOption("$filter", $"({AppendValue(filter, $"userId eq '{user.Id}'")})")
}).Top(200));
}
batchResponseContent = await client.Batch.Request().PostAsync(batchRequestContent, CancellationToken).ConfigureAwait(false);
await ParseBatchResponseAsync(client, batchRequestContent, batchResponseContent, signIns).ConfigureAwait(false);
}
while (PagedRequests.Count != 0)
{
await ProcessPagedRequestsAsync(client, signIns).ConfigureAwait(false);
}
return signIns;
}
private static string AppendValue(string baseValue, string appendValue)
{
@ -101,5 +188,114 @@ namespace Microsoft.Store.PartnerCenter.PowerShell.Commands
return $"{baseValue} and {appendValue}";
}
private static IEnumerable<IEnumerable<T>> Batch<T>(IEnumerable<T> entities, int batchSize)
{
int size = 0;
while (size < entities.Count())
{
yield return entities.Skip(size).Take(batchSize);
size += batchSize;
}
}
private async Task ParseBatchResponseAsync(IGraphServiceClient client, BatchRequestContent batchRequestContent, BatchResponseContent batchResponseContent, List<SignIn> signIns, int retryCount = 0)
{
AuditLogRootRestrictedSignInsCollectionResponse collection;
Dictionary<string, HttpResponseMessage> responses;
client.AssertNotNull(nameof(client));
batchRequestContent.AssertNotNull(nameof(batchRequestContent));
batchResponseContent.AssertNotNull(nameof(batchResponseContent));
signIns.AssertNotNull(nameof(signIns));
responses = await batchResponseContent.GetResponsesAsync().ConfigureAwait(false);
foreach (KeyValuePair<string, HttpResponseMessage> item in responses.Where(item => item.Value.IsSuccessStatusCode))
{
collection = await batchResponseContent
.GetResponseByIdAsync<AuditLogRootRestrictedSignInsCollectionResponse>(item.Key).ConfigureAwait(false);
collection.AdditionalData.TryGetValue("@odata.nextLink", out object nextPageLink);
string nextPageLinkString = nextPageLink as string;
if (!string.IsNullOrEmpty(nextPageLinkString))
{
collection.Value.InitializeNextPageRequest(client, nextPageLinkString);
}
if (collection.Value.NextPageRequest != null)
{
PagedRequests.Enqueue(collection.Value.NextPageRequest);
}
signIns.AddRange(collection.Value);
}
if (PagedRequests.Count >= 5)
{
await ProcessPagedRequestsAsync(client, signIns).ConfigureAwait(false);
}
await RetryRequestWithTransientFaultAsync(client, batchRequestContent, responses, signIns, ++retryCount).ConfigureAwait(false);
}
private async Task ProcessPagedRequestsAsync(IGraphServiceClient client, List<SignIn> signIns)
{
BatchRequestContent batchRequestContent;
BatchResponseContent batchResponseContent;
int numberOfRequests;
client.AssertNotNull(nameof(client));
signIns.AssertNotNull(nameof(signIns));
if (PagedRequests.Count == 0)
{
return;
}
batchRequestContent = new BatchRequestContent();
numberOfRequests = PagedRequests.Count > 5 ? 5 : PagedRequests.Count;
for (int i = 0; i < numberOfRequests; i++)
{
batchRequestContent.AddBatchRequestStep(PagedRequests.Dequeue());
}
batchResponseContent = await client.Batch.Request().PostAsync(batchRequestContent, CancellationToken).ConfigureAwait(false);
await ParseBatchResponseAsync(client, batchRequestContent, batchResponseContent, signIns).ConfigureAwait(false);
}
private async Task RetryRequestWithTransientFaultAsync(IGraphServiceClient client, BatchRequestContent batchRequestContent, Dictionary<string, HttpResponseMessage> responses, List<SignIn> signIns, int retryCount)
{
BatchRequestContent retryBatchRequestContent = new BatchRequestContent();
BatchResponseContent batchResponseContent;
Random random;
double delta;
client.AssertNotNull(nameof(client));
batchRequestContent.AssertNotNull(nameof(batchRequestContent));
responses.AssertNotNull(nameof(responses));
if (retryCount <= 3 && responses.Where(item => item.Value.StatusCode == (HttpStatusCode)429).Any())
{
foreach (KeyValuePair<string, HttpResponseMessage> item in responses.Where(item => item.Value.StatusCode == (HttpStatusCode)429))
{
retryBatchRequestContent.AddBatchRequestStep(batchRequestContent.BatchRequestSteps[item.Key]);
}
random = new Random();
delta = (Math.Pow(2.0, retryCount) - 1.0) *
random.Next((int)(DefaultClientBackoff.TotalMilliseconds * 0.8), (int)(DefaultClientBackoff.TotalMilliseconds * 1.2));
await Task.Delay((int)Math.Min(DefaultMinBackoff.TotalMilliseconds + delta, DefaultMaxBackoff.TotalMilliseconds), CancellationToken).ConfigureAwait(false);
batchResponseContent = await client.Batch.Request().PostAsync(retryBatchRequestContent, CancellationToken).ConfigureAwait(false);
await ParseBatchResponseAsync(client, retryBatchRequestContent, batchResponseContent, signIns, retryCount).ConfigureAwait(false);
}
}
}
}