DisclaimerFor the time being, the automated provisioning of Azure Active Directory Applications only targets B2E kind of applications. It is not tackling B2C nor B2B (multi-tenant) apps. The custom Visual Studio Team Services task in a nutshellIn a nutshell, this task was created to automatically provision Azure Active Directory Applications that allow business applications to authorize users and APIs using OAuth2/OpenID. Instead of doing this job manually for each and every business application, it is possible to automate most of these steps as part of the release life cycle. However, in order to remain compliant with most enterprise policies, the provisioned apps remain under the control of the identity and access management team that has to provide the Admin Consent to the deployed apps. Admin Consent is mandatory for all apps that require application permissions while it is optional in some other cases. However, non-consented apps will prompt users as of the first use, which can be annoying with internal employees as internally developed applications should be considered trusted by default. Since the consent part is beyond the scope of this task, feel free to handle it your own way. Release Notesv1.0
v1.0.1
v1.0.2 & 1.0.3
v1.0.4
v1.0.5
Setup prerequisitesThis documentation assumes that you have no Visual Studio Team Services endpoint configured yet. If you already have some and if you know Visual Studio Team Services, feel free to adjust your existing endpoints with the information provided below. Creation of the Azure Active Directory Application.Once you have enabled this extension into your Visual Studio Team Services account, you have to create an Azure Active Directory Application that will be used by the task in order to authenticate against your directory. You must grant it the following application permission: over your Azure Active Directory tenant. Make sure to create an application secret and to copy its value for later use. This will give the task the right of registering applications while not being able to interfere with other apps. Depending on the level of trust between application teams and operation teams within your organization, one may also grant the Read and Write directory data permission, which is required to use the User & Group assignment. Unfortunately, this cannot be restricted to your apps only. Therefore, if the identity & access management team wants to remain fully in control and has a low risk appetite, you should not grant this permission. The counterpart is that the second task (user and group assignment) will not work without this. The task will use the ClientCredentials flow to connect to Azure Active Directory. You may consider the registration of this App somehow similar to a regular VSTS Service Endpoint. Note that if you already have endpoints registered, you could simply reuse one of the existing Azure Active Directory Applications and give it the above permission. Granting Contributor Role via Role-Based Access Control aka RBACThe task is will be using the Azure Active Directory Application created in the previous step while connecting to Azure Active Directory and will also be using the RBAC "Key Vault Contributor Role" (more on this below): In the select textbox, you should enter the application identifier of the app you created. Creation of the Key VaultAll the application identifier and secrets will be sent to Azure Key Vault by the task. Therefore, you must have a vault and grant the contributor access policy to the Azure Active Directory Application created earlier as shown by the below screenshot: Creation of a Service AccountWhen using Access Tokens together with Azure Active Directory V2 PowerShell cmdlets, an account name must be provided to the Connect-AzureAD cmdlet. Therefore, the easiest is to create a service account that is simply a member of the directory. Creation of the VSTS Service EndpointNow that the Azure Active Directory Application has all the required permissions, it is time to register it inside of Visual Studio Team Services by creating a new Service Endpoint.
Recommended actionsSince the task is supposed to be used across release definitions, it is easier to setup a Variable Group in Visual Studio Team Services where you define the task parameters. These can be overriden at task level should it vary from time to time. While this step is optional, I strongly recommend you to do it. Here is a screenshot of the Variable Group: Note that I blurred some values for privacy reasons but here is what these variables stand for:
If you do not create this Variable Group, you'll have to define these values at task level. Using the custom Visual Studio Team Services taskVSTS AgentYou should use the Hosted 2017 agent. In case you use on-premises agent, I recommend creating a separate Agent Phase using the Hosted 2017 agent. If you do so, feel free to tick the option labelled "Skip download of artifacts". Configuring the taskSome of the task parameters directly come from the Variable Group created earlier, which means that you must bind this Variable Group to your release definition. They are pre-configured with variable names. You do not need to change anything if you created the Variable Group as explained earlier. ⋅⋅⋅The task shipps with multiple templates that are intended to cover typical topologies. For instance, when having a mobile app connecting to an Azure-hosted API, your work will only consist in providing the right reply & identifer URLs. Since the input field exposed by the task is merely a textbox, you should use a true JSON editor to configure that part of the task. Note that every template is usable "as is" but of course, you should adapt them to your own situation (replyUrls, identifiers etc.). If you are not too sure about how to configure the task, you can test each of the template against a sandbox subscription and look the results in the Azure Portal. Here is an example of a custom API that exposes custom application and delegate permissions, and its related web client. Here are some explanations of the above screenshot:
The outcome of the above config is that the following Azure Active Directory Applications are registered: and the web client will be granted the following permissions: With 1 delegate permission over Azure Active Directory as well as 1 delegate + 1 application permission over the custom API. The application identifier of the webapi as well as the application identifier+secret of the web client will be pushed to Key Vault as shown below: Requesting access to other resourcesWhen configuring the task, if your API or your client app needs access to another resource, you must input the resource identifier such as "https://graph.windows.net" and the name of the role or scope, such as "User.Read". Here is a recap of the role & scope names for both the Azure AD Graph and the Microsoft Graph API. This will be handy for most of your configurations: Azure AD Graph delegate permissions
Azure AD Graph application permissions
Microsoft Graph delegate permissions
Microsoft Graph application permissions
DependenciesAs you noticed, there is a dependency with the Variable Group but there is more. If you use the MSIEnabledRelatedWebAppName attribute, it assumes that you have deployed the corresponding app with MSI enabled in a previous task, as part of the current release. Similarly, the task pushes some information into Key Vault which needs to be fetched by an App Service. Therefore, it is a good practice to define the name of the keyvault secrets as specific release variables that you can reuse across the different tasks of the current release (this task accepts variable names in the JSON template). If you do not use MSI, you still need to push the secret names to the Azure App Service. This can be done through ARM templates. Here is an example of such a sequence within the same release: where the first task is an ARM template that deploys an App Service with MSI enabled and with the corresponding Key Vault secret names: |