Skip to content

Managed identity SQL auth problems (schema creation, new instance events) #166

Open
@andsj073

Description

@andsj073

Hello

The issue

I continuously fail to get the dt schema created in DFX provider SQL Database when using a Managed Identity (either User Assigned or System Assigned) in the SQL_DB_Connection string of the Function App during first run.

The only error message given, when using Mgd Identity, in Logs is:
Could not find stored procedure 'dt.CreateInstance'.

Creation works fine if I use the more basic SQL Server auth with user id and password.

But then, once the schema is in place, and back to using the Mgd Identity for auth to SQL, the created instance/event (by StartNewAsync) does not trigger Durable Orchestration execution, even though a row is created in NewEvents.

The environment

Using a clean install of Azure SQL Database on SQL Server with Elastic pool Standard DTU
and running the VS Code generated "SayHello" durable function on ASP Elastic Premium.

The Mgd Identity of the Function App is added to SQL Server Users executing (as AAD authenticated admin)

CREATE USER "name" FROM EXTERNAL PROVIDER;
ALTER ROLE db_owner ADD MEMBER "name";

Both rows returns successfully and the User is been verified by inspected using SSMS.
No RBAC roles are assigned to the Managed Identity.

Connection string to SQL Database in app settings of Function:

    "name": "SQLDB_Connection",
    "value": "Server=tcp:{redacted name}.database.windows.net,1433;Initial Catalog=DurableDB;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;Authentication=Active Directory Managed Identity;User Id={redacted client id}",

The {redacted client id} is meticulously verified to be the client id of the Managed Identity in portal

The host.json contains

  "extensions": {
    "durableTask": {
      "storageProvider": {
        "type": "mssql",
        "connectionStringName": "SQLDB_Connection",
        "taskEventLockTimeout": "00:02:00",
        "createDatabaseIfNotExists": true
      }
    }
  }

There is no VNet integration, no private endpoints or service endpoints etc. The Function App can positively access the Database through firewall rules. The durable function execution triggered by HTTP returns 500.

Additional information and behavior

Again, everything works fine if I change to connection string in app settings to:

    "name": "SQLDB_Connection",
    "value": "Server=tcp:{redacted name}.database.windows.net,1433;Initial Catalog=DurableDB;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;User ID={redacted username};Password={redacted pwd}",

The the dt Schema is created and the Durable Function executes normally, and rows in TaskHub are created, ending up in RuntimeStatus Completed, with rows in History and Payloads.

However, to add to this for understanding, if I now switch back to the same User Assigned Managed Identity (switching connection string again), then the Durable Function starts execution and creates rows in the dt.NewEvents and dt.Instances table (with RuntimeStatus=Pending), but nothing else (no Payloads and no History) and the Function execution never completes (stuck in RuntimeStatus Pending).

Row in NewEvents

SequenceNumber	Timestamp	VisibleTime	DequeueCount	TaskHub	InstanceID	ExecutionID	EventType	RuntimeStatus	Name	TaskID	PayloadID
5	2023-04-28 07:38:42.2877671	NULL	0	{redacted mgd id name}	9e6aecbbc0994102acfedf869b61623f	8a41f23e32d747eaa90e23ffbec115d7	ExecutionStarted	Pending	DurableFunctionsOrchestrationCSharp1	NULL	NULL

Row in Instances

TaskHub	InstanceID	ExecutionID	Name	Version	CreatedTime	LastUpdatedTime	CompletedTime	RuntimeStatus	LockedBy	LockExpiration	InputPayloadID	OutputPayloadID	CustomStatusPayloadID	ParentInstanceID
{redacted mgd id name}	9e6aecbbc0994102acfedf869b61623f	8a41f23e32d747eaa90e23ffbec115d7	DurableFunctionsOrchestrationCSharp1		2023-04-28 07:38:42.2877671	NULL	NULL	Pending	NULL	NULL	NULL	NULL	NULL	NULL

For this run, no errors can be observed in Logs / Application Insight for the instance. Only successful execution information of the run.

Hence the following method is successfully executed (see logs below) and the DurableFunctionsOrchestrationCSharp1 (Orchestrator) is scheduled (Executed stored procedure dt.CreateInstance in 11ms), but the consecutive execution of DurableFunctionsOrchestrationCSharp1 never happens. No apparent errors.

        [FunctionName("DurableFunctionsOrchestrationCSharp1_HttpStart")]
        public static async Task<HttpResponseMessage> HttpStart(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestMessage req,
            [DurableClient] IDurableOrchestrationClient starter,
            ILogger log)
        {
            // Function input comes from the request content.
            string instanceId = await starter.StartNewAsync("DurableFunctionsOrchestrationCSharp1", null);

            log.LogInformation("Started orchestration with ID = '{instanceId}'.", instanceId);

            return starter.CreateCheckStatusResponse(req, instanceId);
        }

        [FunctionName("DurableFunctionsOrchestrationCSharp1")]
        public static async Task<List<string>> RunOrchestrator(
            [OrchestrationTrigger] IDurableOrchestrationContext context)
        {
            var outputs = new List<string>();

            // Replace "hello" with the name of your Durable Activity Function.
            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"));

            // returns ["Hello Tokyo!", "Hello Seattle!", "Hello 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}!";
        }

The Function NuGets

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <AzureFunctionsVersion>v4</AzureFunctionsVersion>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.DurableTask" Version="2.9.4" />
    <PackageReference Include="Microsoft.DurableTask.SqlServer.AzureFunctions" Version="1.1.1" />
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.1.1" />
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </None>
  </ItemGroup>
</Project>

Oh, and adding to the above, the same erroneous behavior is observed when trying with a System Assigned Mgd Identity of the Function (that is added as db_owner User to the SQL): The execution starts, with a row to Instances, but never completes (no exeuction of the Durable Tasks I guess) and stays in Pending.

Logs

2023-04-28T08:25:10Z   [Information]   23d89f351d38433db3512aa7f884142c: Function 'DurableFunctionsOrchestrationCSharp1 (Orchestrator)' scheduled. Reason: NewInstance. IsReplay: False. State: Scheduled. HubName: {redacted function name}. AppName: {redacted function name}. SlotName: Production. ExtensionVersion: 2.9.4. SequenceNumber: 36.
2023-04-28T08:25:10Z   [Verbose]   23d89f351d38433db3512aa7f884142c: Executed stored procedure dt.CreateInstance in 11ms
2023-04-28T08:25:10Z   [Information]   Started orchestration with ID = '23d89f351d38433db3512aa7f884142c'.
2023-04-28T08:25:10Z   [Information]   Executed 'DurableFunctionsOrchestrationCSharp1_HttpStart' (Succeeded, Id=92bb6dd9-6a44-4151-9999-bb29e193c057, Duration=88ms)

Metadata

Metadata

Assignees

Labels

db-schemaThis issue is related to or will impact the database schema, likely requiring a DB schema update.documentationImprovements or additions to documentation

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions