Skip to content

Commit

Permalink
Publish v19 (#116)
Browse files Browse the repository at this point in the history
* Fix #109

* Update Microsoft.Graph and Microsoft.Identity.Client

* Add ConfigureAwait(false) to Task.WhenAll()

* Fix bug: set ExcludeMembers instead of ExcludeGuests in new AAD tenant dialog

* Better handle scenario when AzureCP cannot get an access token for a tenant

* Update CHANGELOG.md

* Update Microsoft.Identity.Client and Microsoft.Graph

* Update text in AzureCP global admin page

* Update CHANGELOG.md

* Update NuGet packages
  • Loading branch information
Yvand authored Feb 16, 2021
1 parent 317c017 commit 2f80c4d
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 19 deletions.
2 changes: 1 addition & 1 deletion AzureCP.Tests/AzureCP.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
<Version>12.0.3</Version>
</PackageReference>
<PackageReference Include="NUnit">
<Version>3.12.0</Version>
<Version>3.13.1</Version>
</PackageReference>
<PackageReference Include="NUnit3TestAdapter">
<Version>3.17.0</Version>
Expand Down
14 changes: 10 additions & 4 deletions AzureCP/AzureCP.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1151,7 +1151,7 @@ protected virtual void BuildFilter(OperationContext currentContext, List<AzureTe
StringBuilder userFilterBuilder = new StringBuilder();
StringBuilder groupFilterBuilder = new StringBuilder();
StringBuilder userSelectBuilder = new StringBuilder("UserType, Mail, "); // UserType and Mail are always needed to deal with Guest users
StringBuilder groupSelectBuilder = new StringBuilder("Id, "); // Id is always required for groups
StringBuilder groupSelectBuilder = new StringBuilder("Id, securityEnabled, "); // Id is always required for groups

//// Microsoft Graph doesn't support operator not equals (ne) on attribute UserType, it can only be queried using equals (eq)
//string memberOnlyUserTypeFilter = " and UserType eq 'Member'";
Expand Down Expand Up @@ -1463,7 +1463,7 @@ protected virtual async Task<AzureADResult> QueryAzureADTenantAsync(OperationCon
// Cannot use Task.WaitAll() because it's actually blocking the threads, preventing parallel queries on others AAD tenants.
// Use await Task.WhenAll() as it does not block other threads, so all AAD tenants are actually queried in parallel.
// More info: https://stackoverflow.com/questions/12337671/using-async-await-for-multiple-tasks
await Task.WhenAll(new Task[1] { batchQueryTask });
await Task.WhenAll(new Task[1] { batchQueryTask }).ConfigureAwait(false);
ClaimsProviderLogging.LogDebug($"Waiting on Task.WaitAll for {tenant.Name} finished");
}
}
Expand All @@ -1472,6 +1472,11 @@ protected virtual async Task<AzureADResult> QueryAzureADTenantAsync(OperationCon
ClaimsProviderLogging.Log($"[{ProviderInternalName}] Queries on Azure AD tenant '{tenant.Name}' exceeded timeout of {timeout} ms and were cancelled.", TraceSeverity.Unexpected, EventSeverity.Error, TraceCategory.Lookup);
tryAgain = true;
}
catch (ServiceException ex)
{
ClaimsProviderLogging.LogException(ProviderInternalName, $"Microsoft.Graph could not query tenant '{tenant.Name}'", TraceCategory.Lookup, ex);
tryAgain = true;
}
catch (AggregateException ex)
{
// Task.WaitAll throws an AggregateException, which contains all exceptions thrown by tasks it waited on
Expand Down Expand Up @@ -1499,9 +1504,10 @@ protected virtual List<AzureCPResult> ProcessAzureADResults(OperationContext cur
// Split results between users/groups and list of registered domains in the tenant
List<DirectoryObject> usersAndGroups = new List<DirectoryObject>();
// For each Azure AD tenant where list of result (UsersAndGroups) is not null
foreach (AzureADResult tenantResults in azureADResults.Where(x => x.UsersAndGroups != null))
// singleTenantResults in azureADResults can be null if AzureCP failed to get a valid access token for it
foreach (AzureADResult singleTenantResults in azureADResults.Where(singleTenantResults => singleTenantResults != null && singleTenantResults.UsersAndGroups != null))
{
usersAndGroups.AddRange(tenantResults.UsersAndGroups);
usersAndGroups.AddRange(singleTenantResults.UsersAndGroups);
//domains.AddRange(tenantResults.DomainsRegisteredInAzureADTenant);
}

Expand Down
4 changes: 2 additions & 2 deletions AzureCP/AzureCP.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,10 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Graph">
<Version>3.19.0</Version>
<Version>3.23.0</Version>
</PackageReference>
<PackageReference Include="Microsoft.Identity.Client">
<Version>4.22.0</Version>
<Version>4.25.0</Version>
</PackageReference>
<PackageReference Include="Nito.AsyncEx">
<Version>5.1.0</Version>
Expand Down
27 changes: 16 additions & 11 deletions AzureCP/TEMPLATE/ADMIN/AzureCP/AzureCPGlobalSettings.ascx
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,9 @@
<asp:Button UseSubmitBehavior="false" runat="server" class="ms-ButtonHeightWidth" OnClick="BtnOK_Click" Text="<%$Resources:wss,multipages_okbutton_text%>" id="BtnOKTop" accesskey="<%$Resources:wss,okbutton_accesskey%>"/>
</template_buttons>
</wssuc:buttonsection>
<wssuc:inputformsection title="Existing Azure Active Directory tenants" runat="server">
<wssuc:inputformsection title="Registered Azure Active Directory tenants" runat="server">
<template_description>
<wssawc:EncodedLiteral runat="server" text="Azure AD tenants registered." EncodeMethod='HtmlEncodeAllowSimpleTextFormatting'/>
<wssawc:EncodedLiteral runat="server" text="Azure AD tenants currently registered in AzureCP configuration." EncodeMethod='HtmlEncodeAllowSimpleTextFormatting'/>
</template_description>
<template_inputformcontrols>
<tr><td>
Expand All @@ -143,15 +143,15 @@
</td></tr>
</template_inputformcontrols>
</wssuc:inputformsection>
<wssuc:inputformsection title="New Azure Active Directory tenant" runat="server">
<wssuc:inputformsection title="Register a new Azure Active Directory tenant" runat="server">
<template_description>
<wssawc:EncodedLiteral runat="server" text="<p>A dedicated app must be registered in Azure AD to authorize AzureCP to run queries.<br />Read <a href='https://yvand.github.io/AzureCP/Register-App-In-AAD.html' target='_blank'>this article</a> to see how to do it, then you can enter the information here.<br /><br />AzureCP can authenticate either with a secret or a certificate.</p>" EncodeMethod='NoEncode' />
<wssawc:EncodedLiteral runat="server" text="<p>AzureCP needs its own app registration to connect to your Azure AD tenant, with permissions 'Group.Read.All' and 'User.Read.All'.<br />Check <a href='https://yvand.github.io/AzureCP/Register-App-In-AAD.html' target='_blank'>this page</a> to see how to register it properly.<br /><br />AzureCP can authenticate using <a href='https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow#get-a-token' target='_blank'>either a secret or a certificate</a>.</p>" EncodeMethod='NoEncode' />
</template_description>
<template_inputformcontrols>
<tr><td>
<div id="divNewLdapConnection">
<fieldset>
<legend>Details about new Azure AD tenant</legend>
<legend>Information on the Azure AD tenant to register</legend>
<ul>
<li>
<label for="<%= TxtTenantName.ClientID %>">Tenant name: <em>*</em></label>
Expand Down Expand Up @@ -202,7 +202,7 @@
</td></tr>
</template_inputformcontrols>
</wssuc:inputformsection>
<wssuc:inputformsection runat="server" title="User identifier property" description="Set the properties that identify users in Azure Active Directory.<br/><br/>AzureCP automatically maps those properties with the identity claim type set in the SharePoint TrustedLoginProvider">
<wssuc:inputformsection runat="server" title="User identifier property" description="Set the properties that identify users in Azure Active Directory.<br/>AzureCP automatically maps them to the identity claim type you set in the SPTrustedIdentityTokenIssuer.<br/><br/>Be cautious: Changing it may make existing Azure AD user permissions invalid.">
<template_inputformcontrols>
<div id="divUserIdentifiers">
<label>User identifier for 'Member' users:</label>
Expand All @@ -215,7 +215,7 @@
</div>
</template_inputformcontrols>
</wssuc:inputformsection>
<wssuc:inputformsection runat="server" title="Display of user identifier results" description="Configure how entities created with identity claim type are shown in the people picker.<br/>It does not change the actual value of the entity, that is the user identifier.">
<wssuc:inputformsection runat="server" title="Display of user identifier results" description="Configure how entities created with the identity claim type appear in the people picker.<br/>It does not affect the actual value of the entity, which is always set with the user identifier property.">
<template_inputformcontrols>
<wssawc:InputFormRadioButton id="RbIdentityDefault"
LabelText="Show the user identifier value"
Expand All @@ -237,17 +237,22 @@
</wssawc:InputFormRadioButton>
</template_inputformcontrols>
</wssuc:inputformsection>
<wssuc:inputformsection runat="server" title="Bypass Azure AD lookup" description="Completely bypass Azure AD lookup and consider any input as valid.<br/><br/>This can be useful to keep people picker working even if connectivity with Azure tenant is lost.">
<wssuc:inputformsection runat="server" title="Bypass Azure AD lookup" description="Skip Azure AD lookup and consider any input as valid.<br/><br/>This can be useful to keep people picker working even if connectivity with the Azure tenant is lost.">
<template_inputformcontrols>
<asp:Checkbox Runat="server" Name="ChkAlwaysResolveUserInput" ID="ChkAlwaysResolveUserInput" Text="Bypass Azure AD lookup" />
</template_inputformcontrols>
</wssuc:inputformsection>
<wssuc:inputformsection runat="server" title="Require exact match" description="Set to only return results that exactly match the user input (case-insensitive).">
<wssuc:inputformsection runat="server" title="Require exact match" description="Enable this to return only results that match exactly the user input (case-insensitive).">
<template_inputformcontrols>
<asp:Checkbox Runat="server" Name="ChkFilterExactMatchOnly" ID="ChkFilterExactMatchOnly" Text="Require exact match" />
</template_inputformcontrols>
</wssuc:inputformsection>
<wssuc:inputformsection runat="server" title="Augmentation" description="Enable augmentation to let AzureCP get group membership of Azure AD users.<br/><br/>If not enabled, permissions granted on Azure AD groups may not work.">
<wssuc:inputformsection runat="server" title="Augmentation" >
<template_description>
<wssawc:EncodedLiteral runat="server" text="Enable augmentation to let AzureCP get " EncodeMethod='HtmlEncodeAllowSimpleTextFormatting'/>
<a href="https://docs.microsoft.com/en-us/graph/api/user-getmembergroups" target="_blank"><wssawc:EncodedLiteral runat="server" text="all the Azure AD groups" EncodeMethod='HtmlEncodeAllowSimpleTextFormatting'/></a>
<wssawc:EncodedLiteral runat="server" text="that the user is a member of.<br/><br/>If not enabled, permissions granted to Azure AD groups may not work correctly." EncodeMethod='HtmlEncodeAllowSimpleTextFormatting'/>
</template_description>
<template_inputformcontrols>
<asp:Checkbox Runat="server" Name="ChkAugmentAADRoles" ID="ChkAugmentAADRoles" Text="Retrieve Azure AD groups" />
</template_inputformcontrols>
Expand All @@ -262,7 +267,7 @@
<asp:Checkbox Runat="server" Name="ChkFilterSecurityEnabledGroupsOnly" ID="ChkFilterSecurityEnabledGroupsOnly" Text="Return <a href='https://docs.microsoft.com/en-us/graph/api/resources/groups-overview?view=graph-rest-1.0' target='_blank'>security-enabled</a> groups only" />
</template_inputformcontrols>
</wssuc:inputformsection>
<wssuc:inputformsection runat="server" title="Reset AzureCP configuration" description="Restore configuration to its default values. Every changes, including claim types configuration, will be reset.">
<wssuc:inputformsection runat="server" title="Reset AzureCP configuration" description="Restore configuration to its default values. All changes, including in claim types mappings, will be lost.">
<template_inputformcontrols>
<asp:Button runat="server" ID="BtnResetAzureCPConfig" Text="Reset AzureCP configuration" onclick="BtnResetAzureCPConfig_Click" class="ms-ButtonHeightWidth" OnClientClick="return confirm('Do you really want to reset AzureCP configuration?');" />
</template_inputformcontrols>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ void AddTenantConnection()
Name = this.TxtTenantName.Text,
ApplicationId = this.TxtClientId.Text,
ApplicationSecret = this.TxtClientSecret.Text,
ExcludeMembers = this.ChkMemberUserTypeOnly.Checked,
ExcludeGuests = this.ChkMemberUserTypeOnly.Checked,
ClientCertificatePrivateKey = cert,
CloudInstance = (AzureCloudInstance)Enum.Parse(typeof(AzureCloudInstance), this.DDLAzureCloudInstance.SelectedValue)
});
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Change log for AzureCP

## Unreleased

* Fix bug: No Azure AD group was returned when FilterSecurityEnabledGroupsOnly is set to true - https://github.com/Yvand/AzureCP/issues/109
* Fix bug: Setting "Filter out Guest users" in new AAD teant dialog excludes members instead of guests - https://github.com/Yvand/AzureCP/issues/107
* Add ConfigureAwait(false) to Task.WhenAll()
* Update the text in AzureCP global admin page
* Better handle scenario when AzureCP cannot get an access token for a tenant
* Update NuGet package Microsoft.Graph.3.19.0 -> Microsoft.Graph.3.23.0
* Update NuGet package Microsoft.Identity.Client.4.22.0 -> Microsoft.Identity.Client.4.25.0
* Update NuGet package NUnit.3.12.0 -> Microsoft.Identity.Client.3.13.1

## AzureCP 18.0.20201120.1245 enhancements & bug-fixes - Published in November 24, 2020

* IMPORTANT: due to its dependencies and issues specific to .NET 4.6.1 (and lower) with .NET Standard 2.0, AzureCP 18 requires at least .NET 4.7.2.
Expand Down

0 comments on commit 2f80c4d

Please sign in to comment.