Merge branch '2.7.x' into 3.0.x
This commit is contained in:
@@ -48,7 +48,7 @@ public abstract class OnEndpointElementCondition extends SpringBootCondition {
|
||||
@Override
|
||||
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
AnnotationAttributes annotationAttributes = AnnotationAttributes
|
||||
.fromMap(metadata.getAnnotationAttributes(this.annotationType.getName()));
|
||||
.fromMap(metadata.getAnnotationAttributes(this.annotationType.getName()));
|
||||
String endpointName = annotationAttributes.getString("value");
|
||||
ConditionOutcome outcome = getEndpointOutcome(context, endpointName);
|
||||
if (outcome != null) {
|
||||
@@ -63,7 +63,7 @@ public abstract class OnEndpointElementCondition extends SpringBootCondition {
|
||||
if (environment.containsProperty(enabledProperty)) {
|
||||
boolean match = environment.getProperty(enabledProperty, Boolean.class, true);
|
||||
return new ConditionOutcome(match, ConditionMessage.forCondition(this.annotationType)
|
||||
.because(this.prefix + endpointName + ".enabled is " + match));
|
||||
.because(this.prefix + endpointName + ".enabled is " + match));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -79,9 +79,9 @@ public abstract class OnEndpointElementCondition extends SpringBootCondition {
|
||||
*/
|
||||
protected ConditionOutcome getDefaultOutcome(ConditionContext context, AnnotationAttributes annotationAttributes) {
|
||||
boolean match = Boolean
|
||||
.parseBoolean(context.getEnvironment().getProperty(this.prefix + "defaults.enabled", "true"));
|
||||
.parseBoolean(context.getEnvironment().getProperty(this.prefix + "defaults.enabled", "true"));
|
||||
return new ConditionOutcome(match, ConditionMessage.forCondition(this.annotationType)
|
||||
.because(this.prefix + "defaults.enabled is considered " + match));
|
||||
.because(this.prefix + "defaults.enabled is considered " + match));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -36,7 +36,7 @@ class AvailabilityProbesHealthEndpointGroupsPostProcessor implements HealthEndpo
|
||||
|
||||
AvailabilityProbesHealthEndpointGroupsPostProcessor(Environment environment) {
|
||||
this.addAdditionalPaths = "true"
|
||||
.equalsIgnoreCase(environment.getProperty("management.endpoint.health.probes.add-additional-paths"));
|
||||
.equalsIgnoreCase(environment.getProperty("management.endpoint.health.probes.add-additional-paths"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -73,8 +73,11 @@ public class CloudFoundryWebEndpointDiscoverer extends WebEndpointDiscoverer {
|
||||
}
|
||||
|
||||
private boolean isHealthEndpointExtension(Class<?> extensionBeanType) {
|
||||
return MergedAnnotations.from(extensionBeanType).get(EndpointWebExtension.class)
|
||||
.getValue("endpoint", Class.class).map(HealthEndpoint.class::isAssignableFrom).orElse(false);
|
||||
return MergedAnnotations.from(extensionBeanType)
|
||||
.get(EndpointWebExtension.class)
|
||||
.getValue("endpoint", Class.class)
|
||||
.map(HealthEndpoint.class::isAssignableFrom)
|
||||
.orElse(false);
|
||||
}
|
||||
|
||||
private boolean isCloudFoundryHealthEndpointExtension(Class<?> extensionBeanType) {
|
||||
@@ -85,8 +88,8 @@ public class CloudFoundryWebEndpointDiscoverer extends WebEndpointDiscoverer {
|
||||
|
||||
@Override
|
||||
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
|
||||
hints.reflection().registerType(CloudFoundryEndpointFilter.class,
|
||||
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
|
||||
hints.reflection()
|
||||
.registerType(CloudFoundryEndpointFilter.class, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -80,12 +80,12 @@ class CloudFoundrySecurityInterceptor {
|
||||
try {
|
||||
Token token = getToken(exchange.getRequest());
|
||||
return this.tokenValidator.validate(token)
|
||||
.then(this.cloudFoundrySecurityService.getAccessLevel(token.toString(), this.applicationId))
|
||||
.filter((accessLevel) -> accessLevel.isAccessAllowed(id))
|
||||
.switchIfEmpty(
|
||||
Mono.error(new CloudFoundryAuthorizationException(Reason.ACCESS_DENIED, "Access denied")))
|
||||
.doOnSuccess((accessLevel) -> exchange.getAttributes().put("cloudFoundryAccessLevel", accessLevel))
|
||||
.then();
|
||||
.then(this.cloudFoundrySecurityService.getAccessLevel(token.toString(), this.applicationId))
|
||||
.filter((accessLevel) -> accessLevel.isAccessAllowed(id))
|
||||
.switchIfEmpty(
|
||||
Mono.error(new CloudFoundryAuthorizationException(Reason.ACCESS_DENIED, "Access denied")))
|
||||
.doOnSuccess((accessLevel) -> exchange.getAttributes().put("cloudFoundryAccessLevel", accessLevel))
|
||||
.then();
|
||||
}
|
||||
catch (CloudFoundryAuthorizationException ex) {
|
||||
return Mono.error(ex);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -91,26 +91,26 @@ class CloudFoundryWebFluxEndpointHandlerMapping extends AbstractWebFluxEndpointH
|
||||
public Publisher<ResponseEntity<Object>> links(ServerWebExchange exchange) {
|
||||
ServerHttpRequest request = exchange.getRequest();
|
||||
return CloudFoundryWebFluxEndpointHandlerMapping.this.securityInterceptor.preHandle(exchange, "")
|
||||
.map((securityResponse) -> {
|
||||
if (!securityResponse.getStatus().equals(HttpStatus.OK)) {
|
||||
return new ResponseEntity<>(securityResponse.getStatus());
|
||||
}
|
||||
AccessLevel accessLevel = exchange.getAttribute(AccessLevel.REQUEST_ATTRIBUTE);
|
||||
Map<String, Link> links = CloudFoundryWebFluxEndpointHandlerMapping.this.linksResolver
|
||||
.resolveLinks(request.getURI().toString());
|
||||
return new ResponseEntity<>(
|
||||
Collections.singletonMap("_links", getAccessibleLinks(accessLevel, links)),
|
||||
HttpStatus.OK);
|
||||
});
|
||||
.map((securityResponse) -> {
|
||||
if (!securityResponse.getStatus().equals(HttpStatus.OK)) {
|
||||
return new ResponseEntity<>(securityResponse.getStatus());
|
||||
}
|
||||
AccessLevel accessLevel = exchange.getAttribute(AccessLevel.REQUEST_ATTRIBUTE);
|
||||
Map<String, Link> links = CloudFoundryWebFluxEndpointHandlerMapping.this.linksResolver
|
||||
.resolveLinks(request.getURI().toString());
|
||||
return new ResponseEntity<>(
|
||||
Collections.singletonMap("_links", getAccessibleLinks(accessLevel, links)), HttpStatus.OK);
|
||||
});
|
||||
}
|
||||
|
||||
private Map<String, Link> getAccessibleLinks(AccessLevel accessLevel, Map<String, Link> links) {
|
||||
if (accessLevel == null) {
|
||||
return new LinkedHashMap<>();
|
||||
}
|
||||
return links.entrySet().stream()
|
||||
.filter((entry) -> entry.getKey().equals("self") || accessLevel.isAccessAllowed(entry.getKey()))
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
return links.entrySet()
|
||||
.stream()
|
||||
.filter((entry) -> entry.getKey().equals("self") || accessLevel.isAccessAllowed(entry.getKey()))
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -141,7 +141,7 @@ class CloudFoundryWebFluxEndpointHandlerMapping extends AbstractWebFluxEndpointH
|
||||
@Override
|
||||
public Mono<ResponseEntity<Object>> handle(ServerWebExchange exchange, Map<String, String> body) {
|
||||
return this.securityInterceptor.preHandle(exchange, this.endpointId.toLowerCaseString())
|
||||
.flatMap((securityResponse) -> flatMapResponse(exchange, body, securityResponse));
|
||||
.flatMap((securityResponse) -> flatMapResponse(exchange, body, securityResponse));
|
||||
}
|
||||
|
||||
private Mono<ResponseEntity<Object>> flatMapResponse(ServerWebExchange exchange, Map<String, String> body,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -96,9 +96,9 @@ public class ReactiveCloudFoundryActuatorAutoConfiguration {
|
||||
public CloudFoundryInfoEndpointWebExtension cloudFoundryInfoEndpointWebExtension(GitProperties properties,
|
||||
ObjectProvider<InfoContributor> infoContributors) {
|
||||
List<InfoContributor> contributors = infoContributors.orderedStream()
|
||||
.map((infoContributor) -> (infoContributor instanceof GitInfoContributor)
|
||||
? new GitInfoContributor(properties, InfoPropertiesInfoContributor.Mode.FULL) : infoContributor)
|
||||
.toList();
|
||||
.map((infoContributor) -> (infoContributor instanceof GitInfoContributor)
|
||||
? new GitInfoContributor(properties, InfoPropertiesInfoContributor.Mode.FULL) : infoContributor)
|
||||
.toList();
|
||||
return new CloudFoundryInfoEndpointWebExtension(new InfoEndpoint(contributors));
|
||||
}
|
||||
|
||||
@@ -143,8 +143,8 @@ public class ReactiveCloudFoundryActuatorAutoConfiguration {
|
||||
CorsConfiguration corsConfiguration = new CorsConfiguration();
|
||||
corsConfiguration.addAllowedOrigin(CorsConfiguration.ALL);
|
||||
corsConfiguration.setAllowedMethods(Arrays.asList(HttpMethod.GET.name(), HttpMethod.POST.name()));
|
||||
corsConfiguration.setAllowedHeaders(
|
||||
Arrays.asList(HttpHeaders.AUTHORIZATION, "X-Cf-App-Instance", HttpHeaders.CONTENT_TYPE));
|
||||
corsConfiguration
|
||||
.setAllowedHeaders(Arrays.asList(HttpHeaders.AUTHORIZATION, "X-Cf-App-Instance", HttpHeaders.CONTENT_TYPE));
|
||||
return corsConfiguration;
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ public class ReactiveCloudFoundryActuatorAutoConfiguration {
|
||||
|
||||
private WebFilterChainProxy postProcess(WebFilterChainProxy existing) {
|
||||
ServerWebExchangeMatcher cloudFoundryRequestMatcher = ServerWebExchangeMatchers
|
||||
.pathMatchers("/cloudfoundryapplication/**");
|
||||
.pathMatchers("/cloudfoundryapplication/**");
|
||||
WebFilter noOpFilter = (exchange, chain) -> chain.filter(exchange);
|
||||
MatcherSecurityWebFilterChain ignoredRequestFilterChain = new MatcherSecurityWebFilterChain(
|
||||
cloudFoundryRequestMatcher, Collections.singletonList(noOpFilter));
|
||||
|
||||
@@ -72,8 +72,9 @@ class ReactiveCloudFoundrySecurityService {
|
||||
}
|
||||
|
||||
private Http11SslContextSpec createSslContextSpec() {
|
||||
return Http11SslContextSpec.forClient().configure(
|
||||
(builder) -> builder.sslProvider(SslProvider.JDK).trustManager(InsecureTrustManagerFactory.INSTANCE));
|
||||
return Http11SslContextSpec.forClient()
|
||||
.configure((builder) -> builder.sslProvider(SslProvider.JDK)
|
||||
.trustManager(InsecureTrustManagerFactory.INSTANCE));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,8 +86,13 @@ class ReactiveCloudFoundrySecurityService {
|
||||
*/
|
||||
Mono<AccessLevel> getAccessLevel(String token, String applicationId) throws CloudFoundryAuthorizationException {
|
||||
String uri = getPermissionsUri(applicationId);
|
||||
return this.webClient.get().uri(uri).header("Authorization", "bearer " + token).retrieve().bodyToMono(Map.class)
|
||||
.map(this::getAccessLevel).onErrorMap(this::mapError);
|
||||
return this.webClient.get()
|
||||
.uri(uri)
|
||||
.header("Authorization", "bearer " + token)
|
||||
.retrieve()
|
||||
.bodyToMono(Map.class)
|
||||
.map(this::getAccessLevel)
|
||||
.onErrorMap(this::mapError);
|
||||
}
|
||||
|
||||
private Throwable mapError(Throwable throwable) {
|
||||
@@ -123,8 +129,10 @@ class ReactiveCloudFoundrySecurityService {
|
||||
|
||||
private Mono<? extends Map<String, String>> fetchTokenKeys(String url) {
|
||||
RequestHeadersSpec<?> uri = this.webClient.get().uri(url + "/token_keys");
|
||||
return uri.retrieve().bodyToMono(STRING_OBJECT_MAP).map(this::extractTokenKeys).onErrorMap(
|
||||
((ex) -> new CloudFoundryAuthorizationException(Reason.SERVICE_UNAVAILABLE, ex.getMessage())));
|
||||
return uri.retrieve()
|
||||
.bodyToMono(STRING_OBJECT_MAP)
|
||||
.map(this::extractTokenKeys)
|
||||
.onErrorMap(((ex) -> new CloudFoundryAuthorizationException(Reason.SERVICE_UNAVAILABLE, ex.getMessage())));
|
||||
}
|
||||
|
||||
private Map<String, String> extractTokenKeys(Map<String, Object> response) {
|
||||
@@ -141,10 +149,14 @@ class ReactiveCloudFoundrySecurityService {
|
||||
* @return the UAA url Mono
|
||||
*/
|
||||
Mono<String> getUaaUrl() {
|
||||
this.uaaUrl = this.webClient.get().uri(this.cloudControllerUrl + "/info").retrieve().bodyToMono(Map.class)
|
||||
.map((response) -> (String) response.get("token_endpoint")).cache()
|
||||
.onErrorMap((ex) -> new CloudFoundryAuthorizationException(Reason.SERVICE_UNAVAILABLE,
|
||||
"Unable to fetch token keys from UAA."));
|
||||
this.uaaUrl = this.webClient.get()
|
||||
.uri(this.cloudControllerUrl + "/info")
|
||||
.retrieve()
|
||||
.bodyToMono(Map.class)
|
||||
.map((response) -> (String) response.get("token_endpoint"))
|
||||
.cache()
|
||||
.onErrorMap((ex) -> new CloudFoundryAuthorizationException(Reason.SERVICE_UNAVAILABLE,
|
||||
"Unable to fetch token keys from UAA."));
|
||||
return this.uaaUrl;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -51,8 +51,10 @@ class ReactiveTokenValidator {
|
||||
}
|
||||
|
||||
Mono<Void> validate(Token token) {
|
||||
return validateAlgorithm(token).then(validateKeyIdAndSignature(token)).then(validateExpiry(token))
|
||||
.then(validateIssuer(token)).then(validateAudience(token));
|
||||
return validateAlgorithm(token).then(validateKeyIdAndSignature(token))
|
||||
.then(validateExpiry(token))
|
||||
.then(validateIssuer(token))
|
||||
.then(validateAudience(token));
|
||||
}
|
||||
|
||||
private Mono<Void> validateAlgorithm(Token token) {
|
||||
@@ -70,9 +72,9 @@ class ReactiveTokenValidator {
|
||||
|
||||
private Mono<Void> validateKeyIdAndSignature(Token token) {
|
||||
return getTokenKey(token).filter((tokenKey) -> hasValidSignature(token, tokenKey))
|
||||
.switchIfEmpty(Mono.error(new CloudFoundryAuthorizationException(Reason.INVALID_SIGNATURE,
|
||||
"RSA Signature did not match content")))
|
||||
.then();
|
||||
.switchIfEmpty(Mono.error(new CloudFoundryAuthorizationException(Reason.INVALID_SIGNATURE,
|
||||
"RSA Signature did not match content")))
|
||||
.then();
|
||||
}
|
||||
|
||||
private Mono<String> getTokenKey(Token token) {
|
||||
@@ -81,10 +83,12 @@ class ReactiveTokenValidator {
|
||||
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")));
|
||||
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) {
|
||||
@@ -122,11 +126,12 @@ class ReactiveTokenValidator {
|
||||
}
|
||||
|
||||
private Mono<Void> validateIssuer(Token token) {
|
||||
return this.securityService.getUaaUrl().map((uaaUrl) -> String.format("%s/oauth/token", uaaUrl))
|
||||
.filter((issuerUri) -> issuerUri.equals(token.getIssuer()))
|
||||
.switchIfEmpty(Mono.error(
|
||||
new CloudFoundryAuthorizationException(Reason.INVALID_ISSUER, "Token issuer does not match")))
|
||||
.then();
|
||||
return this.securityService.getUaaUrl()
|
||||
.map((uaaUrl) -> String.format("%s/oauth/token", uaaUrl))
|
||||
.filter((issuerUri) -> issuerUri.equals(token.getIssuer()))
|
||||
.switchIfEmpty(Mono
|
||||
.error(new CloudFoundryAuthorizationException(Reason.INVALID_ISSUER, "Token issuer does not match")))
|
||||
.then();
|
||||
}
|
||||
|
||||
private Mono<Void> validateAudience(Token token) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -100,9 +100,9 @@ public class CloudFoundryActuatorAutoConfiguration {
|
||||
public CloudFoundryInfoEndpointWebExtension cloudFoundryInfoEndpointWebExtension(GitProperties properties,
|
||||
ObjectProvider<InfoContributor> infoContributors) {
|
||||
List<InfoContributor> contributors = infoContributors.orderedStream()
|
||||
.map((infoContributor) -> (infoContributor instanceof GitInfoContributor)
|
||||
? new GitInfoContributor(properties, InfoPropertiesInfoContributor.Mode.FULL) : infoContributor)
|
||||
.toList();
|
||||
.map((infoContributor) -> (infoContributor instanceof GitInfoContributor)
|
||||
? new GitInfoContributor(properties, InfoPropertiesInfoContributor.Mode.FULL) : infoContributor)
|
||||
.toList();
|
||||
return new CloudFoundryInfoEndpointWebExtension(new InfoEndpoint(contributors));
|
||||
}
|
||||
|
||||
@@ -147,8 +147,8 @@ public class CloudFoundryActuatorAutoConfiguration {
|
||||
CorsConfiguration corsConfiguration = new CorsConfiguration();
|
||||
corsConfiguration.addAllowedOrigin(CorsConfiguration.ALL);
|
||||
corsConfiguration.setAllowedMethods(Arrays.asList(HttpMethod.GET.name(), HttpMethod.POST.name()));
|
||||
corsConfiguration.setAllowedHeaders(
|
||||
Arrays.asList(HttpHeaders.AUTHORIZATION, "X-Cf-App-Instance", HttpHeaders.CONTENT_TYPE));
|
||||
corsConfiguration
|
||||
.setAllowedHeaders(Arrays.asList(HttpHeaders.AUTHORIZATION, "X-Cf-App-Instance", HttpHeaders.CONTENT_TYPE));
|
||||
return corsConfiguration;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -94,7 +94,7 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebMvcEndpoin
|
||||
@Reflective
|
||||
public Map<String, Map<String, Link>> links(HttpServletRequest request, HttpServletResponse response) {
|
||||
SecurityResponse securityResponse = CloudFoundryWebEndpointServletHandlerMapping.this.securityInterceptor
|
||||
.preHandle(request, null);
|
||||
.preHandle(request, null);
|
||||
if (!securityResponse.getStatus().equals(HttpStatus.OK)) {
|
||||
sendFailureResponse(response, securityResponse);
|
||||
}
|
||||
@@ -104,10 +104,11 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebMvcEndpoin
|
||||
return Collections.singletonMap("_links", filteredLinks);
|
||||
}
|
||||
Map<String, Link> links = CloudFoundryWebEndpointServletHandlerMapping.this.linksResolver
|
||||
.resolveLinks(request.getRequestURL().toString());
|
||||
filteredLinks = links.entrySet().stream()
|
||||
.filter((e) -> e.getKey().equals("self") || accessLevel.isAccessAllowed(e.getKey()))
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
.resolveLinks(request.getRequestURL().toString());
|
||||
filteredLinks = links.entrySet()
|
||||
.stream()
|
||||
.filter((e) -> e.getKey().equals("self") || accessLevel.isAccessAllowed(e.getKey()))
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
return Collections.singletonMap("_links", filteredLinks);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -68,7 +68,7 @@ class OnAvailableEndpointCondition extends SpringBootCondition {
|
||||
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
Environment environment = context.getEnvironment();
|
||||
MergedAnnotation<ConditionalOnAvailableEndpoint> conditionAnnotation = metadata.getAnnotations()
|
||||
.get(ConditionalOnAvailableEndpoint.class);
|
||||
.get(ConditionalOnAvailableEndpoint.class);
|
||||
Class<?> target = getTarget(context, metadata, conditionAnnotation);
|
||||
MergedAnnotation<Endpoint> endpointAnnotation = getEndpointAnnotation(target);
|
||||
return getMatchOutcome(environment, conditionAnnotation, endpointAnnotation);
|
||||
@@ -134,8 +134,8 @@ class OnAvailableEndpointCondition extends SpringBootCondition {
|
||||
}
|
||||
Boolean userDefinedDefault = isEnabledByDefault(environment);
|
||||
if (userDefinedDefault != null) {
|
||||
return new ConditionOutcome(userDefinedDefault, message.because(
|
||||
"no property " + key + " found so using user defined default from " + ENABLED_BY_DEFAULT_KEY));
|
||||
return new ConditionOutcome(userDefinedDefault, message
|
||||
.because("no property " + key + " found so using user defined default from " + ENABLED_BY_DEFAULT_KEY));
|
||||
}
|
||||
boolean endpointDefault = endpointAnnotation.getBoolean("enableByDefault");
|
||||
return new ConditionOutcome(endpointDefault,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -45,9 +45,10 @@ public class JacksonEndpointAutoConfiguration {
|
||||
@ConditionalOnClass({ ObjectMapper.class, Jackson2ObjectMapperBuilder.class })
|
||||
public EndpointObjectMapper endpointObjectMapper() {
|
||||
ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json()
|
||||
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,
|
||||
SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS)
|
||||
.serializationInclusion(Include.NON_NULL).build();
|
||||
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,
|
||||
SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS)
|
||||
.serializationInclusion(Include.NON_NULL)
|
||||
.build();
|
||||
return () -> objectMapper;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -89,7 +89,7 @@ class DefaultEndpointObjectNameFactory implements EndpointObjectNameFactory {
|
||||
}
|
||||
StringBuilder builder = new StringBuilder();
|
||||
this.properties.getStaticNames()
|
||||
.forEach((name, value) -> builder.append(",").append(name).append("=").append(value));
|
||||
.forEach((name, value) -> builder.append(",").append(name).append("=").append(value));
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -101,7 +101,9 @@ class JerseyWebEndpointManagementContextConfiguration {
|
||||
WebEndpointsSupplier webEndpointsSupplier, HealthEndpointGroups healthEndpointGroups) {
|
||||
Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
|
||||
ExposableWebEndpoint health = webEndpoints.stream()
|
||||
.filter((endpoint) -> endpoint.getEndpointId().equals(HEALTH_ENDPOINT_ID)).findFirst().get();
|
||||
.filter((endpoint) -> endpoint.getEndpointId().equals(HEALTH_ENDPOINT_ID))
|
||||
.findFirst()
|
||||
.get();
|
||||
return new JerseyAdditionalHealthEndpointPathsManagementResourcesRegistrar(health, healthEndpointGroups);
|
||||
}
|
||||
|
||||
@@ -195,8 +197,10 @@ class JerseyWebEndpointManagementContextConfiguration {
|
||||
JerseyHealthEndpointAdditionalPathResourceFactory resourceFactory = new JerseyHealthEndpointAdditionalPathResourceFactory(
|
||||
WebServerNamespace.MANAGEMENT, this.groups);
|
||||
Collection<Resource> endpointResources = resourceFactory
|
||||
.createEndpointResources(mapping, Collections.singletonList(this.endpoint), null, null, false)
|
||||
.stream().filter(Objects::nonNull).toList();
|
||||
.createEndpointResources(mapping, Collections.singletonList(this.endpoint), null, null, false)
|
||||
.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.toList();
|
||||
register(endpointResources, config);
|
||||
}
|
||||
|
||||
|
||||
@@ -118,7 +118,9 @@ public class WebFluxEndpointManagementContextConfiguration {
|
||||
WebEndpointsSupplier webEndpointsSupplier, HealthEndpointGroups groups) {
|
||||
Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
|
||||
ExposableWebEndpoint health = webEndpoints.stream()
|
||||
.filter((endpoint) -> endpoint.getEndpointId().equals(HealthEndpoint.ID)).findFirst().get();
|
||||
.filter((endpoint) -> endpoint.getEndpointId().equals(HealthEndpoint.ID))
|
||||
.findFirst()
|
||||
.get();
|
||||
return new AdditionalHealthEndpointPathsWebFluxHandlerMapping(new EndpointMapping(""), health,
|
||||
groups.getAllWithAdditionalPath(WebServerNamespace.MANAGEMENT));
|
||||
}
|
||||
@@ -149,7 +151,7 @@ public class WebFluxEndpointManagementContextConfiguration {
|
||||
static class ServerCodecConfigurerEndpointObjectMapperBeanPostProcessor implements BeanPostProcessor {
|
||||
|
||||
private static final List<MediaType> MEDIA_TYPES = Collections
|
||||
.unmodifiableList(Arrays.asList(MediaType.APPLICATION_JSON, new MediaType("application", "*+json")));
|
||||
.unmodifiableList(Arrays.asList(MediaType.APPLICATION_JSON, new MediaType("application", "*+json")));
|
||||
|
||||
private final Supplier<EndpointObjectMapper> endpointObjectMapper;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -113,7 +113,9 @@ public class WebMvcEndpointManagementContextConfiguration {
|
||||
WebEndpointsSupplier webEndpointsSupplier, HealthEndpointGroups groups) {
|
||||
Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
|
||||
ExposableWebEndpoint health = webEndpoints.stream()
|
||||
.filter((endpoint) -> endpoint.getEndpointId().equals(HealthEndpoint.ID)).findFirst().get();
|
||||
.filter((endpoint) -> endpoint.getEndpointId().equals(HealthEndpoint.ID))
|
||||
.findFirst()
|
||||
.get();
|
||||
return new AdditionalHealthEndpointPathsWebMvcHandlerMapping(health,
|
||||
groups.getAllWithAdditionalPath(WebServerNamespace.MANAGEMENT));
|
||||
}
|
||||
@@ -144,7 +146,7 @@ public class WebMvcEndpointManagementContextConfiguration {
|
||||
static class EndpointObjectMapperWebMvcConfigurer implements WebMvcConfigurer {
|
||||
|
||||
private static final List<MediaType> MEDIA_TYPES = Collections
|
||||
.unmodifiableList(Arrays.asList(MediaType.APPLICATION_JSON, new MediaType("application", "*+json")));
|
||||
.unmodifiableList(Arrays.asList(MediaType.APPLICATION_JSON, new MediaType("application", "*+json")));
|
||||
|
||||
private final EndpointObjectMapper endpointObjectMapper;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -93,7 +93,7 @@ public abstract class AbstractCompositeHealthContributorConfiguration<C, I exten
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException("Unable to create health indicator %s for bean type %s"
|
||||
.formatted(this.indicatorType, this.beanType), ex);
|
||||
.formatted(this.indicatorType, this.beanType), ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ class HealthEndpointConfiguration {
|
||||
|
||||
private Object applyPostProcessors(HealthEndpointGroups bean) {
|
||||
for (HealthEndpointGroupsPostProcessor postProcessor : this.postProcessors.orderedStream()
|
||||
.toArray(HealthEndpointGroupsPostProcessor[]::new)) {
|
||||
.toArray(HealthEndpointGroupsPostProcessor[]::new)) {
|
||||
bean = postProcessor.postProcessHealthEndpointGroups(bean);
|
||||
}
|
||||
return bean;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -68,7 +68,9 @@ class HealthEndpointReactiveWebExtensionConfiguration {
|
||||
WebEndpointsSupplier webEndpointsSupplier, HealthEndpointGroups groups) {
|
||||
Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
|
||||
ExposableWebEndpoint health = webEndpoints.stream()
|
||||
.filter((endpoint) -> endpoint.getEndpointId().equals(HealthEndpoint.ID)).findFirst().get();
|
||||
.filter((endpoint) -> endpoint.getEndpointId().equals(HealthEndpoint.ID))
|
||||
.findFirst()
|
||||
.get();
|
||||
return new AdditionalHealthEndpointPathsWebFluxHandlerMapping(new EndpointMapping(""), health,
|
||||
groups.getAllWithAdditionalPath(WebServerNamespace.SERVER));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -78,8 +78,10 @@ class HealthEndpointWebExtensionConfiguration {
|
||||
|
||||
private static ExposableWebEndpoint getHealthEndpoint(WebEndpointsSupplier webEndpointsSupplier) {
|
||||
Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
|
||||
return webEndpoints.stream().filter((endpoint) -> endpoint.getEndpointId().equals(HealthEndpoint.ID))
|
||||
.findFirst().get();
|
||||
return webEndpoints.stream()
|
||||
.filter((endpoint) -> endpoint.getEndpointId().equals(HealthEndpoint.ID))
|
||||
.findFirst()
|
||||
.get();
|
||||
}
|
||||
|
||||
@ConditionalOnBean(DispatcherServlet.class)
|
||||
@@ -160,8 +162,10 @@ class HealthEndpointWebExtensionConfiguration {
|
||||
JerseyHealthEndpointAdditionalPathResourceFactory resourceFactory = new JerseyHealthEndpointAdditionalPathResourceFactory(
|
||||
WebServerNamespace.SERVER, this.groups);
|
||||
Collection<Resource> endpointResources = resourceFactory
|
||||
.createEndpointResources(mapping, Collections.singletonList(this.endpoint), null, null, false)
|
||||
.stream().filter(Objects::nonNull).toList();
|
||||
.createEndpointResources(mapping, Collections.singletonList(this.endpoint), null, null, false)
|
||||
.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.toList();
|
||||
register(endpointResources, config);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -39,7 +39,7 @@ class OnEnabledInfoContributorCondition extends OnEndpointElementCondition {
|
||||
InfoContributorFallback fallback = annotationAttributes.getEnum("fallback");
|
||||
if (fallback == InfoContributorFallback.DISABLE) {
|
||||
return new ConditionOutcome(false, ConditionMessage.forCondition(ConditionalOnEnabledInfoContributor.class)
|
||||
.because("management.info." + annotationAttributes.getString("value") + ".enabled is not true"));
|
||||
.because("management.info." + annotationAttributes.getString("value") + ".enabled is not true"));
|
||||
}
|
||||
return super.getDefaultOutcome(context, annotationAttributes);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -86,9 +86,10 @@ public class DataSourceHealthContributorAutoConfiguration implements Initializin
|
||||
public HealthContributor dbHealthContributor(Map<String, DataSource> dataSources,
|
||||
DataSourceHealthIndicatorProperties dataSourceHealthIndicatorProperties) {
|
||||
if (dataSourceHealthIndicatorProperties.isIgnoreRoutingDataSources()) {
|
||||
Map<String, DataSource> filteredDatasources = dataSources.entrySet().stream()
|
||||
.filter((e) -> !(e.getValue() instanceof AbstractRoutingDataSource))
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
Map<String, DataSource> filteredDatasources = dataSources.entrySet()
|
||||
.stream()
|
||||
.filter((e) -> !(e.getValue() instanceof AbstractRoutingDataSource))
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
return createContributor(filteredDatasources);
|
||||
}
|
||||
return createContributor(dataSources);
|
||||
@@ -127,9 +128,11 @@ public class DataSourceHealthContributorAutoConfiguration implements Initializin
|
||||
|
||||
RoutingDataSourceHealthContributor(AbstractRoutingDataSource routingDataSource,
|
||||
Function<DataSource, HealthContributor> contributorFunction) {
|
||||
Map<String, DataSource> routedDataSources = routingDataSource.getResolvedDataSources().entrySet().stream()
|
||||
.collect(Collectors.toMap((e) -> Objects.toString(e.getKey(), UNNAMED_DATASOURCE_KEY),
|
||||
Map.Entry::getValue));
|
||||
Map<String, DataSource> routedDataSources = routingDataSource.getResolvedDataSources()
|
||||
.entrySet()
|
||||
.stream()
|
||||
.collect(Collectors.toMap((e) -> Objects.toString(e.getKey(), UNNAMED_DATASOURCE_KEY),
|
||||
Map.Entry::getValue));
|
||||
this.delegate = CompositeHealthContributor.fromMap(routedDataSources, contributorFunction);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -59,8 +59,8 @@ public class LoggersEndpointAutoConfiguration {
|
||||
ConditionMessage.Builder message = ConditionMessage.forCondition("Logging System");
|
||||
String loggingSystem = System.getProperty(LoggingSystem.SYSTEM_PROPERTY);
|
||||
if (LoggingSystem.NONE.equals(loggingSystem)) {
|
||||
return ConditionOutcome.noMatch(
|
||||
message.because("system property " + LoggingSystem.SYSTEM_PROPERTY + " is set to none"));
|
||||
return ConditionOutcome
|
||||
.noMatch(message.because("system property " + LoggingSystem.SYSTEM_PROPERTY + " is set to none"));
|
||||
}
|
||||
return ConditionOutcome.match(message.because("enabled"));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -60,14 +60,14 @@ public class Log4J2MetricsAutoConfiguration {
|
||||
try {
|
||||
if (Class.forName("org.apache.logging.log4j.core.LoggerContext").isInstance(loggerContext)) {
|
||||
return ConditionOutcome
|
||||
.match("LoggerContext was an instance of org.apache.logging.log4j.core.LoggerContext");
|
||||
.match("LoggerContext was an instance of org.apache.logging.log4j.core.LoggerContext");
|
||||
}
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// Continue with no match
|
||||
}
|
||||
return ConditionOutcome
|
||||
.noMatch("Logger context was not an instance of org.apache.logging.log4j.core.LoggerContext");
|
||||
.noMatch("Logger context was not an instance of org.apache.logging.log4j.core.LoggerContext");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -108,8 +108,8 @@ class MeterRegistryPostProcessor implements BeanPostProcessor, SmartInitializing
|
||||
private void applyCustomizers(MeterRegistry meterRegistry) {
|
||||
List<MeterRegistryCustomizer<?>> customizers = this.customizers.orderedStream().toList();
|
||||
LambdaSafe.callbacks(MeterRegistryCustomizer.class, customizers, meterRegistry)
|
||||
.withLogger(MeterRegistryPostProcessor.class)
|
||||
.invoke((customizer) -> customizer.customize(meterRegistry));
|
||||
.withLogger(MeterRegistryPostProcessor.class)
|
||||
.invoke((customizer) -> customizer.customize(meterRegistry));
|
||||
}
|
||||
|
||||
private void applyFilters(MeterRegistry meterRegistry) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -42,7 +42,7 @@ public class PropertiesAutoTimer implements AutoTimer {
|
||||
@Override
|
||||
public void apply(Builder builder) {
|
||||
builder.publishPercentileHistogram(this.properties.isPercentilesHistogram())
|
||||
.publishPercentiles(this.properties.getPercentiles());
|
||||
.publishPercentiles(this.properties.getPercentiles());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -84,24 +84,29 @@ public class PropertiesMeterFilter implements MeterFilter {
|
||||
public DistributionStatisticConfig configure(Meter.Id id, DistributionStatisticConfig config) {
|
||||
Distribution distribution = this.properties.getDistribution();
|
||||
return DistributionStatisticConfig.builder()
|
||||
.percentilesHistogram(lookupWithFallbackToAll(distribution.getPercentilesHistogram(), id, null))
|
||||
.percentiles(lookupWithFallbackToAll(distribution.getPercentiles(), id, null))
|
||||
.serviceLevelObjectives(
|
||||
convertServiceLevelObjectives(id.getType(), lookup(distribution.getSlo(), id, null)))
|
||||
.minimumExpectedValue(
|
||||
convertMeterValue(id.getType(), lookup(distribution.getMinimumExpectedValue(), id, null)))
|
||||
.maximumExpectedValue(
|
||||
convertMeterValue(id.getType(), lookup(distribution.getMaximumExpectedValue(), id, null)))
|
||||
.expiry(lookupWithFallbackToAll(distribution.getExpiry(), id, null))
|
||||
.bufferLength(lookupWithFallbackToAll(distribution.getBufferLength(), id, null)).build().merge(config);
|
||||
.percentilesHistogram(lookupWithFallbackToAll(distribution.getPercentilesHistogram(), id, null))
|
||||
.percentiles(lookupWithFallbackToAll(distribution.getPercentiles(), id, null))
|
||||
.serviceLevelObjectives(
|
||||
convertServiceLevelObjectives(id.getType(), lookup(distribution.getSlo(), id, null)))
|
||||
.minimumExpectedValue(
|
||||
convertMeterValue(id.getType(), lookup(distribution.getMinimumExpectedValue(), id, null)))
|
||||
.maximumExpectedValue(
|
||||
convertMeterValue(id.getType(), lookup(distribution.getMaximumExpectedValue(), id, null)))
|
||||
.expiry(lookupWithFallbackToAll(distribution.getExpiry(), id, null))
|
||||
.bufferLength(lookupWithFallbackToAll(distribution.getBufferLength(), id, null))
|
||||
.build()
|
||||
.merge(config);
|
||||
}
|
||||
|
||||
private double[] convertServiceLevelObjectives(Meter.Type meterType, ServiceLevelObjectiveBoundary[] slo) {
|
||||
if (slo == null) {
|
||||
return null;
|
||||
}
|
||||
double[] converted = Arrays.stream(slo).map((candidate) -> candidate.getValue(meterType))
|
||||
.filter(Objects::nonNull).mapToDouble(Double::doubleValue).toArray();
|
||||
double[] converted = Arrays.stream(slo)
|
||||
.map((candidate) -> candidate.getValue(meterType))
|
||||
.filter(Objects::nonNull)
|
||||
.mapToDouble(Double::doubleValue)
|
||||
.toArray();
|
||||
return (converted.length != 0) ? converted : null;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -68,7 +68,7 @@ class CacheMetricsRegistrarConfiguration {
|
||||
|
||||
private void bindCacheManagerToRegistry(String beanName, CacheManager cacheManager) {
|
||||
cacheManager.getCacheNames()
|
||||
.forEach((cacheName) -> bindCacheToRegistry(beanName, cacheManager.getCache(cacheName)));
|
||||
.forEach((cacheName) -> bindCacheToRegistry(beanName, cacheManager.getCache(cacheName)));
|
||||
}
|
||||
|
||||
private void bindCacheToRegistry(String beanName, Cache cache) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -40,7 +40,7 @@ class OnMetricsExportEnabledCondition extends SpringBootCondition {
|
||||
@Override
|
||||
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
AnnotationAttributes annotationAttributes = AnnotationAttributes
|
||||
.fromMap(metadata.getAnnotationAttributes(ConditionalOnEnabledMetricsExport.class.getName()));
|
||||
.fromMap(metadata.getAnnotationAttributes(ConditionalOnEnabledMetricsExport.class.getName()));
|
||||
String endpointName = annotationAttributes.getString("value");
|
||||
ConditionOutcome outcome = getProductOutcome(context, endpointName);
|
||||
if (outcome != null) {
|
||||
@@ -55,7 +55,7 @@ class OnMetricsExportEnabledCondition extends SpringBootCondition {
|
||||
if (environment.containsProperty(enabledProperty)) {
|
||||
boolean match = environment.getProperty(enabledProperty, Boolean.class, true);
|
||||
return new ConditionOutcome(match, ConditionMessage.forCondition(ConditionalOnEnabledMetricsExport.class)
|
||||
.because(enabledProperty + " is " + match));
|
||||
.because(enabledProperty + " is " + match));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -70,7 +70,7 @@ class OnMetricsExportEnabledCondition extends SpringBootCondition {
|
||||
private ConditionOutcome getDefaultOutcome(ConditionContext context) {
|
||||
boolean match = Boolean.parseBoolean(context.getEnvironment().getProperty(DEFAULT_PROPERTY_NAME, "true"));
|
||||
return new ConditionOutcome(match, ConditionMessage.forCondition(ConditionalOnEnabledMetricsExport.class)
|
||||
.because(DEFAULT_PROPERTY_NAME + " is considered " + match));
|
||||
.because(DEFAULT_PROPERTY_NAME + " is considered " + match));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -64,9 +64,11 @@ public class AppOpticsMetricsExportAutoConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public AppOpticsMeterRegistry appOpticsMeterRegistry(AppOpticsConfig config, Clock clock) {
|
||||
return AppOpticsMeterRegistry.builder(config).clock(clock).httpClient(
|
||||
new HttpUrlConnectionSender(this.properties.getConnectTimeout(), this.properties.getReadTimeout()))
|
||||
.build();
|
||||
return AppOpticsMeterRegistry.builder(config)
|
||||
.clock(clock)
|
||||
.httpClient(
|
||||
new HttpUrlConnectionSender(this.properties.getConnectTimeout(), this.properties.getReadTimeout()))
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -64,9 +64,11 @@ public class DatadogMetricsExportAutoConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public DatadogMeterRegistry datadogMeterRegistry(DatadogConfig datadogConfig, Clock clock) {
|
||||
return DatadogMeterRegistry.builder(datadogConfig).clock(clock).httpClient(
|
||||
new HttpUrlConnectionSender(this.properties.getConnectTimeout(), this.properties.getReadTimeout()))
|
||||
.build();
|
||||
return DatadogMeterRegistry.builder(datadogConfig)
|
||||
.clock(clock)
|
||||
.httpClient(
|
||||
new HttpUrlConnectionSender(this.properties.getConnectTimeout(), this.properties.getReadTimeout()))
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -64,9 +64,11 @@ public class DynatraceMetricsExportAutoConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public DynatraceMeterRegistry dynatraceMeterRegistry(DynatraceConfig dynatraceConfig, Clock clock) {
|
||||
return DynatraceMeterRegistry.builder(dynatraceConfig).clock(clock).httpClient(
|
||||
new HttpUrlConnectionSender(this.properties.getConnectTimeout(), this.properties.getReadTimeout()))
|
||||
.build();
|
||||
return DynatraceMeterRegistry.builder(dynatraceConfig)
|
||||
.clock(clock)
|
||||
.httpClient(
|
||||
new HttpUrlConnectionSender(this.properties.getConnectTimeout(), this.properties.getReadTimeout()))
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -73,9 +73,11 @@ public class ElasticMetricsExportAutoConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ElasticMeterRegistry elasticMeterRegistry(ElasticConfig elasticConfig, Clock clock) {
|
||||
return ElasticMeterRegistry.builder(elasticConfig).clock(clock).httpClient(
|
||||
new HttpUrlConnectionSender(this.properties.getConnectTimeout(), this.properties.getReadTimeout()))
|
||||
.build();
|
||||
return ElasticMeterRegistry.builder(elasticConfig)
|
||||
.clock(clock)
|
||||
.httpClient(
|
||||
new HttpUrlConnectionSender(this.properties.getConnectTimeout(), this.properties.getReadTimeout()))
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -64,9 +64,11 @@ public class HumioMetricsExportAutoConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public HumioMeterRegistry humioMeterRegistry(HumioConfig humioConfig, Clock clock) {
|
||||
return HumioMeterRegistry.builder(humioConfig).clock(clock).httpClient(
|
||||
new HttpUrlConnectionSender(this.properties.getConnectTimeout(), this.properties.getReadTimeout()))
|
||||
.build();
|
||||
return HumioMeterRegistry.builder(humioConfig)
|
||||
.clock(clock)
|
||||
.httpClient(
|
||||
new HttpUrlConnectionSender(this.properties.getConnectTimeout(), this.properties.getReadTimeout()))
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -64,9 +64,11 @@ public class InfluxMetricsExportAutoConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public InfluxMeterRegistry influxMeterRegistry(InfluxConfig influxConfig, Clock clock) {
|
||||
return InfluxMeterRegistry.builder(influxConfig).clock(clock).httpClient(
|
||||
new HttpUrlConnectionSender(this.properties.getConnectTimeout(), this.properties.getReadTimeout()))
|
||||
.build();
|
||||
return InfluxMeterRegistry.builder(influxConfig)
|
||||
.clock(clock)
|
||||
.httpClient(
|
||||
new HttpUrlConnectionSender(this.properties.getConnectTimeout(), this.properties.getReadTimeout()))
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -64,9 +64,11 @@ public class KairosMetricsExportAutoConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public KairosMeterRegistry kairosMeterRegistry(KairosConfig kairosConfig, Clock clock) {
|
||||
return KairosMeterRegistry.builder(kairosConfig).clock(clock).httpClient(
|
||||
new HttpUrlConnectionSender(this.properties.getConnectTimeout(), this.properties.getReadTimeout()))
|
||||
.build();
|
||||
return KairosMeterRegistry.builder(kairosConfig)
|
||||
.clock(clock)
|
||||
.httpClient(
|
||||
new HttpUrlConnectionSender(this.properties.getConnectTimeout(), this.properties.getReadTimeout()))
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -81,8 +81,10 @@ public class NewRelicMetricsExportAutoConfiguration {
|
||||
@ConditionalOnMissingBean
|
||||
public NewRelicMeterRegistry newRelicMeterRegistry(NewRelicConfig newRelicConfig, Clock clock,
|
||||
NewRelicClientProvider newRelicClientProvider) {
|
||||
return NewRelicMeterRegistry.builder(newRelicConfig).clock(clock).clientProvider(newRelicClientProvider)
|
||||
.build();
|
||||
return NewRelicMeterRegistry.builder(newRelicConfig)
|
||||
.clock(clock)
|
||||
.clientProvider(newRelicClientProvider)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -95,7 +95,7 @@ public class DataSourcePoolMetricsAutoConfiguration {
|
||||
Collection<DataSourcePoolMetadataProvider> metadataProviders, MeterRegistry registry) {
|
||||
String dataSourceName = getDataSourceName(beanName);
|
||||
new DataSourcePoolMetrics(dataSource, metadataProviders, dataSourceName, Collections.emptyList())
|
||||
.bindTo(registry);
|
||||
.bindTo(registry);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -98,8 +98,8 @@ public class MongoMetricsAutoConfiguration {
|
||||
MongoClientSettingsBuilderCustomizer mongoMetricsConnectionPoolListenerClientSettingsBuilderCustomizer(
|
||||
MongoMetricsConnectionPoolListener mongoMetricsConnectionPoolListener) {
|
||||
return (clientSettingsBuilder) -> clientSettingsBuilder
|
||||
.applyToConnectionPoolSettings((connectionPoolSettingsBuilder) -> connectionPoolSettingsBuilder
|
||||
.addConnectionPoolListener(mongoMetricsConnectionPoolListener));
|
||||
.applyToConnectionPoolSettings((connectionPoolSettingsBuilder) -> connectionPoolSettingsBuilder
|
||||
.addConnectionPoolListener(mongoMetricsConnectionPoolListener));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -78,7 +78,8 @@ public class HibernateMetricsAutoConfiguration implements SmartInitializingSingl
|
||||
String entityManagerFactoryName = getEntityManagerFactoryName(beanName);
|
||||
try {
|
||||
new HibernateMetrics(entityManagerFactory.unwrap(SessionFactory.class), entityManagerFactoryName,
|
||||
Collections.emptyList()).bindTo(registry);
|
||||
Collections.emptyList())
|
||||
.bindTo(registry);
|
||||
}
|
||||
catch (PersistenceException ex) {
|
||||
// Continue
|
||||
|
||||
@@ -93,7 +93,8 @@ class ObservationRegistryConfigurer {
|
||||
@SuppressWarnings("unchecked")
|
||||
private void customize(ObservationRegistry registry) {
|
||||
LambdaSafe.callbacks(ObservationRegistryCustomizer.class, asOrderedList(this.customizers), registry)
|
||||
.withLogger(ObservationRegistryConfigurer.class).invoke((customizer) -> customizer.customize(registry));
|
||||
.withLogger(ObservationRegistryConfigurer.class)
|
||||
.invoke((customizer) -> customizer.customize(registry));
|
||||
}
|
||||
|
||||
private <T> List<T> asOrderedList(ObjectProvider<T> provider) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -74,7 +74,7 @@ public class HttpClientObservationsAutoConfiguration {
|
||||
String name = (observationName != null) ? observationName : metricName;
|
||||
MeterFilter denyFilter = new OnlyOnceLoggingDenyMeterFilter(
|
||||
() -> "Reached the maximum number of URI tags for '%s'. Are you using 'uriVariables'?"
|
||||
.formatted(name));
|
||||
.formatted(name));
|
||||
return MeterFilter.maximumAllowableTags(name, "uri", clientProperties.getMaxUriTags(), denyFilter);
|
||||
}
|
||||
|
||||
|
||||
@@ -246,8 +246,10 @@ public final class EndpointRequest {
|
||||
}
|
||||
|
||||
private String toString(List<Object> endpoints, String emptyValue) {
|
||||
return (!endpoints.isEmpty()) ? endpoints.stream().map(this::getEndpointId).map(Object::toString)
|
||||
.collect(Collectors.joining(", ", "[", "]")) : emptyValue;
|
||||
return (!endpoints.isEmpty()) ? endpoints.stream()
|
||||
.map(this::getEndpointId)
|
||||
.map(Object::toString)
|
||||
.collect(Collectors.joining(", ", "[", "]")) : emptyValue;
|
||||
}
|
||||
|
||||
private EndpointId getEndpointId(Object source) {
|
||||
|
||||
@@ -250,8 +250,9 @@ public final class EndpointRequest {
|
||||
|
||||
private List<RequestMatcher> getDelegateMatchers(RequestMatcherFactory requestMatcherFactory,
|
||||
RequestMatcherProvider matcherProvider, Set<String> paths) {
|
||||
return paths.stream().map((path) -> requestMatcherFactory.antPath(matcherProvider, path, "/**"))
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
return paths.stream()
|
||||
.map((path) -> requestMatcherFactory.antPath(matcherProvider, path, "/**"))
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -261,8 +262,10 @@ public final class EndpointRequest {
|
||||
}
|
||||
|
||||
private String toString(List<Object> endpoints, String emptyValue) {
|
||||
return (!endpoints.isEmpty()) ? endpoints.stream().map(this::getEndpointId).map(Object::toString)
|
||||
.collect(Collectors.joining(", ", "[", "]")) : emptyValue;
|
||||
return (!endpoints.isEmpty()) ? endpoints.stream()
|
||||
.map(this::getEndpointId)
|
||||
.map(Object::toString)
|
||||
.collect(Collectors.joining(", ", "[", "]")) : emptyValue;
|
||||
}
|
||||
|
||||
private EndpointId getEndpointId(Object source) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -62,8 +62,8 @@ public class StartupEndpointAutoConfiguration {
|
||||
ConditionMessage.Builder message = ConditionMessage.forCondition("ApplicationStartup");
|
||||
ApplicationStartup applicationStartup = context.getBeanFactory().getApplicationStartup();
|
||||
if (applicationStartup instanceof BufferingApplicationStartup) {
|
||||
return ConditionOutcome.match(
|
||||
message.because("configured applicationStartup is of type BufferingApplicationStartup."));
|
||||
return ConditionOutcome
|
||||
.match(message.because("configured applicationStartup is of type BufferingApplicationStartup."));
|
||||
}
|
||||
return ConditionOutcome.noMatch(message.because("configured applicationStartup is of type "
|
||||
+ applicationStartup.getClass() + ", expected BufferingApplicationStartup."));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -101,9 +101,13 @@ public class BraveAutoConfiguration {
|
||||
List<TracingCustomizer> tracingCustomizers, CurrentTraceContext currentTraceContext,
|
||||
Factory propagationFactory, Sampler sampler) {
|
||||
String applicationName = environment.getProperty("spring.application.name", DEFAULT_APPLICATION_NAME);
|
||||
Builder builder = Tracing.newBuilder().currentTraceContext(currentTraceContext).traceId128Bit(true)
|
||||
.supportsJoin(false).propagationFactory(propagationFactory).sampler(sampler)
|
||||
.localServiceName(applicationName);
|
||||
Builder builder = Tracing.newBuilder()
|
||||
.currentTraceContext(currentTraceContext)
|
||||
.traceId128Bit(true)
|
||||
.supportsJoin(false)
|
||||
.propagationFactory(propagationFactory)
|
||||
.sampler(sampler)
|
||||
.localServiceName(applicationName);
|
||||
spanHandlers.forEach(builder::addSpanHandler);
|
||||
for (TracingCustomizer tracingCustomizer : tracingCustomizers) {
|
||||
tracingCustomizer.customize(builder);
|
||||
@@ -234,7 +238,8 @@ public class BraveAutoConfiguration {
|
||||
List<String> correlationFields = this.tracingProperties.getBaggage().getCorrelation().getFields();
|
||||
for (String field : correlationFields) {
|
||||
builder.add(CorrelationScopeConfig.SingleCorrelationField.newBuilder(BaggageField.create(field))
|
||||
.flushOnUpdate().build());
|
||||
.flushOnUpdate()
|
||||
.build());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -88,8 +88,10 @@ public class OpenTelemetryAutoConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
OpenTelemetry openTelemetry(SdkTracerProvider sdkTracerProvider, ContextPropagators contextPropagators) {
|
||||
return OpenTelemetrySdk.builder().setTracerProvider(sdkTracerProvider).setPropagators(contextPropagators)
|
||||
.build();
|
||||
return OpenTelemetrySdk.builder()
|
||||
.setTracerProvider(sdkTracerProvider)
|
||||
.setPropagators(contextPropagators)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -97,8 +99,9 @@ public class OpenTelemetryAutoConfiguration {
|
||||
SdkTracerProvider otelSdkTracerProvider(Environment environment, ObjectProvider<SpanProcessor> spanProcessors,
|
||||
Sampler sampler) {
|
||||
String applicationName = environment.getProperty("spring.application.name", DEFAULT_APPLICATION_NAME);
|
||||
SdkTracerProviderBuilder builder = SdkTracerProvider.builder().setSampler(sampler)
|
||||
.setResource(Resource.create(Attributes.of(ResourceAttributes.SERVICE_NAME, applicationName)));
|
||||
SdkTracerProviderBuilder builder = SdkTracerProvider.builder()
|
||||
.setSampler(sampler)
|
||||
.setResource(Resource.create(Attributes.of(ResourceAttributes.SERVICE_NAME, applicationName)));
|
||||
spanProcessors.orderedStream().forEach(builder::addSpanProcessor);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -79,7 +79,8 @@ class ZipkinConfigurations {
|
||||
ZipkinRestTemplateSender restTemplateSender(ZipkinProperties properties,
|
||||
ObjectProvider<ZipkinRestTemplateBuilderCustomizer> customizers) {
|
||||
RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder()
|
||||
.setConnectTimeout(properties.getConnectTimeout()).setReadTimeout(properties.getReadTimeout());
|
||||
.setConnectTimeout(properties.getConnectTimeout())
|
||||
.setReadTimeout(properties.getReadTimeout());
|
||||
restTemplateBuilder = applyCustomizers(restTemplateBuilder, customizers);
|
||||
return new ZipkinRestTemplateSender(properties.getEndpoint(), restTemplateBuilder.build());
|
||||
}
|
||||
@@ -87,7 +88,7 @@ class ZipkinConfigurations {
|
||||
private RestTemplateBuilder applyCustomizers(RestTemplateBuilder restTemplateBuilder,
|
||||
ObjectProvider<ZipkinRestTemplateBuilderCustomizer> customizers) {
|
||||
Iterable<ZipkinRestTemplateBuilderCustomizer> orderedCustomizers = () -> customizers.orderedStream()
|
||||
.iterator();
|
||||
.iterator();
|
||||
RestTemplateBuilder currentBuilder = restTemplateBuilder;
|
||||
for (ZipkinRestTemplateBuilderCustomizer customizer : orderedCustomizers) {
|
||||
currentBuilder = customizer.customize(currentBuilder);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -74,8 +74,12 @@ class ZipkinWebClientSender extends HttpSender {
|
||||
}
|
||||
|
||||
private Mono<ResponseEntity<Void>> sendRequest() {
|
||||
return this.webClient.post().uri(this.endpoint).headers(this::addDefaultHeaders).bodyValue(getBody())
|
||||
.retrieve().toBodilessEntity();
|
||||
return this.webClient.post()
|
||||
.uri(this.endpoint)
|
||||
.headers(this::addDefaultHeaders)
|
||||
.bodyValue(getBody())
|
||||
.retrieve()
|
||||
.toBodilessEntity();
|
||||
}
|
||||
|
||||
private void addDefaultHeaders(HttpHeaders headers) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -59,12 +59,12 @@ public final class ManagementContextFactory {
|
||||
public ConfigurableApplicationContext createManagementContext(ApplicationContext parentContext) {
|
||||
Environment parentEnvironment = parentContext.getEnvironment();
|
||||
ConfigurableEnvironment childEnvironment = ApplicationContextFactory.DEFAULT
|
||||
.createEnvironment(this.webApplicationType);
|
||||
.createEnvironment(this.webApplicationType);
|
||||
if (parentEnvironment instanceof ConfigurableEnvironment) {
|
||||
childEnvironment.setConversionService(((ConfigurableEnvironment) parentEnvironment).getConversionService());
|
||||
}
|
||||
ConfigurableApplicationContext managementContext = ApplicationContextFactory.DEFAULT
|
||||
.create(this.webApplicationType);
|
||||
.create(this.webApplicationType);
|
||||
managementContext.setEnvironment(childEnvironment);
|
||||
managementContext.setParent(parentContext);
|
||||
return managementContext;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -121,7 +121,7 @@ class ChildManagementContextInitializer
|
||||
|
||||
protected final ConfigurableApplicationContext createManagementContext() {
|
||||
ConfigurableApplicationContext managementContext = this.managementContextFactory
|
||||
.createManagementContext(this.parentContext);
|
||||
.createManagementContext(this.parentContext);
|
||||
managementContext.setId(this.parentContext.getId() + ":management");
|
||||
if (managementContext instanceof ConfigurableWebServerApplicationContext webServerApplicationContext) {
|
||||
webServerApplicationContext.setServerNamespace("management");
|
||||
@@ -162,9 +162,10 @@ class ChildManagementContextInitializer
|
||||
public void applyTo(GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode) {
|
||||
GenerationContext managementGenerationContext = generationContext.withName("Management");
|
||||
ClassName generatedInitializerClassName = new ApplicationContextAotGenerator()
|
||||
.processAheadOfTime(this.managementContext, managementGenerationContext);
|
||||
GeneratedMethod postProcessorMethod = beanRegistrationCode.getMethods().add("addManagementInitializer",
|
||||
(method) -> method.addJavadoc("Use AOT management context initialization")
|
||||
.processAheadOfTime(this.managementContext, managementGenerationContext);
|
||||
GeneratedMethod postProcessorMethod = beanRegistrationCode.getMethods()
|
||||
.add("addManagementInitializer",
|
||||
(method) -> method.addJavadoc("Use AOT management context initialization")
|
||||
.addModifiers(Modifier.PRIVATE, Modifier.STATIC)
|
||||
.addParameter(RegisteredBean.class, "registeredBean")
|
||||
.addParameter(ChildManagementContextInitializer.class, "instance")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -55,7 +55,8 @@ class ManagementContextConfigurationImportSelector implements DeferredImportSele
|
||||
@Override
|
||||
public String[] selectImports(AnnotationMetadata metadata) {
|
||||
ManagementContextType contextType = (ManagementContextType) metadata
|
||||
.getAnnotationAttributes(EnableManagementContext.class.getName()).get("value");
|
||||
.getAnnotationAttributes(EnableManagementContext.class.getName())
|
||||
.get("value");
|
||||
// Find all management context configuration classes, filtering duplicates
|
||||
List<ManagementConfiguration> configurations = getConfigurations();
|
||||
OrderComparator.sort(configurations);
|
||||
@@ -118,7 +119,7 @@ class ManagementContextConfigurationImportSelector implements DeferredImportSele
|
||||
|
||||
private ManagementContextType readContextType(AnnotationMetadata annotationMetadata) {
|
||||
Map<String, Object> annotationAttributes = annotationMetadata
|
||||
.getAnnotationAttributes(ManagementContextConfiguration.class.getName());
|
||||
.getAnnotationAttributes(ManagementContextConfiguration.class.getName());
|
||||
return (annotationAttributes != null) ? (ManagementContextType) annotationAttributes.get("value")
|
||||
: ManagementContextType.ANY;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -62,7 +62,7 @@ public abstract class ManagementWebServerFactoryCustomizer<T extends Configurabl
|
||||
@Override
|
||||
public final void customize(T factory) {
|
||||
ManagementServerProperties managementServerProperties = BeanFactoryUtils
|
||||
.beanOfTypeIncludingAncestors(this.beanFactory, ManagementServerProperties.class);
|
||||
.beanOfTypeIncludingAncestors(this.beanFactory, ManagementServerProperties.class);
|
||||
// Customize as per the parent context first (so e.g. the access logs go to
|
||||
// the same place)
|
||||
customizeSameAsParentContext(factory);
|
||||
@@ -89,7 +89,7 @@ public abstract class ManagementWebServerFactoryCustomizer<T extends Configurabl
|
||||
@SuppressWarnings("unchecked")
|
||||
private void invokeCustomizers(T factory, List<WebServerFactoryCustomizer<?>> customizers) {
|
||||
LambdaSafe.callbacks(WebServerFactoryCustomizer.class, customizers, factory)
|
||||
.invoke((customizer) -> customizer.customize(factory));
|
||||
.invoke((customizer) -> customizer.customize(factory));
|
||||
}
|
||||
|
||||
protected void customize(T factory, ManagementServerProperties managementServerProperties,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -49,10 +49,10 @@ class OnManagementPortCondition extends SpringBootCondition {
|
||||
ManagementPortType actualType = ManagementPortType.get(context.getEnvironment());
|
||||
if (actualType == requiredType) {
|
||||
return ConditionOutcome
|
||||
.match(message.because("actual port type (" + actualType + ") matched required type"));
|
||||
.match(message.because("actual port type (" + actualType + ") matched required type"));
|
||||
}
|
||||
return ConditionOutcome.noMatch(message
|
||||
.because("actual port type (" + actualType + ") did not match required type (" + requiredType + ")"));
|
||||
.because("actual port type (" + actualType + ") did not match required type (" + requiredType + ")"));
|
||||
}
|
||||
|
||||
private boolean isWebApplicationContext(ConditionContext context) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -111,8 +111,8 @@ class ServletManagementChildContextConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnBean(name = "securityFilterChainRegistration", search = SearchStrategy.ANCESTORS)
|
||||
DelegatingFilterProxyRegistrationBean securityFilterChainRegistration(HierarchicalBeanFactory beanFactory) {
|
||||
return beanFactory.getParentBeanFactory().getBean("securityFilterChainRegistration",
|
||||
DelegatingFilterProxyRegistrationBean.class);
|
||||
return beanFactory.getParentBeanFactory()
|
||||
.getBean("securityFilterChainRegistration", DelegatingFilterProxyRegistrationBean.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -34,8 +34,8 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class RabbitHealthContributorAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(RabbitAutoConfiguration.class,
|
||||
RabbitHealthContributorAutoConfiguration.class, HealthContributorAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(RabbitAutoConfiguration.class,
|
||||
RabbitHealthContributorAutoConfiguration.class, HealthContributorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void runShouldCreateIndicator() {
|
||||
@@ -45,7 +45,7 @@ class RabbitHealthContributorAutoConfigurationTests {
|
||||
@Test
|
||||
void runWhenDisabledShouldNotCreateIndicator() {
|
||||
this.contextRunner.withPropertyValues("management.health.rabbit.enabled:false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(RabbitHealthIndicator.class));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(RabbitHealthIndicator.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -47,7 +47,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class AuditAutoConfigurationTests {
|
||||
|
||||
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(AuditAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(AuditAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void autoConfigurationIsDisabledByDefault() {
|
||||
@@ -66,34 +66,34 @@ class AuditAutoConfigurationTests {
|
||||
@Test
|
||||
void ownAuthenticationAuditListener() {
|
||||
this.contextRunner.withUserConfiguration(CustomAuditEventRepositoryConfiguration.class)
|
||||
.withUserConfiguration(CustomAuthenticationAuditListenerConfiguration.class)
|
||||
.run((context) -> assertThat(context.getBean(AbstractAuthenticationAuditListener.class))
|
||||
.isInstanceOf(TestAuthenticationAuditListener.class));
|
||||
.withUserConfiguration(CustomAuthenticationAuditListenerConfiguration.class)
|
||||
.run((context) -> assertThat(context.getBean(AbstractAuthenticationAuditListener.class))
|
||||
.isInstanceOf(TestAuthenticationAuditListener.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void ownAuthorizationAuditListener() {
|
||||
this.contextRunner.withUserConfiguration(CustomAuditEventRepositoryConfiguration.class)
|
||||
.withUserConfiguration(CustomAuthorizationAuditListenerConfiguration.class)
|
||||
.run((context) -> assertThat(context.getBean(AbstractAuthorizationAuditListener.class))
|
||||
.isInstanceOf(TestAuthorizationAuditListener.class));
|
||||
.withUserConfiguration(CustomAuthorizationAuditListenerConfiguration.class)
|
||||
.run((context) -> assertThat(context.getBean(AbstractAuthorizationAuditListener.class))
|
||||
.isInstanceOf(TestAuthorizationAuditListener.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void ownAuditListener() {
|
||||
this.contextRunner.withUserConfiguration(CustomAuditEventRepositoryConfiguration.class)
|
||||
.withUserConfiguration(CustomAuditListenerConfiguration.class)
|
||||
.run((context) -> assertThat(context.getBean(AbstractAuditListener.class))
|
||||
.isInstanceOf(TestAuditListener.class));
|
||||
.withUserConfiguration(CustomAuditListenerConfiguration.class)
|
||||
.run((context) -> assertThat(context.getBean(AbstractAuditListener.class))
|
||||
.isInstanceOf(TestAuditListener.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void backsOffWhenDisabled() {
|
||||
this.contextRunner.withUserConfiguration(CustomAuditEventRepositoryConfiguration.class)
|
||||
.withPropertyValues("management.auditevents.enabled=false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(AuditListener.class)
|
||||
.doesNotHaveBean(AuthenticationAuditListener.class)
|
||||
.doesNotHaveBean(AuthorizationAuditListener.class));
|
||||
.withPropertyValues("management.auditevents.enabled=false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(AuditListener.class)
|
||||
.doesNotHaveBean(AuthenticationAuditListener.class)
|
||||
.doesNotHaveBean(AuthorizationAuditListener.class));
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -42,14 +42,14 @@ class AuditEventsEndpointAutoConfigurationTests {
|
||||
@Test
|
||||
void runWhenRepositoryBeanAvailableShouldHaveEndpointBean() {
|
||||
this.contextRunner.withUserConfiguration(CustomAuditEventRepositoryConfiguration.class)
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=auditevents")
|
||||
.run((context) -> assertThat(context).hasSingleBean(AuditEventsEndpoint.class));
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=auditevents")
|
||||
.run((context) -> assertThat(context).hasSingleBean(AuditEventsEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void endpointBacksOffWhenRepositoryNotAvailable() {
|
||||
this.contextRunner.withPropertyValues("management.endpoints.web.exposure.include=auditevents")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(AuditEventsEndpoint.class));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(AuditEventsEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -60,9 +60,9 @@ class AuditEventsEndpointAutoConfigurationTests {
|
||||
@Test
|
||||
void runWhenEnabledPropertyIsFalseShouldNotHaveEndpoint() {
|
||||
this.contextRunner.withUserConfiguration(CustomAuditEventRepositoryConfiguration.class)
|
||||
.withPropertyValues("management.endpoint.auditevents.enabled:false")
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=*")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(AuditEventsEndpoint.class));
|
||||
.withPropertyValues("management.endpoint.auditevents.enabled:false")
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=*")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(AuditEventsEndpoint.class));
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -35,30 +35,30 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class AvailabilityHealthContributorAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(ApplicationAvailabilityAutoConfiguration.class,
|
||||
AvailabilityHealthContributorAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(ApplicationAvailabilityAutoConfiguration.class,
|
||||
AvailabilityHealthContributorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void probesWhenNotKubernetesAddsNoBeans() {
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(ApplicationAvailability.class)
|
||||
.doesNotHaveBean(LivenessStateHealthIndicator.class)
|
||||
.doesNotHaveBean(ReadinessStateHealthIndicator.class));
|
||||
.doesNotHaveBean(LivenessStateHealthIndicator.class)
|
||||
.doesNotHaveBean(ReadinessStateHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void livenessIndicatorWhenPropertyEnabledAddsBeans() {
|
||||
this.contextRunner.withPropertyValues("management.health.livenessState.enabled=true")
|
||||
.run((context) -> assertThat(context).hasSingleBean(ApplicationAvailability.class)
|
||||
.hasSingleBean(LivenessStateHealthIndicator.class)
|
||||
.doesNotHaveBean(ReadinessStateHealthIndicator.class));
|
||||
.run((context) -> assertThat(context).hasSingleBean(ApplicationAvailability.class)
|
||||
.hasSingleBean(LivenessStateHealthIndicator.class)
|
||||
.doesNotHaveBean(ReadinessStateHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void readinessIndicatorWhenPropertyEnabledAddsBeans() {
|
||||
this.contextRunner.withPropertyValues("management.health.readinessState.enabled=true")
|
||||
.run((context) -> assertThat(context).hasSingleBean(ApplicationAvailability.class)
|
||||
.hasSingleBean(ReadinessStateHealthIndicator.class)
|
||||
.doesNotHaveBean(LivenessStateHealthIndicator.class));
|
||||
.run((context) -> assertThat(context).hasSingleBean(ApplicationAvailability.class)
|
||||
.hasSingleBean(ReadinessStateHealthIndicator.class)
|
||||
.doesNotHaveBean(LivenessStateHealthIndicator.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -35,44 +35,48 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class AvailabilityProbesAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(ApplicationAvailabilityAutoConfiguration.class,
|
||||
AvailabilityHealthContributorAutoConfiguration.class, AvailabilityProbesAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(ApplicationAvailabilityAutoConfiguration.class,
|
||||
AvailabilityHealthContributorAutoConfiguration.class, AvailabilityProbesAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void probesWhenNotKubernetesAddsNoBeans() {
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(ApplicationAvailability.class)
|
||||
.doesNotHaveBean(LivenessStateHealthIndicator.class)
|
||||
.doesNotHaveBean(ReadinessStateHealthIndicator.class)
|
||||
.doesNotHaveBean(AvailabilityProbesHealthEndpointGroupsPostProcessor.class));
|
||||
.doesNotHaveBean(LivenessStateHealthIndicator.class)
|
||||
.doesNotHaveBean(ReadinessStateHealthIndicator.class)
|
||||
.doesNotHaveBean(AvailabilityProbesHealthEndpointGroupsPostProcessor.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void probesWhenKubernetesAddsBeans() {
|
||||
this.contextRunner.withPropertyValues("spring.main.cloud-platform=kubernetes")
|
||||
.run((context) -> assertThat(context).hasSingleBean(ApplicationAvailability.class)
|
||||
.hasSingleBean(LivenessStateHealthIndicator.class).hasBean("livenessStateHealthIndicator")
|
||||
.hasSingleBean(ReadinessStateHealthIndicator.class).hasBean("readinessStateHealthIndicator")
|
||||
.hasSingleBean(AvailabilityProbesHealthEndpointGroupsPostProcessor.class));
|
||||
.run((context) -> assertThat(context).hasSingleBean(ApplicationAvailability.class)
|
||||
.hasSingleBean(LivenessStateHealthIndicator.class)
|
||||
.hasBean("livenessStateHealthIndicator")
|
||||
.hasSingleBean(ReadinessStateHealthIndicator.class)
|
||||
.hasBean("readinessStateHealthIndicator")
|
||||
.hasSingleBean(AvailabilityProbesHealthEndpointGroupsPostProcessor.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void probesWhenPropertyEnabledAddsBeans() {
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.probes.enabled=true")
|
||||
.run((context) -> assertThat(context).hasSingleBean(ApplicationAvailability.class)
|
||||
.hasSingleBean(LivenessStateHealthIndicator.class).hasBean("livenessStateHealthIndicator")
|
||||
.hasSingleBean(ReadinessStateHealthIndicator.class).hasBean("readinessStateHealthIndicator")
|
||||
.hasSingleBean(AvailabilityProbesHealthEndpointGroupsPostProcessor.class));
|
||||
.run((context) -> assertThat(context).hasSingleBean(ApplicationAvailability.class)
|
||||
.hasSingleBean(LivenessStateHealthIndicator.class)
|
||||
.hasBean("livenessStateHealthIndicator")
|
||||
.hasSingleBean(ReadinessStateHealthIndicator.class)
|
||||
.hasBean("readinessStateHealthIndicator")
|
||||
.hasSingleBean(AvailabilityProbesHealthEndpointGroupsPostProcessor.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void probesWhenKubernetesAndPropertyDisabledAddsNotBeans() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.main.cloud-platform=kubernetes",
|
||||
"management.endpoint.health.probes.enabled=false")
|
||||
.run((context) -> assertThat(context).hasSingleBean(ApplicationAvailability.class)
|
||||
.doesNotHaveBean(LivenessStateHealthIndicator.class)
|
||||
.doesNotHaveBean(ReadinessStateHealthIndicator.class)
|
||||
.doesNotHaveBean(AvailabilityProbesHealthEndpointGroupsPostProcessor.class));
|
||||
.withPropertyValues("spring.main.cloud-platform=kubernetes",
|
||||
"management.endpoint.health.probes.enabled=false")
|
||||
.run((context) -> assertThat(context).hasSingleBean(ApplicationAvailability.class)
|
||||
.doesNotHaveBean(LivenessStateHealthIndicator.class)
|
||||
.doesNotHaveBean(ReadinessStateHealthIndicator.class)
|
||||
.doesNotHaveBean(AvailabilityProbesHealthEndpointGroupsPostProcessor.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ class AvailabilityProbesHealthEndpointGroupsPostProcessorTests {
|
||||
names.add("liveness");
|
||||
given(groups.getNames()).willReturn(names);
|
||||
assertThat(this.postProcessor.postProcessHealthEndpointGroups(groups))
|
||||
.isInstanceOf(AvailabilityProbesHealthEndpointGroups.class);
|
||||
.isInstanceOf(AvailabilityProbesHealthEndpointGroups.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -60,7 +60,7 @@ class AvailabilityProbesHealthEndpointGroupsPostProcessorTests {
|
||||
names.add("readiness");
|
||||
given(groups.getNames()).willReturn(names);
|
||||
assertThat(this.postProcessor.postProcessHealthEndpointGroups(groups))
|
||||
.isInstanceOf(AvailabilityProbesHealthEndpointGroups.class);
|
||||
.isInstanceOf(AvailabilityProbesHealthEndpointGroups.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -72,7 +72,7 @@ class AvailabilityProbesHealthEndpointGroupsPostProcessorTests {
|
||||
names.add("boot");
|
||||
given(groups.getNames()).willReturn(names);
|
||||
assertThat(this.postProcessor.postProcessHealthEndpointGroups(groups))
|
||||
.isInstanceOf(AvailabilityProbesHealthEndpointGroups.class);
|
||||
.isInstanceOf(AvailabilityProbesHealthEndpointGroups.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -52,7 +52,7 @@ class AvailabilityProbesHealthEndpointGroupsTests {
|
||||
@Test
|
||||
void createWhenGroupsIsNullThrowsException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new AvailabilityProbesHealthEndpointGroups(null, false))
|
||||
.withMessage("Groups must not be null");
|
||||
.withMessage("Groups must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -32,12 +32,12 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class BeansEndpointAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(BeansEndpointAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(BeansEndpointAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void runShouldHaveEndpointBean() {
|
||||
this.contextRunner.withPropertyValues("management.endpoints.web.exposure.include=beans")
|
||||
.run((context) -> assertThat(context).hasSingleBean(BeansEndpoint.class));
|
||||
.run((context) -> assertThat(context).hasSingleBean(BeansEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -48,8 +48,8 @@ class BeansEndpointAutoConfigurationTests {
|
||||
@Test
|
||||
void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
|
||||
this.contextRunner.withPropertyValues("management.endpoint.beans.enabled:false")
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=*")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(BeansEndpoint.class));
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=*")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(BeansEndpoint.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -36,42 +36,42 @@ import static org.mockito.Mockito.mock;
|
||||
class CachesEndpointAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(CachesEndpointAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(CachesEndpointAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void runShouldHaveEndpointBean() {
|
||||
this.contextRunner.withBean(CacheManager.class, () -> mock(CacheManager.class))
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=caches")
|
||||
.run((context) -> assertThat(context).hasSingleBean(CachesEndpoint.class));
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=caches")
|
||||
.run((context) -> assertThat(context).hasSingleBean(CachesEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWithoutCacheManagerShouldHaveEndpointBean() {
|
||||
this.contextRunner.withPropertyValues("management.endpoints.web.exposure.include=caches")
|
||||
.run((context) -> assertThat(context).hasSingleBean(CachesEndpoint.class));
|
||||
.run((context) -> assertThat(context).hasSingleBean(CachesEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWhenNotExposedShouldNotHaveEndpointBean() {
|
||||
this.contextRunner.withBean(CacheManager.class, () -> mock(CacheManager.class))
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(CachesEndpoint.class));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(CachesEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
|
||||
this.contextRunner.withPropertyValues("management.endpoint.caches.enabled:false")
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=*")
|
||||
.withBean(CacheManager.class, () -> mock(CacheManager.class))
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(CachesEndpoint.class));
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=*")
|
||||
.withBean(CacheManager.class, () -> mock(CacheManager.class))
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(CachesEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWhenOnlyExposedOverJmxShouldHaveEndpointBeanWithoutWebExtension() {
|
||||
this.contextRunner.withBean(CacheManager.class, () -> mock(CacheManager.class))
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=info", "spring.jmx.enabled=true",
|
||||
"management.endpoints.jmx.exposure.include=caches")
|
||||
.run((context) -> assertThat(context).hasSingleBean(CachesEndpoint.class)
|
||||
.doesNotHaveBean(CachesEndpointWebExtension.class));
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=info", "spring.jmx.enabled=true",
|
||||
"management.endpoints.jmx.exposure.include=caches")
|
||||
.run((context) -> assertThat(context).hasSingleBean(CachesEndpoint.class)
|
||||
.doesNotHaveBean(CachesEndpointWebExtension.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -38,35 +38,35 @@ import static org.mockito.Mockito.mock;
|
||||
class CassandraHealthContributorAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(CassandraHealthContributorAutoConfiguration.class,
|
||||
HealthContributorAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(CassandraHealthContributorAutoConfiguration.class,
|
||||
HealthContributorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void runWithoutCqlSessionOrCassandraOperationsShouldNotCreateIndicator() {
|
||||
this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean("cassandraHealthContributor")
|
||||
.doesNotHaveBean(CassandraDriverHealthIndicator.class));
|
||||
.doesNotHaveBean(CassandraDriverHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWithCqlSessionOnlyShouldCreateDriverIndicator() {
|
||||
this.contextRunner.withBean(CqlSession.class, () -> mock(CqlSession.class))
|
||||
.run((context) -> assertThat(context).hasSingleBean(CassandraDriverHealthIndicator.class));
|
||||
.run((context) -> assertThat(context).hasSingleBean(CassandraDriverHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWithCqlSessionAndSpringDataAbsentShouldCreateDriverIndicator() {
|
||||
this.contextRunner.withBean(CqlSession.class, () -> mock(CqlSession.class))
|
||||
.withClassLoader(new FilteredClassLoader("org.springframework.data"))
|
||||
.run((context) -> assertThat(context).hasSingleBean(CassandraDriverHealthIndicator.class));
|
||||
.withClassLoader(new FilteredClassLoader("org.springframework.data"))
|
||||
.run((context) -> assertThat(context).hasSingleBean(CassandraDriverHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWhenDisabledShouldNotCreateIndicator() {
|
||||
this.contextRunner.withBean(CqlSession.class, () -> mock(CqlSession.class))
|
||||
.withBean(CassandraOperations.class, () -> mock(CassandraOperations.class))
|
||||
.withPropertyValues("management.health.cassandra.enabled:false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean("cassandraHealthContributor")
|
||||
.doesNotHaveBean(CassandraDriverHealthIndicator.class));
|
||||
.withBean(CassandraOperations.class, () -> mock(CassandraOperations.class))
|
||||
.withPropertyValues("management.health.cassandra.enabled:false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean("cassandraHealthContributor")
|
||||
.doesNotHaveBean(CassandraDriverHealthIndicator.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -40,45 +40,46 @@ import static org.mockito.Mockito.mock;
|
||||
class CassandraReactiveHealthContributorAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(CassandraReactiveHealthContributorAutoConfiguration.class,
|
||||
CassandraHealthContributorAutoConfiguration.class, HealthContributorAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(CassandraReactiveHealthContributorAutoConfiguration.class,
|
||||
CassandraHealthContributorAutoConfiguration.class, HealthContributorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void runWithoutCqlSessionOrReactiveCassandraOperationsShouldNotCreateIndicator() {
|
||||
this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean("cassandraHealthContributor")
|
||||
.doesNotHaveBean(CassandraDriverReactiveHealthIndicator.class));
|
||||
.doesNotHaveBean(CassandraDriverReactiveHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWithCqlSessionOnlyShouldCreateDriverIndicator() {
|
||||
this.contextRunner.withBean(CqlSession.class, () -> mock(CqlSession.class)).run((context) -> assertThat(context)
|
||||
.hasBean("cassandraHealthContributor").hasSingleBean(CassandraDriverReactiveHealthIndicator.class));
|
||||
this.contextRunner.withBean(CqlSession.class, () -> mock(CqlSession.class))
|
||||
.run((context) -> assertThat(context).hasBean("cassandraHealthContributor")
|
||||
.hasSingleBean(CassandraDriverReactiveHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWithCqlSessionAndReactiveCassandraOperationsShouldCreateDriverIndicator() {
|
||||
this.contextRunner.withBean(CqlSession.class, () -> mock(CqlSession.class))
|
||||
.withBean(ReactiveCassandraOperations.class, () -> mock(ReactiveCassandraOperations.class))
|
||||
.withBean(CassandraOperations.class, () -> mock(CassandraOperations.class))
|
||||
.run((context) -> assertThat(context).hasBean("cassandraHealthContributor")
|
||||
.hasSingleBean(CassandraDriverReactiveHealthIndicator.class)
|
||||
.doesNotHaveBean(CassandraDriverHealthIndicator.class));
|
||||
.withBean(ReactiveCassandraOperations.class, () -> mock(ReactiveCassandraOperations.class))
|
||||
.withBean(CassandraOperations.class, () -> mock(CassandraOperations.class))
|
||||
.run((context) -> assertThat(context).hasBean("cassandraHealthContributor")
|
||||
.hasSingleBean(CassandraDriverReactiveHealthIndicator.class)
|
||||
.doesNotHaveBean(CassandraDriverHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWithCqlSessionAndSpringDataAbsentShouldCreateDriverIndicator() {
|
||||
this.contextRunner.withBean(CqlSession.class, () -> mock(CqlSession.class))
|
||||
.withClassLoader(new FilteredClassLoader("org.springframework.data"))
|
||||
.run((context) -> assertThat(context).hasBean("cassandraHealthContributor")
|
||||
.hasSingleBean(CassandraDriverReactiveHealthIndicator.class));
|
||||
.withClassLoader(new FilteredClassLoader("org.springframework.data"))
|
||||
.run((context) -> assertThat(context).hasBean("cassandraHealthContributor")
|
||||
.hasSingleBean(CassandraDriverReactiveHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWhenDisabledShouldNotCreateIndicator() {
|
||||
this.contextRunner.withBean(CqlSession.class, () -> mock(CqlSession.class))
|
||||
.withBean(ReactiveCassandraOperations.class, () -> mock(ReactiveCassandraOperations.class))
|
||||
.withPropertyValues("management.health.cassandra.enabled:false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean("cassandraHealthContributor"));
|
||||
.withBean(ReactiveCassandraOperations.class, () -> mock(ReactiveCassandraOperations.class))
|
||||
.withPropertyValues("management.health.cassandra.enabled:false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean("cassandraHealthContributor"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -58,7 +58,7 @@ class CloudFoundryAuthorizationExceptionTests {
|
||||
@Test
|
||||
void statusCodeForUnsupportedSignatureAlgorithmReasonShouldBe401() {
|
||||
assertThat(createException(Reason.UNSUPPORTED_TOKEN_SIGNING_ALGORITHM).getStatusCode())
|
||||
.isEqualTo(HttpStatus.UNAUTHORIZED);
|
||||
.isEqualTo(HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -74,7 +74,7 @@ class CloudFoundryAuthorizationExceptionTests {
|
||||
@Test
|
||||
void statusCodeForServiceUnavailableReasonShouldBe503() {
|
||||
assertThat(createException(Reason.SERVICE_UNAVAILABLE).getStatusCode())
|
||||
.isEqualTo(HttpStatus.SERVICE_UNAVAILABLE);
|
||||
.isEqualTo(HttpStatus.SERVICE_UNAVAILABLE);
|
||||
}
|
||||
|
||||
private CloudFoundryAuthorizationException createException(Reason reason) {
|
||||
|
||||
@@ -67,8 +67,8 @@ class CloudFoundryWebEndpointDiscovererTests {
|
||||
if (endpoint.getEndpointId().equals(EndpointId.of("health"))) {
|
||||
WebOperation operation = findMainReadOperation(endpoint);
|
||||
assertThat(operation
|
||||
.invoke(new InvocationContext(mock(SecurityContext.class), Collections.emptyMap())))
|
||||
.isEqualTo("cf");
|
||||
.invoke(new InvocationContext(mock(SecurityContext.class), Collections.emptyMap())))
|
||||
.isEqualTo("cf");
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -78,8 +78,9 @@ class CloudFoundryWebEndpointDiscovererTests {
|
||||
void shouldRegisterHints() {
|
||||
RuntimeHints runtimeHints = new RuntimeHints();
|
||||
new CloudFoundryWebEndpointDiscovererRuntimeHints().registerHints(runtimeHints, getClass().getClassLoader());
|
||||
assertThat(RuntimeHintsPredicates.reflection().onType(CloudFoundryEndpointFilter.class)
|
||||
.withMemberCategories(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS)).accepts(runtimeHints);
|
||||
assertThat(RuntimeHintsPredicates.reflection()
|
||||
.onType(CloudFoundryEndpointFilter.class)
|
||||
.withMemberCategories(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS)).accepts(runtimeHints);
|
||||
}
|
||||
|
||||
private WebOperation findMainReadOperation(ExposableWebEndpoint endpoint) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -36,7 +36,7 @@ class TokenTests {
|
||||
@Test
|
||||
void invalidJwtShouldThrowException() {
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(() -> new Token("invalid-token"))
|
||||
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -44,9 +44,9 @@ class TokenTests {
|
||||
String header = "{\"alg\": \"RS256\", \"kid\": \"key-id\", \"typ\": \"JWT\"}";
|
||||
String claims = "invalid-claims";
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(() -> new Token(Base64.getEncoder().encodeToString(header.getBytes()) + "."
|
||||
+ Base64.getEncoder().encodeToString(claims.getBytes())))
|
||||
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
.isThrownBy(() -> new Token(Base64.getEncoder().encodeToString(header.getBytes()) + "."
|
||||
+ Base64.getEncoder().encodeToString(claims.getBytes())))
|
||||
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -54,9 +54,9 @@ class TokenTests {
|
||||
String header = "invalid-header";
|
||||
String claims = "{\"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\"}";
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(() -> new Token(Base64.getEncoder().encodeToString(header.getBytes()) + "."
|
||||
+ Base64.getEncoder().encodeToString(claims.getBytes())))
|
||||
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
.isThrownBy(() -> new Token(Base64.getEncoder().encodeToString(header.getBytes()) + "."
|
||||
+ Base64.getEncoder().encodeToString(claims.getBytes())))
|
||||
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -64,7 +64,7 @@ class TokenTests {
|
||||
String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ0b3B0YWwu"
|
||||
+ "Y29tIiwiZXhwIjoxNDI2NDIwODAwLCJhd2Vzb21lIjp0cnVlfQ.";
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(() -> new Token(token))
|
||||
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -89,7 +89,7 @@ class TokenTests {
|
||||
String claims = "{\"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\"}";
|
||||
Token token = createToken(header, claims);
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(token::getSignatureAlgorithm)
|
||||
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -98,7 +98,7 @@ class TokenTests {
|
||||
String claims = "{\"exp\": 2147483647}";
|
||||
Token token = createToken(header, claims);
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(token::getIssuer)
|
||||
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -107,7 +107,7 @@ class TokenTests {
|
||||
String claims = "{\"exp\": 2147483647}";
|
||||
Token token = createToken(header, claims);
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(token::getKeyId)
|
||||
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -116,7 +116,7 @@ class TokenTests {
|
||||
String claims = "{\"iss\": \"http://localhost:8080/uaa/oauth/token\"}";
|
||||
Token token = createToken(header, claims);
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(token::getExpiry)
|
||||
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
}
|
||||
|
||||
private Token createToken(String header, String claims) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -50,23 +50,23 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class CloudFoundryReactiveHealthEndpointWebExtensionTests {
|
||||
|
||||
private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner()
|
||||
.withPropertyValues("VCAP_APPLICATION={}")
|
||||
.withConfiguration(AutoConfigurations.of(ReactiveSecurityAutoConfiguration.class,
|
||||
ReactiveUserDetailsServiceAutoConfiguration.class, WebFluxAutoConfiguration.class,
|
||||
JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class,
|
||||
ReactiveCloudFoundryActuatorAutoConfigurationTests.WebClientCustomizerConfig.class,
|
||||
WebClientAutoConfiguration.class, ManagementContextAutoConfiguration.class,
|
||||
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
|
||||
HealthContributorAutoConfiguration.class, HealthEndpointAutoConfiguration.class,
|
||||
ReactiveCloudFoundryActuatorAutoConfiguration.class))
|
||||
.withUserConfiguration(TestHealthIndicator.class);
|
||||
.withPropertyValues("VCAP_APPLICATION={}")
|
||||
.withConfiguration(AutoConfigurations.of(ReactiveSecurityAutoConfiguration.class,
|
||||
ReactiveUserDetailsServiceAutoConfiguration.class, WebFluxAutoConfiguration.class,
|
||||
JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class,
|
||||
ReactiveCloudFoundryActuatorAutoConfigurationTests.WebClientCustomizerConfig.class,
|
||||
WebClientAutoConfiguration.class, ManagementContextAutoConfiguration.class,
|
||||
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
|
||||
HealthContributorAutoConfiguration.class, HealthEndpointAutoConfiguration.class,
|
||||
ReactiveCloudFoundryActuatorAutoConfiguration.class))
|
||||
.withUserConfiguration(TestHealthIndicator.class);
|
||||
|
||||
@Test
|
||||
void healthComponentsAlwaysPresent() {
|
||||
this.contextRunner.run((context) -> {
|
||||
CloudFoundryReactiveHealthEndpointWebExtension extension = context
|
||||
.getBean(CloudFoundryReactiveHealthEndpointWebExtension.class);
|
||||
.getBean(CloudFoundryReactiveHealthEndpointWebExtension.class);
|
||||
HealthComponent body = extension.health(ApiVersion.V3).block(Duration.ofSeconds(30)).getBody();
|
||||
HealthComponent health = ((CompositeHealth) body).getComponents().entrySet().iterator().next().getValue();
|
||||
assertThat(((Health) health).getDetails()).containsEntry("spring", "boot");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -39,7 +39,7 @@ class CloudFoundryWebFluxEndpointHandlerMappingTests {
|
||||
new CloudFoundryWebFluxEndpointHandlerMappingRuntimeHints().registerHints(runtimeHints,
|
||||
getClass().getClassLoader());
|
||||
assertThat(RuntimeHintsPredicates.reflection().onMethod(CloudFoundryLinksHandler.class, "links"))
|
||||
.accepts(runtimeHints);
|
||||
.accepts(runtimeHints);
|
||||
assertThat(RuntimeHintsPredicates.reflection().onType(Link.class)).accepts(runtimeHints);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -78,50 +78,87 @@ class CloudFoundryWebFluxEndpointIntegrationTests {
|
||||
|
||||
private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner(
|
||||
AnnotationConfigReactiveWebServerApplicationContext::new)
|
||||
.withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class,
|
||||
HttpHandlerAutoConfiguration.class, ReactiveWebServerFactoryAutoConfiguration.class))
|
||||
.withUserConfiguration(TestEndpointConfiguration.class).withPropertyValues("server.port=0");
|
||||
.withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class, HttpHandlerAutoConfiguration.class,
|
||||
ReactiveWebServerFactoryAutoConfiguration.class))
|
||||
.withUserConfiguration(TestEndpointConfiguration.class)
|
||||
.withPropertyValues("server.port=0");
|
||||
|
||||
@Test
|
||||
void operationWithSecurityInterceptorForbidden() {
|
||||
given(tokenValidator.validate(any())).willReturn(Mono.empty());
|
||||
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(Mono.just(AccessLevel.RESTRICTED));
|
||||
this.contextRunner.run(withWebTestClient((client) -> client.get().uri("/cfApplication/test")
|
||||
.accept(MediaType.APPLICATION_JSON).header("Authorization", "bearer " + mockAccessToken()).exchange()
|
||||
.expectStatus().isEqualTo(HttpStatus.FORBIDDEN)));
|
||||
this.contextRunner.run(withWebTestClient((client) -> client.get()
|
||||
.uri("/cfApplication/test")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken())
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isEqualTo(HttpStatus.FORBIDDEN)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void operationWithSecurityInterceptorSuccess() {
|
||||
given(tokenValidator.validate(any())).willReturn(Mono.empty());
|
||||
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(Mono.just(AccessLevel.FULL));
|
||||
this.contextRunner.run(withWebTestClient((client) -> client.get().uri("/cfApplication/test")
|
||||
.accept(MediaType.APPLICATION_JSON).header("Authorization", "bearer " + mockAccessToken()).exchange()
|
||||
.expectStatus().isEqualTo(HttpStatus.OK)));
|
||||
this.contextRunner.run(withWebTestClient((client) -> client.get()
|
||||
.uri("/cfApplication/test")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken())
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isEqualTo(HttpStatus.OK)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void responseToOptionsRequestIncludesCorsHeaders() {
|
||||
this.contextRunner.run(withWebTestClient((client) -> client.options().uri("/cfApplication/test")
|
||||
.accept(MediaType.APPLICATION_JSON).header("Access-Control-Request-Method", "POST")
|
||||
.header("Origin", "https://example.com").exchange().expectStatus().isOk().expectHeader()
|
||||
.valueEquals("Access-Control-Allow-Origin", "https://example.com").expectHeader()
|
||||
.valueEquals("Access-Control-Allow-Methods", "GET,POST")));
|
||||
this.contextRunner.run(withWebTestClient((client) -> client.options()
|
||||
.uri("/cfApplication/test")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.header("Access-Control-Request-Method", "POST")
|
||||
.header("Origin", "https://example.com")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectHeader()
|
||||
.valueEquals("Access-Control-Allow-Origin", "https://example.com")
|
||||
.expectHeader()
|
||||
.valueEquals("Access-Control-Allow-Methods", "GET,POST")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void linksToOtherEndpointsWithFullAccess() {
|
||||
given(tokenValidator.validate(any())).willReturn(Mono.empty());
|
||||
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(Mono.just(AccessLevel.FULL));
|
||||
this.contextRunner
|
||||
.run(withWebTestClient((client) -> client.get().uri("/cfApplication").accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken()).exchange().expectStatus().isOk()
|
||||
.expectBody().jsonPath("_links.length()").isEqualTo(5).jsonPath("_links.self.href").isNotEmpty()
|
||||
.jsonPath("_links.self.templated").isEqualTo(false).jsonPath("_links.info.href").isNotEmpty()
|
||||
.jsonPath("_links.info.templated").isEqualTo(false).jsonPath("_links.env.href").isNotEmpty()
|
||||
.jsonPath("_links.env.templated").isEqualTo(false).jsonPath("_links.test.href").isNotEmpty()
|
||||
.jsonPath("_links.test.templated").isEqualTo(false).jsonPath("_links.test-part.href")
|
||||
.isNotEmpty().jsonPath("_links.test-part.templated").isEqualTo(true)));
|
||||
this.contextRunner.run(withWebTestClient((client) -> client.get()
|
||||
.uri("/cfApplication")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken())
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody()
|
||||
.jsonPath("_links.length()")
|
||||
.isEqualTo(5)
|
||||
.jsonPath("_links.self.href")
|
||||
.isNotEmpty()
|
||||
.jsonPath("_links.self.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.info.href")
|
||||
.isNotEmpty()
|
||||
.jsonPath("_links.info.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.env.href")
|
||||
.isNotEmpty()
|
||||
.jsonPath("_links.env.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.test.href")
|
||||
.isNotEmpty()
|
||||
.jsonPath("_links.test.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.test-part.href")
|
||||
.isNotEmpty()
|
||||
.jsonPath("_links.test-part.templated")
|
||||
.isEqualTo(true)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -129,31 +166,55 @@ class CloudFoundryWebFluxEndpointIntegrationTests {
|
||||
CloudFoundryAuthorizationException exception = new CloudFoundryAuthorizationException(Reason.INVALID_TOKEN,
|
||||
"invalid-token");
|
||||
willThrow(exception).given(tokenValidator).validate(any());
|
||||
this.contextRunner.run(withWebTestClient((client) -> client.get().uri("/cfApplication")
|
||||
.accept(MediaType.APPLICATION_JSON).header("Authorization", "bearer " + mockAccessToken()).exchange()
|
||||
.expectStatus().isUnauthorized()));
|
||||
this.contextRunner.run(withWebTestClient((client) -> client.get()
|
||||
.uri("/cfApplication")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken())
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isUnauthorized()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void linksToOtherEndpointsWithRestrictedAccess() {
|
||||
given(tokenValidator.validate(any())).willReturn(Mono.empty());
|
||||
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(Mono.just(AccessLevel.RESTRICTED));
|
||||
this.contextRunner
|
||||
.run(withWebTestClient((client) -> client.get().uri("/cfApplication").accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken()).exchange().expectStatus().isOk()
|
||||
.expectBody().jsonPath("_links.length()").isEqualTo(2).jsonPath("_links.self.href").isNotEmpty()
|
||||
.jsonPath("_links.self.templated").isEqualTo(false).jsonPath("_links.info.href").isNotEmpty()
|
||||
.jsonPath("_links.info.templated").isEqualTo(false).jsonPath("_links.env").doesNotExist()
|
||||
.jsonPath("_links.test").doesNotExist().jsonPath("_links.test-part").doesNotExist()));
|
||||
this.contextRunner.run(withWebTestClient((client) -> client.get()
|
||||
.uri("/cfApplication")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken())
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody()
|
||||
.jsonPath("_links.length()")
|
||||
.isEqualTo(2)
|
||||
.jsonPath("_links.self.href")
|
||||
.isNotEmpty()
|
||||
.jsonPath("_links.self.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.info.href")
|
||||
.isNotEmpty()
|
||||
.jsonPath("_links.info.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.env")
|
||||
.doesNotExist()
|
||||
.jsonPath("_links.test")
|
||||
.doesNotExist()
|
||||
.jsonPath("_links.test-part")
|
||||
.doesNotExist()));
|
||||
}
|
||||
|
||||
private ContextConsumer<AssertableReactiveWebApplicationContext> withWebTestClient(
|
||||
Consumer<WebTestClient> clientConsumer) {
|
||||
return (context) -> {
|
||||
int port = ((AnnotationConfigReactiveWebServerApplicationContext) context.getSourceApplicationContext())
|
||||
.getWebServer().getPort();
|
||||
clientConsumer.accept(WebTestClient.bindToServer().baseUrl("http://localhost:" + port)
|
||||
.responseTimeout(Duration.ofMinutes(5)).build());
|
||||
.getWebServer()
|
||||
.getPort();
|
||||
clientConsumer.accept(WebTestClient.bindToServer()
|
||||
.baseUrl("http://localhost:" + port)
|
||||
.responseTimeout(Duration.ofMinutes(5))
|
||||
.build());
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -84,15 +84,15 @@ class ReactiveCloudFoundryActuatorAutoConfigurationTests {
|
||||
private static final String V3_JSON = ApiVersion.V3.getProducedMimeType().toString();
|
||||
|
||||
private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(ReactiveSecurityAutoConfiguration.class,
|
||||
ReactiveUserDetailsServiceAutoConfiguration.class, WebFluxAutoConfiguration.class,
|
||||
JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class, WebClientCustomizerConfig.class,
|
||||
WebClientAutoConfiguration.class, ManagementContextAutoConfiguration.class,
|
||||
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
|
||||
HealthContributorAutoConfiguration.class, HealthEndpointAutoConfiguration.class,
|
||||
InfoContributorAutoConfiguration.class, InfoEndpointAutoConfiguration.class,
|
||||
ProjectInfoAutoConfiguration.class, ReactiveCloudFoundryActuatorAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(ReactiveSecurityAutoConfiguration.class,
|
||||
ReactiveUserDetailsServiceAutoConfiguration.class, WebFluxAutoConfiguration.class,
|
||||
JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class, WebClientCustomizerConfig.class,
|
||||
WebClientAutoConfiguration.class, ManagementContextAutoConfiguration.class,
|
||||
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
|
||||
HealthContributorAutoConfiguration.class, HealthEndpointAutoConfiguration.class,
|
||||
InfoContributorAutoConfiguration.class, InfoEndpointAutoConfiguration.class,
|
||||
ProjectInfoAutoConfiguration.class, ReactiveCloudFoundryActuatorAutoConfiguration.class));
|
||||
|
||||
@AfterEach
|
||||
void close() {
|
||||
@@ -101,149 +101,161 @@ class ReactiveCloudFoundryActuatorAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
void cloudFoundryPlatformActive() {
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
EndpointMapping endpointMapping = (EndpointMapping) ReflectionTestUtils.getField(handlerMapping,
|
||||
"endpointMapping");
|
||||
assertThat(endpointMapping.getPath()).isEqualTo("/cloudfoundryapplication");
|
||||
CorsConfiguration corsConfiguration = (CorsConfiguration) ReflectionTestUtils
|
||||
.getField(handlerMapping, "corsConfiguration");
|
||||
assertThat(corsConfiguration.getAllowedOrigins()).contains("*");
|
||||
assertThat(corsConfiguration.getAllowedMethods())
|
||||
.containsAll(Arrays.asList(HttpMethod.GET.name(), HttpMethod.POST.name()));
|
||||
assertThat(corsConfiguration.getAllowedHeaders())
|
||||
.containsAll(Arrays.asList("Authorization", "X-Cf-App-Instance", "Content-Type"));
|
||||
});
|
||||
this.contextRunner
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
EndpointMapping endpointMapping = (EndpointMapping) ReflectionTestUtils.getField(handlerMapping,
|
||||
"endpointMapping");
|
||||
assertThat(endpointMapping.getPath()).isEqualTo("/cloudfoundryapplication");
|
||||
CorsConfiguration corsConfiguration = (CorsConfiguration) ReflectionTestUtils.getField(handlerMapping,
|
||||
"corsConfiguration");
|
||||
assertThat(corsConfiguration.getAllowedOrigins()).contains("*");
|
||||
assertThat(corsConfiguration.getAllowedMethods())
|
||||
.containsAll(Arrays.asList(HttpMethod.GET.name(), HttpMethod.POST.name()));
|
||||
assertThat(corsConfiguration.getAllowedHeaders())
|
||||
.containsAll(Arrays.asList("Authorization", "X-Cf-App-Instance", "Content-Type"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void cloudfoundryapplicationProducesActuatorMediaType() {
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
|
||||
WebTestClient webTestClient = WebTestClient.bindToApplicationContext(context).build();
|
||||
webTestClient.get().uri("/cloudfoundryapplication").header("Content-Type",
|
||||
V2_JSON + ";charset=UTF-8");
|
||||
});
|
||||
this.contextRunner
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
WebTestClient webTestClient = WebTestClient.bindToApplicationContext(context).build();
|
||||
webTestClient.get().uri("/cloudfoundryapplication").header("Content-Type", V2_JSON + ";charset=UTF-8");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void cloudFoundryPlatformActiveSetsApplicationId() {
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
|
||||
String applicationId = (String) ReflectionTestUtils.getField(interceptor, "applicationId");
|
||||
assertThat(applicationId).isEqualTo("my-app-id");
|
||||
});
|
||||
this.contextRunner
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
|
||||
String applicationId = (String) ReflectionTestUtils.getField(interceptor, "applicationId");
|
||||
assertThat(applicationId).isEqualTo("my-app-id");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void cloudFoundryPlatformActiveSetsCloudControllerUrl() {
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor,
|
||||
"cloudFoundrySecurityService");
|
||||
String cloudControllerUrl = (String) ReflectionTestUtils.getField(interceptorSecurityService,
|
||||
"cloudControllerUrl");
|
||||
assertThat(cloudControllerUrl).isEqualTo("https://my-cloud-controller.com");
|
||||
});
|
||||
this.contextRunner
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor,
|
||||
"cloudFoundrySecurityService");
|
||||
String cloudControllerUrl = (String) ReflectionTestUtils.getField(interceptorSecurityService,
|
||||
"cloudControllerUrl");
|
||||
assertThat(cloudControllerUrl).isEqualTo("https://my-cloud-controller.com");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void cloudFoundryPlatformActiveAndCloudControllerUrlNotPresent() {
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = context.getBean(
|
||||
"cloudFoundryWebFluxEndpointHandlerMapping",
|
||||
CloudFoundryWebFluxEndpointHandlerMapping.class);
|
||||
Object securityInterceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils.getField(securityInterceptor,
|
||||
"cloudFoundrySecurityService");
|
||||
assertThat(interceptorSecurityService).isNull();
|
||||
});
|
||||
.run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = context.getBean(
|
||||
"cloudFoundryWebFluxEndpointHandlerMapping", CloudFoundryWebFluxEndpointHandlerMapping.class);
|
||||
Object securityInterceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils.getField(securityInterceptor,
|
||||
"cloudFoundrySecurityService");
|
||||
assertThat(interceptorSecurityService).isNull();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void cloudFoundryPathsIgnoredBySpringSecurity() {
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
|
||||
WebFilterChainProxy chainProxy = context.getBean(WebFilterChainProxy.class);
|
||||
List<SecurityWebFilterChain> filters = (List<SecurityWebFilterChain>) ReflectionTestUtils
|
||||
.getField(chainProxy, "filters");
|
||||
Boolean cfRequestMatches = filters.get(0)
|
||||
.matches(MockServerWebExchange
|
||||
.from(MockServerHttpRequest.get("/cloudfoundryapplication/my-path").build()))
|
||||
.block(Duration.ofSeconds(30));
|
||||
Boolean otherRequestMatches = filters.get(0)
|
||||
.matches(MockServerWebExchange.from(MockServerHttpRequest.get("/some-other-path").build()))
|
||||
.block(Duration.ofSeconds(30));
|
||||
assertThat(cfRequestMatches).isTrue();
|
||||
assertThat(otherRequestMatches).isFalse();
|
||||
otherRequestMatches = filters.get(1)
|
||||
.matches(MockServerWebExchange.from(MockServerHttpRequest.get("/some-other-path").build()))
|
||||
.block(Duration.ofSeconds(30));
|
||||
assertThat(otherRequestMatches).isTrue();
|
||||
});
|
||||
this.contextRunner
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
WebFilterChainProxy chainProxy = context.getBean(WebFilterChainProxy.class);
|
||||
List<SecurityWebFilterChain> filters = (List<SecurityWebFilterChain>) ReflectionTestUtils
|
||||
.getField(chainProxy, "filters");
|
||||
Boolean cfRequestMatches = filters.get(0)
|
||||
.matches(MockServerWebExchange
|
||||
.from(MockServerHttpRequest.get("/cloudfoundryapplication/my-path").build()))
|
||||
.block(Duration.ofSeconds(30));
|
||||
Boolean otherRequestMatches = filters.get(0)
|
||||
.matches(MockServerWebExchange.from(MockServerHttpRequest.get("/some-other-path").build()))
|
||||
.block(Duration.ofSeconds(30));
|
||||
assertThat(cfRequestMatches).isTrue();
|
||||
assertThat(otherRequestMatches).isFalse();
|
||||
otherRequestMatches = filters.get(1)
|
||||
.matches(MockServerWebExchange.from(MockServerHttpRequest.get("/some-other-path").build()))
|
||||
.block(Duration.ofSeconds(30));
|
||||
assertThat(otherRequestMatches).isTrue();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void cloudFoundryPlatformInactive() {
|
||||
this.contextRunner.run(
|
||||
(context) -> assertThat(context.containsBean("cloudFoundryWebFluxEndpointHandlerMapping")).isFalse());
|
||||
this.contextRunner
|
||||
.run((context) -> assertThat(context.containsBean("cloudFoundryWebFluxEndpointHandlerMapping")).isFalse());
|
||||
}
|
||||
|
||||
@Test
|
||||
void cloudFoundryManagementEndpointsDisabled() {
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION=---", "management.cloudfoundry.enabled:false").run(
|
||||
(context) -> assertThat(context.containsBean("cloudFoundryWebFluxEndpointHandlerMapping")).isFalse());
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION=---", "management.cloudfoundry.enabled:false")
|
||||
.run((context) -> assertThat(context.containsBean("cloudFoundryWebFluxEndpointHandlerMapping")).isFalse());
|
||||
}
|
||||
|
||||
@Test
|
||||
void allEndpointsAvailableUnderCloudFoundryWithoutEnablingWebIncludes() {
|
||||
this.contextRunner.withBean(TestEndpoint.class, TestEndpoint::new).withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id", "vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Collection<ExposableWebEndpoint> endpoints = handlerMapping.getEndpoints();
|
||||
List<EndpointId> endpointIds = endpoints.stream().map(ExposableWebEndpoint::getEndpointId).toList();
|
||||
assertThat(endpointIds).contains(EndpointId.of("test"));
|
||||
});
|
||||
this.contextRunner.withBean(TestEndpoint.class, TestEndpoint::new)
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Collection<ExposableWebEndpoint> endpoints = handlerMapping.getEndpoints();
|
||||
List<EndpointId> endpointIds = endpoints.stream().map(ExposableWebEndpoint::getEndpointId).toList();
|
||||
assertThat(endpointIds).contains(EndpointId.of("test"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void endpointPathCustomizationIsNotApplied() {
|
||||
this.contextRunner.withBean(TestEndpoint.class, TestEndpoint::new).withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id", "vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Collection<ExposableWebEndpoint> endpoints = handlerMapping.getEndpoints();
|
||||
ExposableWebEndpoint endpoint = endpoints.stream()
|
||||
.filter((candidate) -> EndpointId.of("test").equals(candidate.getEndpointId())).findFirst()
|
||||
.get();
|
||||
assertThat(endpoint.getOperations()).hasSize(1);
|
||||
WebOperation operation = endpoint.getOperations().iterator().next();
|
||||
assertThat(operation.getRequestPredicate().getPath()).isEqualTo("test");
|
||||
});
|
||||
this.contextRunner.withBean(TestEndpoint.class, TestEndpoint::new)
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Collection<ExposableWebEndpoint> endpoints = handlerMapping.getEndpoints();
|
||||
ExposableWebEndpoint endpoint = endpoints.stream()
|
||||
.filter((candidate) -> EndpointId.of("test").equals(candidate.getEndpointId()))
|
||||
.findFirst()
|
||||
.get();
|
||||
assertThat(endpoint.getOperations()).hasSize(1);
|
||||
WebOperation operation = endpoint.getOperations().iterator().next();
|
||||
assertThat(operation.getRequestPredicate().getPath()).isEqualTo("test");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void healthEndpointInvokerShouldBeCloudFoundryWebExtension() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(HealthEndpointAutoConfiguration.class))
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
Collection<ExposableWebEndpoint> endpoints = getHandlerMapping(context).getEndpoints();
|
||||
ExposableWebEndpoint endpoint = endpoints.iterator().next();
|
||||
assertThat(endpoint.getOperations()).hasSize(2);
|
||||
WebOperation webOperation = findOperationWithRequestPath(endpoint, "health");
|
||||
assertThat(webOperation).extracting("invoker").extracting("target")
|
||||
.isInstanceOf(CloudFoundryReactiveHealthEndpointWebExtension.class);
|
||||
});
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
Collection<ExposableWebEndpoint> endpoints = getHandlerMapping(context).getEndpoints();
|
||||
ExposableWebEndpoint endpoint = endpoints.iterator().next();
|
||||
assertThat(endpoint.getOperations()).hasSize(2);
|
||||
WebOperation webOperation = findOperationWithRequestPath(endpoint, "health");
|
||||
assertThat(webOperation).extracting("invoker")
|
||||
.extracting("target")
|
||||
.isInstanceOf(CloudFoundryReactiveHealthEndpointWebExtension.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -251,7 +263,7 @@ class ReactiveCloudFoundryActuatorAutoConfigurationTests {
|
||||
void gitFullDetailsAlwaysPresent() {
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---").run((context) -> {
|
||||
CloudFoundryInfoEndpointWebExtension extension = context
|
||||
.getBean(CloudFoundryInfoEndpointWebExtension.class);
|
||||
.getBean(CloudFoundryInfoEndpointWebExtension.class);
|
||||
Map<String, Object> git = (Map<String, Object>) extension.info().get("git");
|
||||
Map<String, Object> commit = (Map<String, Object>) git.get("commit");
|
||||
assertThat(commit).hasSize(4);
|
||||
@@ -261,38 +273,42 @@ class ReactiveCloudFoundryActuatorAutoConfigurationTests {
|
||||
@Test
|
||||
void skipSslValidation() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(HealthEndpointAutoConfiguration.class))
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com",
|
||||
"management.cloudfoundry.skip-ssl-validation:true")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor,
|
||||
"cloudFoundrySecurityService");
|
||||
WebClient webClient = (WebClient) ReflectionTestUtils.getField(interceptorSecurityService,
|
||||
"webClient");
|
||||
webClient.get().uri("https://self-signed.badssl.com/").retrieve().toBodilessEntity()
|
||||
.block(Duration.ofSeconds(30));
|
||||
});
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com",
|
||||
"management.cloudfoundry.skip-ssl-validation:true")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor,
|
||||
"cloudFoundrySecurityService");
|
||||
WebClient webClient = (WebClient) ReflectionTestUtils.getField(interceptorSecurityService, "webClient");
|
||||
webClient.get()
|
||||
.uri("https://self-signed.badssl.com/")
|
||||
.retrieve()
|
||||
.toBodilessEntity()
|
||||
.block(Duration.ofSeconds(30));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void sslValidationNotSkippedByDefault() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(HealthEndpointAutoConfiguration.class))
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor,
|
||||
"cloudFoundrySecurityService");
|
||||
WebClient webClient = (WebClient) ReflectionTestUtils.getField(interceptorSecurityService,
|
||||
"webClient");
|
||||
assertThatExceptionOfType(RuntimeException.class)
|
||||
.isThrownBy(() -> webClient.get().uri("https://self-signed.badssl.com/").retrieve()
|
||||
.toBodilessEntity().block(Duration.ofSeconds(30)))
|
||||
.withCauseInstanceOf(SSLException.class);
|
||||
});
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor,
|
||||
"cloudFoundrySecurityService");
|
||||
WebClient webClient = (WebClient) ReflectionTestUtils.getField(interceptorSecurityService, "webClient");
|
||||
assertThatExceptionOfType(RuntimeException.class)
|
||||
.isThrownBy(() -> webClient.get()
|
||||
.uri("https://self-signed.badssl.com/")
|
||||
.retrieve()
|
||||
.toBodilessEntity()
|
||||
.block(Duration.ofSeconds(30)))
|
||||
.withCauseInstanceOf(SSLException.class);
|
||||
});
|
||||
}
|
||||
|
||||
private CloudFoundryWebFluxEndpointHandlerMapping getHandlerMapping(ApplicationContext context) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -61,64 +61,68 @@ class ReactiveCloudFoundrySecurityInterceptorTests {
|
||||
|
||||
@Test
|
||||
void preHandleWhenRequestIsPreFlightShouldBeOk() {
|
||||
MockServerWebExchange request = MockServerWebExchange
|
||||
.from(MockServerHttpRequest.options("/a").header(HttpHeaders.ORIGIN, "https://example.com")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET").build());
|
||||
MockServerWebExchange request = MockServerWebExchange.from(MockServerHttpRequest.options("/a")
|
||||
.header(HttpHeaders.ORIGIN, "https://example.com")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET")
|
||||
.build());
|
||||
StepVerifier.create(this.interceptor.preHandle(request, "/a"))
|
||||
.consumeNextWith((response) -> assertThat(response.getStatus()).isEqualTo(HttpStatus.OK))
|
||||
.verifyComplete();
|
||||
.consumeNextWith((response) -> assertThat(response.getStatus()).isEqualTo(HttpStatus.OK))
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void preHandleWhenTokenIsMissingShouldReturnMissingAuthorization() {
|
||||
MockServerWebExchange request = MockServerWebExchange.from(MockServerHttpRequest.get("/a").build());
|
||||
StepVerifier.create(this.interceptor.preHandle(request, "/a")).consumeNextWith(
|
||||
(response) -> assertThat(response.getStatus()).isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus()))
|
||||
.verifyComplete();
|
||||
StepVerifier.create(this.interceptor.preHandle(request, "/a"))
|
||||
.consumeNextWith(
|
||||
(response) -> assertThat(response.getStatus()).isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus()))
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void preHandleWhenTokenIsNotBearerShouldReturnMissingAuthorization() {
|
||||
MockServerWebExchange request = MockServerWebExchange
|
||||
.from(MockServerHttpRequest.get("/a").header(HttpHeaders.AUTHORIZATION, mockAccessToken()).build());
|
||||
StepVerifier.create(this.interceptor.preHandle(request, "/a")).consumeNextWith(
|
||||
(response) -> assertThat(response.getStatus()).isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus()))
|
||||
.verifyComplete();
|
||||
.from(MockServerHttpRequest.get("/a").header(HttpHeaders.AUTHORIZATION, mockAccessToken()).build());
|
||||
StepVerifier.create(this.interceptor.preHandle(request, "/a"))
|
||||
.consumeNextWith(
|
||||
(response) -> assertThat(response.getStatus()).isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus()))
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void preHandleWhenApplicationIdIsNullShouldReturnError() {
|
||||
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator, this.securityService, null);
|
||||
MockServerWebExchange request = MockServerWebExchange.from(MockServerHttpRequest.get("/a")
|
||||
.header(HttpHeaders.AUTHORIZATION, "bearer " + mockAccessToken()).build());
|
||||
.header(HttpHeaders.AUTHORIZATION, "bearer " + mockAccessToken())
|
||||
.build());
|
||||
StepVerifier.create(this.interceptor.preHandle(request, "/a"))
|
||||
.consumeErrorWith((ex) -> assertThat(((CloudFoundryAuthorizationException) ex).getReason())
|
||||
.isEqualTo(Reason.SERVICE_UNAVAILABLE))
|
||||
.verify();
|
||||
.consumeErrorWith((ex) -> assertThat(((CloudFoundryAuthorizationException) ex).getReason())
|
||||
.isEqualTo(Reason.SERVICE_UNAVAILABLE))
|
||||
.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
void preHandleWhenCloudFoundrySecurityServiceIsNullShouldReturnError() {
|
||||
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator, null, "my-app-id");
|
||||
MockServerWebExchange request = MockServerWebExchange
|
||||
.from(MockServerHttpRequest.get("/a").header(HttpHeaders.AUTHORIZATION, mockAccessToken()).build());
|
||||
.from(MockServerHttpRequest.get("/a").header(HttpHeaders.AUTHORIZATION, mockAccessToken()).build());
|
||||
StepVerifier.create(this.interceptor.preHandle(request, "/a"))
|
||||
.consumeErrorWith((ex) -> assertThat(((CloudFoundryAuthorizationException) ex).getReason())
|
||||
.isEqualTo(Reason.SERVICE_UNAVAILABLE))
|
||||
.verify();
|
||||
.consumeErrorWith((ex) -> assertThat(((CloudFoundryAuthorizationException) ex).getReason())
|
||||
.isEqualTo(Reason.SERVICE_UNAVAILABLE))
|
||||
.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
void preHandleWhenAccessIsNotAllowedShouldReturnAccessDenied() {
|
||||
given(this.securityService.getAccessLevel(mockAccessToken(), "my-app-id"))
|
||||
.willReturn(Mono.just(AccessLevel.RESTRICTED));
|
||||
.willReturn(Mono.just(AccessLevel.RESTRICTED));
|
||||
given(this.tokenValidator.validate(any())).willReturn(Mono.empty());
|
||||
MockServerWebExchange request = MockServerWebExchange.from(MockServerHttpRequest.get("/a")
|
||||
.header(HttpHeaders.AUTHORIZATION, "bearer " + mockAccessToken()).build());
|
||||
.header(HttpHeaders.AUTHORIZATION, "bearer " + mockAccessToken())
|
||||
.build());
|
||||
StepVerifier.create(this.interceptor.preHandle(request, "/a"))
|
||||
.consumeNextWith(
|
||||
(response) -> assertThat(response.getStatus()).isEqualTo(Reason.ACCESS_DENIED.getStatus()))
|
||||
.verifyComplete();
|
||||
.consumeNextWith((response) -> assertThat(response.getStatus()).isEqualTo(Reason.ACCESS_DENIED.getStatus()))
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -127,7 +131,8 @@ class ReactiveCloudFoundrySecurityInterceptorTests {
|
||||
given(this.securityService.getAccessLevel(accessToken, "my-app-id")).willReturn(Mono.just(AccessLevel.FULL));
|
||||
given(this.tokenValidator.validate(any())).willReturn(Mono.empty());
|
||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/a")
|
||||
.header(HttpHeaders.AUTHORIZATION, "bearer " + mockAccessToken()).build());
|
||||
.header(HttpHeaders.AUTHORIZATION, "bearer " + mockAccessToken())
|
||||
.build());
|
||||
StepVerifier.create(this.interceptor.preHandle(exchange, "/a")).consumeNextWith((response) -> {
|
||||
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK);
|
||||
assertThat((AccessLevel) exchange.getAttribute("cloudFoundryAccessLevel")).isEqualTo(AccessLevel.FULL);
|
||||
@@ -138,14 +143,15 @@ class ReactiveCloudFoundrySecurityInterceptorTests {
|
||||
void preHandleSuccessfulWithRestrictedAccess() {
|
||||
String accessToken = mockAccessToken();
|
||||
given(this.securityService.getAccessLevel(accessToken, "my-app-id"))
|
||||
.willReturn(Mono.just(AccessLevel.RESTRICTED));
|
||||
.willReturn(Mono.just(AccessLevel.RESTRICTED));
|
||||
given(this.tokenValidator.validate(any())).willReturn(Mono.empty());
|
||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/info")
|
||||
.header(HttpHeaders.AUTHORIZATION, "bearer " + mockAccessToken()).build());
|
||||
.header(HttpHeaders.AUTHORIZATION, "bearer " + mockAccessToken())
|
||||
.build());
|
||||
StepVerifier.create(this.interceptor.preHandle(exchange, "info")).consumeNextWith((response) -> {
|
||||
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK);
|
||||
assertThat((AccessLevel) exchange.getAttribute("cloudFoundryAccessLevel"))
|
||||
.isEqualTo(AccessLevel.RESTRICTED);
|
||||
.isEqualTo(AccessLevel.RESTRICTED);
|
||||
}).verifyComplete();
|
||||
}
|
||||
|
||||
|
||||
@@ -70,8 +70,9 @@ class ReactiveCloudFoundrySecurityServiceTests {
|
||||
String responseBody = "{\"read_sensitive_data\": true,\"read_basic_data\": true}";
|
||||
prepareResponse((response) -> response.setBody(responseBody).setHeader("Content-Type", "application/json"));
|
||||
StepVerifier.create(this.securityService.getAccessLevel("my-access-token", "my-app-id"))
|
||||
.consumeNextWith((accessLevel) -> assertThat(accessLevel).isEqualTo(AccessLevel.FULL)).expectComplete()
|
||||
.verify();
|
||||
.consumeNextWith((accessLevel) -> assertThat(accessLevel).isEqualTo(AccessLevel.FULL))
|
||||
.expectComplete()
|
||||
.verify();
|
||||
expectRequest((request) -> {
|
||||
assertThat(request.getHeader(HttpHeaders.AUTHORIZATION)).isEqualTo("bearer my-access-token");
|
||||
assertThat(request.getPath()).isEqualTo(CLOUD_CONTROLLER_PERMISSIONS);
|
||||
@@ -83,8 +84,9 @@ class ReactiveCloudFoundrySecurityServiceTests {
|
||||
String responseBody = "{\"read_sensitive_data\": false,\"read_basic_data\": true}";
|
||||
prepareResponse((response) -> response.setBody(responseBody).setHeader("Content-Type", "application/json"));
|
||||
StepVerifier.create(this.securityService.getAccessLevel("my-access-token", "my-app-id"))
|
||||
.consumeNextWith((accessLevel) -> assertThat(accessLevel).isEqualTo(AccessLevel.RESTRICTED))
|
||||
.expectComplete().verify();
|
||||
.consumeNextWith((accessLevel) -> assertThat(accessLevel).isEqualTo(AccessLevel.RESTRICTED))
|
||||
.expectComplete()
|
||||
.verify();
|
||||
expectRequest((request) -> {
|
||||
assertThat(request.getHeader(HttpHeaders.AUTHORIZATION)).isEqualTo("bearer my-access-token");
|
||||
assertThat(request.getPath()).isEqualTo(CLOUD_CONTROLLER_PERMISSIONS);
|
||||
@@ -95,11 +97,12 @@ class ReactiveCloudFoundrySecurityServiceTests {
|
||||
void getAccessLevelWhenTokenIsNotValidShouldThrowException() throws Exception {
|
||||
prepareResponse((response) -> response.setResponseCode(401));
|
||||
StepVerifier.create(this.securityService.getAccessLevel("my-access-token", "my-app-id"))
|
||||
.consumeErrorWith((throwable) -> {
|
||||
assertThat(throwable).isInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) throwable).getReason())
|
||||
.isEqualTo(Reason.INVALID_TOKEN);
|
||||
}).verify();
|
||||
.consumeErrorWith((throwable) -> {
|
||||
assertThat(throwable).isInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) throwable).getReason())
|
||||
.isEqualTo(Reason.INVALID_TOKEN);
|
||||
})
|
||||
.verify();
|
||||
expectRequest((request) -> {
|
||||
assertThat(request.getHeader(HttpHeaders.AUTHORIZATION)).isEqualTo("bearer my-access-token");
|
||||
assertThat(request.getPath()).isEqualTo(CLOUD_CONTROLLER_PERMISSIONS);
|
||||
@@ -110,11 +113,12 @@ class ReactiveCloudFoundrySecurityServiceTests {
|
||||
void getAccessLevelWhenForbiddenShouldThrowException() throws Exception {
|
||||
prepareResponse((response) -> response.setResponseCode(403));
|
||||
StepVerifier.create(this.securityService.getAccessLevel("my-access-token", "my-app-id"))
|
||||
.consumeErrorWith((throwable) -> {
|
||||
assertThat(throwable).isInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) throwable).getReason())
|
||||
.isEqualTo(Reason.ACCESS_DENIED);
|
||||
}).verify();
|
||||
.consumeErrorWith((throwable) -> {
|
||||
assertThat(throwable).isInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) throwable).getReason())
|
||||
.isEqualTo(Reason.ACCESS_DENIED);
|
||||
})
|
||||
.verify();
|
||||
expectRequest((request) -> {
|
||||
assertThat(request.getHeader(HttpHeaders.AUTHORIZATION)).isEqualTo("bearer my-access-token");
|
||||
assertThat(request.getPath()).isEqualTo(CLOUD_CONTROLLER_PERMISSIONS);
|
||||
@@ -125,11 +129,12 @@ class ReactiveCloudFoundrySecurityServiceTests {
|
||||
void getAccessLevelWhenCloudControllerIsNotReachableThrowsException() throws Exception {
|
||||
prepareResponse((response) -> response.setResponseCode(500));
|
||||
StepVerifier.create(this.securityService.getAccessLevel("my-access-token", "my-app-id"))
|
||||
.consumeErrorWith((throwable) -> {
|
||||
assertThat(throwable).isInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) throwable).getReason())
|
||||
.isEqualTo(Reason.SERVICE_UNAVAILABLE);
|
||||
}).verify();
|
||||
.consumeErrorWith((throwable) -> {
|
||||
assertThat(throwable).isInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) throwable).getReason())
|
||||
.isEqualTo(Reason.SERVICE_UNAVAILABLE);
|
||||
})
|
||||
.verify();
|
||||
expectRequest((request) -> {
|
||||
assertThat(request.getHeader(HttpHeaders.AUTHORIZATION)).isEqualTo("bearer my-access-token");
|
||||
assertThat(request.getPath()).isEqualTo(CLOUD_CONTROLLER_PERMISSIONS);
|
||||
@@ -159,8 +164,9 @@ class ReactiveCloudFoundrySecurityServiceTests {
|
||||
response.setHeader("Content-Type", "application/json");
|
||||
});
|
||||
StepVerifier.create(this.securityService.fetchTokenKeys())
|
||||
.consumeNextWith((tokenKeys) -> assertThat(tokenKeys.get("test-key")).isEqualTo(tokenKeyValue))
|
||||
.expectComplete().verify();
|
||||
.consumeNextWith((tokenKeys) -> assertThat(tokenKeys.get("test-key")).isEqualTo(tokenKeyValue))
|
||||
.expectComplete()
|
||||
.verify();
|
||||
expectRequest((request) -> assertThat(request.getPath()).isEqualTo("/my-cloud-controller.com/info"));
|
||||
expectRequest((request) -> assertThat(request.getPath()).isEqualTo("/my-uaa.com/token_keys"));
|
||||
}
|
||||
@@ -177,7 +183,9 @@ class ReactiveCloudFoundrySecurityServiceTests {
|
||||
response.setHeader("Content-Type", "application/json");
|
||||
});
|
||||
StepVerifier.create(this.securityService.fetchTokenKeys())
|
||||
.consumeNextWith((tokenKeys) -> assertThat(tokenKeys).hasSize(0)).expectComplete().verify();
|
||||
.consumeNextWith((tokenKeys) -> assertThat(tokenKeys).hasSize(0))
|
||||
.expectComplete()
|
||||
.verify();
|
||||
expectRequest((request) -> assertThat(request.getPath()).isEqualTo("/my-cloud-controller.com/info"));
|
||||
expectRequest((request) -> assertThat(request.getPath()).isEqualTo("/my-uaa.com/token_keys"));
|
||||
}
|
||||
@@ -190,10 +198,9 @@ class ReactiveCloudFoundrySecurityServiceTests {
|
||||
});
|
||||
prepareResponse((response) -> response.setResponseCode(500));
|
||||
StepVerifier.create(this.securityService.fetchTokenKeys())
|
||||
.consumeErrorWith(
|
||||
(throwable) -> assertThat(((CloudFoundryAuthorizationException) throwable).getReason())
|
||||
.isEqualTo(Reason.SERVICE_UNAVAILABLE))
|
||||
.verify();
|
||||
.consumeErrorWith((throwable) -> assertThat(((CloudFoundryAuthorizationException) throwable).getReason())
|
||||
.isEqualTo(Reason.SERVICE_UNAVAILABLE))
|
||||
.verify();
|
||||
expectRequest((request) -> assertThat(request.getPath()).isEqualTo("/my-cloud-controller.com/info"));
|
||||
expectRequest((request) -> assertThat(request.getPath()).isEqualTo("/my-uaa.com/token_keys"));
|
||||
}
|
||||
@@ -205,7 +212,9 @@ class ReactiveCloudFoundrySecurityServiceTests {
|
||||
response.setHeader("Content-Type", "application/json");
|
||||
});
|
||||
StepVerifier.create(this.securityService.getUaaUrl())
|
||||
.consumeNextWith((uaaUrl) -> assertThat(uaaUrl).isEqualTo(UAA_URL)).expectComplete().verify();
|
||||
.consumeNextWith((uaaUrl) -> assertThat(uaaUrl).isEqualTo(UAA_URL))
|
||||
.expectComplete()
|
||||
.verify();
|
||||
expectRequest((request) -> assertThat(request.getPath()).isEqualTo(CLOUD_CONTROLLER + "/info"));
|
||||
expectRequestCount(1);
|
||||
}
|
||||
@@ -216,7 +225,7 @@ class ReactiveCloudFoundrySecurityServiceTests {
|
||||
StepVerifier.create(this.securityService.getUaaUrl()).consumeErrorWith((throwable) -> {
|
||||
assertThat(throwable).isInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) throwable).getReason())
|
||||
.isEqualTo(Reason.SERVICE_UNAVAILABLE);
|
||||
.isEqualTo(Reason.SERVICE_UNAVAILABLE);
|
||||
}).verify();
|
||||
expectRequest((request) -> assertThat(request.getPath()).isEqualTo(CLOUD_CONTROLLER + "/info"));
|
||||
}
|
||||
|
||||
@@ -105,11 +105,12 @@ class ReactiveTokenValidatorTests {
|
||||
String header = "{\"alg\": \"RS256\", \"kid\": \"invalid-key\",\"typ\": \"JWT\"}";
|
||||
String claims = "{\"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
|
||||
StepVerifier
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.consumeErrorWith((ex) -> {
|
||||
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) ex).getReason()).isEqualTo(Reason.INVALID_KEY_ID);
|
||||
}).verify();
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.consumeErrorWith((ex) -> {
|
||||
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) ex).getReason()).isEqualTo(Reason.INVALID_KEY_ID);
|
||||
})
|
||||
.verify();
|
||||
assertThat(this.tokenValidator).hasFieldOrPropertyWithValue("cachedTokenKeys", VALID_KEYS);
|
||||
fetchTokenKeys.assertWasSubscribed();
|
||||
}
|
||||
@@ -123,8 +124,8 @@ class ReactiveTokenValidatorTests {
|
||||
String header = "{\"alg\": \"RS256\", \"kid\": \"valid-key\",\"typ\": \"JWT\"}";
|
||||
String claims = "{\"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
|
||||
StepVerifier
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.verifyComplete();
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.verifyComplete();
|
||||
assertThat(this.tokenValidator).hasFieldOrPropertyWithValue("cachedTokenKeys", VALID_KEYS);
|
||||
fetchTokenKeys.assertWasSubscribed();
|
||||
}
|
||||
@@ -137,8 +138,8 @@ class ReactiveTokenValidatorTests {
|
||||
String header = "{\"alg\": \"RS256\", \"kid\": \"valid-key\",\"typ\": \"JWT\"}";
|
||||
String claims = "{\"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
|
||||
StepVerifier
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.verifyComplete();
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.verifyComplete();
|
||||
assertThat(this.tokenValidator).hasFieldOrPropertyWithValue("cachedTokenKeys", VALID_KEYS);
|
||||
fetchTokenKeys.assertWasSubscribed();
|
||||
}
|
||||
@@ -151,11 +152,12 @@ class ReactiveTokenValidatorTests {
|
||||
String header = "{\"alg\": \"RS256\", \"kid\": \"invalid-key\",\"typ\": \"JWT\"}";
|
||||
String claims = "{\"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
|
||||
StepVerifier
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.consumeErrorWith((ex) -> {
|
||||
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) ex).getReason()).isEqualTo(Reason.INVALID_KEY_ID);
|
||||
}).verify();
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.consumeErrorWith((ex) -> {
|
||||
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) ex).getReason()).isEqualTo(Reason.INVALID_KEY_ID);
|
||||
})
|
||||
.verify();
|
||||
assertThat(this.tokenValidator).hasFieldOrPropertyWithValue("cachedTokenKeys", VALID_KEYS);
|
||||
fetchTokenKeys.assertWasSubscribed();
|
||||
}
|
||||
@@ -168,8 +170,8 @@ class ReactiveTokenValidatorTests {
|
||||
String header = "{\"alg\": \"RS256\", \"kid\": \"valid-key\",\"typ\": \"JWT\"}";
|
||||
String claims = "{\"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
|
||||
StepVerifier
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.verifyComplete();
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.verifyComplete();
|
||||
fetchTokenKeys.assertWasNotSubscribed();
|
||||
}
|
||||
|
||||
@@ -181,12 +183,12 @@ class ReactiveTokenValidatorTests {
|
||||
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\",\"typ\": \"JWT\"}";
|
||||
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
|
||||
StepVerifier
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.consumeErrorWith((ex) -> {
|
||||
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) ex).getReason())
|
||||
.isEqualTo(Reason.INVALID_SIGNATURE);
|
||||
}).verify();
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.consumeErrorWith((ex) -> {
|
||||
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) ex).getReason()).isEqualTo(Reason.INVALID_SIGNATURE);
|
||||
})
|
||||
.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -196,12 +198,13 @@ class ReactiveTokenValidatorTests {
|
||||
String header = "{ \"alg\": \"HS256\", \"kid\": \"valid-key\", \"typ\": \"JWT\"}";
|
||||
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
|
||||
StepVerifier
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.consumeErrorWith((ex) -> {
|
||||
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) ex).getReason())
|
||||
.isEqualTo(Reason.UNSUPPORTED_TOKEN_SIGNING_ALGORITHM);
|
||||
}).verify();
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.consumeErrorWith((ex) -> {
|
||||
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) ex).getReason())
|
||||
.isEqualTo(Reason.UNSUPPORTED_TOKEN_SIGNING_ALGORITHM);
|
||||
})
|
||||
.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -211,11 +214,12 @@ class ReactiveTokenValidatorTests {
|
||||
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\", \"typ\": \"JWT\"}";
|
||||
String claims = "{ \"jti\": \"0236399c350c47f3ae77e67a75e75e7d\", \"exp\": 1477509977, \"scope\": [\"actuator.read\"]}";
|
||||
StepVerifier
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.consumeErrorWith((ex) -> {
|
||||
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) ex).getReason()).isEqualTo(Reason.TOKEN_EXPIRED);
|
||||
}).verify();
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.consumeErrorWith((ex) -> {
|
||||
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) ex).getReason()).isEqualTo(Reason.TOKEN_EXPIRED);
|
||||
})
|
||||
.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -225,11 +229,12 @@ class ReactiveTokenValidatorTests {
|
||||
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\", \"typ\": \"JWT\", \"scope\": [\"actuator.read\"]}";
|
||||
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"foo.bar\"]}";
|
||||
StepVerifier
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.consumeErrorWith((ex) -> {
|
||||
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) ex).getReason()).isEqualTo(Reason.INVALID_ISSUER);
|
||||
}).verify();
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.consumeErrorWith((ex) -> {
|
||||
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) ex).getReason()).isEqualTo(Reason.INVALID_ISSUER);
|
||||
})
|
||||
.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -239,12 +244,12 @@ class ReactiveTokenValidatorTests {
|
||||
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\", \"typ\": \"JWT\"}";
|
||||
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"foo.bar\"]}";
|
||||
StepVerifier
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.consumeErrorWith((ex) -> {
|
||||
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) ex).getReason())
|
||||
.isEqualTo(Reason.INVALID_AUDIENCE);
|
||||
}).verify();
|
||||
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.consumeErrorWith((ex) -> {
|
||||
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
|
||||
assertThat(((CloudFoundryAuthorizationException) ex).getReason()).isEqualTo(Reason.INVALID_AUDIENCE);
|
||||
})
|
||||
.verify();
|
||||
}
|
||||
|
||||
private String getSignedToken(byte[] header, byte[] claims) throws Exception {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -70,172 +70,183 @@ class CloudFoundryActuatorAutoConfigurationTests {
|
||||
private static final String V3_JSON = ApiVersion.V3.getProducedMimeType().toString();
|
||||
|
||||
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(SecurityAutoConfiguration.class, WebMvcAutoConfiguration.class,
|
||||
JacksonAutoConfiguration.class, DispatcherServletAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
|
||||
RestTemplateAutoConfiguration.class, ManagementContextAutoConfiguration.class,
|
||||
ServletManagementContextAutoConfiguration.class, EndpointAutoConfiguration.class,
|
||||
WebEndpointAutoConfiguration.class, CloudFoundryActuatorAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(SecurityAutoConfiguration.class, WebMvcAutoConfiguration.class,
|
||||
JacksonAutoConfiguration.class, DispatcherServletAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
|
||||
RestTemplateAutoConfiguration.class, ManagementContextAutoConfiguration.class,
|
||||
ServletManagementContextAutoConfiguration.class, EndpointAutoConfiguration.class,
|
||||
WebEndpointAutoConfiguration.class, CloudFoundryActuatorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void cloudFoundryPlatformActive() {
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
EndpointMapping endpointMapping = (EndpointMapping) ReflectionTestUtils.getField(handlerMapping,
|
||||
"endpointMapping");
|
||||
assertThat(endpointMapping.getPath()).isEqualTo("/cloudfoundryapplication");
|
||||
CorsConfiguration corsConfiguration = (CorsConfiguration) ReflectionTestUtils
|
||||
.getField(handlerMapping, "corsConfiguration");
|
||||
assertThat(corsConfiguration.getAllowedOrigins()).contains("*");
|
||||
assertThat(corsConfiguration.getAllowedMethods())
|
||||
.containsAll(Arrays.asList(HttpMethod.GET.name(), HttpMethod.POST.name()));
|
||||
assertThat(corsConfiguration.getAllowedHeaders())
|
||||
.containsAll(Arrays.asList("Authorization", "X-Cf-App-Instance", "Content-Type"));
|
||||
});
|
||||
this.contextRunner
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
EndpointMapping endpointMapping = (EndpointMapping) ReflectionTestUtils.getField(handlerMapping,
|
||||
"endpointMapping");
|
||||
assertThat(endpointMapping.getPath()).isEqualTo("/cloudfoundryapplication");
|
||||
CorsConfiguration corsConfiguration = (CorsConfiguration) ReflectionTestUtils.getField(handlerMapping,
|
||||
"corsConfiguration");
|
||||
assertThat(corsConfiguration.getAllowedOrigins()).contains("*");
|
||||
assertThat(corsConfiguration.getAllowedMethods())
|
||||
.containsAll(Arrays.asList(HttpMethod.GET.name(), HttpMethod.POST.name()));
|
||||
assertThat(corsConfiguration.getAllowedHeaders())
|
||||
.containsAll(Arrays.asList("Authorization", "X-Cf-App-Instance", "Content-Type"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void cloudfoundryapplicationProducesActuatorMediaType() {
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
|
||||
mockMvc.perform(get("/cloudfoundryapplication"))
|
||||
.andExpect(header().string("Content-Type", V3_JSON));
|
||||
});
|
||||
this.contextRunner
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
|
||||
mockMvc.perform(get("/cloudfoundryapplication")).andExpect(header().string("Content-Type", V3_JSON));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void cloudFoundryPlatformActiveSetsApplicationId() {
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
|
||||
String applicationId = (String) ReflectionTestUtils.getField(interceptor, "applicationId");
|
||||
assertThat(applicationId).isEqualTo("my-app-id");
|
||||
});
|
||||
this.contextRunner
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
|
||||
String applicationId = (String) ReflectionTestUtils.getField(interceptor, "applicationId");
|
||||
assertThat(applicationId).isEqualTo("my-app-id");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void cloudFoundryPlatformActiveSetsCloudControllerUrl() {
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor,
|
||||
"cloudFoundrySecurityService");
|
||||
String cloudControllerUrl = (String) ReflectionTestUtils.getField(interceptorSecurityService,
|
||||
"cloudControllerUrl");
|
||||
assertThat(cloudControllerUrl).isEqualTo("https://my-cloud-controller.com");
|
||||
});
|
||||
this.contextRunner
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor,
|
||||
"cloudFoundrySecurityService");
|
||||
String cloudControllerUrl = (String) ReflectionTestUtils.getField(interceptorSecurityService,
|
||||
"cloudControllerUrl");
|
||||
assertThat(cloudControllerUrl).isEqualTo("https://my-cloud-controller.com");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void skipSslValidation() {
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com",
|
||||
"management.cloudfoundry.skip-ssl-validation:true").run((context) -> {
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor,
|
||||
"cloudFoundrySecurityService");
|
||||
RestTemplate restTemplate = (RestTemplate) ReflectionTestUtils.getField(interceptorSecurityService,
|
||||
"restTemplate");
|
||||
assertThat(restTemplate.getRequestFactory())
|
||||
.isInstanceOf(SkipSslVerificationHttpRequestFactory.class);
|
||||
});
|
||||
this.contextRunner
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com",
|
||||
"management.cloudfoundry.skip-ssl-validation:true")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor,
|
||||
"cloudFoundrySecurityService");
|
||||
RestTemplate restTemplate = (RestTemplate) ReflectionTestUtils.getField(interceptorSecurityService,
|
||||
"restTemplate");
|
||||
assertThat(restTemplate.getRequestFactory()).isInstanceOf(SkipSslVerificationHttpRequestFactory.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void cloudFoundryPlatformActiveAndCloudControllerUrlNotPresent() {
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Object securityInterceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils.getField(securityInterceptor,
|
||||
"cloudFoundrySecurityService");
|
||||
assertThat(interceptorSecurityService).isNull();
|
||||
});
|
||||
.run((context) -> {
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Object securityInterceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
|
||||
Object interceptorSecurityService = ReflectionTestUtils.getField(securityInterceptor,
|
||||
"cloudFoundrySecurityService");
|
||||
assertThat(interceptorSecurityService).isNull();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void cloudFoundryPathsIgnoredBySpringSecurity() {
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id")
|
||||
.run((context) -> {
|
||||
FilterChainProxy securityFilterChain = (FilterChainProxy) context
|
||||
.getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN);
|
||||
SecurityFilterChain chain = securityFilterChain.getFilterChains().get(0);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setServletPath("/cloudfoundryapplication/my-path");
|
||||
assertThat(chain.getFilters()).isEmpty();
|
||||
assertThat(chain.matches(request)).isTrue();
|
||||
request.setServletPath("/some-other-path");
|
||||
assertThat(chain.matches(request)).isFalse();
|
||||
});
|
||||
.run((context) -> {
|
||||
FilterChainProxy securityFilterChain = (FilterChainProxy) context
|
||||
.getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN);
|
||||
SecurityFilterChain chain = securityFilterChain.getFilterChains().get(0);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setServletPath("/cloudfoundryapplication/my-path");
|
||||
assertThat(chain.getFilters()).isEmpty();
|
||||
assertThat(chain.matches(request)).isTrue();
|
||||
request.setServletPath("/some-other-path");
|
||||
assertThat(chain.matches(request)).isFalse();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void cloudFoundryPlatformInactive() {
|
||||
this.contextRunner.withPropertyValues()
|
||||
.run((context) -> assertThat(context.containsBean("cloudFoundryWebEndpointServletHandlerMapping"))
|
||||
.isFalse());
|
||||
.run((context) -> assertThat(context.containsBean("cloudFoundryWebEndpointServletHandlerMapping"))
|
||||
.isFalse());
|
||||
}
|
||||
|
||||
@Test
|
||||
void cloudFoundryManagementEndpointsDisabled() {
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION=---", "management.cloudfoundry.enabled:false")
|
||||
.run((context) -> assertThat(context.containsBean("cloudFoundryEndpointHandlerMapping")).isFalse());
|
||||
.run((context) -> assertThat(context.containsBean("cloudFoundryEndpointHandlerMapping")).isFalse());
|
||||
}
|
||||
|
||||
@Test
|
||||
void allEndpointsAvailableUnderCloudFoundryWithoutExposeAllOnWeb() {
|
||||
this.contextRunner.withBean(TestEndpoint.class, TestEndpoint::new).withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id", "vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Collection<ExposableWebEndpoint> endpoints = handlerMapping.getEndpoints();
|
||||
assertThat(endpoints.stream()
|
||||
.filter((candidate) -> EndpointId.of("test").equals(candidate.getEndpointId())).findFirst())
|
||||
.isNotEmpty();
|
||||
});
|
||||
this.contextRunner.withBean(TestEndpoint.class, TestEndpoint::new)
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Collection<ExposableWebEndpoint> endpoints = handlerMapping.getEndpoints();
|
||||
assertThat(endpoints.stream()
|
||||
.filter((candidate) -> EndpointId.of("test").equals(candidate.getEndpointId()))
|
||||
.findFirst()).isNotEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void endpointPathCustomizationIsNotApplied() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com",
|
||||
"management.endpoints.web.path-mapping.test=custom")
|
||||
.withBean(TestEndpoint.class, TestEndpoint::new).run((context) -> {
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Collection<ExposableWebEndpoint> endpoints = handlerMapping.getEndpoints();
|
||||
ExposableWebEndpoint endpoint = endpoints.stream()
|
||||
.filter((candidate) -> EndpointId.of("test").equals(candidate.getEndpointId())).findFirst()
|
||||
.get();
|
||||
Collection<WebOperation> operations = endpoint.getOperations();
|
||||
assertThat(operations).hasSize(1);
|
||||
assertThat(operations.iterator().next().getRequestPredicate().getPath()).isEqualTo("test");
|
||||
});
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com",
|
||||
"management.endpoints.web.path-mapping.test=custom")
|
||||
.withBean(TestEndpoint.class, TestEndpoint::new)
|
||||
.run((context) -> {
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
|
||||
Collection<ExposableWebEndpoint> endpoints = handlerMapping.getEndpoints();
|
||||
ExposableWebEndpoint endpoint = endpoints.stream()
|
||||
.filter((candidate) -> EndpointId.of("test").equals(candidate.getEndpointId()))
|
||||
.findFirst()
|
||||
.get();
|
||||
Collection<WebOperation> operations = endpoint.getOperations();
|
||||
assertThat(operations).hasSize(1);
|
||||
assertThat(operations.iterator().next().getRequestPredicate().getPath()).isEqualTo("test");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void healthEndpointInvokerShouldBeCloudFoundryWebExtension() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.withConfiguration(AutoConfigurations.of(HealthContributorAutoConfiguration.class,
|
||||
HealthEndpointAutoConfiguration.class))
|
||||
.run((context) -> {
|
||||
Collection<ExposableWebEndpoint> endpoints = context
|
||||
.getBean("cloudFoundryWebEndpointServletHandlerMapping",
|
||||
CloudFoundryWebEndpointServletHandlerMapping.class)
|
||||
.getEndpoints();
|
||||
ExposableWebEndpoint endpoint = endpoints.iterator().next();
|
||||
assertThat(endpoint.getOperations()).hasSize(2);
|
||||
WebOperation webOperation = findOperationWithRequestPath(endpoint, "health");
|
||||
assertThat(webOperation).extracting("invoker.target")
|
||||
.isInstanceOf(CloudFoundryHealthEndpointWebExtension.class);
|
||||
});
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.withConfiguration(AutoConfigurations.of(HealthContributorAutoConfiguration.class,
|
||||
HealthEndpointAutoConfiguration.class))
|
||||
.run((context) -> {
|
||||
Collection<ExposableWebEndpoint> endpoints = context
|
||||
.getBean("cloudFoundryWebEndpointServletHandlerMapping",
|
||||
CloudFoundryWebEndpointServletHandlerMapping.class)
|
||||
.getEndpoints();
|
||||
ExposableWebEndpoint endpoint = endpoints.iterator().next();
|
||||
assertThat(endpoint.getOperations()).hasSize(2);
|
||||
WebOperation webOperation = findOperationWithRequestPath(endpoint, "health");
|
||||
assertThat(webOperation).extracting("invoker.target")
|
||||
.isInstanceOf(CloudFoundryHealthEndpointWebExtension.class);
|
||||
});
|
||||
}
|
||||
|
||||
private CloudFoundryWebEndpointServletHandlerMapping getHandlerMapping(ApplicationContext context) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -49,21 +49,21 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class CloudFoundryHealthEndpointWebExtensionTests {
|
||||
|
||||
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
|
||||
.withPropertyValues("VCAP_APPLICATION={}")
|
||||
.withConfiguration(AutoConfigurations.of(SecurityAutoConfiguration.class, WebMvcAutoConfiguration.class,
|
||||
JacksonAutoConfiguration.class, DispatcherServletAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
|
||||
RestTemplateAutoConfiguration.class, ManagementContextAutoConfiguration.class,
|
||||
ServletManagementContextAutoConfiguration.class, EndpointAutoConfiguration.class,
|
||||
WebEndpointAutoConfiguration.class, HealthContributorAutoConfiguration.class,
|
||||
HealthEndpointAutoConfiguration.class, CloudFoundryActuatorAutoConfiguration.class))
|
||||
.withUserConfiguration(TestHealthIndicator.class);
|
||||
.withPropertyValues("VCAP_APPLICATION={}")
|
||||
.withConfiguration(AutoConfigurations.of(SecurityAutoConfiguration.class, WebMvcAutoConfiguration.class,
|
||||
JacksonAutoConfiguration.class, DispatcherServletAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
|
||||
RestTemplateAutoConfiguration.class, ManagementContextAutoConfiguration.class,
|
||||
ServletManagementContextAutoConfiguration.class, EndpointAutoConfiguration.class,
|
||||
WebEndpointAutoConfiguration.class, HealthContributorAutoConfiguration.class,
|
||||
HealthEndpointAutoConfiguration.class, CloudFoundryActuatorAutoConfiguration.class))
|
||||
.withUserConfiguration(TestHealthIndicator.class);
|
||||
|
||||
@Test
|
||||
void healthComponentsAlwaysPresent() {
|
||||
this.contextRunner.run((context) -> {
|
||||
CloudFoundryHealthEndpointWebExtension extension = context
|
||||
.getBean(CloudFoundryHealthEndpointWebExtension.class);
|
||||
.getBean(CloudFoundryHealthEndpointWebExtension.class);
|
||||
HealthComponent body = extension.health(ApiVersion.V3).getBody();
|
||||
HealthComponent health = ((CompositeHealth) body).getComponents().entrySet().iterator().next().getValue();
|
||||
assertThat(((Health) health).getDetails()).containsEntry("spring", "boot");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -48,22 +48,22 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class CloudFoundryInfoEndpointWebExtensionTests {
|
||||
|
||||
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
|
||||
.withPropertyValues("VCAP_APPLICATION={}")
|
||||
.withConfiguration(AutoConfigurations.of(SecurityAutoConfiguration.class, WebMvcAutoConfiguration.class,
|
||||
JacksonAutoConfiguration.class, DispatcherServletAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
|
||||
RestTemplateAutoConfiguration.class, ManagementContextAutoConfiguration.class,
|
||||
ServletManagementContextAutoConfiguration.class, EndpointAutoConfiguration.class,
|
||||
WebEndpointAutoConfiguration.class, ProjectInfoAutoConfiguration.class,
|
||||
InfoContributorAutoConfiguration.class, InfoEndpointAutoConfiguration.class,
|
||||
HealthEndpointAutoConfiguration.class, CloudFoundryActuatorAutoConfiguration.class));
|
||||
.withPropertyValues("VCAP_APPLICATION={}")
|
||||
.withConfiguration(AutoConfigurations.of(SecurityAutoConfiguration.class, WebMvcAutoConfiguration.class,
|
||||
JacksonAutoConfiguration.class, DispatcherServletAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
|
||||
RestTemplateAutoConfiguration.class, ManagementContextAutoConfiguration.class,
|
||||
ServletManagementContextAutoConfiguration.class, EndpointAutoConfiguration.class,
|
||||
WebEndpointAutoConfiguration.class, ProjectInfoAutoConfiguration.class,
|
||||
InfoContributorAutoConfiguration.class, InfoEndpointAutoConfiguration.class,
|
||||
HealthEndpointAutoConfiguration.class, CloudFoundryActuatorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void gitFullDetailsAlwaysPresent() {
|
||||
this.contextRunner.run((context) -> {
|
||||
CloudFoundryInfoEndpointWebExtension extension = context
|
||||
.getBean(CloudFoundryInfoEndpointWebExtension.class);
|
||||
.getBean(CloudFoundryInfoEndpointWebExtension.class);
|
||||
Map<String, Object> git = (Map<String, Object>) extension.info().get("git");
|
||||
Map<String, Object> commit = (Map<String, Object>) git.get("commit");
|
||||
assertThat(commit).hasSize(4);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -74,42 +74,79 @@ class CloudFoundryMvcWebEndpointIntegrationTests {
|
||||
void operationWithSecurityInterceptorForbidden() {
|
||||
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(AccessLevel.RESTRICTED);
|
||||
load(TestEndpointConfiguration.class,
|
||||
(client) -> client.get().uri("/cfApplication/test").accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken()).exchange().expectStatus()
|
||||
.isEqualTo(HttpStatus.FORBIDDEN));
|
||||
(client) -> client.get()
|
||||
.uri("/cfApplication/test")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken())
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isEqualTo(HttpStatus.FORBIDDEN));
|
||||
}
|
||||
|
||||
@Test
|
||||
void operationWithSecurityInterceptorSuccess() {
|
||||
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(AccessLevel.FULL);
|
||||
load(TestEndpointConfiguration.class,
|
||||
(client) -> client.get().uri("/cfApplication/test").accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken()).exchange().expectStatus()
|
||||
.isEqualTo(HttpStatus.OK));
|
||||
(client) -> client.get()
|
||||
.uri("/cfApplication/test")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken())
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isEqualTo(HttpStatus.OK));
|
||||
}
|
||||
|
||||
@Test
|
||||
void responseToOptionsRequestIncludesCorsHeaders() {
|
||||
load(TestEndpointConfiguration.class,
|
||||
(client) -> client.options().uri("/cfApplication/test").accept(MediaType.APPLICATION_JSON)
|
||||
.header("Access-Control-Request-Method", "POST").header("Origin", "https://example.com")
|
||||
.exchange().expectStatus().isOk().expectHeader()
|
||||
.valueEquals("Access-Control-Allow-Origin", "https://example.com").expectHeader()
|
||||
.valueEquals("Access-Control-Allow-Methods", "GET,POST"));
|
||||
(client) -> client.options()
|
||||
.uri("/cfApplication/test")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.header("Access-Control-Request-Method", "POST")
|
||||
.header("Origin", "https://example.com")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectHeader()
|
||||
.valueEquals("Access-Control-Allow-Origin", "https://example.com")
|
||||
.expectHeader()
|
||||
.valueEquals("Access-Control-Allow-Methods", "GET,POST"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void linksToOtherEndpointsWithFullAccess() {
|
||||
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(AccessLevel.FULL);
|
||||
load(TestEndpointConfiguration.class,
|
||||
(client) -> client.get().uri("/cfApplication").accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken()).exchange().expectStatus().isOk()
|
||||
.expectBody().jsonPath("_links.length()").isEqualTo(5).jsonPath("_links.self.href").isNotEmpty()
|
||||
.jsonPath("_links.self.templated").isEqualTo(false).jsonPath("_links.info.href").isNotEmpty()
|
||||
.jsonPath("_links.info.templated").isEqualTo(false).jsonPath("_links.env.href").isNotEmpty()
|
||||
.jsonPath("_links.env.templated").isEqualTo(false).jsonPath("_links.test.href").isNotEmpty()
|
||||
.jsonPath("_links.test.templated").isEqualTo(false).jsonPath("_links.test-part.href")
|
||||
.isNotEmpty().jsonPath("_links.test-part.templated").isEqualTo(true));
|
||||
(client) -> client.get()
|
||||
.uri("/cfApplication")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken())
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody()
|
||||
.jsonPath("_links.length()")
|
||||
.isEqualTo(5)
|
||||
.jsonPath("_links.self.href")
|
||||
.isNotEmpty()
|
||||
.jsonPath("_links.self.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.info.href")
|
||||
.isNotEmpty()
|
||||
.jsonPath("_links.info.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.env.href")
|
||||
.isNotEmpty()
|
||||
.jsonPath("_links.env.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.test.href")
|
||||
.isNotEmpty()
|
||||
.jsonPath("_links.test.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.test-part.href")
|
||||
.isNotEmpty()
|
||||
.jsonPath("_links.test-part.templated")
|
||||
.isEqualTo(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -118,21 +155,43 @@ class CloudFoundryMvcWebEndpointIntegrationTests {
|
||||
"invalid-token");
|
||||
willThrow(exception).given(tokenValidator).validate(any());
|
||||
load(TestEndpointConfiguration.class,
|
||||
(client) -> client.get().uri("/cfApplication").accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken()).exchange().expectStatus()
|
||||
.isUnauthorized());
|
||||
(client) -> client.get()
|
||||
.uri("/cfApplication")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken())
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isUnauthorized());
|
||||
}
|
||||
|
||||
@Test
|
||||
void linksToOtherEndpointsWithRestrictedAccess() {
|
||||
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(AccessLevel.RESTRICTED);
|
||||
load(TestEndpointConfiguration.class,
|
||||
(client) -> client.get().uri("/cfApplication").accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken()).exchange().expectStatus().isOk()
|
||||
.expectBody().jsonPath("_links.length()").isEqualTo(2).jsonPath("_links.self.href").isNotEmpty()
|
||||
.jsonPath("_links.self.templated").isEqualTo(false).jsonPath("_links.info.href").isNotEmpty()
|
||||
.jsonPath("_links.info.templated").isEqualTo(false).jsonPath("_links.env").doesNotExist()
|
||||
.jsonPath("_links.test").doesNotExist().jsonPath("_links.test-part").doesNotExist());
|
||||
(client) -> client.get()
|
||||
.uri("/cfApplication")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "bearer " + mockAccessToken())
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isOk()
|
||||
.expectBody()
|
||||
.jsonPath("_links.length()")
|
||||
.isEqualTo(2)
|
||||
.jsonPath("_links.self.href")
|
||||
.isNotEmpty()
|
||||
.jsonPath("_links.self.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.info.href")
|
||||
.isNotEmpty()
|
||||
.jsonPath("_links.info.templated")
|
||||
.isEqualTo(false)
|
||||
.jsonPath("_links.env")
|
||||
.doesNotExist()
|
||||
.jsonPath("_links.test")
|
||||
.doesNotExist()
|
||||
.jsonPath("_links.test-part")
|
||||
.doesNotExist());
|
||||
}
|
||||
|
||||
private AnnotationConfigServletWebServerApplicationContext createApplicationContext(Class<?>... config) {
|
||||
@@ -147,8 +206,11 @@ class CloudFoundryMvcWebEndpointIntegrationTests {
|
||||
BiConsumer<ApplicationContext, WebTestClient> consumer = (context, client) -> clientConsumer.accept(client);
|
||||
try (AnnotationConfigServletWebServerApplicationContext context = createApplicationContext(configuration,
|
||||
CloudFoundryMvcConfiguration.class)) {
|
||||
consumer.accept(context, WebTestClient.bindToServer().baseUrl("http://localhost:" + getPort(context))
|
||||
.responseTimeout(Duration.ofMinutes(5)).build());
|
||||
consumer.accept(context,
|
||||
WebTestClient.bindToServer()
|
||||
.baseUrl("http://localhost:" + getPort(context))
|
||||
.responseTimeout(Duration.ofMinutes(5))
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -87,8 +87,8 @@ class CloudFoundrySecurityServiceTests {
|
||||
void getAccessLevelWhenSpaceDeveloperShouldReturnFull() {
|
||||
String responseBody = "{\"read_sensitive_data\": true,\"read_basic_data\": true}";
|
||||
this.server.expect(requestTo(CLOUD_CONTROLLER_PERMISSIONS))
|
||||
.andExpect(header("Authorization", "bearer my-access-token"))
|
||||
.andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON));
|
||||
.andExpect(header("Authorization", "bearer my-access-token"))
|
||||
.andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON));
|
||||
AccessLevel accessLevel = this.securityService.getAccessLevel("my-access-token", "my-app-id");
|
||||
this.server.verify();
|
||||
assertThat(accessLevel).isEqualTo(AccessLevel.FULL);
|
||||
@@ -98,8 +98,8 @@ class CloudFoundrySecurityServiceTests {
|
||||
void getAccessLevelWhenNotSpaceDeveloperShouldReturnRestricted() {
|
||||
String responseBody = "{\"read_sensitive_data\": false,\"read_basic_data\": true}";
|
||||
this.server.expect(requestTo(CLOUD_CONTROLLER_PERMISSIONS))
|
||||
.andExpect(header("Authorization", "bearer my-access-token"))
|
||||
.andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON));
|
||||
.andExpect(header("Authorization", "bearer my-access-token"))
|
||||
.andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON));
|
||||
AccessLevel accessLevel = this.securityService.getAccessLevel("my-access-token", "my-app-id");
|
||||
this.server.verify();
|
||||
assertThat(accessLevel).isEqualTo(AccessLevel.RESTRICTED);
|
||||
@@ -108,35 +108,37 @@ class CloudFoundrySecurityServiceTests {
|
||||
@Test
|
||||
void getAccessLevelWhenTokenIsNotValidShouldThrowException() {
|
||||
this.server.expect(requestTo(CLOUD_CONTROLLER_PERMISSIONS))
|
||||
.andExpect(header("Authorization", "bearer my-access-token")).andRespond(withUnauthorizedRequest());
|
||||
.andExpect(header("Authorization", "bearer my-access-token"))
|
||||
.andRespond(withUnauthorizedRequest());
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(() -> this.securityService.getAccessLevel("my-access-token", "my-app-id"))
|
||||
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
.isThrownBy(() -> this.securityService.getAccessLevel("my-access-token", "my-app-id"))
|
||||
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getAccessLevelWhenForbiddenShouldThrowException() {
|
||||
this.server.expect(requestTo(CLOUD_CONTROLLER_PERMISSIONS))
|
||||
.andExpect(header("Authorization", "bearer my-access-token"))
|
||||
.andRespond(withStatus(HttpStatus.FORBIDDEN));
|
||||
.andExpect(header("Authorization", "bearer my-access-token"))
|
||||
.andRespond(withStatus(HttpStatus.FORBIDDEN));
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(() -> this.securityService.getAccessLevel("my-access-token", "my-app-id"))
|
||||
.satisfies(reasonRequirement(Reason.ACCESS_DENIED));
|
||||
.isThrownBy(() -> this.securityService.getAccessLevel("my-access-token", "my-app-id"))
|
||||
.satisfies(reasonRequirement(Reason.ACCESS_DENIED));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getAccessLevelWhenCloudControllerIsNotReachableThrowsException() {
|
||||
this.server.expect(requestTo(CLOUD_CONTROLLER_PERMISSIONS))
|
||||
.andExpect(header("Authorization", "bearer my-access-token")).andRespond(withServerError());
|
||||
.andExpect(header("Authorization", "bearer my-access-token"))
|
||||
.andRespond(withServerError());
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(() -> this.securityService.getAccessLevel("my-access-token", "my-app-id"))
|
||||
.satisfies(reasonRequirement(Reason.SERVICE_UNAVAILABLE));
|
||||
.isThrownBy(() -> this.securityService.getAccessLevel("my-access-token", "my-app-id"))
|
||||
.satisfies(reasonRequirement(Reason.SERVICE_UNAVAILABLE));
|
||||
}
|
||||
|
||||
@Test
|
||||
void fetchTokenKeysWhenSuccessfulShouldReturnListOfKeysFromUAA() {
|
||||
this.server.expect(requestTo(CLOUD_CONTROLLER + "/info"))
|
||||
.andRespond(withSuccess("{\"token_endpoint\":\"https://my-uaa.com\"}", MediaType.APPLICATION_JSON));
|
||||
.andRespond(withSuccess("{\"token_endpoint\":\"https://my-uaa.com\"}", MediaType.APPLICATION_JSON));
|
||||
String tokenKeyValue = """
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0m59l2u9iDnMbrXHfqkO
|
||||
@@ -150,7 +152,7 @@ class CloudFoundrySecurityServiceTests {
|
||||
String responseBody = "{\"keys\" : [ {\"kid\":\"test-key\",\"value\" : \"" + tokenKeyValue.replace("\n", "\\n")
|
||||
+ "\"} ]}";
|
||||
this.server.expect(requestTo(UAA_URL + "/token_keys"))
|
||||
.andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON));
|
||||
.andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON));
|
||||
Map<String, String> tokenKeys = this.securityService.fetchTokenKeys();
|
||||
this.server.verify();
|
||||
assertThat(tokenKeys).containsEntry("test-key", tokenKeyValue);
|
||||
@@ -159,10 +161,10 @@ class CloudFoundrySecurityServiceTests {
|
||||
@Test
|
||||
void fetchTokenKeysWhenNoKeysReturnedFromUAA() {
|
||||
this.server.expect(requestTo(CLOUD_CONTROLLER + "/info"))
|
||||
.andRespond(withSuccess("{\"token_endpoint\":\"" + UAA_URL + "\"}", MediaType.APPLICATION_JSON));
|
||||
.andRespond(withSuccess("{\"token_endpoint\":\"" + UAA_URL + "\"}", MediaType.APPLICATION_JSON));
|
||||
String responseBody = "{\"keys\": []}";
|
||||
this.server.expect(requestTo(UAA_URL + "/token_keys"))
|
||||
.andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON));
|
||||
.andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON));
|
||||
Map<String, String> tokenKeys = this.securityService.fetchTokenKeys();
|
||||
this.server.verify();
|
||||
assertThat(tokenKeys).isEmpty();
|
||||
@@ -171,17 +173,17 @@ class CloudFoundrySecurityServiceTests {
|
||||
@Test
|
||||
void fetchTokenKeysWhenUnsuccessfulShouldThrowException() {
|
||||
this.server.expect(requestTo(CLOUD_CONTROLLER + "/info"))
|
||||
.andRespond(withSuccess("{\"token_endpoint\":\"" + UAA_URL + "\"}", MediaType.APPLICATION_JSON));
|
||||
.andRespond(withSuccess("{\"token_endpoint\":\"" + UAA_URL + "\"}", MediaType.APPLICATION_JSON));
|
||||
this.server.expect(requestTo(UAA_URL + "/token_keys")).andRespond(withServerError());
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(() -> this.securityService.fetchTokenKeys())
|
||||
.satisfies(reasonRequirement(Reason.SERVICE_UNAVAILABLE));
|
||||
.isThrownBy(() -> this.securityService.fetchTokenKeys())
|
||||
.satisfies(reasonRequirement(Reason.SERVICE_UNAVAILABLE));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getUaaUrlShouldCallCloudControllerInfoOnlyOnce() {
|
||||
this.server.expect(requestTo(CLOUD_CONTROLLER + "/info"))
|
||||
.andRespond(withSuccess("{\"token_endpoint\":\"" + UAA_URL + "\"}", MediaType.APPLICATION_JSON));
|
||||
.andRespond(withSuccess("{\"token_endpoint\":\"" + UAA_URL + "\"}", MediaType.APPLICATION_JSON));
|
||||
String uaaUrl = this.securityService.getUaaUrl();
|
||||
this.server.verify();
|
||||
assertThat(uaaUrl).isEqualTo(UAA_URL);
|
||||
@@ -194,8 +196,8 @@ class CloudFoundrySecurityServiceTests {
|
||||
void getUaaUrlWhenCloudControllerUrlIsNotReachableShouldThrowException() {
|
||||
this.server.expect(requestTo(CLOUD_CONTROLLER + "/info")).andRespond(withServerError());
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(() -> this.securityService.getUaaUrl())
|
||||
.satisfies(reasonRequirement(Reason.SERVICE_UNAVAILABLE));
|
||||
.isThrownBy(() -> this.securityService.getUaaUrl())
|
||||
.satisfies(reasonRequirement(Reason.SERVICE_UNAVAILABLE));
|
||||
}
|
||||
|
||||
private Consumer<CloudFoundryAuthorizationException> reasonRequirement(Reason reason) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -39,7 +39,7 @@ class CloudFoundryWebEndpointServletHandlerMappingTests {
|
||||
new CloudFoundryWebEndpointServletHandlerMappingRuntimeHints().registerHints(runtimeHints,
|
||||
getClass().getClassLoader());
|
||||
assertThat(RuntimeHintsPredicates.reflection().onMethod(CloudFoundryLinksHandler.class, "links"))
|
||||
.accepts(runtimeHints);
|
||||
.accepts(runtimeHints);
|
||||
assertThat(RuntimeHintsPredicates.reflection().onType(Link.class)).accepts(runtimeHints);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -57,8 +57,8 @@ class SkipSslVerificationHttpRequestFactoryTests {
|
||||
ResponseEntity<String> responseEntity = restTemplate.getForEntity(httpsUrl, String.class);
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThatExceptionOfType(ResourceAccessException.class)
|
||||
.isThrownBy(() -> otherRestTemplate.getForEntity(httpsUrl, String.class))
|
||||
.withCauseInstanceOf(SSLHandshakeException.class);
|
||||
.isThrownBy(() -> otherRestTemplate.getForEntity(httpsUrl, String.class))
|
||||
.withCauseInstanceOf(SSLHandshakeException.class);
|
||||
}
|
||||
|
||||
private String getHttpsUrl() {
|
||||
|
||||
@@ -100,9 +100,10 @@ class TokenValidatorTests {
|
||||
given(this.securityService.fetchTokenKeys()).willReturn(INVALID_KEYS);
|
||||
String header = "{\"alg\": \"RS256\", \"kid\": \"valid-key\",\"typ\": \"JWT\"}";
|
||||
String claims = "{\"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(
|
||||
() -> this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.satisfies(reasonRequirement(Reason.INVALID_KEY_ID));
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(
|
||||
() -> this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.satisfies(reasonRequirement(Reason.INVALID_KEY_ID));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -142,18 +143,20 @@ class TokenValidatorTests {
|
||||
Collections.singletonMap("valid-key", INVALID_KEY));
|
||||
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\",\"typ\": \"JWT\"}";
|
||||
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(
|
||||
() -> this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.satisfies(reasonRequirement(Reason.INVALID_SIGNATURE));
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(
|
||||
() -> this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.satisfies(reasonRequirement(Reason.INVALID_SIGNATURE));
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateTokenWhenTokenAlgorithmIsNotRS256ShouldThrowException() {
|
||||
String header = "{ \"alg\": \"HS256\", \"typ\": \"JWT\"}";
|
||||
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(
|
||||
() -> this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.satisfies(reasonRequirement(Reason.UNSUPPORTED_TOKEN_SIGNING_ALGORITHM));
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(
|
||||
() -> this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.satisfies(reasonRequirement(Reason.UNSUPPORTED_TOKEN_SIGNING_ALGORITHM));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -162,9 +165,10 @@ class TokenValidatorTests {
|
||||
given(this.securityService.fetchTokenKeys()).willReturn(VALID_KEYS);
|
||||
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\", \"typ\": \"JWT\"}";
|
||||
String claims = "{ \"jti\": \"0236399c350c47f3ae77e67a75e75e7d\", \"exp\": 1477509977, \"scope\": [\"actuator.read\"]}";
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(
|
||||
() -> this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.satisfies(reasonRequirement(Reason.TOKEN_EXPIRED));
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(
|
||||
() -> this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.satisfies(reasonRequirement(Reason.TOKEN_EXPIRED));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -173,9 +177,10 @@ class TokenValidatorTests {
|
||||
given(this.securityService.getUaaUrl()).willReturn("https://other-uaa.com");
|
||||
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\", \"typ\": \"JWT\", \"scope\": [\"actuator.read\"]}";
|
||||
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\"}";
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(
|
||||
() -> this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.satisfies(reasonRequirement(Reason.INVALID_ISSUER));
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(
|
||||
() -> this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.satisfies(reasonRequirement(Reason.INVALID_ISSUER));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -184,9 +189,10 @@ class TokenValidatorTests {
|
||||
given(this.securityService.getUaaUrl()).willReturn("http://localhost:8080/uaa");
|
||||
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\", \"typ\": \"JWT\"}";
|
||||
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"foo.bar\"]}";
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(
|
||||
() -> this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.satisfies(reasonRequirement(Reason.INVALID_AUDIENCE));
|
||||
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
|
||||
.isThrownBy(
|
||||
() -> this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
|
||||
.satisfies(reasonRequirement(Reason.INVALID_AUDIENCE));
|
||||
}
|
||||
|
||||
private String getSignedToken(byte[] header, byte[] claims) throws Exception {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -31,12 +31,12 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class ConditionsReportEndpointAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(ConditionsReportEndpointAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(ConditionsReportEndpointAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void runShouldHaveEndpointBean() {
|
||||
this.contextRunner.withPropertyValues("management.endpoints.web.exposure.include=conditions")
|
||||
.run((context) -> assertThat(context).hasSingleBean(ConditionsReportEndpoint.class));
|
||||
.run((context) -> assertThat(context).hasSingleBean(ConditionsReportEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -47,7 +47,7 @@ class ConditionsReportEndpointAutoConfigurationTests {
|
||||
@Test
|
||||
void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
|
||||
this.contextRunner.withPropertyValues("management.endpoint.conditions.enabled:false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(ConditionsReportEndpoint.class));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(ConditionsReportEndpoint.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -47,8 +47,10 @@ class ConditionsReportEndpointTests {
|
||||
@Test
|
||||
void invoke() {
|
||||
new ApplicationContextRunner().withUserConfiguration(Config.class).run((context) -> {
|
||||
ContextConditionsDescriptor report = context.getBean(ConditionsReportEndpoint.class).conditions()
|
||||
.getContexts().get(context.getId());
|
||||
ContextConditionsDescriptor report = context.getBean(ConditionsReportEndpoint.class)
|
||||
.conditions()
|
||||
.getContexts()
|
||||
.get(context.getId());
|
||||
assertThat(report.getPositiveMatches()).isEmpty();
|
||||
assertThat(report.getNegativeMatches()).containsKey("a");
|
||||
assertThat(report.getUnconditionalClasses()).contains("b");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -36,31 +36,32 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class ShutdownEndpointAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(ShutdownEndpointAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(ShutdownEndpointAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void runShouldHaveEndpointBeanThatIsNotDisposable() {
|
||||
this.contextRunner.withPropertyValues("management.endpoint.shutdown.enabled:true")
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=shutdown").run((context) -> {
|
||||
assertThat(context).hasSingleBean(ShutdownEndpoint.class);
|
||||
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
|
||||
Map<String, Object> disposableBeans = (Map<String, Object>) ReflectionTestUtils
|
||||
.getField(beanFactory, "disposableBeans");
|
||||
assertThat(disposableBeans).isEmpty();
|
||||
});
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=shutdown")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(ShutdownEndpoint.class);
|
||||
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
|
||||
Map<String, Object> disposableBeans = (Map<String, Object>) ReflectionTestUtils.getField(beanFactory,
|
||||
"disposableBeans");
|
||||
assertThat(disposableBeans).isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWhenNotExposedShouldNotHaveEndpointBean() {
|
||||
this.contextRunner.withPropertyValues("management.endpoint.shutdown.enabled:true")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(ShutdownEndpoint.class));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(ShutdownEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
|
||||
this.contextRunner.withPropertyValues("management.endpoint.shutdown.enabled:false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(ShutdownEndpoint.class));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(ShutdownEndpoint.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -47,66 +47,67 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class ConfigurationPropertiesReportEndpointAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(ConfigurationPropertiesReportEndpointAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(ConfigurationPropertiesReportEndpointAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void runShouldHaveEndpointBean() {
|
||||
this.contextRunner.withUserConfiguration(Config.class)
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=configprops")
|
||||
.run(validateTestProperties("******", "******"));
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=configprops")
|
||||
.run(validateTestProperties("******", "******"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
|
||||
this.contextRunner.withPropertyValues("management.endpoint.configprops.enabled:false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(ConfigurationPropertiesReportEndpoint.class));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(ConfigurationPropertiesReportEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void rolesCanBeConfiguredViaTheEnvironment() {
|
||||
this.contextRunner.withUserConfiguration(Config.class)
|
||||
.withPropertyValues("management.endpoint.configprops.roles: test")
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=configprops").run((context) -> {
|
||||
assertThat(context).hasSingleBean(ConfigurationPropertiesReportEndpointWebExtension.class);
|
||||
ConfigurationPropertiesReportEndpointWebExtension endpoint = context
|
||||
.getBean(ConfigurationPropertiesReportEndpointWebExtension.class);
|
||||
Set<String> roles = (Set<String>) ReflectionTestUtils.getField(endpoint, "roles");
|
||||
assertThat(roles).contains("test");
|
||||
});
|
||||
.withPropertyValues("management.endpoint.configprops.roles: test")
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=configprops")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(ConfigurationPropertiesReportEndpointWebExtension.class);
|
||||
ConfigurationPropertiesReportEndpointWebExtension endpoint = context
|
||||
.getBean(ConfigurationPropertiesReportEndpointWebExtension.class);
|
||||
Set<String> roles = (Set<String>) ReflectionTestUtils.getField(endpoint, "roles");
|
||||
assertThat(roles).contains("test");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void showValuesCanBeConfiguredViaTheEnvironment() {
|
||||
this.contextRunner.withUserConfiguration(Config.class)
|
||||
.withPropertyValues("management.endpoint.configprops.show-values: WHEN_AUTHORIZED")
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=configprops").run((context) -> {
|
||||
assertThat(context).hasSingleBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
assertThat(context).hasSingleBean(ConfigurationPropertiesReportEndpointWebExtension.class);
|
||||
ConfigurationPropertiesReportEndpointWebExtension webExtension = context
|
||||
.getBean(ConfigurationPropertiesReportEndpointWebExtension.class);
|
||||
ConfigurationPropertiesReportEndpoint endpoint = context
|
||||
.getBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
Show showValuesWebExtension = (Show) ReflectionTestUtils.getField(webExtension, "showValues");
|
||||
assertThat(showValuesWebExtension).isEqualTo(Show.WHEN_AUTHORIZED);
|
||||
Show showValues = (Show) ReflectionTestUtils.getField(endpoint, "showValues");
|
||||
assertThat(showValues).isEqualTo(Show.WHEN_AUTHORIZED);
|
||||
});
|
||||
.withPropertyValues("management.endpoint.configprops.show-values: WHEN_AUTHORIZED")
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=configprops")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
assertThat(context).hasSingleBean(ConfigurationPropertiesReportEndpointWebExtension.class);
|
||||
ConfigurationPropertiesReportEndpointWebExtension webExtension = context
|
||||
.getBean(ConfigurationPropertiesReportEndpointWebExtension.class);
|
||||
ConfigurationPropertiesReportEndpoint endpoint = context
|
||||
.getBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
Show showValuesWebExtension = (Show) ReflectionTestUtils.getField(webExtension, "showValues");
|
||||
assertThat(showValuesWebExtension).isEqualTo(Show.WHEN_AUTHORIZED);
|
||||
Show showValues = (Show) ReflectionTestUtils.getField(endpoint, "showValues");
|
||||
assertThat(showValues).isEqualTo(Show.WHEN_AUTHORIZED);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void customSanitizingFunctionsAreAppliedInOrder() {
|
||||
this.contextRunner.withPropertyValues("management.endpoint.configprops.show-values: ALWAYS")
|
||||
.withUserConfiguration(Config.class, SanitizingFunctionConfiguration.class)
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=configprops",
|
||||
"test.my-test-property=abc")
|
||||
.run(validateTestProperties("$$$111$$$", "$$$222$$$"));
|
||||
.withUserConfiguration(Config.class, SanitizingFunctionConfiguration.class)
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=configprops", "test.my-test-property=abc")
|
||||
.run(validateTestProperties("$$$111$$$", "$$$222$$$"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWhenNotExposedShouldNotHaveEndpointBean() {
|
||||
this.contextRunner
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(ConfigurationPropertiesReportEndpoint.class));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(ConfigurationPropertiesReportEndpoint.class));
|
||||
}
|
||||
|
||||
private ContextConsumer<AssertableApplicationContext> validateTestProperties(String dbPassword,
|
||||
@@ -114,10 +115,13 @@ class ConfigurationPropertiesReportEndpointAutoConfigurationTests {
|
||||
return (context) -> {
|
||||
assertThat(context).hasSingleBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
ConfigurationPropertiesReportEndpoint endpoint = context
|
||||
.getBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
.getBean(ConfigurationPropertiesReportEndpoint.class);
|
||||
ConfigurationPropertiesDescriptor properties = endpoint.configurationProperties();
|
||||
Map<String, Object> nestedProperties = properties.getContexts().get(context.getId()).getBeans()
|
||||
.get("testProperties").getProperties();
|
||||
Map<String, Object> nestedProperties = properties.getContexts()
|
||||
.get(context.getId())
|
||||
.getBeans()
|
||||
.get("testProperties")
|
||||
.getProperties();
|
||||
assertThat(nestedProperties).isNotNull();
|
||||
assertThat(nestedProperties).containsEntry("dbPassword", dbPassword);
|
||||
assertThat(nestedProperties).containsEntry("myTestProperty", myTestProperty);
|
||||
@@ -127,10 +131,10 @@ class ConfigurationPropertiesReportEndpointAutoConfigurationTests {
|
||||
@Test
|
||||
void runWhenOnlyExposedOverJmxShouldHaveEndpointBeanWithoutWebExtension() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=info", "spring.jmx.enabled=true",
|
||||
"management.endpoints.jmx.exposure.include=configprops")
|
||||
.run((context) -> assertThat(context).hasSingleBean(ConfigurationPropertiesReportEndpoint.class)
|
||||
.doesNotHaveBean(ConfigurationPropertiesReportEndpointWebExtension.class));
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=info", "spring.jmx.enabled=true",
|
||||
"management.endpoints.jmx.exposure.include=configprops")
|
||||
.run((context) -> assertThat(context).hasSingleBean(ConfigurationPropertiesReportEndpoint.class)
|
||||
.doesNotHaveBean(ConfigurationPropertiesReportEndpointWebExtension.class));
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -37,19 +37,20 @@ import static org.mockito.Mockito.mock;
|
||||
class CouchbaseHealthContributorAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withBean(Cluster.class, () -> mock(Cluster.class)).withConfiguration(AutoConfigurations
|
||||
.of(CouchbaseHealthContributorAutoConfiguration.class, HealthContributorAutoConfiguration.class));
|
||||
.withBean(Cluster.class, () -> mock(Cluster.class))
|
||||
.withConfiguration(AutoConfigurations.of(CouchbaseHealthContributorAutoConfiguration.class,
|
||||
HealthContributorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void runShouldCreateIndicator() {
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(CouchbaseHealthIndicator.class)
|
||||
.doesNotHaveBean(CouchbaseReactiveHealthIndicator.class));
|
||||
.doesNotHaveBean(CouchbaseReactiveHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWhenDisabledShouldNotCreateIndicator() {
|
||||
this.contextRunner.withPropertyValues("management.health.couchbase.enabled:false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(CouchbaseHealthIndicator.class));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(CouchbaseHealthIndicator.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -36,28 +36,29 @@ import static org.mockito.Mockito.mock;
|
||||
class CouchbaseReactiveHealthContributorAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withBean(Cluster.class, () -> mock(Cluster.class))
|
||||
.withConfiguration(AutoConfigurations.of(CouchbaseReactiveHealthContributorAutoConfiguration.class,
|
||||
HealthContributorAutoConfiguration.class));
|
||||
.withBean(Cluster.class, () -> mock(Cluster.class))
|
||||
.withConfiguration(AutoConfigurations.of(CouchbaseReactiveHealthContributorAutoConfiguration.class,
|
||||
HealthContributorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void runShouldCreateIndicator() {
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(CouchbaseReactiveHealthIndicator.class)
|
||||
.hasBean("couchbaseHealthContributor"));
|
||||
.hasBean("couchbaseHealthContributor"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWithRegularIndicatorShouldOnlyCreateReactiveIndicator() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(CouchbaseHealthContributorAutoConfiguration.class))
|
||||
.run((context) -> assertThat(context).hasSingleBean(CouchbaseReactiveHealthIndicator.class)
|
||||
.hasBean("couchbaseHealthContributor").doesNotHaveBean(CouchbaseHealthIndicator.class));
|
||||
.run((context) -> assertThat(context).hasSingleBean(CouchbaseReactiveHealthIndicator.class)
|
||||
.hasBean("couchbaseHealthContributor")
|
||||
.doesNotHaveBean(CouchbaseHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWhenDisabledShouldNotCreateIndicator() {
|
||||
this.contextRunner.withPropertyValues("management.health.couchbase.enabled:false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(CouchbaseReactiveHealthIndicator.class)
|
||||
.doesNotHaveBean("couchbaseHealthContributor"));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(CouchbaseReactiveHealthIndicator.class)
|
||||
.doesNotHaveBean("couchbaseHealthContributor"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -38,31 +38,32 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class ElasticsearchReactiveHealthContributorAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(ElasticsearchDataAutoConfiguration.class,
|
||||
ReactiveElasticsearchClientAutoConfiguration.class, ElasticsearchRestClientAutoConfiguration.class,
|
||||
ElasticsearchReactiveHealthContributorAutoConfiguration.class,
|
||||
HealthContributorAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(ElasticsearchDataAutoConfiguration.class,
|
||||
ReactiveElasticsearchClientAutoConfiguration.class, ElasticsearchRestClientAutoConfiguration.class,
|
||||
ElasticsearchReactiveHealthContributorAutoConfiguration.class,
|
||||
HealthContributorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void runShouldCreateIndicator() {
|
||||
this.contextRunner.run((context) -> assertThat(context)
|
||||
.hasSingleBean(ElasticsearchReactiveHealthIndicator.class).hasBean("elasticsearchHealthContributor"));
|
||||
this.contextRunner
|
||||
.run((context) -> assertThat(context).hasSingleBean(ElasticsearchReactiveHealthIndicator.class)
|
||||
.hasBean("elasticsearchHealthContributor"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWithRegularIndicatorShouldOnlyCreateReactiveIndicator() {
|
||||
this.contextRunner
|
||||
.withConfiguration(AutoConfigurations.of(ElasticsearchRestHealthContributorAutoConfiguration.class))
|
||||
.run((context) -> assertThat(context).hasSingleBean(ElasticsearchReactiveHealthIndicator.class)
|
||||
.hasBean("elasticsearchHealthContributor")
|
||||
.doesNotHaveBean(ElasticsearchRestClientHealthIndicator.class));
|
||||
.withConfiguration(AutoConfigurations.of(ElasticsearchRestHealthContributorAutoConfiguration.class))
|
||||
.run((context) -> assertThat(context).hasSingleBean(ElasticsearchReactiveHealthIndicator.class)
|
||||
.hasBean("elasticsearchHealthContributor")
|
||||
.doesNotHaveBean(ElasticsearchRestClientHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWhenDisabledShouldNotCreateIndicator() {
|
||||
this.contextRunner.withPropertyValues("management.health.elasticsearch.enabled:false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(ElasticsearchReactiveHealthIndicator.class)
|
||||
.doesNotHaveBean("elasticsearchHealthContributor"));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(ElasticsearchReactiveHealthIndicator.class)
|
||||
.doesNotHaveBean("elasticsearchHealthContributor"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -35,8 +35,8 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class MongoHealthContributorAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(MongoAutoConfiguration.class, MongoDataAutoConfiguration.class,
|
||||
MongoHealthContributorAutoConfiguration.class, HealthContributorAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(MongoAutoConfiguration.class, MongoDataAutoConfiguration.class,
|
||||
MongoHealthContributorAutoConfiguration.class, HealthContributorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void runShouldCreateIndicator() {
|
||||
@@ -46,7 +46,7 @@ class MongoHealthContributorAutoConfigurationTests {
|
||||
@Test
|
||||
void runWhenDisabledShouldNotCreateIndicator() {
|
||||
this.contextRunner.withPropertyValues("management.health.mongo.enabled:false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(MongoHealthIndicator.class));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(MongoHealthIndicator.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -38,28 +38,29 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class MongoReactiveHealthContributorAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(MongoAutoConfiguration.class, MongoDataAutoConfiguration.class,
|
||||
MongoReactiveAutoConfiguration.class, MongoReactiveDataAutoConfiguration.class,
|
||||
MongoReactiveHealthContributorAutoConfiguration.class, HealthContributorAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(MongoAutoConfiguration.class, MongoDataAutoConfiguration.class,
|
||||
MongoReactiveAutoConfiguration.class, MongoReactiveDataAutoConfiguration.class,
|
||||
MongoReactiveHealthContributorAutoConfiguration.class, HealthContributorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void runShouldCreateIndicator() {
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(MongoReactiveHealthIndicator.class)
|
||||
.hasBean("mongoHealthContributor"));
|
||||
.hasBean("mongoHealthContributor"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWithRegularIndicatorShouldOnlyCreateReactiveIndicator() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(MongoHealthContributorAutoConfiguration.class))
|
||||
.run((context) -> assertThat(context).hasSingleBean(MongoReactiveHealthIndicator.class)
|
||||
.hasBean("mongoHealthContributor").doesNotHaveBean(MongoHealthIndicator.class));
|
||||
.run((context) -> assertThat(context).hasSingleBean(MongoReactiveHealthIndicator.class)
|
||||
.hasBean("mongoHealthContributor")
|
||||
.doesNotHaveBean(MongoHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWhenDisabledShouldNotCreateIndicator() {
|
||||
this.contextRunner.withPropertyValues("management.health.mongo.enabled:false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(MongoReactiveHealthIndicator.class)
|
||||
.doesNotHaveBean("mongoHealthContributor"));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(MongoReactiveHealthIndicator.class)
|
||||
.doesNotHaveBean("mongoHealthContributor"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -37,20 +37,20 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class RedisHealthContributorAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class,
|
||||
RedisHealthContributorAutoConfiguration.class, HealthContributorAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class,
|
||||
RedisHealthContributorAutoConfiguration.class, HealthContributorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void runShouldCreateIndicator() {
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(RedisHealthIndicator.class)
|
||||
.doesNotHaveBean(RedisReactiveHealthIndicator.class));
|
||||
.doesNotHaveBean(RedisReactiveHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWhenDisabledShouldNotCreateIndicator() {
|
||||
this.contextRunner.withPropertyValues("management.health.redis.enabled:false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(RedisHealthIndicator.class)
|
||||
.doesNotHaveBean(RedisReactiveHealthIndicator.class));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(RedisHealthIndicator.class)
|
||||
.doesNotHaveBean(RedisReactiveHealthIndicator.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -35,27 +35,28 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class RedisReactiveHealthContributorAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class,
|
||||
RedisReactiveHealthContributorAutoConfiguration.class, HealthContributorAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class,
|
||||
RedisReactiveHealthContributorAutoConfiguration.class, HealthContributorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void runShouldCreateIndicator() {
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(RedisReactiveHealthIndicator.class)
|
||||
.hasBean("redisHealthContributor"));
|
||||
.hasBean("redisHealthContributor"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWithRegularIndicatorShouldOnlyCreateReactiveIndicator() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisHealthContributorAutoConfiguration.class))
|
||||
.run((context) -> assertThat(context).hasSingleBean(RedisReactiveHealthIndicator.class)
|
||||
.hasBean("redisHealthContributor").doesNotHaveBean(RedisHealthIndicator.class));
|
||||
.run((context) -> assertThat(context).hasSingleBean(RedisReactiveHealthIndicator.class)
|
||||
.hasBean("redisHealthContributor")
|
||||
.doesNotHaveBean(RedisHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWhenDisabledShouldNotCreateIndicator() {
|
||||
this.contextRunner.withPropertyValues("management.health.redis.enabled:false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(RedisReactiveHealthIndicator.class)
|
||||
.doesNotHaveBean("redisHealthContributor"));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(RedisReactiveHealthIndicator.class)
|
||||
.doesNotHaveBean("redisHealthContributor"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -40,35 +40,35 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class ElasticsearchRestHealthContributorAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(ElasticsearchRestClientAutoConfiguration.class,
|
||||
ElasticsearchRestHealthContributorAutoConfiguration.class,
|
||||
HealthContributorAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(ElasticsearchRestClientAutoConfiguration.class,
|
||||
ElasticsearchRestHealthContributorAutoConfiguration.class, HealthContributorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void runShouldCreateIndicator() {
|
||||
this.contextRunner.run((context) -> assertThat(context)
|
||||
.hasSingleBean(ElasticsearchRestClientHealthIndicator.class).hasBean("elasticsearchHealthContributor"));
|
||||
this.contextRunner
|
||||
.run((context) -> assertThat(context).hasSingleBean(ElasticsearchRestClientHealthIndicator.class)
|
||||
.hasBean("elasticsearchHealthContributor"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWithoutRestClientShouldNotCreateIndicator() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(RestClient.class))
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(ElasticsearchRestClientHealthIndicator.class)
|
||||
.doesNotHaveBean("elasticsearchHealthContributor"));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(ElasticsearchRestClientHealthIndicator.class)
|
||||
.doesNotHaveBean("elasticsearchHealthContributor"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWithRestClientShouldCreateIndicator() {
|
||||
this.contextRunner.withUserConfiguration(CustomRestClientConfiguration.class)
|
||||
.run((context) -> assertThat(context).hasSingleBean(ElasticsearchRestClientHealthIndicator.class)
|
||||
.hasBean("elasticsearchHealthContributor"));
|
||||
.run((context) -> assertThat(context).hasSingleBean(ElasticsearchRestClientHealthIndicator.class)
|
||||
.hasBean("elasticsearchHealthContributor"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void runWhenDisabledShouldNotCreateIndicator() {
|
||||
this.contextRunner.withPropertyValues("management.health.elasticsearch.enabled:false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(ElasticsearchRestClientHealthIndicator.class)
|
||||
.doesNotHaveBean("elasticsearchHealthContributor"));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(ElasticsearchRestClientHealthIndicator.class)
|
||||
.doesNotHaveBean("elasticsearchHealthContributor"));
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
|
||||
@@ -47,7 +47,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
class EndpointAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(EndpointAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(EndpointAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void mapShouldUseConfigurationConverter() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -37,172 +37,219 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class ConditionalOnAvailableEndpointTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withUserConfiguration(AllEndpointsConfiguration.class);
|
||||
.withUserConfiguration(AllEndpointsConfiguration.class);
|
||||
|
||||
@Test
|
||||
void outcomeShouldMatchDefaults() {
|
||||
this.contextRunner.run((context) -> assertThat(context).hasBean("health").doesNotHaveBean("spring")
|
||||
.doesNotHaveBean("test").doesNotHaveBean("shutdown"));
|
||||
this.contextRunner.run((context) -> assertThat(context).hasBean("health")
|
||||
.doesNotHaveBean("spring")
|
||||
.doesNotHaveBean("test")
|
||||
.doesNotHaveBean("shutdown"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void outcomeWithEnabledByDefaultSetToFalseShouldNotMatchAnything() {
|
||||
this.contextRunner.withPropertyValues("management.endpoints.enabled-by-default=false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean("info").doesNotHaveBean("health")
|
||||
.doesNotHaveBean("spring").doesNotHaveBean("test").doesNotHaveBean("shutdown"));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean("info")
|
||||
.doesNotHaveBean("health")
|
||||
.doesNotHaveBean("spring")
|
||||
.doesNotHaveBean("test")
|
||||
.doesNotHaveBean("shutdown"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void outcomeWhenIncludeAllWebShouldMatchEnabledEndpoints() {
|
||||
this.contextRunner.withPropertyValues("management.endpoints.web.exposure.include=*")
|
||||
.run((context) -> assertThat(context).hasBean("info").hasBean("health").hasBean("test")
|
||||
.hasBean("spring").doesNotHaveBean("shutdown"));
|
||||
.run((context) -> assertThat(context).hasBean("info")
|
||||
.hasBean("health")
|
||||
.hasBean("test")
|
||||
.hasBean("spring")
|
||||
.doesNotHaveBean("shutdown"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void outcomeWhenIncludeAllWebAndDisablingEndpointShouldMatchEnabledEndpoints() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=*",
|
||||
"management.endpoint.test.enabled=false", "management.endpoint.health.enabled=false")
|
||||
.run((context) -> assertThat(context).hasBean("info").doesNotHaveBean("health").doesNotHaveBean("test")
|
||||
.hasBean("spring").doesNotHaveBean("shutdown"));
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=*", "management.endpoint.test.enabled=false",
|
||||
"management.endpoint.health.enabled=false")
|
||||
.run((context) -> assertThat(context).hasBean("info")
|
||||
.doesNotHaveBean("health")
|
||||
.doesNotHaveBean("test")
|
||||
.hasBean("spring")
|
||||
.doesNotHaveBean("shutdown"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void outcomeWhenIncludeAllWebAndEnablingEndpointDisabledByDefaultShouldMatchAll() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=*",
|
||||
"management.endpoint.shutdown.enabled=true")
|
||||
.run((context) -> assertThat(context).hasBean("info").hasBean("health").hasBean("test")
|
||||
.hasBean("spring").hasBean("shutdown"));
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=*",
|
||||
"management.endpoint.shutdown.enabled=true")
|
||||
.run((context) -> assertThat(context).hasBean("info")
|
||||
.hasBean("health")
|
||||
.hasBean("test")
|
||||
.hasBean("spring")
|
||||
.hasBean("shutdown"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void outcomeWhenIncludeAllJmxButJmxDisabledShouldMatchDefaults() {
|
||||
this.contextRunner.withPropertyValues("management.endpoints.jmx.exposure.include=*")
|
||||
.run((context) -> assertThat(context).hasBean("health").doesNotHaveBean("spring")
|
||||
.doesNotHaveBean("test").doesNotHaveBean("shutdown"));
|
||||
.run((context) -> assertThat(context).hasBean("health")
|
||||
.doesNotHaveBean("spring")
|
||||
.doesNotHaveBean("test")
|
||||
.doesNotHaveBean("shutdown"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void outcomeWhenIncludeAllJmxAndJmxEnabledShouldMatchEnabledEndpoints() {
|
||||
this.contextRunner.withPropertyValues("management.endpoints.jmx.exposure.include=*", "spring.jmx.enabled=true")
|
||||
.run((context) -> assertThat(context).hasBean("info").hasBean("health").hasBean("test")
|
||||
.hasBean("spring").doesNotHaveBean("shutdown"));
|
||||
.run((context) -> assertThat(context).hasBean("info")
|
||||
.hasBean("health")
|
||||
.hasBean("test")
|
||||
.hasBean("spring")
|
||||
.doesNotHaveBean("shutdown"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void outcomeWhenIncludeAllJmxAndJmxEnabledAndEnablingEndpointDisabledByDefaultShouldMatchAll() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoints.jmx.exposure.include=*", "spring.jmx.enabled=true",
|
||||
"management.endpoint.shutdown.enabled=true")
|
||||
.run((context) -> assertThat(context).hasBean("health").hasBean("test").hasBean("spring")
|
||||
.hasBean("shutdown"));
|
||||
.withPropertyValues("management.endpoints.jmx.exposure.include=*", "spring.jmx.enabled=true",
|
||||
"management.endpoint.shutdown.enabled=true")
|
||||
.run((context) -> assertThat(context).hasBean("health")
|
||||
.hasBean("test")
|
||||
.hasBean("spring")
|
||||
.hasBean("shutdown"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void outcomeWhenIncludeAllWebAndExcludeMatchesShouldNotMatch() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=*",
|
||||
"management.endpoints.web.exposure.exclude=spring,info")
|
||||
.run((context) -> assertThat(context).hasBean("health").hasBean("test").doesNotHaveBean("info")
|
||||
.doesNotHaveBean("spring").doesNotHaveBean("shutdown"));
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=*",
|
||||
"management.endpoints.web.exposure.exclude=spring,info")
|
||||
.run((context) -> assertThat(context).hasBean("health")
|
||||
.hasBean("test")
|
||||
.doesNotHaveBean("info")
|
||||
.doesNotHaveBean("spring")
|
||||
.doesNotHaveBean("shutdown"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void outcomeWhenIncludeMatchesAndExcludeMatchesShouldNotMatch() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=info,health,spring,test",
|
||||
"management.endpoints.web.exposure.exclude=spring,info")
|
||||
.run((context) -> assertThat(context).hasBean("health").hasBean("test").doesNotHaveBean("info")
|
||||
.doesNotHaveBean("spring").doesNotHaveBean("shutdown"));
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=info,health,spring,test",
|
||||
"management.endpoints.web.exposure.exclude=spring,info")
|
||||
.run((context) -> assertThat(context).hasBean("health")
|
||||
.hasBean("test")
|
||||
.doesNotHaveBean("info")
|
||||
.doesNotHaveBean("spring")
|
||||
.doesNotHaveBean("shutdown"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void outcomeWhenIncludeMatchesShouldMatchEnabledEndpoints() {
|
||||
this.contextRunner.withPropertyValues("management.endpoints.web.exposure.include=spring")
|
||||
.run((context) -> assertThat(context).hasBean("spring").doesNotHaveBean("health")
|
||||
.doesNotHaveBean("info").doesNotHaveBean("test").doesNotHaveBean("shutdown"));
|
||||
.run((context) -> assertThat(context).hasBean("spring")
|
||||
.doesNotHaveBean("health")
|
||||
.doesNotHaveBean("info")
|
||||
.doesNotHaveBean("test")
|
||||
.doesNotHaveBean("shutdown"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void outcomeWhenIncludeMatchOnDisabledEndpointShouldNotMatch() {
|
||||
this.contextRunner.withPropertyValues("management.endpoints.web.exposure.include=shutdown")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean("spring").doesNotHaveBean("health")
|
||||
.doesNotHaveBean("info").doesNotHaveBean("test").doesNotHaveBean("shutdown"));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean("spring")
|
||||
.doesNotHaveBean("health")
|
||||
.doesNotHaveBean("info")
|
||||
.doesNotHaveBean("test")
|
||||
.doesNotHaveBean("shutdown"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void outcomeWhenIncludeMatchOnEnabledEndpointShouldNotMatch() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=shutdown",
|
||||
"management.endpoint.shutdown.enabled=true")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean("spring").doesNotHaveBean("health")
|
||||
.doesNotHaveBean("info").doesNotHaveBean("test").hasBean("shutdown"));
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=shutdown",
|
||||
"management.endpoint.shutdown.enabled=true")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean("spring")
|
||||
.doesNotHaveBean("health")
|
||||
.doesNotHaveBean("info")
|
||||
.doesNotHaveBean("test")
|
||||
.hasBean("shutdown"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void outcomeWhenIncludeMatchesWithCaseShouldMatch() {
|
||||
this.contextRunner.withPropertyValues("management.endpoints.web.exposure.include=sPRing")
|
||||
.run((context) -> assertThat(context).hasBean("spring").doesNotHaveBean("health")
|
||||
.doesNotHaveBean("info").doesNotHaveBean("test").doesNotHaveBean("shutdown"));
|
||||
.run((context) -> assertThat(context).hasBean("spring")
|
||||
.doesNotHaveBean("health")
|
||||
.doesNotHaveBean("info")
|
||||
.doesNotHaveBean("test")
|
||||
.doesNotHaveBean("shutdown"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void outcomeWhenIncludeMatchesAndExcludeAllShouldNotMatch() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=info,health,spring,test",
|
||||
"management.endpoints.web.exposure.exclude=*")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean("health").doesNotHaveBean("info")
|
||||
.doesNotHaveBean("spring").doesNotHaveBean("test").doesNotHaveBean("shutdown"));
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=info,health,spring,test",
|
||||
"management.endpoints.web.exposure.exclude=*")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean("health")
|
||||
.doesNotHaveBean("info")
|
||||
.doesNotHaveBean("spring")
|
||||
.doesNotHaveBean("test")
|
||||
.doesNotHaveBean("shutdown"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void outcomeWhenIncludeMatchesShouldMatchWithExtensionsAndComponents() {
|
||||
this.contextRunner.withUserConfiguration(ComponentEnabledIfEndpointIsExposedConfiguration.class)
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=spring")
|
||||
.run((context) -> assertThat(context).hasBean("spring").hasBean("springComponent")
|
||||
.hasBean("springExtension").doesNotHaveBean("info").doesNotHaveBean("health")
|
||||
.doesNotHaveBean("test").doesNotHaveBean("shutdown"));
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=spring")
|
||||
.run((context) -> assertThat(context).hasBean("spring")
|
||||
.hasBean("springComponent")
|
||||
.hasBean("springExtension")
|
||||
.doesNotHaveBean("info")
|
||||
.doesNotHaveBean("health")
|
||||
.doesNotHaveBean("test")
|
||||
.doesNotHaveBean("shutdown"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void outcomeWithNoEndpointReferenceShouldFail() {
|
||||
this.contextRunner.withUserConfiguration(ComponentWithNoEndpointReferenceConfiguration.class)
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=*").run((context) -> {
|
||||
assertThat(context).hasFailed();
|
||||
assertThat(context.getStartupFailure().getCause().getMessage())
|
||||
.contains("No endpoint is specified and the return type of the @Bean method "
|
||||
+ "is neither an @Endpoint, nor an @EndpointExtension");
|
||||
});
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=*")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasFailed();
|
||||
assertThat(context.getStartupFailure().getCause().getMessage())
|
||||
.contains("No endpoint is specified and the return type of the @Bean method "
|
||||
+ "is neither an @Endpoint, nor an @EndpointExtension");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void outcomeOnCloudFoundryShouldMatchAll() {
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---").run(
|
||||
(context) -> assertThat(context).hasBean("info").hasBean("health").hasBean("spring").hasBean("test"));
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---")
|
||||
.run((context) -> assertThat(context).hasBean("info").hasBean("health").hasBean("spring").hasBean("test"));
|
||||
}
|
||||
|
||||
@Test // gh-21044
|
||||
void outcomeWhenIncludeAllShouldMatchDashedEndpoint() {
|
||||
this.contextRunner.withUserConfiguration(DashedEndpointConfiguration.class)
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=*")
|
||||
.run((context) -> assertThat(context).hasSingleBean(DashedEndpoint.class));
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=*")
|
||||
.run((context) -> assertThat(context).hasSingleBean(DashedEndpoint.class));
|
||||
}
|
||||
|
||||
@Test // gh-21044
|
||||
void outcomeWhenIncludeDashedShouldMatchDashedEndpoint() {
|
||||
this.contextRunner.withUserConfiguration(DashedEndpointConfiguration.class)
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=test-dashed")
|
||||
.run((context) -> assertThat(context).hasSingleBean(DashedEndpoint.class));
|
||||
.withPropertyValues("management.endpoints.web.exposure.include=test-dashed")
|
||||
.run((context) -> assertThat(context).hasSingleBean(DashedEndpoint.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void outcomeWhenEndpointNotExposedOnSpecifiedTechnology() {
|
||||
this.contextRunner.withUserConfiguration(ExposureEndpointConfiguration.class)
|
||||
.withPropertyValues("spring.jmx.enabled=true", "management.endpoints.jmx.exposure.include=test",
|
||||
"management.endpoints.web.exposure.exclude=test")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean("unexposed"));
|
||||
.withPropertyValues("spring.jmx.enabled=true", "management.endpoints.jmx.exposure.include=test",
|
||||
"management.endpoints.web.exposure.exclude=test")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean("unexposed"));
|
||||
}
|
||||
|
||||
@Endpoint(id = "health")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -44,31 +44,29 @@ class IncludeExcludeEndpointFilterTests {
|
||||
@Test
|
||||
void createWhenEndpointTypeIsNullShouldThrowException() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new IncludeExcludeEndpointFilter<>(null, new MockEnvironment(), "foo"))
|
||||
.withMessageContaining("EndpointType must not be null");
|
||||
.isThrownBy(() -> new IncludeExcludeEndpointFilter<>(null, new MockEnvironment(), "foo"))
|
||||
.withMessageContaining("EndpointType must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWhenEnvironmentIsNullShouldThrowException() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new IncludeExcludeEndpointFilter<>(ExposableEndpoint.class, null, "foo"))
|
||||
.withMessageContaining("Environment must not be null");
|
||||
.isThrownBy(() -> new IncludeExcludeEndpointFilter<>(ExposableEndpoint.class, null, "foo"))
|
||||
.withMessageContaining("Environment must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWhenPrefixIsNullShouldThrowException() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(
|
||||
() -> new IncludeExcludeEndpointFilter<>(ExposableEndpoint.class, new MockEnvironment(), null))
|
||||
.withMessageContaining("Prefix must not be empty");
|
||||
.isThrownBy(() -> new IncludeExcludeEndpointFilter<>(ExposableEndpoint.class, new MockEnvironment(), null))
|
||||
.withMessageContaining("Prefix must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWhenPrefixIsEmptyShouldThrowException() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(
|
||||
() -> new IncludeExcludeEndpointFilter<>(ExposableEndpoint.class, new MockEnvironment(), ""))
|
||||
.withMessageContaining("Prefix must not be empty");
|
||||
.isThrownBy(() -> new IncludeExcludeEndpointFilter<>(ExposableEndpoint.class, new MockEnvironment(), ""))
|
||||
.withMessageContaining("Prefix must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -41,7 +41,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class JacksonEndpointAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner runner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(JacksonEndpointAutoConfiguration.class));
|
||||
.withConfiguration(AutoConfigurations.of(JacksonEndpointAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void endpointObjectMapperWhenNoProperty() {
|
||||
@@ -51,13 +51,13 @@ class JacksonEndpointAutoConfigurationTests {
|
||||
@Test
|
||||
void endpointObjectMapperWhenPropertyTrue() {
|
||||
this.runner.withPropertyValues("management.endpoints.jackson.isolated-object-mapper=true")
|
||||
.run((context) -> assertThat(context).hasSingleBean(EndpointObjectMapper.class));
|
||||
.run((context) -> assertThat(context).hasSingleBean(EndpointObjectMapper.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void endpointObjectMapperWhenPropertyFalse() {
|
||||
this.runner.withPropertyValues("management.endpoints.jackson.isolated-object-mapper=false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(EndpointObjectMapper.class));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(EndpointObjectMapper.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user