I am trying to restrict access to an ASP.NET Core 8 Web API using host filtering so that only an Azure Function app can call the API.
I created a simple API using Visual Studio 2022 that uses the simple out of the box WeatherForecast API setup to use host filtering with no other custom code. The AllowedHosts
entry in the appsettings.json
file is set to testhostingrestrctionsfunction8.azurewebsites.net
, which is the URL of the Azure Function app that I setup to access the API.
I added code to configure the host filtering and to use it. I deployed that code to an Azure web app.
Here is the code that I am using:
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Configure the Host Filtering Service.
var allowedHosts = builder.Configuration["AllowedHosts"];
if (allowedHosts?.Length > 0)
{
var allowedHostLIst = new List<string>() { allowedHosts };
builder.Services.AddHostFiltering(options =>
{
options.AllowedHosts = allowedHostLIst;
});
}
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
// Use Host Filtering
app.UseHostFiltering();
app.MapControllers();
app.Run();
}
}
I created a simple .NET 8 Azure Function app in Visual Studio 2022 that was setup to use a Service Bus Trigger with very simple code to make a GET
call to the WeatherForecast
route of the API using a HttpClient
to the web address: https://testhostingrestrctionsapi8.azurewebsites.net/WeatherForecast
.
I deployed that function app to Azure with this code:
public class TestHostingRestrctionsFunction8
{
private readonly ILogger<TestHostingRestrctionsFunction8> _logger;
public TestHostingRestrctionsFunction8(ILogger<TestHostingRestrctionsFunction8> logger)
{
_logger = logger;
}
[Function(nameof(TestHostingRestrctionsFunction8))]
public async Task Run(
[ServiceBusTrigger("testmessages", Connection = "TestMessages")]
ServiceBusReceivedMessage message,
ServiceBusMessageActions messageActions)
{
try
{
_logger.LogInformation("Message ID: {id}", message.MessageId);
_logger.LogInformation("Message Body: {body}", message.Body);
_logger.LogInformation("Message Content-Type: {contentType}", message.ContentType);
// Complete the message
await messageActions.CompleteMessageAsync(message);
string? apiRootUrl = "https://testhostingrestrctionsapi8.azurewebsites.net/";
string? route = "WeatherForecast";
string fetchUrl = apiRootUrl + route;
_logger.LogInformation("fetchUrl: {fetchUrl}", fetchUrl);
string responseBody;
using (var fetchStatusClient = new HttpClient())
{
fetchStatusClient.Timeout = TimeSpan.FromMinutes(10);
fetchStatusClient.DefaultRequestHeaders.Accept.Clear();
fetchStatusClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
responseBody = await fetchStatusClient.GetStringAsync(fetchUrl);
}
_logger.LogInformation("responseBody: {responseBody}", responseBody);
}
catch (Exception ex)
{
_logger.LogError("An error occurred: {error}", ex.ToString());
throw;
}
}
}
When I send a message to the function app, the function app receives the message, completes the message, and then throws the following 400 Bad Request error indicating that the function app cannot access the API:
2024-08-01T19:47:21Z [Information] Executing 'Functions.TestHostingRestrctionsFunction8' (Reason='(null)', Id=9310bb6a-820a-4532-aad0-a544df5d55bb)
2024-08-01T19:47:21Z [Information] Trigger Details: MessageId: 02778db8b8b6402f9bfaaec670fdc940, SequenceNumber: 18, DeliveryCount: 1, EnqueuedTimeUtc: 2024-08-01T19:47:21.0000000+00:00, LockedUntilUtc: 2024-08-01T19:48:21.0150000+00:00, SessionId: (null)
2024-08-01T19:47:21Z [Information] Message ID: 02778db8b8b6402f9bfaaec670fdc940
2024-08-01T19:47:21Z [Information] Message Body: messsage
2024-08-01T19:47:21Z [Information] Message Content-Type: (null)
2024-08-01T19:47:21Z [Information] Start processing HTTP request POST http://127.0.0.1:50100/Settlement/Complete
2024-08-01T19:47:21Z [Information] Sending HTTP request POST http://127.0.0.1:50100/Settlement/Complete
2024-08-01T19:47:21Z [Information] Received HTTP response headers after 32.8808ms - 200
2024-08-01T19:47:21Z [Information] End processing HTTP request after 33.3395ms - 200
2024-08-01T19:47:21Z [Information] fetchUrl: https://testhostingrestrctionsapi8.azurewebsites.net/WeatherForecast
2024-08-01T19:47:21Z [Error] An error occurrred: System.Net.Http.HttpRequestException: Response status code does not indicate success: 400 (Bad Request).
at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode()
at System.Net.Http.HttpClient.GetStringAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
at TestHostingRestrctionsFunction8.TestHostingRestrctionsFunction8.Run(ServiceBusReceivedMessage message, ServiceBusMessageActions messageActions) in D:a1sTestHostingRestrctionsFunction8TestHostingRestrctionsFunction8.cs:line 45
2024-08-01T19:47:21Z [Error] Function 'TestHostingRestrctionsFunction8', Invocation id '9310bb6a-820a-4532-aad0-a544df5d55bb': An exception was thrown by the invocation.
2024-08-01T19:47:21Z [Error] Executed 'Functions.TestHostingRestrctionsFunction8' (Failed, Id=9310bb6a-820a-4532-aad0-a544df5d55bb, Duration=107ms)
What I tried:
Step 1: Before I added any code to implement the Use Host Filtering options in the API, I deployed both the API and Azure Function app, and made sure that the function app could call the API without the Host Filtering options. This worked.
Step 2: I then tried to implement the Host Filtering by adding only testhostingrestrctionsfunction8.azurewebsites.net
to the AllowedHosts
entry in the appsettings.json
file, which did not work.
I also tried replacing the AllowedHosts
value with https://TestHostingRestrctionsFunction8ServiceBus.servicebus.windows.net
and https://TestHostingRestrctionsFunction8ServiceBus.servicebus.windows.net/
one at a time on separate attempts, which also failed.
Step 3: I then setup the configuration for a service for Host Filtering in the Program
class of the API, which also failed.
Step 4: I then setup the app.UseHostFiltering();
call in the Program
class of the API. I tried this with the configuration setup mentioned in the last step and with no configuration setup for the service at all. This also failed.
Result
All of the attempts from steps 2-4 resulted in 400 error that I have included, which is what the API is supposed to return when a host is not allowed to contact the API.
This is supposed to be a simple way to setup host Filtering from what I have read, but none of my attempts have worked.
0