/// <summary>
        /// Creates the workflow.
        /// </summary>
        /// <param name="id">Id to use for this workflow.</param>
        /// <param name="externalServiceUrl">External URL to invoke.</param>
        /// <param name="serviceIdentityTokenSource">The token source to use when authenticating to external services.</param>
        /// <param name="serializerSettingsProvider">The serialization settings provider.</param>
        /// <param name="externalServiceActionLogger">The logger for <see cref="InvokeExternalServiceAction"/>s.</param>
        /// <returns>The workflow definition.</returns>
        public static Workflow Create(
            string id,
            string externalServiceUrl,
            IServiceIdentityAccessTokenSource serviceIdentityTokenSource,
            IJsonSerializerSettingsProvider serializerSettingsProvider,
            ILogger <InvokeExternalServiceAction> externalServiceActionLogger)
        {
            var workflow = new Workflow(
                id,
                "External Action workflow",
                "Simple workflow using an external action");

            WorkflowState waitingToRun = workflow.CreateState(displayName: "Waiting to run");
            WorkflowState done         = workflow.CreateState(displayName: "Done");

            workflow.SetInitialState(waitingToRun);

            WorkflowTransition transition = waitingToRun.CreateTransition(done);
            var action = new InvokeExternalServiceAction(
                serviceIdentityTokenSource,
                serializerSettingsProvider,
                externalServiceActionLogger)
            {
                Id = Guid.NewGuid().ToString(),
                AuthenticateWithManagedServiceIdentity = true,
                MsiAuthenticationResource = "foobar",
                ExternalUrl           = externalServiceUrl,
                ContextItemsToInclude = new[] { "include1", "include2" },
            };

            transition.Actions.Add(action);

            return(workflow);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="CloudEventPublisher"/> class.
 /// </summary>
 /// <param name="httpClient">The <see cref="HttpClient"/> to use when POSTing event data to subscribers.</param>
 /// <param name="serviceIdentityTokenSource">The <see cref="IServiceIdentityAccessTokenSource"/> that will be used to aquire authentication tokens.</param>
 /// <param name="serializerSettingsProvider">The current <see cref="IJsonSerializerSettingsProvider"/>.</param>
 /// <param name="logger">The logger.</param>
 public TenantedCloudEventPublisherFactory(
     HttpClient httpClient,
     IServiceIdentityAccessTokenSource serviceIdentityTokenSource,
     IJsonSerializerSettingsProvider serializerSettingsProvider,
     ILogger <CloudEventPublisher> logger)
 {
     this.httpClient = httpClient;
     this.serviceIdentityTokenSource = serviceIdentityTokenSource;
     this.serializerSettingsProvider = serializerSettingsProvider;
     this.logger = logger;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="CloudEventPublisher"/> class.
 /// </summary>
 /// <param name="marainTenantId">The Marain Tenant Id to add to published events as an extension.</param>
 /// <param name="httpClient">The <see cref="HttpClient"/> to use when POSTing event data to subscribers.</param>
 /// <param name="serviceIdentityTokenSource">The <see cref="IServiceIdentityAccessTokenSource"/> that will be used to aquire authentication tokens.</param>
 /// <param name="serializerSettingsProvider">The current <see cref="IJsonSerializerSettingsProvider"/>.</param>
 /// <param name="logger">The logger.</param>
 public CloudEventPublisher(
     string marainTenantId,
     HttpClient httpClient,
     IServiceIdentityAccessTokenSource serviceIdentityTokenSource,
     IJsonSerializerSettingsProvider serializerSettingsProvider,
     ILogger <CloudEventPublisher> logger)
 {
     this.marainTenantId             = marainTenantId;
     this.httpClient                 = httpClient;
     this.serviceIdentityTokenSource = serviceIdentityTokenSource;
     this.serializerSettingsProvider = serializerSettingsProvider;
     this.logger = logger;
 }
        public async Task ThenTheAuthorizationHeaderShouldBeOfTypeBearerUsingATokenRepresentingTheManagedServiceIdentityWithTheResourceSpecifiedByTheConditionAsync()
        {
            Assert.IsTrue(
                this.requestInfo.Headers.TryGetValue("Authorization", out string authorizationHeader),
                "Should contain authorization header");

            IServiceIdentityAccessTokenSource tokenSource =
                ContainerBindings.GetServiceProvider(this.featureContext).GetRequiredService <IServiceIdentityAccessTokenSource>();

            AccessTokenDetail tokenDetail = await tokenSource.GetAccessTokenAsync(
                new AccessTokenRequest(new[] { $"{this.condition.MsiAuthenticationResource}/.default" }))
                                            .ConfigureAwait(false);

            string expectedHeader = "Bearer " + tokenDetail.AccessToken;

            Assert.AreEqual(expectedHeader, authorizationHeader);
        }
        public async Task GivenGivenIHaveCreatedAndPersistedAWorkflowContainingAnExternalConditionWithIdAsync(string workflowId)
        {
            ExternalServiceBindings.ExternalService externalService            = ExternalServiceBindings.GetService(this.scenarioContext);
            IServiceIdentityAccessTokenSource       serviceIdentityTokenSource =
                ContainerBindings.GetServiceProvider(this.featureContext).GetRequiredService <IServiceIdentityAccessTokenSource>();

            IJsonSerializerSettingsProvider serializerSettingsProvider =
                ContainerBindings.GetServiceProvider(this.featureContext).GetRequiredService <IJsonSerializerSettingsProvider>();

            Workflow workflow = ExternalConditionWorkflowFactory.Create(
                workflowId,
                externalService.TestUrl.ToString(),
                serviceIdentityTokenSource,
                serializerSettingsProvider);

            this.condition = workflow.GetInitialState().Transitions
                             .Single()
                             .Conditions
                             .OfType <InvokeExternalServiceCondition>()
                             .Single();

            ITenantedWorkflowStoreFactory storeFactory = ContainerBindings.GetServiceProvider(this.featureContext)
                                                         .GetService <ITenantedWorkflowStoreFactory>();

            ITenantProvider tenantProvider =
                ContainerBindings.GetServiceProvider(this.featureContext).GetRequiredService <ITenantProvider>();

            IWorkflowStore store = await storeFactory.GetWorkflowStoreForTenantAsync(tenantProvider.Root).ConfigureAwait(false);

            await WorkflowRetryHelper.ExecuteWithStandardTestRetryRulesAsync(async() =>
            {
                try
                {
                    Workflow oldWorkflow = await store.GetWorkflowAsync(workflowId).ConfigureAwait(false);
                    workflow.ETag        = oldWorkflow.ETag;
                }
                catch (WorkflowNotFoundException)
                {
                    // Don't care if there is no old workflow.
                }

                await store.UpsertWorkflowAsync(workflow).ConfigureAwait(false);
            }).ConfigureAwait(false);
        }