Kurkula
Kurkula

Reputation: 6762

Calling WebApi from Azure function securely

I have a scenario where I have asp.net core web api and a azure function. I call web api from azure time triggered function for every 1 hour. I do not have authentication enabled on the web api and I do not want public to access it. Only my azure function should be able to access the web api. How can I restrict web api to access from public but only from azure function with out implementing authentication.

I tried the below, In webapi appsettings file, I updated "AllowedHosts":"https://testfuntionapp.azurewebsites.net". My testfuntionapp is unable to access web api with this change.

I am trying for a cost effective solution.

Upvotes: 1

Views: 1975

Answers (4)

Steve Tses
Steve Tses

Reputation: 19

The fastest and "dirtiest" way to do this, is to pass an API key as a header to your REST API from the function.

You can hardcode the API key to your config file or load it from your DB.

My implementation:

namespace CoreApi.Middleware
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class RequirePartnerApiKeyAttribute : Attribute, IAsyncActionFilter
    {
        private const string ApiKeyHeaderName = "x-partner-apikey";

        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            //----------------------------------------------------
            // Validate Api Key
            //----------------------------------------------------
            if (!context.HttpContext.Request.Headers.TryGetValue(ApiKeyHeaderName, out var apiKey) ||
                string.IsNullOrEmpty(apiKey))
            {
                context.Result = new UnauthorizedResult();
                return;
            }

            var partnerService = context.HttpContext.RequestServices.GetRequiredService<IPartnerService>();
            var apiRequest = new PartnerAuthenticateRequest { PartnerApiKey = apiKey };
            var partner = partnerService.Authenticate(apiRequest, new CancellationToken()).Result;
            if (partner == null)
            {
                context.Result = new UnauthorizedResult();
                return;
            }
            else
            {
                if (Enum.IsDefined(typeof(ApiKeyTypes), partner.PartnerName))
                    context.HttpContext.Items["APIKeyName"] = Enum.Parse(typeof(ApiKeyTypes), partner.PartnerName);
            }
            //----------------------------------------------------

            await next();
        }
    }
}

You can access the API key from any middleware by calling: context.HttpContext.Items["APIKeyName"]

Upvotes: 1

Carter McKay
Carter McKay

Reputation: 490

If you only want your Azure function to be able to access your web API, you can restrict access to your web API by IP address.

In your web API's appsettings.json file, add the following:

"AllowedHosts": "https://testfuntionapp.azurewebsites.net"

This will restrict access to your web API to only requests coming from the specified Azure function.

Upvotes: 1

Alex
Alex

Reputation: 18526

I would also recommend private endpoints as suggested by HariKrishnaRajoli.

In theory it would also suffice to just configure http header filtering for access restriction rules and only allow requests containing a secret header known only to your azure function code. This is probably comparable to "basic" HTTP authentication security, and weaker than the other options.

As an alternative, you can use AAD authentication without really "implementing" much authentication code.

  1. Configure Easy Auth on the WebApi
  2. Configure ManagedIdentity for your Azure Function
  3. Give your the Managed Identity access to call the WebApi using "App Role Assignments"
  4. Extend your Azure Function to acquire and pass access token when calling the WebApi

Upvotes: 2

anon
anon

Reputation:

Please check if my findings help to:

How can I restrict web api to access from public but only from azure function without implementing authentication.

This is where the Azure Virtual Networks comes to.

Create the Virtual Network, configure the Azure Function to only be callable on this VNet and also can configure your core app access to the VNet.

  • By using Private Endpoints, resources are accessible only via your Virtual Network.
  • If Virtual Network Integration enabled, then the Azure Function is able to access the designated resource via the configured private endpoints, which is a higher level of security.

References:

Upvotes: 4

Related Questions