public async Task AddOrUpdateFunctionSecret_ClearsCache_WhenHostSystemSecretAdded() { using (var directory = new TempDirectory()) { CreateTestSecrets(directory.Path); KeyOperationResult result; using (var secretManager = CreateSecretManager(directory.Path, simulateWriteConversion: false)) { var hostKeys = await secretManager.GetHostSecretsAsync(); Assert.Equal(2, hostKeys.SystemKeys.Count); // add a new key result = await secretManager.AddOrUpdateFunctionSecretAsync("host-system-3", "123", HostKeyScopes.SystemKeys, ScriptSecretsType.Host); } string secretsJson = File.ReadAllText(Path.Combine(directory.Path, "host.json")); var persistedSecrets = ScriptSecretSerializer.DeserializeSecrets <HostSecrets>(secretsJson); Assert.Equal(OperationResult.Created, result.Result); Assert.Equal(result.Secret, "123"); var logs = _loggerProvider.GetAllLogMessages(); Assert.Equal(1, logs.Count(p => p.FormattedMessage == "Host keys change detected. Clearing cache.")); Assert.Equal(1, logs.Count(p => p.FormattedMessage == "Host secret 'host-system-3' for 'systemkeys' Created.")); } }
public async Task AddOrUpdateFunctionSecret_ClearsCache_WhenFunctionSecretAdded() { using (var directory = new TempDirectory()) { CreateTestSecrets(directory.Path); KeyOperationResult result; using (var secretManager = CreateSecretManager(directory.Path, simulateWriteConversion: false)) { var keys = await secretManager.GetFunctionSecretsAsync("testfunction"); Assert.Equal(2, keys.Count); // add a new key result = await secretManager.AddOrUpdateFunctionSecretAsync("function-key-3", "9876", "TestFunction", ScriptSecretsType.Function); } string secretsJson = File.ReadAllText(Path.Combine(directory.Path, "testfunction.json")); var persistedSecrets = ScriptSecretSerializer.DeserializeSecrets <FunctionSecrets>(secretsJson); Assert.Equal(OperationResult.Created, result.Result); Assert.Equal(result.Secret, "9876"); var logs = _loggerProvider.GetAllLogMessages(); Assert.Equal(1, logs.Count(p => string.Equals(p.FormattedMessage, "Function keys change detected. Clearing cache for function 'TestFunction'.", StringComparison.OrdinalIgnoreCase))); Assert.Equal(1, logs.Count(p => p.FormattedMessage == "Function secret 'function-key-3' for 'TestFunction' Created.")); } }
public async Task GetHostSecrets_WhenNoHostSecretFileExists_GeneratesSecretsAndPersistsFiles() { using (var directory = new TempDirectory()) { string expectedTraceMessage = Resources.TraceHostSecretGeneration; HostSecretsInfo hostSecrets; using (var secretManager = CreateSecretManager(directory.Path, simulateWriteConversion: false, setStaleValue: false)) { hostSecrets = await secretManager.GetHostSecretsAsync(); } string secretsJson = File.ReadAllText(Path.Combine(directory.Path, ScriptConstants.HostMetadataFileName)); HostSecrets persistedSecrets = ScriptSecretSerializer.DeserializeSecrets <HostSecrets>(secretsJson); Assert.NotNull(hostSecrets); Assert.NotNull(persistedSecrets); Assert.Equal(1, hostSecrets.FunctionKeys.Count); Assert.NotNull(hostSecrets.MasterKey); Assert.NotNull(hostSecrets.SystemKeys); Assert.Equal(0, hostSecrets.SystemKeys.Count); Assert.Equal(persistedSecrets.MasterKey.Value, hostSecrets.MasterKey); Assert.Equal(persistedSecrets.FunctionKeys.First().Value, hostSecrets.FunctionKeys.First().Value); } }
public async Task AddOrUpdateFunctionSecret_ClearsCache_WhenHostLevelFunctionSecretAdded() { using (var directory = new TempDirectory()) { CreateTestSecrets(directory.Path); Mock <IKeyValueConverterFactory> mockValueConverterFactory = GetConverterFactoryMock(false); KeyOperationResult result; ISecretsRepository repository = new FileSystemSecretsRepository(directory.Path); using (var secretManager = new SecretManager(repository, mockValueConverterFactory.Object, _logger, new TestMetricsLogger(), _hostNameProvider)) { var hostKeys = await secretManager.GetHostSecretsAsync(); Assert.Equal(2, hostKeys.FunctionKeys.Count); // add a new key result = await secretManager.AddOrUpdateFunctionSecretAsync("function-host-3", "9876", HostKeyScopes.FunctionKeys, ScriptSecretsType.Host); } string secretsJson = File.ReadAllText(Path.Combine(directory.Path, "host.json")); var persistedSecrets = ScriptSecretSerializer.DeserializeSecrets <HostSecrets>(secretsJson); Assert.Equal(OperationResult.Created, result.Result); Assert.Equal(result.Secret, "9876"); var logs = _loggerProvider.GetAllLogMessages(); Assert.Equal(1, logs.Count(p => p.FormattedMessage == "Host keys change detected. Clearing cache.")); Assert.Equal(1, logs.Count(p => p.FormattedMessage == "Host secret 'function-host-3' for 'functionkeys' Created.")); } }
public async Task AddOrUpdateFunctionSecrets_WithFunctionNameAndNoSecret_EncryptsSecretAndPersistsFile() { using (var directory = new TempDirectory()) { string secretName = "TestSecret"; string functionName = "TestFunction"; string expectedTraceMessage = string.Format(Resources.TraceAddOrUpdateFunctionSecret, "Function", secretName, functionName, "Created"); KeyOperationResult result; using (var secretManager = CreateSecretManager(directory.Path)) { result = await secretManager.AddOrUpdateFunctionSecretAsync(secretName, null, functionName, ScriptSecretsType.Function); } string secretsJson = File.ReadAllText(Path.Combine(directory.Path, "testfunction.json")); FunctionSecrets persistedSecrets = ScriptSecretSerializer.DeserializeSecrets <FunctionSecrets>(secretsJson); Assert.Equal(OperationResult.Created, result.Result); Assert.NotNull(result.Secret); Assert.NotNull(persistedSecrets); Assert.Equal("!" + result.Secret, persistedSecrets.Keys.First().Value); Assert.Equal(secretName, persistedSecrets.Keys.First().Name, StringComparer.Ordinal); Assert.True(persistedSecrets.Keys.First().IsEncrypted); } }
public async Task SetMasterKey_WithoutProvidedKey_GeneratesKeyAndPersistsFile() { using (var directory = new TempDirectory()) { string expectedTraceMessage = "Master key Created"; Mock <IKeyValueConverterFactory> mockValueConverterFactory = GetConverterFactoryMock(false); KeyOperationResult result; var traceWriter = new TestTraceWriter(TraceLevel.Verbose); ISecretsRepository repository = new FileSystemSecretsRepository(directory.Path); using (var secretManager = new SecretManager(repository, mockValueConverterFactory.Object, traceWriter)) { result = await secretManager.SetMasterKeyAsync(); } bool functionSecretsExists = File.Exists(Path.Combine(directory.Path, "testfunction.json")); string secretsJson = File.ReadAllText(Path.Combine(directory.Path, ScriptConstants.HostMetadataFileName)); HostSecrets persistedSecrets = ScriptSecretSerializer.DeserializeSecrets <HostSecrets>(secretsJson); Assert.NotNull(persistedSecrets); Assert.NotNull(persistedSecrets.MasterKey); Assert.Equal(OperationResult.Created, result.Result); Assert.Equal(result.Secret, persistedSecrets.MasterKey.Value); Assert.True(traceWriter.Traces.Any(t => t.Level == TraceLevel.Info && t.Message.IndexOf(expectedTraceMessage) > -1), "Expected Trace message not found"); } }
public async Task SetMasterKey_WithProvidedKey_UsesProvidedKeyAndPersistsFile() { string testSecret = "abcde0123456789abcde0123456789abcde0123456789"; using (var directory = new TempDirectory()) { Mock <IKeyValueConverterFactory> mockValueConverterFactory = GetConverterFactoryMock(false); KeyOperationResult result; ISecretsRepository repository = new FileSystemSecretsRepository(directory.Path); using (var secretManager = new SecretManager(repository, mockValueConverterFactory.Object, NullLogger.Instance)) { result = await secretManager.SetMasterKeyAsync(testSecret); } bool functionSecretsExists = File.Exists(Path.Combine(directory.Path, "testfunction.json")); string secretsJson = File.ReadAllText(Path.Combine(directory.Path, ScriptConstants.HostMetadataFileName)); HostSecrets persistedSecrets = ScriptSecretSerializer.DeserializeSecrets <HostSecrets>(secretsJson); Assert.NotNull(persistedSecrets); Assert.NotNull(persistedSecrets.MasterKey); Assert.Equal(OperationResult.Updated, result.Result); Assert.Equal(testSecret, result.Secret); } }
public void AddOrUpdateFunctionSecrets_WithFunctionNameAndNoSecret_GeneratesFunctionSecretsAndPersistsFile() { var secretsPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); try { using (var variables = new TestScopedEnvironmentVariables("AzureWebJobsFeatureFlags", "MultiKey")) { Mock <IKeyValueConverterFactory> mockValueConverterFactory = GetConverterFactoryMock(false); KeyOperationResult result; using (var secretManager = new SecretManager(secretsPath, mockValueConverterFactory.Object)) { result = secretManager.AddOrUpdateFunctionSecret("TestSecret", null, "TestFunction"); } string secretsJson = File.ReadAllText(Path.Combine(secretsPath, "testfunction.json")); FunctionSecrets persistedSecrets = ScriptSecretSerializer.DeserializeSecrets <FunctionSecrets>(secretsJson); Assert.Equal(OperationResult.Created, result.Result); Assert.NotNull(result.Secret); Assert.NotNull(persistedSecrets); Assert.Equal(result.Secret, persistedSecrets.Keys.First().Value); Assert.Equal("TestSecret", persistedSecrets.Keys.First().Name, StringComparer.Ordinal); } } finally { Directory.Delete(secretsPath, true); } }
public void GetHostSecrets_WhenNoHostSecretFileExists_GeneratesSecretsAndPersistsFiles() { using (var directory = new TempDirectory()) { string expectedTraceMessage = Resources.TraceHostSecretGeneration; Mock <IKeyValueConverterFactory> mockValueConverterFactory = GetConverterFactoryMock(false, false); HostSecretsInfo hostSecrets; var traceWriter = new TestTraceWriter(TraceLevel.Verbose); using (var secretManager = new SecretManager(directory.Path, mockValueConverterFactory.Object, traceWriter)) { hostSecrets = secretManager.GetHostSecrets(); } string secretsJson = File.ReadAllText(Path.Combine(directory.Path, ScriptConstants.HostMetadataFileName)); HostSecrets persistedSecrets = ScriptSecretSerializer.DeserializeSecrets <HostSecrets>(secretsJson); Assert.NotNull(hostSecrets); Assert.NotNull(persistedSecrets); Assert.Equal(1, hostSecrets.FunctionKeys.Count); Assert.NotNull(hostSecrets.MasterKey); Assert.Equal(persistedSecrets.MasterKey.Value, hostSecrets.MasterKey); Assert.Equal(persistedSecrets.FunctionKeys.First().Value, hostSecrets.FunctionKeys.First().Value); Assert.True(traceWriter.Traces.Any(t => t.Level == TraceLevel.Verbose && t.Message.IndexOf(expectedTraceMessage) > -1)); } }
public async Task AddOrUpdateFunctionSecrets_WithScope_UsesSecretandPersistsHostFile(string scope, Func <HostSecrets, IList <Key> > keySelector, TempDirectory directory) { string secretName = "TestSecret"; string expectedTraceMessage = string.Format(Resources.TraceAddOrUpdateFunctionSecret, "Host", secretName, scope, "Created"); Mock <IKeyValueConverterFactory> mockValueConverterFactory = GetConverterFactoryMock(false); KeyOperationResult result; ISecretsRepository repository = new FileSystemSecretsRepository(directory.Path); using (var secretManager = new SecretManager(repository, mockValueConverterFactory.Object, NullLogger.Instance)) { result = await secretManager.AddOrUpdateFunctionSecretAsync(secretName, "TestSecretValue", scope, ScriptSecretsType.Host); } string secretsJson = File.ReadAllText(Path.Combine(directory.Path, ScriptConstants.HostMetadataFileName)); HostSecrets persistedSecrets = ScriptSecretSerializer.DeserializeSecrets <HostSecrets>(secretsJson); Key newSecret = keySelector(persistedSecrets).FirstOrDefault(k => string.Equals(k.Name, secretName, StringComparison.Ordinal)); Assert.Equal(OperationResult.Created, result.Result); Assert.Equal("TestSecretValue", result.Secret, StringComparer.Ordinal); Assert.NotNull(persistedSecrets); Assert.NotNull(newSecret); Assert.Equal(result.Secret, newSecret.Value); Assert.Equal(secretName, newSecret.Name, StringComparer.Ordinal); Assert.NotNull(persistedSecrets.MasterKey); }
public async Task GetHostSecrets_WhenNoHostSecretFileExists_GeneratesSecretsAndPersistsFiles() { using (var directory = new TempDirectory()) { string expectedTraceMessage = Resources.TraceHostSecretGeneration; Mock <IKeyValueConverterFactory> mockValueConverterFactory = GetConverterFactoryMock(false, false); HostSecretsInfo hostSecrets; ISecretsRepository repository = new FileSystemSecretsRepository(directory.Path); using (var secretManager = new SecretManager(repository, mockValueConverterFactory.Object, NullLogger.Instance)) { hostSecrets = await secretManager.GetHostSecretsAsync(); } string secretsJson = File.ReadAllText(Path.Combine(directory.Path, ScriptConstants.HostMetadataFileName)); HostSecrets persistedSecrets = ScriptSecretSerializer.DeserializeSecrets <HostSecrets>(secretsJson); Assert.NotNull(hostSecrets); Assert.NotNull(persistedSecrets); Assert.Equal(1, hostSecrets.FunctionKeys.Count); Assert.NotNull(hostSecrets.MasterKey); Assert.NotNull(hostSecrets.SystemKeys); Assert.Equal(0, hostSecrets.SystemKeys.Count); Assert.Equal(persistedSecrets.MasterKey.Value, hostSecrets.MasterKey); Assert.Equal(persistedSecrets.FunctionKeys.First().Value, hostSecrets.FunctionKeys.First().Value); } }
public async Task AddOrUpdateFunctionSecrets_WithFunctionNameAndProvidedSecret_UsesSecretAndPersistsFile() { using (var directory = new TempDirectory()) { string secretName = "TestSecret"; string functionName = "TestFunction"; string expectedTraceMessage = string.Format(Resources.TraceAddOrUpdateFunctionSecret, "Function", secretName, functionName, "Created"); Mock <IKeyValueConverterFactory> mockValueConverterFactory = GetConverterFactoryMock(false); KeyOperationResult result; ISecretsRepository repository = new FileSystemSecretsRepository(directory.Path); using (var secretManager = new SecretManager(repository, mockValueConverterFactory.Object, NullLogger.Instance)) { result = await secretManager.AddOrUpdateFunctionSecretAsync(secretName, "TestSecretValue", functionName, ScriptSecretsType.Function); } string secretsJson = File.ReadAllText(Path.Combine(directory.Path, "testfunction.json")); FunctionSecrets persistedSecrets = ScriptSecretSerializer.DeserializeSecrets <FunctionSecrets>(secretsJson); Assert.Equal(OperationResult.Created, result.Result); Assert.Equal("TestSecretValue", result.Secret, StringComparer.Ordinal); Assert.NotNull(persistedSecrets); Assert.Equal(result.Secret, persistedSecrets.Keys.First().Value); Assert.Equal(secretName, persistedSecrets.Keys.First().Name, StringComparer.Ordinal); } }
public async Task <ScriptSecrets> GetSecretText(string functionNameOrHost, ScriptSecretsType type) { ScriptSecrets secrets = null; switch (RepositoryType) { case SecretsRepositoryType.FileSystem: string secretText = File.ReadAllText(SecretsFileOrSentinelPath(functionNameOrHost)); secrets = ScriptSecretSerializer.DeserializeSecrets(type, secretText); break; case SecretsRepositoryType.BlobStorage: case SecretsRepositoryType.BlobStorageSas: secrets = await GetSecretBlobText(functionNameOrHost, type); break; case SecretsRepositoryType.KeyVault: secrets = await GetSecretsFromKeyVault(functionNameOrHost, type); break; default: break; } return(secrets); }
public void AddOrUpdateFunctionSecrets_WithNoFunctionNameAndProvidedSecret_UsesSecretAndPersistsHostFile() { var secretsPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); try { using (var variables = new TestScopedEnvironmentVariables("AzureWebJobsFeatureFlags", "MultiKey")) { Mock <IKeyValueConverterFactory> mockValueConverterFactory = GetConverterFactoryMock(false); KeyOperationResult result; using (var secretManager = new SecretManager(secretsPath, mockValueConverterFactory.Object)) { result = secretManager.AddOrUpdateFunctionSecret("TestSecret", "TestSecretValue"); } string secretsJson = File.ReadAllText(Path.Combine(secretsPath, ScriptConstants.HostMetadataFileName)); HostSecrets persistedSecrets = ScriptSecretSerializer.DeserializeSecrets <HostSecrets>(secretsJson); Key newSecret = persistedSecrets.FunctionKeys.FirstOrDefault(k => string.Equals(k.Name, "TestSecret", StringComparison.Ordinal)); Assert.Equal(OperationResult.Created, result.Result); Assert.Equal("TestSecretValue", result.Secret, StringComparer.Ordinal); Assert.NotNull(persistedSecrets); Assert.NotNull(newSecret); Assert.Equal(result.Secret, newSecret.Value); Assert.Equal("TestSecret", newSecret.Name, StringComparer.Ordinal); Assert.NotNull(persistedSecrets.MasterKey); } } finally { Directory.Delete(secretsPath, true); } }
public void SetMasterKey_WithoutProvidedKey_GeneratesKeyAndPersistsFile() { var secretsPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); try { using (var variables = new TestScopedEnvironmentVariables("AzureWebJobsFeatureFlags", "MultiKey")) { Mock <IKeyValueConverterFactory> mockValueConverterFactory = GetConverterFactoryMock(false); KeyOperationResult result; using (var secretManager = new SecretManager(secretsPath, mockValueConverterFactory.Object)) { result = secretManager.SetMasterKey(); } bool functionSecretsExists = File.Exists(Path.Combine(secretsPath, "testfunction.json")); string secretsJson = File.ReadAllText(Path.Combine(secretsPath, ScriptConstants.HostMetadataFileName)); HostSecrets persistedSecrets = ScriptSecretSerializer.DeserializeSecrets <HostSecrets>(secretsJson); Assert.NotNull(persistedSecrets); Assert.NotNull(persistedSecrets.MasterKey); Assert.Equal(OperationResult.Created, result.Result); Assert.Equal(result.Secret, persistedSecrets.MasterKey.Value); } } finally { Directory.Delete(secretsPath, true); } }
public void GetHostSecrets_WhenNoHostSecretFileExists_GeneratesSecretsAndPersistsFiles() { var secretsPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); try { using (var variables = new TestScopedEnvironmentVariables("AzureWebJobsFeatureFlags", "MultiKey")) { Mock <IKeyValueConverterFactory> mockValueConverterFactory = GetConverterFactoryMock(false); HostSecretsInfo hostSecrets; using (var secretManager = new SecretManager(secretsPath, mockValueConverterFactory.Object)) { hostSecrets = secretManager.GetHostSecrets(); } string secretsJson = File.ReadAllText(Path.Combine(secretsPath, ScriptConstants.HostMetadataFileName)); HostSecrets persistedSecrets = ScriptSecretSerializer.DeserializeSecrets <HostSecrets>(secretsJson); Assert.NotNull(hostSecrets); Assert.NotNull(persistedSecrets); Assert.Equal(1, hostSecrets.FunctionKeys.Count); Assert.NotNull(hostSecrets.MasterKey); Assert.Equal(persistedSecrets.MasterKey.Value, hostSecrets.MasterKey); Assert.Equal(persistedSecrets.FunctionKeys.First().Value, hostSecrets.FunctionKeys.First().Value); } } finally { Directory.Delete(secretsPath, true); } }
public void SetMasterKey_WithProvidedKey_UsesProvidedKeyAndPersistsFile() { var secretsPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); string testSecret = "abcde0123456789abcde0123456789abcde0123456789"; try { Mock <IKeyValueConverterFactory> mockValueConverterFactory = GetConverterFactoryMock(false); KeyOperationResult result; using (var secretManager = new SecretManager(secretsPath, mockValueConverterFactory.Object)) { result = secretManager.SetMasterKey(testSecret); } bool functionSecretsExists = File.Exists(Path.Combine(secretsPath, "testfunction.json")); string secretsJson = File.ReadAllText(Path.Combine(secretsPath, ScriptConstants.HostMetadataFileName)); HostSecrets persistedSecrets = ScriptSecretSerializer.DeserializeSecrets <HostSecrets>(secretsJson); Assert.NotNull(persistedSecrets); Assert.NotNull(persistedSecrets.MasterKey); Assert.Equal(OperationResult.Updated, result.Result); Assert.Equal(testSecret, result.Secret); } finally { Directory.Delete(secretsPath, true); } }
public async Task SetMasterKey_WithoutProvidedKey_GeneratesKeyAndPersistsFile() { using (var directory = new TempDirectory()) { Mock <IKeyValueConverterFactory> mockValueConverterFactory = GetConverterFactoryMock(false); KeyOperationResult result; var traceWriter = new TestTraceWriter(System.Diagnostics.TraceLevel.Verbose); ISecretsRepository repository = new FileSystemSecretsRepository(directory.Path); using (var secretManager = new SecretManager(repository, mockValueConverterFactory.Object, null)) { result = await secretManager.SetMasterKeyAsync(); } bool functionSecretsExists = File.Exists(Path.Combine(directory.Path, "testfunction.json")); string secretsJson = File.ReadAllText(Path.Combine(directory.Path, ScriptConstants.HostMetadataFileName)); HostSecrets persistedSecrets = ScriptSecretSerializer.DeserializeSecrets <HostSecrets>(secretsJson); Assert.NotNull(persistedSecrets); Assert.NotNull(persistedSecrets.MasterKey); Assert.Equal(OperationResult.Created, result.Result); Assert.Equal(result.Secret, persistedSecrets.MasterKey.Value); } }
public void SetMasterKey_WithProvidedKey_UsesProvidedKeyAndPersistsFile() { string testSecret = "abcde0123456789abcde0123456789abcde0123456789"; using (var directory = new TempDirectory()) { string expectedTraceMessage = "Master key Updated"; Mock <IKeyValueConverterFactory> mockValueConverterFactory = GetConverterFactoryMock(false); KeyOperationResult result; var traceWriter = new TestTraceWriter(TraceLevel.Verbose); using (var secretManager = new SecretManager(directory.Path, mockValueConverterFactory.Object, traceWriter)) { result = secretManager.SetMasterKey(testSecret); } bool functionSecretsExists = File.Exists(Path.Combine(directory.Path, "testfunction.json")); string secretsJson = File.ReadAllText(Path.Combine(directory.Path, ScriptConstants.HostMetadataFileName)); HostSecrets persistedSecrets = ScriptSecretSerializer.DeserializeSecrets <HostSecrets>(secretsJson); Assert.NotNull(persistedSecrets); Assert.NotNull(persistedSecrets.MasterKey); Assert.Equal(OperationResult.Updated, result.Result); Assert.Equal(testSecret, result.Secret); Assert.True(traceWriter.Traces.Any(t => t.Level == TraceLevel.Info && t.Message.IndexOf(expectedTraceMessage) > -1)); } }
public async Task AddOrUpdateFunctionSecrets_WithNoFunctionNameAndProvidedSecret_UsesSecretAndPersistsHostFile() { using (var directory = new TempDirectory()) { string secretName = "TestSecret"; string expectedTraceMessage = string.Format(Resources.TraceAddOrUpdateFunctionSecret, "Host", secretName, "host", "Created"); Mock <IKeyValueConverterFactory> mockValueConverterFactory = GetConverterFactoryMock(false); KeyOperationResult result; var traceWriter = new TestTraceWriter(TraceLevel.Verbose); ISecretsRepository repository = new FileSystemSecretsRepository(directory.Path); using (var secretManager = new SecretManager(repository, mockValueConverterFactory.Object, traceWriter)) { result = await secretManager.AddOrUpdateFunctionSecretAsync(secretName, "TestSecretValue"); } string secretsJson = File.ReadAllText(Path.Combine(directory.Path, ScriptConstants.HostMetadataFileName)); HostSecrets persistedSecrets = ScriptSecretSerializer.DeserializeSecrets <HostSecrets>(secretsJson); Key newSecret = persistedSecrets.FunctionKeys.FirstOrDefault(k => string.Equals(k.Name, secretName, StringComparison.Ordinal)); Assert.Equal(OperationResult.Created, result.Result); Assert.Equal("TestSecretValue", result.Secret, StringComparer.Ordinal); Assert.NotNull(persistedSecrets); Assert.NotNull(newSecret); Assert.Equal(result.Secret, newSecret.Value); Assert.Equal(secretName, newSecret.Name, StringComparer.Ordinal); Assert.NotNull(persistedSecrets.MasterKey); Assert.True(traceWriter.Traces.Any(t => t.Level == TraceLevel.Info && t.Message.IndexOf(expectedTraceMessage) > -1), "Expected Trace message not found"); } }
public async Task AddOrUpdateFunctionSecrets_WithFunctionNameAndNoSecret_GeneratesFunctionSecretsAndPersistsFile() { using (var directory = new TempDirectory()) { string secretName = "TestSecret"; string functionName = "TestFunction"; string expectedTraceMessage = string.Format(Resources.TraceAddOrUpdateFunctionSecret, "Function", secretName, functionName, "Created"); Mock <IKeyValueConverterFactory> mockValueConverterFactory = GetConverterFactoryMock(false); KeyOperationResult result; var traceWriter = new TestTraceWriter(TraceLevel.Verbose); ISecretsRepository repository = new FileSystemSecretsRepository(directory.Path); using (var secretManager = new SecretManager(repository, mockValueConverterFactory.Object, traceWriter)) { result = await secretManager.AddOrUpdateFunctionSecretAsync(secretName, null, functionName); } string secretsJson = File.ReadAllText(Path.Combine(directory.Path, "testfunction.json")); FunctionSecrets persistedSecrets = ScriptSecretSerializer.DeserializeSecrets <FunctionSecrets>(secretsJson); Assert.Equal(OperationResult.Created, result.Result); Assert.NotNull(result.Secret); Assert.NotNull(persistedSecrets); Assert.Equal(result.Secret, persistedSecrets.Keys.First().Value); Assert.Equal(secretName, persistedSecrets.Keys.First().Name, StringComparer.Ordinal); Assert.True(traceWriter.Traces.Any(t => t.Level == TraceLevel.Info && t.Message.IndexOf(expectedTraceMessage) > -1), "Expected Trace message not found"); } }
private async Task <ScriptSecrets> GetSecretBlobText(string functionNameOrHost, ScriptSecretsType type) { string blobText = null; string blobPath = RelativeBlobPath(functionNameOrHost); if (await BlobContainer.GetBlockBlobReference(blobPath).ExistsAsync()) { blobText = await BlobContainer.GetBlockBlobReference(blobPath).DownloadTextAsync(); } return(ScriptSecretSerializer.DeserializeSecrets(type, blobText)); }
public async Task SetMasterKey_WithoutProvidedKey_GeneratesKeyAndPersistsFile() { using (var directory = new TempDirectory()) { KeyOperationResult result; using (var secretManager = CreateSecretManager(directory.Path, simulateWriteConversion: false)) { result = await secretManager.SetMasterKeyAsync(); } bool functionSecretsExists = File.Exists(Path.Combine(directory.Path, "testfunction.json")); string secretsJson = File.ReadAllText(Path.Combine(directory.Path, ScriptConstants.HostMetadataFileName)); HostSecrets persistedSecrets = ScriptSecretSerializer.DeserializeSecrets <HostSecrets>(secretsJson); Assert.NotNull(persistedSecrets); Assert.NotNull(persistedSecrets.MasterKey); Assert.Equal(OperationResult.Created, result.Result); Assert.Equal(result.Secret, persistedSecrets.MasterKey.Value); } }
public async Task WriteSecret(string functionNameOrHost, ScriptSecrets scriptSecret) { switch (RepositoryType) { case SecretsRepositoryType.FileSystem: WriteSecretsToFile(functionNameOrHost, ScriptSecretSerializer.SerializeSecrets(scriptSecret)); break; case SecretsRepositoryType.BlobStorage: await WriteSecretsBlobAndUpdateSentinelFile(functionNameOrHost, ScriptSecretSerializer.SerializeSecrets(scriptSecret)); break; case SecretsRepositoryType.KeyVault: await WriteSecretsKeyVaultAndUpdateSectinelFile(functionNameOrHost, scriptSecret); break; default: break; } }