Skip to content

Commit

Permalink
Merge pull request #53 from demisto/ciac-6603/adapt-xsoar-coonnection…
Browse files Browse the repository at this point in the history
…-config-dialog-to-select-xsoar-version

Support for xsoar 8/xsiam configuration
  • Loading branch information
ilaner authored Apr 11, 2024
2 parents 79d4b09 + 80af68e commit a523217
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 30 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
# Unreleased

- Fixed an issue with `demisto-sdk` arguments where there are special characters in the path.
- Added support for XSOAR NG/ XSIAM env vars setting.
- Added support for comments in `.env` file.

# [0.7.0] (2023-11-21)

Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ This will configure `.env` file with the following environment variables:
* DEMISTO_USERNAME (XSOAR username)
* DEMISTO_PASSWORD (XSOAR password)
* DEMISTO_API_KEY (XSOAR API key)
* XSIAM_AUTH_ID (XSOAR/XSIAM Auth ID) (Relevant for XSOAR 8/XSIAM)
* DEMISTO_VERIFY_SSL (Verify SSL in XSOAR, `true` or `false`)
## Configure XSOAR unit tests

Expand Down Expand Up @@ -86,7 +87,7 @@ If the `license/cla` status check remains on *Pending*, even though all contribu

* `npm install`
* `npm run compile`
* `pip demisto-sdk`
* `pip install demisto-sdk`

### Main Locations

Expand Down
108 changes: 81 additions & 27 deletions src/devEnvs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ import JSON5 from "json5";
import * as dsdk from "./demistoSDKWrapper";
import * as fs from "fs-extra";
import { spawn } from "child_process";
import { parse, stringify } from "envfile";
import { getContentPath } from "./tools";
import { getContentPath, parse, stringify } from "./tools";

enum Platform {
XSOAR6 = 'XSOAR 6',
XSOAR8_XSIAM = 'XSOAR 8/XSIAM'
}

export async function installDevEnv(): Promise<void> {
const workspaces = vscode.workspace.workspaceFolders;
Expand All @@ -28,6 +31,7 @@ export async function installDevEnv(): Promise<void> {
title: "Select dependencies to install",
placeHolder: "Leave blank to skip dependencies installation",
canPickMany: true,
ignoreFocusOut: true,
})
.then(async (dependencies) => {
if (dependencies) {
Expand All @@ -53,6 +57,8 @@ export async function installDevEnv(): Promise<void> {
title: "Do you want to install pre-commit hooks?",
placeHolder:
"Installing pre-commit hooks will run `validate` and `lint` before every commit",
ignoreFocusOut: true,

})
.then(async (answer) => {
if (answer === "Yes") {
Expand All @@ -76,6 +82,8 @@ export async function installDevEnv(): Promise<void> {
title: "Would you like to configure the connection to XSOAR?",
placeHolder:
"This will ask you to configure the connection XSOAR, allowing Demisto-SDK commands such as upload and download",
ignoreFocusOut: true,

})
.then(async (answer) => {
if (answer === "Yes") {
Expand Down Expand Up @@ -132,12 +140,11 @@ async function getDemistoSDKPath(
let demistoSDKPathString = path.resolve(demistoSDKParentPath, "demisto-sdk");
if (!(await fs.pathExists(demistoSDKPathString))) {
Logger.info(`demisto-sdk not found in ${demistoSDKPathString}`);
const answer = await vscode.window.showQuickPick(
["Select Demisto-SDK path", "Clone repository"],
{
placeHolder:
"Do you want to use an existing repository or clone a new one?",
const answer = await vscode.window
.showQuickPick(["Select Demisto-SDK path", "Clone repository"], {
placeHolder: "Do you want to use an existing repository or clone a new one?",
title: "Select Demisto-SDK repository path",
ignoreFocusOut: true,
}
);
if (answer === "Clone repository") {
Expand Down Expand Up @@ -214,19 +221,20 @@ export async function developDemistoSDK(): Promise<void> {
`demisto-sdk_content.code-workspace`
);
fs.writeJsonSync(workspaceOutput, workspace, { spaces: 2 });
const response = await vscode.window.showQuickPick(
["Existing Window", "New Window"],
{
placeHolder:
"Select if you want to open in existing window or new window",
const response = await vscode.window
.showQuickPick(["Existing Window", "New Window"], {
placeHolder: "Select if you want to open in existing window or new window",
title: "Where would you like to open the environment?",
ignoreFocusOut: true,
}
);
const openInNewWindow = response === "New Window";
const installDemistoSDK = await vscode.window.showQuickPick(["Yes", "No"], {
title: "Do you want to install Demisto-SDK dependencies?",
placeHolder: " Will run poetry install in the demisto-sdk repository",
});
const installDemistoSDK = await vscode.window
.showQuickPick(["Yes", "No"], {
title: "Do you want to install Demisto-SDK dependencies?",
placeHolder: " Will run poetry install in the demisto-sdk repository",
ignoreFocusOut: true,
});
if (installDemistoSDK === "Yes") {
spawn(`cd ${demistoSDKPathString} && poetry install`);
}
Expand All @@ -239,6 +247,7 @@ export async function developDemistoSDK(): Promise<void> {

export async function configureDemistoVars(): Promise<void> {
const workspaces = vscode.workspace.workspaceFolders;

if (!workspaces) {
vscode.window.showErrorMessage("Could not find a valid workspace");
return;
Expand All @@ -256,6 +265,16 @@ export async function configureDemistoVars(): Promise<void> {
if (!env) {
env = {};
}

// Select configured platform
const configuredPlatform = await vscode.window
.showQuickPick([Platform.XSOAR6, Platform.XSOAR8_XSIAM], {
title: "Platform",
placeHolder: "Select configured platform",
ignoreFocusOut: true,
}) ?? Platform.XSOAR6;

// XSOAR url
await vscode.window
.showInputBox({
title: "XSOAR URL",
Expand All @@ -270,6 +289,8 @@ export async function configureDemistoVars(): Promise<void> {
vscode.window.showInformationMessage(
"Enter either XSOAR username and password, or an API key"
);

// XSOAR username
await vscode.window
.showInputBox({
title: "XSOAR username (optional)",
Expand All @@ -281,6 +302,8 @@ export async function configureDemistoVars(): Promise<void> {
env["DEMISTO_USERNAME"] = username;
}
});

// XSOAR password
await vscode.window
.showInputBox({
title: "XSOAR password (optional)",
Expand All @@ -294,6 +317,7 @@ export async function configureDemistoVars(): Promise<void> {
}
});

// XSOAR API Key
await vscode.window
.showInputBox({
title: "XSOAR API key (optional)",
Expand All @@ -306,10 +330,31 @@ export async function configureDemistoVars(): Promise<void> {
env["DEMISTO_API_KEY"] = apiKey;
}
});

// XSIAM Auth ID
if (configuredPlatform === Platform.XSOAR8_XSIAM){
await vscode.window
.showInputBox({
title: "XSIAM Auth ID",
ignoreFocusOut: true,
}).then((authId) => {
if (authId){
env["XSIAM_AUTH_ID"] = authId;
}
})
} else {
// Commenting XSIAM_AUTH_ID if exist.
if (env["XSIAM_AUTH_ID"])
env["# XSIAM_AUTH_ID"] = `${env["XSIAM_AUTH_ID"]}`;
delete env["XSIAM_AUTH_ID"];
}

// Verify SSL
await vscode.window
.showQuickPick(["true", "false"], {
title: "XSOAR SSL verification",
placeHolder: "Should XSOAR SSL verification be enabled?",
ignoreFocusOut: true,
})
.then((verifySSL) => {
if (verifySSL) {
Expand Down Expand Up @@ -383,6 +428,7 @@ export async function setupIntegrationEnv(dirPath: string): Promise<void> {
{
title: `Do you want to open a new workspace with a virtual environment, or inside a Devcontainer?`,
placeHolder: "Virtual environment creation is slow, but provide better IDE autocompletion",
ignoreFocusOut: true,
}
)
if (!answer) {
Expand All @@ -400,11 +446,10 @@ export async function setupIntegrationEnv(dirPath: string): Promise<void> {
Logger.info("Virtualenv exists.");
vsCodePath = path.join(packDir, ".vscode");
await vscode.window
.showQuickPick(
["Open existing virtual environment", "Create new virtual environment"],
{
.showQuickPick(["Open existing virtual environment", "Create new virtual environment"], {
title: `Found virtual environment in ${filePath.name}`,
placeHolder: "Creating virtual environment can take few minutes",
ignoreFocusOut: true,
}
)
.then(async (answer) => {
Expand All @@ -428,8 +473,18 @@ export async function setupIntegrationEnv(dirPath: string): Promise<void> {
let instanceName: string | undefined;

if (process.env.DEMISTO_SDK_GCP_PROJECT_ID) {
secretId = await vscode.window.showInputBox({ title: "Do you want to fetch a custom secret from GCP?", placeHolder: "Enter secret name, leave blank to skip" })
instanceName = await vscode.window.showInputBox({ title: "Create an instance on XSOAR/XSIAM", placeHolder: "Enter the instance name. Leave blank to skip" })
secretId = await vscode.window
.showInputBox({
title: "Do you want to fetch a custom secret from GCP?",
placeHolder: "Enter secret name, leave blank to skip",
ignoreFocusOut: true,
})
instanceName = await vscode.window
.showInputBox({
title: "Create an instance on XSOAR/XSIAM",
placeHolder: "Enter the instance name. Leave blank to skip",
ignoreFocusOut: true,
})
}
await dsdk.setupEnv(dirPath, shouldCreateVirtualenv, shouldOverwriteVirtualenv, secretId, instanceName);
if (answer === "Devcontainer (advanced)") {
Expand All @@ -446,12 +501,11 @@ export async function setupIntegrationEnv(dirPath: string): Promise<void> {
`content-${filePath.name}.code-workspace`
);
fs.writeJsonSync(workspaceOutput, workspace, { spaces: 2 });
const response = await vscode.window.showQuickPick(
["Existing Window", "New Window"],
{
placeHolder:
"Select if you want to open in existing window or new window",
title: "Where would you like to open the environment?",
const response = await vscode.window
.showQuickPick(["Existing Window", "New Window"],{
placeHolder: "Select if you want to open in existing window or new window",
title: "Where would you like to open the environment?",
ignoreFocusOut: true,
}
);
const openInNewWindow = response === "New Window";
Expand Down
4 changes: 2 additions & 2 deletions src/runAndDebug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ async function argsManagment(argumentNames: vscode.QuickPickItem[], args: Argumn
}
}).then(() => { return [query, flag] })
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
async function runIntegration(ymlObject: any, runOrDebug: string): Promise<Map<string, string> | undefined> {
// Map for query the command
const query: Map<string, string> = new Map<string, string>()
Expand Down Expand Up @@ -223,7 +223,7 @@ async function runIntegration(ymlObject: any, runOrDebug: string): Promise<Map<s
}
}).then(() => { return query })
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
async function runScript(ymlObject: any, runOrDebug: string): Promise<Map<string, string>> {
const query: Map<string, string> = new Map<string, string>()
const [argumentNames, argsRequired] = QuickPickItemForArgs(ymlObject.args)
Expand Down
58 changes: 58 additions & 0 deletions src/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,4 +278,62 @@ export function getWebviewRemoveCommandButton(commandIndex: number): string {
});
</script>
`;
}

/** We don't normalize anything, so it is just strings and strings. */
export type Data = Record<string, string>

/** We typecast the value as a string so that it is compatible with envfiles. */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type Input = Record<string, any>

// This function is copied from https://github.com/bevry/envfile/pull/213
// TODO - Utilize 'parse()' from 'envfile' once the official package adopts the mentioned PR.
/** Parse an envfile string. */
export function parse(src: string): Data {
const result: Data = {}
const lines = src.toString().split('\n')
let notHandleCount = 0
for (const [lineIndex, line] of lines.entries()) {
const match = line.match(/^([^=:#]+?)[=:](.*)/)
if (match) {
const key = match[1].trim()
const value = match[2].trim().replace(/['"]+/g, '')
result[key] = value
} else if ( line.trim().startsWith('#')) {
const sym = Symbol.for(`comment#${lineIndex - notHandleCount}`)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
result[sym as any] = line
} else {
notHandleCount++
}
}
return result
}

// This function is copied from https://github.com/bevry/envfile/pull/213
// TODO - Utilize 'stringify()' from 'envfile' once the official package adopts the mentioned PR.
/** Turn an object into an envfile string. */
export function stringify(obj: Input): string {
const result = []
for (const key of Reflect.ownKeys(obj)) {
const value = obj[key as string]
if (key) {
if (
typeof key === 'symbol' &&
(key as symbol).toString().startsWith('Symbol(comment')
) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [_, lineIndex] = (
(key as symbol).description ?? 'comment#0'
).split('#')
result.splice(parseInt(lineIndex, 10), 0, value)

} else {
const line = `${key as string}=${String(value)}`
result.push(line)
}
}
}
return result.join('\n')
}

0 comments on commit a523217

Please sign in to comment.