コード例 #1
0
        public virtual HostSecretsInfo GetHostSecrets()
        {
            if (_hostSecrets == null)
            {
                HostSecrets hostSecrets;

                if (!TryLoadSecrets(_hostSecretsPath, out hostSecrets))
                {
                    hostSecrets = GenerateHostSecrets();
                    PersistSecrets(hostSecrets, _hostSecretsPath);
                }

                // Host secrets will be in the original persisted state at this point (e.g. encrypted),
                // so we read the secrets running them through the appropriate readers
                hostSecrets = ReadHostSecrets(hostSecrets);

                // If the persistence state of any of our secrets is stale (e.g. the encryption key has been rotated), update
                // the state and persist the secrets
                if (hostSecrets.HasStaleKeys)
                {
                    RefreshSecrets(hostSecrets, _hostSecretsPath);
                }

                _hostSecrets = new HostSecretsInfo
                {
                    MasterKey    = hostSecrets.MasterKey.Value,
                    FunctionKeys = hostSecrets.FunctionKeys.ToDictionary(s => s.Name, s => s.Value)
                };
            }

            return(_hostSecrets);
        }
コード例 #2
0
        public async virtual Task <HostSecretsInfo> GetHostSecretsAsync()
        {
            if (_hostSecrets == null)
            {
                HostSecrets hostSecrets = await LoadSecretsAsync <HostSecrets>();

                if (hostSecrets == null)
                {
                    _traceWriter.Verbose(Resources.TraceHostSecretGeneration);
                    hostSecrets = GenerateHostSecrets();
                    await PersistSecretsAsync(hostSecrets);
                }

                // Host secrets will be in the original persisted state at this point (e.g. encrypted),
                // so we read the secrets running them through the appropriate readers
                hostSecrets = ReadHostSecrets(hostSecrets);

                // If the persistence state of any of our secrets is stale (e.g. the encryption key has been rotated), update
                // the state and persist the secrets
                if (hostSecrets.HasStaleKeys)
                {
                    _traceWriter.Verbose(Resources.TraceStaleHostSecretRefresh);
                    await RefreshSecretsAsync(hostSecrets);
                }

                _hostSecrets = new HostSecretsInfo
                {
                    MasterKey    = hostSecrets.MasterKey.Value,
                    FunctionKeys = hostSecrets.FunctionKeys.ToDictionary(s => s.Name, s => s.Value)
                };
            }

            return(_hostSecrets);
        }
コード例 #3
0
        internal static async Task <(string, AuthorizationLevel)> GetAuthorizationLevelAsync(ISecretManager secretManager, string keyValue, string functionName = null)
        {
            // see if the key specified is the master key
            HostSecretsInfo hostSecrets = await secretManager.GetHostSecretsAsync();

            if (!string.IsNullOrEmpty(hostSecrets.MasterKey) &&
                Key.SecretValueEquals(keyValue, hostSecrets.MasterKey))
            {
                return(ScriptConstants.DefaultMasterKeyName, AuthorizationLevel.Admin);
            }

            if (HasMatchingKey(hostSecrets.SystemKeys, keyValue, out string keyName))
            {
                return(keyName, AuthorizationLevel.System);
            }

            // see if the key specified matches the host function key
            if (HasMatchingKey(hostSecrets.FunctionKeys, keyValue, out keyName))
            {
                return(keyName, AuthorizationLevel.Function);
            }

            // If there is a function specific key specified try to match against that
            if (functionName != null)
            {
                IDictionary <string, string> functionSecrets = await secretManager.GetFunctionSecretsAsync(functionName);

                if (HasMatchingKey(functionSecrets, keyValue, out keyName))
                {
                    return(keyName, AuthorizationLevel.Function);
                }
            }

            return(null, AuthorizationLevel.Anonymous);
        }
コード例 #4
0
        public async Task <(string, AuthorizationLevel)> GetAuthorizationLevelOrNullAsync(string keyValue, string functionName = null)
        {
            if (keyValue != null)
            {
                // Before authorizing, check the cache load state. Do this first because checking the auth level will
                // cause the secrets to be loaded into cache - we want to know if they were cached BEFORE this check.
                bool secretsCached = _hostSecrets != null || _functionSecrets.Any();

                var result = await GetAuthorizationLevelAsync(this, keyValue, functionName);

                if (result.Item2 != AuthorizationLevel.Anonymous)
                {
                    // key match
                    return(result);
                }
                else
                {
                    // A key was presented but there wasn't a match. If we used cached key values,
                    // reset cache and try once more.
                    // We throttle resets, to ensure invalid requests can't force us to slam storage.
                    if (secretsCached && ((DateTime.UtcNow - _lastCacheResetTime) > TimeSpan.FromMinutes(1)))
                    {
                        _hostSecrets = null;
                        _functionSecrets.Clear();
                        _lastCacheResetTime = DateTime.UtcNow;

                        return(await GetAuthorizationLevelAsync(this, keyValue, functionName));
                    }
                }
            }

            // no key match
            return(null, AuthorizationLevel.Anonymous);
        }
コード例 #5
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);
        }
コード例 #6
0
        public async virtual Task <HostSecretsInfo> GetHostSecretsAsync()
        {
            if (_hostSecrets == null)
            {
                HostSecrets hostSecrets;
                // Allow only one thread to modify the secrets
                await _hostSecretsLock.WaitAsync();

                try
                {
                    hostSecrets = await LoadSecretsAsync <HostSecrets>();

                    if (hostSecrets == null)
                    {
                        // host secrets do not yet exist so generate them
                        _logger.LogDebug(Resources.TraceHostSecretGeneration);
                        hostSecrets = GenerateHostSecrets();
                        await PersistSecretsAsync(hostSecrets);
                    }

                    try
                    {
                        // Host secrets will be in the original persisted state at this point (e.g. encrypted),
                        // so we read the secrets running them through the appropriate readers
                        hostSecrets = ReadHostSecrets(hostSecrets);
                    }
                    catch (CryptographicException)
                    {
                        _logger?.LogDebug(Resources.TraceNonDecryptedHostSecretRefresh);
                        await PersistSecretsAsync(hostSecrets, null, true);

                        hostSecrets = GenerateHostSecrets(hostSecrets);
                        await RefreshSecretsAsync(hostSecrets);
                    }

                    // If the persistence state of any of our secrets is stale (e.g. the encryption key has been rotated), update
                    // the state and persist the secrets
                    if (hostSecrets.HasStaleKeys)
                    {
                        _logger.LogDebug(Resources.TraceStaleHostSecretRefresh);
                        await RefreshSecretsAsync(hostSecrets);
                    }

                    _hostSecrets = new HostSecretsInfo
                    {
                        MasterKey    = hostSecrets.MasterKey.Value,
                        FunctionKeys = hostSecrets.FunctionKeys.ToDictionary(s => s.Name, s => s.Value),
                        SystemKeys   = hostSecrets.SystemKeys.ToDictionary(s => s.Name, s => s.Value)
                    };
                }
                finally
                {
                    _hostSecretsLock.Release();
                }
            }

            return(_hostSecrets);
        }
コード例 #7
0
        private void InitializeCache()
        {
            var cachedFunctionSecrets = _startupContextProvider.GetFunctionSecretsOrNull();

            _functionSecrets = cachedFunctionSecrets != null ?
                               new ConcurrentDictionary <string, IDictionary <string, string> >(cachedFunctionSecrets, StringComparer.OrdinalIgnoreCase) :
                               new ConcurrentDictionary <string, IDictionary <string, string> >(StringComparer.OrdinalIgnoreCase);

            _hostSecrets = _startupContextProvider.GetHostSecretsOrNull();
        }
コード例 #8
0
 private void OnSecretsChanged(object sender, SecretsChangedEventArgs e)
 {
     // clear the cached secrets if they exist
     // they'll be reloaded on demand next time
     if (e.SecretsType == ScriptSecretsType.Host)
     {
         _hostSecrets = null;
     }
     else
     {
         Dictionary <string, string> secrets;
         _secretsMap.TryRemove(e.Name, out secrets);
     }
 }
コード例 #9
0
 private void OnChanged(object sender, FileSystemEventArgs e)
 {
     // clear the cached secrets if they exist
     // they'll be reloaded on demand next time
     if (string.Compare(Path.GetFileName(e.FullPath), ScriptConstants.HostMetadataFileName, StringComparison.OrdinalIgnoreCase) == 0)
     {
         _hostSecrets = null;
     }
     else
     {
         Dictionary <string, string> secrets;
         string name = Path.GetFileNameWithoutExtension(e.FullPath).ToLowerInvariant();
         _secretsMap.TryRemove(name, out secrets);
     }
 }
コード例 #10
0
        public virtual HostSecretsInfo GetHostSecretsOrNull()
        {
            if (Context?.Secrets?.Host != null)
            {
                var hostSecrets = Context.Secrets.Host;
                var secretsInfo = new HostSecretsInfo
                {
                    MasterKey    = hostSecrets.Master,
                    FunctionKeys = new Dictionary <string, string>(hostSecrets.Function, StringComparer.OrdinalIgnoreCase),
                    SystemKeys   = new Dictionary <string, string>(hostSecrets.System, StringComparer.OrdinalIgnoreCase)
                };
                _logger.LogDebug("Loaded host keys from startup context");

                return(secretsInfo);
            }

            return(null);
        }
コード例 #11
0
 private void OnSecretsChanged(object sender, SecretsChangedEventArgs e)
 {
     // clear the cached secrets if they exist
     // they'll be reloaded on demand next time
     if (e.SecretsType == ScriptSecretsType.Host)
     {
         _hostSecrets = null;
     }
     else
     {
         if (string.IsNullOrEmpty(e.Name))
         {
             _secretsMap.Clear();
         }
         else
         {
             _secretsMap.TryRemove(e.Name, out _);
         }
     }
 }
コード例 #12
0
 private void ClearCacheOnChange(ScriptSecretsType secretsType, string functionName)
 {
     // clear the cached secrets if they exist
     // they'll be reloaded on demand next time
     if (secretsType == ScriptSecretsType.Host && _hostSecrets != null)
     {
         _logger.LogInformation("Host keys change detected. Clearing cache.");
         _hostSecrets = null;
     }
     else
     {
         if (!string.IsNullOrEmpty(functionName) && _functionSecrets.ContainsKey(functionName))
         {
             _logger.LogInformation($"Function keys change detected. Clearing cache for function '{functionName}'.");
             _functionSecrets.TryRemove(functionName, out _);
         }
         else if (_functionSecrets.Any())
         {
             _logger.LogInformation("Function keys change detected. Clearing all cached function keys.");
             _functionSecrets.Clear();
         }
     }
 }
コード例 #13
0
        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);
            }
        }