mirror of
https://github.com/SonarSource/sonarqube-scan-action.git
synced 2026-04-13 17:25:00 +03:00
171 lines
4.7 KiB
JavaScript
171 lines
4.7 KiB
JavaScript
// SonarQube Scan Action
|
|
// Copyright (C) SonarSource Sàrl
|
|
// mailto:contact 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.
|
|
|
|
import * as core from "@actions/core";
|
|
import * as exec from "@actions/exec";
|
|
import * as fs from "fs";
|
|
import * as os from "os";
|
|
import * as path from "path";
|
|
import { parseArgsStringToArgv } from "string-argv";
|
|
|
|
const KEYTOOL_MAIN_CLASS = "sun.security.tools.keytool.Main";
|
|
const TRUSTSTORE_PASSWORD = "changeit"; // default password of the Java truststore!
|
|
|
|
export async function runSonarScanner(
|
|
inputArgs,
|
|
projectBaseDir,
|
|
scannerDir,
|
|
runnerEnv = {}
|
|
) {
|
|
const { runnerDebug, runnerOs, runnerTemp, sonarRootCert, sonarcloudUrl } =
|
|
runnerEnv;
|
|
|
|
const scannerBin =
|
|
runnerOs === "Windows" ? "sonar-scanner.bat" : "sonar-scanner";
|
|
|
|
const scannerArgs = [];
|
|
|
|
/**
|
|
* Not sanitization is needed when populating scannerArgs.
|
|
* @actions/exec will take care of sanitizing the args it receives.
|
|
*/
|
|
|
|
if (sonarcloudUrl) {
|
|
scannerArgs.push(`-Dsonar.scanner.sonarcloudUrl=${sonarcloudUrl}`);
|
|
}
|
|
|
|
if (runnerDebug === "1") {
|
|
scannerArgs.push("--debug");
|
|
}
|
|
|
|
if (projectBaseDir) {
|
|
scannerArgs.push(`-Dsonar.projectBaseDir=${projectBaseDir}`);
|
|
}
|
|
|
|
// The SSL folder may exist on an uncleaned self-hosted runner
|
|
const sslFolder = path.join(os.homedir(), ".sonar", "ssl");
|
|
const truststoreFile = path.join(sslFolder, "truststore.p12");
|
|
|
|
const keytoolParams = {
|
|
scannerDir,
|
|
truststoreFile,
|
|
};
|
|
|
|
if (fs.existsSync(truststoreFile)) {
|
|
let aliasSonarIsPresent = true;
|
|
|
|
try {
|
|
await checkSonarAliasInTruststore(keytoolParams);
|
|
} catch (_) {
|
|
aliasSonarIsPresent = false;
|
|
core.info(
|
|
`Existing Scanner truststore ${truststoreFile} does not contain 'sonar' alias`
|
|
);
|
|
}
|
|
|
|
if (aliasSonarIsPresent) {
|
|
core.info(
|
|
`Removing 'sonar' alias from already existing Scanner truststore: ${truststoreFile}`
|
|
);
|
|
await deleteSonarAliasFromTruststore(keytoolParams);
|
|
}
|
|
}
|
|
|
|
if (sonarRootCert) {
|
|
core.info("Adding SSL certificate to the Scanner truststore");
|
|
const tempCertPath = path.join(runnerTemp, "tmpcert.pem");
|
|
|
|
try {
|
|
fs.unlinkSync(tempCertPath);
|
|
} catch (_) {
|
|
// File doesn't exist, ignore
|
|
}
|
|
|
|
fs.writeFileSync(tempCertPath, sonarRootCert);
|
|
fs.mkdirSync(sslFolder, { recursive: true });
|
|
|
|
await importCertificateToTruststore(keytoolParams, tempCertPath);
|
|
|
|
scannerArgs.push(
|
|
`-Dsonar.scanner.truststorePassword=${TRUSTSTORE_PASSWORD}`
|
|
);
|
|
}
|
|
|
|
if (inputArgs) {
|
|
/**
|
|
* No sanitization, but it is parsing a string into an array of arguments in a safe way (= no command execution),
|
|
* and with good enough support of quotes to support arguments containing spaces.
|
|
*/
|
|
const args = parseArgsStringToArgv(inputArgs);
|
|
scannerArgs.push(...args);
|
|
}
|
|
|
|
/**
|
|
* Arguments are sanitized by `exec`
|
|
*/
|
|
await exec.exec(scannerBin, scannerArgs);
|
|
}
|
|
|
|
/**
|
|
* Use keytool for now, as SonarQube 10.6 and below doesn't support openssl generated keystores
|
|
* keytool requires a password > 6 characters, so we won't use the default password 'sonar'
|
|
*/
|
|
function executeKeytoolCommand({
|
|
scannerDir,
|
|
truststoreFile,
|
|
extraArgs,
|
|
options = {},
|
|
}) {
|
|
const baseArgs = [
|
|
KEYTOOL_MAIN_CLASS,
|
|
"-storetype",
|
|
"PKCS12",
|
|
"-keystore",
|
|
truststoreFile,
|
|
"-storepass",
|
|
TRUSTSTORE_PASSWORD,
|
|
"-noprompt",
|
|
"-trustcacerts",
|
|
...extraArgs,
|
|
];
|
|
|
|
return exec.exec(`${scannerDir}/jre/bin/java`, baseArgs, options);
|
|
}
|
|
|
|
function importCertificateToTruststore(keytoolParams, certPath) {
|
|
return executeKeytoolCommand({
|
|
...keytoolParams,
|
|
extraArgs: ["-importcert", "-alias", "sonar", "-file", certPath],
|
|
});
|
|
}
|
|
|
|
function checkSonarAliasInTruststore(keytoolParams) {
|
|
return executeKeytoolCommand({
|
|
...keytoolParams,
|
|
extraArgs: ["-list", "-v", "-alias", "sonar"],
|
|
options: { silent: true },
|
|
});
|
|
}
|
|
|
|
function deleteSonarAliasFromTruststore(keytoolParams) {
|
|
return executeKeytoolCommand({
|
|
...keytoolParams,
|
|
extraArgs: ["-delete", "-alias", "sonar"],
|
|
});
|
|
}
|