Skip to content

Commit

Permalink
smallrye-health as optional dependency (#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
ggrebert authored Feb 3, 2024
1 parent 9e664f8 commit 28023a5
Show file tree
Hide file tree
Showing 10 changed files with 52 additions and 15 deletions.
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,22 +53,34 @@ Or add to you pom.xml directly:
Now that you configured your POM to use the service, now you need to configure which scanner(s) you want to use in `application.properties`:

### ClamAV

[ClamAV](https://www.clamav.net/) is an open source Linux based virus scanning engine.
If you don't set a host `quarkus.antivirus.clamav.host` a DevService will start a ClamAV instance for you on a dynamic free port, so you can test locally during development.

```properties
quarkus.antivirus.clamav.enabled=true
quarkus.antivirus.clamav.health.enabled=true
```

#### ClamAV Health Check

If you are using the `quarkus-smallrye-health` extension,
quarkus-vault can add a readiness health check to validate the connection to the ClamAV server.

If enabled (by default) and the extension is present,
when you access the `/q/health/ready` endpoint of your application you will have information about the connection validation status.

You can disable this behavior by setting the property `quarkus.antivirus.clamav.health.enabled` to `false` in your application.properties.

### VirusTotal

[VirusTotal](https://www.virustotal.com/) is a REST API that analyses suspicious files to detect malware using over 70 antivirus scanners. VirusTotal checks the hash of a file to see if it has been scanned and what the results are. You can set the threshold of how many of the 70+ engines you want to report the file as malicious before you consider it a malicious file using the `minimum-votes` property.

```properties
quarkus.antivirus.virustotal.enabled=true
quarkus.antivirus.virustotal.key=<YOUR API KEY>
quarkus.antivirus.virustotal.minimum-votes=1
```

## Usage

Simply inject the `Antivirus` service, and it will run the scan against all configured services. It works against `InputStream` so it can be used in any Quarkus application it is not constrained to REST applications only.
Expand Down
7 changes: 6 additions & 1 deletion deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-health-deployment</artifactId>
<artifactId>quarkus-smallrye-health-spi</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
Expand All @@ -49,6 +49,11 @@
<artifactId>quarkus-junit5-internal</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.smallrye.health.deployment.spi.HealthBuildItem;

/**
* Main processor for the Antivirus extension.
Expand All @@ -29,12 +30,10 @@ void registerBeans(BuildProducer<AdditionalBeanBuildItem> beans,
.addBeanClasses(VirusTotalEngine.class)
.addBeanClasses(Antivirus.class)
.build());
}

// health check
if (buildConfig.healthEnabled()) {
beans.produce(AdditionalBeanBuildItem.builder().setUnremovable()
.addBeanClasses(ClamAVHealthCheck.class)
.build());
}
@BuildStep
HealthBuildItem addHealthCheck(ClamAVBuildConfig buildConfig) {
return new HealthBuildItem(ClamAVHealthCheck.class.getName(), buildConfig.healthEnabled());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class AntivirusDevModeTest {
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class));

@Test
public void writeYourOwnDevModeTest() {
void writeYourOwnDevModeTest() {
// Write your dev mode tests here - see the testing extension guide https://quarkus.io/guides/writing-extensions#testing-hot-reload for more information
Assertions.assertTrue(true, "Add dev mode assertions to " + getClass().getName());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;
import io.restassured.RestAssured;

public class AntivirusTest {

Expand All @@ -16,8 +17,13 @@ public class AntivirusTest {
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class));

@Test
public void writeYourOwnUnitTest() {
void writeYourOwnUnitTest() {
// Write your unit tests here - see the testing extension guide https://quarkus.io/guides/writing-extensions#testing-extensions for more information
Assertions.assertTrue(true, "Add some assertions to " + getClass().getName());
}

@Test
void testHealthServlet() {
RestAssured.when().get("/q/health").then().statusCode(404);
}
}
4 changes: 4 additions & 0 deletions integration-tests/imperative/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-openapi</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-health</artifactId>
</dependency>
<dependency>
<groupId>io.quarkiverse.antivirus</groupId>
<artifactId>quarkus-antivirus</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ quarkus.http.limits.max-body-size=200m
quarkus.antivirus.clamav.enabled=true
quarkus.antivirus.clamav.chunk-size=30000
quarkus.antivirus.clamav.devservice.fresh-clam=false
quarkus.antivirus.clamav.health.enabled=true
# VirusTotal
quarkus.antivirus.virustotal.enabled=true
quarkus.antivirus.virustotal.key=<YOUR KEY HERE>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
public class ClamAVResourceTest {

@Test
public void testValidFile() {
void testValidFile() {
given()
.when().get("/clamav/valid")
.then()
Expand All @@ -27,7 +27,7 @@ public void testValidFile() {
}

@Test
public void testInvalidFile() {
void testInvalidFile() {
RestAssured.defaultParser = Parser.TEXT;
Response response = given()
.contentType(ContentType.TEXT)
Expand All @@ -44,4 +44,9 @@ public void testInvalidFile() {
"Scan detected viruses in file 'invalid.txt'! Virus scanner message = stream: Win.Test.EICAR_HDB-1 FOUND"));
}
}

@Test
void testHealthServlet() {
RestAssured.when().get("/q/health").then().statusCode(200);
}
}
1 change: 1 addition & 0 deletions runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-health</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>jakarta.xml.bind</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,21 @@ public class ClamAVHealthCheck implements HealthCheck {

@Inject
ClamAVEngine engine;

@Inject
ClamAVRuntimeConfig config;

@Override
public HealthCheckResponse call() {
final String server = String.format("%s:%s", config.host(), config.port());
final String host = config.host().orElseThrow();
final String server = String.format("%s:%s", host, config.port());

HealthCheckResponseBuilder responseBuilder = HealthCheckResponse.named("ClamAV Daemon");
responseBuilder = engine.ping() ? responseBuilder.up().withData(server, "UP")

responseBuilder = engine.ping()
? responseBuilder.up().withData(server, "UP")
: responseBuilder.down().withData(server, "DOWN");

return responseBuilder.build();
}
}

0 comments on commit 28023a5

Please sign in to comment.