diff options
author | Michal Duda <michal.duda@sonarsource.com> | 2018-12-18 15:41:25 +0100 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2019-01-09 20:21:08 +0100 |
commit | db9ccd217314f45a612028ffcf64daff0169f370 (patch) | |
tree | d94a0a77a3e5e5f16fb86fae38b0c58562fe93f8 | |
parent | e74dca535a14fc636b7dca18a5196d16ee3b365a (diff) | |
download | sonarqube-db9ccd217314f45a612028ffcf64daff0169f370.tar.gz sonarqube-db9ccd217314f45a612028ffcf64daff0169f370.zip |
SONAR-11594 scanner authentication token
Support passing the scanner authentication token with $SONAR_TOKEN
4 files changed, 47 insertions, 21 deletions
diff --git a/server/sonar-docs/src/pages/sonarcloud/integrations/bitbucketcloud.md b/server/sonar-docs/src/pages/sonarcloud/integrations/bitbucketcloud.md index 5485432ecf0..5ed96887e74 100644 --- a/server/sonar-docs/src/pages/sonarcloud/integrations/bitbucketcloud.md +++ b/server/sonar-docs/src/pages/sonarcloud/integrations/bitbucketcloud.md @@ -13,25 +13,34 @@ In Bitbucket Cloud, go to your team's "Settings > Find integrations" page, searc ## Analyzing with Pipelines -SonarCloud integrates with Bitbucket Pipelines to make it easier to trigger analyses. Follow the steps: +SonarCloud integrates with Bitbucket Pipelines to make it easier to trigger analyses. Follow these steps: -1. On SonarCloud, once your project is created, follow the tutorial on the dashboard of the project. You can copy-paste the command line displayed at the end. +1. On SonarCloud, once your project is created, follow the tutorial on the dashboard of the project. Copy-paste the command line displayed at the end but without the `sonar.login` setting. -2. On Bitbucket Cloud, go to the "Settings > Pipelines > Environment variables" page of your team, and add a new SONAR_TOKEN variable that contains the value of the SonarCloud token (something like `9ad01c85336b265406fa6554a9a681a4b281135f`) which you created during the tutorial (and which is available inside the command line that you copy-pasted). **Make sure that you click on the "Lock" icon to encrypt and hide this token.** +2. On Bitbucket Cloud, go to the "Settings > Pipelines > Account variables" page of your team, and add a new SONAR_TOKEN variable that contains the value of the SonarCloud token which you created during the tutorial (something like `9ad01c85336b265406fa6554a9a681a4b281135f`). **Make sure that you click on the "Lock" icon to encrypt and hide this token.** -3. Inside the `bitbucket-pipelines.yml` file of your repository, copy the command line provided by the tutorial and replace the actual token by its variable name. For example, for a Java Maven-based project, you should have something like: +3. Inside the `bitbucket-pipelines.yml` file of your repository paste the command you copied in step 1. For example, for a Java Maven-based project, you should have something like: ``` script: - -mvn sonar:sonar -Dsonar.host.url=https://sonarcloud.io -Dsonar.projectKey=my-project -Dsonar.organization=my-team-org -Dsonar.login=$SONAR_TOKEN + -mvn sonar:sonar -Dsonar.host.url=https://sonarcloud.io -Dsonar.projectKey=my-project -Dsonar.organization=my-team-org ``` -When this change on `bitbucket-pipelines.yml` is committed and pushed, Pipelines should automatically run a new build and therefore trigger the analysis of the repository. Shortly after, your project will appear on SonarCloud in your organization. +When this change on `bitbucket-pipelines.yml` is committed and pushed, Pipelines should automatically run a new build and therefore trigger the analysis of the repository. Shortly after, your project will appear on SonarCloud in your organization. -From now on, everytime Pipelines triggers a build, SonarCloud will: +## Analyzing pull requests with Pipelines -* Analyze every new branch that contains the change on the `bitbucket-pipelines.yml` file. -* Analyze and decorate every pull request based on such a branch. +In order to trigger SonarCloud analysis on each pull request update, you have to supply the copied command in `pull-requests` section of `bitbucket-pipelines.yml` (check [Configure bitbucket-pipelines.yml](https://confluence.atlassian.com/bitbucket/configure-bitbucket-pipelines-yml-792298910.html#Configurebitbucket-pipelines.yml-ci_pull-requests) for more details about that section). Here is a sample configuration: +``` +pipelines: + ... + pull-requests: + feature/*: + - step: + script: + - mvn -B verify sonar:sonar -Dsonar.host.url=https://sonarcloud.io -Dsonar.projectKey=... -Dsonar.organization=... + ... +``` ## Quality widget diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerWsClientProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerWsClientProvider.java index 7101bfd96bf..67fe816a83f 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerWsClientProvider.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerWsClientProvider.java @@ -22,6 +22,7 @@ package org.sonar.scanner.bootstrap; import org.picocontainer.injectors.ProviderAdapter; import org.sonar.api.CoreProperties; import org.sonar.api.batch.ScannerSide; +import org.sonar.api.utils.System2; import org.sonar.batch.bootstrapper.EnvironmentInformation; import org.sonarqube.ws.client.HttpConnector; import org.sonarqube.ws.client.WsClientFactories; @@ -39,13 +40,15 @@ public class ScannerWsClientProvider extends ProviderAdapter { private ScannerWsClient wsClient; - public synchronized ScannerWsClient provide(final GlobalProperties settings, final EnvironmentInformation env, GlobalAnalysisMode globalMode) { + public synchronized ScannerWsClient provide(final GlobalProperties settings, final EnvironmentInformation env, + GlobalAnalysisMode globalMode, System2 system) { if (wsClient == null) { String url = defaultIfBlank(settings.property("sonar.host.url"), CoreProperties.SERVER_BASE_URL_DEFAULT_VALUE); HttpConnector.Builder connectorBuilder = HttpConnector.newBuilder(); String timeoutSec = defaultIfBlank(settings.property(READ_TIMEOUT_SEC_PROPERTY), valueOf(DEFAULT_READ_TIMEOUT_SEC)); - String login = defaultIfBlank(settings.property(CoreProperties.LOGIN), null); + String token = defaultIfBlank(system.envVariable("SONAR_TOKEN"), null); + String login = defaultIfBlank(settings.property(CoreProperties.LOGIN), token); connectorBuilder .readTimeoutMilliseconds(parseInt(timeoutSec) * 1_000) .connectTimeoutMilliseconds(CONNECT_TIMEOUT_MS) diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/AnalysisContextReportPublisher.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/AnalysisContextReportPublisher.java index 237ad54f65d..8badd6715df 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/AnalysisContextReportPublisher.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/AnalysisContextReportPublisher.java @@ -112,9 +112,15 @@ public class AnalysisContextReportPublisher { private void writeEnvVariables(BufferedWriter fileWriter) throws IOException { fileWriter.append("Environment variables:\n"); Map<String, String> envVariables = system.envVariables(); - for (String env : new TreeSet<>(envVariables.keySet())) { - fileWriter.append(String.format(KEY_VALUE_FORMAT, env, envVariables.get(env))).append('\n'); - } + new TreeSet<>(envVariables.keySet()) + .forEach(envKey -> { + try { + String envValue = isSensitiveEnvVariable(envKey) ? "******" : envVariables.get(envKey); + fileWriter.append(String.format(KEY_VALUE_FORMAT, envKey, envValue)).append('\n'); + } catch (IOException e) { + throw new IllegalStateException(e); + } + }); } private void writeGlobalSettings(BufferedWriter fileWriter) throws IOException { @@ -146,7 +152,7 @@ public class AnalysisContextReportPublisher { } private static void dumpPropIfNotSensitive(BufferedWriter fileWriter, String prop, String value) throws IOException { - fileWriter.append(String.format(KEY_VALUE_FORMAT, prop, sensitive(prop) ? "******" : StringUtils.abbreviate(value, MAX_WIDTH))).append('\n'); + fileWriter.append(String.format(KEY_VALUE_FORMAT, prop, isSensitiveProperty(prop) ? "******" : StringUtils.abbreviate(value, MAX_WIDTH))).append('\n'); } /** @@ -183,7 +189,11 @@ public class AnalysisContextReportPublisher { return propKey.startsWith(ENV_PROP_PREFIX) && system.envVariables().containsKey(propKey.substring(ENV_PROP_PREFIX.length())); } - private static boolean sensitive(String key) { - return key.equals(CoreProperties.LOGIN) || key.contains(".password") || key.contains(".secured"); + private static boolean isSensitiveEnvVariable(String key) { + return key.contains("_TOKEN") || key.contains("_PASSWORD") || key.contains("_SECURED"); + } + + private static boolean isSensitiveProperty(String key) { + return key.equals(CoreProperties.LOGIN) || key.contains(".password") || key.contains(".secured") || key.contains(".token"); } } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerWsClientProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerWsClientProviderTest.java index c72c88f9031..804107b7886 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerWsClientProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerWsClientProviderTest.java @@ -23,10 +23,12 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.junit.Test; +import org.sonar.api.utils.System2; import org.sonar.batch.bootstrapper.EnvironmentInformation; import org.sonarqube.ws.client.HttpConnector; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; public class ScannerWsClientProviderTest { @@ -37,7 +39,7 @@ public class ScannerWsClientProviderTest { public void provide_client_with_default_settings() { GlobalProperties settings = new GlobalProperties(new HashMap<>()); - ScannerWsClient client = underTest.provide(settings, env, new GlobalAnalysisMode(new GlobalProperties(Collections.emptyMap()))); + ScannerWsClient client = underTest.provide(settings, env, new GlobalAnalysisMode(new GlobalProperties(Collections.emptyMap())), mock(System2.class)); assertThat(client).isNotNull(); assertThat(client.baseUrl()).isEqualTo("http://localhost:9000/"); @@ -57,7 +59,7 @@ public class ScannerWsClientProviderTest { props.put("sonar.ws.timeout", "42"); GlobalProperties settings = new GlobalProperties(props); - ScannerWsClient client = underTest.provide(settings, env, new GlobalAnalysisMode(new GlobalProperties(Collections.emptyMap()))); + ScannerWsClient client = underTest.provide(settings, env, new GlobalAnalysisMode(new GlobalProperties(Collections.emptyMap())), mock(System2.class)); assertThat(client).isNotNull(); HttpConnector httpConnector = (HttpConnector) client.wsConnector(); @@ -67,9 +69,11 @@ public class ScannerWsClientProviderTest { @Test public void build_singleton() { + System2 system = mock(System2.class); + GlobalProperties settings = new GlobalProperties(new HashMap<>()); - ScannerWsClient first = underTest.provide(settings, env, new GlobalAnalysisMode(new GlobalProperties(Collections.emptyMap()))); - ScannerWsClient second = underTest.provide(settings, env, new GlobalAnalysisMode(new GlobalProperties(Collections.emptyMap()))); + ScannerWsClient first = underTest.provide(settings, env, new GlobalAnalysisMode(new GlobalProperties(Collections.emptyMap())), system); + ScannerWsClient second = underTest.provide(settings, env, new GlobalAnalysisMode(new GlobalProperties(Collections.emptyMap())), system); assertThat(first).isSameAs(second); } } |