2

在 Azure 门户中注册应用程序时,我们的团队希望使用应用程序清单中定义的应用程序角色。这是我们的 TestApp 清单中的一个示例。

  "appRoles": [
  { "allowedMemberTypes": [
      "User",
      "Application"],
    "displayName": "My App Role 2",
    "id": "0993b354-6b2f-471d-bba2-f7467a1bbbf2",
    "isEnabled": true,
    "description": "My App Role description for MyAppRole2",
    "value": "MyAppRole2" },
  { "allowedMemberTypes": [
      "User" ],
    "displayName": "My App Role 1",
    "id": "0993b354-6b2f-471d-bba2-f7467a1baaf2",
    "isEnabled": true,
    "description": "My App Role description for MyAppRole1",
    "value": "MyAppRole1" }]

这些应用程序角色在 Web 应用程序中显示为角色声明,允许开发人员通过如下所示装饰端点来控制对端点的访问。

[Authorize (Roles = "MyAppRole2")]
public class AdministrationController : Controller
{
}

通过 Azure 门户(在企业应用程序下),我们可以将用户和/或组分配给特定应用程序的角色,并且一切正常。但是,当尝试直接访问数据库(从 SSMS)时,应用程序角色的成员资格不起作用。

CREATE USER [TestApp] FROM EXTERNAL PROVIDER
CREATE ROLE [MyAppRole2] AUTHORIZATION [TestApp1]

我们也试过

CREATE ROLE [My App Role 2] AUTHORIZATION [TestApp1]

在任何一种情况下,在数据库级别检查成员身份都会返回“0”假。

SELECT IS_MEMBER('MyAppRole2') [My App Role 2]

但是,如果我们创建一个 AAD 组(例如'My Group For TestApp My App Role 2'),通过 Enterprise Apps 接口将'My App Role 2' 角色分配给组,并通过 AAD 用户将用户分配到组和组接口...我们可以通过在 SQL 中使用组来查看组的成员资格。

下面创建 Azure SQL 和 AAD 中的组安全主体之间的关系。

CREATE USER [My Group For TestApp My App Role 2] FROM EXTERNAL PROVIDER

任何在该组中直接登录 SQL 的用户都将显示为该组的成员。对于同时也是 AAD 组成员的经过身份验证的 SSMS 用户,以下返回 true。

SELECT IS_MEMBER('My Group For TestApp My App Role 2')

虽然这可行,但如果我们从组中删除应用程序角色(在 Azure 企业应用程序下),上述查询仍然返回 true。这是因为即使该组不再有权访问应用程序角色,用户仍然是该组的有效成员。因此,这种变通方法无效,因为数据库实际上并未验证用户是否参与了应用程序角色。

我们如何将应用程序角色直接关联到数据库角色以确保适当的安全性?

4

1 回答 1

0

根据我的理解,您将 Azure AD 应用程序中定义的应用程序角色与 SQL Server中的应用程序角色混合在一起。

如果要使用角色管理 Azure AD 服务主体。我们可以使用以下命令创建数据库角色并将该角色分配给 Azure AD 中创建的服务主体:

CREATE ROLE customRole2

alter role customRole2 add member FeiTestApp
--FeiTestApp is the service principal in Azure AD
EXECUTE AS USER = 'FeiTestApp';  

SELECT IS_MEMBER('customRole2')
REVERT;

该命令应该返回1,然后我们也可以使用访问令牌来检查结果,如下所示:

SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
builder["Data Source"] = "xxxx.database.windows.net"; // replace with your server name
builder["Initial Catalog"] = "DBTest"; // replace with your database name
builder["Connect Timeout"] = 30;

string authority = "https://login.microsoftonline.com/{0}";
string tenantId = "microsoft.onmicrosoft.com";
string clientId = "";
string secrect = "";
string resourceId = "https://database.windows.net/";
AuthenticationContext authContext = new AuthenticationContext(string.Format(authority,tenantId));
var accessToken=  authContext.AcquireTokenAsync(resourceId, new ClientCredential(clientId, secrect)).Result.AccessToken;

using (SqlConnection connection = new SqlConnection(builder.ConnectionString))
{
    try
    {
        connection.AccessToken = accessToken;
        connection.Open();         
        SqlCommand cmd = new SqlCommand("SELECT IS_MEMBER('customRole2')", connection);

        var reader = cmd.ExecuteReader();
        while (reader.Read())
        {
            Console.WriteLine($"{reader[0]}");              
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}

有关 Azure SQL 数据库角色管理的更多详细信息,您可以参考以下文档:

校长(数据库引擎)

于 2017-03-08T09:49:10.270 回答