/// <inheritdoc/> public async Task <ITenant> CreateWellKnownChildTenantAsync( string parentTenantId, Guid wellKnownChildTenantGuid, string name) { ArgumentNullException.ThrowIfNull(parentTenantId); try { (ITenant parentTenant, CloudBlobContainer cloudBlobContainer) = await this.GetContainerAndTenantForChildTenantsOf(parentTenantId).ConfigureAwait(false); // We need to copy blob storage settings for the Tenancy container definition from the parent to the new child // to support the tenant blob store provider. We would expect this to be overridden by clients that wanted to // establish their own settings. BlobStorageConfiguration tenancyStorageConfiguration = parentTenant.GetBlobStorageConfiguration(ContainerDefinition); IPropertyBag childProperties = this.propertyBagFactory.Create(values => values.AddBlobStorageConfiguration(ContainerDefinition, tenancyStorageConfiguration)); var child = new Tenant( parentTenantId.CreateChildId(wellKnownChildTenantGuid), name, childProperties); // As we create the new blob, we need to ensure there isn't already a tenant with the same Id. We do this by // providing an If-None-Match header passing a "*", which will cause a storage exception with a 409 status // code if a blob with the same Id already exists. CloudBlockBlob blob = GetLiveTenantBlockBlobReference(child.Id, cloudBlobContainer); string text = JsonConvert.SerializeObject(child, this.serializerSettings); await blob.UploadTextAsync( text, null, AccessCondition.GenerateIfNoneMatchCondition("*"), null, null).ConfigureAwait(false); child.ETag = blob.Properties.ETag; return(child); } catch (FormatException fex) { throw new TenantNotFoundException("Unsupported tenant ID", fex); } catch (StorageException ex) when(ex.RequestInformation.HttpStatusCode == (int)HttpStatusCode.NotFound) { throw new TenantNotFoundException(); } catch (StorageException ex) when(ex.RequestInformation.HttpStatusCode == (int)HttpStatusCode.Conflict) { // This exception is thrown because there's already a tenant with the same Id. This should never happen when // this method has been called from CreateChildTenantAsync as the Guid will have been generated and the // chances of it matching one previously generated are miniscule. However, it could happen when calling this // method directly with a wellKnownChildTenantGuid that's already in use. In this case, the fault is with // the client code - creating tenants with well known Ids is something one would expect to happen under // controlled conditions, so it's only likely that a conflict will occur when either the client code has made // a mistake or someone is actively trying to cause problems. throw new ArgumentException( $"A child tenant of '{parentTenantId}' with a well known Guid of '{wellKnownChildTenantGuid}' already exists.", nameof(wellKnownChildTenantGuid)); } }
private static void CommonServiceInit( FeatureContext featureContext, IServiceCollection serviceCollection) { serviceCollection.AddSingleton(Configuration); serviceCollection.AddSingleton(Configuration.GetSection("TestSettings").Get <TestSettings>()); serviceCollection.AddRequiredTenancyServices(); if (featureContext.FeatureInfo.Tags.Any(t => t == "withBlobStorageTenantProvider")) { serviceCollection.AddTenantProviderBlobStore(_ => { var blobStorageConfiguration = new BlobStorageConfiguration(); Configuration.Bind("TENANCYBLOBSTORAGECONFIGURATIONOPTIONS", blobStorageConfiguration); return(blobStorageConfiguration); }); // Now replace the service for ITenantStore and ITenantProvider with a decorated TenantProviderBlobStore. serviceCollection.AddSingleton(sp => new TenantTrackingTenantProviderDecorator( sp.GetRequiredService <TenantProviderBlobStore>())); serviceCollection.Remove(serviceCollection.First(x => x.ServiceType == typeof(ITenantProvider))); serviceCollection.AddSingleton <ITenantProvider>( sp => sp.GetRequiredService <TenantTrackingTenantProviderDecorator>()); serviceCollection.AddSingleton <ITenantStore>( sp => sp.GetRequiredService <TenantTrackingTenantProviderDecorator>()); } else { serviceCollection.AddSingleton <FakeTenantProvider>(); serviceCollection.AddSingleton <ITenantProvider>(sp => sp.GetRequiredService <FakeTenantProvider>()); } serviceCollection.AddServiceIdentityAzureTokenCredentialSourceFromLegacyConnectionString(Configuration["AzureServicesAuthConnectionString"]); }
public BlobStore(BlobStorageConfiguration configuration) { containerClient = new BlobContainerClient( configuration.ConnectionString, configuration.ContainerName); this.configuration = configuration; }
/// <summary> /// Adds services an Azure Blob storage-based implementation of <see cref="ITenantProvider"/>. /// </summary> /// <param name="services">The service collection.</param> /// <param name="getRootTenantStorageConfiguration"> /// A function that returns the <see cref="BlobStorageConfiguration"/> that will be used for the root tenant to /// determine where to store its children. /// </param> /// <returns>The modified service collection.</returns> public static IServiceCollection AddTenantProviderBlobStore( this IServiceCollection services, Func <IServiceProvider, BlobStorageConfiguration> getRootTenantStorageConfiguration) { if (services.Any(s => typeof(ITenantProvider).IsAssignableFrom(s.ServiceType))) { return(services); } services.AddRequiredTenancyServices(); services.AddSingleton(sp => { BlobStorageConfiguration rootTenantStorageConfig = getRootTenantStorageConfiguration(sp); IPropertyBagFactory propertyBagFactory = sp.GetRequiredService <IPropertyBagFactory>(); var rootTenant = new RootTenant(propertyBagFactory); rootTenant.UpdateProperties( values => values.AddBlobStorageConfiguration( TenantProviderBlobStore.ContainerDefinition, rootTenantStorageConfig)); ITenantCloudBlobContainerFactory tenantCloudBlobContainerFactory = sp.GetRequiredService <ITenantCloudBlobContainerFactory>(); IJsonSerializerSettingsProvider serializerSettingsProvider = sp.GetRequiredService <IJsonSerializerSettingsProvider>(); return(new TenantProviderBlobStore(rootTenant, propertyBagFactory, tenantCloudBlobContainerFactory, serializerSettingsProvider)); }); services.AddSingleton <ITenantStore>(sp => sp.GetRequiredService <TenantProviderBlobStore>()); services.AddSingleton <ITenantProvider>(sp => sp.GetRequiredService <TenantProviderBlobStore>()); return(services); }
public void GivenIHaveAddedBlobStorageConfigurationToTheCurrentTenant(Table table) { ITenantProvider tenantProvider = this.serviceProvider.GetRequiredService <ITenantProvider>(); var blobStorageConfiguration = new BlobStorageConfiguration(); TenancyContainerScenarioBindings.Configuration.Bind("TESTBLOBSTORAGECONFIGURATIONOPTIONS", blobStorageConfiguration); blobStorageConfiguration.DisableTenantIdPrefix = bool.Parse(table.Rows[0]["DisableTenantIdPrefix"]); string overriddenContainerName = table.Rows[0]["Container"]; if (!string.IsNullOrEmpty(overriddenContainerName)) { // We can run into a problem when running tests multiple times: the container // name ends up being the same each time, and since we delete the container at // the end of the test, the next execution can fail because Azure Storage doesn't // let you create a container with the same name as one you've just deleted. (You // sometimes need to wait for a few minutes.) So we use a unique name. overriddenContainerName += Guid.NewGuid(); blobStorageConfiguration.Container = overriddenContainerName; } tenantProvider.Root.UpdateProperties(values => values.AddBlobStorageConfiguration(this.blobStorageContainerDefinition, blobStorageConfiguration)); }
private static EnrollmentConfigurationItem[] GetClaimsConfig(FeatureContext featureContext) { IConfiguration configuration = ContainerBindings .GetServiceProvider(featureContext) .GetRequiredService <IConfiguration>(); // Load the config items we need: BlobStorageConfiguration claimPermissionsStoreStorageConfiguration = configuration.GetSection("TestBlobStorageConfiguration").Get <BlobStorageConfiguration>() ?? new BlobStorageConfiguration(); claimPermissionsStoreStorageConfiguration.Container = "claimpermissions"; BlobStorageConfiguration resourceAccessRuleSetsStoreStorageConfiguration = configuration.GetSection("TestBlobStorageConfiguration").Get <BlobStorageConfiguration>() ?? new BlobStorageConfiguration(); resourceAccessRuleSetsStoreStorageConfiguration.Container = "resourceaccessrulesets"; return(new EnrollmentConfigurationItem[] { new EnrollmentBlobStorageConfigurationItem { Key = "claimPermissionsStore", Configuration = claimPermissionsStoreStorageConfiguration, }, new EnrollmentBlobStorageConfigurationItem { Key = "resourceAccessRuleSetsStore", Configuration = resourceAccessRuleSetsStoreStorageConfiguration, }, }); }
private static EnrollmentConfigurationItem[] GetOperationsConfig(FeatureContext featureContext) { IConfiguration configuration = ContainerBindings .GetServiceProvider(featureContext) .GetRequiredService <IConfiguration>(); // Can't create a logger using the generic type of this class because it's static, so we'll do it using // the feature context instead. ILogger <FeatureContext> logger = ContainerBindings .GetServiceProvider(featureContext) .GetRequiredService <ILogger <FeatureContext> >(); BlobStorageConfiguration blobStorageConfiguration = configuration.GetSection("TestBlobStorageConfiguration").Get <BlobStorageConfiguration>() ?? new BlobStorageConfiguration(); if (string.IsNullOrEmpty(blobStorageConfiguration.AccountName)) { logger.LogDebug("No configuration value 'TestBlobStorageConfiguration:AccountName' provided; using local storage emulator."); } return(new EnrollmentConfigurationItem[] { new EnrollmentBlobStorageConfigurationItem { Key = "operationsStore", Configuration = blobStorageConfiguration, }, }); }
public void ThenTheTenantedCloudBlobContainerShouldBeNamedUsingAHashOfTheTenantIdAndTheNameSpecifiedInTheBlobConfiguration() { ITenantProvider tenantProvider = this.serviceProvider.GetRequiredService <ITenantProvider>(); BlobStorageConfiguration blobStorageConfiguration = tenantProvider.Root.GetBlobStorageConfiguration(this.blobStorageContainerDefinition); string expectedNamePlain = string.Concat(RootTenant.RootTenantId, "-", blobStorageConfiguration.Container); string expectedName = AzureStorageNameHelper.HashAndEncodeBlobContainerName(expectedNamePlain); Assert.AreEqual(expectedName, this.Container.Name); }
public void RemoteConnectionString() { const string BlobStorageAccount = "account"; const string BlobStorageKey = "key"; const string EndpointSuffix = "suffix"; var connectionString = new BlobStorageConfiguration(BlobStorageAccount, BlobStorageKey, EndpointSuffix).ConnectionString; Assert.Equal("DefaultEndpointsProtocol=https;AccountName=account;AccountKey=key;EndpointSuffix=suffix", connectionString); }
/// <summary> /// Creates the whitelist with the given configuration. /// </summary> /// <param name="configuration">The Azure Blob Storage configuration to use.</param> public FaceWhitelist(BlobStorageConfiguration configuration) { whitelistedUserIds = new ConcurrentBag <string>(); var storageAccount = CloudStorageAccount.Parse(configuration.ConnectionString); blobClient = storageAccount.CreateCloudBlobClient(); const string ContainerName = "whitelist"; container = blobClient.GetContainerReference(ContainerName); container.CreateIfNotExists(); }
public SessionRepository(BlobStorageConfiguration configuration) { var storageAccount = new CloudStorageAccount( new Microsoft.Azure.Storage.Auth.StorageCredentials( configuration.AccountName, configuration.Key), true); var blobClient = storageAccount.CreateCloudBlobClient(); _container = blobClient.GetContainerReference(configuration.ContainerName); if (_sessions == null) { var blockBlob = _container.GetBlockBlobReference("sessions"); _sessions = new List <Session>(JsonConvert.DeserializeObject <Session[]>(blockBlob.DownloadTextAsync().Result)); } }
public void ThenTheTenantCalledShouldContainBlobStorageConfigurationForABlobStorageContainerDefinitionWithContainerName( string tenantName, string containerName) { InMemoryTenantProvider tenantProvider = ContainerBindings.GetServiceProvider(this.scenarioContext).GetRequiredService <InMemoryTenantProvider>(); ITenant tenant = tenantProvider.GetTenantByName(tenantName) ?? throw new TenantNotFoundException($"Could not find tenant with name '{tenantName}'"); var containerDefinition = new BlobStorageContainerDefinition(containerName); BlobStorageConfiguration tenantConfigItem = tenant.GetBlobStorageConfiguration(containerDefinition); // GetBlobStorageConfiguration would have thrown an exception if the config didn't exist, but we'll do a // not null assertion anyway... Assert.IsNotNull(tenantConfigItem); }
private static EnrollmentConfigurationItem[] GetWorkflowConfig(FeatureContext featureContext) { IConfiguration configuration = ContainerBindings .GetServiceProvider(featureContext) .GetRequiredService <IConfiguration>(); // Note: this next part is using configuration types from the old (v2) Corvus.Tenancy // libraries. Unfortunately, this is currently unavoidable because the current version // of Marain.TenantManagement.Abstractions defines enrollment mechanism in terms of // those older types. // Load the config items we need: CosmosConfiguration cosmosConfiguration = configuration.GetSection("TestCosmosConfiguration").Get <CosmosConfiguration>() ?? new CosmosConfiguration(); cosmosConfiguration.DatabaseName = "endjinspecssharedthroughput"; BlobStorageConfiguration storageConfiguration = configuration.GetSection("TestBlobStorageConfiguration").Get <BlobStorageConfiguration>() ?? new BlobStorageConfiguration(); return(new EnrollmentConfigurationItem[] { new EnrollmentBlobStorageConfigurationItem { Key = "workflowStore", Configuration = storageConfiguration, }, new EnrollmentCosmosConfigurationItem { Key = "workflowInstanceStore", Configuration = cosmosConfiguration, }, new EnrollmentBlobStorageConfigurationItem { Key = "operationsStore", Configuration = storageConfiguration, }, }); }
public RystemCacheServiceProvider WithBlobStorage(BlobStorageConfiguration configuration = default, string serviceKey = default) => (RystemCacheServiceProvider)WithIntegration(ServiceProviderType.AzureBlockBlobStorage, configuration, serviceKey);
static IServiceContainer CompositionRoot(string slackToken, SlackUser adminUser, FaceDetectionConfiguration faceDetectionConfiguration, BlobStorageConfiguration blobStorageConfiguration) { var serviceContainer = new ServiceContainer(); serviceContainer.RegisterInstance(slackToken); serviceContainer.RegisterInstance(adminUser); if (string.IsNullOrEmpty(faceDetectionConfiguration.Key)) { serviceContainer.Register <IFaceDetectionClient, FaceServiceClientDummy>(); serviceContainer.Register <IFaceWhitelist, FaceWhitelistDummy>(); } else { serviceContainer.RegisterInstance(faceDetectionConfiguration); serviceContainer.RegisterInstance <IFaceServiceClient>(new FaceServiceClient(faceDetectionConfiguration.Key, faceDetectionConfiguration.URL)); serviceContainer.Register <IFaceDetectionClient, FaceDetectionClient>(); serviceContainer.RegisterInstance <IFaceWhitelist>(new FaceWhitelist(blobStorageConfiguration)); } serviceContainer.Register <ISlackProfileValidator, SlackProfileValidator>(); serviceContainer.Register <ISlackConnector, SlackConnector.SlackConnector>(); serviceContainer.Register <ISlackIntegration, SlackIntegration>(); serviceContainer.Register <ProfilebotImplmentation>(); return(serviceContainer); }
public void Start(string slackToken, SlackUser adminUser, FaceDetectionConfiguration faceDetectionConfiguration, BlobStorageConfiguration blobStorageConfiguration) { if (string.IsNullOrEmpty(slackToken)) { throw new ArgumentException(nameof(slackToken)); } if (string.IsNullOrEmpty(adminUser.Id)) { throw new ArgumentException(nameof(adminUser.Id)); } var serviceContainer = CompositionRoot(slackToken, adminUser, faceDetectionConfiguration, blobStorageConfiguration); profilebot = serviceContainer.GetInstance <ProfilebotImplmentation>(); profilebot .Connect() .ContinueWith(task => { if (!task.IsCompleted || task.IsFaulted) { Console.WriteLine($"Error connecting to Slack: {task.Exception}"); } }); }
public AzureBlobService(BlobStorageConfiguration configuration) { _blobClient = new BlobServiceClient(configuration.ConnectionString); }
public RystemDataServiceProvider WithAppendBlob(BlobStorageConfiguration configuration = default, string serviceKey = default) => (RystemDataServiceProvider)WithIntegration(ServiceProviderType.AzureAppendBlobStorage, configuration, serviceKey);