mirror of
https://github.com/SonarSource/sonarqube-scan-action.git
synced 2026-10-03 10:01:39 +00:00
SQSCANGHA-112 SQSCANGHA-113 Fixes from review and keytool refactor
This commit is contained in:
1 parent
60aee7033b
commit
a64281002c
5 files changed
+195
-172
No files matched your search
Vendored
+97
-86
@@ -29895,7 +29895,7 @@ async function installSonarScanner({
|
|||||||
let toolDir = toolCacheExports.find(TOOLNAME, scannerVersion, flavor);
|
let toolDir = toolCacheExports.find(TOOLNAME, scannerVersion, flavor);
|
||||||
|
|
||||||
if (!toolDir) {
|
if (!toolDir) {
|
||||||
console.log(
|
coreExports.info(
|
||||||
`Installing Sonar Scanner CLI ${scannerVersion} for ${flavor}...`
|
`Installing Sonar Scanner CLI ${scannerVersion} for ${flavor}...`
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -29905,7 +29905,7 @@ async function installSonarScanner({
|
|||||||
flavor,
|
flavor,
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`Downloading from: ${downloadUrl}`);
|
coreExports.info(`Downloading from: ${downloadUrl}`);
|
||||||
|
|
||||||
const downloadPath = await toolCacheExports.downloadTool(downloadUrl);
|
const downloadPath = await toolCacheExports.downloadTool(downloadUrl);
|
||||||
const extractedPath = await toolCacheExports.extractZip(downloadPath);
|
const extractedPath = await toolCacheExports.extractZip(downloadPath);
|
||||||
@@ -29918,9 +29918,9 @@ async function installSonarScanner({
|
|||||||
|
|
||||||
toolDir = await toolCacheExports.cacheDir(scannerPath, TOOLNAME, scannerVersion, flavor);
|
toolDir = await toolCacheExports.cacheDir(scannerPath, TOOLNAME, scannerVersion, flavor);
|
||||||
|
|
||||||
console.log(`Sonar Scanner CLI cached to: ${toolDir}`);
|
coreExports.info(`Sonar Scanner CLI cached to: ${toolDir}`);
|
||||||
} else {
|
} else {
|
||||||
console.log(`Using cached Sonar Scanner CLI from: ${toolDir}`);
|
coreExports.info(`Using cached Sonar Scanner CLI from: ${toolDir}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the bin directory to PATH
|
// Add the bin directory to PATH
|
||||||
@@ -29967,30 +29967,33 @@ function firstString() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const KEYTOOL_MAIN_CLASS = "sun.security.tools.keytool.Main";
|
||||||
|
const TRUSTSTORE_PASSWORD = "changeit"; // default password of the Java truststore!
|
||||||
|
|
||||||
async function runSonarScanner(
|
async function runSonarScanner(
|
||||||
inputArgs,
|
inputArgs,
|
||||||
projectBaseDir,
|
projectBaseDir,
|
||||||
scannerDir,
|
scannerDir,
|
||||||
runnerEnv = {}
|
runnerEnv = {}
|
||||||
) {
|
) {
|
||||||
const {
|
const { runnerDebug, runnerOs, runnerTemp, sonarRootCert, sonarcloudUrl } =
|
||||||
RUNNER_DEBUG,
|
runnerEnv;
|
||||||
RUNNER_OS,
|
|
||||||
RUNNER_TEMP,
|
|
||||||
SONAR_ROOT_CERT,
|
|
||||||
SONARCLOUD_URL,
|
|
||||||
} = runnerEnv;
|
|
||||||
|
|
||||||
const scannerBin =
|
const scannerBin =
|
||||||
RUNNER_OS === "Windows" ? "sonar-scanner.bat" : "sonar-scanner";
|
runnerOs === "Windows" ? "sonar-scanner.bat" : "sonar-scanner";
|
||||||
|
|
||||||
const scannerArgs = [];
|
const scannerArgs = [];
|
||||||
|
|
||||||
if (SONARCLOUD_URL) {
|
/**
|
||||||
scannerArgs.push(`-Dsonar.scanner.sonarcloudUrl=${SONARCLOUD_URL}`);
|
* 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 (RUNNER_DEBUG === "1") {
|
if (runnerDebug === "1") {
|
||||||
scannerArgs.push("--debug");
|
scannerArgs.push("--debug");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30000,68 +30003,36 @@ async function runSonarScanner(
|
|||||||
|
|
||||||
// The SSL folder may exist on an uncleaned self-hosted runner
|
// The SSL folder may exist on an uncleaned self-hosted runner
|
||||||
const sslFolder = path.join(require$$0.homedir(), ".sonar", "ssl");
|
const sslFolder = path.join(require$$0.homedir(), ".sonar", "ssl");
|
||||||
/**
|
|
||||||
* 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'
|
|
||||||
*/
|
|
||||||
const keytoolMainClass = "sun.security.tools.keytool.Main";
|
|
||||||
const truststoreFile = path.join(sslFolder, "truststore.p12");
|
const truststoreFile = path.join(sslFolder, "truststore.p12");
|
||||||
const truststorePassword = "changeit";
|
|
||||||
|
const keytoolParams = {
|
||||||
|
scannerDir,
|
||||||
|
truststoreFile,
|
||||||
|
};
|
||||||
|
|
||||||
if (fs.existsSync(truststoreFile)) {
|
if (fs.existsSync(truststoreFile)) {
|
||||||
let aliasSonarIsPresent = true;
|
let aliasSonarIsPresent = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await execExports.exec(
|
await checkSonarAliasInTruststore(keytoolParams);
|
||||||
`${scannerDir}/jre/bin/java`,
|
|
||||||
[
|
|
||||||
keytoolMainClass,
|
|
||||||
"-storetype",
|
|
||||||
"PKCS12",
|
|
||||||
"-keystore",
|
|
||||||
truststoreFile,
|
|
||||||
"-storepass",
|
|
||||||
truststorePassword,
|
|
||||||
"-noprompt",
|
|
||||||
"-trustcacerts",
|
|
||||||
"-list",
|
|
||||||
"-v",
|
|
||||||
"-alias",
|
|
||||||
"sonar",
|
|
||||||
],
|
|
||||||
{ silent: true }
|
|
||||||
);
|
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
aliasSonarIsPresent = false;
|
aliasSonarIsPresent = false;
|
||||||
console.log(
|
coreExports.info(
|
||||||
`Existing Scanner truststore ${truststoreFile} does not contain 'sonar' alias`
|
`Existing Scanner truststore ${truststoreFile} does not contain 'sonar' alias`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aliasSonarIsPresent) {
|
if (aliasSonarIsPresent) {
|
||||||
console.log(
|
coreExports.info(
|
||||||
`Removing 'sonar' alias from already existing Scanner truststore: ${truststoreFile}`
|
`Removing 'sonar' alias from already existing Scanner truststore: ${truststoreFile}`
|
||||||
);
|
);
|
||||||
await execExports.exec(`${scannerDir}/jre/bin/java`, [
|
await deleteSonarAliasFromTruststore(keytoolParams);
|
||||||
keytoolMainClass,
|
|
||||||
"-storetype",
|
|
||||||
"PKCS12",
|
|
||||||
"-keystore",
|
|
||||||
truststoreFile,
|
|
||||||
"-storepass",
|
|
||||||
truststorePassword,
|
|
||||||
"-noprompt",
|
|
||||||
"-trustcacerts",
|
|
||||||
"-delete",
|
|
||||||
"-alias",
|
|
||||||
"sonar",
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SONAR_ROOT_CERT) {
|
if (sonarRootCert) {
|
||||||
console.log("Adding SSL certificate to the Scanner truststore");
|
coreExports.info("Adding SSL certificate to the Scanner truststore");
|
||||||
const tempCertPath = path.join(RUNNER_TEMP, "tmpcert.pem");
|
const tempCertPath = path.join(runnerTemp, "tmpcert.pem");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fs.unlinkSync(tempCertPath);
|
fs.unlinkSync(tempCertPath);
|
||||||
@@ -30069,39 +30040,79 @@ async function runSonarScanner(
|
|||||||
// File doesn't exist, ignore
|
// File doesn't exist, ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.writeFileSync(tempCertPath, SONAR_ROOT_CERT);
|
fs.writeFileSync(tempCertPath, sonarRootCert);
|
||||||
fs.mkdirSync(sslFolder, { recursive: true });
|
fs.mkdirSync(sslFolder, { recursive: true });
|
||||||
|
|
||||||
await execExports.exec(`${scannerDir}/jre/bin/java`, [
|
await importCertificateToTruststore(keytoolParams, tempCertPath);
|
||||||
keytoolMainClass,
|
|
||||||
"-storetype",
|
|
||||||
"PKCS12",
|
|
||||||
"-keystore",
|
|
||||||
truststoreFile,
|
|
||||||
"-storepass",
|
|
||||||
truststorePassword,
|
|
||||||
"-noprompt",
|
|
||||||
"-trustcacerts",
|
|
||||||
"-importcert",
|
|
||||||
"-alias",
|
|
||||||
"sonar",
|
|
||||||
"-file",
|
|
||||||
tempCertPath,
|
|
||||||
]);
|
|
||||||
|
|
||||||
scannerArgs.push(
|
scannerArgs.push(
|
||||||
`-Dsonar.scanner.truststorePassword=${truststorePassword}`
|
`-Dsonar.scanner.truststorePassword=${TRUSTSTORE_PASSWORD}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inputArgs) {
|
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);
|
const args = parseArgsStringToArgv(inputArgs);
|
||||||
scannerArgs.push(...args);
|
scannerArgs.push(...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Arguments are sanitized by `exec`
|
||||||
|
*/
|
||||||
await execExports.exec(scannerBin, scannerArgs);
|
await execExports.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 execExports.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"],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function validateScannerVersion(version) {
|
function validateScannerVersion(version) {
|
||||||
if (!version) {
|
if (!version) {
|
||||||
return;
|
return;
|
||||||
@@ -30116,7 +30127,7 @@ function validateScannerVersion(version) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function checkSonarToken(core, sonarToken) {
|
function checkSonarToken(core, sonarToken) {
|
||||||
{
|
if (!sonarToken) {
|
||||||
core.warning(
|
core.warning(
|
||||||
"Running this GitHub Action without SONAR_TOKEN is not recommended"
|
"Running this GitHub Action without SONAR_TOKEN is not recommended"
|
||||||
);
|
);
|
||||||
@@ -30164,21 +30175,21 @@ function getInputs() {
|
|||||||
*/
|
*/
|
||||||
function getEnvVariables() {
|
function getEnvVariables() {
|
||||||
return {
|
return {
|
||||||
RUNNER_DEBUG: process.env.RUNNER_DEBUG,
|
runnerDebug: process.env.RUNNER_DEBUG,
|
||||||
RUNNER_OS: process.env.RUNNER_OS,
|
runnerOs: process.env.RUNNER_OS,
|
||||||
RUNNER_TEMP: process.env.RUNNER_TEMP,
|
runnerTemp: process.env.RUNNER_TEMP,
|
||||||
SONAR_ROOT_CERT: process.env.SONAR_ROOT_CERT,
|
sonarRootCert: process.env.SONAR_ROOT_CERT,
|
||||||
SONARCLOUD_URL: process.env.SONARCLOUD_URL,
|
sonarcloudUrl: process.env.SONARCLOUD_URL,
|
||||||
SONAR_TOKEN: process.env.SONAR_TOKEN,
|
sonarToken: process.env.SONAR_TOKEN,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function runSanityChecks(inputs) {
|
function runSanityChecks(inputs) {
|
||||||
try {
|
try {
|
||||||
const { projectBaseDir, scannerVersion } = inputs;
|
const { projectBaseDir, scannerVersion, sonarToken } = inputs;
|
||||||
|
|
||||||
validateScannerVersion(scannerVersion);
|
validateScannerVersion(scannerVersion);
|
||||||
checkSonarToken(core$1);
|
checkSonarToken(core$1, sonarToken);
|
||||||
checkMavenProject(core$1, projectBaseDir);
|
checkMavenProject(core$1, projectBaseDir);
|
||||||
checkGradleProject(core$1, projectBaseDir);
|
checkGradleProject(core$1, projectBaseDir);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"index.js","sources":["../node_modules/@actions/core/lib/utils.js","../node_modules/@actions/core/lib/command.js","../node_modules/@actions/core/lib/file-command.js","../node_modules/@actions/http-client/lib/proxy.js","../node_modules/tunnel/lib/tunnel.js","../node_modules/tunnel/index.js","../node_modules/undici/lib/core/symbols.js","../node_modules/undici/lib/core/errors.js","../node_modules/undici/lib/core/constants.js","../node_modules/undici/lib/core/util.js","../node_modules/undici/lib/timers.js","../node_modules/@fastify/busboy/deps/streamsearch/sbmh.js","../node_modules/@fastify/busboy/deps/dicer/lib/PartStream.js","../node_modules/@fastify/busboy/lib/utils/getLimit.js","../node_modules/@fastify/busboy/deps/dicer/lib/HeaderParser.js","../node_modules/@fastify/busboy/deps/dicer/lib/Dicer.js","../node_modules/@fastify/busboy/lib/utils/decodeText.js","../node_modules/@fastify/busboy/lib/utils/parseParams.js","../node_modules/@fastify/busboy/lib/utils/basename.js","../node_modules/@fastify/busboy/lib/types/multipart.js","../node_modules/@fastify/busboy/lib/utils/Decoder.js","../node_modules/@fastify/busboy/lib/types/urlencoded.js","../node_modules/@fastify/busboy/lib/main.js","../node_modules/undici/lib/fetch/constants.js","../node_modules/undici/lib/fetch/global.js","../node_modules/undici/lib/fetch/util.js","../node_modules/undici/lib/fetch/symbols.js","../node_modules/undici/lib/fetch/webidl.js","../node_modules/undici/lib/fetch/dataURL.js","../node_modules/undici/lib/fetch/file.js","../node_modules/undici/lib/fetch/formdata.js","../node_modules/undici/lib/fetch/body.js","../node_modules/undici/lib/core/request.js","../node_modules/undici/lib/dispatcher.js","../node_modules/undici/lib/dispatcher-base.js","../node_modules/undici/lib/core/connect.js","../node_modules/undici/lib/llhttp/utils.js","../node_modules/undici/lib/llhttp/constants.js","../node_modules/undici/lib/handler/RedirectHandler.js","../node_modules/undici/lib/interceptor/redirectInterceptor.js","../node_modules/undici/lib/llhttp/llhttp-wasm.js","../node_modules/undici/lib/llhttp/llhttp_simd-wasm.js","../node_modules/undici/lib/client.js","../node_modules/undici/lib/node/fixed-queue.js","../node_modules/undici/lib/pool-stats.js","../node_modules/undici/lib/pool-base.js","../node_modules/undici/lib/pool.js","../node_modules/undici/lib/balanced-pool.js","../node_modules/undici/lib/compat/dispatcher-weakref.js","../node_modules/undici/lib/agent.js","../node_modules/undici/lib/api/readable.js","../node_modules/undici/lib/api/util.js","../node_modules/undici/lib/api/abort-signal.js","../node_modules/undici/lib/api/api-request.js","../node_modules/undici/lib/api/api-stream.js","../node_modules/undici/lib/api/api-pipeline.js","../node_modules/undici/lib/api/api-upgrade.js","../node_modules/undici/lib/api/api-connect.js","../node_modules/undici/lib/api/index.js","../node_modules/undici/lib/mock/mock-errors.js","../node_modules/undici/lib/mock/mock-symbols.js","../node_modules/undici/lib/mock/mock-utils.js","../node_modules/undici/lib/mock/mock-interceptor.js","../node_modules/undici/lib/mock/mock-client.js","../node_modules/undici/lib/mock/mock-pool.js","../node_modules/undici/lib/mock/pluralizer.js","../node_modules/undici/lib/mock/pending-interceptors-formatter.js","../node_modules/undici/lib/mock/mock-agent.js","../node_modules/undici/lib/proxy-agent.js","../node_modules/undici/lib/handler/RetryHandler.js","../node_modules/undici/lib/global.js","../node_modules/undici/lib/handler/DecoratorHandler.js","../node_modules/undici/lib/fetch/headers.js","../node_modules/undici/lib/fetch/response.js","../node_modules/undici/lib/fetch/request.js","../node_modules/undici/lib/fetch/index.js","../node_modules/undici/lib/fileapi/symbols.js","../node_modules/undici/lib/fileapi/progressevent.js","../node_modules/undici/lib/fileapi/encoding.js","../node_modules/undici/lib/fileapi/util.js","../node_modules/undici/lib/fileapi/filereader.js","../node_modules/undici/lib/cache/symbols.js","../node_modules/undici/lib/cache/util.js","../node_modules/undici/lib/cache/cache.js","../node_modules/undici/lib/cache/cachestorage.js","../node_modules/undici/lib/cookies/constants.js","../node_modules/undici/lib/cookies/util.js","../node_modules/undici/lib/cookies/parse.js","../node_modules/undici/lib/cookies/index.js","../node_modules/undici/lib/websocket/constants.js","../node_modules/undici/lib/websocket/symbols.js","../node_modules/undici/lib/websocket/events.js","../node_modules/undici/lib/websocket/util.js","../node_modules/undici/lib/websocket/connection.js","../node_modules/undici/lib/websocket/frame.js","../node_modules/undici/lib/websocket/receiver.js","../node_modules/undici/lib/websocket/websocket.js","../node_modules/undici/index.js","../node_modules/@actions/http-client/lib/index.js","../node_modules/@actions/http-client/lib/auth.js","../node_modules/@actions/core/lib/oidc-utils.js","../node_modules/@actions/core/lib/summary.js","../node_modLine truncated
|
{"version":3,"file":"index.js","sources":["../node_modules/@actions/core/lib/utils.js","../node_modules/@actions/core/lib/command.js","../node_modules/@actions/core/lib/file-command.js","../node_modules/@actions/http-client/lib/proxy.js","../node_modules/tunnel/lib/tunnel.js","../node_modules/tunnel/index.js","../node_modules/undici/lib/core/symbols.js","../node_modules/undici/lib/core/errors.js","../node_modules/undici/lib/core/constants.js","../node_modules/undici/lib/core/util.js","../node_modules/undici/lib/timers.js","../node_modules/@fastify/busboy/deps/streamsearch/sbmh.js","../node_modules/@fastify/busboy/deps/dicer/lib/PartStream.js","../node_modules/@fastify/busboy/lib/utils/getLimit.js","../node_modules/@fastify/busboy/deps/dicer/lib/HeaderParser.js","../node_modules/@fastify/busboy/deps/dicer/lib/Dicer.js","../node_modules/@fastify/busboy/lib/utils/decodeText.js","../node_modules/@fastify/busboy/lib/utils/parseParams.js","../node_modules/@fastify/busboy/lib/utils/basename.js","../node_modules/@fastify/busboy/lib/types/multipart.js","../node_modules/@fastify/busboy/lib/utils/Decoder.js","../node_modules/@fastify/busboy/lib/types/urlencoded.js","../node_modules/@fastify/busboy/lib/main.js","../node_modules/undici/lib/fetch/constants.js","../node_modules/undici/lib/fetch/global.js","../node_modules/undici/lib/fetch/util.js","../node_modules/undici/lib/fetch/symbols.js","../node_modules/undici/lib/fetch/webidl.js","../node_modules/undici/lib/fetch/dataURL.js","../node_modules/undici/lib/fetch/file.js","../node_modules/undici/lib/fetch/formdata.js","../node_modules/undici/lib/fetch/body.js","../node_modules/undici/lib/core/request.js","../node_modules/undici/lib/dispatcher.js","../node_modules/undici/lib/dispatcher-base.js","../node_modules/undici/lib/core/connect.js","../node_modules/undici/lib/llhttp/utils.js","../node_modules/undici/lib/llhttp/constants.js","../node_modules/undici/lib/handler/RedirectHandler.js","../node_modules/undici/lib/interceptor/redirectInterceptor.js","../node_modules/undici/lib/llhttp/llhttp-wasm.js","../node_modules/undici/lib/llhttp/llhttp_simd-wasm.js","../node_modules/undici/lib/client.js","../node_modules/undici/lib/node/fixed-queue.js","../node_modules/undici/lib/pool-stats.js","../node_modules/undici/lib/pool-base.js","../node_modules/undici/lib/pool.js","../node_modules/undici/lib/balanced-pool.js","../node_modules/undici/lib/compat/dispatcher-weakref.js","../node_modules/undici/lib/agent.js","../node_modules/undici/lib/api/readable.js","../node_modules/undici/lib/api/util.js","../node_modules/undici/lib/api/abort-signal.js","../node_modules/undici/lib/api/api-request.js","../node_modules/undici/lib/api/api-stream.js","../node_modules/undici/lib/api/api-pipeline.js","../node_modules/undici/lib/api/api-upgrade.js","../node_modules/undici/lib/api/api-connect.js","../node_modules/undici/lib/api/index.js","../node_modules/undici/lib/mock/mock-errors.js","../node_modules/undici/lib/mock/mock-symbols.js","../node_modules/undici/lib/mock/mock-utils.js","../node_modules/undici/lib/mock/mock-interceptor.js","../node_modules/undici/lib/mock/mock-client.js","../node_modules/undici/lib/mock/mock-pool.js","../node_modules/undici/lib/mock/pluralizer.js","../node_modules/undici/lib/mock/pending-interceptors-formatter.js","../node_modules/undici/lib/mock/mock-agent.js","../node_modules/undici/lib/proxy-agent.js","../node_modules/undici/lib/handler/RetryHandler.js","../node_modules/undici/lib/global.js","../node_modules/undici/lib/handler/DecoratorHandler.js","../node_modules/undici/lib/fetch/headers.js","../node_modules/undici/lib/fetch/response.js","../node_modules/undici/lib/fetch/request.js","../node_modules/undici/lib/fetch/index.js","../node_modules/undici/lib/fileapi/symbols.js","../node_modules/undici/lib/fileapi/progressevent.js","../node_modules/undici/lib/fileapi/encoding.js","../node_modules/undici/lib/fileapi/util.js","../node_modules/undici/lib/fileapi/filereader.js","../node_modules/undici/lib/cache/symbols.js","../node_modules/undici/lib/cache/util.js","../node_modules/undici/lib/cache/cache.js","../node_modules/undici/lib/cache/cachestorage.js","../node_modules/undici/lib/cookies/constants.js","../node_modules/undici/lib/cookies/util.js","../node_modules/undici/lib/cookies/parse.js","../node_modules/undici/lib/cookies/index.js","../node_modules/undici/lib/websocket/constants.js","../node_modules/undici/lib/websocket/symbols.js","../node_modules/undici/lib/websocket/events.js","../node_modules/undici/lib/websocket/util.js","../node_modules/undici/lib/websocket/connection.js","../node_modules/undici/lib/websocket/frame.js","../node_modules/undici/lib/websocket/receiver.js","../node_modules/undici/lib/websocket/websocket.js","../node_modules/undici/index.js","../node_modules/@actions/http-client/lib/index.js","../node_modules/@actions/http-client/lib/auth.js","../node_modules/@actions/core/lib/oidc-utils.js","../node_modules/@actions/core/lib/summary.js","../node_modLine truncated
|
||||||
+8
-8
@@ -28,21 +28,21 @@ function getInputs() {
|
|||||||
*/
|
*/
|
||||||
function getEnvVariables() {
|
function getEnvVariables() {
|
||||||
return {
|
return {
|
||||||
RUNNER_DEBUG: process.env.RUNNER_DEBUG,
|
runnerDebug: process.env.RUNNER_DEBUG,
|
||||||
RUNNER_OS: process.env.RUNNER_OS,
|
runnerOs: process.env.RUNNER_OS,
|
||||||
RUNNER_TEMP: process.env.RUNNER_TEMP,
|
runnerTemp: process.env.RUNNER_TEMP,
|
||||||
SONAR_ROOT_CERT: process.env.SONAR_ROOT_CERT,
|
sonarRootCert: process.env.SONAR_ROOT_CERT,
|
||||||
SONARCLOUD_URL: process.env.SONARCLOUD_URL,
|
sonarcloudUrl: process.env.SONARCLOUD_URL,
|
||||||
SONAR_TOKEN: process.env.SONAR_TOKEN,
|
sonarToken: process.env.SONAR_TOKEN,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function runSanityChecks(inputs) {
|
function runSanityChecks(inputs) {
|
||||||
try {
|
try {
|
||||||
const { projectBaseDir, scannerVersion } = inputs;
|
const { projectBaseDir, scannerVersion, sonarToken } = inputs;
|
||||||
|
|
||||||
validateScannerVersion(scannerVersion);
|
validateScannerVersion(scannerVersion);
|
||||||
checkSonarToken(core);
|
checkSonarToken(core, sonarToken);
|
||||||
checkMavenProject(core, projectBaseDir);
|
checkMavenProject(core, projectBaseDir);
|
||||||
checkGradleProject(core, projectBaseDir);
|
checkGradleProject(core, projectBaseDir);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export async function installSonarScanner({
|
|||||||
let toolDir = tc.find(TOOLNAME, scannerVersion, flavor);
|
let toolDir = tc.find(TOOLNAME, scannerVersion, flavor);
|
||||||
|
|
||||||
if (!toolDir) {
|
if (!toolDir) {
|
||||||
console.log(
|
core.info(
|
||||||
`Installing Sonar Scanner CLI ${scannerVersion} for ${flavor}...`
|
`Installing Sonar Scanner CLI ${scannerVersion} for ${flavor}...`
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ export async function installSonarScanner({
|
|||||||
flavor,
|
flavor,
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`Downloading from: ${downloadUrl}`);
|
core.info(`Downloading from: ${downloadUrl}`);
|
||||||
|
|
||||||
const downloadPath = await tc.downloadTool(downloadUrl);
|
const downloadPath = await tc.downloadTool(downloadUrl);
|
||||||
const extractedPath = await tc.extractZip(downloadPath);
|
const extractedPath = await tc.extractZip(downloadPath);
|
||||||
@@ -46,9 +46,9 @@ export async function installSonarScanner({
|
|||||||
|
|
||||||
toolDir = await tc.cacheDir(scannerPath, TOOLNAME, scannerVersion, flavor);
|
toolDir = await tc.cacheDir(scannerPath, TOOLNAME, scannerVersion, flavor);
|
||||||
|
|
||||||
console.log(`Sonar Scanner CLI cached to: ${toolDir}`);
|
core.info(`Sonar Scanner CLI cached to: ${toolDir}`);
|
||||||
} else {
|
} else {
|
||||||
console.log(`Using cached Sonar Scanner CLI from: ${toolDir}`);
|
core.info(`Using cached Sonar Scanner CLI from: ${toolDir}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the bin directory to PATH
|
// Add the bin directory to PATH
|
||||||
|
|||||||
+85
-73
@@ -1,33 +1,37 @@
|
|||||||
|
import * as core from "@actions/core";
|
||||||
import * as exec from "@actions/exec";
|
import * as exec from "@actions/exec";
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import * as os from "os";
|
import * as os from "os";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
import { parseArgsStringToArgv } from "string-argv";
|
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(
|
export async function runSonarScanner(
|
||||||
inputArgs,
|
inputArgs,
|
||||||
projectBaseDir,
|
projectBaseDir,
|
||||||
scannerDir,
|
scannerDir,
|
||||||
runnerEnv = {}
|
runnerEnv = {}
|
||||||
) {
|
) {
|
||||||
const {
|
const { runnerDebug, runnerOs, runnerTemp, sonarRootCert, sonarcloudUrl } =
|
||||||
RUNNER_DEBUG,
|
runnerEnv;
|
||||||
RUNNER_OS,
|
|
||||||
RUNNER_TEMP,
|
|
||||||
SONAR_ROOT_CERT,
|
|
||||||
SONARCLOUD_URL,
|
|
||||||
} = runnerEnv;
|
|
||||||
|
|
||||||
const scannerBin =
|
const scannerBin =
|
||||||
RUNNER_OS === "Windows" ? "sonar-scanner.bat" : "sonar-scanner";
|
runnerOs === "Windows" ? "sonar-scanner.bat" : "sonar-scanner";
|
||||||
|
|
||||||
const scannerArgs = [];
|
const scannerArgs = [];
|
||||||
|
|
||||||
if (SONARCLOUD_URL) {
|
/**
|
||||||
scannerArgs.push(`-Dsonar.scanner.sonarcloudUrl=${SONARCLOUD_URL}`);
|
* 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 (RUNNER_DEBUG === "1") {
|
if (runnerDebug === "1") {
|
||||||
scannerArgs.push("--debug");
|
scannerArgs.push("--debug");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,68 +41,36 @@ export async function runSonarScanner(
|
|||||||
|
|
||||||
// The SSL folder may exist on an uncleaned self-hosted runner
|
// The SSL folder may exist on an uncleaned self-hosted runner
|
||||||
const sslFolder = path.join(os.homedir(), ".sonar", "ssl");
|
const sslFolder = path.join(os.homedir(), ".sonar", "ssl");
|
||||||
/**
|
|
||||||
* 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'
|
|
||||||
*/
|
|
||||||
const keytoolMainClass = "sun.security.tools.keytool.Main";
|
|
||||||
const truststoreFile = path.join(sslFolder, "truststore.p12");
|
const truststoreFile = path.join(sslFolder, "truststore.p12");
|
||||||
const truststorePassword = "changeit";
|
|
||||||
|
const keytoolParams = {
|
||||||
|
scannerDir,
|
||||||
|
truststoreFile,
|
||||||
|
};
|
||||||
|
|
||||||
if (fs.existsSync(truststoreFile)) {
|
if (fs.existsSync(truststoreFile)) {
|
||||||
let aliasSonarIsPresent = true;
|
let aliasSonarIsPresent = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await exec.exec(
|
await checkSonarAliasInTruststore(keytoolParams);
|
||||||
`${scannerDir}/jre/bin/java`,
|
|
||||||
[
|
|
||||||
keytoolMainClass,
|
|
||||||
"-storetype",
|
|
||||||
"PKCS12",
|
|
||||||
"-keystore",
|
|
||||||
truststoreFile,
|
|
||||||
"-storepass",
|
|
||||||
truststorePassword,
|
|
||||||
"-noprompt",
|
|
||||||
"-trustcacerts",
|
|
||||||
"-list",
|
|
||||||
"-v",
|
|
||||||
"-alias",
|
|
||||||
"sonar",
|
|
||||||
],
|
|
||||||
{ silent: true }
|
|
||||||
);
|
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
aliasSonarIsPresent = false;
|
aliasSonarIsPresent = false;
|
||||||
console.log(
|
core.info(
|
||||||
`Existing Scanner truststore ${truststoreFile} does not contain 'sonar' alias`
|
`Existing Scanner truststore ${truststoreFile} does not contain 'sonar' alias`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aliasSonarIsPresent) {
|
if (aliasSonarIsPresent) {
|
||||||
console.log(
|
core.info(
|
||||||
`Removing 'sonar' alias from already existing Scanner truststore: ${truststoreFile}`
|
`Removing 'sonar' alias from already existing Scanner truststore: ${truststoreFile}`
|
||||||
);
|
);
|
||||||
await exec.exec(`${scannerDir}/jre/bin/java`, [
|
await deleteSonarAliasFromTruststore(keytoolParams);
|
||||||
keytoolMainClass,
|
|
||||||
"-storetype",
|
|
||||||
"PKCS12",
|
|
||||||
"-keystore",
|
|
||||||
truststoreFile,
|
|
||||||
"-storepass",
|
|
||||||
truststorePassword,
|
|
||||||
"-noprompt",
|
|
||||||
"-trustcacerts",
|
|
||||||
"-delete",
|
|
||||||
"-alias",
|
|
||||||
"sonar",
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SONAR_ROOT_CERT) {
|
if (sonarRootCert) {
|
||||||
console.log("Adding SSL certificate to the Scanner truststore");
|
core.info("Adding SSL certificate to the Scanner truststore");
|
||||||
const tempCertPath = path.join(RUNNER_TEMP, "tmpcert.pem");
|
const tempCertPath = path.join(runnerTemp, "tmpcert.pem");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fs.unlinkSync(tempCertPath);
|
fs.unlinkSync(tempCertPath);
|
||||||
@@ -106,35 +78,75 @@ export async function runSonarScanner(
|
|||||||
// File doesn't exist, ignore
|
// File doesn't exist, ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.writeFileSync(tempCertPath, SONAR_ROOT_CERT);
|
fs.writeFileSync(tempCertPath, sonarRootCert);
|
||||||
fs.mkdirSync(sslFolder, { recursive: true });
|
fs.mkdirSync(sslFolder, { recursive: true });
|
||||||
|
|
||||||
await exec.exec(`${scannerDir}/jre/bin/java`, [
|
await importCertificateToTruststore(keytoolParams, tempCertPath);
|
||||||
keytoolMainClass,
|
|
||||||
"-storetype",
|
|
||||||
"PKCS12",
|
|
||||||
"-keystore",
|
|
||||||
truststoreFile,
|
|
||||||
"-storepass",
|
|
||||||
truststorePassword,
|
|
||||||
"-noprompt",
|
|
||||||
"-trustcacerts",
|
|
||||||
"-importcert",
|
|
||||||
"-alias",
|
|
||||||
"sonar",
|
|
||||||
"-file",
|
|
||||||
tempCertPath,
|
|
||||||
]);
|
|
||||||
|
|
||||||
scannerArgs.push(
|
scannerArgs.push(
|
||||||
`-Dsonar.scanner.truststorePassword=${truststorePassword}`
|
`-Dsonar.scanner.truststorePassword=${TRUSTSTORE_PASSWORD}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inputArgs) {
|
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);
|
const args = parseArgsStringToArgv(inputArgs);
|
||||||
scannerArgs.push(...args);
|
scannerArgs.push(...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Arguments are sanitized by `exec`
|
||||||
|
*/
|
||||||
await exec.exec(scannerBin, scannerArgs);
|
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"],
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in new issue
Block a user