Skip to content

Commit

Permalink
Switch logstream command to use Bearer token when basic auth is not a…
Browse files Browse the repository at this point in the history
…llowed. (#3342)
  • Loading branch information
khkh-ms authored Apr 28, 2023
1 parent fd56265 commit 8878ab9
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 3 deletions.
24 changes: 21 additions & 3 deletions src/Azure.Functions.Cli/Actions/AzureActions/LogStreamAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,29 @@ public override async Task RunAsync()
throw new CliException("Log stream is not currently supported in Linux Consumption Apps. " +
"Please use --browser to open Azure Application Insights Live Stream in the Azure portal.");
}
var basicHeaderValue = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{functionApp.PublishingUserName}:{functionApp.PublishingPassword}"));


using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", basicHeaderValue);
var isBasicAuthAllowed = true;
try
{
isBasicAuthAllowed = await AzureHelper.IsBasicAuthAllowedForSCM(functionApp, AccessToken, ManagementURL);
}
catch (Exception)
{
// ignore: We don't want to fail the command on basic auth check. There is extremely low likelihood of getting the exception here.
}

if (isBasicAuthAllowed)
{
var basicHeaderValue = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{functionApp.PublishingUserName}:{functionApp.PublishingPassword}"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", basicHeaderValue);
}
else
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken);
}

client.DefaultRequestHeaders.Add("User-Agent", Constants.CliUserAgent);
var response = await client.GetStreamAsync(new Uri($"https://{functionApp.ScmUri}/api/logstream/application"));
using (var reader = new StreamReader(response))
Expand Down
1 change: 1 addition & 0 deletions src/Azure.Functions.Cli/Arm/ArmUriTemplates.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ internal static class ArmUriTemplates
public const string WebsitesApiVersion = "2015-08-01";
public const string SyncTriggersApiVersion = "2016-08-01";
public const string ArgApiVersion = "2019-04-01";
public const string BasicAuthCheckApiVersion = "2022-03-01";

public const string ArgUri = "providers/Microsoft.ResourceGraph/resources";

Expand Down
34 changes: 34 additions & 0 deletions src/Azure.Functions.Cli/Arm/Models/BasicAuthCheckResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static NuGet.Client.ManagedCodeConventions;

namespace Azure.Functions.Cli.Arm.Models
{
class BasicAuthCheckResponse
{
[JsonProperty(PropertyName = "id")]
public string Id { get; set; }

[JsonProperty(PropertyName = "name")]
public string ResourceName { get; set; }

[JsonProperty(PropertyName = "type")]
public string ResourceType { get; set; }

[JsonProperty(PropertyName = "location")]
public string Location { get; set; }

[JsonProperty(PropertyName = "properties")]
public BasicAuthCheckResponseProperties Properties { get; set; }
}

class BasicAuthCheckResponseProperties
{
[JsonProperty(PropertyName = "allow")]
public bool Allow { get; set; }
}
}
13 changes: 13 additions & 0 deletions src/Azure.Functions.Cli/Helpers/AzureHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,19 @@ internal static async Task<string> GetResourceIDFromArg(IEnumerable<string> subI
?? throw new CliException("Error finding the Azure Resource information.");
}

internal static async Task<bool> IsBasicAuthAllowedForSCM(Site functionApp, string accessToken, string managementURL)
{
var url = new Uri($"{managementURL}{functionApp.SiteId}/basicPublishingCredentialsPolicies/scm?api-version={ArmUriTemplates.BasicAuthCheckApiVersion}");

var response = await ArmClient.HttpInvoke(HttpMethod.Get, url, accessToken);
response.EnsureSuccessStatusCode();

var result = await response.Content.ReadAsStringAsync();
var basicAuthResponse = JsonConvert.DeserializeObject<BasicAuthCheckResponse>(result);

return basicAuthResponse.Properties.Allow;
}

internal static ArmResourceId ParseResourceId(string resourceId)
{
if (string.IsNullOrEmpty(resourceId))
Expand Down

0 comments on commit 8878ab9

Please sign in to comment.