Polish
This commit is contained in:
parent
2319d01feb
commit
960083bd33
|
@ -23,7 +23,6 @@ import java.security.PublicKey;
|
||||||
import java.security.Signature;
|
import java.security.Signature;
|
||||||
import java.security.spec.InvalidKeySpecException;
|
import java.security.spec.InvalidKeySpecException;
|
||||||
import java.security.spec.X509EncodedKeySpec;
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
@ -71,24 +70,31 @@ class ReactiveTokenValidator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mono<Void> validateKeyIdAndSignature(Token token) {
|
private Mono<Void> validateKeyIdAndSignature(Token token) {
|
||||||
String keyId = token.getKeyId();
|
return getTokenKey(token).filter((tokenKey) -> hasValidSignature(token, tokenKey))
|
||||||
Map<String, String> localCachedTokenKeys = new HashMap<>(this.cachedTokenKeys);
|
|
||||||
return Mono.just(localCachedTokenKeys)
|
|
||||||
.filter((tokenKeys) -> tokenKeys.containsKey(keyId))
|
|
||||||
.switchIfEmpty(this.securityService.fetchTokenKeys()
|
|
||||||
.doOnSuccess((fetchedTokenKeys) -> {
|
|
||||||
this.cachedTokenKeys.clear();
|
|
||||||
this.cachedTokenKeys.putAll(fetchedTokenKeys);
|
|
||||||
}).filter((tokenKeys) -> tokenKeys.containsKey(keyId))
|
|
||||||
.switchIfEmpty((Mono.error(new CloudFoundryAuthorizationException(
|
|
||||||
Reason.INVALID_KEY_ID,
|
|
||||||
"Key Id present in token header does not match")))))
|
|
||||||
.filter((tokenKeys) -> hasValidSignature(token, tokenKeys.get(keyId)))
|
|
||||||
.switchIfEmpty(Mono.error(new CloudFoundryAuthorizationException(
|
.switchIfEmpty(Mono.error(new CloudFoundryAuthorizationException(
|
||||||
Reason.INVALID_SIGNATURE, "RSA Signature did not match content")))
|
Reason.INVALID_SIGNATURE, "RSA Signature did not match content")))
|
||||||
.then();
|
.then();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Mono<String> getTokenKey(Token token) {
|
||||||
|
String keyId = token.getKeyId();
|
||||||
|
String cached = this.cachedTokenKeys.get(keyId);
|
||||||
|
if (cached != null) {
|
||||||
|
return Mono.just(cached);
|
||||||
|
}
|
||||||
|
return this.securityService.fetchTokenKeys().doOnSuccess(this::cacheTokenKeys)
|
||||||
|
.filter((tokenKeys) -> tokenKeys.containsKey(keyId))
|
||||||
|
.map((tokenKeys) -> tokenKeys.get(keyId))
|
||||||
|
.switchIfEmpty(Mono.error(
|
||||||
|
new CloudFoundryAuthorizationException(Reason.INVALID_KEY_ID,
|
||||||
|
"Key Id present in token header does not match")));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cacheTokenKeys(Map<String, String> tokenKeys) {
|
||||||
|
this.cachedTokenKeys.clear();
|
||||||
|
this.cachedTokenKeys.putAll(tokenKeys);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean hasValidSignature(Token token, String key) {
|
private boolean hasValidSignature(Token token, String key) {
|
||||||
try {
|
try {
|
||||||
PublicKey publicKey = getPublicKey(key);
|
PublicKey publicKey = getPublicKey(key);
|
||||||
|
|
|
@ -28,8 +28,8 @@ import org.springframework.boot.actuate.autoconfigure.metrics.export.PropertiesC
|
||||||
* @author Jon Schneider
|
* @author Jon Schneider
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
*/
|
*/
|
||||||
class AtlasPropertiesConfigAdapter extends
|
class AtlasPropertiesConfigAdapter extends PropertiesConfigAdapter<AtlasProperties>
|
||||||
PropertiesConfigAdapter<AtlasProperties> implements AtlasConfig {
|
implements AtlasConfig {
|
||||||
|
|
||||||
AtlasPropertiesConfigAdapter(AtlasProperties properties) {
|
AtlasPropertiesConfigAdapter(AtlasProperties properties) {
|
||||||
super(properties);
|
super(properties);
|
||||||
|
|
|
@ -30,8 +30,7 @@ import org.springframework.boot.actuate.autoconfigure.metrics.export.PropertiesC
|
||||||
* @author Jon Schneider
|
* @author Jon Schneider
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
*/
|
*/
|
||||||
class GangliaPropertiesConfigAdapter
|
class GangliaPropertiesConfigAdapter extends PropertiesConfigAdapter<GangliaProperties>
|
||||||
extends PropertiesConfigAdapter<GangliaProperties>
|
|
||||||
implements GangliaConfig {
|
implements GangliaConfig {
|
||||||
|
|
||||||
GangliaPropertiesConfigAdapter(GangliaProperties properties) {
|
GangliaPropertiesConfigAdapter(GangliaProperties properties) {
|
||||||
|
|
|
@ -30,8 +30,7 @@ import org.springframework.boot.actuate.autoconfigure.metrics.export.PropertiesC
|
||||||
* @author Jon Schneider
|
* @author Jon Schneider
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
*/
|
*/
|
||||||
class GraphitePropertiesConfigAdapter
|
class GraphitePropertiesConfigAdapter extends PropertiesConfigAdapter<GraphiteProperties>
|
||||||
extends PropertiesConfigAdapter<GraphiteProperties>
|
|
||||||
implements GraphiteConfig {
|
implements GraphiteConfig {
|
||||||
|
|
||||||
GraphitePropertiesConfigAdapter(GraphiteProperties properties) {
|
GraphitePropertiesConfigAdapter(GraphiteProperties properties) {
|
||||||
|
|
|
@ -28,9 +28,8 @@ import org.springframework.boot.actuate.autoconfigure.metrics.export.PropertiesC
|
||||||
* @author Jon Schneider
|
* @author Jon Schneider
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
*/
|
*/
|
||||||
class PrometheusPropertiesConfigAdapter
|
class PrometheusPropertiesConfigAdapter extends
|
||||||
extends PropertiesConfigAdapter<PrometheusProperties>
|
PropertiesConfigAdapter<PrometheusProperties> implements PrometheusConfig {
|
||||||
implements PrometheusConfig {
|
|
||||||
|
|
||||||
PrometheusPropertiesConfigAdapter(PrometheusProperties properties) {
|
PrometheusPropertiesConfigAdapter(PrometheusProperties properties) {
|
||||||
super(properties);
|
super(properties);
|
||||||
|
|
|
@ -28,8 +28,8 @@ import org.springframework.boot.actuate.autoconfigure.metrics.export.PropertiesC
|
||||||
* @author Jon Schneider
|
* @author Jon Schneider
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
public class SimplePropertiesConfigAdapter extends
|
public class SimplePropertiesConfigAdapter
|
||||||
PropertiesConfigAdapter<SimpleProperties> implements SimpleConfig {
|
extends PropertiesConfigAdapter<SimpleProperties> implements SimpleConfig {
|
||||||
|
|
||||||
public SimplePropertiesConfigAdapter(SimpleProperties properties) {
|
public SimplePropertiesConfigAdapter(SimpleProperties properties) {
|
||||||
super(properties);
|
super(properties);
|
||||||
|
|
|
@ -29,8 +29,8 @@ import org.springframework.boot.actuate.autoconfigure.metrics.export.PropertiesC
|
||||||
* @author Jon Schneider
|
* @author Jon Schneider
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
public class StatsdPropertiesConfigAdapter extends
|
public class StatsdPropertiesConfigAdapter
|
||||||
PropertiesConfigAdapter<StatsdProperties> implements StatsdConfig {
|
extends PropertiesConfigAdapter<StatsdProperties> implements StatsdConfig {
|
||||||
|
|
||||||
public StatsdPropertiesConfigAdapter(StatsdProperties properties) {
|
public StatsdPropertiesConfigAdapter(StatsdProperties properties) {
|
||||||
super(properties);
|
super(properties);
|
||||||
|
|
|
@ -93,8 +93,10 @@ public class ReactiveTokenValidatorTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validateTokenWhenKidValidationFailsTwiceShouldThrowException() throws Exception {
|
public void validateTokenWhenKidValidationFailsTwiceShouldThrowException()
|
||||||
PublisherProbe<Map<String, String>> fetchTokenKeys = PublisherProbe.of(Mono.just(VALID_KEYS));
|
throws Exception {
|
||||||
|
PublisherProbe<Map<String, String>> fetchTokenKeys = PublisherProbe
|
||||||
|
.of(Mono.just(VALID_KEYS));
|
||||||
ReflectionTestUtils.setField(this.tokenValidator, "cachedTokenKeys", VALID_KEYS);
|
ReflectionTestUtils.setField(this.tokenValidator, "cachedTokenKeys", VALID_KEYS);
|
||||||
given(this.securityService.fetchTokenKeys()).willReturn(fetchTokenKeys.mono());
|
given(this.securityService.fetchTokenKeys()).willReturn(fetchTokenKeys.mono());
|
||||||
given(this.securityService.getUaaUrl())
|
given(this.securityService.getUaaUrl())
|
||||||
|
@ -110,15 +112,19 @@ public class ReactiveTokenValidatorTests {
|
||||||
assertThat(((CloudFoundryAuthorizationException) ex).getReason())
|
assertThat(((CloudFoundryAuthorizationException) ex).getReason())
|
||||||
.isEqualTo(Reason.INVALID_KEY_ID);
|
.isEqualTo(Reason.INVALID_KEY_ID);
|
||||||
}).verify();
|
}).verify();
|
||||||
Object cachedTokenKeys = ReflectionTestUtils.getField(this.tokenValidator, "cachedTokenKeys");
|
Object cachedTokenKeys = ReflectionTestUtils.getField(this.tokenValidator,
|
||||||
|
"cachedTokenKeys");
|
||||||
assertThat(cachedTokenKeys).isEqualTo(VALID_KEYS);
|
assertThat(cachedTokenKeys).isEqualTo(VALID_KEYS);
|
||||||
fetchTokenKeys.assertWasSubscribed();
|
fetchTokenKeys.assertWasSubscribed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validateTokenWhenKidValidationSucceedsInTheSecondAttempt() throws Exception {
|
public void validateTokenWhenKidValidationSucceedsInTheSecondAttempt()
|
||||||
PublisherProbe<Map<String, String>> fetchTokenKeys = PublisherProbe.of(Mono.just(VALID_KEYS));
|
throws Exception {
|
||||||
ReflectionTestUtils.setField(this.tokenValidator, "cachedTokenKeys", INVALID_KEYS);
|
PublisherProbe<Map<String, String>> fetchTokenKeys = PublisherProbe
|
||||||
|
.of(Mono.just(VALID_KEYS));
|
||||||
|
ReflectionTestUtils.setField(this.tokenValidator, "cachedTokenKeys",
|
||||||
|
INVALID_KEYS);
|
||||||
given(this.securityService.fetchTokenKeys()).willReturn(fetchTokenKeys.mono());
|
given(this.securityService.fetchTokenKeys()).willReturn(fetchTokenKeys.mono());
|
||||||
given(this.securityService.getUaaUrl())
|
given(this.securityService.getUaaUrl())
|
||||||
.willReturn(Mono.just("http://localhost:8080/uaa"));
|
.willReturn(Mono.just("http://localhost:8080/uaa"));
|
||||||
|
@ -128,14 +134,16 @@ public class ReactiveTokenValidatorTests {
|
||||||
.create(this.tokenValidator.validate(
|
.create(this.tokenValidator.validate(
|
||||||
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||||
.verifyComplete();
|
.verifyComplete();
|
||||||
Object cachedTokenKeys = ReflectionTestUtils.getField(this.tokenValidator, "cachedTokenKeys");
|
Object cachedTokenKeys = ReflectionTestUtils.getField(this.tokenValidator,
|
||||||
|
"cachedTokenKeys");
|
||||||
assertThat(cachedTokenKeys).isEqualTo(VALID_KEYS);
|
assertThat(cachedTokenKeys).isEqualTo(VALID_KEYS);
|
||||||
fetchTokenKeys.assertWasSubscribed();
|
fetchTokenKeys.assertWasSubscribed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validateTokenWhenCacheIsEmptyShouldFetchTokenKeys() throws Exception {
|
public void validateTokenWhenCacheIsEmptyShouldFetchTokenKeys() throws Exception {
|
||||||
PublisherProbe<Map<String, String>> fetchTokenKeys = PublisherProbe.of(Mono.just(VALID_KEYS));
|
PublisherProbe<Map<String, String>> fetchTokenKeys = PublisherProbe
|
||||||
|
.of(Mono.just(VALID_KEYS));
|
||||||
given(this.securityService.fetchTokenKeys()).willReturn(fetchTokenKeys.mono());
|
given(this.securityService.fetchTokenKeys()).willReturn(fetchTokenKeys.mono());
|
||||||
given(this.securityService.getUaaUrl())
|
given(this.securityService.getUaaUrl())
|
||||||
.willReturn(Mono.just("http://localhost:8080/uaa"));
|
.willReturn(Mono.just("http://localhost:8080/uaa"));
|
||||||
|
@ -145,14 +153,17 @@ public class ReactiveTokenValidatorTests {
|
||||||
.create(this.tokenValidator.validate(
|
.create(this.tokenValidator.validate(
|
||||||
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||||
.verifyComplete();
|
.verifyComplete();
|
||||||
Object cachedTokenKeys = ReflectionTestUtils.getField(this.tokenValidator, "cachedTokenKeys");
|
Object cachedTokenKeys = ReflectionTestUtils.getField(this.tokenValidator,
|
||||||
|
"cachedTokenKeys");
|
||||||
assertThat(cachedTokenKeys).isEqualTo(VALID_KEYS);
|
assertThat(cachedTokenKeys).isEqualTo(VALID_KEYS);
|
||||||
fetchTokenKeys.assertWasSubscribed();
|
fetchTokenKeys.assertWasSubscribed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validateTokenWhenCacheEmptyAndInvalidKeyShouldThrowException() throws Exception {
|
public void validateTokenWhenCacheEmptyAndInvalidKeyShouldThrowException()
|
||||||
PublisherProbe<Map<String, String>> fetchTokenKeys = PublisherProbe.of(Mono.just(VALID_KEYS));
|
throws Exception {
|
||||||
|
PublisherProbe<Map<String, String>> fetchTokenKeys = PublisherProbe
|
||||||
|
.of(Mono.just(VALID_KEYS));
|
||||||
given(this.securityService.fetchTokenKeys()).willReturn(fetchTokenKeys.mono());
|
given(this.securityService.fetchTokenKeys()).willReturn(fetchTokenKeys.mono());
|
||||||
given(this.securityService.getUaaUrl())
|
given(this.securityService.getUaaUrl())
|
||||||
.willReturn(Mono.just("http://localhost:8080/uaa"));
|
.willReturn(Mono.just("http://localhost:8080/uaa"));
|
||||||
|
@ -167,7 +178,8 @@ public class ReactiveTokenValidatorTests {
|
||||||
assertThat(((CloudFoundryAuthorizationException) ex).getReason())
|
assertThat(((CloudFoundryAuthorizationException) ex).getReason())
|
||||||
.isEqualTo(Reason.INVALID_KEY_ID);
|
.isEqualTo(Reason.INVALID_KEY_ID);
|
||||||
}).verify();
|
}).verify();
|
||||||
Object cachedTokenKeys = ReflectionTestUtils.getField(this.tokenValidator, "cachedTokenKeys");
|
Object cachedTokenKeys = ReflectionTestUtils.getField(this.tokenValidator,
|
||||||
|
"cachedTokenKeys");
|
||||||
assertThat(cachedTokenKeys).isEqualTo(VALID_KEYS);
|
assertThat(cachedTokenKeys).isEqualTo(VALID_KEYS);
|
||||||
fetchTokenKeys.assertWasSubscribed();
|
fetchTokenKeys.assertWasSubscribed();
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,8 +42,8 @@ public class CouchbaseHealthIndicatorTests {
|
||||||
public void couchbaseIsUp() {
|
public void couchbaseIsUp() {
|
||||||
CouchbaseOperations couchbaseOperations = mock(CouchbaseOperations.class);
|
CouchbaseOperations couchbaseOperations = mock(CouchbaseOperations.class);
|
||||||
ClusterInfo clusterInfo = mock(ClusterInfo.class);
|
ClusterInfo clusterInfo = mock(ClusterInfo.class);
|
||||||
given(clusterInfo.getAllVersions()).willReturn(
|
given(clusterInfo.getAllVersions())
|
||||||
Arrays.asList(new Version(1, 2, 3)));
|
.willReturn(Arrays.asList(new Version(1, 2, 3)));
|
||||||
given(couchbaseOperations.getCouchbaseClusterInfo()).willReturn(clusterInfo);
|
given(couchbaseOperations.getCouchbaseClusterInfo()).willReturn(clusterInfo);
|
||||||
CouchbaseHealthIndicator healthIndicator = new CouchbaseHealthIndicator(
|
CouchbaseHealthIndicator healthIndicator = new CouchbaseHealthIndicator(
|
||||||
couchbaseOperations);
|
couchbaseOperations);
|
||||||
|
@ -56,8 +56,8 @@ public class CouchbaseHealthIndicatorTests {
|
||||||
@Test
|
@Test
|
||||||
public void couchbaseIsDown() {
|
public void couchbaseIsDown() {
|
||||||
CouchbaseOperations couchbaseOperations = mock(CouchbaseOperations.class);
|
CouchbaseOperations couchbaseOperations = mock(CouchbaseOperations.class);
|
||||||
given(couchbaseOperations.getCouchbaseClusterInfo()).willThrow(
|
given(couchbaseOperations.getCouchbaseClusterInfo())
|
||||||
new IllegalStateException("test, expected"));
|
.willThrow(new IllegalStateException("test, expected"));
|
||||||
CouchbaseHealthIndicator healthIndicator = new CouchbaseHealthIndicator(
|
CouchbaseHealthIndicator healthIndicator = new CouchbaseHealthIndicator(
|
||||||
couchbaseOperations);
|
couchbaseOperations);
|
||||||
Health health = healthIndicator.health();
|
Health health = healthIndicator.health();
|
||||||
|
|
|
@ -19,7 +19,7 @@ package org.springframework.boot.autoconfigure.data.alt.couchbase;
|
||||||
import org.springframework.boot.autoconfigure.data.couchbase.city.City;
|
import org.springframework.boot.autoconfigure.data.couchbase.city.City;
|
||||||
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
|
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
|
||||||
|
|
||||||
public interface ReactiveCityCouchbaseRepository extends
|
public interface ReactiveCityCouchbaseRepository
|
||||||
ReactiveCrudRepository<City, Long> {
|
extends ReactiveCrudRepository<City, Long> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue