Changes and new tests from Netflix
This commit is contained in:
9
pom.xml
9
pom.xml
@@ -70,7 +70,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-netflix-dependencies</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<version>${spring-cloud-netflix.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -81,6 +81,13 @@
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-openfeign-dependencies</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-test-support</artifactId>
|
||||
|
||||
@@ -183,6 +183,11 @@
|
||||
<artifactId>ribbon</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<profiles>
|
||||
<profile>
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.openfeign.hystrix.security;
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.cloud.openfeign.hystrix.security.app.UsernameClient;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author Daniel Lavoie
|
||||
*/
|
||||
@Configuration
|
||||
@SpringBootApplication
|
||||
@EnableFeignClients(clients = UsernameClient.class)
|
||||
public class HystrixSecurityApplication {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.openfeign.hystrix.security;
|
||||
|
||||
import java.util.Base64;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.boot.web.server.LocalServerPort;
|
||||
import org.springframework.cloud.netflix.hystrix.security.SecurityContextConcurrencyStrategy;
|
||||
import org.springframework.cloud.openfeign.hystrix.security.app.CustomConcurrenyStrategy;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import com.netflix.hystrix.strategy.HystrixPlugins;
|
||||
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests that a secured web service returning values using a feign client properly access
|
||||
* the security context from a hystrix command.
|
||||
* @author Daniel Lavoie
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@DirtiesContext
|
||||
@SpringBootTest(classes = HystrixSecurityApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT,
|
||||
properties = { "username.ribbon.listOfServers=localhost:${local.server.port}",
|
||||
"feign.hystrix.enabled=true"})
|
||||
@ActiveProfiles("proxysecurity")
|
||||
public class HystrixSecurityTests {
|
||||
@Autowired
|
||||
private CustomConcurrenyStrategy customConcurrenyStrategy;
|
||||
|
||||
@LocalServerPort
|
||||
private String serverPort;
|
||||
|
||||
//TODOO: move to constants in TestAutoConfiguration
|
||||
private String username = "user";
|
||||
|
||||
private String password = "password";
|
||||
|
||||
@Test
|
||||
public void testSecurityConcurrencyStrategyInstalled() {
|
||||
HystrixConcurrencyStrategy concurrencyStrategy = HystrixPlugins.getInstance().getConcurrencyStrategy();
|
||||
assertThat(concurrencyStrategy).isInstanceOf(SecurityContextConcurrencyStrategy.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFeignHystrixSecurity() {
|
||||
HttpHeaders headers = HystrixSecurityTests.createBasicAuthHeader(username,
|
||||
password);
|
||||
|
||||
String usernameResult = new RestTemplate()
|
||||
.exchange("http://localhost:" + serverPort + "/proxy-username",
|
||||
HttpMethod.GET, new HttpEntity<Void>(headers), String.class)
|
||||
.getBody();
|
||||
|
||||
Assert.assertTrue("Username should have been intercepted by feign interceptor.",
|
||||
username.equals(usernameResult));
|
||||
|
||||
Assert.assertTrue("Custom hook should have been called.",
|
||||
customConcurrenyStrategy.isHookCalled());
|
||||
}
|
||||
|
||||
public static HttpHeaders createBasicAuthHeader(final String username,
|
||||
final String password) {
|
||||
return new HttpHeaders() {
|
||||
private static final long serialVersionUID = 1766341693637204893L;
|
||||
|
||||
{
|
||||
String auth = username + ":" + password;
|
||||
byte[] encodedAuth = Base64.getEncoder().encode(auth.getBytes());
|
||||
String authHeader = "Basic " + new String(encodedAuth);
|
||||
this.set("Authorization", authHeader);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.springframework.cloud.openfeign.hystrix.security.app;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
|
||||
|
||||
@Component
|
||||
public class CustomConcurrenyStrategy extends HystrixConcurrencyStrategy {
|
||||
private boolean hookCalled;
|
||||
|
||||
@Override
|
||||
public <T> Callable<T> wrapCallable(Callable<T> callable) {
|
||||
this.hookCalled = true;
|
||||
|
||||
return super.wrapCallable(callable);
|
||||
}
|
||||
|
||||
public boolean isHookCalled() {
|
||||
return hookCalled;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.openfeign.hystrix.security.app;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @author Daniel Lavoie
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/proxy-username")
|
||||
public class ProxyUsernameController {
|
||||
@Autowired
|
||||
private UsernameClient usernameClient;
|
||||
|
||||
@RequestMapping
|
||||
public String getUsername() {
|
||||
return usernameClient.getUsername();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.openfeign.hystrix.security.app;
|
||||
|
||||
import feign.RequestInterceptor;
|
||||
import feign.RequestTemplate;
|
||||
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* This interceptor should be called from an Hyxtrix command execution thread. It is
|
||||
* access the SecurityContext and settings an http header from the authentication details.
|
||||
*
|
||||
* @author Daniel Lavoie
|
||||
*/
|
||||
@Component
|
||||
public class TestInterceptor implements RequestInterceptor {
|
||||
|
||||
@Override
|
||||
public void apply(RequestTemplate template) {
|
||||
if (SecurityContextHolder.getContext().getAuthentication() != null)
|
||||
template.header("username",
|
||||
SecurityContextHolder.getContext().getAuthentication().getName());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.openfeign.hystrix.security.app;
|
||||
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
/**
|
||||
* @author Daniel Lavoie
|
||||
*/
|
||||
@FeignClient("username")
|
||||
public interface UsernameClient {
|
||||
|
||||
@RequestMapping("/username")
|
||||
public String getUsername();
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.openfeign.hystrix.security.app;
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @author Daniel Lavoie
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/username")
|
||||
public class UsernameController {
|
||||
@RequestMapping
|
||||
public String getUsername(@RequestHeader String username){
|
||||
return username;
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
package org.springframework.cloud.openfeign.ribbon;
|
||||
package org.springframework.cloud.netflix.feign.ribbon;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import javax.net.ssl.SSLContextSpi;
|
||||
@@ -30,10 +30,11 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.openfeign.ribbon.FeignRibbonClientRetryTests;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
@@ -42,8 +43,10 @@ import static org.junit.Assert.assertNull;
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = FeignRibbonHttpClientConfigurationTests.Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
@SpringBootTest(classes = FeignRibbonHttpClientConfigurationTests.FeignRibbonHttpClientConfigurationTestsApplication.class,
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
properties = {"debug=true","feign.httpclient.disableSslValidation=true"})
|
||||
@DirtiesContext
|
||||
public class FeignRibbonHttpClientConfigurationTests {
|
||||
|
||||
@Autowired
|
||||
@@ -77,11 +80,10 @@ public class FeignRibbonHttpClientConfigurationTests {
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@RestController
|
||||
public static class Application {
|
||||
static class FeignRibbonHttpClientConfigurationTestsApplication {
|
||||
public static void main(String[] args) {
|
||||
new SpringApplicationBuilder(FeignRibbonClientRetryTests.Application.class)
|
||||
.run(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
package org.springframework.cloud.openfeign.ribbon;
|
||||
package org.springframework.cloud.netflix.feign.ribbon;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
@@ -28,18 +28,21 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.commons.httpclient.OkHttpClientFactory;
|
||||
import org.springframework.cloud.openfeign.ribbon.FeignRibbonClientRetryTests;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = FeignRibbonOkHttpClientConfigurationTests.Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
@SpringBootTest(classes = FeignRibbonOkHttpClientConfigurationTests.FeignRibbonOkHttpClientConfigurationTestsApplication.class,
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
properties = {"debug=true","feign.httpclient.disableSslValidation=true",
|
||||
"feign.okhttp.enabled=true", "feign.httpclient.enabled=false"})
|
||||
@DirtiesContext
|
||||
public class FeignRibbonOkHttpClientConfigurationTests {
|
||||
|
||||
@Autowired
|
||||
@@ -60,11 +63,10 @@ public class FeignRibbonOkHttpClientConfigurationTests {
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@RestController
|
||||
public static class Application {
|
||||
static class FeignRibbonOkHttpClientConfigurationTestsApplication {
|
||||
public static void main(String[] args) {
|
||||
new SpringApplicationBuilder(FeignRibbonClientRetryTests.Application.class)
|
||||
.run(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,11 @@
|
||||
<artifactId>spring-cloud-openfeign-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.openfeign</groupId>
|
||||
<artifactId>feign-core</artifactId>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-openfeign</artifactId>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
<relativePath>..</relativePath>
|
||||
</parent>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
<name>Spring Cloud Starter OpenFeign</name>
|
||||
@@ -15,7 +16,7 @@
|
||||
<url>https://www.spring.io</url>
|
||||
</organization>
|
||||
<properties>
|
||||
<main.basedir>${basedir}/../../..</main.basedir>
|
||||
<main.basedir>${basedir}/../..</main.basedir>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
@@ -25,7 +26,6 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-openfeign-core</artifactId>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
|
||||
@@ -1 +1 @@
|
||||
provides: spring-platform-netflix-core, eureka-client
|
||||
provides: spring-cloud-openfeign-core
|
||||
Reference in New Issue
Block a user