skip to Main Content

I have an http triggered azure function that starts an orchestrator function. In my dev tenant the code runs without a problem but when deploying to another tenant there has been nothing but trouble, in terms of security settings that affect the azure function.

Right now we are able to call the http trigger when connected to the company network via VPN, and the http triggered function runs without a problem. In the logs we can se that the orchestrator function starts, but immediately fails.

We have tested that we are able to connect to the storage account, and we have tried removing all the code inside the orchestrator besides a log-statement. But it still fails.

Is there some settings in the Azure portal that may have been made that only would affect the orchestrator, and not the Http-triggered function?

[FunctionName(nameof(PlannerOrchestrator))]
public async Task<string> PlannerOrchestrator(
    [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log)
{
    log.LogInformation("Starting orchestration for Planner request");
    return string.Empty;
}
[FunctionName(nameof(PostPlannerTask))]
public async Task<IActionResult> PostPlannerTask(
    [HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequest req,
    [DurableClient] IDurableClient client,
    ILogger log)
{

    log.LogInformation("C# HTTP trigger function processed a request.");
    var incomingAccessToken = req.Headers.TryGetValue("Authorization", out var tokenHeaderValue) ? tokenHeaderValue.FirstOrDefault()?.Replace("Bearer ", string.Empty) : null;

    try
    {
        bool validToken = ValidateToken(incomingAccessToken);
        log.LogInformation("Valid token: {validToken}", validToken);
        if (!validToken)
        {
            return new UnauthorizedResult();
        }
    }
    catch (Exception ex)
    {
        log.LogError("Invalid token: {ex}", ex.Message);
        
        return new BadRequestResult();
    }


    var requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    var plannerRequest = JsonConvert.DeserializeObject<PlannerRequest>(requestBody);

    log.LogInformation("Request received: {request}", requestBody);

    var instanceId = nameof(PlannerOrchestrator) + "-" + Guid.NewGuid();

    instanceId = await client.StartNewAsync(nameof(PlannerOrchestrator), instanceId, plannerRequest);
    log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
    return await client.WaitForCompletionOrCreateCheckStatusResponseAsync(req, instanceId, TimeSpan.FromSeconds(60));
}

2

Answers


  1. Chosen as BEST ANSWER

    Figured out the problem. We had no control over creating the function and we found out that they had set it to .NET8 isolated worker, instead of .NET6 In-process.

    Had to rewrite the code to .NET8 isolated, then it were able to run successfully.


  2. Check the error logs in LogStream=>App Insights Logs:

    enter image description here

    Use the below query to check the error logs related to Durable function as mentioned in MSDOC:

    let orchestrationInstanceID = "XXXXXX"; 
    let start = datetime(XXXX-XX-XXTXX:XX:XX); 
    traces  
    | where timestamp > start and timestamp < start + 1h
    | extend instanceId = iif(isnull(customDimensions["prop__InstanceId"] ) , customDimensions["prop__instanceId"], customDimensions["prop__InstanceId"] ) 
    | extend logLevel = customDimensions["LogLevel"]
    | extend functionName = customDimensions["prop__functionName"]
    | extend status = customDimensions["prop__status"]
    | extend details = customDimensions["prop__Details"] 
    | extend reason = customDimensions["prop__reason"]
    | where severityLevel > 1 // to see all logs of  severity level "Information" or greater.
    | where instanceId == orchestrationInstanceID
    | sort by timestamp asc
    

    I have deployed your code to Azure function app and able to run the function as expected.

    Code Snippet:

    public static async Task<IActionResult> PostPlannerTask(
    [HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequest req,
    [DurableClient] IDurableClient client,
    ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");
            var incomingAccessToken = req.Headers.TryGetValue("Authorization", out var tokenHeaderValue) ? tokenHeaderValue.FirstOrDefault()?.Replace("Bearer ", string.Empty) : null;
    
            try
            {
                bool validToken = ValidateToken(incomingAccessToken);
                log.LogInformation("Valid token: {validToken}", validToken);
                if (!validToken)
                {
                    return new UnauthorizedResult();
                }
            }
            catch (Exception ex)
            {
                log.LogError("Invalid token: {ex}", ex.Message);
    
                return new BadRequestResult();
            }
            var requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            var plannerRequest = JsonConvert.DeserializeObject<PlannerRequest>(requestBody);
    
            log.LogInformation("Request received: {request}", requestBody);
    
            var instanceId = nameof(Function1) + "-" + Guid.NewGuid();
    
            instanceId = await client.StartNewAsync(nameof(Function1), instanceId, plannerRequest);
            log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
            return await client.WaitForCompletionOrCreateCheckStatusResponseAsync(req, instanceId, TimeSpan.FromSeconds(60));
        }
        private static bool ValidateToken(string token)
        {
            return !string.IsNullOrEmpty(token);
        }
    

    Durable function:

    [FunctionName("Function1")]
    public static async Task<List<string>> RunOrchestrator(
        [OrchestrationTrigger] IDurableOrchestrationContext context)
    {
        var outputs = new List<string>();
        outputs.Add(await context.CallActivityAsync<string>(nameof(SayHello), "Tokyo"));
        outputs.Add(await context.CallActivityAsync<string>(nameof(SayHello), "Seattle"));
        outputs.Add(await context.CallActivityAsync<string>(nameof(SayHello), "London"));
        return outputs;
    }
    
    [FunctionName(nameof(SayHello))]
    public static string SayHello([ActivityTrigger] string name, ILogger log)
    {
        log.LogInformation("Saying hello to {name}.", name);
        return $"Hello {name}!";
    }
    
    [FunctionName("Function1_HttpStart")]
    public static async Task<HttpResponseMessage> HttpStart(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestMessage req,
        [DurableClient] IDurableOrchestrationClient starter,
        ILogger log)
    {
        string instanceId = await starter.StartNewAsync("Function1", null);
    
        log.LogInformation("Started orchestration with ID = '{instanceId}'.", instanceId);
    
        return starter.CreateCheckStatusResponse(req, instanceId);
    }
    

    Deployed to Azure function App.

    Portal:

    enter image description here

    Provide Bearer token in Auth section while running the function:

    enter image description here

    Response:

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search