Skip to content

Commit 6015892

Browse files
authored
Removing obsolete auth policy (#11335)
1 parent bb09888 commit 6015892

File tree

10 files changed

+24
-204
lines changed

10 files changed

+24
-204
lines changed

src/WebJobs.Script.WebHost/Controllers/HostController.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public HostController(IOptions<ScriptApplicationHostOptions> applicationHostOpti
6868

6969
[HttpGet]
7070
[Route("admin/host/status")]
71-
[Authorize(Policy = PolicyNames.AdminAuthLevelOrInternal)]
71+
[Authorize(Policy = PolicyNames.AdminAuthLevel)]
7272
[TypeFilter(typeof(EnableDebugModeFilter))]
7373
public async Task<IActionResult> GetHostStatus([FromServices] IScriptHostManager scriptHostManager, [FromServices] IHostIdProvider hostIdProvider, [FromServices] IServiceProvider serviceProvider = null)
7474
{
@@ -120,7 +120,7 @@ public async Task<IActionResult> GetHostStatus([FromServices] IScriptHostManager
120120
/// </summary>
121121
[HttpGet]
122122
[Route("admin/host/processes")]
123-
[Authorize(Policy = PolicyNames.AdminAuthLevelOrInternal)]
123+
[Authorize(Policy = PolicyNames.AdminAuthLevel)]
124124
public async Task<IActionResult> GetWorkerProcesses([FromServices] IScriptHostManager scriptHostManager)
125125
{
126126
if (!Utility.TryGetHostService(scriptHostManager, out IWebHostRpcWorkerChannelManager webHostLanguageWorkerChannelManager))
@@ -186,7 +186,7 @@ public async Task<IActionResult> GetWorkerProcesses([FromServices] IScriptHostMa
186186

187187
[HttpPost]
188188
[Route("admin/host/drain")]
189-
[Authorize(Policy = PolicyNames.AdminAuthLevelOrInternal)]
189+
[Authorize(Policy = PolicyNames.AdminAuthLevel)]
190190
public async Task<IActionResult> Drain([FromServices] IScriptHostManager scriptHostManager, CancellationToken cancellation)
191191
{
192192
_logger.LogDebug("Received request to drain the host");
@@ -224,7 +224,7 @@ public async Task<IActionResult> Drain([FromServices] IScriptHostManager scriptH
224224

225225
[HttpGet]
226226
[Route("admin/host/drain/status")]
227-
[Authorize(Policy = PolicyNames.AdminAuthLevelOrInternal)]
227+
[Authorize(Policy = PolicyNames.AdminAuthLevel)]
228228
public IActionResult DrainStatus([FromServices] IScriptHostManager scriptHostManager)
229229
{
230230
if (Utility.TryGetHostService(scriptHostManager, out IFunctionActivityStatusProvider functionActivityStatusProvider) &&
@@ -258,7 +258,7 @@ public IActionResult DrainStatus([FromServices] IScriptHostManager scriptHostMan
258258

259259
[HttpPost]
260260
[Route("admin/host/resume")]
261-
[Authorize(Policy = PolicyNames.AdminAuthLevelOrInternal)]
261+
[Authorize(Policy = PolicyNames.AdminAuthLevel)]
262262
public async Task<IActionResult> Resume([FromServices] IScriptHostManager scriptHostManager, CancellationToken cancellation)
263263
{
264264
try
@@ -326,7 +326,7 @@ public async Task<IActionResult> Ping([FromServices] IScriptHostManager scriptHo
326326

327327
[HttpPost]
328328
[Route("admin/host/scale/status")]
329-
[Authorize(Policy = PolicyNames.AdminAuthLevelOrInternal)]
329+
[Authorize(Policy = PolicyNames.AdminAuthLevel)]
330330
[ResponseCache(NoStore = true, Location = ResponseCacheLocation.None)]
331331
[RequiresRunningHost]
332332
public async Task<IActionResult> GetScaleStatus([FromBody] ScaleStatusContext context, [FromServices] IScriptHostManager scriptHostManager)
@@ -355,7 +355,7 @@ public async Task<IActionResult> GetScaleStatus([FromBody] ScaleStatusContext co
355355

356356
[HttpPost]
357357
[Route("admin/host/log")]
358-
[Authorize(Policy = PolicyNames.AdminAuthLevelOrInternal)]
358+
[Authorize(Policy = PolicyNames.AdminAuthLevel)]
359359
public IActionResult Log([FromBody] IEnumerable<HostLogEntry> logEntries)
360360
{
361361
if (logEntries == null)
@@ -406,7 +406,7 @@ public IActionResult LaunchDebugger()
406406

407407
[HttpPost]
408408
[Route("admin/host/synctriggers")]
409-
[Authorize(Policy = PolicyNames.AdminAuthLevelOrInternal)]
409+
[Authorize(Policy = PolicyNames.AdminAuthLevel)]
410410
[RequiresRunningHost]
411411
public async Task<IActionResult> SyncTriggers()
412412
{
@@ -513,7 +513,7 @@ public async Task<IActionResult> ExtensionWebHookHandler(string extensionName, C
513513

514514
[HttpGet]
515515
[Route("admin/host/config")]
516-
[Authorize(Policy = PolicyNames.AdminAuthLevelOrInternal)]
516+
[Authorize(Policy = PolicyNames.AdminAuthLevel)]
517517
[RequiresRunningHost]
518518
public IActionResult GetConfig([FromServices] IScriptHostManager scriptHostManager)
519519
{

src/WebJobs.Script.WebHost/Middleware/VirtualFileSystemMiddleware.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ private async Task<bool> AuthenticateAndAuthorize(HttpContext context)
104104
var authorizationPolicyProvider = context.RequestServices.GetRequiredService<IAuthorizationPolicyProvider>();
105105
var policyEvaluator = context.RequestServices.GetRequiredService<IPolicyEvaluator>();
106106

107-
if (!AuthorizationOptionsExtensions.CheckPlatformInternal(context, allowAppServiceInternal: false))
107+
if (!AuthorizationOptionsExtensions.EnforceAdminIsolation(context, allowAppServiceInternal: false))
108108
{
109109
return false;
110110
}

src/WebJobs.Script.WebHost/Security/Authorization/Policies/AuthorizationOptionsExtensions.cs

Lines changed: 8 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
using Microsoft.Azure.WebJobs.Extensions.Http;
99
using Microsoft.Azure.WebJobs.Script.Extensions;
1010
using Microsoft.Azure.WebJobs.Script.WebHost.Authentication;
11-
using Microsoft.Azure.WebJobs.Script.WebHost.Extensions;
1211
using Microsoft.Extensions.DependencyInjection;
1312

1413
namespace Microsoft.Azure.WebJobs.Script.WebHost.Security.Authorization.Policies
@@ -25,7 +24,7 @@ public static void AddScriptPolicies(this AuthorizationOptions options)
2524
{
2625
if (c.Resource is AuthorizationFilterContext filterContext)
2726
{
28-
if (!CheckPlatformInternal(filterContext.HttpContext, allowAppServiceInternal: false))
27+
if (!EnforceAdminIsolation(filterContext.HttpContext, allowAppServiceInternal: true))
2928
{
3029
return false;
3130
}
@@ -41,47 +40,13 @@ public static void AddScriptPolicies(this AuthorizationOptions options)
4140
p.AddRequirements(new AuthLevelRequirement(AuthorizationLevel.System));
4241
});
4342

44-
options.AddPolicy(PolicyNames.AdminAuthLevelOrInternal, p =>
45-
{
46-
p.AddScriptAuthenticationSchemes();
47-
p.RequireAssertion(async c =>
48-
{
49-
if (c.Resource is AuthorizationFilterContext filterContext)
50-
{
51-
if (!CheckPlatformInternal(filterContext.HttpContext, allowAppServiceInternal: true))
52-
{
53-
return false;
54-
}
55-
56-
if (filterContext.HttpContext.Request.IsAppServiceInternalRequest() &&
57-
filterContext.HttpContext.Request.IsInternalAuthAllowed())
58-
{
59-
return true;
60-
}
61-
62-
var authorizationService = filterContext.HttpContext.RequestServices.GetRequiredService<IAuthorizationService>();
63-
AuthorizationResult result = await authorizationService.AuthorizeAsync(c.User, PolicyNames.AdminAuthLevel);
64-
65-
return result.Succeeded;
66-
}
67-
68-
return false;
69-
});
70-
});
71-
7243
options.AddPolicy(PolicyNames.SystemKeyAuthLevel, p =>
7344
{
7445
p.AddScriptAuthenticationSchemes();
7546
p.RequireAssertion(c =>
7647
{
7748
if (c.Resource is AuthorizationFilterContext filterContext)
7849
{
79-
if (filterContext.HttpContext.Request.IsAppServiceInternalRequest() &&
80-
filterContext.HttpContext.Request.IsInternalAuthAllowed())
81-
{
82-
return true;
83-
}
84-
8550
string keyName = null;
8651
object keyNameObject = filterContext.RouteData.Values["extensionName"];
8752
if (keyNameObject != null)
@@ -114,9 +79,14 @@ private static void AddScriptAuthenticationSchemes(this AuthorizationPolicyBuild
11479
builder.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
11580
}
11681

117-
internal static bool CheckPlatformInternal(HttpContext httpContext, bool allowAppServiceInternal)
82+
/// <summary>
83+
/// When AdminIsolation is enabled, performs platform internal request verification on the specified HTTP context.
84+
/// </summary>
85+
/// <param name="httpContext">The <see cref="HttpContext"/> to check.</param>
86+
/// <param name="allowAppServiceInternal">True if App Service internal requests should also be allowed; otherwise, false.</param>
87+
/// <returns>True if the request passes isolation checks, false otherwise.</returns>
88+
internal static bool EnforceAdminIsolation(HttpContext httpContext, bool allowAppServiceInternal)
11889
{
119-
// when AdminIsolation is enabled, verify the request is platform internal
12090
var environment = httpContext.RequestServices.GetRequiredService<IEnvironment>();
12191
if (environment.IsAdminIsolationEnabled() &&
12292
!(httpContext.Request.IsPlatformInternalRequest(environment) || (allowAppServiceInternal && httpContext.Request.IsAppServiceInternalRequest())))

src/WebJobs.Script.WebHost/Security/Authorization/Policies/PolicyNames.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ namespace Microsoft.Azure.WebJobs.Script.WebHost.Security.Authorization.Policies
1111
public static class PolicyNames
1212
{
1313
public const string AdminAuthLevel = "AuthLevelAdmin";
14-
public const string AdminAuthLevelOrInternal = "InternalAuthLevelAdmin";
1514
public const string SystemAuthLevel = "AuthLevelSystem";
1615
public const string FunctionAuthLevel = "AuthLevelFunction";
1716
public const string SystemKeyAuthLevel = "AuthLevelSystemKey";

src/WebJobs.Script/Config/FunctionsHostingConfigOptions.cs

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,13 @@
33

44
using System;
55
using System.Collections.Generic;
6-
using System.Linq;
7-
using Microsoft.AspNetCore.Http;
86
using Microsoft.Azure.WebJobs.Script.Workers.Rpc;
97

108
namespace Microsoft.Azure.WebJobs.Script.Config
119
{
1210
public class FunctionsHostingConfigOptions
1311
{
1412
private readonly Dictionary<string, string> _features;
15-
private PathString[] _allowedInternalAuthApis;
1613

1714
public FunctionsHostingConfigOptions()
1815
{
@@ -78,24 +75,6 @@ internal bool SwtIssuerEnabled
7875
}
7976
}
8077

81-
/// <summary>
82-
/// Gets or sets a string delimited by '|' that contains a list of admin APIs that are allowed to
83-
/// be invoked internally by platform components.
84-
/// </summary>
85-
internal string InternalAuthApisAllowList
86-
{
87-
get
88-
{
89-
return GetFeature(ScriptConstants.HostingConfigInternalAuthApisAllowList);
90-
}
91-
92-
set
93-
{
94-
_allowedInternalAuthApis = null;
95-
_features[ScriptConstants.HostingConfigInternalAuthApisAllowList] = value;
96-
}
97-
}
98-
9978
/// <summary>
10079
/// Gets a string delimited by '|' that contains the name of the apps with worker indexing disabled.
10180
/// </summary>
@@ -243,32 +222,5 @@ internal bool GetFeatureAsBooleanOrDefault(string name, bool defaultValue)
243222
}
244223
return defaultValue;
245224
}
246-
247-
internal bool CheckInternalAuthAllowList(HttpRequest httpRequest)
248-
{
249-
if (InternalAuthApisAllowList != null && _allowedInternalAuthApis == null)
250-
{
251-
// initialize our cached allow list on demand
252-
_allowedInternalAuthApis = InternalAuthApisAllowList.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries).Select(p => new PathString(p)).ToArray();
253-
}
254-
255-
if (_allowedInternalAuthApis != null)
256-
{
257-
// An allow list is configured, so we ensure that the current request
258-
// matches any of the allowed APIs.
259-
foreach (PathString ps in _allowedInternalAuthApis)
260-
{
261-
if (httpRequest.Path.StartsWithSegments(ps, StringComparison.OrdinalIgnoreCase))
262-
{
263-
return true;
264-
}
265-
}
266-
267-
return false;
268-
}
269-
270-
// no allow list configured
271-
return true;
272-
}
273225
}
274226
}

src/WebJobs.Script/Extensions/HttpRequestExtensions.cs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@
1313
using Microsoft.AspNetCore.Http.Extensions;
1414
using Microsoft.AspNetCore.WebUtilities;
1515
using Microsoft.Azure.WebJobs.Extensions.Http;
16-
using Microsoft.Azure.WebJobs.Script.Config;
1716
using Microsoft.Extensions.DependencyInjection;
18-
using Microsoft.Extensions.Options;
1917
using Microsoft.Extensions.Primitives;
2018
using Newtonsoft.Json;
2119
using Newtonsoft.Json.Linq;
@@ -104,13 +102,6 @@ public static bool IsPlatformInternalRequest(this HttpRequest request, IEnvironm
104102
return string.Compare(value, "true", StringComparison.OrdinalIgnoreCase) == 0;
105103
}
106104

107-
public static bool IsInternalAuthAllowed(this HttpRequest httpRequest)
108-
{
109-
// Check to see if the specific API is allowed based on any configured allow list
110-
var options = httpRequest.HttpContext.RequestServices.GetService<IOptions<FunctionsHostingConfigOptions>>().Value;
111-
return options.CheckInternalAuthAllowList(httpRequest);
112-
}
113-
114105
private static IEnvironment GetEnvironment(HttpRequest request, IEnvironment environment = null)
115106
{
116107
return environment ?? request.HttpContext.RequestServices?.GetService<IEnvironment>() ?? SystemEnvironment.Instance;

src/WebJobs.Script/ScriptConstants.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,6 @@ public static class ScriptConstants
143143
public const string HostingConfigDisableLinuxAppServiceExecutionEventLogBackoff = "DisableLinuxLogBackoff";
144144
public const string FeatureFlagEnableLegacyDurableVersionCheck = "EnableLegacyDurableVersionCheck";
145145
public const string HostingConfigSwtIssuerEnabled = "SwtIssuerEnabled";
146-
public const string HostingConfigInternalAuthApisAllowList = "InternalAuthApisAllowList";
147146

148147
public const string SiteAzureFunctionsUriFormat = "https://{0}.azurewebsites.net/azurefunctions";
149148
public const string ScmSiteUriFormat = "https://{0}.scm.azurewebsites.net";

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

Lines changed: 6 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ public async Task ExtensionWebHook_Succeeds()
246246
[InlineData("admin/host/extensionBundle/v1/templates", true, true, false, true, false, HttpStatusCode.Unauthorized)]
247247
[InlineData("admin/host/extensionBundle/v1/templates", true, true, true, false, true, HttpStatusCode.NotFound)]
248248
[InlineData("admin/host/extensionBundle/v1/templates", true, false, false, false, true, HttpStatusCode.NotFound)]
249-
[InlineData("admin/host/extensionBundle/v1/templates", true, true, false, true, true, HttpStatusCode.Forbidden)]
249+
[InlineData("admin/host/extensionBundle/v1/templates", true, true, false, true, true, HttpStatusCode.NotFound)]
250250
[InlineData("admin/vfs/host.json", true, true, true, false, true, HttpStatusCode.OK)]
251251
[InlineData("admin/vfs/host.json", true, true, false, false, true, HttpStatusCode.Unauthorized)]
252252
[InlineData("admin/vfs/host.json", true, true, true, false, false, HttpStatusCode.Unauthorized)]
@@ -476,46 +476,21 @@ public async Task ArmExtensionsResourceFilter_GetNonSecretResource_Succeeds()
476476
}
477477

478478
[Fact]
479-
public async Task SyncTriggers_InternalAuth_Succeeds()
479+
public async Task SyncTriggers_AdminTokenProvided_Succeeds()
480480
{
481481
using (var httpClient = _fixture.Host.CreateHttpClient())
482482
{
483483
string uri = "admin/host/synctriggers";
484+
string token = _fixture.Host.GenerateAdminJwtToken(issuer: ScriptConstants.AppServiceCoreUri);
484485
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri);
486+
request.Headers.Add(ScriptConstants.SiteTokenHeaderName, token);
485487
HttpResponseMessage response = await httpClient.SendAsync(request);
486488
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
487489
}
488490
}
489491

490-
[Theory]
491-
[InlineData("", HttpStatusCode.Unauthorized)]
492-
[InlineData("|", HttpStatusCode.Unauthorized)]
493-
[InlineData("/admin/host/foo|/admin/host/bar", HttpStatusCode.Unauthorized)]
494-
[InlineData("/admin/host/status|/admin/host/synctriggers", HttpStatusCode.OK)]
495-
public async Task SyncTriggers_InternalAuth_AllowListSpecified_ReturnsExpectedResult(string allowList, HttpStatusCode expected)
496-
{
497-
var options = _fixture.Host.WebHostServices.GetService<IOptions<FunctionsHostingConfigOptions>>().Value;
498-
499-
try
500-
{
501-
options.InternalAuthApisAllowList = allowList;
502-
503-
using (var httpClient = _fixture.Host.CreateHttpClient())
504-
{
505-
string uri = "admin/host/synctriggers";
506-
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri);
507-
HttpResponseMessage response = await httpClient.SendAsync(request);
508-
Assert.Equal(expected, response.StatusCode);
509-
}
510-
}
511-
finally
512-
{
513-
options.InternalAuthApisAllowList = null;
514-
}
515-
}
516-
517492
[Fact]
518-
public async Task SyncTriggers_ExternalUnauthorized_ReturnsUnauthorized()
493+
public async Task SyncTriggers_NoAuthentication_ReturnsUnauthorized()
519494
{
520495
string uri = "admin/host/synctriggers";
521496
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri);
@@ -524,7 +499,7 @@ public async Task SyncTriggers_ExternalUnauthorized_ReturnsUnauthorized()
524499
}
525500

526501
[Fact]
527-
public async Task SyncTriggers_AdminLevel_Succeeds()
502+
public async Task SyncTriggers_MasterKeyProvided_Succeeds()
528503
{
529504
string uri = "admin/host/synctriggers";
530505
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri);
@@ -543,23 +518,6 @@ public async Task HostLog_Anonymous_Fails()
543518
Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
544519
}
545520

546-
[Fact]
547-
public async Task HostLog_PlatformInternal_Succeeds()
548-
{
549-
var environment = _fixture.Host.JobHostServices.GetService<IEnvironment>();
550-
Assert.True(environment.IsAppService());
551-
552-
using (var httpClient = _fixture.Host.CreateHttpClient())
553-
{
554-
// no x-arr-log-id header makes this request platform internal
555-
var request = new HttpRequestMessage(HttpMethod.Post, "admin/host/log");
556-
request.Content = new StringContent("[]");
557-
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
558-
var response = await httpClient.SendAsync(request);
559-
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
560-
}
561-
}
562-
563521
[Fact]
564522
public async Task HostLog_AdminLevel_Succeeds()
565523
{

0 commit comments

Comments
 (0)