public virtual FunctionSecrets GetFunctionSecrets(string functionName) { if (string.IsNullOrEmpty(functionName)) { throw new ArgumentNullException("functionName"); } functionName = functionName.ToLowerInvariant(); return(_secretsMap.GetOrAdd(functionName, (n) => { FunctionSecrets secrets; string secretFileName = string.Format(CultureInfo.InvariantCulture, "{0}.json", functionName); string secretFilePath = Path.Combine(_secretsPath, secretFileName); if (File.Exists(secretFilePath)) { // load the secrets file string secretsJson = File.ReadAllText(secretFilePath); secrets = JsonConvert.DeserializeObject <FunctionSecrets>(secretsJson); } else { // initialize with new secrets and save it secrets = new FunctionSecrets { Key = GenerateSecretString() }; File.WriteAllText(secretFilePath, JsonConvert.SerializeObject(secrets, Formatting.Indented)); } return secrets; })); }
private async Task <ScriptSecrets> ReadFunctionSecrets(string functionName) { List <IEnumerable <SecretItem> > secretsPages = await GetKeyVaultSecretsPagesAsync(_keyVaultClient.Value, GetVaultBaseUrl()); List <Task <SecretBundle> > tasks = new List <Task <SecretBundle> >(); string prefix = $"{FunctionPrefix}{Normalize(functionName)}--"; foreach (SecretItem item in FindSecrets(secretsPages, x => x.Identifier.Name.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))) { tasks.Add(_keyVaultClient.Value.GetSecretAsync(GetVaultBaseUrl(), item.Identifier.Name)); } if (!tasks.Any()) { return(null); } await Task.WhenAll(tasks); FunctionSecrets functionSecrets = new FunctionSecrets() { Keys = new List <Key>() }; foreach (Task <SecretBundle> task in tasks) { SecretBundle item = task.Result; functionSecrets.Keys.Add(SecretBundleToKey(item, prefix)); } return(functionSecrets); }
private bool TryLoadFunctionSecrets(string functionName, out FunctionSecrets secrets, string filePath = null) { secrets = null; string secretsFilePath = filePath ?? GetFunctionSecretsFilePath(functionName); return(TryLoadSecrets(secretsFilePath, out secrets)); }
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); }
private async Task <ScriptSecrets> ReadFunctionSecrets(string functionName) { AsyncPageable <SecretProperties> secretsPages = GetKeyVaultSecretsPagesAsync(_secretClient.Value); List <Task <Response <KeyVaultSecret> > > tasks = new List <Task <Response <KeyVaultSecret> > >(); string prefix = $"{FunctionPrefix}{Normalize(functionName)}--"; foreach (SecretProperties item in await FindSecrets(secretsPages, x => x.Name.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))) { tasks.Add(_secretClient.Value.GetSecretAsync(item.Name)); } if (!tasks.Any()) { return(null); } await Task.WhenAll(tasks); FunctionSecrets functionSecrets = new FunctionSecrets() { Keys = new List <Key>() }; foreach (Task <Response <KeyVaultSecret> > task in tasks) { KeyVaultSecret item = task.Result; functionSecrets.Keys.Add(KeyVaultSecretToKey(item, prefix)); } return(functionSecrets); }
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 virtual Task <IDictionary <string, string> > GetFunctionSecretsAsync(string functionName, bool merged = false) { if (string.IsNullOrEmpty(functionName)) { throw new ArgumentNullException(nameof(functionName)); } functionName = functionName.ToLowerInvariant(); Dictionary <string, string> functionSecrets; _secretsMap.TryGetValue(functionName, out functionSecrets); if (functionSecrets == null) { FunctionSecrets secrets = await LoadFunctionSecretsAsync(functionName); if (secrets == null) { string message = string.Format(Resources.TraceFunctionSecretGeneration, functionName); _logger?.LogDebug(message); secrets = new FunctionSecrets { Keys = new List <Key> { GenerateKey(ScriptConstants.DefaultFunctionKeyName) } }; await PersistSecretsAsync(secrets, functionName); } // Read all secrets, which will run the keys through the appropriate readers secrets.Keys = secrets.Keys.Select(k => _keyValueConverterFactory.ReadKey(k)).ToList(); if (secrets.HasStaleKeys) { _logger?.LogDebug(string.Format(Resources.TraceStaleFunctionSecretRefresh, functionName)); await RefreshSecretsAsync(secrets, functionName); } Dictionary <string, string> result = secrets.Keys.ToDictionary(s => s.Name, s => s.Value); functionSecrets = _secretsMap.AddOrUpdate(functionName, result, (n, r) => result); } if (merged) { // If merged is true, we combine function specific keys with host level function keys, // prioritizing function specific keys HostSecretsInfo hostSecrets = await GetHostSecretsAsync(); Dictionary <string, string> hostFunctionSecrets = hostSecrets.FunctionKeys; functionSecrets = functionSecrets.Union(hostFunctionSecrets.Where(s => !functionSecrets.ContainsKey(s.Key))) .ToDictionary(kv => kv.Key, kv => kv.Value); } return(functionSecrets); }
private static string SerializeFunctionSecrets(FunctionSecrets secrets) { // Output: // { "key" : "keyvalue" } var functionSecrets = new JObject { [FunctionKeyPropertyName] = GetFunctionKeyFromCollection(secrets?.Keys) }; return(functionSecrets.ToString()); }
public virtual IDictionary <string, string> GetFunctionSecrets(string functionName, bool merged = false) { if (string.IsNullOrEmpty(functionName)) { throw new ArgumentNullException(nameof(functionName)); } functionName = functionName.ToLowerInvariant(); var functionSecrets = _secretsMap.GetOrAdd(functionName, n => { FunctionSecrets secrets; string secretsFilePath = GetFunctionSecretsFilePath(functionName); if (!TryLoadFunctionSecrets(functionName, out secrets, secretsFilePath)) { _traceWriter.VerboseFormat(Resources.TraceFunctionSecretGeneration, functionName); secrets = new FunctionSecrets { Keys = new List <Key> { GenerateKey(ScriptConstants.DefaultFunctionKeyName) } }; PersistSecrets(secrets, secretsFilePath); } // Read all secrets, which will run the keys through the appropriate readers secrets.Keys = secrets.Keys.Select(k => _keyValueConverterFactory.ReadKey(k)).ToList(); if (secrets.HasStaleKeys) { _traceWriter.VerboseFormat(Resources.TraceStaleFunctionSecretRefresh, functionName); RefreshSecrets(secrets, secretsFilePath); } return(secrets.Keys.ToDictionary(s => s.Name, s => s.Value)); }); if (merged) { // If merged is true, we combine function specific keys with host level function keys, // prioritizing function specific keys Dictionary <string, string> hostFunctionSecrets = GetHostSecrets().FunctionKeys; functionSecrets = functionSecrets.Union(hostFunctionSecrets.Where(s => !functionSecrets.ContainsKey(s.Key))) .ToDictionary(kv => kv.Key, kv => kv.Value); } return(functionSecrets); }
private async Task <ScriptSecrets> ReadFunctionSecrets(string functionName) { IDictionary <string, string> secrets = await _kubernetesClient.GetSecrets(); var prefix = $"{FunctionKeyPrefix}{functionName}."; var functionSecrets = new FunctionSecrets() { Keys = secrets .Where(p => p.Key.StartsWith(prefix)) .Select(p => ParseKeyWithPrefix(prefix, p.Key, p.Value)) .ToList() }; return(functionSecrets.Keys.Count == 0 ? null : functionSecrets); }
public static Dictionary <string, string> GetDictionaryFromScriptSecrets(ScriptSecrets secrets, string functionName) { Dictionary <string, string> dic = new Dictionary <string, string>(); HostSecrets hostSecrets = secrets as HostSecrets; FunctionSecrets functionSecrets = secrets as FunctionSecrets; if (hostSecrets != null) { if (hostSecrets.MasterKey != null) { dic.Add(MasterKey + "master", hostSecrets.MasterKey.Value); } if (hostSecrets.FunctionKeys != null) { foreach (Key key in hostSecrets.FunctionKeys) { dic.Add($"{FunctionKeyPrefix}{Normalize(key.Name)}", key.Value); } } if (hostSecrets.SystemKeys != null) { foreach (Key key in hostSecrets.SystemKeys) { dic.Add($"{SystemKeyPrefix}{Normalize(key.Name)}", key.Value); } } } else if (functionSecrets != null) { if (functionSecrets.Keys != null) { foreach (Key key in functionSecrets.Keys) { dic.Add($"{FunctionPrefix}{Normalize(functionName)}--{Normalize(key.Name)}", key.Value); } } } return(dic); }
private FunctionSecrets GenerateFunctionSecrets(FunctionSecrets secrets) { secrets.Keys = RegenerateKeys(secrets.Keys); return(secrets); }
public async virtual Task <IDictionary <string, string> > GetFunctionSecretsAsync(string functionName, bool merged = false) { using (_metricsLogger.LatencyEvent(GetMetricEventName(MetricEventNames.SecretManagerGetFunctionSecrets), functionName)) { if (string.IsNullOrEmpty(functionName)) { throw new ArgumentNullException(nameof(functionName)); } functionName = functionName.ToLowerInvariant(); Dictionary <string, string> functionSecrets; _secretsMap.TryGetValue(functionName, out functionSecrets); if (functionSecrets == null) { FunctionSecrets secrets = await LoadFunctionSecretsAsync(functionName); if (secrets == null) { // no secrets exist for this function so generate them string message = string.Format(Resources.TraceFunctionSecretGeneration, functionName); _logger.LogDebug(message); secrets = GenerateFunctionSecrets(); await PersistSecretsAsync(secrets, functionName); } try { // Read all secrets, which will run the keys through the appropriate readers secrets.Keys = secrets.Keys.Select(k => _keyValueConverterFactory.ReadKey(k)).ToList(); } catch (CryptographicException ex) { string message = string.Format(Resources.TraceNonDecryptedFunctionSecretRefresh, functionName, ex); _logger?.LogDebug(message); await PersistSecretsAsync(secrets, functionName, true); secrets = GenerateFunctionSecrets(secrets); await RefreshSecretsAsync(secrets, functionName); } if (secrets.HasStaleKeys) { _logger.LogDebug(string.Format(Resources.TraceStaleFunctionSecretRefresh, functionName)); await RefreshSecretsAsync(secrets, functionName); } Dictionary <string, string> result = secrets.Keys.ToDictionary(s => s.Name, s => s.Value); functionSecrets = _secretsMap.AddOrUpdate(functionName, result, (n, r) => result); } if (merged) { // If merged is true, we combine function specific keys with host level function keys, // prioritizing function specific keys HostSecretsInfo hostSecrets = await GetHostSecretsAsync(); Dictionary <string, string> hostFunctionSecrets = hostSecrets.FunctionKeys; functionSecrets = functionSecrets.Union(hostFunctionSecrets.Where(s => !functionSecrets.ContainsKey(s.Key))) .ToDictionary(kv => kv.Key, kv => kv.Value); } return(functionSecrets); } }