public async Task CallHttpActionOrchestrationWithManagedIdentity()
        {
            DurableHttpRequest request = null;

            // Mock the CallHttpAsync API so we can capture the request and return a fixed response.
            var contextMock = new Mock <IDurableOrchestrationContext>();

            contextMock
            .Setup(ctx => ctx.CallHttpAsync(It.IsAny <DurableHttpRequest>()))
            .Callback <DurableHttpRequest>(req => request = req)
            .Returns(Task.FromResult(new DurableHttpResponse(System.Net.HttpStatusCode.OK)));

            var shim = new OutOfProcOrchestrationShim(contextMock.Object);

            var executionJson = @"
{
    ""isDone"": false,
    ""actions"": [
        [{
            ""actionType"": ""CallHttp"",
            ""httpRequest"": {
                ""method"": ""GET"",
                ""uri"": ""https://example.com"",
                ""tokenSource"": {
                    ""kind"": ""AzureManagedIdentity"",
                    ""resource"": ""https://management.core.windows.net/.default""
                }
            }
        }]
    ]
}";

            // Feed the out-of-proc execution result JSON to the out-of-proc shim.
            var jsonObject = JObject.Parse(executionJson);
            OrchestrationInvocationResult result = new OrchestrationInvocationResult()
            {
                ReturnValue = jsonObject,
            };
            bool moreWork = await shim.ScheduleDurableTaskEvents(result);

            Assert.NotNull(request);
            Assert.Equal(HttpMethod.Get, request.Method);
            Assert.Equal(new Uri("https://example.com"), request.Uri);
            Assert.Null(request.Content);

            Assert.NotNull(request.TokenSource);
            ManagedIdentityTokenSource tokenSource = Assert.IsType <ManagedIdentityTokenSource>(request.TokenSource);

            Assert.Equal("https://management.core.windows.net/.default", tokenSource.Resource);
        }
        public static async Task RunOrchestrator(
            [OrchestrationTrigger] IDurableOrchestrationContext context)
        {
            ResourceInfo vmInfo         = context.GetInput <ResourceInfo>();
            string       apiVersion     = vmInfo.ApiVersion ?? "2018-06-01";
            string       subscriptionId = vmInfo.SubscriptionId;
            string       resourceGroup  = vmInfo.ResourceGroup;

            // Implicitly uses the Azure AD identity of the current app to make an HTTP call to Azure Resource Manager
            var managedIdentity = new ManagedIdentityTokenSource("https://management.core.windows.net");

            // List all of the VMs in my subscription and add them to a list.
            DurableHttpRequest request = new DurableHttpRequest(
                HttpMethod.Get,
                new Uri($"https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.Compute/virtualMachines?api-version=2018-06-01"),
                tokenSource: managedIdentity);
            DurableHttpResponse response = await context.CallHttpAsync(request);

            if (response.StatusCode != HttpStatusCode.OK)
            {
                throw new ArgumentException($"Failed to list VMs: {response.StatusCode}: {response.Content}");
            }

            // Deserializes content to just get the names of the VMs in the subscription
            JObject jObject     = JsonConvert.DeserializeObject <JObject>(response.Content);
            var     vmNamesList = new List <string>();

            foreach (JToken value in jObject["value"])
            {
                string vmName = value["name"].ToString();
                vmNamesList.Add(vmName);
            }

            // Restart all of the VMs in my subscription
            foreach (string vmName in vmNamesList)
            {
                var restartRequest = new DurableHttpRequest(
                    HttpMethod.Post,
                    new Uri($"https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.Compute/virtualMachines/{vmName}/restart?api-version={apiVersion}"),
                    tokenSource: managedIdentity);
                DurableHttpResponse restartResponse = await context.CallHttpAsync(restartRequest);

                if (restartResponse.StatusCode != HttpStatusCode.OK)
                {
                    throw new ArgumentException($"Failed to restart VM: {restartResponse.StatusCode}: {restartResponse.Content}");
                }
            }
        }
        public async Task OpenCircuit(
            [OrchestrationTrigger] IDurableOrchestrationContext context,
            ILogger log)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            try
            {
                var failureRequest = context.GetInput <FailureRequest>();
                var resourceId     = failureRequest.ResourceId;

                if (!context.IsReplaying)
                {
                    log.LogInformation("Disabling function app ({resourceId}) to open circuit.", resourceId);
                }

                var managedIdentity = new ManagedIdentityTokenSource("https://management.azure.com/.default");

                // Note: Configurable resourceId works only for other Azure App Service applications.
                var stopFunctionRequest = new DurableHttpRequest(
                    HttpMethod.Post,
                    new Uri($"https://management.azure.com{resourceId}/stop?api-version=2019-08-01"),
                    tokenSource: managedIdentity);

                // Note: Use of ConfigureAwait can break orchestration tasks (prevents from completing; instance remains in a 'running' state).
                // See https://github.com/Azure/azure-functions-durable-extension/issues/995 and
                // https://docs.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-code-constraints
#pragma warning disable CA2007 // Consider calling ConfigureAwait on the awaited task
                DurableHttpResponse restartResponse = await context.CallHttpAsync(stopFunctionRequest);

#pragma warning restore CA2007 // Consider calling ConfigureAwait on the awaited task

                if (restartResponse.StatusCode != HttpStatusCode.OK)
                {
                    if (!context.IsReplaying)
                    {
                        log.LogError("Failed to stop Function App: {restartResponse.StatusCode}: {restartResponse.Content}", restartResponse.StatusCode, restartResponse.Content);
                    }

                    throw new ApplicationException($"Failed to stop Function App: {restartResponse.StatusCode}: {restartResponse.Content}");
                }

                if (restartResponse.StatusCode == HttpStatusCode.OK)
                {
                    if (!context.IsReplaying)
                    {
                        // Logging as a warning to aide in noticing this messages, as stopping of an Azure Function
                        // may be an action worthy of human intervention.
                        log.LogWarning("Successfully STOPPED Azure Function with Resource ID {resourceId}.", resourceId);
                    }
                }

                return;
            }
            catch (Exception e)
            {
                log.LogError(e, "Unexpected error '{msg}' while processing.", e.Message);
                throw;
            }
        }