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 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 AuthorizationLevelAttributeTests() { _actionContext = new HttpActionContext(); HttpControllerContext controllerContext = new HttpControllerContext(); _actionContext.ControllerContext = controllerContext; HttpConfiguration httpConfig = new HttpConfiguration(); controllerContext.Configuration = httpConfig; Mock <IDependencyResolver> mockDependencyResolver = new Mock <IDependencyResolver>(MockBehavior.Strict); httpConfig.DependencyResolver = mockDependencyResolver.Object; _mockSecretManager = new Mock <SecretManager>(MockBehavior.Strict); _hostSecrets = new HostSecrets { MasterKey = TestMasterKeyValue, FunctionKey = TestHostFunctionKeyValue }; _mockSecretManager.Setup(p => p.GetHostSecrets()).Returns(_hostSecrets); _functionSecrets = new FunctionSecrets { Key = TestFunctionKeyValue }; _mockSecretManager.Setup(p => p.GetFunctionSecrets(It.IsAny <string>())).Returns(_functionSecrets); mockDependencyResolver.Setup(p => p.GetService(typeof(SecretManager))).Returns(_mockSecretManager.Object); }
public void SerializeFunctionSecrets_ReturnsExpectedResult() { var serializer = new ScriptSecretSerializerV0(); var secrets = new FunctionSecrets { Keys = new List <Key> { new Key { Name = string.Empty, Value = "Value1", IsEncrypted = false }, new Key { Name = "Key2", Value = "Value2", IsEncrypted = true } } }; string serializedSecret = serializer.SerializeSecrets(secrets); Assert.NotNull(serializedSecret); var jsonObject = JObject.Parse(serializedSecret); var serializedSecretValue = jsonObject.Value <string>("key"); Assert.Equal("Value1", serializedSecretValue); }
public void SerializeFunctionSecrets_ReturnsExpectedResult() { var serializer = new ScriptSecretSerializerV1(); var secrets = new FunctionSecrets { Keys = new List <Key> { new Key { Name = "Key1", Value = "Value1", IsEncrypted = false }, new Key { Name = "Key2", Value = "Value2", IsEncrypted = true } } }; string serializedSecret = serializer.SerializeSecrets(secrets); var jsonObject = JObject.Parse(serializedSecret); var serializedSecrets = jsonObject.Property("keys")?.Value?.ToObject <List <Key> >(); Assert.NotNull(serializedSecret); AssertKeyCollectionsEquality(secrets.Keys, serializedSecrets); }
public async Task WriteAsync_ChangeNotificationUpdatesExistingSecret(SecretsRepositoryType repositoryType) { using (var directory = new TempDirectory()) { await _fixture.TestInitialize(repositoryType, directory.Path); string testFunctionName = functionName; ScriptSecretsType secretsType = ScriptSecretsType.Function; FunctionSecrets initialSecretText = new FunctionSecrets() { Keys = new List <Key> { new Key(KeyName, "test1") } }; FunctionSecrets updatedSecretText = new FunctionSecrets() { Keys = new List <Key> { new Key(KeyName, "test2") } }; await _fixture.WriteSecret(testFunctionName, initialSecretText); var target = _fixture.GetNewSecretRepository(); ScriptSecrets preTextResult = await target.ReadAsync(secretsType, testFunctionName); await _fixture.WriteSecret(testFunctionName, updatedSecretText); ScriptSecrets postTextResult = await target.ReadAsync(secretsType, testFunctionName); Assert.Equal("test1", (preTextResult as FunctionSecrets).Keys[0].Value); Assert.Equal("test2", (postTextResult as FunctionSecrets).Keys[0].Value); } }
public void AddOrUpdateFunctionSecrets_WithFunctionNameAndProvidedSecret_UsesSecretAndPersistsFile() { 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", "TestFunction"); } string secretsJson = File.ReadAllText(Path.Combine(secretsPath, "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("TestSecret", persistedSecrets.Keys.First().Name, StringComparer.Ordinal); } } finally { Directory.Delete(secretsPath, true); } }
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"); } }
public async Task ReadAsync_ReadsExpectedFile(SecretsRepositoryType repositoryType, ScriptSecretsType secretsType) { using (var directory = new TempDirectory()) { await _fixture.TestInitialize(repositoryType, directory.Path); ScriptSecrets testSecrets = null; if (secretsType == ScriptSecretsType.Host) { testSecrets = new HostSecrets() { MasterKey = new Key("master", "test"), FunctionKeys = new List <Key>() { new Key(KeyName, "test") }, SystemKeys = new List <Key>() { new Key(KeyName, "test") } }; } else { testSecrets = new FunctionSecrets() { Keys = new List <Key>() { new Key(KeyName, "test") } }; } string testFunctionName = secretsType == ScriptSecretsType.Host ? "host" : functionName; await _fixture.WriteSecret(testFunctionName, testSecrets); var target = _fixture.GetNewSecretRepository(); ScriptSecrets secretsContent = await target.ReadAsync(secretsType, testFunctionName); if (secretsType == ScriptSecretsType.Host) { Assert.Equal((secretsContent as HostSecrets).MasterKey.Name, "master"); Assert.Equal((secretsContent as HostSecrets).MasterKey.Value, "test"); Assert.Equal((secretsContent as HostSecrets).FunctionKeys[0].Name, KeyName); Assert.Equal((secretsContent as HostSecrets).FunctionKeys[0].Value, "test"); Assert.Equal((secretsContent as HostSecrets).SystemKeys[0].Name, KeyName); Assert.Equal((secretsContent as HostSecrets).SystemKeys[0].Value, "test"); } else { Assert.Equal((secretsContent as FunctionSecrets).Keys[0].Name, KeyName); Assert.Equal((secretsContent as FunctionSecrets).Keys[0].Value, "test"); } } }
public void FunctionKeys(string functionName, string secretName) { FunctionSecrets hostSecrets = new FunctionSecrets() { Keys = new List <Key> { new Key(secretName, "test") } }; Dictionary <string, string> dictionary = KeyVaultSecretsRepository.GetDictionaryFromScriptSecrets(hostSecrets, functionName); Assert.True(dictionary[$"function--{KeyVaultSecretsRepository.Normalize(functionName)}--{KeyVaultSecretsRepository.Normalize(secretName)}"] == "test"); }
private async Task <ScriptSecrets> GetSecretsFromKeyVault(string functionNameOrHost, ScriptSecretsType type) { var secretResults = SecretClient.GetPropertiesOfSecretsAsync().AsPages(); var searchPages = new List <SecretProperties>(); await foreach (Page <SecretProperties> page in secretResults) { { foreach (SecretProperties secret in page.Values) { searchPages.Add(secret); } } } if (type == ScriptSecretsType.Host) { KeyVaultSecret masterBundle = await SecretClient.GetSecretAsync(searchPages.FirstOrDefault(x => x.Name.StartsWith("host--master")).Name); KeyVaultSecret functionKeyBundle = await SecretClient.GetSecretAsync(searchPages.FirstOrDefault(x => x.Name.StartsWith("host--functionKey")).Name); KeyVaultSecret systemKeyBundle = await SecretClient.GetSecretAsync(searchPages.FirstOrDefault(x => x.Name.StartsWith("host--systemKey")).Name); HostSecrets hostSecrets = new HostSecrets() { FunctionKeys = new List <Key>() { new Key(GetSecretName(functionKeyBundle.Name), functionKeyBundle.Value) }, SystemKeys = new List <Key>() { new Key(GetSecretName(systemKeyBundle.Name), systemKeyBundle.Value) } }; hostSecrets.MasterKey = new Key("master", masterBundle.Value); return(hostSecrets); } else { KeyVaultSecret functionKeyBundle = await SecretClient.GetSecretAsync(searchPages.FirstOrDefault(x => x.Name.StartsWith("function--")).Name); FunctionSecrets functionSecrets = new FunctionSecrets() { Keys = new List <Key>() { new Key(GetSecretName(functionKeyBundle.Name), functionKeyBundle.Value) } }; return(functionSecrets); } }
internal static AuthorizationLevel GetAuthorizationLevel(HttpRequestMessage request, SecretManager secretManager, string functionName = null) { // TODO: Add support for validating "EasyAuth" headers // first see if a key value is specified via headers or query string (header takes precidence) IEnumerable <string> values; string keyValue = null; if (request.Headers.TryGetValues(FunctionsKeyHeaderName, out values)) { keyValue = values.FirstOrDefault(); } else { var queryParameters = request.GetQueryNameValuePairs().ToDictionary(p => p.Key, p => p.Value, StringComparer.OrdinalIgnoreCase); queryParameters.TryGetValue("code", out keyValue); } if (!string.IsNullOrEmpty(keyValue)) { // see if the key specified is the master key HostSecrets hostSecrets = secretManager.GetHostSecrets(); if (!string.IsNullOrEmpty(hostSecrets.MasterKey) && SecretEqual(keyValue, hostSecrets.MasterKey)) { return(AuthorizationLevel.Admin); } // see if the key specified matches the host function key if (!string.IsNullOrEmpty(hostSecrets.FunctionKey) && SecretEqual(keyValue, hostSecrets.FunctionKey)) { return(AuthorizationLevel.Function); } // if there is a function specific key specified try to match against that if (functionName != null) { FunctionSecrets functionSecrets = secretManager.GetFunctionSecrets(functionName); if (functionSecrets != null && !string.IsNullOrEmpty(functionSecrets.Key) && SecretEqual(keyValue, functionSecrets.Key)) { return(AuthorizationLevel.Function); } } } return(AuthorizationLevel.Anonymous); }
public Task <string> GetReceiverConfigAsync(string name, string id) { // "id" will be the function name // we ignore the "name" parameter since we only allow a function // to be mapped to a single receiver FunctionSecrets secrets = _secretManager.GetFunctionSecrets(id); if (secrets != null) { return(Task.FromResult(secrets.Key)); } return(null); }
public void DeserializeFunctionSecrets_ReturnsExpectedResult() { var serializer = new ScriptSecretSerializerV0(); var serializedSecret = "{ 'key': 'TestValue' }"; var expected = new List <Key> { new Key { Name = ScriptConstants.DefaultFunctionKeyName, Value = "TestValue", IsEncrypted = false } }; FunctionSecrets actual = serializer.DeserializeSecrets <FunctionSecrets>(JObject.Parse(serializedSecret)); AssertKeyCollectionsEquality(expected, actual.Keys); }
private async Task <ScriptSecrets> GetSecretsFromKeyVault(string functionNameOrHost, ScriptSecretsType type) { var secretResults = await KeyVaultClient.GetSecretsAsync(GetKeyVaultBaseUrl()); if (type == ScriptSecretsType.Host) { SecretBundle masterBundle = await KeyVaultClient.GetSecretAsync(GetKeyVaultBaseUrl(), secretResults.FirstOrDefault(x => x.Identifier.Name.StartsWith("host--master")).Identifier.Name); SecretBundle functionKeyBundle = await KeyVaultClient.GetSecretAsync(GetKeyVaultBaseUrl(), secretResults.FirstOrDefault(x => x.Identifier.Name.StartsWith("host--functionKey")).Identifier.Name); SecretBundle systemKeyBundle = await KeyVaultClient.GetSecretAsync(GetKeyVaultBaseUrl(), secretResults.FirstOrDefault(x => x.Identifier.Name.StartsWith("host--systemKey")).Identifier.Name); HostSecrets hostSecrets = new HostSecrets() { FunctionKeys = new List <Key>() { new Key(GetSecretName(functionKeyBundle.SecretIdentifier.Name), functionKeyBundle.Value) }, SystemKeys = new List <Key>() { new Key(GetSecretName(systemKeyBundle.SecretIdentifier.Name), systemKeyBundle.Value) } }; hostSecrets.MasterKey = new Key("master", masterBundle.Value); return(hostSecrets); } else { SecretBundle functionKeyBundle = await KeyVaultClient.GetSecretAsync(GetKeyVaultBaseUrl(), secretResults.FirstOrDefault(x => x.Identifier.Name.StartsWith("function--")).Identifier.Name); FunctionSecrets functionSecrets = new FunctionSecrets() { Keys = new List <Key>() { new Key(GetSecretName(functionKeyBundle.SecretIdentifier.Name), functionKeyBundle.Value) } }; return(functionSecrets); } }
public async Task GetSecretSnapshots_ReturnsExpected(SecretsRepositoryType repositoryType, ScriptSecretsType secretsType) { using (var directory = new TempDirectory()) { await _fixture.TestInitialize(repositoryType, directory.Path); ScriptSecrets secrets = null; if (secretsType == ScriptSecretsType.Host) { secrets = new HostSecrets() { MasterKey = new Key("master", "test") }; } else { secrets = new FunctionSecrets() { Keys = new List <Key>() { new Key(KeyName, "test") } }; } string testFunctionName = secretsType == ScriptSecretsType.Host ? null : functionName; var target = _fixture.GetNewSecretRepository(); await target.WriteAsync(secretsType, testFunctionName, secrets); for (int i = 0; i < 5; i++) { await target.WriteSnapshotAsync(secretsType, testFunctionName, secrets); } string[] files = await target.GetSecretSnapshots(secretsType, testFunctionName); Assert.True(files.Length > 0); } }
public void DeserializeFunctionSecrets_ReturnsExpectedResult(string serializedSecret, string hostName) { var serializer = new ScriptSecretSerializerV1(); var expected = new List <Key> { new Key { Name = "Key1", Value = "Value1", IsEncrypted = false }, new Key { Name = "Key2", Value = "Value2", IsEncrypted = true } }; FunctionSecrets actual = serializer.DeserializeSecrets <FunctionSecrets>(JObject.Parse(serializedSecret)); Assert.Equal(hostName, actual.HostName); AssertKeyCollectionsEquality(expected, actual.Keys); }
public void DeserializeFunctionSecrets_ReturnsExpectedResult() { var serializer = new ScriptSecretSerializerV1(); var serializedSecret = "{ 'keys': [ { 'name': 'Key1', 'value': 'Value1', 'encrypted': false }, { 'name': 'Key2', 'value': 'Value2', 'encrypted': true } ] }"; var expected = new List <Key> { new Key { Name = "Key1", Value = "Value1", IsEncrypted = false }, new Key { Name = "Key2", Value = "Value2", IsEncrypted = true } }; FunctionSecrets actual = serializer.DeserializeSecrets <FunctionSecrets>(JObject.Parse(serializedSecret)); AssertKeyCollectionsEquality(expected, actual.Keys); }
public async Task<FunctionSecrets> GetFunctionSecretsAsync(string functionName) { FunctionSecrets secrets; string secretFilePath = GetFunctionSecretsFilePath(functionName); if (FileSystemHelpers.FileExists(secretFilePath)) { // load the secrets file string secretsJson = await FileSystemHelpers.ReadAllTextFromFileAsync(secretFilePath); secrets = JsonConvert.DeserializeObject<FunctionSecrets>(secretsJson); } else { // initialize with new secrets and save it secrets = new FunctionSecrets { Key = SecurityUtility.GenerateSecretString() }; FileSystemHelpers.EnsureDirectory(Path.GetDirectoryName(secretFilePath)); await FileSystemHelpers.WriteAllTextToFileAsync(secretFilePath, JsonConvert.SerializeObject(secrets, Formatting.Indented)); } secrets.TriggerUrl = String.Format(@"https://{0}/api/{1}?code={2}", System.Environment.GetEnvironmentVariable("WEBSITE_HOSTNAME") ?? "localhost", functionName, secrets.Key); return secrets; }
public async Task ReadAsync_ReadsExpectedKeyVaultPages(SecretsRepositoryType repositoryType, ScriptSecretsType secretsType) { using (var directory = new TempDirectory()) { await _fixture.TestInitialize(repositoryType, directory.Path); ScriptSecrets testSecrets = null; int keyCount = 35; List <Key> functionKeys = new List <Key>(); for (int i = 0; i < keyCount; ++i) { functionKeys.Add(new Key(KeyName + Guid.NewGuid().ToString(), "test" + i.ToString())); } if (secretsType == ScriptSecretsType.Host) { testSecrets = new HostSecrets() { MasterKey = new Key("master", "test"), FunctionKeys = functionKeys, SystemKeys = new List <Key>() { new Key(KeyName, "test") } }; } else { testSecrets = new FunctionSecrets() { Keys = functionKeys }; } string testFunctionName = secretsType == ScriptSecretsType.Host ? "host" : functionName; await _fixture.WriteSecret(testFunctionName, testSecrets); var target = _fixture.GetNewSecretRepository(); ScriptSecrets secretsContent = await target.ReadAsync(secretsType, testFunctionName); if (secretsType == ScriptSecretsType.Host) { Assert.Equal((secretsContent as HostSecrets).MasterKey.Name, "master"); Assert.Equal((secretsContent as HostSecrets).MasterKey.Value, "test"); Assert.Equal((secretsContent as HostSecrets).FunctionKeys.Count, functionKeys.Count); foreach (Key originalKey in functionKeys) { var matchingKeys = (secretsContent as HostSecrets).FunctionKeys.Where(x => string.Equals(x.Name, originalKey.Name)); Assert.Equal(matchingKeys.Count(), 1); Assert.Equal(matchingKeys.First().Value, originalKey.Value); } Assert.Equal((secretsContent as HostSecrets).SystemKeys[0].Name, KeyName); Assert.Equal((secretsContent as HostSecrets).SystemKeys[0].Value, "test"); } else { Assert.Equal((secretsContent as FunctionSecrets).Keys.Count, functionKeys.Count); foreach (Key originalKey in functionKeys) { var matchingKeys = (secretsContent as FunctionSecrets).Keys.Where(x => string.Equals(x.Name, originalKey.Name)); Assert.Equal(matchingKeys.Count(), 1); Assert.Equal(matchingKeys.First().Value, originalKey.Value); } } } }
private FunctionSecrets GetFunctionSecrets(string functionName) { FunctionSecrets secrets; string secretFilePath = GetFunctionSecretsFilePath(functionName); if (File.Exists(secretFilePath)) { // load the secrets file string secretsJson = FileSystemHelpers.ReadAllTextFromFile(secretFilePath); secrets = JsonConvert.DeserializeObject<FunctionSecrets>(secretsJson); } else { // initialize with new secrets and save it secrets = new FunctionSecrets { Key = SecurityUtility.GenerateSecretString() }; FileSystemHelpers.EnsureDirectory(Path.GetDirectoryName(secretFilePath)); FileSystemHelpers.WriteAllText(secretFilePath, JsonConvert.SerializeObject(secrets, Formatting.Indented)); } return secrets; }
public async Task WriteAsync_CreatesExpectedFile(SecretsRepositoryType repositoryType, ScriptSecretsType secretsType) { using (var directory = new TempDirectory()) { await _fixture.TestInitialize(repositoryType, directory.Path); ScriptSecrets secrets = null; if (secretsType == ScriptSecretsType.Host) { secrets = new HostSecrets() { MasterKey = new Key("master", "test"), FunctionKeys = new List <Key>() { new Key(KeyName, "test") }, SystemKeys = new List <Key>() { new Key(KeyName, "test") } }; } else { secrets = new FunctionSecrets() { Keys = new List <Key>() { new Key(KeyName, "test") } }; } string testFunctionName = secretsType == ScriptSecretsType.Host ? null : functionName; var target = _fixture.GetNewSecretRepository(); await target.WriteAsync(secretsType, testFunctionName, secrets); string filePath = Path.Combine(directory.Path, $"{testFunctionName ?? "host"}.json"); if (repositoryType == SecretsRepositoryType.BlobStorage || repositoryType == SecretsRepositoryType.BlobStorageSas) { Assert.True(_fixture.MarkerFileExists(testFunctionName ?? "host")); } ScriptSecrets secrets1 = await _fixture.GetSecretText(testFunctionName ?? "host", secretsType); if (secretsType == ScriptSecretsType.Host) { Assert.Equal((secrets1 as HostSecrets).MasterKey.Name, "master"); Assert.Equal((secrets1 as HostSecrets).MasterKey.Value, "test"); Assert.Equal((secrets1 as HostSecrets).FunctionKeys[0].Name, KeyName); Assert.Equal((secrets1 as HostSecrets).FunctionKeys[0].Value, "test"); Assert.Equal((secrets1 as HostSecrets).SystemKeys[0].Name, KeyName); Assert.Equal((secrets1 as HostSecrets).SystemKeys[0].Value, "test"); } else { Assert.Equal((secrets1 as FunctionSecrets).Keys[0].Name, KeyName); Assert.Equal((secrets1 as FunctionSecrets).Keys[0].Value, "test"); } } }