Skip to content

Commit ca088d6

Browse files
Merge remote-tracking branch 'origin/master' into release/current
2 parents e3b550c + e025eb6 commit ca088d6

38 files changed

+622
-93
lines changed

openbas-api/pom.xml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<parent>
77
<groupId>io.openbas</groupId>
88
<artifactId>openbas-platform</artifactId>
9-
<version>1.18.3</version>
9+
<version>1.18.4</version>
1010
</parent>
1111

1212
<artifactId>openbas-api</artifactId>
@@ -49,7 +49,7 @@
4949
<dependency>
5050
<groupId>io.openbas</groupId>
5151
<artifactId>openbas-framework</artifactId>
52-
<version>1.18.3</version>
52+
<version>1.18.4</version>
5353
</dependency>
5454
<dependency>
5555
<groupId>co.elastic.clients</groupId>
@@ -234,6 +234,12 @@
234234
</exclusion>
235235
</exclusions>
236236
</dependency>
237+
<dependency>
238+
<groupId>org.mock-server</groupId>
239+
<artifactId>mockserver-netty</artifactId>
240+
<version>5.15.0</version>
241+
<scope>test</scope>
242+
</dependency>
237243
<dependency>
238244
<groupId>org.springframework.security</groupId>
239245
<artifactId>spring-security-test</artifactId>

openbas-api/src/main/java/io/openbas/authorisation/TlsConfig.java

Lines changed: 81 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import java.nio.file.Path;
99
import java.nio.file.Paths;
1010
import java.security.KeyStore;
11+
import java.security.KeyStoreException;
12+
import java.security.NoSuchAlgorithmException;
1113
import java.security.cert.CertificateException;
1214
import java.security.cert.CertificateFactory;
1315
import java.security.cert.X509Certificate;
@@ -41,7 +43,7 @@ private Set<String> getFilesPaths(String dir) {
4143
.filter(path -> path.endsWith(".pem"))
4244
.collect(Collectors.toSet());
4345
} catch (Exception e) {
44-
log.info("No extra trusted certificate found in " + dir);
46+
log.info("No extra trusted certificate found in {}", dir, e);
4547
return new HashSet<>();
4648
}
4749
}
@@ -73,14 +75,8 @@ private List<X509Certificate> getExtraCerts(Set<String> filesPaths)
7375
return extraCerts;
7476
}
7577

76-
/**
77-
* Get and set extra trusted certificates to the java trust manager
78-
*
79-
* @return tls context with our extra trusted certificates
80-
* @throws Exception exception
81-
*/
82-
@Bean
83-
public X509TrustManager tlsContextCustom() throws Exception {
78+
private X509TrustManager getDefaultTrustManager()
79+
throws NoSuchAlgorithmException, KeyStoreException {
8480
TrustManagerFactory trustManagerFactory =
8581
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
8682
trustManagerFactory.init((KeyStore) null);
@@ -93,42 +89,91 @@ public X509TrustManager tlsContextCustom() throws Exception {
9389
}
9490
}
9591

92+
return defaultX509CertificateTrustManager;
93+
}
94+
95+
private Optional<X509TrustManager> getAdditionalTrustManager()
96+
throws NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException {
9697
Set<String> filesPaths = getFilesPaths(openBASConfig.getExtraTrustedCertsDir());
9798

99+
// early return; if there aren't any extra certs
100+
// don't bother building a trust manager
101+
if (filesPaths.isEmpty()) {
102+
return Optional.empty();
103+
}
104+
98105
List<X509Certificate> extraCerts = getExtraCerts(filesPaths);
99106

100-
X509TrustManager finalDefaultTm = defaultX509CertificateTrustManager;
107+
// in-memory keystore
108+
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
109+
keyStore.load(null, null);
110+
for (X509Certificate cert : extraCerts) {
111+
keyStore.setCertificateEntry(cert.getSubjectX500Principal().getName(), cert);
112+
}
101113

102-
X509TrustManager wrapper =
103-
new X509TrustManager() {
104-
private X509Certificate[] mergeCertificates() {
105-
ArrayList<X509Certificate> resultingCerts = new ArrayList<>();
106-
resultingCerts.addAll(Arrays.asList(finalDefaultTm.getAcceptedIssuers()));
107-
resultingCerts.addAll(extraCerts);
108-
return resultingCerts.toArray(new X509Certificate[resultingCerts.size()]);
109-
}
114+
TrustManagerFactory trustManagerFactory =
115+
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
116+
trustManagerFactory.init(keyStore);
110117

111-
@Override
112-
public X509Certificate[] getAcceptedIssuers() {
113-
return mergeCertificates();
114-
}
118+
return Arrays.stream(trustManagerFactory.getTrustManagers())
119+
.filter(tm -> tm instanceof X509TrustManager)
120+
.map(tm -> Optional.of((X509TrustManager) tm))
121+
.findFirst()
122+
.orElse(Optional.empty());
123+
}
115124

116-
@Override
117-
public void checkServerTrusted(X509Certificate[] chain, String authType) {
118-
try {
119-
finalDefaultTm.checkServerTrusted(chain, authType);
120-
} catch (CertificateException e) {
121-
log.error("Error occurred during checkServerTrusted", e);
122-
}
123-
}
125+
/**
126+
* Get and set extra trusted certificates to the java trust manager
127+
*
128+
* @return tls context with our extra trusted certificates
129+
* @throws Exception exception
130+
*/
131+
@Bean
132+
public X509TrustManager tlsContextCustom() throws Exception {
133+
X509TrustManager defaultX509CertificateTrustManager = getDefaultTrustManager();
134+
Optional<X509TrustManager> additionalTrustManager = getAdditionalTrustManager();
135+
136+
return new X509TrustManager() {
137+
private X509Certificate[] mergeCertificates() {
138+
ArrayList<X509Certificate> resultingCerts =
139+
new ArrayList<>(Arrays.asList(defaultX509CertificateTrustManager.getAcceptedIssuers()));
140+
additionalTrustManager.ifPresent(
141+
tm -> resultingCerts.addAll(Arrays.asList(tm.getAcceptedIssuers())));
142+
return resultingCerts.toArray(new X509Certificate[0]);
143+
}
144+
145+
@Override
146+
public X509Certificate[] getAcceptedIssuers() {
147+
return mergeCertificates();
148+
}
124149

125-
@Override
126-
public void checkClientTrusted(X509Certificate[] chain, String authType)
127-
throws CertificateException {
128-
finalDefaultTm.checkClientTrusted(mergeCertificates(), authType);
150+
@Override
151+
public void checkServerTrusted(X509Certificate[] chain, String authType)
152+
throws CertificateException {
153+
try {
154+
defaultX509CertificateTrustManager.checkServerTrusted(chain, authType);
155+
} catch (Exception e) {
156+
if (additionalTrustManager.isPresent()) {
157+
additionalTrustManager.get().checkServerTrusted(chain, authType);
158+
} else {
159+
throw e;
129160
}
130-
};
161+
}
162+
}
131163

132-
return wrapper;
164+
@Override
165+
public void checkClientTrusted(X509Certificate[] chain, String authType)
166+
throws CertificateException {
167+
try {
168+
defaultX509CertificateTrustManager.checkClientTrusted(chain, authType);
169+
} catch (Exception e) {
170+
if (additionalTrustManager.isPresent()) {
171+
additionalTrustManager.get().checkClientTrusted(chain, authType);
172+
} else {
173+
throw e;
174+
}
175+
}
176+
}
177+
};
133178
}
134179
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package io.openbas.migration;
2+
3+
import java.sql.Connection;
4+
import java.sql.Statement;
5+
import org.flywaydb.core.api.migration.BaseJavaMigration;
6+
import org.flywaydb.core.api.migration.Context;
7+
import org.springframework.stereotype.Component;
8+
9+
@Component
10+
public class V4_11__Payload_Expectations extends BaseJavaMigration {
11+
12+
@Override
13+
public void migrate(Context context) throws Exception {
14+
Connection connection = context.getConnection();
15+
try (Statement statement = connection.createStatement()) {
16+
statement.execute(
17+
"""
18+
ALTER TABLE payloads ADD COLUMN payload_expectations text[];
19+
""");
20+
}
21+
}
22+
}

openbas-api/src/main/java/io/openbas/migration/V4_11__List_Widget_config_update.java renamed to openbas-api/src/main/java/io/openbas/migration/V4_12__List_Widget_config_update.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import org.springframework.stereotype.Component;
88

99
@Component
10-
public class V4_11__List_Widget_config_update extends BaseJavaMigration {
10+
public class V4_12__List_Widget_config_update extends BaseJavaMigration {
1111

1212
@Override
1313
public void migrate(Context context) throws Exception {

openbas-api/src/main/java/io/openbas/migration/V4_12__Update_Role_table.java renamed to openbas-api/src/main/java/io/openbas/migration/V4_13__Update_Role_table.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import org.springframework.stereotype.Component;
88

99
@Component
10-
public class V4_12__Update_Role_table extends BaseJavaMigration {
10+
public class V4_13__Update_Role_table extends BaseJavaMigration {
1111

1212
@Override
1313
public void migrate(Context context) throws Exception {

openbas-api/src/main/java/io/openbas/rest/payload/form/PayloadCreateInput.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.fasterxml.jackson.annotation.JsonProperty;
66
import io.openbas.database.model.*;
77
import io.openbas.database.model.Endpoint.PLATFORM_TYPE;
8+
import io.openbas.database.model.InjectExpectation.EXPECTATION_TYPE;
89
import io.openbas.database.model.Payload.PAYLOAD_SOURCE;
910
import io.openbas.database.model.Payload.PAYLOAD_STATUS;
1011
import io.swagger.v3.oas.annotations.media.DiscriminatorMapping;
@@ -62,6 +63,11 @@ public class PayloadCreateInput {
6263
private Payload.PAYLOAD_EXECUTION_ARCH executionArch =
6364
Payload.PAYLOAD_EXECUTION_ARCH.ALL_ARCHITECTURES;
6465

66+
@JsonProperty("payload_expectations")
67+
@NotNull
68+
private EXPECTATION_TYPE[] expectations =
69+
new EXPECTATION_TYPE[] {EXPECTATION_TYPE.PREVENTION, EXPECTATION_TYPE.DETECTION};
70+
6571
@JsonProperty("payload_description")
6672
private String description;
6773

openbas-api/src/main/java/io/openbas/rest/payload/form/PayloadUpdateInput.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import com.fasterxml.jackson.annotation.JsonProperty;
66
import io.openbas.database.model.Endpoint.PLATFORM_TYPE;
7+
import io.openbas.database.model.InjectExpectation;
78
import io.openbas.database.model.Payload;
89
import io.openbas.database.model.PayloadArgument;
910
import io.openbas.database.model.PayloadPrerequisite;
@@ -42,6 +43,13 @@ public class PayloadUpdateInput {
4243
private Payload.PAYLOAD_EXECUTION_ARCH executionArch =
4344
Payload.PAYLOAD_EXECUTION_ARCH.ALL_ARCHITECTURES;
4445

46+
@JsonProperty("payload_expectations")
47+
@NotNull
48+
private InjectExpectation.EXPECTATION_TYPE[] expectations =
49+
new InjectExpectation.EXPECTATION_TYPE[] {
50+
InjectExpectation.EXPECTATION_TYPE.PREVENTION, InjectExpectation.EXPECTATION_TYPE.DETECTION
51+
};
52+
4553
@JsonProperty("executable_file")
4654
private String executableFile;
4755

openbas-api/src/main/java/io/openbas/rest/payload/form/PayloadUpsertInput.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@
33
import static io.openbas.config.AppConfig.MANDATORY_MESSAGE;
44

55
import com.fasterxml.jackson.annotation.JsonProperty;
6-
import io.openbas.database.model.Endpoint;
7-
import io.openbas.database.model.Payload;
8-
import io.openbas.database.model.PayloadArgument;
9-
import io.openbas.database.model.PayloadPrerequisite;
6+
import io.openbas.database.model.*;
107
import io.swagger.v3.oas.annotations.media.Schema;
118
import jakarta.validation.constraints.NotBlank;
129
import jakarta.validation.constraints.NotNull;
@@ -48,6 +45,13 @@ public class PayloadUpsertInput {
4845
private Payload.PAYLOAD_EXECUTION_ARCH executionArch =
4946
Payload.PAYLOAD_EXECUTION_ARCH.ALL_ARCHITECTURES;
5047

48+
@JsonProperty("payload_expectations")
49+
@NotNull
50+
private InjectExpectation.EXPECTATION_TYPE[] expectations =
51+
new InjectExpectation.EXPECTATION_TYPE[] {
52+
InjectExpectation.EXPECTATION_TYPE.PREVENTION, InjectExpectation.EXPECTATION_TYPE.DETECTION
53+
};
54+
5155
@JsonProperty("payload_description")
5256
private String description;
5357

openbas-api/src/main/java/io/openbas/rest/payload/service/PayloadService.java

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import io.openbas.injector_contract.ContractTargetedProperty;
3030
import io.openbas.injector_contract.fields.*;
3131
import io.openbas.injectors.openbas.util.OpenBASObfuscationMap;
32+
import io.openbas.model.inject.form.Expectation;
3233
import io.openbas.rest.payload.PayloadUtils;
3334
import jakarta.annotation.Resource;
3435
import jakarta.validation.constraints.NotBlank;
@@ -146,7 +147,7 @@ private Contract buildContract(
146147
true);
147148
ContractAsset assetField = assetField(Multiple);
148149
ContractAssetGroup assetGroupField = assetGroupField(Multiple);
149-
ContractExpectations expectationsField = expectations();
150+
ContractExpectations expectationsField = expectations(payload.getExpectations());
150151
ContractDef builder = contractBuilder();
151152
builder.mandatoryGroup(assetField, assetGroupField);
152153

@@ -184,12 +185,35 @@ private Contract buildContract(
184185
true);
185186
}
186187

187-
private ContractExpectations expectations() {
188-
return expectationsField(
189-
List.of(
190-
this.expectationBuilderService.buildPreventionExpectation(),
191-
this.expectationBuilderService.buildDetectionExpectation(),
192-
this.expectationBuilderService.buildVulnerabilityExpectation()));
188+
private ContractExpectations expectations(InjectExpectation.EXPECTATION_TYPE[] expectationTypes) {
189+
List<Expectation> expectations = new ArrayList<>();
190+
if (expectationTypes.length == 0) {
191+
return expectationsField(
192+
List.of(
193+
this.expectationBuilderService.buildPreventionExpectation(),
194+
this.expectationBuilderService.buildDetectionExpectation()));
195+
} else {
196+
for (InjectExpectation.EXPECTATION_TYPE type : expectationTypes) {
197+
switch (type) {
198+
case TEXT -> expectations.add(this.expectationBuilderService.buildTextExpectation());
199+
case DOCUMENT ->
200+
expectations.add(this.expectationBuilderService.buildDocumentExpectation());
201+
case ARTICLE ->
202+
expectations.add(this.expectationBuilderService.buildArticleExpectation());
203+
case CHALLENGE ->
204+
expectations.add(this.expectationBuilderService.buildChallengeExpectation());
205+
case MANUAL -> expectations.add(this.expectationBuilderService.buildManualExpectation());
206+
case PREVENTION ->
207+
expectations.add(this.expectationBuilderService.buildPreventionExpectation());
208+
case DETECTION ->
209+
expectations.add(this.expectationBuilderService.buildDetectionExpectation());
210+
case VULNERABILITY ->
211+
expectations.add(this.expectationBuilderService.buildVulnerabilityExpectation());
212+
default -> throw new IllegalArgumentException("Unsupported expectation type: " + type);
213+
}
214+
}
215+
return expectationsField(expectations);
216+
}
193217
}
194218

195219
public Payload duplicate(@NotBlank final String payloadId) {

0 commit comments

Comments
 (0)