Example #1
0
        public static SitePublishProfile GetPublishProperties(string subscriptionId, string siteName, string tenantId, string applicationId, string password)
        {
            var token = ServicePrincipal.GetAuthorizationToken(tenantId, applicationId, password);

            using (var resourcesClient = new ResourceManagementClient(new TokenCloudCredentials(subscriptionId, token)))
                using (var webSiteClient = new WebSiteManagementClient(new TokenCredentials(token))
                {
                    SubscriptionId = subscriptionId
                })
                {
                    // Because we only know the site name, we need to search the ResourceGroups to find it
                    var resourceGroups = resourcesClient.ResourceGroups.List(new ResourceGroupListParameters()).ResourceGroups.Select(rg => rg.Name).ToList();

                    foreach (var resourceGroup in resourceGroups)
                    {
                        var sites        = webSiteClient.Sites.GetSites(resourceGroup, null, null, true).Value;
                        var matchingSite = sites.FirstOrDefault(x => x.Name.Equals(siteName, StringComparison.OrdinalIgnoreCase));

                        if (matchingSite == null)
                        {
                            continue;
                        }

                        // Once we know the Resource Group, we have to POST a request to the URI below to retrieve the publishing credentials
                        var publishSettingsUri = new Uri(resourcesClient.BaseUri,
                                                         $"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.Web/sites/{matchingSite.Name}/config/publishingCredentialz/list?api-version=2015-08-01");
                        Log.Verbose($"Retrieving publishing profile from {publishSettingsUri}");

                        SitePublishProfile publishProperties = null;
                        var request = new HttpRequestMessage {
                            Method = HttpMethod.Post, RequestUri = publishSettingsUri
                        };
                        // Add the authentication headers
                        var requestTask = resourcesClient.Credentials.ProcessHttpRequestAsync(request, new CancellationToken())
                                          .ContinueWith(authResult => resourcesClient.HttpClient.SendAsync(request), TaskContinuationOptions.NotOnFaulted)
                                          .ContinueWith(publishSettingsResponse =>
                        {
                            var result = publishSettingsResponse.Result.Result;

                            if (!result.IsSuccessStatusCode)
                            {
                                Log.Error($"Retrieving publishing credentials failed. Publish-settings URI: {publishSettingsUri}");
                                throw new Exception($"Retrieving publishing credentials failed with HTTP status {(int)result.StatusCode} - {result.ReasonPhrase}");
                            }

                            dynamic response       = JObject.Parse(result.Content.AsString());
                            string publishUserName = response.properties.publishingUserName;
                            string publishPassword = response.properties.publishingPassword;
                            string scmUri          = response.properties.scmUri;
                            Log.Verbose($"Retrieved publishing profile. URI: {scmUri}  UserName: {publishUserName}");
                            publishProperties = new SitePublishProfile(publishUserName, publishPassword, new Uri(scmUri));
                        }, TaskContinuationOptions.NotOnFaulted);

                        requestTask.Wait();
                        return(publishProperties);
                    }

                    throw new CommandException($"Could not find Azure WebSite '{siteName}' in subscription '{subscriptionId}'");
                }
        }
        public static SitePublishProfile GetPublishProperties(string subscriptionId, string resourceGroupName, AzureTargetSite azureTargetSite, string tenantId, string applicationId, string password, string resourceManagementEndpoint, string activeDirectoryEndPoint)
        {
            var token   = ServicePrincipal.GetAuthorizationToken(tenantId, applicationId, password, resourceManagementEndpoint, activeDirectoryEndPoint);
            var baseUri = new Uri(resourceManagementEndpoint);

            using (var resourcesClient = new ResourceManagementClient(new TokenCredentials(token))
            {
                SubscriptionId = subscriptionId,
                BaseUri = baseUri,
            })
                using (var webSiteClient = new WebSiteManagementClient(new Uri(resourceManagementEndpoint), new TokenCredentials(token))
                {
                    SubscriptionId = subscriptionId
                })
                {
                    resourcesClient.HttpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
                    resourcesClient.HttpClient.BaseAddress = baseUri;

                    Log.Verbose($"Looking up site {azureTargetSite.Site} in resourceGroup {resourceGroupName}");

                    var sites = webSiteClient.WebApps.List();
                    if (sites.Any())
                    {
                        Log.Verbose("Found sites:");
                        foreach (var site in sites)
                        {
                            Log.Verbose($"{site.ResourceGroup} / {site.Name}");
                        }
                    }

                    var matchingSites = sites
                                        .Where(webApp => string.Equals(webApp.Name, azureTargetSite.Site, StringComparison.CurrentCultureIgnoreCase) &&
                                               (string.IsNullOrWhiteSpace(resourceGroupName) || string.Equals(webApp.ResourceGroup, resourceGroupName, StringComparison.InvariantCultureIgnoreCase)))
                                        .ToList();

                    if (!matchingSites.Any())
                    {
                        var resourceGroupMessage = !string.IsNullOrWhiteSpace(resourceGroupName)
                        ? $" in resource group '{resourceGroupName}' and"
                        : " in";
                        throw new CommandException($"Could not find Azure WebSite '{azureTargetSite.Site}'{resourceGroupMessage} subscription '{subscriptionId}'");
                    }

                    // if more than one site, fail
                    if (matchingSites.Count > 1)
                    {
                        throw new CommandException(
                                  $"Found {matchingSites.Count} matching the site name '{azureTargetSite.Site}' in subscription '{subscriptionId}'.{(string.IsNullOrWhiteSpace(resourceGroupName) ? " Please supply a Resource Group name." : string.Empty)}");
                    }

                    var matchingSite = matchingSites.Single();
                    resourceGroupName = matchingSite.ResourceGroup;

                    // ARM resource ID of the source app. App resource ID is of the form:
                    //  - /subscriptions/{subId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{siteName} for production slots and
                    //  - /subscriptions/{subId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{siteName}/slots/{slotName} for other slots.

                    // We allow the slot to be defined on both the target directly (which will come through on the matchingSite.Name) or on the
                    // step for backwards compatibility with older Azure steps.
                    var siteAndSlotPath = matchingSite.Name;
                    if (azureTargetSite.HasSlot)
                    {
                        Log.Verbose($"Using the deployment slot {azureTargetSite.Slot}");
                        siteAndSlotPath = $"{matchingSite.Name}/slots/{azureTargetSite.Slot}";
                    }

                    // Once we know the Resource Group, we have to POST a request to the URI below to retrieve the publishing credentials
                    var publishSettingsUri = new Uri(resourcesClient.BaseUri,
                                                     $"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{siteAndSlotPath}/config/publishingCredentials/list?api-version=2016-08-01");
                    Log.Verbose($"Retrieving publishing profile from {publishSettingsUri}");

                    SitePublishProfile publishProperties = null;
                    var request = new HttpRequestMessage {
                        Method = HttpMethod.Post, RequestUri = publishSettingsUri
                    };
                    // Add the authentication headers
                    var requestTask = resourcesClient.Credentials.ProcessHttpRequestAsync(request, new CancellationToken())
                                      .ContinueWith(authResult => resourcesClient.HttpClient.SendAsync(request), TaskContinuationOptions.NotOnFaulted)
                                      .ContinueWith(publishSettingsResponse =>
                    {
                        var result = publishSettingsResponse.Result.Result;
                        if (!result.IsSuccessStatusCode)
                        {
                            Log.Error($"Retrieving publishing credentials failed. Publish-settings URI: {publishSettingsUri}");
                            throw new Exception($"Retrieving publishing credentials failed with HTTP status {(int)result.StatusCode} - {result.ReasonPhrase}");
                        }

                        dynamic response       = JObject.Parse(result.Content.AsString());
                        string publishUserName = response.properties.publishingUserName;
                        string publishPassword = response.properties.publishingPassword;
                        string scmUri          = response.properties.scmUri;
                        Log.Verbose($"Retrieved publishing profile. URI: {scmUri}  UserName: {publishUserName}");
                        publishProperties = new SitePublishProfile(publishUserName, publishPassword, new Uri(scmUri));
                    }, TaskContinuationOptions.NotOnFaulted);

                    requestTask.Wait();
                    return(publishProperties);
                }
        }
        public static SitePublishProfile GetPublishProperties(AzureServicePrincipalAccount account, string resourceGroupName, AzureTargetSite azureTargetSite)
        {
            if (account.ResourceManagementEndpointBaseUri != DefaultVariables.ResourceManagementEndpoint)
            {
                Log.Info("Using override for resource management endpoint - {0}", account.ResourceManagementEndpointBaseUri);
            }

            if (account.ActiveDirectoryEndpointBaseUri != DefaultVariables.ActiveDirectoryEndpoint)
            {
                Log.Info("Using override for Azure Active Directory endpoint - {0}", account.ActiveDirectoryEndpointBaseUri);
            }

            var token   = ServicePrincipal.GetAuthorizationToken(account.TenantId, account.ClientId, account.Password, account.ResourceManagementEndpointBaseUri, account.ActiveDirectoryEndpointBaseUri);
            var baseUri = new Uri(account.ResourceManagementEndpointBaseUri);

            using (var resourcesClient = new ResourceManagementClient(new TokenCredentials(token))
            {
                SubscriptionId = account.SubscriptionNumber,
                BaseUri = baseUri,
            })
                using (var webSiteClient = new WebSiteManagementClient(new Uri(account.ResourceManagementEndpointBaseUri), new TokenCredentials(token))
                {
                    SubscriptionId = account.SubscriptionNumber
                })
                {
                    webSiteClient.SetRetryPolicy(new Microsoft.Rest.TransientFaultHandling.RetryPolicy(new HttpStatusCodeErrorDetectionStrategy(), 3));
                    resourcesClient.HttpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
                    resourcesClient.HttpClient.BaseAddress = baseUri;

                    Log.Verbose($"Looking up site {azureTargetSite.Site} {(string.IsNullOrWhiteSpace(resourceGroupName) ? string.Empty : $"in resourceGroup {resourceGroupName}")}");

                    Site matchingSite;
                    if (string.IsNullOrWhiteSpace(resourceGroupName))
                    {
                        matchingSite      = FindSiteByNameWithRetry(account, azureTargetSite, webSiteClient) ?? throw new CommandException(GetSiteNotFoundExceptionMessage(account, azureTargetSite));
                        resourceGroupName = matchingSite.ResourceGroup;
                    }
                    else
                    {
                        var site = webSiteClient.WebApps.Get(resourceGroupName, azureTargetSite.Site);
                        Log.Verbose("Found site:");
                        LogSite(site);

                        matchingSite = site ?? throw new CommandException(GetSiteNotFoundExceptionMessage(account, azureTargetSite, resourceGroupName));
                    }

                    // ARM resource ID of the source app. App resource ID is of the form:
                    //  - /subscriptions/{subId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{siteName} for production slots and
                    //  - /subscriptions/{subId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{siteName}/slots/{slotName} for other slots.

                    // We allow the slot to be defined on both the target directly (which will come through on the matchingSite.Name) or on the
                    // step for backwards compatibility with older Azure steps.

                    var siteAndSlotPath = matchingSite.Name;
                    if (azureTargetSite.HasSlot)
                    {
                        Log.Verbose($"Using the deployment slot {azureTargetSite.Slot}");
                        siteAndSlotPath = $"{matchingSite.Name}/slots/{azureTargetSite.Slot}";
                    }

                    // Once we know the Resource Group, we have to POST a request to the URI below to retrieve the publishing credentials
                    var publishSettingsUri = new Uri(resourcesClient.BaseUri,
                                                     $"/subscriptions/{account.SubscriptionNumber}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{siteAndSlotPath}/config/publishingCredentials/list?api-version=2016-08-01");
                    Log.Verbose($"Retrieving publishing profile from {publishSettingsUri}");

                    SitePublishProfile publishProperties = null;
                    var request = new HttpRequestMessage {
                        Method = HttpMethod.Post, RequestUri = publishSettingsUri
                    };
                    // Add the authentication headers
                    var requestTask = resourcesClient.Credentials.ProcessHttpRequestAsync(request, new CancellationToken())
                                      .ContinueWith(authResult => resourcesClient.HttpClient.SendAsync(request), TaskContinuationOptions.NotOnFaulted)
                                      .ContinueWith(publishSettingsResponse =>
                    {
                        var result = publishSettingsResponse.Result.Result;
                        if (!result.IsSuccessStatusCode)
                        {
                            Log.Error($"Retrieving publishing credentials failed. Publish-settings URI: {publishSettingsUri}");
                            throw new Exception($"Retrieving publishing credentials failed with HTTP status {(int)result.StatusCode} - {result.ReasonPhrase}");
                        }

                        dynamic response       = JObject.Parse(result.Content.AsString());
                        string publishUserName = response.properties.publishingUserName;
                        string publishPassword = response.properties.publishingPassword;
                        string scmUri          = response.properties.scmUri;
                        Log.Verbose($"Retrieved publishing profile. URI: {scmUri}  UserName: {publishUserName}");
                        publishProperties = new SitePublishProfile(publishUserName, publishPassword, new Uri(scmUri));
                    }, TaskContinuationOptions.NotOnFaulted);

                    requestTask.Wait();

                    return(publishProperties);
                }