从守护程序创建新的Azure SQL Server

Gno*_*ian 2 c# azure azure-active-directory azure-sql-database

如何使用Azure SDK从守护程序(技术上是队列处理器)在资源组中创建新的Azure SQL Server?我遇到的问题是尝试创建时的授权错误.这是例外:

Hyak.Common.CloudException AuthorizationFailed:对象ID为"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"的客户端"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"无权执行"Microsoft.Sql/servers/write"操作超范围'/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/{myResourceGroupName}/providers/Microsoft.Sql/servers/{newServerName}'.

(实际异常在每个占位符中都有实际值.)

我正在使用Microsoft.Azure.Management.SqlNuGet软件包,版本0.38.0-prerelease(最新版本).

我以前曾试图用来CertificateCloudCredentials进行更改 - 但它产生了以下异常:

Hyak.Common.CloudException AuthenticationFailed:身份验证失败."授权"标题不存在或以无效格式提供.

现在我正在使用TokenCloudCredentials,通过以下方式获得:

AuthenticationContext aContext = new AuthenticationContext(string.Format(
            anApiConfiguration.LoginUriFormat,
            anApiConfiguration.TenantId));
ClientCredential aClientCredential = new ClientCredential(
            anApiConfiguration.ClientId, 
            anApiConfiguration.ClientSecretKey);
AuthenticationResult aTokenResponse = await aContext.AcquireTokenAsync(
            anApiConfiguration.BaseResourceUrl, 
            aClientCredential);
Run Code Online (Sandbox Code Playgroud)

从此我成功获得了一个令牌.然后我使用该令牌如下:

SqlManagementClient sql = new SqlManagementClient(anAuthToken);
ServerCreateOrUpdateProperties someProperties = 
    new ServerCreateOrUpdateProperties {
        AdministratorLogin = someSettings.AdminAccountName,
        AdministratorLoginPassword = someSettings.AdminPassword,
        Version = "12.0"
};
ServerGetResponse aCreateResponse = 
    await sql.Servers.CreateOrUpdateAsync(
        someSettings.GetResourceGroup(aRegionType),
        aServerName, 
        new ServerCreateOrUpdateParameters(someProperties, aRegion));
Run Code Online (Sandbox Code Playgroud)

最后一行,即CreateOrUpdateAsync调用,是在这篇文章的顶部产生异常的原因.

在Azure Active Directory中,客户端应用程序被授予Windows Azure Service Management API应用程序中的Access Azure服务管理(预览)委派权限(该应用程序唯一存在的权限).(如果重要,我还授予客户端应用程序Windows Azure Active Directory应用程序的所有可用权限.)

Ada*_*omm 5

我想我已经弄清楚问题是什么以及如何解决它(我也能在我的工作计算机上重现这个问题).

原因

在示例应用程序中,获取身份验证令牌的默认方法是使用错误的帐户.例如,我的订阅和应用程序位于我的example@outlook.com电子邮件帐户下,但是当我从工作计算机运行控制台应用程序时,应用程序获取username@company.com的令牌并尝试执行该帐户下的操作.看起来获取身份验证令牌的代码是使用来自计算机的一些缓存帐户信息(IE?).

您看到的错误消息与RBAC(基于角色的访问控制)有关,限制经过身份验证但未经授权的帐户对您的资源执行操作(https://azure.microsoft.com/en-us/documentation/articles/role-based- access-control-configure /).

您可以稍微更改一下代码,告诉它在执行操作时使用哪个帐户.将示例应用程序中的"GetAccessTokenUsingUserCredentials"方法更改为如下所示:

    private static AuthenticationResult GetAccessTokenUsingUserCredentials(UserCredential userCredential)
    {
        AuthenticationContext authContext = new AuthenticationContext
            ("https://login.windows.net/" /* AAD URI */
            + "YOU.onmicrosoft.com" /* Tenant ID or AAD domain */);

        AuthenticationResult token = authContext.AcquireToken(
            "https://management.azure.com/"/* the Azure Resource Management endpoint */,
            "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" /* application client ID from AAD*/,
            new Uri("XXXX" /* redirect URI */,
            PromptBehavior.Auto,
            new UserIdentifier(userCredential.UserName, UserIdentifierType.RequiredDisplayableId));

        return token;
    }
Run Code Online (Sandbox Code Playgroud)

并在main函数中更改获取令牌的行:

        var token = GetAccessTokenUsingUserCredentials(new UserCredential("<desired_account_email>"));
Run Code Online (Sandbox Code Playgroud)

您应该能够稍微修改它以获取密码,这样就不会弹出AAD登录框.

我希望这对你有用!

编辑:这是如何让它为Web应用程序工作:

  1. 从Web应用程序的"配置"页面获取您的客户端ID和密钥(您需要选择密钥的持续时间,然后单击"保存"以生成密钥)
  2. 将应用程序中的身份验证代码更改为如下所示:

    private static AuthenticationResult GetAccessTokenForWebApp()
    {
        AuthenticationContext authContext = new AuthenticationContext
            ("https://login.windows.net/" /* AAD URI */
            + "YOU.onmicrosoft.com" /* Tenant ID or AAD domain */);
    
        ClientCredential cc = new ClientCredential("<client_id>", "<key>");
    
        AuthenticationResult token = authContext.AcquireToken(
            "https://management.azure.com/"/* the Azure Resource Management endpoint */,
            cc);
    
        return token;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 此时,如果您尝试运行该应用程序,您将收到如下所示的身份验证错误:

Hyak.Common.CloudException AuthorizationFailed:对象ID为"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"的客户端"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"无权执行"Microsoft.Sql/servers/write"操作超范围'/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/{myResourceGroupName}/providers/Microsoft.Sql/servers/{newServerName}'.

这是因为您需要为应用程序/服务主体添加RBAC角色.从您需要复制"对象ID"的错误消息中,这是将用于角色分配的AD对象ID.

  1. 获取适用于Windows Azure的最新PowerShell cmdlet:http://azure.microsoft.com/en-us/downloads/
  2. 安装PowerShell后,运行以下命令:

    Switch-AzureMode AzureResourceManager #_this will be deprecated soon_
    Add-AzureAccount # you will be prompted for your credentials
    New-AzureRoleAssignment -ObjectId <your_object_id> -RoleDefinitionName <role_name> 
    # You can use "Contributor" to give the web app access to basically everything.
    # You can look in portal.azure.com for the roles that are available
    
    Run Code Online (Sandbox Code Playgroud)
    1. 当上面运行时,您应该看到对象id已添加到角色的输出.

你的网络应用程序现在应该工作!

一些奖金阅读:

对于服务主管/应用程序登录:http://azure.microsoft.com/en-us/documentation/articles/resource-group-authenticate-service-principal/

代表登录:https://msdn.microsoft.com/en-us/library/azure/dn790557.aspx