From bbda64178b9d55524e0651743826323cefa9c26b Mon Sep 17 00:00:00 2001 From: Florian Dreier Date: Fri, 17 Jan 2025 14:49:19 +0100 Subject: [PATCH] TS-41530 Fix Gradle upload to Teamscale --- CHANGELOG.md | 1 + .../test/commons/TeamscaleMockServer.java | 35 +++++++++++++++++++ .../tia/client/DefaultExcludesSystemTest.java | 4 ++- .../com/teamscale/tia/TiaMavenSystemTest.java | 4 ++- .../teamscale/config/ServerConfiguration.kt | 4 +-- .../com/teamscale/TeamscalePluginTest.kt | 1 + 6 files changed, 45 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 362b87da1..cf4149ea1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ We use [semantic versioning](http://semver.org/): - PATCH version when you make backwards compatible bug fixes. # Next version +- [fix] _teamscale-gradle-plugin_: 401 Unauthorized error when trying to upload reports to Teamscale # 34.2.1 - [fix] _agent_: Warning about multiple agents being present is misleading diff --git a/common-system-test/src/main/java/com/teamscale/test/commons/TeamscaleMockServer.java b/common-system-test/src/main/java/com/teamscale/test/commons/TeamscaleMockServer.java index 0d78f4c7c..a4a6af18e 100644 --- a/common-system-test/src/main/java/com/teamscale/test/commons/TeamscaleMockServer.java +++ b/common-system-test/src/main/java/com/teamscale/test/commons/TeamscaleMockServer.java @@ -8,6 +8,7 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; +import java.util.Base64; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -61,6 +62,8 @@ public class TeamscaleMockServer { private List impactedTests; private final List profilerEvents = new ArrayList<>(); private ProfilerConfiguration profilerConfiguration; + private String username = null; + private String accessToken = null; public TeamscaleMockServer(int port) throws IOException { service = Service.ignite(); @@ -78,6 +81,12 @@ public TeamscaleMockServer(int port) throws IOException { } /** Configures the server to accept report uploads and store them within the mock for later retrieval. */ + public TeamscaleMockServer withAuthentication(String username, String accessToken) { + this.username = username; + this.accessToken = accessToken; + return this; + } + public TeamscaleMockServer acceptingReportUploads() { service.post("api/v5.9.0/projects/:projectName/external-analysis/session/auto-create/report", this::handleReport); @@ -122,6 +131,8 @@ public TestwiseCoverageReport parseUploadedTestwiseCoverageReport(int index) thr } private String handleImpactedTests(Request request, Response response) throws IOException { + requireAuthentication(request, response); + collectedUserAgents.add(request.headers("User-Agent")); impactedTestCommits.add(request.queryParams("end-revision") + ", " + request.queryParams("end")); impactedTestRepositories.add(request.queryParams("repository")); @@ -132,6 +143,8 @@ private String handleImpactedTests(Request request, Response response) throws IO } private String handleProfilerRegistration(Request request, Response response) throws JsonProcessingException { + requireAuthentication(request, response); + collectedUserAgents.add(request.headers("User-Agent")); profilerEvents.add( "Profiler registered and requested configuration " + request.queryParams("configuration-id")); @@ -142,18 +155,24 @@ private String handleProfilerRegistration(Request request, Response response) th } private String handleProfilerHeartbeat(Request request, Response response) { + requireAuthentication(request, response); + collectedUserAgents.add(request.headers("User-Agent")); profilerEvents.add("Profiler " + request.params(":profilerId") + " sent heartbeat"); return ""; } private String handleProfilerLogs(Request request, Response response) { + requireAuthentication(request, response); + collectedUserAgents.add(request.headers("User-Agent")); profilerEvents.add("Profiler " + request.params(":profilerId") + " sent logs"); return ""; } private String handleProfilerUnregister(Request request, Response response) { + requireAuthentication(request, response); + collectedUserAgents.add(request.headers("User-Agent")); profilerEvents.add("Profiler " + request.params(":profilerId") + " unregistered"); return "foo"; @@ -164,6 +183,8 @@ public List getProfilerEvents() { } private String handleReport(Request request, Response response) throws IOException, ServletException { + requireAuthentication(request, response); + collectedUserAgents.add(request.headers("User-Agent")); uploadCommits.add(request.queryParams("revision") + ", " + request.queryParams("t")); uploadRepositories.add(request.queryParams("repository")); @@ -189,4 +210,18 @@ public void shutdown() { service.awaitStop(); } + private void requireAuthentication(Request request, Response response) { + if (username != null && accessToken != null) { + String authHeader = request.headers("Authorization"); + if (authHeader == null || !authHeader.equals(buildBasicAuthHeader(username, accessToken))) { + response.status(401); + throw new IllegalArgumentException("Unauthorized"); + } + } + } + + private String buildBasicAuthHeader(String username, String accessToken) { + String credentials = username + ":" + accessToken; + return "Basic " + Base64.getEncoder().encodeToString(credentials.getBytes()); + } } diff --git a/system-tests/default-excludes-test/src/test/java/com/teamscale/tia/client/DefaultExcludesSystemTest.java b/system-tests/default-excludes-test/src/test/java/com/teamscale/tia/client/DefaultExcludesSystemTest.java index 0c98dc807..affe1064a 100644 --- a/system-tests/default-excludes-test/src/test/java/com/teamscale/tia/client/DefaultExcludesSystemTest.java +++ b/system-tests/default-excludes-test/src/test/java/com/teamscale/tia/client/DefaultExcludesSystemTest.java @@ -18,7 +18,9 @@ public void systemTest() throws Exception { System.setProperty("org.eclipse.jetty.util.log.class", "org.eclipse.jetty.util.log.StdErrLog"); System.setProperty("org.eclipse.jetty.LEVEL", "OFF"); - TeamscaleMockServer teamscaleMockServer = new TeamscaleMockServer(SystemTestUtils.TEAMSCALE_PORT).acceptingReportUploads(); + TeamscaleMockServer teamscaleMockServer = new TeamscaleMockServer(SystemTestUtils.TEAMSCALE_PORT) + .withAuthentication("fake", "fake") + .acceptingReportUploads(); new SystemUnderTest().foo(); SystemTestUtils.dumpCoverage(SystemTestUtils.AGENT_PORT); diff --git a/system-tests/tia-maven/src/test/java/com/teamscale/tia/TiaMavenSystemTest.java b/system-tests/tia-maven/src/test/java/com/teamscale/tia/TiaMavenSystemTest.java index 78b55976d..a4593c851 100644 --- a/system-tests/tia-maven/src/test/java/com/teamscale/tia/TiaMavenSystemTest.java +++ b/system-tests/tia-maven/src/test/java/com/teamscale/tia/TiaMavenSystemTest.java @@ -23,7 +23,9 @@ public class TiaMavenSystemTest { @BeforeEach public void startFakeTeamscaleServer() throws Exception { - teamscaleMockServer = new TeamscaleMockServer(SystemTestUtils.TEAMSCALE_PORT).acceptingReportUploads() + teamscaleMockServer = new TeamscaleMockServer(SystemTestUtils.TEAMSCALE_PORT) + .withAuthentication("build", "6lJKEvNHeTxGPhMAi4D84DWqzoSFL1p4") + .acceptingReportUploads() .withImpactedTests("bar/UnitTest/utBla()", "bar/UnitTest/utFoo()", "bar/IntegIT/itBla()", "bar/IntegIT/itFoo()"); } diff --git a/teamscale-gradle-plugin/src/main/kotlin/com/teamscale/config/ServerConfiguration.kt b/teamscale-gradle-plugin/src/main/kotlin/com/teamscale/config/ServerConfiguration.kt index 34e437df0..0bb50aa5b 100644 --- a/teamscale-gradle-plugin/src/main/kotlin/com/teamscale/config/ServerConfiguration.kt +++ b/teamscale-gradle-plugin/src/main/kotlin/com/teamscale/config/ServerConfiguration.kt @@ -30,8 +30,8 @@ data class ServerConfiguration( } fun toClient() = TeamscaleClient( url, - project ?: throw GradleException("Teamscale project name must not be null!"), userName ?: throw GradleException("Teamscale user name must not be null!"), - userAccessToken ?: throw GradleException("Teamscale user access token must not be null!") + userAccessToken ?: throw GradleException("Teamscale user access token must not be null!"), + project ?: throw GradleException("Teamscale project name must not be null!") ) } diff --git a/teamscale-gradle-plugin/src/test/kotlin/com/teamscale/TeamscalePluginTest.kt b/teamscale-gradle-plugin/src/test/kotlin/com/teamscale/TeamscalePluginTest.kt index 825feea1d..766566678 100644 --- a/teamscale-gradle-plugin/src/test/kotlin/com/teamscale/TeamscalePluginTest.kt +++ b/teamscale-gradle-plugin/src/test/kotlin/com/teamscale/TeamscalePluginTest.kt @@ -39,6 +39,7 @@ class TeamscalePluginTest { @BeforeEach fun startFakeTeamscaleServer() { teamscaleMockServer = TeamscaleMockServer(FAKE_TEAMSCALE_PORT) + .withAuthentication("build", "82l1jtkIx6xG7DDG34FLsKhejcHz1cMu") .acceptingReportUploads() .withImpactedTests("com/example/project/JUnit4Test/systemTest") }