changeset 983:ea7a543ecf2f Indore-2017.2.x

TW-50054 introduce server hg path whitelist Hg path from VCS root is used on the server only if it is in whitelist
author Dmitry Neverov <dmitry.neverov@gmail.com>
date Thu, 25 Jan 2018 09:07:17 +0100
parents 4a0ea921c214
children e78734c8fa95 ec20a7691c8b
files mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/Constants.java mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/HgVcsRoot.java mercurial-server/resources/buildServerResources/mercurialSettings.jsp mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgPathProvider.java mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgVcsRootTest.java mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgPathProviderTest.java
diffstat 6 files changed, 57 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/Constants.java	Wed Jan 24 22:02:52 2018 +0100
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/Constants.java	Thu Jan 25 09:07:17 2018 +0100
@@ -45,6 +45,6 @@
   String CUSTOM_CLONE_PATH_ENABLED = "teamcity.hg.customClonePathEnabled";
   String CUSTOM_CLONE_PATH_WHITELIST = "teamcity.hg.customClonePathWhitelist";
   String CUSTOM_CACHES_DIR = "teamcity.hg.customCachesDir";
-  String CUSTOM_HG_PATH_ENABLED = "teamcity.hg.customHgPathEnabled";
+  String CUSTOM_SERVER_HG_PATH_WHITELIST = "teamcity.hg.customServerHgPathWhitelist";
   String CUSTOM_HG_CONFIG_ENABLED = "teamcity.hg.customConfigEnabled";
 }
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/HgVcsRoot.java	Wed Jan 24 22:02:52 2018 +0100
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/HgVcsRoot.java	Thu Jan 25 09:07:17 2018 +0100
@@ -59,7 +59,7 @@
   public HgVcsRoot(@NotNull Map<String, String> vcsRootProperties) {
     myVcsRootProperties = vcsRootProperties;
     myRepository = getProperty(Constants.REPOSITORY_PROP);
-    myHgCommandPath = readHgCommandPath();
+    myHgCommandPath = getProperty(Constants.HG_COMMAND_PATH_PROP);
     myBranchName = getProperty(Constants.BRANCH_NAME_PROP);
     myCustomClonePath = readCustomClonePath();
     myUncompressedTransfer = "true".equals(getProperty(Constants.UNCOMPRESSED_TRANSFER));
@@ -75,14 +75,6 @@
     myUseAgentMirrors = readUseSharedMirrors();
   }
 
-  private String readHgCommandPath() {
-    if (TeamCityProperties.getBooleanOrTrue(Constants.CUSTOM_HG_PATH_ENABLED)) {
-      return getProperty(Constants.HG_COMMAND_PATH_PROP, "hg");
-    } else {
-      return "hg";
-    }
-  }
-
   @NotNull
   private String readCustomHgConfig() {
     if (TeamCityProperties.getBooleanOrTrue(Constants.CUSTOM_HG_CONFIG_ENABLED)) {
@@ -282,4 +274,18 @@
     }
     return false;
   }
+
+  public static boolean isAllowedHgPath(@Nullable String path) {
+    if (StringUtil.isEmptyOrSpaces(path))
+      return false;
+    String whitelist = TeamCityProperties.getProperty(Constants.CUSTOM_SERVER_HG_PATH_WHITELIST);
+    if (StringUtil.isEmpty(whitelist))
+      return false;
+    List<String> paths = StringUtil.split(whitelist, ";");
+    for (String p : paths) {
+      if (p.equals(path))
+        return true;
+    }
+    return false;
+  }
 }
--- a/mercurial-server/resources/buildServerResources/mercurialSettings.jsp	Wed Jan 24 22:02:52 2018 +0100
+++ b/mercurial-server/resources/buildServerResources/mercurialSettings.jsp	Thu Jan 25 09:07:17 2018 +0100
@@ -92,6 +92,7 @@
     <td>
       <props:textProperty name="hgCommandPath" className="longField" />
       <span class="error" id="error_hgCommandPath"></span>
+      <div class="smallNote" style="margin: 0;">The path will be used on TeamCity server only if it is included into whitelist.<bs:help file="Mercurial" anchor="Pathtohgexecutabledetection"/></div>
     </td>
   </tr>
   <tr class="advancedSetting">
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgPathProvider.java	Wed Jan 24 22:02:52 2018 +0100
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgPathProvider.java	Thu Jan 25 09:07:17 2018 +0100
@@ -33,23 +33,12 @@
 
 
   public String getHgPath(@NotNull final HgVcsRoot root) {
-    String serverWideHgPath = myConfig.getHgPath();
-    if (serverWideHgPath != null) {
-      return serverWideHgPath;
+    String pathFromRoot = root.getHgPath();
+    if (HgVcsRoot.isAllowedHgPath(pathFromRoot)) {
+      return pathFromRoot;
     } else {
-      String pathFromRoot = root.getHgPath();
-      if (pathFromRoot.equals(unresolvedAgentHgPath())) {
-        //try to use hg from the PATH:
-        return "hg";
-      } else {
-        return pathFromRoot;
-      }
+      String serverWideHgPath = myConfig.getHgPath();
+      return serverWideHgPath != null ? serverWideHgPath : "hg";
     }
   }
-
-
-  private String unresolvedAgentHgPath() {
-    //Use hard-coded value here in order to not add dependency on agent part of plugin:
-    return "%teamcity.hg.agent.path%";
-  }
 }
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgVcsRootTest.java	Wed Jan 24 22:02:52 2018 +0100
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgVcsRootTest.java	Thu Jan 25 09:07:17 2018 +0100
@@ -141,15 +141,36 @@
     assertEquals(hgRoot.getCustomClonePath(), tempDir.getCanonicalPath());
   }
 
-  public void disable_custom_hg_path() throws Exception {
-    VcsRoot root = vcsRoot().withUrl("http://some.org/repo").withHgPath("/some/path").build();
-    assertEquals("/some/path", new HgVcsRoot(root).getHgPath());
-    try {
-      System.setProperty(Constants.CUSTOM_HG_PATH_ENABLED, "false");
-      assertEquals("hg", new HgVcsRoot(root).getHgPath());
-    } finally {
-      System.getProperties().remove(Constants.CUSTOM_HG_PATH_ENABLED);
-    }
+  public void hg_path_whitelist() throws Exception {
+    assertFalse(HgVcsRoot.isAllowedHgPath(null));
+    assertFalse(HgVcsRoot.isAllowedHgPath("/some/path"));
+    setInternalProperty(Constants.CUSTOM_SERVER_HG_PATH_WHITELIST, "/some/path1;/some/path2");
+    assertTrue(HgVcsRoot.isAllowedHgPath("/some/path1"));
+    assertTrue(HgVcsRoot.isAllowedHgPath("/some/path2"));
+    assertFalse(HgVcsRoot.isAllowedHgPath("/some/other/path"));
+    assertFalse(HgVcsRoot.isAllowedHgPath("/some/path11"));
+    assertFalse(HgVcsRoot.isAllowedHgPath("/some/path1/hg"));
+
+    ServerHgPathProvider serverHgPathProvider = new ServerHgPathProvider(new ServerPluginConfigBuilder().build());
+    HgVcsRoot root = new HgVcsRoot(vcsRoot().withHgPath("/some/other/path").withUrl("http://some.org/repo").build());
+    assertEquals("hg", serverHgPathProvider.getHgPath(root));
+
+    serverHgPathProvider = new ServerHgPathProvider(new ServerPluginConfigBuilder().hgPath("/server/hg/path").build());
+    root = new HgVcsRoot(vcsRoot().withHgPath("/some/other/path").withUrl("http://some.org/repo").build());
+    assertEquals("/server/hg/path", serverHgPathProvider.getHgPath(root));
+
+    root = new HgVcsRoot(vcsRoot().withHgPath("/some/path1").withUrl("http://some.org/repo").build());
+    assertEquals("/some/path1", serverHgPathProvider.getHgPath(root));
+    root = new HgVcsRoot(vcsRoot().withHgPath("/some/path2").withUrl("http://some.org/repo").build());
+    assertEquals("/some/path2", serverHgPathProvider.getHgPath(root));
+
+    serverHgPathProvider = new ServerHgPathProvider(new ServerPluginConfigBuilder().hgPath("/server/hg/path").build());
+    root = new HgVcsRoot(vcsRoot().withHgPath("%teamcity.hg.agent.path%").withUrl("http://some.org/repo").build());
+    assertEquals("/server/hg/path", serverHgPathProvider.getHgPath(root));
+
+    serverHgPathProvider = new ServerHgPathProvider(new ServerPluginConfigBuilder().build());
+    root = new HgVcsRoot(vcsRoot().withHgPath("%teamcity.hg.agent.path%").withUrl("http://some.org/repo").build());
+    assertEquals("hg", serverHgPathProvider.getHgPath(root));
   }
 
   public void disable_custom_hg_config() throws Exception {
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgPathProviderTest.java	Wed Jan 24 22:02:52 2018 +0100
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgPathProviderTest.java	Thu Jan 25 09:07:17 2018 +0100
@@ -26,20 +26,22 @@
  * @author dmitry.neverov
  */
 @Test
-public class ServerHgPathProviderTest {
+public class ServerHgPathProviderTest extends BaseMercurialTestCase {
 
   private String myServerWideHgPath;
   private String myVcsRootHgPath;
 
 
   @BeforeMethod
-  public void setUp() {
+  public void setUp() throws Exception {
+    super.setUp();
     myServerWideHgPath = null;
     myVcsRootHgPath = "/vcs/root/hg/path";
   }
 
 
-  public void server_should_use_settings_from_vcs_root_if_server_wide_path_is_not_set() throws Exception {
+  public void server_should_use_whitelisted_settings_from_vcs_root_if_server_wide_path_is_not_set() throws Exception {
+    setInternalProperty(Constants.CUSTOM_SERVER_HG_PATH_WHITELIST, myVcsRootHgPath);
     myServerWideHgPath = null;
     HgPathProvider provider = createHgPathProvider();
     HgVcsRoot root = createHgRoot();