Skip to content

Commit 8df66c9

Browse files
committed
handle domains with multiple ips better
- probe the first IP of a domain only - cache results for 10m
1 parent 39e294c commit 8df66c9

File tree

6 files changed

+52
-28
lines changed

6 files changed

+52
-28
lines changed

examples/docker-compose.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ services:
1111
- 9090:9090
1212

1313
tls-grade-exporter:
14-
image: ghcr.io/ping7io/tls-grade-exporter:latest
14+
image: ping7io/tls-grade-exporter:latest
1515
ports:
1616
- 9218:9218

pom.xml

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,26 +19,32 @@
1919
<dependencies>
2020
<dependency>
2121
<groupId>org.springframework.boot</groupId>
22-
<artifactId>spring-boot-starter-webflux</artifactId>
22+
<artifactId>spring-boot-starter-actuator</artifactId>
2323
</dependency>
2424
<dependency>
25-
<groupId>com.fasterxml.jackson.core</groupId>
26-
<artifactId>jackson-databind</artifactId>
27-
<version>2.16.0</version>
25+
<groupId>org.springframework.boot</groupId>
26+
<artifactId>spring-boot-starter-web</artifactId>
27+
</dependency>
28+
<dependency>
29+
<groupId>org.springframework.boot</groupId>
30+
<artifactId>spring-boot-starter-cache</artifactId>
2831
</dependency>
2932
<dependency>
3033
<groupId>org.projectlombok</groupId>
3134
<artifactId>lombok</artifactId>
32-
<version>1.18.30</version>
33-
<scope>provided</scope>
35+
<optional>true</optional>
36+
</dependency>
37+
<dependency>
38+
<groupId>com.fasterxml.jackson.core</groupId>
39+
<artifactId>jackson-databind</artifactId>
40+
<version>2.16.0</version>
3441
</dependency>
3542

3643
<!-- Actuator -->
3744
<dependency>
3845
<groupId>org.springframework.boot</groupId>
3946
<artifactId>spring-boot-starter-actuator</artifactId>
4047
</dependency>
41-
4248
<dependency>
4349
<groupId>io.micrometer</groupId>
4450
<artifactId>micrometer-registry-prometheus</artifactId>
@@ -47,13 +53,13 @@
4753

4854
<!-- Test dependencies -->
4955
<dependency>
50-
<groupId>org.springframework.boot</groupId>
51-
<artifactId>spring-boot-starter-test</artifactId>
52-
<scope>test</scope>
56+
<groupId>org.projectlombok</groupId>
57+
<artifactId>lombok</artifactId>
58+
<optional>true</optional>
5359
</dependency>
5460
<dependency>
55-
<groupId>io.projectreactor</groupId>
56-
<artifactId>reactor-test</artifactId>
61+
<groupId>org.springframework.boot</groupId>
62+
<artifactId>spring-boot-starter-test</artifactId>
5763
<scope>test</scope>
5864
</dependency>
5965
</dependencies>

src/main/java/io/ping7/tlsgradeexporter/TestSslService.java

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,23 @@
11
package io.ping7.tlsgradeexporter;
22

33
import java.nio.charset.StandardCharsets;
4+
import java.util.HashSet;
45
import java.util.List;
5-
import java.util.concurrent.CompletableFuture;
6+
import java.util.Set;
67

7-
import org.springframework.aot.hint.ExecutableMode;
88
import org.springframework.aot.hint.MemberCategory;
99
import org.springframework.aot.hint.RuntimeHints;
1010
import org.springframework.aot.hint.RuntimeHintsRegistrar;
11+
import org.springframework.cache.annotation.Cacheable;
1112
import org.springframework.context.annotation.ImportRuntimeHints;
1213
import org.springframework.stereotype.Service;
13-
import org.springframework.util.ReflectionUtils;
1414
import org.springframework.util.StopWatch;
1515

1616
import com.fasterxml.jackson.core.type.TypeReference;
1717
import com.fasterxml.jackson.databind.ObjectMapper;
1818

1919
import io.micrometer.core.annotation.Timed;
20-
import io.micrometer.core.instrument.MeterRegistry;
2120
import lombok.extern.java.Log;
22-
import reactor.core.publisher.Mono;
2321

2422
/**
2523
* Runs the test ssl command
@@ -31,11 +29,22 @@ public class TestSslService {
3129

3230
private final ObjectMapper om = new ObjectMapper();
3331

32+
private final Set<String> activeRatings = new HashSet<>();
33+
34+
public boolean isCurrentlyRating(String target) {
35+
return activeRatings.contains(target);
36+
}
37+
3438
@Timed
35-
public Mono<TlsGrade> rate(String target) {
36-
return Mono.fromFuture(CompletableFuture.supplyAsync(() -> computeTestSslOutput(target)))
37-
.onErrorComplete()
38-
.map(s -> toTlsGrade(s, target));
39+
@Cacheable("targets")
40+
public TlsGrade rate(String target) {
41+
activeRatings.add(target);
42+
43+
try {
44+
return toTlsGrade(computeTestSslOutput(target), target);
45+
} finally {
46+
activeRatings.remove(target);
47+
}
3948
}
4049

4150
private String computeTestSslOutput(String target) {
@@ -113,7 +122,7 @@ else if ("scanTime".equals(f.getId())) {
113122

114123
private String[] rateCommandFor(String target) {
115124
return new String[] { "testssl.sh/testssl.sh", "--quiet", "--color", "0", "--jsonfile",
116-
"/dev/stderr", "--quiet", "--hints", target };
125+
"/dev/stderr", "--hints", "--ip", "one", target };
117126
}
118127

119128
static class TestSslServiceRuntimeHints implements RuntimeHintsRegistrar {

src/main/java/io/ping7/tlsgradeexporter/TlsGradeExporter.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,27 @@
11
package io.ping7.tlsgradeexporter;
22

33
import org.springframework.beans.factory.annotation.Autowired;
4+
import org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties.Http;
5+
import org.springframework.http.HttpStatusCode;
46
import org.springframework.http.MediaType;
57
import org.springframework.http.ResponseEntity;
68
import org.springframework.web.bind.annotation.GetMapping;
79
import org.springframework.web.bind.annotation.RequestParam;
810
import org.springframework.web.bind.annotation.RestController;
911

10-
import reactor.core.publisher.Mono;
11-
1212
@RestController
1313
public class TlsGradeExporter {
1414

1515
@Autowired
1616
private TestSslService testSsl;
1717

1818
@GetMapping("/probe")
19-
public Mono<ResponseEntity<String>> tlsGradeMetrics(@RequestParam String target) {
20-
return testSsl.rate(target)
21-
.map(this::toPrometheusResponse);
19+
public ResponseEntity<String> tlsGradeMetrics(@RequestParam String target) {
20+
if (!testSsl.isCurrentlyRating(target)) {
21+
return toPrometheusResponse(testSsl.rate(target));
22+
} else {
23+
return ResponseEntity.noContent().build();
24+
}
2225
}
2326

2427
ResponseEntity<String> toPrometheusResponse(TlsGrade grade) {

src/main/java/io/ping7/tlsgradeexporter/TlsGradeExporterApplication.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
import org.springframework.boot.SpringApplication;
44
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
import org.springframework.cache.annotation.EnableCaching;
56

67
@SpringBootApplication
8+
@EnableCaching
79
public class TlsGradeExporterApplication {
810

911
public static void main(String[] args) {

src/main/resources/application.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
spring:
22
main:
33
banner-mode: off
4+
cache:
5+
cache-names: "targets"
6+
caffeine:
7+
spec: "maximumSize=256,expireAfterWrite=10m"
48

59
server:
610
port : 9218

0 commit comments

Comments
 (0)