Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#2116 Escaping unsafe pattern values of Regex constructor ​​derived from URL query parameter values containing special Regex chars #2150

Merged
merged 7 commits into from
Sep 20, 2024
96 changes: 96 additions & 0 deletions test/Ocelot.AcceptanceTests/PathToDownstreamUrlTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
using IdentityServer4.AccessTokenValidation;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Ocelot.Configuration.File;

namespace Ocelot.AcceptanceTests;

public class PathToDownstreamUrlTests : IDisposable
int0x81 marked this conversation as resolved.
Show resolved Hide resolved
{
private IWebHost _servicebuilder;
private readonly Steps _steps;
private readonly Action<IdentityServerAuthenticationOptions> _options;
private readonly string _serverRootUrl;
private string _downstreamFinalPath;

public PathToDownstreamUrlTests()
{
var serverPort = PortFinder.GetRandomPort();
_serverRootUrl = $"http://localhost:{serverPort}";
_steps = new Steps();
_options = o =>
{
o.ApiName = "api";
o.RequireHttpsMetadata = false;
};
}

[Fact]
[Trait("Bug", "2116")]
public void Should_change_downstream_path_by_upstream_path_when_path_contains_malicious_characters()
{
var port = PortFinder.GetRandomPort();

var configuration = new FileConfiguration
{
Routes = new List<FileRoute>
{
new()
{
DownstreamPathTemplate = "/routed/api/{path}",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new()
{
Host = "localhost",
Port = port,
},
},
DownstreamScheme = "http",
UpstreamPathTemplate = "/api/{path}",
UpstreamHttpMethod = new List<string> { "Get" },
},
},
};

this.Given(x => x.GivenThereIsAServiceRunningOn($"http://localhost:{port}", 200))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning(_options, "Test"))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/api/debug("))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => ThenTheDownstreamPathIs("/routed/api/debug("))
.BDDfy();
}

private void GivenThereIsAServiceRunningOn(string url, int statusCode)
int0x81 marked this conversation as resolved.
Show resolved Hide resolved
{
_servicebuilder = new WebHostBuilder()
.UseUrls(url)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseUrls(url)
.Configure(app =>
{
app.Run(context =>
{
_downstreamFinalPath = context.Request.Path.Value;
return Task.CompletedTask;
});
})
.Build();

_servicebuilder.Start();
}

private void ThenTheDownstreamPathIs(string path)
{
_downstreamFinalPath.ShouldBe(path);
}

public void Dispose()
{
_servicebuilder?.Dispose();
_steps.Dispose();
}
}