private async Task CopyKeysFromFileSystemToBlobStorage(BlobStorageSecretsRepository blobStorageSecretsRepository) { string migrateSentinelPath = Path.Combine(blobStorageSecretsRepository.SecretsSentinelFilePath, "migrate-sentinel.json"); if (File.Exists(migrateSentinelPath)) { // Migration is already done _logger?.LogTrace("Sentinel file is detected."); return; } try { using (var stream = new FileStream(migrateSentinelPath, FileMode.CreateNew)) using (var writer = new StreamWriter(stream)) { //write file _logger?.LogTrace("Sentinel file created."); } } catch (IOException) { _logger?.LogTrace("Sentinel file is already created by another instance."); return; } string[] files = Directory.GetFiles(blobStorageSecretsRepository.SecretsSentinelFilePath.Replace("Sentinels", string.Empty)); if (await blobStorageSecretsRepository.BlobContainer.ExistsAsync()) { BlobResultSegment resultSegment = await blobStorageSecretsRepository.BlobContainer.ListBlobsSegmentedAsync(blobStorageSecretsRepository.SecretsBlobPath + "/", null); // Check for conflicts if (resultSegment.Results.ToArray().Length > 0) { _logger?.LogTrace("Conflict detected. Secrets container is not empty."); return; } } else { await blobStorageSecretsRepository.BlobContainer.CreateIfNotExistsAsync(); } if (files.Length > 0) { List <Task> copyTasks = new List <Task>(); foreach (string file in files) { string blobName = Path.GetFileName(file); CloudBlockBlob cloudBlockBlob = blobStorageSecretsRepository.BlobContainer.GetBlockBlobReference(blobStorageSecretsRepository.SecretsBlobPath + "/" + blobName); string contents = File.ReadAllText(file); Task copyTask = cloudBlockBlob.UploadTextAsync(contents); copyTasks.Add(copyTask); _logger?.LogTrace("'{0}' was migrated.", cloudBlockBlob.StorageUri.PrimaryUri.AbsoluteUri.ToString()); } await Task.WhenAll(copyTasks); } _logger?.LogTrace("Finished successfully."); }
internal ISecretsRepository CreateSecretsRepository() { ISecretsRepository repository = null; if (TryGetSecretsRepositoryType(out Type repositoryType)) { if (repositoryType == typeof(FileSystemSecretsRepository)) { repository = new FileSystemSecretsRepository(_options.CurrentValue.SecretsPath, _loggerFactory.CreateLogger <FileSystemSecretsRepository>(), _environment); } else if (repositoryType == typeof(KeyVaultSecretsRepository)) { string azureWebJobsSecretStorageKeyVaultUri = _environment.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebJobsSecretStorageKeyVaultUri); string azureWebJobsSecretStorageKeyVaultClientId = _environment.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebJobsSecretStorageKeyVaultClientId); string azureWebJobsSecretStorageKeyVaultClientSecret = _environment.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebJobsSecretStorageKeyVaultClientSecret); string azureWebJobsSecretStorageKeyVaultTenantId = _environment.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebJobsSecretStorageKeyVaultTenantId); var keyVaultLogger = _loggerFactory.CreateLogger <KeyVaultSecretsRepository>(); return(new KeyVaultSecretsRepository(Path.Combine(_options.CurrentValue.SecretsPath, "Sentinels"), azureWebJobsSecretStorageKeyVaultUri, azureWebJobsSecretStorageKeyVaultClientId, azureWebJobsSecretStorageKeyVaultClientSecret, azureWebJobsSecretStorageKeyVaultTenantId, keyVaultLogger, _environment)); } else if (repositoryType == typeof(KubernetesSecretsRepository)) { repository = new KubernetesSecretsRepository(_environment, new SimpleKubernetesClient(_environment, _loggerFactory.CreateLogger <SimpleKubernetesClient>())); } else if (repositoryType == typeof(BlobStorageSasSecretsRepository)) { string secretStorageSas = _environment.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebJobsSecretStorageSas); string siteSlotName = _environment.GetAzureWebsiteUniqueSlotName() ?? _hostIdProvider.GetHostIdAsync(CancellationToken.None).GetAwaiter().GetResult(); repository = new BlobStorageSasSecretsRepository(Path.Combine(_options.CurrentValue.SecretsPath, "Sentinels"), secretStorageSas, siteSlotName, _loggerFactory.CreateLogger <BlobStorageSasSecretsRepository>(), _environment, _azureBlobStorageProvider); } else if (repositoryType == typeof(BlobStorageSecretsRepository)) { string siteSlotName = _environment.GetAzureWebsiteUniqueSlotName() ?? _hostIdProvider.GetHostIdAsync(CancellationToken.None).GetAwaiter().GetResult(); repository = new BlobStorageSecretsRepository(Path.Combine(_options.CurrentValue.SecretsPath, "Sentinels"), ConnectionStringNames.Storage, siteSlotName, _loggerFactory.CreateLogger <BlobStorageSecretsRepository>(), _environment, _azureBlobStorageProvider); } } if (repository == null) { throw new InvalidOperationException("Secret initialization from Blob storage failed due to missing both an Azure Storage connection string and a SAS connection uri. " + $"For Blob Storage, please provide at least one of these. If you intend to use files for secrets, add an App Setting key '{EnvironmentSettingNames.AzureWebJobsSecretStorageType}' with value '{FileStorage}'."); } _logger.LogInformation(new EventId(3, "CreatedSecretRespository"), "Resolved secret storage provider {provider}", repository.Name); return(repository); }
private async Task <BlobStorageSecretsRepository> BlobStorageSecretsRepositoryFactory() { BlobStorageSecretsRepository blobStorageSecretsRepository = new BlobStorageSecretsRepository(_secretSentinelDirectoryPath, _accountConnectionString, _siteSlotName); blobStorageSecretsRepository.SecretsChanged += BlobStorageSecretsMigrationRepository_SecretsChanged; try { await CopyKeysFromFileSystemToBlobStorage(blobStorageSecretsRepository); } catch (Exception ex) { _logger?.LogTrace("{0}", ex.ToString()); } return(blobStorageSecretsRepository); }