Add support for AAD contained users in SQL DB (#2005)

This commit is contained in:
Karl Burtram
2023-04-14 17:02:00 -07:00
committed by GitHub
parent 13672c1d05
commit 4614795f19
2 changed files with 48 additions and 9 deletions

View File

@@ -120,20 +120,21 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
User existingUser = dataContainer.Server.Databases[parentDb.Name].Users[parameters.Name]; User existingUser = dataContainer.Server.Databases[parentDb.Name].Users[parameters.Name];
userType = UserActions.GetCurrentUserTypeForExistingUser(existingUser); userType = UserActions.GetCurrentUserTypeForExistingUser(existingUser);
DatabaseUserType databaseUserType = UserActions.GetDatabaseUserTypeForUserType(userType); DatabaseUserType databaseUserType = UserActions.GetDatabaseUserTypeForUserType(userType);
// if contained user determine if SQL or AAD auth type
ServerAuthenticationType authenticationType =
(databaseUserType == DatabaseUserType.Contained && userType == ExhaustiveUserTypes.ExternalUser)
? ServerAuthenticationType.AzureActiveDirectory : ServerAuthenticationType.Sql;
userInfo = new UserInfo() userInfo = new UserInfo()
{ {
Type = databaseUserType, Type = databaseUserType,
AuthenticationType = authenticationType,
Name = parameters.Name, Name = parameters.Name,
LoginName = existingUser.Login, LoginName = existingUser.Login,
DefaultSchema = existingUser.DefaultSchema, DefaultSchema = existingUser.DefaultSchema,
}; };
// update the authentication type for contained users
if (databaseUserType == DatabaseUserType.Contained)
{
userInfo.AuthenticationType = ServerAuthenticationType.Sql;
}
// Default language is only applicable for users inside a contained database. // Default language is only applicable for users inside a contained database.
if (LanguageUtils.IsDefaultLanguageSupported(dataContainer.Server) if (LanguageUtils.IsDefaultLanguageSupported(dataContainer.Server)
&& parentDb.ContainmentType != ContainmentType.None) && parentDb.ContainmentType != ContainmentType.None)
@@ -222,7 +223,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
}, },
SupportContainedUser = supportsContainedUser, SupportContainedUser = supportsContainedUser,
SupportWindowsAuthentication = false, SupportWindowsAuthentication = false,
SupportAADAuthentication = false, SupportAADAuthentication = currentUserPrototype.AADAuthSupported,
SupportSQLAuthentication = true, SupportSQLAuthentication = true,
Languages = languageOptionsList.ToArray(), Languages = languageOptionsList.ToArray(),
Schemas = currentUserPrototype.SchemaNames.ToArray(), Schemas = currentUserPrototype.SchemaNames.ToArray(),
@@ -490,7 +491,14 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
userType = ExhaustiveUserTypes.WindowsUser; userType = ExhaustiveUserTypes.WindowsUser;
break; break;
case DatabaseUserType.Contained: case DatabaseUserType.Contained:
userType = ExhaustiveUserTypes.SqlUserWithPassword; if (user.AuthenticationType == ServerAuthenticationType.AzureActiveDirectory)
{
userType = ExhaustiveUserTypes.ExternalUser;
}
else
{
userType = ExhaustiveUserTypes.SqlUserWithPassword;
}
break; break;
case DatabaseUserType.NoConnectAccess: case DatabaseUserType.NoConnectAccess:
userType = ExhaustiveUserTypes.SqlUserWithoutLogin; userType = ExhaustiveUserTypes.SqlUserWithoutLogin;
@@ -516,6 +524,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
case ExhaustiveUserTypes.SqlUserWithoutLogin: case ExhaustiveUserTypes.SqlUserWithoutLogin:
databaseUserType = DatabaseUserType.NoConnectAccess; databaseUserType = DatabaseUserType.NoConnectAccess;
break; break;
case ExhaustiveUserTypes.ExternalUser:
databaseUserType = DatabaseUserType.Contained;
break;
} }
return databaseUserType; return databaseUserType;
} }
@@ -548,6 +559,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
return ExhaustiveUserTypes.CertificateMappedUser; return ExhaustiveUserTypes.CertificateMappedUser;
case UserType.AsymmetricKey: case UserType.AsymmetricKey:
return ExhaustiveUserTypes.AsymmetricKeyMappedUser; return ExhaustiveUserTypes.AsymmetricKeyMappedUser;
case UserType.External:
return ExhaustiveUserTypes.ExternalUser;
default: default:
return ExhaustiveUserTypes.Unknown; return ExhaustiveUserTypes.Unknown;
} }

View File

@@ -146,6 +146,12 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
case DatabaseUserType.NoConnectAccess: case DatabaseUserType.NoConnectAccess:
userType = UserType.NoLogin; userType = UserType.NoLogin;
break; break;
case DatabaseUserType.Contained:
if (userInfo.AuthenticationType == ServerAuthenticationType.AzureActiveDirectory)
{
userType = UserType.External;
}
break;
// all the other user types are using SqlLogin // all the other user types are using SqlLogin
} }
return userType; return userType;
@@ -361,6 +367,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
private List<string> roleNames; private List<string> roleNames;
private bool exists = false; private bool exists = false;
private Database parent; private Database parent;
private CDataContainer context;
public bool IsRoleMembershipChangesApplied { get; set; } //default is false public bool IsRoleMembershipChangesApplied { get; set; } //default is false
public bool IsSchemaOwnershipChangesApplied { get; set; } //default is false public bool IsSchemaOwnershipChangesApplied { get; set; } //default is false
@@ -494,6 +501,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
this.currentState = current; this.currentState = current;
this.originalState = original; this.originalState = original;
this.exists = !context.IsNewObject; this.exists = !context.IsNewObject;
this.context = context;
Database? parent = context.Server.GetSmoObject(new Urn(context.ParentUrn)) as Database ?? throw new ArgumentException("Context ParentUrn is invalid"); Database? parent = context.Server.GetSmoObject(new Urn(context.ParentUrn)) as Database ?? throw new ArgumentException("Context ParentUrn is invalid");
this.parent = parent; this.parent = parent;
@@ -691,6 +699,22 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
return result; return result;
} }
public bool AADAuthSupported
{
get
{
return context?.Server?.ServerType == DatabaseEngineType.SqlAzureDatabase;
}
}
public bool WindowsAuthSupported
{
get
{
return context?.Server?.ServerType != DatabaseEngineType.SqlAzureDatabase;
}
}
} }
internal class UserPrototypeWithDefaultSchema : UserPrototype, internal class UserPrototypeWithDefaultSchema : UserPrototype,
@@ -1029,6 +1053,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
break; break;
case ExhaustiveUserTypes.SqlUserWithoutLogin: case ExhaustiveUserTypes.SqlUserWithoutLogin:
case ExhaustiveUserTypes.ExternalUser:
currentPrototype ??= new UserPrototypeWithDefaultSchema(context, currentData, originalData); currentPrototype ??= new UserPrototypeWithDefaultSchema(context, currentData, originalData);
break; break;
@@ -1060,6 +1085,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
WindowsUser, WindowsUser,
LoginMappedUser, LoginMappedUser,
CertificateMappedUser, CertificateMappedUser,
AsymmetricKeyMappedUser AsymmetricKeyMappedUser,
ExternalUser,
}; };
} }