]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-16227 changed generation of tokens in sonarqube to include identifier
authorLukasz Jarocki <lukasz.jarocki@sonarsource.com>
Tue, 5 Apr 2022 10:33:05 +0000 (12:33 +0200)
committersonartech <sonartech@sonarsource.com>
Tue, 5 Apr 2022 20:03:16 +0000 (20:03 +0000)
server/sonar-webserver-auth/src/main/java/org/sonar/server/usertoken/TokenGenerator.java
server/sonar-webserver-auth/src/main/java/org/sonar/server/usertoken/TokenGeneratorImpl.java
server/sonar-webserver-auth/src/main/java/org/sonar/server/usertoken/TokenType.java [new file with mode: 0644]
server/sonar-webserver-auth/src/test/java/org/sonar/server/usertoken/TokenGeneratorImplTest.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/TokenAction.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/TokenRenewAction.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/usertoken/ws/GenerateAction.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/badge/ws/TokenActionTest.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/badge/ws/TokenRenewActionTest.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/usertoken/ws/GenerateActionTest.java

index 8891969dea3c8038692d2150a10cfbedd9d6d8c9..b41644530bf4f1a21929a511674dc11bc6f4319e 100644 (file)
@@ -35,7 +35,7 @@ public interface TokenGenerator {
    * must not contain colon character ":".
    *
    */
-  String generate();
+  String generate(TokenType tokenType);
 
   /**
    * Hash a token.<br/>
index 01e0d8f5534577eab64a33f13104ba673239c7fd..235a2fb0285b061e2dab0b2abdb9a69f09f4ce1b 100644 (file)
@@ -24,12 +24,19 @@ import org.apache.commons.codec.binary.Hex;
 import org.apache.commons.codec.digest.DigestUtils;
 
 public class TokenGeneratorImpl implements TokenGenerator {
+
+  private static final String SONARQUBE_TOKEN_PREFIX = "sq";
+
   @Override
-  public String generate() {
+  public String generate(TokenType tokenType) {
     SecureRandom random = new SecureRandom();
-    byte[] bytes = new byte[20];
-    random.nextBytes(bytes);
-    return Hex.encodeHexString(bytes);
+    byte[] randomBytes = new byte[20];
+    random.nextBytes(randomBytes);
+    return buildIdentifiablePartOfToken(tokenType) + Hex.encodeHexString(randomBytes);
+  }
+
+  private static String buildIdentifiablePartOfToken(TokenType tokenType) {
+    return SONARQUBE_TOKEN_PREFIX + tokenType.getIdentifier() + "_";
   }
 
   @Override
diff --git a/server/sonar-webserver-auth/src/main/java/org/sonar/server/usertoken/TokenType.java b/server/sonar-webserver-auth/src/main/java/org/sonar/server/usertoken/TokenType.java
new file mode 100644 (file)
index 0000000..8251bc8
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.usertoken;
+
+public enum TokenType {
+  USER_TOKEN("u");
+
+  private final String identifier;
+
+  TokenType(String identifier) {
+    this.identifier = identifier;
+  }
+
+  public String getIdentifier() {
+    return identifier;
+  }
+}
index 3469191331e195a52b32ec972ce2c7bd3d3ace65..2a45c30a4a5171c8f60eec444c51f3ddc6b448ec 100644 (file)
@@ -24,23 +24,30 @@ import org.junit.Test;
 import static org.assertj.core.api.Assertions.assertThat;
 
 public class TokenGeneratorImplTest {
-  TokenGeneratorImpl underTest = new TokenGeneratorImpl();
+  private TokenGeneratorImpl underTest = new TokenGeneratorImpl();
 
   @Test
   public void generate_different_tokens() {
     // this test is not enough to ensure that generated strings are unique,
     // but it still does a simple and stupid verification
-    String firstToken = underTest.generate();
-    String secondToken = underTest.generate();
+    String firstToken = underTest.generate(TokenType.USER_TOKEN);
+    String secondToken = underTest.generate(TokenType.USER_TOKEN);
 
     assertThat(firstToken)
       .isNotEqualTo(secondToken)
-      .hasSize(40);
+      .hasSize(44);
+  }
+
+  @Test
+  public void generate_tokenShouldHaveSonarQubePrefix() {
+    String token = underTest.generate(TokenType.USER_TOKEN);
+
+    assertThat(token).matches("squ_.*");
   }
 
   @Test
   public void token_does_not_contain_colon() {
-    assertThat(underTest.generate()).doesNotContain(":");
+    assertThat(underTest.generate(TokenType.USER_TOKEN)).doesNotContain(":");
   }
 
   @Test
index 1c46bf86ecfea21721cb991b4911577ba35c3ed8..6298e21679a9224d9ad1019ab7a44c118fdb5fe4 100644 (file)
@@ -31,6 +31,7 @@ import org.sonar.db.project.ProjectDto;
 import org.sonar.db.project.ProjectBadgeTokenDto;
 import org.sonar.server.user.UserSession;
 import org.sonar.server.usertoken.TokenGenerator;
+import org.sonar.server.usertoken.TokenType;
 import org.sonarqube.ws.ProjectBadgeToken.TokenWsResponse;
 
 import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
@@ -79,7 +80,8 @@ public class TokenAction implements ProjectBadgesWsAction {
       ProjectBadgeTokenDto projectBadgeTokenDto = dbClient.projectBadgeTokenDao().selectTokenByProject(dbSession, projectDto);
 
       if (projectBadgeTokenDto == null) {
-        projectBadgeTokenDto = dbClient.projectBadgeTokenDao().insert(dbSession, tokenGenerator.generate(), projectDto, userSession.getUuid(), userSession.getLogin());
+        projectBadgeTokenDto = dbClient.projectBadgeTokenDao().insert(dbSession, tokenGenerator.generate(TokenType.USER_TOKEN),
+          projectDto, userSession.getUuid(), userSession.getLogin());
         dbSession.commit();
       }
 
index 777b147da28e97f9c0616b7cb7b7fe0a1a3293a0..23905c9d668867ae4535d3f211e8663b6a9103f3 100644 (file)
@@ -29,6 +29,7 @@ import org.sonar.db.DbSession;
 import org.sonar.db.project.ProjectDto;
 import org.sonar.server.user.UserSession;
 import org.sonar.server.usertoken.TokenGenerator;
+import org.sonar.server.usertoken.TokenType;
 
 import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
 
@@ -72,7 +73,7 @@ public class TokenRenewAction implements ProjectBadgesWsAction {
 
       ProjectDto projectDto = dbClient.projectDao().selectProjectByKey(dbSession, projectKey).orElseThrow(() -> new IllegalArgumentException("project not found"));
       userSession.checkProjectPermission(UserRole.ADMIN, projectDto);
-      String newGeneratedToken = tokenGenerator.generate();
+      String newGeneratedToken = tokenGenerator.generate(TokenType.USER_TOKEN);
       dbClient.projectBadgeTokenDao().upsert(dbSession, newGeneratedToken, projectDto, userSession.getUuid(), userSession.getLogin());
       dbSession.commit();
     }
index f031a9de61d139933c82df44c3ea79584d075cf4..8f79de5619a42f7a7e74a400445ec8b499059f94 100644 (file)
@@ -29,6 +29,7 @@ import org.sonar.db.user.UserDto;
 import org.sonar.db.user.UserTokenDto;
 import org.sonar.server.exceptions.ServerException;
 import org.sonar.server.usertoken.TokenGenerator;
+import org.sonar.server.usertoken.TokenType;
 import org.sonarqube.ws.UserTokens;
 import org.sonarqube.ws.UserTokens.GenerateWsResponse;
 
@@ -90,7 +91,7 @@ public class GenerateAction implements UserTokensWsAction {
       UserDto user = userTokenSupport.getUser(dbSession, request);
       checkTokenDoesNotAlreadyExists(dbSession, user, name);
 
-      String token = tokenGenerator.generate();
+      String token = tokenGenerator.generate(TokenType.USER_TOKEN);
       String tokenHash = hashToken(dbSession, token);
       UserTokenDto userTokenDto = insertTokenInDb(dbSession, user, name, tokenHash);
       return buildResponse(userTokenDto, token, user);
index aaf65087c8a33243727faaf51a0f221d4d55eddb..46fe9733d4b56175923a7679b8a3f43e1099719b 100644 (file)
@@ -29,6 +29,7 @@ import org.sonar.db.component.ComponentDto;
 import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.tester.UserSessionRule;
 import org.sonar.server.usertoken.TokenGenerator;
+import org.sonar.server.usertoken.TokenType;
 import org.sonar.server.ws.TestRequest;
 import org.sonar.server.ws.TestResponse;
 import org.sonar.server.ws.WsActionTester;
@@ -73,7 +74,7 @@ public class TokenActionTest {
   public void should_generate_token() {
     ComponentDto project = db.components().insertPrivateProject();
     userSession.logIn().addProjectPermission(UserRole.USER, project);
-    when(tokenGenerator.generate()).thenReturn("generated_token");
+    when(tokenGenerator.generate(TokenType.USER_TOKEN)).thenReturn("generated_token");
 
     TestResponse response = ws.newRequest().setParam("project", project.getKey()).execute();
 
@@ -84,14 +85,14 @@ public class TokenActionTest {
   public void should_reuse_generated_token() {
     ComponentDto project = db.components().insertPrivateProject();
     userSession.logIn().addProjectPermission(UserRole.USER, project);
-    when(tokenGenerator.generate()).thenReturn("generated_token");
+    when(tokenGenerator.generate(TokenType.USER_TOKEN)).thenReturn("generated_token");
 
     // first call, generating the token
     TestResponse firstResponse = ws.newRequest().setParam("project", project.getKey()).execute();
     firstResponse.assertJson("{\"token\":\"generated_token\"}");
 
     // 2nd call, reusing the existing token
-    when(tokenGenerator.generate()).thenReturn("never_generated_token");
+    when(tokenGenerator.generate(TokenType.USER_TOKEN)).thenReturn("never_generated_token");
     TestResponse secondResponse = ws.newRequest().setParam("project", project.getKey()).execute();
 
     secondResponse.assertJson("{\"token\":\"generated_token\"}");
index f070742cd9fc70db2aea3549a5bd2f4fd08d17c5..65b2ad863253897d55d9c50cb761d3404cb5b674 100644 (file)
@@ -33,6 +33,7 @@ import org.sonar.db.project.ProjectDto;
 import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.tester.UserSessionRule;
 import org.sonar.server.usertoken.TokenGenerator;
+import org.sonar.server.usertoken.TokenType;
 import org.sonar.server.ws.TestRequest;
 import org.sonar.server.ws.TestResponse;
 import org.sonar.server.ws.WsActionTester;
@@ -86,7 +87,7 @@ public class TokenRenewActionTest {
   public void should_add_token_when_no_token_yet_and_return_204() {
     ProjectDto project = db.components().insertPrivateProjectDto();
     userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
-    when(tokenGenerator.generate()).thenReturn("generated_token");
+    when(tokenGenerator.generate(TokenType.USER_TOKEN)).thenReturn("generated_token");
 
     TestResponse response = ws.newRequest().setParam("project", project.getKey()).execute();
 
@@ -100,7 +101,7 @@ public class TokenRenewActionTest {
   public void should_replace_existing_token_when__token_already_present_and_update_update_at() {
     ProjectDto project = db.components().insertPrivateProjectDto();
     userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
-    when(tokenGenerator.generate()).thenReturn("generated_token");
+    when(tokenGenerator.generate(TokenType.USER_TOKEN)).thenReturn("generated_token");
 
     ws.newRequest().setParam("project", project.getKey()).execute(); //inserting first token with updated at 1000
 
index ad834144e990e6222241f9c6787235c757b8bd11..d000a55914ca205f7aa531acb320d7b720275e7b 100644 (file)
@@ -34,6 +34,7 @@ import org.sonar.server.exceptions.ServerException;
 import org.sonar.server.exceptions.UnauthorizedException;
 import org.sonar.server.tester.UserSessionRule;
 import org.sonar.server.usertoken.TokenGenerator;
+import org.sonar.server.usertoken.TokenType;
 import org.sonar.server.ws.TestRequest;
 import org.sonar.server.ws.WsActionTester;
 import org.sonarqube.ws.MediaTypes;
@@ -64,7 +65,7 @@ public class GenerateActionTest {
 
   @Before
   public void setUp() {
-    when(tokenGenerator.generate()).thenReturn("123456789");
+    when(tokenGenerator.generate(TokenType.USER_TOKEN)).thenReturn("123456789");
     when(tokenGenerator.hash(anyString())).thenReturn("987654321");
   }