Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SIGINT-2425: bridge binary renamed and SIGINT-2439: Handle bridge cli bundle sub directory for bidge cli execution #14

Merged
merged 21 commits into from
Nov 6, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ To use Black Duck Security Scan, please follow the steps below:
1. Configure Azure DevOps as described in the [Azure Prerequisites](https://sig-product-docs.synopsys.com/bundle/bridge/page/documentation/c_azure-prerequisites.html) page.
2. Install and configure Black Duck Security Scan for the Black Duck product you are using. <br/>
[Polaris](https://sig-product-docs.synopsys.com/bundle/bridge/page/documentation/c_azure-with-polaris.html) <br/>
[Black Duck](https://sig-product-docs.synopsys.com/bundle/bridge/page/documentation/c_azure-with-blackduck.html) <br/>
[Black Duck SCA](https://sig-product-docs.synopsys.com/bundle/bridge/page/documentation/c_azure-with-blackduck.html) <br/>
[Coverity](https://sig-product-docs.synopsys.com/bundle/bridge/page/documentation/c_azure-with-coverity.html) <br/>
3. For additional configuration options, visit the [Additional Azure Configuration](https://sig-product-docs.synopsys.com/bundle/bridge/page/documentation/c_additional-azure-parameters.html) page.

Expand Down
2,609 changes: 1,331 additions & 1,278 deletions blackduck-security-task/dist/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion blackduck-security-task/dist/index.js.map

Large diffs are not rendered by default.

26 changes: 13 additions & 13 deletions blackduck-security-task/dist/lib1.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"messages": {
"TOOL_LIB_CachingTool": "Caching tool: %s %s %s",
"_TOOL_LIB_CachingTool.comment": "This informational log message indicates that a tool, that was just downloaded, is being copied into the cache directory. %s %s %s represent the tool name, version information, and processor architecture.",
"TOOL_LIB_Downloading": "Downloading: %s",
"_TOOL_LIB_Downloading.comment": "This information log message indicates that a file is being downloaded. %s represents the URL being downloaded.",
"TOOL_LIB_ExtractingArchive": "Extracting archive",
"_TOOL_LIB_ExtractingArchive.comment": "This informational log message indicates that an archive file is being extracted. For example, a .zip file, .7z file, or .tar.gz file.",
"TOOL_LIB_FoundInCache": "Found tool in cache: %s %s %s",
"_TOOL_LIB_FoundInCache.comment": "This informational log message indicates that the request tool is already cached, and does not need to be downloaded again. %s %s %s represent the tool name, version information, and processor architecture.",
"TOOL_LIB_PrependPath": "Prepending PATH environment variable with directory: %s",
"_TOOL_LIB_PrependPath.comment": "This informational log message indicates that a directory is being prepended to the front of the PATH environment variable. The directories specified by the PATH environment variable are used to resolve the location of command line tools."
}
{
"messages": {
"TOOL_LIB_CachingTool": "Caching tool: %s %s %s",
"_TOOL_LIB_CachingTool.comment": "This informational log message indicates that a tool, that was just downloaded, is being copied into the cache directory. %s %s %s represent the tool name, version information, and processor architecture.",
"TOOL_LIB_Downloading": "Downloading: %s",
"_TOOL_LIB_Downloading.comment": "This information log message indicates that a file is being downloaded. %s represents the URL being downloaded.",
"TOOL_LIB_ExtractingArchive": "Extracting archive",
"_TOOL_LIB_ExtractingArchive.comment": "This informational log message indicates that an archive file is being extracted. For example, a .zip file, .7z file, or .tar.gz file.",
"TOOL_LIB_FoundInCache": "Found tool in cache: %s %s %s",
"_TOOL_LIB_FoundInCache.comment": "This informational log message indicates that the request tool is already cached, and does not need to be downloaded again. %s %s %s represent the tool name, version information, and processor architecture.",
"TOOL_LIB_PrependPath": "Prepending PATH environment variable with directory: %s",
"_TOOL_LIB_PrependPath.comment": "This informational log message indicates that a directory is being prepended to the front of the PATH environment variable. The directories specified by the PATH environment variable are used to resolve the location of command line tools."
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
// Copyright (c) 2024 Black Duck Software Inc. All rights reserved worldwide.

import { ErrorCode } from "./enum/ErrorCodes";
export const BRIDGE_CLI_DEFAULT_PATH_MAC = "/bridge-cli"; //Path will be in home
export const BRIDGE_CLI_DEFAULT_PATH_WINDOWS = "\\bridge-cli";
export const BRIDGE_CLI_DEFAULT_PATH_LINUX = "/bridge-cli";
export const BRIDGE_CLI_DEFAULT_PATH_UNIX = "/bridge-cli-bundle"; //Path will be in home
export const BRIDGE_CLI_DEFAULT_PATH_WINDOWS = "\\bridge-cli-bundle";
export const BRIDGE_CLI_DEFAULT_SUBDIRECTORY_PATH_UNIX = "/bridge-cli-bundle"; //Subdirectory for bridle-cli
export const BRIDGE_CLI_DEFAULT_SUBDIRECTORY_PATH_WINDOWS =
"\\bridge-cli-bundle";
export const BRIDGE_CLI_EXECUTABLE_WINDOWS = "bridge-cli.exe";
export const BRIDGE_CLI_EXECUTABLE_MAC_LINUX = "bridge-cli";
export const BRIDGE_CLI_ZIP_FILE_NAME = "bridge-cli.zip";
export const BRIDGE_CLI_ZIP_FILE_NAME = "bridge-cli-bundle.zip";

export const APPLICATION_NAME = "blackduck-extension";
export const AZURE_TOKEN_KEY = "azure_token";
export const POLARIS_AZURE_TOKEN_KEY_CLASSIC_EDITOR = "polarisAzureToken";
export const BLACKDUCKSCA_AZURE_TOKEN_KEY_CLASSIC_EDITOR =
Expand Down
141 changes: 110 additions & 31 deletions blackduck-security-task/src/blackduck-security-task/bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import * as constants from "./application-constant";

import * as inputs from "./input";
import { extractZipped, getRemoteFile, parseToBoolean } from "./utility";
import { readFileSync } from "fs";
import { readFileSync, renameSync } from "fs";
import { DownloadFileResponse } from "./model/download-file-response";
import DomParser from "dom-parser";
import {
Expand Down Expand Up @@ -57,34 +57,56 @@ import { ErrorCode } from "./enum/ErrorCodes";

export class Bridge {
bridgeExecutablePath: string;
bridgeVersion: string;
bridgeArtifactoryURL: string;
bridgeUrlPattern: string;
bridgeUrlLatestPattern: string;

constructor() {
this.bridgeExecutablePath = "";
this.bridgeVersion = "";
this.bridgeArtifactoryURL =
"https://repo.blackduck.com/bds-integrations-release/com/blackduck/integration/bridge-cli";
"https://artifactory.internal.synopsys.com/artifactory/clops-local/clops.sig.synopsys.com/bridge/binaries/bridge-cli-bundle";
this.bridgeUrlPattern = this.bridgeArtifactoryURL.concat(
"/$version/bridge-cli-$version-$platform.zip"
"/$version/bridge-cli-bundle-$version-$platform.zip"
);
this.bridgeUrlLatestPattern = this.bridgeArtifactoryURL.concat(
"/latest/bridge-cli-$platform.zip"
"/latest/bridge-cli-bundle-$platform.zip"
);
}

async extractBridge(fileInfo: DownloadFileResponse): Promise<string> {
const extractZippedFilePath: string =
const bridgeInstallDirectory: string =
inputs.BRIDGECLI_INSTALL_DIRECTORY_KEY || this.getBridgeDefaultPath();

const bridgeCliFullPath = path.join(
String(bridgeInstallDirectory),
String(this.getDefaultBridgeSubDirectory())
);
taskLib.debug("bridgeCliFullPath: " + bridgeCliFullPath);

// Clear the existing bridge, if available
if (taskLib.exist(extractZippedFilePath)) {
await taskLib.rmRF(extractZippedFilePath);
if (taskLib.exist(bridgeCliFullPath)) {
await taskLib.rmRF(bridgeCliFullPath);
}

await extractZipped(fileInfo.filePath, extractZippedFilePath);
await extractZipped(fileInfo.filePath, bridgeInstallDirectory);

return Promise.resolve(extractZippedFilePath);
if (this.bridgeVersion != "") {
const bridgePathWithVersion = path.join(
String(bridgeInstallDirectory),
String(this.getBridgeSubDirectoryWithVersion())
);
taskLib.debug("bridgePathWithVersion: " + bridgePathWithVersion);
if (taskLib.exist(bridgePathWithVersion)) {
taskLib.debug(
"Renaming bridge versioned path to default bridge-cli path"
);
renameSync(bridgePathWithVersion, bridgeCliFullPath);
}
}
taskLib.debug("Bridge Executable Path: " + bridgeCliFullPath);
return Promise.resolve(bridgeCliFullPath);
}

async executeBridgeCommand(
Expand All @@ -93,6 +115,7 @@ export class Bridge {
command: string
): Promise<number> {
taskLib.debug("extractedPath: ".concat(executablePath));
process.env["BRIDGE_CACHE_DIR"] = executablePath;

const executableBridgePath = await this.setBridgeExecutablePath(
executablePath
Expand Down Expand Up @@ -360,11 +383,12 @@ export class Bridge {
);
}
// To check whether bridge already exists with same version mentioned in bridge url
const versionsArray = bridgeUrl.match(".*bridge-cli-([0-9.]*).*");
const versionsArray = bridgeUrl.match(".*bridge-cli-bundle-([0-9.]*).*");
if (versionsArray) {
version = versionsArray[1];
if (!version) {
const regex = /\w*(bridge-cli-(win64|linux64|macosx|macos_arm).zip)/;
const regex =
/\w*(bridge-cli-bundle-(win64|linux64|macosx|macos_arm).zip)/;
version = await this.getBridgeVersionFromLatestURL(
bridgeUrl.replace(regex, "versions.txt")
);
Expand Down Expand Up @@ -400,6 +424,8 @@ export class Bridge {
}
}

this.bridgeVersion = version;

console.info(DOWNLOADING_BRIDGE_CLI);
console.info(BRIDGE_CLI_URL_MESSAGE.concat(bridgeUrl));
return bridgeUrl;
Expand Down Expand Up @@ -484,7 +510,7 @@ export class Bridge {
): Promise<boolean> {
try {
const contents = readFileSync(bridgeVersionFilePath, "utf-8");
return contents.includes("Bridge CLI Package: ".concat(bridgeVersion));
return contents.includes("bridge-cli-bundle: ".concat(bridgeVersion));
} catch (e) {
console.info(ERROR_READING_VERSION_FILE.concat((e as Error).message));
}
Expand Down Expand Up @@ -519,7 +545,7 @@ export class Bridge {
const htmlResponse = (await httpResponse.readBody()).trim();
const lines = htmlResponse.split("\n");
for (const line of lines) {
if (line.includes("Bridge CLI Package")) {
if (line.includes("bridge-cli-bundle")) {
return line.split(":")[1].trim();
}
}
Expand All @@ -539,15 +565,10 @@ export class Bridge {
let bridgeDefaultPath = "";
const osName = process.platform;

if (osName === "darwin") {
if (osName === "darwin" || osName === "linux") {
bridgeDefaultPath = path.join(
process.env["HOME"] as string,
constants.BRIDGE_CLI_DEFAULT_PATH_MAC
);
} else if (osName === "linux") {
bridgeDefaultPath = path.join(
process.env["HOME"] as string,
constants.BRIDGE_CLI_DEFAULT_PATH_LINUX
constants.BRIDGE_CLI_DEFAULT_PATH_UNIX
);
} else if (osName === "win32") {
bridgeDefaultPath = path.join(
Expand All @@ -559,6 +580,56 @@ export class Bridge {
return bridgeDefaultPath;
}

getDefaultBridgeSubDirectory(): string {
let bridgeSubDirectory = "";
const osName = process.platform;

if (osName === "darwin" || osName === "linux") {
let osPlatform = constants.LINUX_PLATFORM;
if (osName === "darwin") {
osPlatform = this.getMacOsSuffix();
}
bridgeSubDirectory =
constants.BRIDGE_CLI_DEFAULT_SUBDIRECTORY_PATH_UNIX.concat("-").concat(
osPlatform
);
} else if (osName === "win32") {
bridgeSubDirectory =
constants.BRIDGE_CLI_DEFAULT_SUBDIRECTORY_PATH_WINDOWS.concat(
"-"
).concat(constants.WINDOWS_PLATFORM);
}
taskLib.debug("bridgeSubDirectory:" + bridgeSubDirectory);
return bridgeSubDirectory;
}

getBridgeSubDirectoryWithVersion(): string {
let bridgeSubDirectoryWithVersion = "";
const osName = process.platform;
const version =
this.bridgeVersion != "" ? "-".concat(this.bridgeVersion) : "";

if (osName === "darwin" || osName === "linux") {
let osPlatform = constants.LINUX_PLATFORM;
if (osName === "darwin") {
osPlatform = this.getMacOsSuffix();
}
bridgeSubDirectoryWithVersion =
constants.BRIDGE_CLI_DEFAULT_SUBDIRECTORY_PATH_UNIX.concat(version)
.concat("-")
.concat(osPlatform);
} else if (osName === "win32") {
bridgeSubDirectoryWithVersion =
constants.BRIDGE_CLI_DEFAULT_SUBDIRECTORY_PATH_WINDOWS.concat(version)
.concat("-")
.concat(constants.WINDOWS_PLATFORM);
}
taskLib.debug(
"bridgeSubDirectoryWithVersion:" + bridgeSubDirectoryWithVersion
);
return bridgeSubDirectoryWithVersion;
}

// Get bridge version url
getVersionUrl(version: string): string {
const osName = process.platform;
Expand Down Expand Up @@ -597,12 +668,7 @@ export class Bridge {
const osName = process.platform;
let bridgeDownloadUrl = this.bridgeUrlLatestPattern;
if (osName === "darwin") {
const cpuInfo = os.cpus();
taskLib.debug(`cpuInfo :: ${JSON.stringify(cpuInfo)}`);
const isIntel = cpuInfo[0].model.includes("Intel");
const osSuffix = isIntel
? constants.MAC_INTEL_PLATFORM
: constants.MAC_ARM_PLATFORM;
const osSuffix = this.getMacOsSuffix();
bridgeDownloadUrl = bridgeDownloadUrl.replace("$platform", osSuffix);
} else if (osName === "linux") {
bridgeDownloadUrl = bridgeDownloadUrl.replace(
Expand All @@ -619,6 +685,13 @@ export class Bridge {
return bridgeDownloadUrl;
}

getMacOsSuffix(): string {
const cpuInfo = os.cpus();
taskLib.debug(`cpuInfo :: ${JSON.stringify(cpuInfo)}`);
const isIntel = cpuInfo[0].model.includes("Intel");
return isIntel ? constants.MAC_INTEL_PLATFORM : constants.MAC_ARM_PLATFORM;
}

async setBridgeExecutablePath(filePath: string): Promise<string> {
if (process.platform === "win32") {
this.bridgeExecutablePath = path.join(
Expand All @@ -636,11 +709,17 @@ export class Bridge {

//contains executable path with extension file
async getBridgePath(): Promise<string> {
let bridgeDirectoryPath = this.getBridgeDefaultPath();
let bridgeDirectoryPath = path.join(
String(this.getBridgeDefaultPath()),
String(this.getDefaultBridgeSubDirectory())
);
if (BRIDGECLI_INSTALL_DIRECTORY_KEY) {
bridgeDirectoryPath = BRIDGECLI_INSTALL_DIRECTORY_KEY;
bridgeDirectoryPath = path.join(
String(BRIDGECLI_INSTALL_DIRECTORY_KEY),
String(this.getDefaultBridgeSubDirectory())
);
console.info(LOOKING_FOR_BRIDGE_CLI_INSTALL_DIR);
if (!taskLib.exist(bridgeDirectoryPath)) {
if (!taskLib.exist(BRIDGECLI_INSTALL_DIRECTORY_KEY)) {
throw new Error(
BRIDGE_CLI_INSTALL_DIRECTORY_NOT_EXISTS.concat(
constants.SPACE
Expand All @@ -649,8 +728,8 @@ export class Bridge {
}
} else {
console.info(LOOKING_FOR_BRIDGE_CLI_DEFAULT_PATH);
if (ENABLE_NETWORK_AIRGAP && this.getBridgeDefaultPath()) {
if (!taskLib.exist(this.getBridgeDefaultPath())) {
if (ENABLE_NETWORK_AIRGAP && bridgeDirectoryPath) {
if (!taskLib.exist(bridgeDirectoryPath)) {
throw new Error(
BRIDGE_CLI_DEFAULT_DIRECTORY_NOT_EXISTS.concat(
constants.SPACE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ import {
export class BridgeToolsParameter {
tempDir: string;
private static STAGE_OPTION = "--stage";
private static BLACKDUCK_STAGE = "blackduck";
private static BLACKDUCKSCA_STAGE = "blackducksca";
private static BD_STATE_FILE_NAME = "bd_input.json";
private static INPUT_OPTION = "--input";
private static POLARIS_STAGE = "polaris";
Expand Down Expand Up @@ -420,7 +420,7 @@ export class BridgeToolsParameter {
command = BridgeToolsParameter.STAGE_OPTION.concat(
BridgeToolsParameter.SPACE
)
.concat(BridgeToolsParameter.BLACKDUCK_STAGE)
.concat(BridgeToolsParameter.BLACKDUCKSCA_STAGE)
.concat(BridgeToolsParameter.SPACE)
.concat(BridgeToolsParameter.INPUT_OPTION)
.concat(BridgeToolsParameter.SPACE)
Expand Down Expand Up @@ -607,7 +607,7 @@ export class BridgeToolsParameter {
) {
throw new Error(
"Invalid value for "
.concat(constants.BLACKDUCK_FIXPR_MAXCOUNT_KEY)
.concat(constants.BLACKDUCKSCA_FIXPR_MAXCOUNT_KEY)
.concat(constants.SPACE)
.concat(ErrorCode.INVALID_BLACKDUCKSCA_FIXPR_MAXCOUNT.toString())
);
Expand All @@ -617,10 +617,10 @@ export class BridgeToolsParameter {
);
if (createSinglePr && inputs.BLACKDUCKSCA_FIXPR_MAXCOUNT) {
throw new Error(
constants.BLACKDUCK_FIXPR_MAXCOUNT_KEY.concat(
constants.BLACKDUCKSCA_FIXPR_MAXCOUNT_KEY.concat(
" is not applicable with "
)
.concat(constants.BLACKDUCK_FIXPR_CREATE_SINGLE_PR_KEY)
.concat(constants.BLACKDUCKSCA_FIXPR_CREATE_SINGLE_PR_KEY)
.concat(constants.SPACE)
.concat(
ErrorCode.BLACKDUCKSCA_FIXPR_MAXCOUNT_NOT_APPLICABLE.toString()
Expand Down
2 changes: 1 addition & 1 deletion blackduck-security-task/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"id": "edd0f606-d9e3-4294-9d0d-64f9f1aadfde",
"name": "BlackDuckSecurityScan",
"friendlyName": "Black Duck Security Scan",
"description": "Run security scans on Polaris, Black Duck, Coverity or Software Risk Manager (SRM) platforms",
"description": "Run security scans on Polaris, Black Duck SCA, Coverity or Software Risk Manager (SRM) platforms",
"helpMarkDown": "",
"category": "Utility",
"author": "Black Duck Software Inc.",
Expand Down
Loading