-
Notifications
You must be signed in to change notification settings - Fork 1.7k
#2165 Global configuration SecurityOptions
#2170
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
Changes from 10 commits
c3fea2c
1b0af5f
7e0f066
9e54669
4667bc2
cf362ed
eb6036e
eb2fa5e
4a37e8b
bd592a3
b4dbf32
8f51eff
2c35ad9
05914fa
a06a467
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| namespace Ocelot.Configuration.File | ||
| { | ||
| internal static class FileSecurityOptionsExtensions | ||
raman-m marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| { | ||
| internal static bool IsFullFilled(this FileSecurityOptions fileSecurityOptions) | ||
| => fileSecurityOptions.IPAllowedList.Count > 0 || fileSecurityOptions.IPBlockedList.Count > 0; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -16,18 +16,18 @@ public async Task<Response> Security(DownstreamRoute downstreamRoute, HttpContex | |||||||||||||||||||
| return new OkResponse(); | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| if (securityOptions.IPBlockedList != null) | ||||||||||||||||||||
| if (securityOptions.IPBlockedList != null && securityOptions.IPBlockedList.Count > 0 && clientIp != null) | ||||||||||||||||||||
| { | ||||||||||||||||||||
| if (securityOptions.IPBlockedList.Exists(f => f == clientIp.ToString())) | ||||||||||||||||||||
| if (securityOptions.IPBlockedList.Contains(clientIp.ToString())) | ||||||||||||||||||||
|
||||||||||||||||||||
| public static bool operator ==(ServiceHostAndPort h, Lease l) => h == l.HostAndPort; | |
| public static bool operator !=(ServiceHostAndPort h, Lease l) => !(h == l); | |
| public static bool operator ==(Lease l, ServiceHostAndPort h) => l.HostAndPort == h; | |
| public static bool operator !=(Lease l, ServiceHostAndPort h) => !(l == h); |
The same types of 2 operands:
Ocelot/src/Ocelot/LoadBalancer/Lease.cs
Lines 55 to 56 in 41fc9bd
| public static bool operator ==(Lease x, Lease y) => x.HostAndPort == y.HostAndPort; // ignore -> x.Connections == y.Connections; | |
| public static bool operator !=(Lease x, Lease y) => !(x == y); |
and
Ocelot/src/Ocelot/Requester/MessageInvokerPool.cs
Lines 119 to 120 in 41fc9bd
| public static bool operator ==(MessageInvokerCacheKey left, MessageInvokerCacheKey right) => left.Equals(right); | |
| public static bool operator !=(MessageInvokerCacheKey left, MessageInvokerCacheKey right) => !(left == right); |
Cool, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe in a next Feature PR ? 🤣
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, next time... 😋
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,163 @@ | ||
| using Microsoft.AspNetCore.Http; | ||
| using Ocelot.Configuration.File; | ||
|
|
||
| namespace Ocelot.AcceptanceTests.Security | ||
Fabman08 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| { | ||
| public sealed class SecurityOptionsTests: Steps | ||
| { | ||
| private readonly ServiceHandler _serviceHandler; | ||
|
|
||
| public SecurityOptionsTests() | ||
| { | ||
| _serviceHandler = new ServiceHandler(); | ||
| } | ||
|
|
||
| public override void Dispose() | ||
| { | ||
| _serviceHandler.Dispose(); | ||
| base.Dispose(); | ||
| } | ||
|
|
||
| [Fact] | ||
raman-m marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| public void should_call_with_allowed_ip_in_global_config() | ||
| { | ||
| var port = PortFinder.GetRandomPort(); | ||
| var ip = Dns.GetHostAddresses("192.168.1.35")[0]; | ||
| var route = GivenRoute(port, "/myPath", "/worldPath"); | ||
| var configuration = GivenConfigurationWithSecurityOptions(route); | ||
|
|
||
| this.Given(x => x.GivenThereIsAServiceRunningOn(DownstreamUrl(port), ip)) | ||
| .And(x => GivenThereIsAConfiguration(configuration)) | ||
| .And(x => GivenOcelotIsRunning()) | ||
| .When(x => WhenIGetUrlOnTheApiGateway("/worldPath")) | ||
| .Then(x => ThenTheStatusCodeShouldBe(HttpStatusCode.OK)); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void should_block_call_with_blocked_ip_in_global_config() | ||
| { | ||
| var port = PortFinder.GetRandomPort(); | ||
| var ip = Dns.GetHostAddresses("192.168.1.55")[0]; | ||
| var route = GivenRoute(port, "/myPath", "/worldPath"); | ||
| var configuration = GivenConfigurationWithSecurityOptions(route); | ||
|
|
||
| this.Given(x => x.GivenThereIsAServiceRunningOn(DownstreamUrl(port), ip)) | ||
| .And(x => GivenThereIsAConfiguration(configuration)) | ||
| .And(x => GivenOcelotIsRunning()) | ||
| .When(x => WhenIGetUrlOnTheApiGateway("/worldPath")) | ||
| .Then(x => ThenTheStatusCodeShouldBe(HttpStatusCode.Unauthorized)); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void should_call_with_allowed_ip_in_route_config() | ||
| { | ||
| var port = PortFinder.GetRandomPort(); | ||
| var ip = Dns.GetHostAddresses("192.168.1.1")[0]; | ||
| var securityConfig = new FileSecurityOptions | ||
| { | ||
| IPAllowedList = new List<string> { "192.168.1.1" }, | ||
| }; | ||
|
|
||
| var route = GivenRoute(port, "/myPath", "/worldPath", securityConfig); | ||
| var configuration = GivenConfiguration(route); | ||
|
|
||
| this.Given(x => x.GivenThereIsAServiceRunningOn(DownstreamUrl(port), ip)) | ||
| .And(x => GivenThereIsAConfiguration(configuration)) | ||
| .And(x => GivenOcelotIsRunning()) | ||
| .When(x => WhenIGetUrlOnTheApiGateway("/worldPath")) | ||
| .Then(x => ThenTheStatusCodeShouldBe(HttpStatusCode.OK)); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void should_block_call_with_blocked_ip_in_route_config() | ||
| { | ||
| var port = PortFinder.GetRandomPort(); | ||
| var ip = Dns.GetHostAddresses("192.168.1.1")[0]; | ||
| var securityConfig = new FileSecurityOptions | ||
| { | ||
| IPBlockedList = new List<string> { "192.168.1.1" }, | ||
| }; | ||
|
|
||
| var route = GivenRoute(port, "/myPath", "/worldPath", securityConfig); | ||
| var configuration = GivenConfiguration(route); | ||
|
|
||
| this.Given(x => x.GivenThereIsAServiceRunningOn(DownstreamUrl(port), ip)) | ||
| .And(x => GivenThereIsAConfiguration(configuration)) | ||
| .And(x => GivenOcelotIsRunning()) | ||
| .When(x => WhenIGetUrlOnTheApiGateway("/worldPath")) | ||
| .Then(x => ThenTheStatusCodeShouldBe(HttpStatusCode.Unauthorized)); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void should_call_with_allowed_ip_in_route_config_and_blocked_ip_in_global_config() | ||
| { | ||
| var port = PortFinder.GetRandomPort(); | ||
| var ip = Dns.GetHostAddresses("192.168.1.55")[0]; | ||
| var securityConfig = new FileSecurityOptions | ||
| { | ||
| IPAllowedList = new List<string> { "192.168.1.55" }, | ||
| }; | ||
|
|
||
| var route = GivenRoute(port, "/myPath", "/worldPath", securityConfig); | ||
| var configuration = GivenConfigurationWithSecurityOptions(route); | ||
|
|
||
| this.Given(x => x.GivenThereIsAServiceRunningOn(DownstreamUrl(port), ip)) | ||
| .And(x => GivenThereIsAConfiguration(configuration)) | ||
| .And(x => GivenOcelotIsRunning()) | ||
| .When(x => WhenIGetUrlOnTheApiGateway("/worldPath")) | ||
| .Then(x => ThenTheStatusCodeShouldBe(HttpStatusCode.OK)); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void should_block_call_with_blocked_ip_in_route_config_and_allowed_ip_in_global_config() | ||
| { | ||
| var port = PortFinder.GetRandomPort(); | ||
| var ip = Dns.GetHostAddresses("192.168.1.35")[0]; | ||
| var securityConfig = new FileSecurityOptions | ||
| { | ||
| IPBlockedList = new List<string> { "192.168.1.35" }, | ||
| }; | ||
|
|
||
| var route = GivenRoute(port, "/myPath", "/worldPath", securityConfig); | ||
| var configuration = GivenConfigurationWithSecurityOptions(route); | ||
|
|
||
| this.Given(x => x.GivenThereIsAServiceRunningOn(DownstreamUrl(port), ip)) | ||
| .And(x => GivenThereIsAConfiguration(configuration)) | ||
| .And(x => GivenOcelotIsRunning()) | ||
| .When(x => WhenIGetUrlOnTheApiGateway("/worldPath")) | ||
| .Then(x => ThenTheStatusCodeShouldBe(HttpStatusCode.Unauthorized)); | ||
| } | ||
|
|
||
| private void GivenThereIsAServiceRunningOn(string url, IPAddress ipAddess) | ||
| { | ||
| _serviceHandler.GivenThereIsAServiceRunningOn(url, async context => | ||
| { | ||
| context.Connection.RemoteIpAddress = ipAddess; | ||
| context.Response.StatusCode = (int)HttpStatusCode.OK; | ||
| await context.Response.WriteAsync("a valida response body"); | ||
| }); | ||
| } | ||
|
|
||
| private static FileConfiguration GivenConfigurationWithSecurityOptions(params FileRoute[] routes) | ||
| { | ||
| var config = GivenConfiguration(routes); | ||
| config.GlobalConfiguration.SecurityOptions = new FileSecurityOptions | ||
| { | ||
| IPAllowedList = new List<string> { "192.168.1.30-50" }, | ||
| IPBlockedList = new List<string> { "192.168.1.1-100" }, | ||
| ExcludeAllowedFromBlocked = true | ||
| }; | ||
|
|
||
| return config; | ||
| } | ||
|
|
||
| private FileRoute GivenRoute(int port, string downstream, string upstream, FileSecurityOptions fileSecurityOptions = null) | ||
| => new() | ||
| { | ||
| DownstreamPathTemplate = downstream, | ||
| UpstreamPathTemplate = upstream, | ||
| UpstreamHttpMethod = new List<string> { "Get" }, | ||
| SecurityOptions = fileSecurityOptions ?? new FileSecurityOptions(), | ||
| }; | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.