Ejemplo n.º 1
0
        /// <summary>
        /// Read all functions and populate function metadata.
        /// </summary>
        internal ImmutableArray <FunctionMetadata> LoadFunctionMetadata()
        {
            ICollection <string> functionsWhiteList = _scriptOptions.Value.Functions;

            _logger.FunctionMetadataManagerLoadingFunctionsMetadata();

            List <FunctionMetadata> functionMetadataList = _functionMetadataProvider.GetFunctionMetadata().ToList();

            _functionErrors = _functionMetadataProvider.FunctionErrors.ToDictionary(kvp => kvp.Key, kvp => (ICollection <string>)kvp.Value.ToList());

            // Validate
            foreach (FunctionMetadata functionMetadata in functionMetadataList.ToList())
            {
                if (!IsScriptFileDetermined(functionMetadata))
                {
                    // Exclude invalid functions
                    functionMetadataList.Remove(functionMetadata);
                }
            }
            Errors = _functionErrors.ToImmutableDictionary(kvp => kvp.Key, kvp => kvp.Value.ToImmutableArray());

            if (functionsWhiteList != null)
            {
                _logger.LogInformation($"A function whitelist has been specified, excluding all but the following functions: [{string.Join(", ", functionsWhiteList)}]");
                functionMetadataList = functionMetadataList.Where(function => functionsWhiteList.Any(functionName => functionName.Equals(function.Name, StringComparison.CurrentCultureIgnoreCase))).ToList();
                Errors = _functionErrors.Where(kvp => functionsWhiteList.Any(functionName => functionName.Equals(kvp.Key, StringComparison.CurrentCultureIgnoreCase))).ToImmutableDictionary(kvp => kvp.Key, kvp => kvp.Value.ToImmutableArray());
            }
            _logger.FunctionMetadataManagerFunctionsLoaded(functionMetadataList.Count());

            return(functionMetadataList.ToImmutableArray());
        }
Ejemplo n.º 2
0
        internal IEnumerable <FunctionMetadata> GetFunctionsMetadata(ScriptJobHostOptions hostOptions, ILogger logger, bool includeProxies = false)
        {
            IEnumerable <FunctionMetadata> functionsMetadata = _functionMetadataProvider.GetFunctionMetadata();

            if (includeProxies)
            {
                // get proxies metadata
                var values = ProxyMetadataManager.ReadProxyMetadata(hostOptions.RootScriptPath, logger);
                var proxyFunctionsMetadata = values.Item1;
                if (proxyFunctionsMetadata?.Count > 0)
                {
                    functionsMetadata = proxyFunctionsMetadata.Concat(functionsMetadata);
                }
            }

            return(functionsMetadata);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Read all functions and populate function metadata.
        /// </summary>
        internal ImmutableArray <FunctionMetadata> LoadFunctionMetadata(bool forceRefresh = false, bool includeCustomProviders = true)
        {
            _functionMetadataMap.Clear();

            ICollection <string> functionsAllowList = _scriptOptions?.Value?.Functions;

            _logger.FunctionMetadataManagerLoadingFunctionsMetadata();

            var immutableFunctionMetadata = _functionMetadataProvider.GetFunctionMetadata(_languageWorkerOptions.Value.WorkerConfigs, forceRefresh);
            var functionMetadataList      = new List <FunctionMetadata>();

            _functionErrors = new Dictionary <string, ICollection <string> >();

            if (!immutableFunctionMetadata.IsDefaultOrEmpty)
            {
                functionMetadataList.AddRange(immutableFunctionMetadata);
            }

            if (!_functionMetadataProvider.FunctionErrors?.IsEmpty ?? false)
            {
                _functionErrors = _functionMetadataProvider.FunctionErrors.ToDictionary(kvp => kvp.Key, kvp => (ICollection <string>)kvp.Value.ToList());
            }

            // Add metadata and errors from any additional function providers
            if (includeCustomProviders)
            {
                LoadCustomProviderFunctions(functionMetadataList);
            }

            // Validate
            foreach (FunctionMetadata functionMetadata in functionMetadataList.ToList())
            {
                if (!IsScriptFileDetermined(functionMetadata))
                {
                    // Exclude invalid functions
                    functionMetadataList.Remove(functionMetadata);
                }
            }
            Errors = _functionErrors.ToImmutableDictionary(kvp => kvp.Key, kvp => kvp.Value.ToImmutableArray());

            if (functionsAllowList != null)
            {
                _logger.LogInformation($"A function allow list has been specified, excluding all but the following functions: [{string.Join(", ", functionsAllowList)}]");
                Errors = _functionErrors.Where(kvp => functionsAllowList.Any(functionName => functionName.Equals(kvp.Key, StringComparison.CurrentCultureIgnoreCase))).ToImmutableDictionary(kvp => kvp.Key, kvp => kvp.Value.ToImmutableArray());
            }

            return(functionMetadataList.OrderBy(f => f.Name, StringComparer.OrdinalIgnoreCase).ToImmutableArray());
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Read all functions and populate function metadata.
        /// </summary>
        private ImmutableArray <FunctionMetadata> LoadFunctionMetadata()
        {
            ICollection <string> functionsWhiteList = _scriptOptions.Value.Functions;

            _logger.FunctionMetadataManagerLoadingFunctionsMetadata();
            ImmutableArray <FunctionMetadata> metadata = _functionMetadataProvider.GetFunctionMetadata();

            Errors = _functionMetadataProvider.FunctionErrors;

            if (functionsWhiteList != null)
            {
                _logger.LogInformation($"A function whitelist has been specified, excluding all but the following functions: [{string.Join(", ", functionsWhiteList)}]");
                metadata = metadata.Where(function => functionsWhiteList.Any(functionName => functionName.Equals(function.Name, StringComparison.CurrentCultureIgnoreCase))).ToImmutableArray();
                Errors   = _functionMetadataProvider.FunctionErrors.Where(kvp => functionsWhiteList.Any(functionName => functionName.Equals(kvp.Key, StringComparison.CurrentCultureIgnoreCase))).ToImmutableDictionary <string, ImmutableArray <string> >();
            }
            _logger.FunctionMetadataManagerFunctionsLoaded(metadata.Length);
            return(metadata);
        }
        public async Task <string> GetSyncTriggersPayload()
        {
            var hostOptions       = _applicationHostOptions.CurrentValue.ToHostOptions();
            var functionsMetadata = _functionMetadataProvider.GetFunctionMetadata();

            // trigger information used by the ScaleController
            var triggers = await GetFunctionTriggers(functionsMetadata, hostOptions);

            var triggersArray = new JArray(triggers);

            if (!ArmCacheEnabled)
            {
                // extended format is disabled - just return triggers
                return(JsonConvert.SerializeObject(triggersArray));
            }

            // Add triggers to the payload
            JObject result = new JObject();

            result.Add("triggers", triggersArray);

            // Add functions details to the payload
            JObject functions   = new JObject();
            string  routePrefix = await WebFunctionsManager.GetRoutePrefix(hostOptions.RootScriptPath);

            var functionDetails = await WebFunctionsManager.GetFunctionMetadataResponse(functionsMetadata, hostOptions, _hostNameProvider);

            result.Add("functions", new JArray(functionDetails.Select(p => JObject.FromObject(p))));

            // Add functions secrets to the payload
            // Only secret types we own/control can we cache directly
            // Encryption is handled by Antares before storage
            var secretsStorageType = _environment.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebJobsSecretStorageType);

            if (string.IsNullOrEmpty(secretsStorageType) ||
                string.Compare(secretsStorageType, "files", StringComparison.OrdinalIgnoreCase) == 0 ||
                string.Compare(secretsStorageType, "blob", StringComparison.OrdinalIgnoreCase) == 0)
            {
                JObject secrets = new JObject();
                result.Add("secrets", secrets);

                // add host secrets
                var hostSecretsInfo = await _secretManagerProvider.Current.GetHostSecretsAsync();

                var hostSecrets = new JObject();
                hostSecrets.Add("master", hostSecretsInfo.MasterKey);
                hostSecrets.Add("function", JObject.FromObject(hostSecretsInfo.FunctionKeys));
                hostSecrets.Add("system", JObject.FromObject(hostSecretsInfo.SystemKeys));
                secrets.Add("host", hostSecrets);

                // add function secrets
                var functionSecrets = new JArray();
                var httpFunctions   = functionsMetadata.Where(p => !p.IsProxy && p.InputBindings.Any(q => q.IsTrigger && string.Compare(q.Type, "httptrigger", StringComparison.OrdinalIgnoreCase) == 0)).Select(p => p.Name);
                foreach (var functionName in httpFunctions)
                {
                    var currSecrets = await _secretManagerProvider.Current.GetFunctionSecretsAsync(functionName);

                    var currElement = new JObject()
                    {
                        { "name", functionName },
                        { "secrets", JObject.FromObject(currSecrets) }
                    };
                    functionSecrets.Add(currElement);
                }
                secrets.Add("function", functionSecrets);
            }
            else
            {
                // TODO: handle other external key storage types
                // like KeyVault when the feature comes online
            }

            string json = JsonConvert.SerializeObject(result);

            if (json.Length > ScriptConstants.MaxTriggersStringLength)
            {
                // The settriggers call to the FE enforces a max request size
                // limit. If we're over limit, revert to the minimal triggers
                // format.
                _logger.LogWarning($"SyncTriggers payload of length '{json.Length}' exceeds max length of '{ScriptConstants.MaxTriggersStringLength}'. Reverting to minimal format.");
                return(JsonConvert.SerializeObject(triggersArray));
            }

            return(json);
        }