C# 从守护进程创建新的Azure SQL Server

C# 从守护进程创建新的Azure SQL Server,c#,azure,azure-sql-database,azure-active-directory,C#,Azure,Azure Sql Database,Azure Active Directory,如何使用Azure SDK从守护进程(技术上是队列处理器)在资源组中创建新的Azure SQL Server?我遇到的问题是在尝试创建时出现授权错误。例外情况如下: Hyak.Common.CloudException授权失败:对象id为“XXXXXXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXXXXXX-XXXXXXXXXXXX”的客户端“XXXXXXXX-XXXX-XXXX-XXXXXXXX-XXXXXXXXXXXXXXXX-XXXXXXXXXXXXXXXX”无权执行操作“

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

Hyak.Common.CloudException授权失败:对象id为“XXXXXXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXXXXXX-XXXXXXXXXXXX”的客户端“XXXXXXXX-XXXX-XXXX-XXXXXXXX-XXXXXXXXXXXXXXXX-XXXXXXXXXXXXXXXX”无权执行操作“Microsoft.Sql/servers/write'over scope'/subscriptions/XXXXXXXXXXXXXXXXXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/resourceGroups/{myResourceGroupName}”/providers/Microsoft.Sql/servers/{newServerName}

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

我使用的是
Microsoft.Azure.Management.Sql
NuGet软件包,版本为0.38.0-prerelease(当前最新版本)

我以前曾尝试使用
CertificateCloudCredentials
进行更改,但出现了以下异常:

Hyak.Common.CloudException身份验证失败:身份验证失败。“授权”标头不存在或提供的格式无效

现在我使用的是
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);
由此我成功地获得了一个令牌。然后,我使用该令牌,如下所示:

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));
最后一行,
CreateOrUpdateAsync
调用就是本文顶部产生异常的地方


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

我编写了一个控制台应用程序来测试各种场景。虽然我需要尝试更多的案例,但目前我实施的案例中只有两个成功:

  • 具有ClientId\u RedirectUri\u PromptBehavior的NativeClient客户端
  • 具有ClientId\u RedirectUri\u PromptBehavior\u UserIdentifier的NativeClientApp
如果您感兴趣,源代码如下。另外,我现在只测试资源组的创建,因为这比创建Sql Server实例要简单得多。两者似乎产生相同的错误

初步结果 结果输出显示案例、结果和继续的线索

WebApp with ClientCertificate
The method or operation is not implemented.
Press any key to continue.

WebApp with ClientAssertion
The method or operation is not implemented.
Press any key to continue.

WebApp with ClientCredential
AuthorizationFailed: The client '7a31a564-20ba-4ac1-a2ee-4f5e35a70dcc' with object id '7a31a564-20ba-4ac1-a2ee-4f5e35a70dcc' does not have authorization to perform action 'Microsoft.Resources/subscriptions/resourcegroups/write' ov
er scope '/subscriptions/14929cfc-3501-48cf-a5c9-b24a7daaf694/resourcegroups/MY_RESOURCE_GROUP_NAME635776010237527878'.
Press any key to continue.

WebApp with ClientId_UserAssertion
The method or operation is not implemented.
Press any key to continue.

WebApp with ClientCredential_UserAssertion
AADSTS50027: Invalid JWT token. AADSTS50027: Invalid JWT token. Token format not valid.
Trace ID: a64f0683-23ae-4461-8546-55293f7ff1d3
Correlation ID: 62cc80e9-f013-4a74-8031-3294e69d4478
Timestamp: 2015-09-12 03:43:57Z
Press any key to continue.

WebApp with ClientAssertion_UserAssertion
The method or operation is not implemented.
Press any key to continue.

WebApp with ClientCertificate_UserAssertion
The method or operation is not implemented.
Press any key to continue.

WebApp with ClientId_RedirectUri
The method or operation is not implemented.
Press any key to continue.

WebApp with ClientId_UserCredential
missing_federation_metadata_url: Federation Metadata Url is missing for federated user. This user type is unsupported.
Press any key to continue.

WebApp with ClientId_RedirectUri_PromptBehavior
AADSTS90014: The request body must contain the following parameter: 'client_secret or client_assertion'.
Trace ID: 06fde160-bd2b-4f16-b49e-0f0ff8e17f48
Correlation ID: baabb83f-cebb-48ba-b2be-1efb53ec3121
Timestamp: 2015-09-12 03:44:21Z
Press any key to continue.

WebApp with ClientId_RedirectUri_PromptBehavior_UserIdentifier
AADSTS90014: The request body must contain the following parameter: 'client_secret or client_assertion'.
Trace ID: 6110ef02-a6b0-4e41-b0e5-db97b13c66ce
Correlation ID: e6f6526a-8395-480a-8ac7-b75903b324d9
Timestamp: 2015-09-12 03:44:30Z
Press any key to continue.

WebApp with ClientId_RedirectUri_PromptBehavior_UserIdentifier_ExtraQueryParams
The method or operation is not implemented.
Press any key to continue.

NativeClientApp with ClientCertificate
The method or operation is not implemented.
Press any key to continue.

NativeClientApp with ClientAssertion
The method or operation is not implemented.
Press any key to continue.

NativeClientApp with ClientCredential
Value cannot be null.
Parameter name: clientSecret
Press any key to continue.

NativeClientApp with ClientId_UserAssertion
The method or operation is not implemented.
Press any key to continue.

NativeClientApp with ClientCredential_UserAssertion
Value cannot be null.
Parameter name: clientSecret
Press any key to continue.

NativeClientApp with ClientAssertion_UserAssertion
The method or operation is not implemented.
Press any key to continue.

NativeClientApp with ClientCertificate_UserAssertion
The method or operation is not implemented.
Press any key to continue.

NativeClientApp with ClientId_RedirectUri
The method or operation is not implemented.
Press any key to continue.

NativeClientApp with ClientId_UserCredential
missing_federation_metadata_url: Federation Metadata Url is missing for federated user. This user type is unsupported.
Press any key to continue.

NativeClientApp with ClientId_RedirectUri_PromptBehavior
Success! Created MY_RESOURCE_GROUP_NAME635776011040240760
Press any key to continue.

NativeClientApp with ClientId_RedirectUri_PromptBehavior_UserIdentifier
Success! Created MY_RESOURCE_GROUP_NAME635776011079693849
Press any key to continue.

NativeClientApp with ClientId_RedirectUri_PromptBehavior_UserIdentifier_ExtraQueryParams
The method or operation is not implemented.
Press any key to continue.

Testing complete.:)
Program.cs packages.config
我想我已经找到了问题所在以及解决方法(我还能够在我的工作电脑上重现这个问题)

原因

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

您看到的错误消息与RBAC(基于角色的访问控制)有关,RBAC限制经过身份验证但未经授权的帐户对您的资源执行操作()

解决方案

您可以稍微更改代码,告诉它在执行操作时使用哪个帐户。将示例应用中的“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;
    }
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;
}
在main函数中,将获取令牌的行更改为:

        var token = GetAccessTokenUsingUserCredentials(new UserCredential("<desired_account_email>"));
var-token=GetAccessTokenUsingUserCredentials(新用户凭证(“”);
您应该能够对其进行一些修改,以同时输入密码,这样AAD登录框就不会弹出

我希望这对你有用

编辑:以下是如何使其在Web应用程序中工作:
  • 从web应用的“配置”页面获取客户端ID和密钥(您需要选择密钥的持续时间,然后单击“保存”以生成密钥)
  • 将应用程序中的身份验证代码更改为如下所示:

        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;
        }
    
    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;
    }
    
    私有静态身份验证结果GetAccessTokenForWebApp()
    {
    AuthenticationContext authContext=新建AuthenticationContext
    ("https://login.windows.net/“/*AAD URI*/
    +“YOU.onmicrosoft.com”/*租户ID或AAD域*/);
    ClientCredential cc=新的ClientCredential(“,”);
    AuthenticationResult令牌=authContext.AcquireToken(
    "https://management.azure.com/“/*Azure资源管理终结点*/,
    cc);
    返回令牌;
    }
    
  • 此时,如果您尝试运行该应用程序,将出现如下身份验证错误:
  • Hyak.Common.CloudException授权失败:对象id为“XXXXXXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXXXXXX-XXXXXXXXXXXX”的客户端“XXXXXXXX-XXXX-XXXX-XXXXXXXX-XXXXXXXXXXXXXXXX-XXXXXXXXXXXXXXXX”无权执行操作“Microsoft.Sql/servers/write'over scope'/subscriptions/XXXXXXXXXXXXXXXXXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/resourceGroups/{myResourceGroupName}”/providers/Microsoft.Sql/servers/{newServerName}

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

  • 获取适用于Windows Azure的最新powershell cmdlet:
  • 安装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
    
    切换AzureMode AzureResourceManager\u这将很快被弃用_
    添加AzureAccount#系统将提示您输入凭据
    新AzureRoleAssignment-ObjectId-RoleDefinitionName
    #您可以使用“Contributor”让web应用程序访问基本上所有内容。
    #您可以在portal.azure.com中查找可用的角色
    
  • 当以上运行时,您应该会看到ou