Skip to content

Commit 1f8e2cd

Browse files
authored
Merge pull request #5480 from Azure/dev
Merge dev to v3.x
2 parents 12b292c + acfb162 commit 1f8e2cd

File tree

10 files changed

+98
-18
lines changed

10 files changed

+98
-18
lines changed

src/WebJobs.Script.WebHost/Diagnostics/LinuxContainerEventGenerator.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public LinuxContainerEventGenerator(IEnvironment environment, Action<string> wri
3838

3939
public static string DetailsEventRegex { get; } = $"{ScriptConstants.LinuxFunctionDetailsEventStreamName} (?<AppName>[^,]*),(?<FunctionName>[^,]*),\\\\\"(?<InputBindings>.*)\\\\\",\\\\\"(?<OutputBindings>.*)\\\\\",(?<ScriptType>[^,]*),(?<IsDisabled>[0|1])";
4040

41-
public static string AzureMonitorEventRegex { get; } = $"{ScriptConstants.LinuxAzureMonitorEventStreamName} (?<Level>[0-6]),(?<ResourceId>[^,]*),(?<OperationName>[^,]*),(?<Category>[^,]*),(?<RegionName>[^,]*),(?<Properties>[^,]*),(?<ContainerName>[^,\"]*),(?<TenantId>[^,\"]*),(?<EventTimestamp>[^,]+)";
41+
public static string AzureMonitorEventRegex { get; } = $"{ScriptConstants.LinuxAzureMonitorEventStreamName} (?<Level>[0-6]),(?<ResourceId>[^,]*),(?<OperationName>[^,]*),(?<Category>[^,]*),(?<RegionName>[^,]*),\"(?<Properties>[^,]*)\",(?<ContainerName>[^,\"]*),(?<TenantId>[^,\"]*),(?<EventTimestamp>[^,]+)";
4242

4343
private string StampName
4444
{
@@ -104,7 +104,7 @@ private void ConsoleWriter(string evt)
104104

105105
public override void LogAzureMonitorDiagnosticLogEvent(LogLevel level, string resourceId, string operationName, string category, string regionName, string properties)
106106
{
107-
_writeEvent($"{ScriptConstants.LinuxAzureMonitorEventStreamName} {(int)ToEventLevel(level)},{resourceId},{operationName},{category},{regionName},{properties},{_containerName},{TenantId}, {DateTime.UtcNow.ToString()}");
107+
_writeEvent($"{ScriptConstants.LinuxAzureMonitorEventStreamName} {(int)ToEventLevel(level)},{resourceId},{operationName},{category},{regionName},{NormalizeString(properties)},{_containerName},{TenantId},{DateTime.UtcNow.ToString()}");
108108
}
109109
}
110110
}

src/WebJobs.Script/Extensions/HttpRequestExtensions.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Collections.Generic;
66
using System.Linq;
77
using System.Net.Http.Headers;
8+
using System.Security.Claims;
89
using System.Threading.Tasks;
910
using Microsoft.AspNetCore.Http;
1011
using Microsoft.AspNetCore.Http.Extensions;
@@ -110,7 +111,7 @@ public static bool IsMediaTypeOctetOrMultipart(this HttpRequest request)
110111
public static async Task<JObject> GetRequestAsJObject(this HttpRequest request)
111112
{
112113
var jObjectHttp = new JObject();
113-
jObjectHttp["Url"] = $"{(request.IsHttps ? "https" : "http")}://{request.Host.ToString()}{request.Path.ToString()}{request.QueryString.ToString()}"; // [http|https]://{url}{path}{query}
114+
jObjectHttp["Url"] = $"{(request.IsHttps ? "https" : "http")}://{request.Host.ToString()}{request.Path.ToString()}{request.QueryString.ToString()}";
114115
jObjectHttp["Method"] = request.Method.ToString();
115116
if (request.Query != null)
116117
{
@@ -131,7 +132,7 @@ public static async Task<JObject> GetRequestAsJObject(this HttpRequest request)
131132

132133
if (request.HttpContext?.User?.Identities != null)
133134
{
134-
jObjectHttp["Identities"] = JsonConvert.SerializeObject(request.HttpContext.User.Identities);
135+
jObjectHttp["Identities"] = GetUserIdentitiesAsString(request.HttpContext.User.Identities);
135136
}
136137

137138
// parse request body as content-type
@@ -165,5 +166,14 @@ internal static IDictionary<string, string> GetQueryCollectionAsDictionary(this
165166
}
166167
return queryParamsDictionary;
167168
}
169+
170+
internal static string GetUserIdentitiesAsString(IEnumerable<ClaimsIdentity> claimsIdentities)
171+
{
172+
return JsonConvert.SerializeObject(claimsIdentities, new JsonSerializerSettings
173+
{
174+
// Claims property in Identities had circular reference to property 'Subject'
175+
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
176+
});
177+
}
168178
}
169179
}

src/WebJobs.Script/Host/FunctionMetadataManager.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,17 @@ namespace Microsoft.Azure.WebJobs.Script
1818
public class FunctionMetadataManager : IFunctionMetadataManager
1919
{
2020
private const string _functionConfigurationErrorMessage = "Unable to determine the primary function script.Make sure atleast one script file is present.Try renaming your entry point script to 'run' or alternatively you can specify the name of the entry point script explicitly by adding a 'scriptFile' property to your function metadata.";
21-
private readonly IEnumerable<RpcWorkerConfig> _workerConfigs;
2221
private readonly bool _isHttpWorker;
2322
private readonly Lazy<ImmutableArray<FunctionMetadata>> _functionMetadataArray;
2423
private readonly IOptions<ScriptJobHostOptions> _scriptOptions;
2524
private readonly IFunctionMetadataProvider _functionMetadataProvider;
2625
private readonly ILogger _logger;
2726
private Dictionary<string, ICollection<string>> _functionErrors = new Dictionary<string, ICollection<string>>();
2827

29-
public FunctionMetadataManager(IOptions<ScriptJobHostOptions> scriptOptions, IFunctionMetadataProvider functionMetadataProvider, IOptions<LanguageWorkerOptions> languageWorkerOptions, IOptions<HttpWorkerOptions> httpWorkerOptions, ILoggerFactory loggerFactory)
28+
public FunctionMetadataManager(IOptions<ScriptJobHostOptions> scriptOptions, IFunctionMetadataProvider functionMetadataProvider, IOptions<HttpWorkerOptions> httpWorkerOptions, ILoggerFactory loggerFactory)
3029
{
3130
_scriptOptions = scriptOptions;
3231
_functionMetadataProvider = functionMetadataProvider;
33-
_workerConfigs = languageWorkerOptions.Value.WorkerConfigs;
3432
_logger = loggerFactory.CreateLogger(LogCategories.Startup);
3533
_functionMetadataArray = new Lazy<ImmutableArray<FunctionMetadata>>(LoadFunctionMetadata);
3634
_isHttpWorker = httpWorkerOptions.Value.Description != null;

src/WebJobs.Script/Utility.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,11 @@ internal static string GetWorkerRuntime(IEnumerable<FunctionMetadata> functions)
585585
{
586586
var functionsListWithoutProxies = functions?.Where(f => f.IsProxy == false);
587587
string functionLanguage = functionsListWithoutProxies.FirstOrDefault()?.Language;
588+
if (string.IsNullOrEmpty(functionLanguage))
589+
{
590+
return null;
591+
}
592+
588593
if (IsDotNetLanguageFunction(functionLanguage))
589594
{
590595
return RpcWorkerConstants.DotNetLanguageWorkerName;
@@ -604,7 +609,7 @@ internal static bool IsFunctionMetadataLanguageSupportedByWorkerRuntime(Function
604609
{
605610
return true;
606611
}
607-
return functionMetadata.Language.Equals(workerRuntime, StringComparison.OrdinalIgnoreCase);
612+
return !string.IsNullOrEmpty(functionMetadata.Language) && functionMetadata.Language.Equals(workerRuntime, StringComparison.OrdinalIgnoreCase);
608613
}
609614

610615
public static bool IsDotNetLanguageFunction(string functionLanguage)
@@ -625,7 +630,7 @@ private static bool ContainsFunctionWithWorkerRuntime(IEnumerable<FunctionMetada
625630
}
626631
if (functions != null && functions.Any())
627632
{
628-
return functions.Any(f => f.Language.Equals(workerRuntime, StringComparison.OrdinalIgnoreCase));
633+
return functions.Any(f => !string.IsNullOrEmpty(f.Language) && f.Language.Equals(workerRuntime, StringComparison.OrdinalIgnoreCase));
629634
}
630635
return false;
631636
}

src/WebJobs.Script/Workers/Rpc/Configuration/RpcWorkerConfigFactory.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ internal void AddProvider(string workerDir)
143143
workerDescription.FormatWorkerPathIfNeeded(_systemRuntimeInformation, _environment, _logger);
144144
workerDescription.ThrowIfDefaultWorkerPathNotExists();
145145
_workerDescripionDictionary[workerDescription.Language] = workerDescription;
146+
_logger.LogDebug($"Added WorkerConfig for language: {workerDescription.Language}");
146147
}
147148
}
148149
catch (Exception ex)
@@ -226,6 +227,11 @@ internal string GetExecutablePathForJava(string defaultExecutablePath)
226227
internal bool ShouldAddWorkerConfig(string workerDescriptionLanguage)
227228
{
228229
string workerRuntime = _environment.GetEnvironmentVariable(RpcWorkerConstants.FunctionWorkerRuntimeSettingName);
230+
if (_environment.IsPlaceholderModeEnabled())
231+
{
232+
return true;
233+
}
234+
229235
if (!string.IsNullOrEmpty(workerRuntime))
230236
{
231237
_logger.LogDebug($"EnvironmentVariable {RpcWorkerConstants.FunctionWorkerRuntimeSettingName}: {workerRuntime}");

test/WebJobs.Script.Tests/Diagnostics/LinuxContainerEventGeneratorTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ public void ParseAzureMonitoringEvents(LogLevel level, string resourceId, string
214214
p => Assert.Equal(operationName, p),
215215
p => Assert.Equal(category, p),
216216
p => Assert.Equal(regionName, p),
217-
p => Assert.Equal(properties, p),
217+
p => Assert.Equal(properties, UnNormalize(p)),
218218
p => Assert.Equal(_containerName.ToUpperInvariant(), p),
219219
p => Assert.Equal(_tenantId, p),
220220
p => Assert.True(DateTime.TryParse(p, out DateTime dt)));

test/WebJobs.Script.Tests/Extensions/HttpRequestExtensionsTest.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Security.Claims;
7+
using System.Security.Principal;
68
using System.Text;
79
using Microsoft.AspNetCore.Http;
810
using Microsoft.Azure.WebJobs.Script.Config;
@@ -39,5 +41,27 @@ public void IsAppServiceInternalRequest_ReturnsExpectedResult()
3941
Assert.True(request.IsAppServiceInternalRequest());
4042
}
4143
}
44+
45+
[Fact]
46+
public void ConvertUserIdentitiesToString_RemovesCircularReference()
47+
{
48+
string expectedUserIdentities = "[{\"AuthenticationType\":\"TestAuthType\",\"IsAuthenticated\":true";
49+
IIdentity identity = new TestIdentity();
50+
Claim claim = new Claim("authlevel", "admin", "test", "LOCAL AUTHORITY", "LOCAL AUTHORITY");
51+
List<Claim> claims = new List<Claim>() { claim };
52+
ClaimsIdentity claimsIdentity = new ClaimsIdentity(identity, claims);
53+
List<ClaimsIdentity> claimsIdentities = new List<ClaimsIdentity>() { claimsIdentity };
54+
string userIdentitiesString = HttpRequestExtensions.GetUserIdentitiesAsString(claimsIdentities);
55+
Assert.Contains(expectedUserIdentities, userIdentitiesString);
56+
}
57+
}
58+
59+
internal class TestIdentity : IIdentity
60+
{
61+
public string AuthenticationType => "TestAuthType";
62+
63+
public bool IsAuthenticated => true;
64+
65+
public string Name => "TestIdentityName";
4266
}
4367
}

test/WebJobs.Script.Tests/FunctionMetadataManagerTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public FunctionMetadataManagerTests()
2929
string functionsPath = Path.Combine(Environment.CurrentDirectory, @"..\..\..\..\..\sample\node");
3030
_defaultHttpWorkerOptions = new HttpWorkerOptions();
3131
_scriptJobHostOptions.RootScriptPath = functionsPath;
32-
_testFunctionMetadataManager = new FunctionMetadataManager(new OptionsWrapper<ScriptJobHostOptions>(_scriptJobHostOptions), _mockFunctionMetadataProvider.Object, new OptionsWrapper<LanguageWorkerOptions>(GetTestLanguageWorkerOptions()), new OptionsWrapper<HttpWorkerOptions>(_defaultHttpWorkerOptions), MockNullLoggerFactory.CreateLoggerFactory());
32+
_testFunctionMetadataManager = new FunctionMetadataManager(new OptionsWrapper<ScriptJobHostOptions>(_scriptJobHostOptions), _mockFunctionMetadataProvider.Object, new OptionsWrapper<HttpWorkerOptions>(_defaultHttpWorkerOptions), MockNullLoggerFactory.CreateLoggerFactory());
3333
}
3434

3535
[Theory]
@@ -54,7 +54,7 @@ public void FunctionMetadataManager_Verify_FunctionErrors(string scriptFile)
5454
mockFunctionMetadataProvider.Setup(m => m.GetFunctionMetadata(false)).Returns(functionMetadataCollection.ToImmutableArray());
5555
mockFunctionMetadataProvider.Setup(m => m.FunctionErrors).Returns(mockFunctionErrors);
5656

57-
FunctionMetadataManager testFunctionMetadataManager = new FunctionMetadataManager(new OptionsWrapper<ScriptJobHostOptions>(_scriptJobHostOptions), mockFunctionMetadataProvider.Object, new OptionsWrapper<LanguageWorkerOptions>(GetTestLanguageWorkerOptions()), new OptionsWrapper<HttpWorkerOptions>(_defaultHttpWorkerOptions), MockNullLoggerFactory.CreateLoggerFactory());
57+
FunctionMetadataManager testFunctionMetadataManager = new FunctionMetadataManager(new OptionsWrapper<ScriptJobHostOptions>(_scriptJobHostOptions), mockFunctionMetadataProvider.Object, new OptionsWrapper<HttpWorkerOptions>(_defaultHttpWorkerOptions), MockNullLoggerFactory.CreateLoggerFactory());
5858

5959
var validatedFunctionMetadataArray = testFunctionMetadataManager.LoadFunctionMetadata();
6060
Assert.Empty(validatedFunctionMetadataArray);
@@ -71,7 +71,7 @@ public void FunctionMetadataManager_Verify_FunctionErrors(string scriptFile)
7171
public void IsScriptFileDetermined_ScriptFile_Emtpy_HttpWorker_Returns_True(string scriptFile)
7272
{
7373
FunctionMetadata functionMetadata = GetTestFunctionMetadata(scriptFile);
74-
FunctionMetadataManager testFunctionMetadataManager = new FunctionMetadataManager(new OptionsWrapper<ScriptJobHostOptions>(_scriptJobHostOptions), _mockFunctionMetadataProvider.Object, new OptionsWrapper<LanguageWorkerOptions>(GetTestLanguageWorkerOptions()), new OptionsWrapper<HttpWorkerOptions>(GetTestHttpWorkerOptions()), MockNullLoggerFactory.CreateLoggerFactory());
74+
FunctionMetadataManager testFunctionMetadataManager = new FunctionMetadataManager(new OptionsWrapper<ScriptJobHostOptions>(_scriptJobHostOptions), _mockFunctionMetadataProvider.Object, new OptionsWrapper<HttpWorkerOptions>(GetTestHttpWorkerOptions()), MockNullLoggerFactory.CreateLoggerFactory());
7575

7676
Assert.True(testFunctionMetadataManager.IsScriptFileDetermined(functionMetadata));
7777
}

test/WebJobs.Script.Tests/ScriptHostTests.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,37 @@ public void IsSupportedRuntime_Returns_True()
914914
Assert.True(Utility.IsSupportedRuntime(RpcWorkerConstants.NodeLanguageWorkerName, TestHelpers.GetTestWorkerConfigs()));
915915
}
916916

917+
[Fact]
918+
public void GetWorkerRuntime_Returns_null()
919+
{
920+
FunctionMetadata funcJs1 = new FunctionMetadata()
921+
{
922+
Name = "funcJs1",
923+
Language = "node"
924+
};
925+
FunctionMetadata funcPython1 = new FunctionMetadata()
926+
{
927+
Name = "funcPython1",
928+
Language = null,
929+
};
930+
IEnumerable<FunctionMetadata> functionsList = new Collection<FunctionMetadata>()
931+
{
932+
funcJs1, funcPython1
933+
};
934+
string actualRuntime = Utility.GetWorkerRuntime(functionsList);
935+
Assert.Equal(null, actualRuntime);
936+
937+
FunctionMetadata funcLanguageNull = new FunctionMetadata()
938+
{
939+
Name = "func"
940+
};
941+
functionsList = new Collection<FunctionMetadata>()
942+
{
943+
funcJs1, funcPython1, funcLanguageNull
944+
};
945+
Assert.Equal(null, actualRuntime);
946+
}
947+
917948
[Theory]
918949
[InlineData("CSharp")]
919950
[InlineData("DotNetAssembly")]

test/WebJobs.Script.Tests/Workers/Rpc/RpcWorkerConfigFactoryTests.cs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -223,12 +223,18 @@ public void AddArgumentsFromAppSettings_JavaOpts(string expectedArgument, string
223223
}
224224

225225
[Theory]
226-
[InlineData("python", "Python", true)]
227-
[InlineData("python", "NOde", false)]
228-
[InlineData("python", "", true)]
229-
[InlineData("python", null, true)]
230-
public void ShouldAddProvider_Returns_Expected(string workerLanguage, string workerRuntime, bool expectedResult)
226+
[InlineData("python", "Python", false, true)]
227+
[InlineData("python", "NOde", false, false)]
228+
[InlineData("python", "", false, true)]
229+
[InlineData("python", null, false, true)]
230+
[InlineData("python", "NOde", true, true)]
231+
[InlineData("python", null, true, true)]
232+
public void ShouldAddProvider_Returns_Expected(string workerLanguage, string workerRuntime, bool placeholderMode, bool expectedResult)
231233
{
234+
if (placeholderMode)
235+
{
236+
_testEnvironment.SetEnvironmentVariable(EnvironmentSettingNames.AzureWebsitePlaceholderMode, "1");
237+
}
232238
var expectedWorkersDir = Path.Combine(Path.GetDirectoryName(new Uri(typeof(RpcWorkerConfigFactory).Assembly.CodeBase).LocalPath), RpcWorkerConstants.DefaultWorkersDirectoryName);
233239
var config = new ConfigurationBuilder().Build();
234240
var testLogger = new TestLogger("test");

0 commit comments

Comments
 (0)