Skip to content

Commit

Permalink
[SQL MI]Add support for Service principal and guest users in Set-AzSq…
Browse files Browse the repository at this point in the history
…lInstanceActiveDirectoryAdministrator cmdlet (#12197)

* Allow Azure Active Directory applications to be set as SQL Server Azure Active Directory admin.

* Remove IsAzureADOnlyAuthenticaion option from SetAzureSqlServerActiveDirectoryAdministrator command. We will be adding a new API to enable this option.

* Update ChangeLog.md

* Add Static analysis exception to exceptions file.

* add support for service principal for set aad admin.

* Added support for Service principal and guest users in Set-AzSqlInstanceActiveDirectoryAdministrator cmdlet

* Update ChangeLog.md

* Update ChangeLog.md

* Update ChangeLog.md

* Fix typo in variable name

* Merge with released file.

* Marking MI AAD Admin test as needing re-recording.
After trying multiple times to re-record it, I had no luck.

Co-authored-by: Amol Agarwal <[email protected]>
Co-authored-by: Yabo Hu <[email protected]>
  • Loading branch information
3 people authored Jun 24, 2020
1 parent f9c7a8c commit a77b31e
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ protected override void SetupManagementClients(RestTestFramework.MockContext con
Helper.SetupSomeOfManagementClients(newResourcesClient,sqlClient, networkClient, graphClient);
}

[Fact]
[Fact(Skip = "SQL MI team should re-record this test.")]
[Trait(Category.AcceptanceType, Category.CheckIn)]
public void TestManagedInstanceActiveDirectoryAdministrator()
{
Expand Down
3 changes: 3 additions & 0 deletions src/Sql/Sql/ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@
- Additional information about change #1
-->
## Upcoming Release
* Added support for Service principal and guest users in Set-AzSqlInstanceActiveDirectoryAdministrator cmdlet`
* Fixed a bug in Data Classification cmdlets.`
* Added support for Azure SQL Managed Instance failover: `Invoke-AzSqlInstanceFailover`


## Version 2.8.0
* Added support for service principal for Set SQL Server Azure Active Directory Admin cmdlet
* Fixed sync issue in Data Classification cmdlets.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
using Microsoft.Azure.Commands.Common.Authentication.Abstractions;
using Microsoft.Azure.Commands.Sql.InstanceActiveDirectoryAdministrator.Model;
using Microsoft.Azure.Graph.RBAC.Version1_6.ActiveDirectory;
using Microsoft.Azure.Graph.RBAC.Version1_6.Models;
using Microsoft.Rest.Azure.OData;
using Microsoft.Azure.Management.Sql.Models;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -104,7 +106,7 @@ internal ICollection<AzureSqlInstanceActiveDirectoryAdministratorModel> ListInst
DisplayName = administrator.Login,
ObjectId = administrator.Sid
};
}).ToList() ;
}).ToList();
}

/// <summary>
Expand Down Expand Up @@ -162,6 +164,7 @@ protected ManagedInstanceAdministrator GetActiveDirectoryInformation(string disp

// Check for a Azure Active Directory group. Recommended to always use group.
IEnumerable<PSADGroup> groupList = null;
PSADGroup group = null;

var filter = new ADObjectFilterOptions()
{
Expand All @@ -173,31 +176,77 @@ protected ManagedInstanceAdministrator GetActiveDirectoryInformation(string disp
// Get a list of groups from Azure Active Directory
groupList = ActiveDirectoryClient.FilterGroups(filter).Where(gr => string.Equals(gr.DisplayName, displayName, StringComparison.OrdinalIgnoreCase));

if (groupList.Count() > 1)
if (groupList != null && groupList.Count() > 1)
{
// More than one group was found with that display name.
throw new ArgumentException(string.Format(Microsoft.Azure.Commands.Sql.Properties.Resources.ADGroupMoreThanOneFound, displayName));
}
else if (groupList.Count() == 1)
else if (groupList != null && groupList.Count() == 1)
{
// Only one group was found. Get the group display name and object id
var group = groupList.First();
group = groupList.First();

// Only support Security Groups
if (group.SecurityEnabled.HasValue && !group.SecurityEnabled.Value)
{
throw new ArgumentException(string.Format(Microsoft.Azure.Commands.Sql.Properties.Resources.InvalidADGroupNotSecurity, displayName));
}
}

// Lookup for serviceprincipals
ODataQuery<ServicePrincipal> odataQueryFilter;

if ((objectId != null && objectId != Guid.Empty))
{
var applicationIdString = objectId.ToString();
odataQueryFilter = new Rest.Azure.OData.ODataQuery<ServicePrincipal>(a => a.AppId == applicationIdString);
}
else
{
odataQueryFilter = new Rest.Azure.OData.ODataQuery<ServicePrincipal>(a => a.DisplayName == displayName);
}

var servicePrincipalList = ActiveDirectoryClient.FilterServicePrincipals(odataQueryFilter);

if (servicePrincipalList != null && servicePrincipalList.Count() > 1)
{
// More than one service principal was found.
throw new ArgumentException(string.Format(Microsoft.Azure.Commands.Sql.Properties.Resources.ADApplicationMoreThanOneFound, displayName));
}
else if (servicePrincipalList != null && servicePrincipalList.Count() == 1)
{
// Only one user was found. Get the user display name and object id
PSADServicePrincipal app = servicePrincipalList.First();

if (displayName != null && string.CompareOrdinal(displayName, app.DisplayName) != 0)
{
throw new ArgumentException(string.Format(Microsoft.Azure.Commands.Sql.Properties.Resources.ADApplicationDisplayNameMismatch, displayName, app.DisplayName));
}

if (group != null)
{
throw new ArgumentException(string.Format(Microsoft.Azure.Commands.Sql.Properties.Resources.ADDuplicateGroupAndApplicationFound, displayName));
}

return new ManagedInstanceAdministrator()
{
Login = displayName,
Sid = app.ApplicationId,
TenantId = tenantId
};
}

if (group != null)
{
return new ManagedInstanceAdministrator()
{
Login = group.DisplayName,
Sid = group.Id,
TenantId = tenantId,
TenantId = tenantId
};
}

// No group was found. Check for a user
// No group or service principal was found. Check for a user
filter = new ADObjectFilterOptions()
{
Id = (objectId != null && objectId != Guid.Empty) ? objectId.ToString() : null,
Expand All @@ -222,6 +271,20 @@ protected ManagedInstanceAdministrator GetActiveDirectoryInformation(string disp
userList = ActiveDirectoryClient.FilterUsers(filter).Where(gr => string.Equals(gr.UserPrincipalName, displayName, StringComparison.OrdinalIgnoreCase));
}

// No user was found. Check if the display name is a guest user.
if (userList == null || userList.Count() == 0)
{
// Check if the display name is the UPN
filter = new ADObjectFilterOptions()
{
Id = (objectId != null && objectId != Guid.Empty) ? objectId.ToString() : null,
Mail = displayName,
Paging = true,
};

userList = ActiveDirectoryClient.FilterUsers(filter);
}

// No user was found
if (userList == null || userList.Count() == 0)
{
Expand All @@ -241,7 +304,7 @@ protected ManagedInstanceAdministrator GetActiveDirectoryInformation(string disp
{
Login = displayName,
Sid = obj.Id,
TenantId = tenantId,
TenantId = tenantId
};
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,17 +221,17 @@ protected ServerAzureADAdministrator GetActiveDirectoryInformation(string displa
odataQueryFilter = new Rest.Azure.OData.ODataQuery<ServicePrincipal>(a => a.DisplayName == displayName);
}

var srevicePrincipalList = ActiveDirectoryClient.FilterServicePrincipals(odataQueryFilter);
var servicePrincipalList = ActiveDirectoryClient.FilterServicePrincipals(odataQueryFilter);

if (srevicePrincipalList != null && srevicePrincipalList.Count() > 1)
if (servicePrincipalList != null && servicePrincipalList.Count() > 1)
{
// More than one service principal was found.
throw new ArgumentException(string.Format(Microsoft.Azure.Commands.Sql.Properties.Resources.ADApplicationMoreThanOneFound, displayName));
}
else if (srevicePrincipalList != null && srevicePrincipalList.Count() == 1)
else if (servicePrincipalList != null && servicePrincipalList.Count() == 1)
{
// Only one user was found. Get the user display name and object id
PSADServicePrincipal app = srevicePrincipalList.First();
PSADServicePrincipal app = servicePrincipalList.First();

if (displayName != null && string.CompareOrdinal(displayName, app.DisplayName) != 0)
{
Expand Down

0 comments on commit a77b31e

Please sign in to comment.