Beispiel #1
0
        public async Task NoOptionsCall_WithRoute_MatchingOrigin_Test()
        {
            var httpContext = new DefaultHttpContext();

            httpContext.Request.Method = "POST";
            httpContext.Request.Headers.Add(HeaderNames.Origin, "http://origin-host");

            var routeDefinitionMatch = new RouteDefinitionMatch
            {
                RouteDefinition = new RouteDefinition
                {
                    AllowOrigins = new List <string> {
                        "http://origin-host"
                    }
                }
            };

            httpContext.SetRouteDefinitionMatch(routeDefinitionMatch);

            await _middleware.InvokeAsync(httpContext);

            Assert.IsTrue(httpContext.Response.Headers.ContainsKey(HeaderNames.AccessControlAllowOrigin));
            Assert.AreEqual(httpContext.Request.Headers[HeaderNames.Origin],
                            httpContext.Response.Headers[HeaderNames.AccessControlAllowOrigin]);

            A.CallTo(() => _next(httpContext))
            .MustHaveHappened();
        }
        public async Task RequiredClaims_WithAuthentication_Must_CallNext_Test()
        {
            var httpContext = new DefaultHttpContext();

            httpContext.User = new ClaimsPrincipal(new ClaimsIdentity(new List <Claim>
            {
                new Claim("Claim", "value"),
                new Claim("Claim", "12345")
            }, "basic"));

            var routeDefinitionMatch = new RouteDefinitionMatch
            {
                RouteDefinition = new RouteDefinition
                {
                    RequireAuthentication = false,
                    RequiredClaims        = new List <KeyValuePair <string, string> >
                    {
                        new KeyValuePair <string, string>("Claim", "^[a-z]+$"),
                        new KeyValuePair <string, string>("Claim", "^[0-9]+$")
                    }
                }
            };

            httpContext.SetRouteDefinitionMatch(routeDefinitionMatch);
            await _middleware.InvokeAsync(httpContext);

            A.CallTo(() => _next(httpContext)).MustHaveHappened();
        }
        public async Task RequiredClaims_WithAuthentication_And_InvalidClaim_Must_Return401_Test()
        {
            var httpContext = new DefaultHttpContext();

            httpContext.User = new ClaimsPrincipal(new ClaimsIdentity(new List <Claim>
            {
                new Claim("Claim", "value")
            }, "basic"));

            var routeDefinitionMatch = new RouteDefinitionMatch
            {
                RouteDefinition = new RouteDefinition
                {
                    RequireAuthentication = false,
                    RequiredClaims        = new List <KeyValuePair <string, string> >
                    {
                        new KeyValuePair <string, string>("Claim", "[0-9]+"),
                        new KeyValuePair <string, string>("Claim", "[a-z]+")
                    }
                }
            };

            httpContext.SetRouteDefinitionMatch(routeDefinitionMatch);
            await _middleware.InvokeAsync(httpContext);

            A.CallTo(() => _next(httpContext)).MustNotHaveHappened();
            Assert.AreEqual(StatusCodes.Status401Unauthorized, httpContext.Response.StatusCode);
        }
        public async Task HttpAsyncError_StartedResponse_Must_Return_ResponseStatusCode()
        {
            var httpContext = new DefaultHttpContext();
            var routeDefinitionMatch = new RouteDefinitionMatch
            {
                RouteDefinition = new RouteDefinition()
            };
            
            httpContext.SetRouteDefinitionMatch(routeDefinitionMatch);


            var httpResponseFeature = A.Fake<IHttpResponseFeature>();
            A.CallTo(() => httpResponseFeature.HasStarted).Returns(true);
            A.CallTo(() => httpResponseFeature.StatusCode).Returns(StatusCodes.Status200OK);
            httpContext.Features.Set(httpResponseFeature);
            
            A.CallTo(() => _publisherService.HttpAsync(A<RouteDefinitionMatch>.Ignored, A<HttpContext>.Ignored))
                .Throws(new Exception());
            
            await _middleware.InvokeAsync(httpContext);

            A.CallTo(() => httpResponseFeature.HasStarted).MustHaveHappened();
            Assert.AreEqual(StatusCodes.Status200OK, httpContext.Response.StatusCode);
            
        }
Beispiel #5
0
        public async Task HttpAsync(RouteDefinitionMatch routeDefinitionMatch, HttpContext httpContext)
        {
            if (routeDefinitionMatch?.RouteDefinition?.RouteEndpoints == null)
            {
                throw new ArgumentException("Invalid route definition", nameof(routeDefinitionMatch));
            }

            if (routeDefinitionMatch.RouteDefinition.RouteEndpoints.Count == 0)
            {
                throw new ArgumentException("Route definition must contains at least 1 RouteEndpoint", nameof(routeDefinitionMatch));
            }

            var originIpAddress = httpContext.GetOriginIpAddress();

            if (originIpAddress == null)
            {
                throw new ArgumentException("Origin IP Address is null", nameof(httpContext));
            }



            var ipHashIndex = originIpAddress.GetHashIndex();
            var endpointId  = ipHashIndex % routeDefinitionMatch.RouteDefinition.RouteEndpoints.Count;
            var endpointStr = routeDefinitionMatch.RouteDefinition.RouteEndpoints[endpointId].RenderTemplate(routeDefinitionMatch.Values);

            var endpoint = new Uri(endpointStr);

            var clientId   = $"{endpoint.Host}";
            var httpClient = _httpClients.GetOrAdd(clientId, _ => _httpClientFactory.CreateClient());


            var httpRequestMessage = httpContext.Request.ToHttpRequestMessage(endpoint);

            if (routeDefinitionMatch.RouteDefinition.ClaimMappings != null)
            {
                foreach (var(claimType, headerName) in routeDefinitionMatch.RouteDefinition.ClaimMappings)
                {
                    var claims = httpContext.User.Claims.Where(c => c.Type == claimType);
                    foreach (var claim in claims)
                    {
                        httpRequestMessage.Headers.Add(headerName, claim.Value);
                    }
                }
            }


            if (httpContext.Connection.RemoteIpAddress != null)
            {
                httpRequestMessage.Headers.Add(HttpHeaderNames.XForwardedFor,
                                               httpContext.Connection.RemoteIpAddress.ToString());
            }


            var httpResponseMessage = await httpClient.SendAsync(httpRequestMessage, HttpCompletionOption.ResponseHeadersRead, httpContext.RequestAborted);

            await httpResponseMessage.PopulateHttpResponseAsync(httpContext.Response, httpContext.RequestAborted);
        }
        public async Task InvalidRouteDefinitionMatch_Must_Return500_Test()
        {
            var httpContext          = new DefaultHttpContext();
            var routeDefinitionMatch = new RouteDefinitionMatch();

            httpContext.SetRouteDefinitionMatch(routeDefinitionMatch);
            await _middleware.InvokeAsync(httpContext);

            Assert.AreEqual(StatusCodes.Status500InternalServerError, httpContext.Response.StatusCode);
        }
Beispiel #7
0
        public async Task InvalidRouteDefinitionMatch_Must_Throw_ArgumentException_Test()
        {
            var routeDefinitionMatch = new RouteDefinitionMatch();
            var httpContext          = new DefaultHttpContext();

            httpContext.Connection.RemoteIpAddress = new IPAddress(new byte[] { 0, 0, 0, 0 });

            var ex = await Assert.ThrowsExceptionAsync <ArgumentException>(() => _publisherService.HttpAsync(routeDefinitionMatch, httpContext));

            Assert.AreEqual("routeDefinitionMatch", ex.ParamName);
        }
 public async Task RouteDefinitionMatch_WithHttpEndpoint_Must_CallHttp_Test()
 {
     var httpContext = new DefaultHttpContext();
     var routeDefinitionMatch = new RouteDefinitionMatch
     {
         RouteDefinition = new RouteDefinition()
     };
     httpContext.SetRouteDefinitionMatch(routeDefinitionMatch);
     await _middleware.InvokeAsync(httpContext);
     A.CallTo(() => _publisherService.HttpAsync(routeDefinitionMatch, httpContext)).MustHaveHappened();
 }
Beispiel #9
0
        public async Task CallToEndpoint_Test()
        {
            var routeDefinitionMatch = new RouteDefinitionMatch
            {
                RouteDefinition = new RouteDefinition
                {
                    RouteEndpoints = new List <string> {
                        "http://test-host"
                    },
                    ClaimMappings = new Dictionary <string, string>
                    {
                        { "Claim1", "Header-Claim1" },
                        { "Claim2", "Header-Claim2" }
                    }
                }
            };
            var httpContext = new DefaultHttpContext();

            httpContext.Connection.RemoteIpAddress = new IPAddress(new byte[] { 0, 0, 0, 0 });
            httpContext.Request.Method             = HttpMethods.Get;
            httpContext.User = new ClaimsPrincipal(new ClaimsIdentity(new List <Claim>
            {
                new Claim("Claim1", "Claim-Value")
            }));

            HttpRequestMessage requestArgument = null;

            A.CallTo(_httpMessageHandler)
            .Where(m => m.Method.Name == "SendAsync")
            .WithReturnType <Task <HttpResponseMessage> >()
            .Invokes((call) =>
            {
                requestArgument = (HttpRequestMessage)call.Arguments[0];
            })
            .Returns(new HttpResponseMessage
            {
                Content = new StringContent("")
            });

            await _publisherService.HttpAsync(routeDefinitionMatch, httpContext);

            A.CallTo(_httpMessageHandler)
            .Where(m =>
                   m.Method.Name == "SendAsync")
            .WithReturnType <Task <HttpResponseMessage> >()
            .MustHaveHappened();

            Assert.IsTrue(requestArgument.Headers.Any(h => h.Key == HttpHeaderNames.XForwardedFor &&
                                                      h.Value.Contains("0.0.0.0")));
            Assert.IsTrue(requestArgument.Headers.Any(h => h.Key == "Header-Claim1" &&
                                                      h.Value.Contains("Claim-Value")));
        }
        public async Task ValidRouteDefinitionMatch_Must_CallNext_Test()
        {
            var httpContext          = new DefaultHttpContext();
            var routeDefinitionMatch = new RouteDefinitionMatch
            {
                RouteDefinition = new RouteDefinition()
            };

            httpContext.SetRouteDefinitionMatch(routeDefinitionMatch);
            await _middleware.InvokeAsync(httpContext);

            A.CallTo(() => _next(httpContext)).MustHaveHappened();
        }
        public async Task RequireAuthentication_Must_Return401_Test()
        {
            var httpContext          = new DefaultHttpContext();
            var routeDefinitionMatch = new RouteDefinitionMatch
            {
                RouteDefinition = new RouteDefinition
                {
                    RequireAuthentication = true
                }
            };

            httpContext.SetRouteDefinitionMatch(routeDefinitionMatch);
            await _middleware.InvokeAsync(httpContext);

            Assert.AreEqual(StatusCodes.Status401Unauthorized, httpContext.Response.StatusCode);
        }
Beispiel #12
0
        public async Task NullOriginIpAddress_Must_Throw_ArgumentException_Test()
        {
            var routeDefinitionMatch = new RouteDefinitionMatch
            {
                RouteDefinition = new RouteDefinition
                {
                    RouteEndpoints = new List <string> {
                        "http://test-host"
                    }
                }
            };
            var httpContext = new DefaultHttpContext();

            var ex = await Assert.ThrowsExceptionAsync <ArgumentException>(() => _publisherService.HttpAsync(routeDefinitionMatch, httpContext));

            Assert.AreEqual("httpContext", ex.ParamName);
        }
        public async Task HttpAsyncError_WithNoStartedResponse_Must_Return_502StatusCode()
        {
            var httpContext = new DefaultHttpContext();
            var routeDefinitionMatch = new RouteDefinitionMatch
            {
                RouteDefinition = new RouteDefinition()
            };
            
            httpContext.SetRouteDefinitionMatch(routeDefinitionMatch);

            A.CallTo(() => _publisherService.HttpAsync(A<RouteDefinitionMatch>.Ignored, A<HttpContext>.Ignored))
                .Throws(new Exception());
            
            await _middleware.InvokeAsync(httpContext);
            
            Assert.AreEqual(StatusCodes.Status502BadGateway, httpContext.Response.StatusCode);
            
        }
        public async Task RequireAuthentication_Must_CallNext_Test()
        {
            var httpContext = new DefaultHttpContext();

            httpContext.User = new ClaimsPrincipal(new ClaimsIdentity("basic"));

            var routeDefinitionMatch = new RouteDefinitionMatch
            {
                RouteDefinition = new RouteDefinition
                {
                    RequireAuthentication = true
                }
            };

            httpContext.SetRouteDefinitionMatch(routeDefinitionMatch);
            await _middleware.InvokeAsync(httpContext);

            A.CallTo(() => _next(httpContext)).MustHaveHappened();
        }
        public async Task <RouteDefinitionMatch> MatchAsync(string pathString, string method)
        {
            await LoadRouteDefinitionsAsync();

            var routeTemplateMatch = _routeTemplateCollection.Match(pathString);
            var routeDefinition    = routeTemplateMatch?.Item.SingleOrDefault(rd =>
                                                                              rd.RouteMethods.Contains(method));

            if (routeDefinition == null)
            {
                return(null);
            }

            var routeDefinitionMatch = new RouteDefinitionMatch
            {
                RouteDefinition = routeDefinition,
                Values          = routeTemplateMatch.Values
            };

            return(routeDefinitionMatch);
        }
        public async Task RequiredClaims_WithNoAuthentication_Must_CallNext_Test()
        {
            var httpContext = new DefaultHttpContext();

            var routeDefinitionMatch = new RouteDefinitionMatch
            {
                RouteDefinition = new RouteDefinition
                {
                    RequireAuthentication = false,
                    RequiredClaims        = new List <KeyValuePair <string, string> >
                    {
                        new KeyValuePair <string, string>("Claim", "Value")
                    }
                }
            };

            httpContext.SetRouteDefinitionMatch(routeDefinitionMatch);
            await _middleware.InvokeAsync(httpContext);

            A.CallTo(() => _next(httpContext)).MustHaveHappened();
        }
Beispiel #17
0
        public async Task OptionsCall_WithRoute_MatchingOrigin_Test()
        {
            var httpContext = new DefaultHttpContext();

            httpContext.Request.Method = HttpMethods.Options;
            httpContext.Request.Headers.Add(HeaderNames.Origin, "http://origin-host");

            var routeDefinitionMatch = new RouteDefinitionMatch
            {
                RouteDefinition = new RouteDefinition
                {
                    RouteMethods = new List <string> {
                        "POST", "PUT"
                    },
                    AllowOrigins = new List <string> {
                        "http://origin-host"
                    }
                }
            };

            A.CallTo(() => _routeDefinitionMatcher.MatchAsync(A <string> .Ignored, A <string> .Ignored))
            .Returns(routeDefinitionMatch);

            await _middleware.InvokeAsync(httpContext);

            A.CallTo(() => _next(httpContext))
            .MustNotHaveHappened();

            Assert.IsTrue(httpContext.Response.Headers.ContainsKey(HeaderNames.AccessControlAllowOrigin));
            Assert.AreEqual(httpContext.Request.Headers[HeaderNames.Origin],
                            httpContext.Response.Headers[HeaderNames.AccessControlAllowOrigin]);

            Assert.IsTrue(httpContext.Response.Headers.ContainsKey(HeaderNames.AccessControlAllowMethods));
            foreach (var method in routeDefinitionMatch.RouteDefinition.RouteMethods)
            {
                Assert.IsTrue(httpContext.Response.Headers[HeaderNames.AccessControlAllowMethods].Contains(method));
            }

            Assert.AreEqual(StatusCodes.Status204NoContent, httpContext.Response.StatusCode);
        }
        public async Task RequiredClaims_WithAuthentication_And_NoClaims_Must_Return401_Test()
        {
            var httpContext = new DefaultHttpContext();

            httpContext.User = new ClaimsPrincipal(new ClaimsIdentity("basic"));

            var routeDefinitionMatch = new RouteDefinitionMatch
            {
                RouteDefinition = new RouteDefinition
                {
                    RequireAuthentication = false,
                    RequiredClaims        = new List <KeyValuePair <string, string> >
                    {
                        new KeyValuePair <string, string>("Claim", "Value")
                    }
                }
            };

            httpContext.SetRouteDefinitionMatch(routeDefinitionMatch);
            await _middleware.InvokeAsync(httpContext);

            Assert.AreEqual(StatusCodes.Status401Unauthorized, httpContext.Response.StatusCode);
        }
        public async Task MappedClaims_InRequestHeaders_Must_Return403_Test()
        {
            var httpContext = new DefaultHttpContext();

            httpContext.Request.Headers.Add(new KeyValuePair <string, StringValues>("Mapped-Claim-Header", "value"));

            var routeDefinitionMatch = new RouteDefinitionMatch
            {
                RouteDefinition = new RouteDefinition
                {
                    ClaimMappings = new Dictionary <string, string>
                    {
                        { "Claim", "Mapped-Claim-Header" }
                    }
                }
            };

            httpContext.SetRouteDefinitionMatch(routeDefinitionMatch);
            await _middleware.InvokeAsync(httpContext);

            A.CallTo(() => _next(httpContext)).MustNotHaveHappened();
            Assert.AreEqual(StatusCodes.Status403Forbidden, httpContext.Response.StatusCode);
        }
 public static void SetRouteDefinitionMatch(this HttpContext httpContext, RouteDefinitionMatch routeDefinitionMatch)
 {
     httpContext.Items.Add("routeDefinitionMatch", routeDefinitionMatch);
 }