Skip to content

Commit c9609a3

Browse files
authored
Enabling Admin Isolation for Flex Consumption (#11369)
1 parent ef5cc7c commit c9609a3

File tree

3 files changed

+74
-72
lines changed

3 files changed

+74
-72
lines changed

src/WebJobs.Script/Extensions/HttpRequestExtensions.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ public static TValue GetItemOrDefault<TValue>(this HttpRequest request, string k
7878
public static bool IsAppServiceInternalRequest(this HttpRequest request, IEnvironment environment = null)
7979
{
8080
environment = GetEnvironment(request, environment);
81-
if (!environment.IsAppService())
81+
82+
if (!FrontEndRoutingEnsured(environment))
8283
{
8384
return false;
8485
}
@@ -92,7 +93,8 @@ public static bool IsAppServiceInternalRequest(this HttpRequest request, IEnviro
9293
public static bool IsPlatformInternalRequest(this HttpRequest request, IEnvironment environment = null)
9394
{
9495
environment = GetEnvironment(request, environment);
95-
if (!environment.IsAppService())
96+
97+
if (!FrontEndRoutingEnsured(environment))
9698
{
9799
return false;
98100
}
@@ -102,6 +104,13 @@ public static bool IsPlatformInternalRequest(this HttpRequest request, IEnvironm
102104
return string.Compare(value, "true", StringComparison.OrdinalIgnoreCase) == 0;
103105
}
104106

107+
private static bool FrontEndRoutingEnsured(this IEnvironment environment)
108+
{
109+
// Verify we're running on a sku that ensures all requests go through the
110+
// Antares Front End.
111+
return environment.IsAppService() || environment.IsFlexConsumptionSku();
112+
}
113+
105114
private static IEnvironment GetEnvironment(HttpRequest request, IEnvironment environment = null)
106115
{
107116
return environment ?? request.HttpContext.RequestServices?.GetService<IEnvironment>() ?? SystemEnvironment.Instance;

test/WebJobs.Script.Tests.Integration/WebHostEndToEnd/SamplesEndToEndTests_CSharp.cs

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -211,24 +211,31 @@ public async Task ExtensionWebHook_Succeeds()
211211

212212
[Theory]
213213
[Trait(TestTraits.Group, TestTraits.AdminIsolationTests)]
214-
[InlineData("admin/host/status", true, true, false, false, true, HttpStatusCode.Forbidden)]
215-
[InlineData("admin/host/status", true, true, true, false, false, HttpStatusCode.Unauthorized)]
216-
[InlineData("admin/host/status", true, true, true, true, true, HttpStatusCode.OK)]
217-
[InlineData("admin/host/status", true, false, false, false, true, HttpStatusCode.OK)]
218-
[InlineData("admin/host/status", true, false, false, true, true, HttpStatusCode.OK)]
219-
[InlineData("admin/host/status", true, true, true, false, true, HttpStatusCode.OK)]
220-
[InlineData("admin/host/status", false, true, false, true, true, HttpStatusCode.Forbidden)]
221-
[InlineData("admin/host/extensionBundle/v1/templates", true, true, false, true, false, HttpStatusCode.Unauthorized)]
222-
[InlineData("admin/host/extensionBundle/v1/templates", true, true, true, false, true, HttpStatusCode.NotFound)]
223-
[InlineData("admin/host/extensionBundle/v1/templates", true, false, false, false, true, HttpStatusCode.NotFound)]
224-
[InlineData("admin/host/extensionBundle/v1/templates", true, true, false, true, true, HttpStatusCode.NotFound)]
225-
[InlineData("admin/vfs/host.json", true, true, true, false, true, HttpStatusCode.OK)]
226-
[InlineData("admin/vfs/host.json", true, true, false, false, true, HttpStatusCode.Unauthorized)]
227-
[InlineData("admin/vfs/host.json", true, true, true, false, false, HttpStatusCode.Unauthorized)]
228-
public async Task AdminIsolation_ReturnsExpectedStatus(string uri, bool isAppService, bool enableIsolation, bool isPlatformInternal, bool bypassFE, bool addAuthKey, HttpStatusCode expectedStatus)
214+
[InlineData("admin/host/status", ScriptConstants.DynamicSku, "1", true, false, false, true, HttpStatusCode.Forbidden)]
215+
[InlineData("admin/host/status", ScriptConstants.DynamicSku, "1", true, true, false, false, HttpStatusCode.Unauthorized)]
216+
[InlineData("admin/host/status", ScriptConstants.DynamicSku, "1", true, true, true, true, HttpStatusCode.OK)]
217+
[InlineData("admin/host/status", ScriptConstants.DynamicSku, "1", false, false, false, true, HttpStatusCode.OK)]
218+
[InlineData("admin/host/status", ScriptConstants.DynamicSku, "1", false, false, true, true, HttpStatusCode.OK)]
219+
[InlineData("admin/host/status", ScriptConstants.DynamicSku, "1", true, true, false, true, HttpStatusCode.OK)]
220+
[InlineData("admin/host/status", ScriptConstants.DynamicSku, null, true, false, true, true, HttpStatusCode.Forbidden)]
221+
[InlineData("admin/host/extensionBundle/v1/templates", ScriptConstants.DynamicSku, "1", true, false, true, false, HttpStatusCode.Unauthorized)]
222+
[InlineData("admin/host/extensionBundle/v1/templates", ScriptConstants.DynamicSku, "1", true, true, false, true, HttpStatusCode.NotFound)]
223+
[InlineData("admin/host/extensionBundle/v1/templates", ScriptConstants.DynamicSku, "1", false, false, false, true, HttpStatusCode.NotFound)]
224+
[InlineData("admin/host/extensionBundle/v1/templates", ScriptConstants.DynamicSku, "1", true, false, true, true, HttpStatusCode.NotFound)]
225+
[InlineData("admin/vfs/host.json", ScriptConstants.DynamicSku, "1", true, true, false, true, HttpStatusCode.OK)]
226+
[InlineData("admin/vfs/host.json", ScriptConstants.DynamicSku, "1", true, false, false, true, HttpStatusCode.Unauthorized)]
227+
[InlineData("admin/vfs/host.json", ScriptConstants.DynamicSku, "1", true, true, false, false, HttpStatusCode.Unauthorized)]
228+
[InlineData("admin/host/status", ScriptConstants.FlexConsumptionSku, null, true, true, false, true, HttpStatusCode.OK)]
229+
[InlineData("admin/host/status", ScriptConstants.FlexConsumptionSku, null, true, false, true, true, HttpStatusCode.OK)]
230+
[InlineData("admin/host/status", ScriptConstants.FlexConsumptionSku, null, true, false, false, true, HttpStatusCode.Forbidden)]
231+
[InlineData("admin/host/status", ScriptConstants.FlexConsumptionSku, null, true, false, true, false, HttpStatusCode.Unauthorized)]
232+
public async Task AdminIsolation_ReturnsExpectedStatus(string uri, string sku, string websiteInstanceId, bool enableIsolation, bool isPlatformInternal, bool bypassFE, bool addAuthKey, HttpStatusCode expectedStatus)
229233
{
230234
var environment = this._fixture.Host.WebHostServices.GetService<IEnvironment>();
231-
string websiteInstanceId = environment.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteInstanceId);
235+
string originalWebsiteInstanceId = environment.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteInstanceId);
236+
237+
environment.SetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteSku, sku);
238+
environment.SetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteInstanceId, websiteInstanceId);
232239

233240
try
234241
{
@@ -238,16 +245,6 @@ public async Task AdminIsolation_ReturnsExpectedStatus(string uri, bool isAppSer
238245
Assert.True(environment.IsAdminIsolationEnabled());
239246
}
240247

241-
if (!isAppService)
242-
{
243-
environment.SetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteInstanceId, null);
244-
Assert.False(environment.IsAppService());
245-
}
246-
else
247-
{
248-
Assert.True(environment.IsAppService());
249-
}
250-
251248
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri);
252249

253250
if (addAuthKey)
@@ -274,7 +271,7 @@ public async Task AdminIsolation_ReturnsExpectedStatus(string uri, bool isAppSer
274271
finally
275272
{
276273
environment.SetEnvironmentVariable(EnvironmentSettingNames.FunctionsAdminIsolationEnabled, null);
277-
environment.SetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteInstanceId, websiteInstanceId);
274+
environment.SetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteInstanceId, originalWebsiteInstanceId);
278275
}
279276
}
280277

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

Lines changed: 39 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -20,77 +20,73 @@ namespace Microsoft.Azure.WebJobs.Script.Tests.Extensions
2020
{
2121
public class HttpRequestExtensionsTest
2222
{
23-
[Fact]
23+
[Theory]
2424
[Trait(TestTraits.Group, TestTraits.AdminIsolationTests)]
25-
public void IsPlatformInternalRequest_ReturnsExpectedResult()
25+
[InlineData(ScriptConstants.DynamicSku, null, "True", false)]
26+
[InlineData(ScriptConstants.DynamicSku, "1", "True", true)]
27+
[InlineData(ScriptConstants.DynamicSku, "1", "true", true)]
28+
[InlineData(ScriptConstants.DynamicSku, "1", "False", false)]
29+
[InlineData(ScriptConstants.DynamicSku, "1", null, false)]
30+
[InlineData(ScriptConstants.FlexConsumptionSku, null, "True", true)]
31+
[InlineData(ScriptConstants.FlexConsumptionSku, null, null, false)]
32+
public void IsPlatformInternalRequest_ReturnsExpectedResult(string sku, string websiteInstanceId, string platformInternalHeaderValue, bool expected)
2633
{
27-
// not running under Azure
28-
TestEnvironment testEnvironment = new TestEnvironment();
29-
var request = HttpTestHelpers.CreateHttpRequest("GET", "http://foobar");
30-
Assert.False(request.IsPlatformInternalRequest(testEnvironment));
31-
32-
// running under Azure
3334
var vars = new Dictionary<string, string>
3435
{
35-
{ EnvironmentSettingNames.AzureWebsiteInstanceId, "123" }
36+
{ EnvironmentSettingNames.AzureWebsiteInstanceId, websiteInstanceId },
37+
{ EnvironmentSettingNames.AzureWebsiteSku, sku }
3638
};
3739
using (var env = new TestScopedEnvironmentVariable(vars))
3840
{
3941
var environment = SystemEnvironment.Instance;
40-
Assert.True(environment.IsAppService());
4142

4243
var headers = new HeaderDictionary();
43-
request = HttpTestHelpers.CreateHttpRequest("GET", "http://foobar", headers);
44-
Assert.False(request.IsPlatformInternalRequest(testEnvironment));
44+
headers.Add(ScriptConstants.AntaresPlatformInternal, platformInternalHeaderValue);
4545

46-
headers.Clear();
47-
headers.Add(ScriptConstants.AntaresPlatformInternal, "False");
48-
request = HttpTestHelpers.CreateHttpRequest("GET", "http://foobar", headers);
49-
Assert.False(request.IsPlatformInternalRequest(environment));
50-
51-
headers.Clear();
52-
headers.Add(ScriptConstants.AntaresPlatformInternal, "True");
53-
request = HttpTestHelpers.CreateHttpRequest("GET", "http://foobar", headers);
54-
Assert.True(request.IsPlatformInternalRequest(environment));
55-
56-
headers.Clear();
57-
headers.Add(ScriptConstants.AntaresPlatformInternal, "true");
58-
request = HttpTestHelpers.CreateHttpRequest("GET", "http://foobar", headers);
59-
Assert.True(request.IsPlatformInternalRequest(environment));
46+
// verify using explicit environment
47+
var request = HttpTestHelpers.CreateHttpRequest("GET", "http://foobar", headers);
48+
Assert.Equal(expected, request.IsPlatformInternalRequest(environment));
6049

61-
headers.Clear();
62-
headers.Add(ScriptConstants.AntaresPlatformInternal, "True");
50+
// verify using request services environment
6351
request = HttpTestHelpers.CreateHttpRequest("GET", "http://foobar", headers);
6452
var servicesMock = new Mock<IServiceProvider>();
6553
servicesMock.Setup(s => s.GetService(typeof(IEnvironment))).Returns(environment);
6654
request.HttpContext.RequestServices = servicesMock.Object;
67-
Assert.True(request.IsPlatformInternalRequest());
55+
Assert.Equal(expected, request.IsPlatformInternalRequest());
6856
}
6957
}
7058

71-
[Fact]
72-
public void IsAppServiceInternalRequest_ReturnsExpectedResult()
59+
[Theory]
60+
[InlineData(ScriptConstants.DynamicSku, true, true, false)]
61+
[InlineData(ScriptConstants.DynamicSku, true, false, true)]
62+
[InlineData(ScriptConstants.DynamicSku, false, true, false)]
63+
[InlineData(ScriptConstants.DynamicSku, false, false, false)]
64+
[InlineData(ScriptConstants.FlexConsumptionSku, false, true, false)]
65+
[InlineData(ScriptConstants.FlexConsumptionSku, false, false, true)]
66+
public void IsAppServiceInternalRequest_ReturnsExpectedResult(string sku, bool includeWebsiteInstanceId, bool includeLogIdHeader, bool expected)
7367
{
74-
// not running under Azure
7568
var request = HttpTestHelpers.CreateHttpRequest("GET", "http://foobar");
76-
Assert.False(request.IsAppServiceInternalRequest());
7769

78-
// running under Azure
79-
var vars = new Dictionary<string, string>
70+
var vars = new Dictionary<string, string>();
71+
vars.Add(EnvironmentSettingNames.AzureWebsiteSku, sku);
72+
if (includeWebsiteInstanceId)
8073
{
81-
{ EnvironmentSettingNames.AzureWebsiteInstanceId, "123" }
82-
};
74+
// container running in App Service
75+
vars.Add(EnvironmentSettingNames.AzureWebsiteInstanceId, "123");
76+
}
77+
8378
using (var env = new TestScopedEnvironmentVariable(vars))
8479
{
85-
// with header
8680
var headers = new HeaderDictionary();
87-
headers.Add(ScriptConstants.AntaresLogIdHeaderName, "123");
8881

89-
request = HttpTestHelpers.CreateHttpRequest("GET", "http://foobar", headers);
90-
Assert.False(request.IsAppServiceInternalRequest());
82+
if (includeLogIdHeader)
83+
{
84+
// include the FE log id header
85+
headers.Add(ScriptConstants.AntaresLogIdHeaderName, "123");
86+
}
9187

92-
request = HttpTestHelpers.CreateHttpRequest("GET", "http://foobar");
93-
Assert.True(request.IsAppServiceInternalRequest());
88+
request = HttpTestHelpers.CreateHttpRequest("GET", "http://foobar", headers);
89+
Assert.Equal(expected, request.IsAppServiceInternalRequest());
9490
}
9591
}
9692

0 commit comments

Comments
 (0)