Skip to content

Commit 8df66d1

Browse files
kashimizfabiocav
authored andcommitted
Inject CORS middleware at specialization in Linux consumption. Resolves #4889
1 parent 0e47f50 commit 8df66d1

File tree

12 files changed

+406
-1
lines changed

12 files changed

+406
-1
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the MIT License. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Linq;
7+
using System.Threading.Tasks;
8+
using Microsoft.AspNetCore.Cors.Infrastructure;
9+
using Microsoft.Extensions.Options;
10+
11+
namespace Microsoft.Azure.WebJobs.Script.WebHost.Configuration
12+
{
13+
public class CorsOptionsSetup : IConfigureOptions<CorsOptions>
14+
{
15+
private readonly IEnvironment _env;
16+
private readonly IOptions<HostCorsOptions> _hostCorsOptions;
17+
18+
public CorsOptionsSetup(IEnvironment env, IOptions<HostCorsOptions> hostCorsOptions)
19+
{
20+
_env = env;
21+
_hostCorsOptions = hostCorsOptions;
22+
}
23+
24+
public void Configure(CorsOptions options)
25+
{
26+
if (_env.IsLinuxConsumption() && _hostCorsOptions.Value != null)
27+
{
28+
string[] allowedOrigins = _hostCorsOptions.Value.AllowedOrigins?.ToArray() ?? Array.Empty<string>();
29+
var policyBuilder = new CorsPolicyBuilder(allowedOrigins);
30+
31+
if (_hostCorsOptions.Value.SupportCredentials)
32+
{
33+
policyBuilder = policyBuilder.AllowCredentials();
34+
}
35+
36+
var policy = policyBuilder.Build();
37+
options.AddDefaultPolicy(policy);
38+
}
39+
}
40+
}
41+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the MIT License. See License.txt in the project root for license information.
3+
4+
using System.Collections.Generic;
5+
6+
namespace Microsoft.Azure.WebJobs.Script.WebHost.Configuration
7+
{
8+
public class HostCorsOptions
9+
{
10+
public IEnumerable<string> AllowedOrigins { get; set; }
11+
12+
public bool SupportCredentials { get; set; }
13+
}
14+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the MIT License. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using Microsoft.Extensions.Configuration;
7+
using Microsoft.Extensions.Options;
8+
using Newtonsoft.Json;
9+
10+
namespace Microsoft.Azure.WebJobs.Script.WebHost.Configuration
11+
{
12+
public class HostCorsOptionsSetup : IConfigureOptions<HostCorsOptions>
13+
{
14+
private readonly IConfiguration _configuration;
15+
16+
public HostCorsOptionsSetup(IConfiguration configuration)
17+
{
18+
_configuration = configuration;
19+
}
20+
21+
public void Configure(HostCorsOptions options)
22+
{
23+
var allowedOriginsString = _configuration.GetValue<string>(EnvironmentSettingNames.CorsAllowedOrigins);
24+
25+
IEnumerable<string> corsAllowedOrigins = Array.Empty<string>();
26+
if (!string.IsNullOrWhiteSpace(allowedOriginsString))
27+
{
28+
corsAllowedOrigins = JsonConvert.DeserializeObject<IEnumerable<string>>(allowedOriginsString);
29+
}
30+
options.AllowedOrigins = corsAllowedOrigins;
31+
32+
var supportCredentialsString = _configuration.GetValue<bool?>(EnvironmentSettingNames.CorsSupportCredentials);
33+
options.SupportCredentials = supportCredentialsString ?? false;
34+
}
35+
}
36+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the MIT License. See License.txt in the project root for license information.
3+
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Threading.Tasks;
7+
using Microsoft.AspNetCore.Cors.Infrastructure;
8+
using Microsoft.AspNetCore.Http;
9+
using Microsoft.Azure.WebJobs.Script.Middleware;
10+
using Microsoft.Azure.WebJobs.Script.WebHost.Configuration;
11+
using Microsoft.Extensions.Options;
12+
13+
namespace Microsoft.Azure.WebJobs.Script.WebHost.Middleware
14+
{
15+
public class CorsConfigurationMiddleware : IJobHostHttpMiddleware
16+
{
17+
private RequestDelegate _invoke;
18+
19+
public CorsConfigurationMiddleware(IOptions<HostCorsOptions> hostCorsOptions, ICorsMiddlewareFactory middlewareFactory)
20+
{
21+
RequestDelegate contextNext = async context =>
22+
{
23+
if (context.Items.Remove(ScriptConstants.CorsMiddlewareRequestDelegate, out object requestDelegate) && requestDelegate is RequestDelegate next)
24+
{
25+
await next(context);
26+
}
27+
};
28+
29+
var corsMiddleware = middlewareFactory.CreateCorsMiddleware(contextNext, hostCorsOptions);
30+
if (corsMiddleware != null)
31+
{
32+
_invoke = corsMiddleware.Invoke;
33+
}
34+
else
35+
{
36+
_invoke = contextNext;
37+
}
38+
}
39+
40+
public async Task Invoke(HttpContext context, RequestDelegate next)
41+
{
42+
context.Items.Add(ScriptConstants.CorsMiddlewareRequestDelegate, next);
43+
await _invoke(context);
44+
}
45+
}
46+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Linq;
6+
using Microsoft.AspNetCore.Cors.Infrastructure;
7+
using Microsoft.AspNetCore.Http;
8+
using Microsoft.Azure.WebJobs.Script.WebHost.Configuration;
9+
using Microsoft.Extensions.Options;
10+
11+
namespace Microsoft.Azure.WebJobs.Script.WebHost.Middleware
12+
{
13+
public class CorsMiddlewareFactory : ICorsMiddlewareFactory
14+
{
15+
private readonly IOptions<CorsOptions> _corsOptions;
16+
17+
public CorsMiddlewareFactory(IOptions<CorsOptions> corsOptions)
18+
{
19+
_corsOptions = corsOptions;
20+
}
21+
22+
public CorsMiddleware CreateCorsMiddleware(RequestDelegate next, IOptions<HostCorsOptions> corsOptions)
23+
{
24+
CorsMiddleware middleware = null;
25+
if (corsOptions?.Value != null)
26+
{
27+
var corsService = new CorsService(_corsOptions);
28+
var policy = _corsOptions.Value.GetPolicy(_corsOptions.Value.DefaultPolicyName);
29+
middleware = new CorsMiddleware(next, corsService, policy);
30+
}
31+
32+
return middleware;
33+
}
34+
}
35+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the MIT License. See License.txt in the project root for license information.
3+
4+
using Microsoft.AspNetCore.Cors.Infrastructure;
5+
using Microsoft.AspNetCore.Http;
6+
using Microsoft.Azure.WebJobs.Script.WebHost.Configuration;
7+
using Microsoft.Extensions.Options;
8+
9+
namespace Microsoft.Azure.WebJobs.Script.WebHost.Middleware
10+
{
11+
public interface ICorsMiddlewareFactory
12+
{
13+
CorsMiddleware CreateCorsMiddleware(RequestDelegate next, IOptions<HostCorsOptions> corsOptions);
14+
}
15+
}

src/WebJobs.Script.WebHost/Models/HostAssignmentContext.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,17 @@ public void ApplyAppSettings(IEnvironment environment)
110110
{
111111
environment.SetEnvironmentVariable(pair.Key, pair.Value);
112112
}
113+
114+
if (CorsSettings != null)
115+
{
116+
environment.SetEnvironmentVariable(EnvironmentSettingNames.CorsSupportCredentials, CorsSettings.SupportCredentials.ToString());
117+
118+
if (CorsSettings.AllowedOrigins != null)
119+
{
120+
var allowedOrigins = JsonConvert.SerializeObject(CorsSettings.AllowedOrigins);
121+
environment.SetEnvironmentVariable(EnvironmentSettingNames.CorsAllowedOrigins, allowedOrigins);
122+
}
123+
}
113124
}
114125
}
115126
}

src/WebJobs.Script.WebHost/WebScriptHostBuilderExtension.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ public static IHostBuilder AddWebScriptHost(this IHostBuilder builder, IServiceP
3838
services.ConfigureOptions<HttpOptionsSetup>();
3939
services.ConfigureOptions<CustomHttpHeadersOptionsSetup>();
4040
services.ConfigureOptions<HostHstsOptionsSetup>();
41+
services.ConfigureOptions<HostCorsOptionsSetup>();
42+
services.ConfigureOptions<CorsOptionsSetup>();
4143
})
4244
.AddScriptHost(webHostOptions, configLoggerFactory, metricsLogger, webJobsBuilder =>
4345
{
@@ -84,6 +86,12 @@ public static IHostBuilder AddWebScriptHost(this IHostBuilder builder, IServiceP
8486
services.TryAddSingleton<IJobHostMiddlewarePipeline, DefaultMiddlewarePipeline>();
8587
services.TryAddEnumerable(ServiceDescriptor.Singleton<IJobHostHttpMiddleware, CustomHttpHeadersMiddleware>());
8688
services.TryAddEnumerable(ServiceDescriptor.Singleton<IJobHostHttpMiddleware, HstsConfigurationMiddleware>());
89+
if (environment.IsLinuxConsumption())
90+
{
91+
services.AddCors();
92+
services.AddSingleton<ICorsMiddlewareFactory, CorsMiddlewareFactory>();
93+
services.TryAddEnumerable(ServiceDescriptor.Singleton<IJobHostHttpMiddleware, CorsConfigurationMiddleware>());
94+
}
8795
services.TryAddSingleton<IScaleMetricsRepository, TableStorageScaleMetricsRepository>();
8896

8997
// Make sure the registered IHostIdProvider is used

src/WebJobs.Script/Environment/EnvironmentSettingNames.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,5 +82,9 @@ public static class EnvironmentSettingNames
8282
public const string FunctionsSecretsPath = "FUNCTIONS_SECRETS_PATH";
8383
public const string FunctionsTestDataPath = "FUNCTIONS_TEST_DATA_PATH";
8484
public const string MeshInitURI = "MESH_INIT_URI";
85+
86+
// CORS settings
87+
public const string CorsAllowedOrigins = "CORS_ALLOWED_ORIGINS";
88+
public const string CorsSupportCredentials = "CORS_SUPPORT_CREDENTIALS";
8589
}
8690
}

src/WebJobs.Script/ScriptConstants.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public static class ScriptConstants
2121
public const string AzureFunctionsDuplicateHttpHeadersKey = "MS_AzureFunctionsDuplicateHttpHeaders";
2222
public const string JobHostMiddlewarePipelineRequestDelegate = "MS_JobHostMiddlewarePipelineRequestDelegate";
2323
public const string HstsMiddlewareRequestDelegate = "MS_HstsMiddlewareRequestDelegate";
24+
public const string CorsMiddlewareRequestDelegate = "MS_CorsMiddlewareRequestDelegate";
2425

2526
public const string LegacyPlaceholderTemplateSiteName = "FunctionsPlaceholderTemplateSite";
2627

0 commit comments

Comments
 (0)