如何以编程方式管理客户的基于使用情况的订阅?

时间:2016-07-26 12:36:33

标签: azure azure-active-directory

首先我要描述一个“手动”场景。我作为合作伙伴登录合作伙伴中心并转到客户列表(https://partnercenter.microsoft.com/en-us/pcv/customers/list)。对于任何客户,可以使用All resources (Azure portal)链接在Azure门户中管理其所有基于使用情况的订阅:

enter image description here

特别是,我可以为订阅添加共同管理员(即添加角色为Owner的用户):

enter image description here

如何自动管理客户的订阅?

我的努力:我有一些CREST API和RBAC API的经验。这是docs中描述的Azure Active Directory(AAD)应用程序的限制:

  

您只能在订阅中为相同目录中的应用程序授予对订阅资源的访问权限。

由于每个客户的订阅都存在于单独的客户AAD中,因此RBAC API似乎无法提供帮助:

  1. 它需要一个基于AAD应用程序的令牌(即基于TenantIdClientIdClientSecret),没有办法 以编程方式在客户的目录中创建AAD应用程序。

  2. 位于合作伙伴的AAD中的应用无法访问 客户的订阅。

  3. 是否有任何方式以编程方式将admin / co-admin / owner添加到客户的订阅中?

1 个答案:

答案 0 :(得分:0)

Patrick Liang help在MSDN论坛上,最后我提出了一个解决方案:为合作伙伴的AAD应用启用Pre-consent功能,以授予客户订阅权限。让我来形容一下:

<强> 1。 Partner Center Explorer项目

https://github.com/Microsoft/Partner-Center-Explorer/

这是一个类似于partnercenter.microsoft.com的Web应用程序,它是各种Microsoft API使用的一个很好的例子。最重要的是,这个项目是从合作伙伴AAD app访问客户订阅的完整示例。但是,它建议用户交互(OAuth对login.live.com作为合作伙伴进行身份验证),并且在尝试避免它时遇到了一些问题。下面我将介绍如何使用代码中已有的所有凭据连接到客户的订阅。

<强> 2。合作伙伴AAD应用

创建原生 AAD应用而不是网络AAD应用,但以相同的方式配置其“对其他应用的权限”。 跳过不适用于原生应用的步骤(例如,跳过client_secret获取并跳过清单更新)。

第3。 PowerShell脚本

应用配置的最后一步是运行此脚本:

Connect-MsolService
$g = Get-MsolGroup | ? {$_.DisplayName -eq 'AdminAgents'} 
$s = Get-MsolServicePrincipal | ? {$_.AppPrincipalId -eq 'INSERT-CLIENT-ID-HERE'}
Add-MsolGroupMember -GroupObjectId $g.ObjectId -GroupMemberType ServicePrincipal -GroupMemberObjectId $s.ObjectId

需要安装几个模块来执行这些命令。如果在“Microsoft专业人员的Microsoft Online Services登录助手”安装过程中出现错误,请尝试安装BETA模块:

Microsoft Online Services Sign-In Assistant for IT Professionals BETA

你可能需要这个:

Microsoft Online Services Module for Windows PowerShell 64-bit

<强> 4。代码

最后,我们准备进行身份验证并create a role assignment

public async void AssignRoleAsync()
{
    var token = await GetTokenAsync();

    var response = await AssignRoleAsync(token.AccessToken);
}

public async Task<AuthenticationResult> GetTokenAsync()
{
    var authContext = new AuthenticationContext($"https://login.windows.net/{CustomerId}");

    return await authContext.AcquireTokenAsync(
        "https://management.core.windows.net/"
        , ApplicationId
        , new UserCredential(PartnerUserName, PartnerPassword));
}


public async Task<HttpResponseMessage> AssignRoleAsync(string accessToken)
{
    string newAssignmentId = Guid.NewGuid().ToString();
    string subSegment = $"subscriptions/{CustomerSubscriptionId}/providers/Microsoft.Authorization";
    string requestUri = $"https://management.azure.com/{subSegment}/roleAssignments/{newAssignmentId}?api-version=2015-07-01";
    string roleDefinitionId = "INSERT_ROLE_GUID_HERE";

    using (var client = new HttpClient())
    {
        client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);

        var body = new AssignRoleRequestBody();
        body.properties.principalId = UserToAssignId;
        body.properties.roleDefinitionId = $"/{subSegment}/roleDefinitions/{roleDefinitionId}";

        var httpRequest = HttpHelper.CreateJsonRequest(body, HttpMethod.Put, requestUri);

        return await client.SendAsync(httpRequest);
    }
}

要获取角色定义ID,只需向每个订阅范围get all roles发出请求。

有用的链接:

MSDN: How to manage customer's usage-based subscription programmatically?

MSDN: When will auto-stamping/implicit consent be available for CREST customers?

Managing Role-Based Access Control with the REST API