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);
        }
        public async Task <SyncTriggersPayload> GetSyncTriggersPayload()
        {
            var hostOptions       = _applicationHostOptions.CurrentValue.ToHostOptions();
            var functionsMetadata = _functionMetadataManager.GetFunctionMetadata();

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

            var triggersArray = new JArray(triggers);
            int count         = triggersArray.Count;

            if (!ArmCacheEnabled)
            {
                // extended format is disabled - just return triggers
                return(new SyncTriggersPayload
                {
                    Content = JsonConvert.SerializeObject(triggersArray),
                    Count = count
                });
            }

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

            result.Add("triggers", triggersArray);

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

            var listableFunctions = _functionMetadataManager.GetFunctionMetadata().Where(m => !m.IsCodeless());
            var functionDetails   = await WebFunctionsManager.GetFunctionMetadataResponse(listableFunctions, hostOptions, _hostNameProvider);

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

            // TEMP: refactor this code to properly add extensions in all scenario(#7394)
            // Add the host.json extensions to the payload
            if (_environment.IsKubernetesManagedHosting())
            {
                JObject extensionsPayload = await GetHostJsonExtensionsAsync(_applicationHostOptions, _logger);

                if (extensionsPayload != null)
                {
                    result.Add("extensions", extensionsPayload);
                }
            }

            if (_secretManagerProvider.SecretsEnabled)
            {
                // 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.Equals(secretsStorageType, "files", StringComparison.OrdinalIgnoreCase) ||
                    string.Equals(secretsStorageType, "blob", StringComparison.OrdinalIgnoreCase))
                {
                    var functionAppSecrets = new FunctionAppSecrets();

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

                    functionAppSecrets.Host = new FunctionAppSecrets.HostSecrets
                    {
                        Master   = hostSecretsInfo.MasterKey,
                        Function = hostSecretsInfo.FunctionKeys,
                        System   = hostSecretsInfo.SystemKeys
                    };

                    // add function secrets
                    var httpFunctions = functionsMetadata.Where(p => p.InputBindings.Any(q => q.IsTrigger && string.Equals(q.Type, "httptrigger", StringComparison.OrdinalIgnoreCase))).Select(p => p.Name).ToArray();
                    functionAppSecrets.Function = new FunctionAppSecrets.FunctionSecrets[httpFunctions.Length];
                    for (int i = 0; i < httpFunctions.Length; i++)
                    {
                        var currFunctionName = httpFunctions[i];
                        var currSecrets      = await _secretManagerProvider.Current.GetFunctionSecretsAsync(currFunctionName);

                        functionAppSecrets.Function[i] = new FunctionAppSecrets.FunctionSecrets
                        {
                            Name    = currFunctionName,
                            Secrets = currSecrets
                        };
                    }

                    result.Add("secrets", JObject.FromObject(functionAppSecrets));
                }
                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 && !_environment.IsKubernetesManagedHosting())
            {
                // 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(new SyncTriggersPayload
                {
                    Content = JsonConvert.SerializeObject(triggersArray),
                    Count = count
                });
            }

            return(new SyncTriggersPayload
            {
                Content = json,
                Count = count
            });
        }
Exemplo n.º 3
0
        public async Task <JToken> GetSyncTriggersPayload()
        {
            var hostOptions       = _applicationHostOptions.CurrentValue.ToHostOptions();
            var functionsMetadata = WebFunctionsManager.GetFunctionsMetadata(hostOptions, _workerConfigs, _logger);

            // 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(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
            }

            return(result);
        }