Inheritance: ScriptSecrets
        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;
            }));
        }
Beispiel #2
0
        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);
        }
Beispiel #7
0
        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());
        }
Beispiel #9
0
        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);
        }
Beispiel #10
0
        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);
        }
Beispiel #11
0
        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);
        }
Beispiel #12
0
 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);
            }
        }