1
0

Solution restructured to use multiple test projects

This commit is contained in:
2024-07-04 18:22:26 +02:00
parent 508379d704
commit df6763b99b
144 changed files with 387 additions and 1693 deletions

View File

@@ -0,0 +1,352 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Security.Claims;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Common.AspNetCore.Security.BasicAuthentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Primitives;
using Moq;
namespace AMWD.Common.AspNetCore.Tests.Attributes
{
[TestClass]
public class BasicAuthenticationAttributeTest
{
private Mock<IHeaderDictionary> _requestHeaderMock;
private Mock<IHeaderDictionary> _responseHeaderMock;
private Mock<HttpRequest> _requestMock;
private Mock<HttpResponse> _responseMock;
private Mock<HttpContext> _contextMock;
private Dictionary<string, string> _requestHeaders;
private string _validatorRealm;
private ClaimsPrincipal _validatorResult;
private string _responseHeaderAuthCallback;
[TestInitialize]
public void InitializeTest()
{
_requestHeaders = [];
_validatorRealm = null;
_validatorResult = null;
_responseHeaderAuthCallback = null;
}
[TestMethod]
public async Task ShouldValidateViaUsernamePassword()
{
// arrange
var attribute = new BasicAuthenticationAttribute
{
Username = "user",
Password = "password"
};
_requestHeaders.Add("Authorization", $"Basic {Convert.ToBase64String(Encoding.UTF8.GetBytes($"{attribute.Username}:{attribute.Password}"))}");
var context = GetContext();
// act
await attribute.OnAuthorizationAsync(context);
// assert
Assert.IsNull(context.Result);
Assert.IsTrue(string.IsNullOrWhiteSpace(_responseHeaderAuthCallback));
}
[TestMethod]
public async Task ShouldValidateViaValidator()
{
// arrange
var attribute = new BasicAuthenticationAttribute();
_requestHeaders.Add("Authorization", $"Basic {Convert.ToBase64String(Encoding.UTF8.GetBytes($"{attribute.Username}:{attribute.Password}"))}");
_validatorResult = new ClaimsPrincipal();
var context = GetContext(hasValidator: true);
// act
await attribute.OnAuthorizationAsync(context);
// assert
Assert.IsNull(context.Result);
Assert.IsTrue(string.IsNullOrWhiteSpace(_responseHeaderAuthCallback));
}
[TestMethod]
public async Task ShouldAllowAnonymous()
{
// arrange
var attribute = new BasicAuthenticationAttribute
{
Username = "user",
Password = "password"
};
var context = GetContext(isAnonymousAllowed: true);
// act
await attribute.OnAuthorizationAsync(context);
// assert
Assert.IsNull(context.Result);
Assert.IsTrue(string.IsNullOrWhiteSpace(_responseHeaderAuthCallback));
}
[TestMethod]
public async Task ShouldAskOnUsernamePasswordWithoutRealm()
{
// arrange
var attribute = new BasicAuthenticationAttribute
{
Username = "user",
Password = "password"
};
var context = GetContext();
// act
await attribute.OnAuthorizationAsync(context);
// assert
Assert.IsNotNull(context.Result);
Assert.IsTrue(context.Result is StatusCodeResult);
Assert.AreEqual(401, ((StatusCodeResult)context.Result).StatusCode);
Assert.IsFalse(string.IsNullOrWhiteSpace(_responseHeaderAuthCallback));
Assert.AreEqual("Basic", _responseHeaderAuthCallback);
}
[TestMethod]
public async Task ShouldAskOnUsernamePasswordWithRealm()
{
// arrange
var attribute = new BasicAuthenticationAttribute
{
Username = "user",
Password = "password",
Realm = "re:al\"m"
};
var context = GetContext();
// act
await attribute.OnAuthorizationAsync(context);
// assert
Assert.IsNotNull(context.Result);
Assert.IsTrue(context.Result is StatusCodeResult);
Assert.AreEqual(401, ((StatusCodeResult)context.Result).StatusCode);
Assert.IsFalse(string.IsNullOrWhiteSpace(_responseHeaderAuthCallback));
Assert.AreEqual("Basic realm=\"re:alm\"", _responseHeaderAuthCallback);
}
[TestMethod]
public async Task ShouldAskOnUsernamePasswordWrongUser()
{
// arrange
var attribute = new BasicAuthenticationAttribute
{
Username = "user",
Password = "password"
};
_requestHeaders.Add("Authorization", $"Basic {Convert.ToBase64String(Encoding.UTF8.GetBytes($"{attribute.Username}a:{attribute.Password}"))}");
var context = GetContext();
// act
await attribute.OnAuthorizationAsync(context);
// assert
Assert.IsNotNull(context.Result);
Assert.IsTrue(context.Result is StatusCodeResult);
Assert.AreEqual(401, ((StatusCodeResult)context.Result).StatusCode);
Assert.IsFalse(string.IsNullOrWhiteSpace(_responseHeaderAuthCallback));
Assert.AreEqual("Basic", _responseHeaderAuthCallback);
}
[TestMethod]
public async Task ShouldAskOnUsernamePasswordWrongPassword()
{
// arrange
var attribute = new BasicAuthenticationAttribute
{
Username = "user",
Password = "password"
};
_requestHeaders.Add("Authorization", $"Basic {Convert.ToBase64String(Encoding.UTF8.GetBytes($"{attribute.Username}:{attribute.Password}a"))}");
var context = GetContext();
// act
await attribute.OnAuthorizationAsync(context);
// assert
Assert.IsNotNull(context.Result);
Assert.IsTrue(context.Result is StatusCodeResult);
Assert.AreEqual(401, ((StatusCodeResult)context.Result).StatusCode);
Assert.IsFalse(string.IsNullOrWhiteSpace(_responseHeaderAuthCallback));
Assert.AreEqual("Basic", _responseHeaderAuthCallback);
}
[TestMethod]
public async Task ShouldAskOnValidatorWithRealmOnAttribute()
{
// arrange
var attribute = new BasicAuthenticationAttribute
{
Realm = "attribute"
};
_requestHeaders.Add("Authorization", $"Basic {Convert.ToBase64String(Encoding.UTF8.GetBytes($"{attribute.Username}:{attribute.Password}"))}");
var context = GetContext(hasValidator: true);
// act
await attribute.OnAuthorizationAsync(context);
// assert
Assert.IsNotNull(context.Result);
Assert.IsTrue(context.Result is StatusCodeResult);
Assert.AreEqual(401, ((StatusCodeResult)context.Result).StatusCode);
Assert.IsFalse(string.IsNullOrWhiteSpace(_responseHeaderAuthCallback));
Assert.AreEqual("Basic realm=\"attribute\"", _responseHeaderAuthCallback);
}
[TestMethod]
public async Task ShouldAskOnValidatorWithRealmOnValidator()
{
// arrange
_validatorRealm = "validator";
var attribute = new BasicAuthenticationAttribute();
_requestHeaders.Add("Authorization", $"Basic {Convert.ToBase64String(Encoding.UTF8.GetBytes($"{attribute.Username}:{attribute.Password}"))}");
var context = GetContext(hasValidator: true);
// act
await attribute.OnAuthorizationAsync(context);
// assert
Assert.IsNotNull(context.Result);
Assert.IsTrue(context.Result is StatusCodeResult);
Assert.AreEqual(401, ((StatusCodeResult)context.Result).StatusCode);
Assert.IsFalse(string.IsNullOrWhiteSpace(_responseHeaderAuthCallback));
Assert.AreEqual("Basic realm=\"validator\"", _responseHeaderAuthCallback);
}
[TestMethod]
public async Task ShouldReturnInternalError()
{
// arrange
var attribute = new BasicAuthenticationAttribute();
_requestHeaders.Add("Authorization", $"Basic {Convert.ToBase64String(Encoding.UTF8.GetBytes($"{attribute.Username}"))}");
var context = GetContext();
// act
await attribute.OnAuthorizationAsync(context);
// assert
Assert.IsNotNull(context.Result);
Assert.IsTrue(context.Result is StatusCodeResult);
Assert.AreEqual(500, ((StatusCodeResult)context.Result).StatusCode);
}
private AuthorizationFilterContext GetContext(bool isAnonymousAllowed = false, bool hasValidator = false)
{
_requestHeaderMock = new Mock<IHeaderDictionary>();
foreach (var header in _requestHeaders)
{
StringValues outVal = header.Value;
_requestHeaderMock
.Setup(h => h.ContainsKey(header.Key))
.Returns(true);
_requestHeaderMock
.Setup(h => h[header.Key])
.Returns(header.Value);
_requestHeaderMock
.Setup(h => h.TryGetValue(header.Key, out outVal))
.Returns(true);
}
_responseHeaderMock = new Mock<IHeaderDictionary>();
_responseHeaderMock
.SetupSet(h => h.WWWAuthenticate = It.IsAny<StringValues>())
.Callback<StringValues>((value) =>
{
_responseHeaderAuthCallback = value;
});
_requestMock = new Mock<HttpRequest>();
_requestMock
.Setup(r => r.Headers)
.Returns(_requestHeaderMock.Object);
_responseMock = new Mock<HttpResponse>();
_responseMock
.Setup(r => r.Headers)
.Returns(_responseHeaderMock.Object);
var requestServicesMock = new Mock<IServiceProvider>();
if (hasValidator)
{
var validatorMock = new Mock<IBasicAuthenticationValidator>();
validatorMock
.Setup(v => v.Realm)
.Returns(_validatorRealm);
validatorMock
.Setup(v => v.ValidateAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<IPAddress>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(_validatorResult);
requestServicesMock
.Setup(rs => rs.GetService(typeof(IBasicAuthenticationValidator)))
.Returns(validatorMock.Object);
}
var connectionInfoMock = new Mock<ConnectionInfo>();
connectionInfoMock
.Setup(ci => ci.RemoteIpAddress)
.Returns(IPAddress.Loopback);
_contextMock = new Mock<HttpContext>();
_contextMock
.Setup(c => c.Request)
.Returns(_requestMock.Object);
_contextMock
.Setup(c => c.Response)
.Returns(_responseMock.Object);
_contextMock
.Setup(c => c.RequestServices)
.Returns(requestServicesMock.Object);
_contextMock
.Setup(c => c.Connection)
.Returns(connectionInfoMock.Object);
_contextMock
.Setup(c => c.RequestAborted)
.Returns(CancellationToken.None);
var routeDataMock = new Mock<RouteData>();
var actionDescriptor = new ActionDescriptor
{
EndpointMetadata = new List<object>()
};
if (isAnonymousAllowed)
actionDescriptor.EndpointMetadata.Add(new AllowAnonymousAttribute());
return new AuthorizationFilterContext(new ActionContext
{
HttpContext = _contextMock.Object,
RouteData = routeDataMock.Object,
ActionDescriptor = actionDescriptor,
}, new List<IFilterMetadata>());
}
}
}

View File

@@ -0,0 +1,339 @@
using System;
using System.Collections.Generic;
using System.Net;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Configuration;
using Moq;
namespace AMWD.Common.AspNetCore.Tests.Attributes
{
[TestClass]
public class IPAllowListAttributeTest
{
private Dictionary<string, string> _requestHeaders;
private Dictionary<object, object> _itemsCallback;
private string _configKey;
private bool _configExists;
private List<string> _allowedIpsConfig;
[TestInitialize]
public void InitializeTest()
{
_requestHeaders = [];
_itemsCallback = [];
_configKey = null;
_configExists = false;
_allowedIpsConfig = [];
}
[TestMethod]
public void ShouldDenyOnNoConfiguration()
{
// arrange
var remote = IPAddress.Parse("192.168.178.1");
var attribute = new IPAllowListAttribute();
var context = GetContext(remote);
// act
attribute.OnActionExecuting(context);
// assert
Assert.IsNotNull(context.Result);
Assert.IsTrue(context.Result is StatusCodeResult);
Assert.AreEqual(403, ((StatusCodeResult)context.Result).StatusCode);
Assert.AreEqual(1, _itemsCallback.Count);
Assert.AreEqual(remote, _itemsCallback["RemoteAddress"]);
}
[TestMethod]
public void ShouldDenyOnWrongConfiguration()
{
// arrange
var remote = IPAddress.Parse("192.168.178.1");
var attribute = new IPAllowListAttribute
{
AllowedIpAddresses = "192.168.178:1"
};
var context = GetContext(remote);
// act
attribute.OnActionExecuting(context);
// assert
Assert.IsNotNull(context.Result);
Assert.IsTrue(context.Result is StatusCodeResult);
Assert.AreEqual(403, ((StatusCodeResult)context.Result).StatusCode);
Assert.AreEqual(1, _itemsCallback.Count);
Assert.AreEqual(remote, _itemsCallback["RemoteAddress"]);
}
[TestMethod]
public void ShouldAllowLocalAccess()
{
// arrange
var attribute = new IPAllowListAttribute();
var context = GetContext();
// act
attribute.OnActionExecuting(context);
// assert
Assert.IsNull(context.Result);
Assert.AreEqual(1, _itemsCallback.Count);
Assert.AreEqual(IPAddress.Loopback, _itemsCallback["RemoteAddress"]);
}
[TestMethod]
public void ShouldDenyLocalAccess()
{
// arrange
var attribute = new IPAllowListAttribute
{
AllowLocalAccess = false
};
var context = GetContext();
// act
attribute.OnActionExecuting(context);
// assert
Assert.IsNotNull(context.Result);
Assert.IsTrue(context.Result is StatusCodeResult);
Assert.AreEqual(403, ((StatusCodeResult)context.Result).StatusCode);
Assert.AreEqual(1, _itemsCallback.Count);
Assert.AreEqual(IPAddress.Loopback, _itemsCallback["RemoteAddress"]);
}
[DataTestMethod]
[DataRow("192.168.178.10")]
[DataRow("192.168.178.20")]
public void ShouldAllowSpecificAddress(string address)
{
// arrange
var remote = IPAddress.Parse(address);
var attribute = new IPAllowListAttribute
{
AllowLocalAccess = false,
AllowedIpAddresses = ",127.0.0.0/8,192.168.178.10"
};
var context = GetContext(remote);
// act
attribute.OnActionExecuting(context);
// assert
if (address == "192.168.178.10")
{
Assert.IsNull(context.Result);
}
else
{
Assert.IsNotNull(context.Result);
Assert.IsTrue(context.Result is StatusCodeResult);
Assert.AreEqual(403, ((StatusCodeResult)context.Result).StatusCode);
}
Assert.AreEqual(1, _itemsCallback.Count);
Assert.AreEqual(remote, _itemsCallback["RemoteAddress"]);
}
[TestMethod]
public void ShouldAllowLocalAccessConfig()
{
// arrange
_configKey = "White:List";
_configExists = true;
_allowedIpsConfig.Add("127.0.0.0/8");
_allowedIpsConfig.Add("192.168.178.10");
var attribute = new IPAllowListAttribute
{
AllowLocalAccess = true,
ConfigurationKey = _configKey
};
var context = GetContext();
// act
attribute.OnActionExecuting(context);
// assert
Assert.IsNull(context.Result);
Assert.AreEqual(1, _itemsCallback.Count);
Assert.AreEqual(IPAddress.Loopback, _itemsCallback["RemoteAddress"]);
}
[TestMethod]
public void ShouldDenyLocalAccessConfig()
{
// arrange
_configKey = "White:List";
_configExists = true;
_allowedIpsConfig.Add("");
_allowedIpsConfig.Add("192.168.178.10");
var attribute = new IPAllowListAttribute
{
AllowLocalAccess = false,
ConfigurationKey = _configKey
};
var context = GetContext();
// act
attribute.OnActionExecuting(context);
// assert
Assert.IsNotNull(context.Result);
Assert.IsTrue(context.Result is StatusCodeResult);
Assert.AreEqual(403, ((StatusCodeResult)context.Result).StatusCode);
Assert.AreEqual(1, _itemsCallback.Count);
Assert.AreEqual(IPAddress.Loopback, _itemsCallback["RemoteAddress"]);
}
[DataTestMethod]
[DataRow("192.168.178.10")]
[DataRow("192.168.178.20")]
public void ShouldAllowSpecificAddressConfig(string address)
{
// arrange
_configKey = "White:List";
_configExists = true;
_allowedIpsConfig.Add("192.168.178.10");
var attribute = new IPAllowListAttribute
{
AllowLocalAccess = false,
ConfigurationKey = _configKey
};
var remote = IPAddress.Parse(address);
var context = GetContext(remote);
// act
attribute.OnActionExecuting(context);
// assert
if (address == "192.168.178.10")
{
Assert.IsNull(context.Result);
}
else
{
Assert.IsNotNull(context.Result);
Assert.IsTrue(context.Result is StatusCodeResult);
Assert.AreEqual(403, ((StatusCodeResult)context.Result).StatusCode);
}
Assert.AreEqual(1, _itemsCallback.Count);
Assert.AreEqual(remote, _itemsCallback["RemoteAddress"]);
}
[TestMethod]
public void ShouldDenyOnMissingConfiguration()
{
// arrange
_configKey = "White:List";
_configExists = false;
var attribute = new IPAllowListAttribute
{
AllowLocalAccess = false,
ConfigurationKey = _configKey
};
var context = GetContext();
// act
attribute.OnActionExecuting(context);
// assert
Assert.IsNotNull(context.Result);
Assert.IsTrue(context.Result is StatusCodeResult);
Assert.AreEqual(403, ((StatusCodeResult)context.Result).StatusCode);
Assert.AreEqual(1, _itemsCallback.Count);
Assert.AreEqual(IPAddress.Loopback, _itemsCallback["RemoteAddress"]);
}
private ActionExecutingContext GetContext(IPAddress remote = null)
{
var requestHeaderMock = new Mock<IHeaderDictionary>();
foreach (var header in _requestHeaders)
{
requestHeaderMock
.Setup(h => h.ContainsKey(header.Key))
.Returns(true);
requestHeaderMock
.Setup(h => h[header.Key])
.Returns(header.Value);
}
var requestMock = new Mock<HttpRequest>();
requestMock
.Setup(r => r.Headers)
.Returns(requestHeaderMock.Object);
var connectionInfoMock = new Mock<ConnectionInfo>();
connectionInfoMock
.Setup(ci => ci.LocalIpAddress)
.Returns(IPAddress.Loopback);
connectionInfoMock
.Setup(ci => ci.RemoteIpAddress)
.Returns(remote ?? IPAddress.Loopback);
var itemsMock = new Mock<IDictionary<object, object>>();
itemsMock
.SetupSet(i => i[It.IsAny<object>()] = It.IsAny<object>())
.Callback<object, object>((key, val) => _itemsCallback.Add(key, val));
var configurationMock = new Mock<IConfiguration>();
var children = new List<IConfigurationSection>();
foreach (string ipAddress in _allowedIpsConfig)
{
var csm = new Mock<IConfigurationSection>();
csm.Setup(cs => cs.Value).Returns(ipAddress);
children.Add(csm.Object);
}
var configSectionMock = new Mock<IConfigurationSection>();
configSectionMock
.Setup(cs => cs.GetChildren())
.Returns(children);
configurationMock
.Setup(c => c.GetSection(_configKey))
.Returns(_configExists ? configSectionMock.Object : null);
var requestServicesMock = new Mock<IServiceProvider>();
requestServicesMock
.Setup(s => s.GetService(typeof(IConfiguration)))
.Returns(configurationMock.Object);
var contextMock = new Mock<HttpContext>();
contextMock
.Setup(c => c.Request)
.Returns(requestMock.Object);
contextMock
.Setup(c => c.RequestServices)
.Returns(requestServicesMock.Object);
contextMock
.Setup(c => c.Items)
.Returns(itemsMock.Object);
contextMock
.Setup(c => c.Connection)
.Returns(connectionInfoMock.Object);
var routeDataMock = new Mock<RouteData>();
var actionDescriptorMock = new Mock<ActionDescriptor>();
return new ActionExecutingContext(new ActionContext
{
HttpContext = contextMock.Object,
RouteData = routeDataMock.Object,
ActionDescriptor = actionDescriptorMock.Object,
}, new List<IFilterMetadata>(), new Dictionary<string, object>(), null);
}
}
}

View File

@@ -0,0 +1,338 @@
using System;
using System.Collections.Generic;
using System.Net;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Configuration;
using Moq;
namespace AMWD.Common.AspNetCore.Tests.Attributes
{
[TestClass]
public class IPBlockListAttributeTest
{
private Dictionary<string, string> _requestHeaders;
private Dictionary<object, object> _itemsCallback;
private string _configKey;
private bool _configExists;
private List<string> _restrictedIpsConfig;
[TestInitialize]
public void InitializeTest()
{
_requestHeaders = [];
_itemsCallback = [];
_configKey = null;
_configExists = false;
_restrictedIpsConfig = [];
}
[TestMethod]
public void ShouldAllowOnNoConfiguration()
{
// arrange
var remote = IPAddress.Parse("192.168.178.1");
var attribute = new IPBlockListAttribute();
var context = GetContext(remote);
// act
attribute.OnActionExecuting(context);
// assert
Assert.IsNull(context.Result);
Assert.AreEqual(1, _itemsCallback.Count);
Assert.AreEqual(remote, _itemsCallback["RemoteAddress"]);
}
[TestMethod]
public void ShouldAllowOnWrongConfiguration()
{
// arrange
var remote = IPAddress.Parse("192.168.178.1");
var attribute = new IPBlockListAttribute
{
BlockedIpAddresses = "192.168.178:1"
};
var context = GetContext(remote);
// act
attribute.OnActionExecuting(context);
// assert
Assert.IsNull(context.Result);
Assert.AreEqual(1, _itemsCallback.Count);
Assert.AreEqual(remote, _itemsCallback["RemoteAddress"]);
}
[TestMethod]
public void ShouldAllowLocalAccess()
{
// arrange
var attribute = new IPBlockListAttribute
{
BlockLocalAccess = false,
BlockedIpAddresses = "127.0.0.0/8"
};
var context = GetContext();
// act
attribute.OnActionExecuting(context);
// assert
Assert.IsNull(context.Result);
Assert.AreEqual(1, _itemsCallback.Count);
Assert.AreEqual(IPAddress.Loopback, _itemsCallback["RemoteAddress"]);
}
[TestMethod]
public void ShouldBlockLocalAccess()
{
// arrange
var attribute = new IPBlockListAttribute
{
BlockLocalAccess = true,
BlockedIpAddresses = ",127.0.0.0/8"
};
var context = GetContext();
// act
attribute.OnActionExecuting(context);
// assert
Assert.IsNotNull(context.Result);
Assert.IsTrue(context.Result is StatusCodeResult);
Assert.AreEqual(403, ((StatusCodeResult)context.Result).StatusCode);
Assert.AreEqual(1, _itemsCallback.Count);
Assert.AreEqual(IPAddress.Loopback, _itemsCallback["RemoteAddress"]);
}
[DataTestMethod]
[DataRow("192.168.178.10")]
[DataRow("192.168.178.20")]
public void ShouldBlockSpecificAddress(string address)
{
// arrange
var remote = IPAddress.Parse(address);
var attribute = new IPBlockListAttribute
{
BlockLocalAccess = true,
BlockedIpAddresses = "127.0.0.0/8,192.168.178.10"
};
var context = GetContext(remote);
// act
attribute.OnActionExecuting(context);
// assert
if (address == "192.168.178.10")
{
Assert.IsNotNull(context.Result);
Assert.IsTrue(context.Result is StatusCodeResult);
Assert.AreEqual(403, ((StatusCodeResult)context.Result).StatusCode);
}
else
{
Assert.IsNull(context.Result);
}
Assert.AreEqual(1, _itemsCallback.Count);
Assert.AreEqual(remote, _itemsCallback["RemoteAddress"]);
}
[TestMethod]
public void ShouldAllowLocalAccessConfig()
{
// arrange
_configKey = "Black:List";
_configExists = true;
_restrictedIpsConfig.Add("127.0.0.0/8");
_restrictedIpsConfig.Add("192.168.178.10");
var attribute = new IPBlockListAttribute
{
BlockLocalAccess = false,
ConfigurationKey = _configKey
};
var context = GetContext();
// act
attribute.OnActionExecuting(context);
// assert
Assert.IsNull(context.Result);
Assert.AreEqual(1, _itemsCallback.Count);
Assert.AreEqual(IPAddress.Loopback, _itemsCallback["RemoteAddress"]);
}
[TestMethod]
public void ShouldBlockLocalAccessConfig()
{
// arrange
_configKey = "Black:List";
_configExists = true;
_restrictedIpsConfig.Add("");
_restrictedIpsConfig.Add("127.0.0.0/8");
_restrictedIpsConfig.Add("192.168.178.10");
var attribute = new IPBlockListAttribute
{
BlockLocalAccess = true,
ConfigurationKey = _configKey
};
var context = GetContext();
// act
attribute.OnActionExecuting(context);
// assert
Assert.IsNotNull(context.Result);
Assert.IsTrue(context.Result is StatusCodeResult);
Assert.AreEqual(403, ((StatusCodeResult)context.Result).StatusCode);
Assert.AreEqual(1, _itemsCallback.Count);
Assert.AreEqual(IPAddress.Loopback, _itemsCallback["RemoteAddress"]);
}
[DataTestMethod]
[DataRow("192.168.178.10")]
[DataRow("192.168.178.20")]
public void ShouldBlockSpecificAddressConfig(string address)
{
// arrange
_configKey = "Black:List";
_configExists = true;
_restrictedIpsConfig.Add("127.0.0.0/8");
_restrictedIpsConfig.Add("192.168.178.10");
var attribute = new IPBlockListAttribute
{
BlockLocalAccess = true,
ConfigurationKey = _configKey
};
var remote = IPAddress.Parse(address);
var context = GetContext(remote);
// act
attribute.OnActionExecuting(context);
// assert
if (address == "192.168.178.10")
{
Assert.IsNotNull(context.Result);
Assert.IsTrue(context.Result is StatusCodeResult);
Assert.AreEqual(403, ((StatusCodeResult)context.Result).StatusCode);
}
else
{
Assert.IsNull(context.Result);
}
Assert.AreEqual(1, _itemsCallback.Count);
Assert.AreEqual(remote, _itemsCallback["RemoteAddress"]);
}
[TestMethod]
public void ShouldAllowOnMissingConfiguration()
{
// arrange
_configKey = "Black:List";
_configExists = false;
var attribute = new IPBlockListAttribute
{
BlockLocalAccess = true,
ConfigurationKey = _configKey
};
var context = GetContext();
// act
attribute.OnActionExecuting(context);
// assert
Assert.IsNull(context.Result);
Assert.AreEqual(1, _itemsCallback.Count);
Assert.AreEqual(IPAddress.Loopback, _itemsCallback["RemoteAddress"]);
}
private ActionExecutingContext GetContext(IPAddress remote = null)
{
var requestHeaderMock = new Mock<IHeaderDictionary>();
foreach (var header in _requestHeaders)
{
requestHeaderMock
.Setup(h => h.ContainsKey(header.Key))
.Returns(true);
requestHeaderMock
.Setup(h => h[header.Key])
.Returns(header.Value);
}
var requestMock = new Mock<HttpRequest>();
requestMock
.Setup(r => r.Headers)
.Returns(requestHeaderMock.Object);
var connectionInfoMock = new Mock<ConnectionInfo>();
connectionInfoMock
.Setup(ci => ci.LocalIpAddress)
.Returns(IPAddress.Loopback);
connectionInfoMock
.Setup(ci => ci.RemoteIpAddress)
.Returns(remote ?? IPAddress.Loopback);
var itemsMock = new Mock<IDictionary<object, object>>();
itemsMock
.SetupSet(i => i[It.IsAny<object>()] = It.IsAny<object>())
.Callback<object, object>((key, val) => _itemsCallback.Add(key, val));
var configurationMock = new Mock<IConfiguration>();
var children = new List<IConfigurationSection>();
foreach (string ipAddress in _restrictedIpsConfig)
{
var csm = new Mock<IConfigurationSection>();
csm.Setup(cs => cs.Value).Returns(ipAddress);
children.Add(csm.Object);
}
var configSectionMock = new Mock<IConfigurationSection>();
configSectionMock
.Setup(cs => cs.GetChildren())
.Returns(children);
configurationMock
.Setup(c => c.GetSection(_configKey))
.Returns(_configExists ? configSectionMock.Object : null);
var requestServicesMock = new Mock<IServiceProvider>();
requestServicesMock
.Setup(s => s.GetService(typeof(IConfiguration)))
.Returns(configurationMock.Object);
var contextMock = new Mock<HttpContext>();
contextMock
.Setup(c => c.Request)
.Returns(requestMock.Object);
contextMock
.Setup(c => c.RequestServices)
.Returns(requestServicesMock.Object);
contextMock
.Setup(c => c.Items)
.Returns(itemsMock.Object);
contextMock
.Setup(c => c.Connection)
.Returns(connectionInfoMock.Object);
var routeDataMock = new Mock<RouteData>();
var actionDescriptorMock = new Mock<ActionDescriptor>();
return new ActionExecutingContext(new ActionContext
{
HttpContext = contextMock.Object,
RouteData = routeDataMock.Object,
ActionDescriptor = actionDescriptorMock.Object,
}, new List<IFilterMetadata>(), new Dictionary<string, object>(), null);
}
}
}