Figure 1: Azure File Copy task configured in a vNext build
The nice part is the Azure Subscription setting that allows you to choose one of the Azure endpoints configured for the project. Using service endpoints, you can ask the person that has passwords/keys for an Azure Account to configure an endpoint. Once it is configured it can be used by team members with sufficient right to access it, without requiring them to know the password or token or anything else.
Thanks to Services Endpoints, you can allow members of the team to create builds that can interact with Azure Accounts without giving them any password or token
If you look around you'll find a nice blog post that explains how to connect your VSTS account using a service principal.
Figure 2: Configure a service endpoint for Azure with Service Principal Authentication
Another really interesting aspect of Service Endpoints, is the ability to choose people that can administer the account and people that can use the endpoint, thus giving you full security control over who can do what.
Figure 3: You can manage security for each Service Endpoint configured
Finally, using Service Endpoint, you have a centralized way to manage accessing your Azure Subscription Resources, if for some reason a subscription should be removed and not used anymore, you can simply remove the endpoint. This is a better approach than having data and passwords or tokens scattered all over the VSTS account (builds, etc).
I’ve followed all the steps in the article to connect your VSTS account using a service principal, but when it was time to execute the Azure File Copy action, I got a strange error.
Executing the powershell script: C:\LR\MMS\Services\Mms\TaskAgentProvisioner\Tools\agents\default\tasks\AzureFileCopy\1.0.25\AzureFileCopy.ps1 Looking for Azure PowerShell module at C:\Program Files (x86)\Microsoft SDKs\Azure\PowerShell\ServiceManagement\Azure\Azure.psd1 AzurePSCmdletsVersion= 0.9.8.1 Get-ServiceEndpoint -Name 75a5dd41-27eb-493a-a4fb-xxxxxxxxxxxx -Context Microsoft.TeamFoundation.DistributedTask.Agent.Worker.Common.TaskContext tenantId= ******** azureSubscriptionId= xxxxxxxx-xxxxxxx-xxxx-xxxx-xxxxxxxxxx azureSubscriptionName= MSDN Principal Add-AzureAccount -ServicePrincipal -Tenant $tenantId -Credential $psCredential There is no subscription associated with account ********. Select-AzureSubscription -SubscriptionId xxxxxxxx-xxxxxxx-xxxx-xxxx-xxxxxxxxxx The subscription id xxxxxxxx-xxxxxxx-xxxx-xxxx-xxxxxxxxxx doesn't exist. Parameter name: id The Switch-AzureMode cmdlet is deprecated and will be removed in a future release. The Switch-AzureMode cmdlet is deprecated and will be removed in a future release. Storage account: portalvhdsxxxxxxxxxxxxxxxxx1 not found. Please specify existing storage account
This error is really strange because the first error line told me:
The subscription id xxxxxx-xxxxxx-xxxxxx-xxxxxxxxxxxxx doesn’t exist.
This cannot be the real error, because I’m really sure that my Azure Subscription is active and it is working everywere else. Thanks to the help of Roopesh Nair, I was able to find my mistake. It turns out that the Storage Account I’m trying to access is an old one created with Azure Classic Mode, and it is not accessible with Service Principal. A Service Endpoint using Service Principal can manage only Azure Resource Manager-based entities.
Shame on me because I was aware of this limitation, but for some reason I completely forgot it this time.
Another sign of the problem is the error line telling me: Storage account xxxxxxxxx not found, that should ring a warning bell about the script not being able to find that specific resource, because it was created with classic mode.
The solution is simple, I could use Blob Storage created with Azure Resource Manager, or I can configure another Service Endpoint, this time based on a management certificate. The second option is preferrable, because having two Service Endpoints, one configured with Service Principal and the other configured with Certificate allows me to manage all types of Azure Resources.
Configuring an endpoint with a certificate is really simple. You should only copy data from the management certificate inside the Endpoint Configuration and you are ready to go.
Figure 4: Configure a certificate-based endpoint
Now my build task's Azure File Copy works as expected and I can choose the right Service Endpoint based on what type of resource I should access (Classic or ARM).