Skip to content

Commit d32abbf

Browse files
committed
fix: the tpa token was not being set
Signed-off-by: Ruben Romero Montes <[email protected]>
1 parent 7b551ba commit d32abbf

File tree

9 files changed

+134
-43
lines changed

9 files changed

+134
-43
lines changed

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,11 @@
1313
## Required parameters
1414

1515
- `api.tpa.host` The host of the Trusted Profile Analyzer service. Used as a Vulnerability Provider.
16-
- `api.tpa.token` The TPA token for default authentication to use when the `ex-tpa-token` header is not provided
1716
- `api.snyk.token` Snyk API token for default authentication when the Snyk integration is enabled
1817

1918
### TPA Client Authentication
2019

21-
- `quarkus.oidc-client.tpa.enabled`: Defaults to true. Set to `false` to disable `tpa` authentication
20+
- `quarkus.oidc-client.tpa.enabled`: Defaults to `true`. Set to `false` to disable `tpa` authentication
2221
- `quarkus.oidc-client.tpa.auth-server-url`: Authentication server. Example: https://sso-tpa.example.com/auth/realms/myrealm
2322
- `quarkus.oidc-client.tpa.client-id`: OIDC Client ID
2423
- `quarkus.oidc-client.tpa.credentials.secret`: OIDC Client secret

pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,10 @@
356356
<goal>verify</goal>
357357
</goals>
358358
<configuration>
359+
<includes>
360+
<include>**/*Test.java</include>
361+
<include>**/*IT.java</include>
362+
</includes>
359363
<systemPropertyVariables>
360364
<native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
361365
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>

src/main/java/com/redhat/exhort/integration/providers/tpa/TpaIntegration.java

Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818

1919
package com.redhat.exhort.integration.providers.tpa;
2020

21-
import java.time.Duration;
22-
2321
import org.apache.camel.Exchange;
2422
import org.apache.camel.Message;
2523
import org.apache.camel.builder.AggregationStrategies;
@@ -29,8 +27,6 @@
2927
import com.redhat.exhort.integration.Constants;
3028
import com.redhat.exhort.integration.providers.VulnerabilityProvider;
3129

32-
import io.quarkus.oidc.client.OidcClients;
33-
3430
import jakarta.enterprise.context.ApplicationScoped;
3531
import jakarta.inject.Inject;
3632
import jakarta.ws.rs.HttpMethod;
@@ -40,21 +36,13 @@
4036
@ApplicationScoped
4137
public class TpaIntegration extends EndpointRouteBuilder {
4238

43-
private static final String TPA_CLIENT_TENANT = "tpa";
44-
private static final int TPA_CLIENT_TIMEOUT = 10;
45-
4639
@ConfigProperty(name = "api.tpa.timeout", defaultValue = "60s")
4740
String timeout;
4841

49-
@ConfigProperty(name = "quarkus.oidc-client.tpa.enabled", defaultValue = "true")
50-
boolean tpaEnabled;
51-
5242
@Inject VulnerabilityProvider vulnerabilityProvider;
5343
@Inject TpaResponseHandler responseHandler;
5444
@Inject TpaRequestBuilder requestBuilder;
5545

56-
@Inject OidcClients oidcClients;
57-
5846
@Override
5947
public void configure() throws Exception {
6048
// fmt:off
@@ -75,13 +63,13 @@ public void configure() throws Exception {
7563
.split(body(), AggregationStrategies.beanAllowNull(responseHandler, "aggregateSplit"))
7664
.parallelProcessing()
7765
.transform().method(requestBuilder, "buildRequest")
78-
.process(this::processRequest)
79-
.process(requestBuilder::addAuthentication)
80-
.circuitBreaker()
66+
.circuitBreaker()
8167
.faultToleranceConfiguration()
8268
.timeoutEnabled(true)
8369
.timeoutDuration(timeout)
8470
.end()
71+
.process(this::processRequest)
72+
.process(requestBuilder::addAuthentication)
8573
.to(http("{{api.tpa.host}}"))
8674
.transform(method(responseHandler, "responseToIssues"))
8775
.onFallback()
@@ -140,20 +128,6 @@ private void processRequest(Exchange exchange) {
140128
message.setHeader(Exchange.CONTENT_TYPE, MediaType.APPLICATION_JSON);
141129
message.setHeader(Exchange.HTTP_PATH, Constants.TPA_ANALYZE_PATH);
142130
message.setHeader(Exchange.HTTP_METHOD, HttpMethod.POST);
143-
144-
String token = message.getHeader(Constants.TPA_TOKEN_HEADER, String.class);
145-
if (token == null && !tpaEnabled) {
146-
token = "placeholder";
147-
}
148-
if (token == null) {
149-
token =
150-
oidcClients
151-
.getClient(TPA_CLIENT_TENANT)
152-
.getTokens()
153-
.await()
154-
.atMost(Duration.ofSeconds(TPA_CLIENT_TIMEOUT))
155-
.getAccessToken();
156-
}
157131
}
158132

159133
private void processHealthRequest(Exchange exchange) {

src/main/java/com/redhat/exhort/integration/providers/tpa/TpaRequestBuilder.java

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818

1919
package com.redhat.exhort.integration.providers.tpa;
2020

21+
import java.time.Duration;
2122
import java.util.ArrayList;
2223
import java.util.List;
23-
import java.util.Optional;
2424

2525
import org.apache.camel.Exchange;
2626
import org.eclipse.microprofile.config.inject.ConfigProperty;
@@ -31,18 +31,25 @@
3131
import com.redhat.exhort.integration.Constants;
3232
import com.redhat.exhort.model.DependencyTree;
3333

34+
import io.quarkus.oidc.client.OidcClients;
3435
import io.quarkus.runtime.annotations.RegisterForReflection;
3536

3637
import jakarta.enterprise.context.ApplicationScoped;
38+
import jakarta.inject.Inject;
3739

3840
@ApplicationScoped
3941
@RegisterForReflection
4042
public class TpaRequestBuilder {
4143

44+
@ConfigProperty(name = "quarkus.oidc-client.tpa.enabled", defaultValue = "true")
45+
boolean authEnabled;
46+
47+
@Inject OidcClients oidcClients;
48+
4249
private static final int BULK_SIZE = 128;
4350

44-
@ConfigProperty(name = "api.tpa.token")
45-
Optional<String> defaultToken;
51+
public static final String TPA_CLIENT_TENANT = "tpa";
52+
private static final int TPA_CLIENT_TIMEOUT = 10;
4653

4754
private final ObjectMapper mapper = ObjectMapperProducer.newInstance();
4855

@@ -73,11 +80,20 @@ public List<List<String>> split(DependencyTree tree) {
7380
public void addAuthentication(Exchange exchange) {
7481
var message = exchange.getMessage();
7582
var userToken = message.getHeader(Constants.TPA_TOKEN_HEADER, String.class);
76-
String token = null;
83+
String token;
84+
if (!authEnabled) {
85+
return;
86+
}
7787
if (userToken != null) {
7888
token = userToken;
79-
} else if (defaultToken.isPresent()) {
80-
token = defaultToken.get();
89+
} else {
90+
token =
91+
oidcClients
92+
.getClient(TPA_CLIENT_TENANT)
93+
.getTokens()
94+
.await()
95+
.atMost(Duration.ofSeconds(TPA_CLIENT_TIMEOUT))
96+
.getAccessToken();
8197
}
8298
if (token != null) {
8399
message.setHeader("Authorization", "Bearer " + token);
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Copyright 2023 Red Hat, Inc. and/or its affiliates
3+
* and other contributors as indicated by the @author tags.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
*
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package com.redhat.exhort.extensions;
20+
21+
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
22+
import static com.github.tomakehurst.wiremock.client.WireMock.containing;
23+
24+
import java.util.HashMap;
25+
import java.util.Map;
26+
27+
public class OidcWiremockExtension extends WiremockExtension {
28+
29+
private static final String CLIENT_ID = "test-tpa-client";
30+
private static final String CLIENT_SECRET = "test-tpa-secret";
31+
32+
@Override
33+
public Map<String, String> start() {
34+
var base = super.start();
35+
36+
stubTpaClientToken();
37+
var oidcConfig = new HashMap<>(base);
38+
39+
oidcConfig.put("keycloak.url", server.baseUrl());
40+
return oidcConfig;
41+
}
42+
43+
protected void stubTpaClientToken() {
44+
server.stubFor(
45+
com.github.tomakehurst.wiremock.client.WireMock.post("/auth/realms/tpa/token")
46+
.withBasicAuth(CLIENT_ID, CLIENT_SECRET)
47+
.withHeader(
48+
"Content-Type",
49+
com.github.tomakehurst.wiremock.client.WireMock.equalTo(
50+
"application/x-www-form-urlencoded"))
51+
.withRequestBody(containing("grant_type=client_credentials"))
52+
.willReturn(
53+
aResponse()
54+
.withStatus(200)
55+
.withHeader("Content-Type", "application/json")
56+
.withBody(
57+
String.format(
58+
"{\"access_token\":\"%s\",\"token_type\":\"Bearer\",\"expires_in\":300}",
59+
TPA_TOKEN))));
60+
61+
String openIdConfigJson =
62+
String.format(
63+
"""
64+
{
65+
"jwks_uri": "%1$s/auth/realms/tpa/protocol/openid-connect/certs",
66+
"token_introspection_endpoint": "%1$s/auth/realms/tpa/protocol/openid-connect/token/introspect",
67+
"authorization_endpoint": "%1$s/auth/realms/tpa",
68+
"userinfo_endpoint": "%1$s/auth/realms/tpa/protocol/openid-connect/userinfo",
69+
"token_endpoint": "%1$s/auth/realms/tpa/token",
70+
"issuer" : "https://server.example.com",
71+
"introspection_endpoint": "%1$s/auth/realms/tpa/protocol/openid-connect/token/introspect",
72+
"end_session_endpoint": "%1$s/auth/realms/tpa/protocol/openid-connect/end-session"
73+
}
74+
""",
75+
server.baseUrl());
76+
77+
server.stubFor(
78+
com.github.tomakehurst.wiremock.client.WireMock.get(
79+
"/realms/tpa/.well-known/openid-configuration")
80+
.willReturn(
81+
aResponse()
82+
.withStatus(200)
83+
.withHeader("Content-Type", "application/json")
84+
.withBody(openIdConfigJson)));
85+
}
86+
}

src/test/java/com/redhat/exhort/extensions/WiremockExtension.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public class WiremockExtension implements QuarkusTestResourceLifecycleManager {
3131
public static final String SNYK_TOKEN = "snyk-token-xyz";
3232
public static final String TPA_TOKEN = "tpa-token-abc";
3333

34-
private final WireMockServer server = new WireMockServer(options().dynamicPort());
34+
final WireMockServer server = new WireMockServer(options().dynamicPort());
3535

3636
@Override
3737
public Map<String, String> start() {
@@ -43,8 +43,7 @@ public Map<String, String> start() {
4343
"api.trustedcontent.host", server.baseUrl(),
4444
"api.ossindex.host", server.baseUrl(),
4545
"api.onguard.host", server.baseUrl(),
46-
"api.tpa.host", server.baseUrl(),
47-
"api.tpa.token", TPA_TOKEN);
46+
"api.tpa.host", server.baseUrl());
4847
}
4948

5049
@Override

src/test/java/com/redhat/exhort/integration/AbstractAnalysisTest.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,9 @@ public abstract class AbstractAnalysisTest {
9191

9292
@AfterEach
9393
void resetMock() {
94-
server.resetAll();
94+
if (server != null) {
95+
server.resetAll();
96+
}
9597
}
9698

9799
protected void assertJson(String expectedFile, String currentBody) {
@@ -443,7 +445,8 @@ protected void stubTpaTokenRequests() {
443445
get(urlPathEqualTo(Constants.TPA_TOKEN_PATH))
444446
.withQueryParam("limit", equalTo("0"))
445447
.willReturn(aResponse().withStatus(401)));
446-
// Default request
448+
449+
// Accepted tokens
447450
server.stubFor(
448451
get(urlPathEqualTo(Constants.TPA_TOKEN_PATH))
449452
.withHeader(
@@ -455,12 +458,14 @@ protected void stubTpaTokenRequests() {
455458
.withStatus(200)
456459
.withHeader(Exchange.CONTENT_TYPE, MediaType.APPLICATION_JSON)
457460
.withBodyFile("tpa/empty_report.json")));
461+
458462
// Internal Error
459463
server.stubFor(
460464
get(urlPathEqualTo(Constants.TPA_TOKEN_PATH))
461465
.withHeader(Constants.AUTHORIZATION_HEADER, equalTo("Bearer " + ERROR_TOKEN))
462466
.withQueryParam("limit", equalTo("0"))
463467
.willReturn(aResponse().withStatus(500).withBody("This is an example error")));
468+
464469
// Invalid token
465470
server.stubFor(
466471
get(urlPathEqualTo(Constants.TPA_TOKEN_PATH))

src/test/java/com/redhat/exhort/integration/AnalysisTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,17 @@
5757
import com.redhat.exhort.api.v4.DependencyReport;
5858
import com.redhat.exhort.api.v4.Scanned;
5959
import com.redhat.exhort.api.v4.SourceSummary;
60+
import com.redhat.exhort.extensions.OidcWiremockExtension;
6061

62+
import io.quarkus.test.common.QuarkusTestResource;
6163
import io.quarkus.test.junit.QuarkusTest;
6264

6365
import jakarta.ws.rs.core.MediaType;
6466
import jakarta.ws.rs.core.Response;
6567
import jakarta.ws.rs.core.Response.Status;
6668

6769
@QuarkusTest
70+
@QuarkusTestResource(OidcWiremockExtension.class)
6871
public class AnalysisTest extends AbstractAnalysisTest {
6972

7073
private static final String CYCLONEDX = "cyclonedx";

src/test/resources/application.properties

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ telemetry.disabled=true
44
api.ossindex.disabled=false
55
api.snyk.disabled=false
66
api.tpa.disabled=false
7-
quarkus.oidc-client.tpa.enabled=false
87
quarkus.hibernate-orm.persistence-xml.ignore=true
98
quarkus.keycloak.devservices.enabled=false
109
quarkus.datasource.devservices.enabled=false
@@ -13,3 +12,9 @@ quarkus.datasource.jdbc.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
1312
quarkus.hibernate-orm.database.generation=drop-and-create
1413
quarkus.flyway.enabled=false
1514
quarkus.hibernate-orm.sql-load-script=db/h2/V2__insert_data.sql
15+
16+
# TPA OIDC Client Configuration for testing
17+
quarkus.oidc-client.tpa.auth-server-url=${keycloak.url}/realms/tpa
18+
quarkus.oidc-client.tpa.client-id=test-tpa-client
19+
quarkus.oidc-client.tpa.credentials.secret=test-tpa-secret
20+
quarkus.oidc-client.tpa.grant.type=client

0 commit comments

Comments
 (0)