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

add a security module (#628) #629

Merged
merged 6 commits into from
Sep 25, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions src/Ocelot/Configuration/Builder/DownstreamReRouteBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public class DownstreamReRouteBuilder
private List<AddHeader> _addHeadersToDownstream;
private List<AddHeader> _addHeadersToUpstream;
private bool _dangerousAcceptAnyServerCertificateValidator;

private SecurityOptions _securityOptions;
public DownstreamReRouteBuilder()
{
_downstreamAddresses = new List<DownstreamHostAndPort>();
Expand Down Expand Up @@ -227,6 +227,12 @@ public DownstreamReRouteBuilder WithDangerousAcceptAnyServerCertificateValidator
return this;
}

public DownstreamReRouteBuilder WithSecurityOptions(SecurityOptions securityOptions)
{
_securityOptions = securityOptions;
return this;
}

public DownstreamReRoute Build()
{
return new DownstreamReRoute(
Expand Down Expand Up @@ -258,7 +264,8 @@ public DownstreamReRoute Build()
_delegatingHandlers,
_addHeadersToDownstream,
_addHeadersToUpstream,
_dangerousAcceptAnyServerCertificateValidator);
_dangerousAcceptAnyServerCertificateValidator,
_securityOptions);
}
}
}
12 changes: 12 additions & 0 deletions src/Ocelot/Configuration/Creator/ISecurityOptionsCreator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Ocelot.Configuration.File;
using System;
using System.Collections.Generic;
using System.Text;

namespace Ocelot.Configuration.Creator
{
public interface ISecurityOptionsCreator
{
SecurityOptions Create(FileSecurityOptions securityOptions);
}
}
8 changes: 7 additions & 1 deletion src/Ocelot/Configuration/Creator/ReRoutesCreator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public class ReRoutesCreator : IReRoutesCreator
private readonly IHeaderFindAndReplaceCreator _headerFAndRCreator;
private readonly IDownstreamAddressesCreator _downstreamAddressesCreator;
private readonly IReRouteKeyCreator _reRouteKeyCreator;
private readonly ISecurityOptionsCreator _securityOptionsCreator;

public ReRoutesCreator(
IClaimsToThingCreator claimsToThingCreator,
Expand All @@ -35,7 +36,8 @@ public ReRoutesCreator(
IHeaderFindAndReplaceCreator headerFAndRCreator,
IDownstreamAddressesCreator downstreamAddressesCreator,
ILoadBalancerOptionsCreator loadBalancerOptionsCreator,
IReRouteKeyCreator reRouteKeyCreator
IReRouteKeyCreator reRouteKeyCreator,
ISecurityOptionsCreator securityOptionsCreator
)
{
_reRouteKeyCreator = reRouteKeyCreator;
Expand All @@ -52,6 +54,7 @@ IReRouteKeyCreator reRouteKeyCreator
_fileReRouteOptionsCreator = fileReRouteOptionsCreator;
_httpHandlerOptionsCreator = httpHandlerOptionsCreator;
_loadBalancerOptionsCreator = loadBalancerOptionsCreator;
_securityOptionsCreator = securityOptionsCreator;
}

public List<ReRoute> Create(FileConfiguration fileConfiguration)
Expand Down Expand Up @@ -97,6 +100,8 @@ private DownstreamReRoute SetUpDownstreamReRoute(FileReRoute fileReRoute, FileGl

var lbOptions = _loadBalancerOptionsCreator.Create(fileReRoute.LoadBalancerOptions);

var securityOptions = _securityOptionsCreator.Create(fileReRoute.SecurityOptions);

var reRoute = new DownstreamReRouteBuilder()
.WithKey(fileReRoute.Key)
.WithDownstreamPathTemplate(fileReRoute.DownstreamPathTemplate)
Expand Down Expand Up @@ -128,6 +133,7 @@ private DownstreamReRoute SetUpDownstreamReRoute(FileReRoute fileReRoute, FileGl
.WithAddHeadersToDownstream(hAndRs.AddHeadersToDownstream)
.WithAddHeadersToUpstream(hAndRs.AddHeadersToUpstream)
.WithDangerousAcceptAnyServerCertificateValidator(fileReRoute.DangerousAcceptAnyServerCertificateValidator)
.WithSecurityOptions(securityOptions)
.Build();

return reRoute;
Expand Down
15 changes: 15 additions & 0 deletions src/Ocelot/Configuration/Creator/SecurityOptionsCreator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Text;
using Ocelot.Configuration.File;

namespace Ocelot.Configuration.Creator
{
public class SecurityOptionsCreator : ISecurityOptionsCreator
{
public SecurityOptions Create(FileSecurityOptions securityOptions)
{
return new SecurityOptions(securityOptions.IPWhitelist, securityOptions.IPBlacklist);
}
}
}
5 changes: 4 additions & 1 deletion src/Ocelot/Configuration/DownstreamReRoute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ public DownstreamReRoute(
List<string> delegatingHandlers,
List<AddHeader> addHeadersToDownstream,
List<AddHeader> addHeadersToUpstream,
bool dangerousAcceptAnyServerCertificateValidator)
bool dangerousAcceptAnyServerCertificateValidator,
SecurityOptions securityOptions)
{
DangerousAcceptAnyServerCertificateValidator = dangerousAcceptAnyServerCertificateValidator;
AddHeadersToDownstream = addHeadersToDownstream;
Expand Down Expand Up @@ -66,6 +67,7 @@ public DownstreamReRoute(
DownstreamPathTemplate = downstreamPathTemplate;
LoadBalancerKey = loadBalancerKey;
AddHeadersToUpstream = addHeadersToUpstream;
SecurityOptions = securityOptions;
}

public string Key { get; }
Expand Down Expand Up @@ -97,5 +99,6 @@ public DownstreamReRoute(
public List<AddHeader> AddHeadersToDownstream { get; }
public List<AddHeader> AddHeadersToUpstream { get; }
public bool DangerousAcceptAnyServerCertificateValidator { get; }
public SecurityOptions SecurityOptions { get; }
}
}
2 changes: 2 additions & 0 deletions src/Ocelot/Configuration/File/FileReRoute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public FileReRoute()
DownstreamHostAndPorts = new List<FileHostAndPort>();
DelegatingHandlers = new List<string>();
LoadBalancerOptions = new FileLoadBalancerOptions();
SecurityOptions = new FileSecurityOptions();
Priority = 1;
}

Expand Down Expand Up @@ -50,5 +51,6 @@ public FileReRoute()
public int Priority { get;set; }
public int Timeout { get; set; }
public bool DangerousAcceptAnyServerCertificateValidator { get; set; }
public FileSecurityOptions SecurityOptions { get; set; }
}
}
19 changes: 19 additions & 0 deletions src/Ocelot/Configuration/File/FileSecurityOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace Ocelot.Configuration.File
{
public class FileSecurityOptions
{
public FileSecurityOptions()
{
IPWhitelist = new List<string>();
IPBlacklist = new List<string>();
}

public List<string> IPWhitelist { get; set; }
lfzm marked this conversation as resolved.
Show resolved Hide resolved

public List<string> IPBlacklist { get; set; }
lfzm marked this conversation as resolved.
Show resolved Hide resolved
}
}
19 changes: 19 additions & 0 deletions src/Ocelot/Configuration/SecurityOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace Ocelot.Configuration
{
public class SecurityOptions
{
public SecurityOptions(List<string> whitelist,List<string> blacklist)
{
this.IPBlacklist = blacklist;
this.IPWhitelist = whitelist;
}

public List<string> IPWhitelist { get; private set; }
lfzm marked this conversation as resolved.
Show resolved Hide resolved

public List<string> IPBlacklist { get; private set; }
lfzm marked this conversation as resolved.
Show resolved Hide resolved
}
}
19 changes: 15 additions & 4 deletions src/Ocelot/DependencyInjection/OcelotBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ namespace Ocelot.DependencyInjection
using Ocelot.Infrastructure;
using Ocelot.Middleware.Multiplexer;
using Ocelot.Request.Creator;
using Ocelot.Security.IPSecurity;
using Ocelot.Security;

public class OcelotBuilder : IOcelotBuilder
{
Expand Down Expand Up @@ -125,6 +127,9 @@ public OcelotBuilder(IServiceCollection services, IConfiguration configurationRo
Services.TryAddSingleton<IQoSFactory, QoSFactory>();
Services.TryAddSingleton<IExceptionToErrorMapper, HttpExeptionToErrorMapper>();

//add security
this.AddSecurity();

//add asp.net services..
var assembly = typeof(FileConfigurationController).GetTypeInfo().Assembly;

Expand All @@ -139,22 +144,28 @@ public OcelotBuilder(IServiceCollection services, IConfiguration configurationRo
Services.AddWebEncoders();
}

public IOcelotBuilder AddSingletonDefinedAggregator<T>()
public IOcelotBuilder AddSingletonDefinedAggregator<T>()
where T : class, IDefinedAggregator
{
Services.AddSingleton<IDefinedAggregator, T>();
return this;
}

public IOcelotBuilder AddTransientDefinedAggregator<T>()
public IOcelotBuilder AddTransientDefinedAggregator<T>()
where T : class, IDefinedAggregator
{
Services.AddTransient<IDefinedAggregator, T>();
return this;
}

public IOcelotBuilder AddDelegatingHandler<THandler>(bool global = false)
where THandler : DelegatingHandler
private void AddSecurity()
{
Services.TryAddSingleton<ISecurityOptionsCreator, SecurityOptionsCreator>();
Services.TryAddSingleton<ISecurityPolicy, IPSecurityPolicy>();
}

public IOcelotBuilder AddDelegatingHandler<THandler>(bool global = false)
where THandler : DelegatingHandler
{
if(global)
{
Expand Down
4 changes: 4 additions & 0 deletions src/Ocelot/Middleware/Pipeline/OcelotPipelineExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using Ocelot.Requester.Middleware;
using Ocelot.RequestId.Middleware;
using Ocelot.Responder.Middleware;
using Ocelot.Security.Middleware;
using Ocelot.WebSockets.Middleware;

namespace Ocelot.Middleware.Pipeline
Expand Down Expand Up @@ -48,6 +49,9 @@ public static OcelotRequestDelegate BuildOcelotPipeline(this IOcelotPipelineBuil
// Then we get the downstream route information
builder.UseDownstreamRouteFinderMiddleware();

// This security module, IP whitelist blacklist, extended security mechanism
builder.UseSecurityMiddleware();

//Expand other branch pipes
if (pipelineConfiguration.MapWhenOcelotPipeline != null)
{
Expand Down
41 changes: 41 additions & 0 deletions src/Ocelot/Security/IPSecurity/IPSecurityPolicy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Ocelot.Configuration;
using Ocelot.Middleware;
using Ocelot.Responses;

namespace Ocelot.Security.IPSecurity
{
public class IPSecurityPolicy : ISecurityPolicy
{
public async Task<Response> Security(DownstreamContext context)
{
IPAddress clientIp = context.HttpContext.Connection.RemoteIpAddress;
SecurityOptions securityOptions = context.DownstreamReRoute.SecurityOptions;
if (securityOptions == null)
{
return new OkResponse();
}
if (securityOptions.IPBlacklist != null)
{
if (securityOptions.IPBlacklist.Exists(f => f == clientIp.ToString()))
{
var error = new UnauthenticatedError($"{clientIp.ToString()} Cannot request to enter the blacklist");
lfzm marked this conversation as resolved.
Show resolved Hide resolved
return new ErrorResponse(error);
}
}
if (securityOptions.IPWhitelist != null)
{
if (!securityOptions.IPWhitelist.Exists(f => f == clientIp.ToString()))
{
var error = new UnauthenticatedError($"{clientIp.ToString()} is not in the whitelist, the request is invalid");
return new ErrorResponse(error);
}
}
return await Task.FromResult(new OkResponse());
}
}
}
14 changes: 14 additions & 0 deletions src/Ocelot/Security/ISecurityPolicy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Ocelot.Middleware;
using Ocelot.Responses;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace Ocelot.Security
{
public interface ISecurityPolicy
{
Task<Response> Security(DownstreamContext context);
}
}
44 changes: 44 additions & 0 deletions src/Ocelot/Security/Middleware/SecurityMiddleware.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using Ocelot.Logging;
using Ocelot.Middleware;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace Ocelot.Security.Middleware
{
public class SecurityMiddleware : OcelotMiddleware
{
private readonly OcelotRequestDelegate _next;
private readonly IOcelotLogger _logger;
private readonly IEnumerable<ISecurityPolicy> _securityPolicies;
public SecurityMiddleware(IOcelotLoggerFactory loggerFactory,
IEnumerable<ISecurityPolicy> securityPolicies,
OcelotRequestDelegate next)
: base(loggerFactory.CreateLogger<SecurityMiddleware>())
{
_logger = loggerFactory.CreateLogger<SecurityMiddleware>();
_securityPolicies = securityPolicies;
}

public async Task Invoke(DownstreamContext context)
{
if (_securityPolicies != null)
{
foreach (var policie in _securityPolicies)
{
var result = await policie.Security(context);
if (!result.IsError)
{
continue;
}

this.SetPipelineError(context, result.Errors);
return;
}
}

await _next.Invoke(context);
}
}
}
15 changes: 15 additions & 0 deletions src/Ocelot/Security/Middleware/SecurityMiddlewareExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Ocelot.Middleware.Pipeline;
using System;
using System.Collections.Generic;
using System.Text;

namespace Ocelot.Security.Middleware
{
public static class SecurityMiddlewareExtensions
{
public static IOcelotPipelineBuilder UseSecurityMiddleware(this IOcelotPipelineBuilder builder)
{
return builder.UseMiddleware<SecurityMiddleware>();
}
}
}