src/WebJobs.Script/Config/FunctionsHostingConfigOptions.cs (215 lines of code) (raw):
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Http;
using Microsoft.Azure.WebJobs.Script.Workers.Rpc;
namespace Microsoft.Azure.WebJobs.Script.Config
{
public class FunctionsHostingConfigOptions
{
private readonly Dictionary<string, string> _features;
private PathString[] _allowedInternalAuthApis;
public FunctionsHostingConfigOptions()
{
_features = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
/// <summary>
/// Gets all features in the hosting configuration.
/// </summary>
public Dictionary<string, string> Features => _features;
/// <summary>
/// Gets a value indicating whether worker concurrency feature is enabled in the hosting config.
/// </summary>
internal bool FunctionsWorkerDynamicConcurrencyEnabled
{
get
{
return GetFeature(RpcWorkerConstants.FunctionsWorkerDynamicConcurrencyEnabled) == "1";
}
}
/// <summary>
/// Gets a value indicating whether worker indexing feature is enabled in the hosting config.
/// </summary>
internal bool WorkerIndexingEnabled
{
get
{
return GetFeature(RpcWorkerConstants.WorkerIndexingEnabled) == "1";
}
}
/// <summary>
/// Gets or Sets a value indicating whether the host should shutdown webhost worker channels during shutdown.
/// </summary>
internal bool ShutdownWebhostWorkerChannelsOnHostShutdown
{
get
{
return GetFeatureAsBooleanOrDefault(RpcWorkerConstants.ShutdownWebhostWorkerChannelsOnHostShutdown, true);
}
set
{
_features[RpcWorkerConstants.ShutdownWebhostWorkerChannelsOnHostShutdown] = value ? "1" : "0";
}
}
/// <summary>
/// Gets or sets a value indicating whether SWT tokens should be sent on outgoing requests.
/// </summary>
internal bool SwtIssuerEnabled
{
get
{
return GetFeatureAsBooleanOrDefault(ScriptConstants.HostingConfigSwtIssuerEnabled, true);
}
set
{
_features[ScriptConstants.HostingConfigSwtIssuerEnabled] = value ? "1" : "0";
}
}
/// <summary>
/// Gets or sets a value indicating whether to use cgroup memory metrics for reporting memory usage.
/// </summary>
internal bool IsCGroupMemoryMetricsEnabled
{
get
{
return GetFeatureAsBooleanOrDefault(ScriptConstants.FeatureFlagEnableCGroupMemoryMetrics, false);
}
set
{
_features[ScriptConstants.FeatureFlagEnableCGroupMemoryMetrics] = value ? "1" : "0";
}
}
/// <summary>
/// Gets or sets a string delimited by '|' that contains a list of admin APIs that are allowed to
/// be invoked internally by platform components.
/// </summary>
internal string InternalAuthApisAllowList
{
get
{
return GetFeature(ScriptConstants.HostingConfigInternalAuthApisAllowList);
}
set
{
_allowedInternalAuthApis = null;
_features[ScriptConstants.HostingConfigInternalAuthApisAllowList] = value;
}
}
/// <summary>
/// Gets a string delimited by '|' that contains the name of the apps with worker indexing disabled.
/// </summary>
internal string WorkerIndexingDisabledApps
{
get
{
return GetFeature(RpcWorkerConstants.WorkerIndexingDisabledApps) ?? string.Empty;
}
}
/// <summary>
/// Gets a value indicating whether Linux Log Backoff is disabled in the hosting config.
/// </summary>
internal bool DisableLinuxAppServiceLogBackoff
{
get
{
return GetFeature(ScriptConstants.HostingConfigDisableLinuxAppServiceExecutionEventLogBackoff) == "1";
}
}
/// <summary>
/// Gets or sets a value indicating whether Linux AppService/EP Detailed Execution Event is disabled in the hosting config.
/// </summary>
internal bool DisableLinuxAppServiceExecutionDetails
{
get
{
return GetFeature(ScriptConstants.HostingConfigDisableLinuxAppServiceDetailedExecutionEvents) == "1";
}
set
{
_features[ScriptConstants.HostingConfigDisableLinuxAppServiceDetailedExecutionEvents] = value ? "1" : "0";
}
}
internal bool EnableOrderedInvocationMessages
{
get
{
return GetFeatureAsBooleanOrDefault(ScriptConstants.FeatureFlagEnableOrderedInvocationmessages, true);
}
set
{
_features[ScriptConstants.FeatureFlagEnableOrderedInvocationmessages] = value ? "1" : "0";
}
}
/// <summary>
/// Gets or sets a value indicating whether to ignore the TestData property during read and write operations of functions metadata.
/// </summary>
internal bool IsTestDataSuppressionEnabled
{
get
{
return GetFeatureAsBooleanOrDefault(ScriptConstants.FeatureFlagEnableTestDataSuppression, false);
}
set
{
_features[ScriptConstants.FeatureFlagEnableTestDataSuppression] = value ? "1" : "0";
}
}
/// <summary>
/// Gets the highest version of extension bundle v3 supported.
/// </summary>
internal string MaximumBundleV3Version
{
get
{
return GetFeature(ScriptConstants.MaximumBundleV3Version);
}
}
/// <summary>
/// Gets the highest version of extension bundle v4 supported.
/// </summary>
internal string MaximumBundleV4Version
{
get
{
return GetFeature(ScriptConstants.MaximumBundleV4Version);
}
}
/// <summary>
/// Gets a value indicating whether the host should revert the worker shutdown behavior in the WebHostWorkerChannelManager.
/// </summary>
internal bool RevertWorkerShutdownBehavior
{
get
{
return GetFeature(RpcWorkerConstants.RevertWorkerShutdownBehavior) == "1";
}
}
internal bool ThrowOnMissingFunctionsWorkerRuntime
{
get
{
return GetFeature(RpcWorkerConstants.ThrowOnMissingFunctionsWorkerRuntime) == "1";
}
}
internal bool WorkerRuntimeStrictValidationEnabled
{
get
{
return GetFeatureAsBooleanOrDefault(RpcWorkerConstants.WorkerRuntimeStrictValidationEnabled, false);
}
}
internal bool IsDotNetInProcDisabled
{
get
{
return GetFeatureAsBooleanOrDefault(ScriptConstants.HostingConfigDotNetInProcDisabled, false);
}
}
/// <summary>
/// Gets feature by name.
/// </summary>
/// <param name="name">Feature name.</param>
/// <returns>String value from hosting configuration.</returns>
public string GetFeature(string name)
{
if (_features.TryGetValue(name, out string value))
{
return value;
}
return null;
}
/// <summary>
/// Gets a feature by name, returning the specified default value if not found.
/// </summary>
/// <param name="name">Feature name.</param>
/// <param name="defaultValue">The default value to use.</param>
/// <returns>String value from hosting configuration.</returns>
public string GetFeatureOrDefault(string name, string defaultValue)
{
return GetFeature(name) ?? defaultValue;
}
/// <summary>
/// Gets a feature by name and attempts to parse it into a boolean.
/// Returns "True, False" or ints as booleans. Returns True for any non-zero integer.
/// If none of those (or empty), returns default.
/// </summary>
/// <param name="name">Feature name.</param>
/// <param name="defaultValue">The default value to return if the feature value cannot be parsed into a boolean.</param>
/// <returns>Boolean value if parse-able from hosting configuration. Otherwise, the defaultValue.</returns>
internal bool GetFeatureAsBooleanOrDefault(string name, bool defaultValue)
{
string featureValue = GetFeature(name);
if (string.IsNullOrWhiteSpace(featureValue))
{
return defaultValue;
}
if (bool.TryParse(featureValue, out bool parsedBool))
{
return parsedBool;
}
if (int.TryParse(featureValue, out int parsedInt))
{
return parsedInt != 0;
}
return defaultValue;
}
internal bool CheckInternalAuthAllowList(HttpRequest httpRequest)
{
if (InternalAuthApisAllowList != null && _allowedInternalAuthApis == null)
{
// initialize our cached allow list on demand
_allowedInternalAuthApis = InternalAuthApisAllowList.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries).Select(p => new PathString(p)).ToArray();
}
if (_allowedInternalAuthApis != null)
{
// An allow list is configured, so we ensure that the current request
// matches any of the allowed APIs.
foreach (PathString ps in _allowedInternalAuthApis)
{
if (httpRequest.Path.StartsWithSegments(ps, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
}
// no allow list configured
return true;
}
}
}