/// <summary>
 /// Creates an <see cref="AuthenticationOptions"/>.
 /// </summary>
 /// <param name="tenantId">The Azure AD tenant against which to authenticate.</param>
 /// <param name="serviceIdTokenProviderSource">Provides token providers representing the application.</param>
 /// <param name="serviceIdAzureTokenCredentialSource">Provides Azure token credentials representing the application.</param>
 /// <param name="azureServiceTokenProviderConnectionString">The connection string for the azure service token provide if additional claims are needed.</param>
 private AuthenticationOptions(
     string tenantId,
     IServiceIdentityMicrosoftRestTokenProviderSource serviceIdTokenProviderSource,
     IServiceIdentityAzureTokenCredentialSource serviceIdAzureTokenCredentialSource,
     string azureServiceTokenProviderConnectionString)
 {
     this.TenantId = tenantId ?? throw new ArgumentNullException(nameof(tenantId));
     this.serviceIdTokenProviderSource              = serviceIdTokenProviderSource;
     this.serviceIdAzureTokenCredentialSource       = serviceIdAzureTokenCredentialSource;
     this.AzureServiceTokenProviderConnectionString = azureServiceTokenProviderConnectionString;
 }
 public FakeServiceIdentityTokenSource(IServiceIdentityAzureTokenCredentialSource realTokenProvider)
 {
     this.realTokenProvider = realTokenProvider;
 }
        public static void InitializeContainer(FeatureContext featureContext)
        {
            ContainerBindings.ConfigureServices(
                featureContext,
                services =>
            {
                IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
                                                             .AddEnvironmentVariables()
                                                             .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true);

                IConfiguration root = configurationBuilder.Build();

                services.AddSingleton(root);

                services.AddLogging();

                services.AddInMemoryTenantProvider();

                services.AddJsonNetSerializerSettingsProvider();
                services.AddJsonNetPropertyBag();
                services.AddJsonNetCultureInfoConverter();
                services.AddJsonNetDateTimeOffsetToIso8601AndUnixTimeConverter();
                services.AddSingleton <JsonConverter>(new StringEnumConverter(true));
                services.AddCosmosClientBuilderWithNewtonsoftJsonIntegration();

                // Even non-cosmos tests depend on ICosmosContainerSourceWithTenantLegacyTransition
                // because the various 'data catalog' parts of the test use a Cosmos DB.
                services.AddTenantCosmosContainerFactory();
                services.AddCosmosContainerV2ToV3Transition();

                services.AddInMemoryWorkflowTriggerQueue();
                services.AddInMemoryLeasing();

                services.RegisterCoreWorkflowContentTypes();
                services.AddTenantedWorkflowEngineFactory();

                if (featureContext.FeatureInfo.Tags.Any(t => t == "useCosmosStores"))
                {
                    services.AddTenantedAzureCosmosWorkflowStore();
                    services.AddTenantedAzureCosmosWorkflowInstanceStore();
                }
                else if (featureContext.FeatureInfo.Tags.Any(t => t == "useSqlStores"))
                {
                    services.AddTenantedSqlWorkflowStore();
                    services.AddTenantedSqlWorkflowInstanceStore();
                }
                else if (featureContext.FeatureInfo.Tags.Any(t => t == "useAzureBlobStore"))
                {
                    services.AddTenantedBlobWorkflowStore();

                    // We don't yet have a blob implementation of the instance store.
                    services.AddSingleton <ITenantedWorkflowInstanceStoreFactory, FakeTenantedWorkflowInstanceStoreFactory>();
                }

                services.AddContent(factory => factory.RegisterTestContentTypes());

                services.AddSingleton <DataCatalogItemRepositoryFactory>();

                // Faking out the service identity is slightly awkward because in some cases we need
                // it to work for real (so we can read Azure Key Vault secrets in configuration)
                // but some tests need to provide fake results. So we spin up a second container
                // with a real service identity, and put a wrapper around that into the container
                // that everything is really using.
                ServiceCollection containerForRealTokenProvider = new();
                string azureServicesAuthConnectionString        = root["AzureServicesAuthConnectionString"];
                containerForRealTokenProvider
                .AddServiceIdentityAzureTokenCredentialSourceFromLegacyConnectionString(azureServicesAuthConnectionString);
                IServiceProvider spForRealTokenProvider = containerForRealTokenProvider.BuildServiceProvider();
                IServiceIdentityAzureTokenCredentialSource realTokenProvider = spForRealTokenProvider.GetRequiredService <IServiceIdentityAzureTokenCredentialSource>();

                // We do this to get the IServiceIdentityAccessTokenSource, because there isn't an easy way to get that
                // but our adapter as the IServiceIdentityAzureTokenCredentialSource.
                services.AddServiceIdentityAzureTokenCredentialSourceFromLegacyConnectionString(azureServicesAuthConnectionString);

                // And now we replace the IServiceIdentityAzureTokenCredentialSource with our adapter.
                services.AddSingleton <IServiceIdentityAzureTokenCredentialSource>(new FakeServiceIdentityTokenSource(realTokenProvider));
            });
        }