Skip to content

Commit d50fe88

Browse files
committed
Add CF support for reactive actuators
Closes gh-10780
1 parent 7c5d2fa commit d50fe88

File tree

32 files changed

+2474
-273
lines changed

32 files changed

+2474
-273
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure/pom.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,16 @@
348348
<artifactId>logback-classic</artifactId>
349349
<scope>test</scope>
350350
</dependency>
351+
<dependency>
352+
<groupId>io.projectreactor</groupId>
353+
<artifactId>reactor-test</artifactId>
354+
<scope>test</scope>
355+
</dependency>
356+
<dependency>
357+
<groupId>com.squareup.okhttp3</groupId>
358+
<artifactId>mockwebserver</artifactId>
359+
<scope>test</scope>
360+
</dependency>
351361
<dependency>
352362
<groupId>com.jayway.jsonpath</groupId>
353363
<artifactId>json-path</artifactId>

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/AccessLevel.java

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,13 @@
1919
import java.util.Arrays;
2020
import java.util.List;
2121

22-
import javax.servlet.http.HttpServletRequest;
23-
2422
/**
2523
* The specific access level granted to the cloud foundry user that's calling the
2624
* endpoints.
2725
*
2826
* @author Madhura Bhave
2927
*/
30-
enum AccessLevel {
28+
public enum AccessLevel {
3129

3230
/**
3331
* Restricted access to a limited set of endpoints.
@@ -39,7 +37,7 @@ enum AccessLevel {
3937
*/
4038
FULL;
4139

42-
private static final String REQUEST_ATTRIBUTE = "cloudFoundryAccessLevel";
40+
public static final String REQUEST_ATTRIBUTE = "cloudFoundryAccessLevel";
4341

4442
private final List<String> endpointPaths;
4543

@@ -56,12 +54,4 @@ public boolean isAccessAllowed(String endpointPath) {
5654
return this.endpointPaths.isEmpty() || this.endpointPaths.contains(endpointPath);
5755
}
5856

59-
public void put(HttpServletRequest request) {
60-
request.setAttribute(REQUEST_ATTRIBUTE, this);
61-
}
62-
63-
public static AccessLevel get(HttpServletRequest request) {
64-
return (AccessLevel) request.getAttribute(REQUEST_ATTRIBUTE);
65-
}
66-
6757
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/CloudFoundryAuthorizationException.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,15 @@
2323
*
2424
* @author Madhura Bhave
2525
*/
26-
class CloudFoundryAuthorizationException extends RuntimeException {
26+
public class CloudFoundryAuthorizationException extends RuntimeException {
2727

2828
private final Reason reason;
2929

30-
CloudFoundryAuthorizationException(Reason reason, String message) {
30+
public CloudFoundryAuthorizationException(Reason reason, String message) {
3131
this(reason, message, null);
3232
}
3333

34-
CloudFoundryAuthorizationException(Reason reason, String message, Throwable cause) {
34+
public CloudFoundryAuthorizationException(Reason reason, String message, Throwable cause) {
3535
super(message);
3636
this.reason = reason;
3737
}
@@ -55,7 +55,7 @@ public Reason getReason() {
5555
/**
5656
* Reasons why the exception can be thrown.
5757
*/
58-
enum Reason {
58+
public enum Reason {
5959

6060
ACCESS_DENIED(HttpStatus.FORBIDDEN),
6161

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright 2012-2017 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.autoconfigure.cloudfoundry;
18+
19+
import org.springframework.http.HttpStatus;
20+
21+
/**
22+
* Response from the Cloud Foundry security interceptors.
23+
*
24+
* @author Madhura Bhave
25+
*/
26+
public class SecurityResponse {
27+
28+
private final HttpStatus status;
29+
30+
private final String message;
31+
32+
public SecurityResponse(HttpStatus status) {
33+
this(status, null);
34+
}
35+
36+
public SecurityResponse(HttpStatus status, String message) {
37+
this.status = status;
38+
this.message = message;
39+
}
40+
41+
public HttpStatus getStatus() {
42+
return this.status;
43+
}
44+
45+
public String getMessage() {
46+
return this.message;
47+
}
48+
49+
public static SecurityResponse success() {
50+
return new SecurityResponse(HttpStatus.OK);
51+
}
52+
53+
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/Token.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.List;
2121
import java.util.Map;
2222

23+
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.CloudFoundryAuthorizationException.Reason;
2324
import org.springframework.boot.json.JsonParserFactory;
2425
import org.springframework.util.Base64Utils;
2526
import org.springframework.util.StringUtils;
@@ -29,7 +30,7 @@
2930
*
3031
* @author Madhura Bhave
3132
*/
32-
class Token {
33+
public class Token {
3334

3435
private static final Charset UTF_8 = Charset.forName("UTF-8");
3536

@@ -41,21 +42,21 @@ class Token {
4142

4243
private final Map<String, Object> claims;
4344

44-
Token(String encoded) {
45+
public Token(String encoded) {
4546
this.encoded = encoded;
4647
int firstPeriod = encoded.indexOf('.');
4748
int lastPeriod = encoded.lastIndexOf('.');
4849
if (firstPeriod <= 0 || lastPeriod <= firstPeriod) {
4950
throw new CloudFoundryAuthorizationException(
50-
CloudFoundryAuthorizationException.Reason.INVALID_TOKEN,
51+
Reason.INVALID_TOKEN,
5152
"JWT must have header, body and signature");
5253
}
5354
this.header = parseJson(encoded.substring(0, firstPeriod));
5455
this.claims = parseJson(encoded.substring(firstPeriod + 1, lastPeriod));
5556
this.signature = encoded.substring(lastPeriod + 1);
5657
if (!StringUtils.hasLength(this.signature)) {
5758
throw new CloudFoundryAuthorizationException(
58-
CloudFoundryAuthorizationException.Reason.INVALID_TOKEN,
59+
Reason.INVALID_TOKEN,
5960
"Token must have non-empty crypto segment");
6061
}
6162
}
@@ -67,7 +68,7 @@ private Map<String, Object> parseJson(String base64) {
6768
}
6869
catch (RuntimeException ex) {
6970
throw new CloudFoundryAuthorizationException(
70-
CloudFoundryAuthorizationException.Reason.INVALID_TOKEN,
71+
Reason.INVALID_TOKEN,
7172
"Token could not be parsed", ex);
7273
}
7374
}
@@ -106,12 +107,12 @@ private <T> T getRequired(Map<String, Object> map, String key, Class<T> type) {
106107
Object value = map.get(key);
107108
if (value == null) {
108109
throw new CloudFoundryAuthorizationException(
109-
CloudFoundryAuthorizationException.Reason.INVALID_TOKEN,
110+
Reason.INVALID_TOKEN,
110111
"Unable to get value from key " + key);
111112
}
112113
if (!type.isInstance(value)) {
113114
throw new CloudFoundryAuthorizationException(
114-
CloudFoundryAuthorizationException.Reason.INVALID_TOKEN,
115+
Reason.INVALID_TOKEN,
115116
"Unexpected value type from key " + key + " value " + value);
116117
}
117118
return (T) value;

0 commit comments

Comments
 (0)