diff --git a/package-lock.json b/package-lock.json index e8c7ef5..77edd68 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "vscode-splunk-soar", - "version": "0.0.30", + "version": "0.0.33", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "vscode-splunk-soar", - "version": "0.0.30", + "version": "0.0.33", "license": "Apache-2.0", "dependencies": { "@babel/core": "^7.19.6", diff --git a/package.json b/package.json index 94091f6..df042cb 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "icon": "media/soarcloud.png", "publisher": "Splunk", "license": "Apache-2.0", - "version": "0.0.32", + "version": "0.0.33", "engines": { "vscode": "^1.72.0" }, diff --git a/src/commands/environments/addEnvironmentWizard.ts b/src/commands/environments/addEnvironmentWizard.ts index 55b7cd9..85b6ac6 100644 --- a/src/commands/environments/addEnvironmentWizard.ts +++ b/src/commands/environments/addEnvironmentWizard.ts @@ -3,7 +3,7 @@ import {MultiStepInput} from '../../wizard/MultiStepInput' import { ConnectEnvironment } from './environments'; const wizardTitle = "Add Environment" -const totalSteps = 4 +const totalSteps = 5 function shouldResume() { // Could show a notification with the option to resume. @@ -44,14 +44,38 @@ async function connectSslVerifyInput(input: MultiStepInput, state: Partial conectUsernameInput(input, state); + return (input: MultiStepInput) => authTypeInput(input, state); } -async function conectUsernameInput(input: MultiStepInput, state: Partial){ - state.username = await input.showInputBox({ +async function authTypeInput(input: MultiStepInput, state: Partial){ + let authPick = await input.showQuickPick({ title: wizardTitle, step: 3, totalSteps: totalSteps, + placeholder: 'Auth type', + value: state.authType || '', + items: [{"label": "local"}, {"label": "token"}], + shouldResume: shouldResume, + ignoreFocusOut: true, + canSelectMany: false + }); + + if (authPick[0].label === "local") { + state.authType = "local"; + return (input: MultiStepInput) => connectUsernameInput(input, state); + } + else { + state.authType = "token"; + return (input: MultiStepInput) => connectTokenNameInput(input, state); + } + +} + +async function connectUsernameInput(input: MultiStepInput, state: Partial){ + state.username = await input.showInputBox({ + title: wizardTitle, + step: 4, + totalSteps: totalSteps, value: state.username || '', prompt: `Username`, shouldResume: shouldResume, @@ -62,10 +86,41 @@ async function conectUsernameInput(input: MultiStepInput, state: Partial connectPasswordInput(input, state); } +async function connectTokenNameInput(input: MultiStepInput, state: Partial){ + state.username = await input.showInputBox({ + title: wizardTitle, + step: 4, + totalSteps: totalSteps, + value: state.username || '', + prompt: `Token name`, + shouldResume: shouldResume, + validate: validateNameIsUnique, + ignoreFocusOut: true + }); + + return (input: MultiStepInput) => connectTokenInput(input, state); +} + +async function connectTokenInput(input: MultiStepInput, state: Partial){ + state.password = await input.showInputBox({ + title: wizardTitle, + step: 5, + totalSteps: totalSteps, + value: '', + prompt: `Token`, + shouldResume: shouldResume, + validate: validateNameIsUnique, + isPassword: true, + ignoreFocusOut: true + }); + + return; +} + async function connectPasswordInput(input: MultiStepInput, state: Partial){ state.password = await input.showInputBox({ title: wizardTitle, - step: 4, + step: 5, totalSteps: totalSteps, value: '', prompt: `Password`, diff --git a/src/commands/environments/environments.ts b/src/commands/environments/environments.ts index 9683978..ecc00b5 100644 --- a/src/commands/environments/environments.ts +++ b/src/commands/environments/environments.ts @@ -13,9 +13,11 @@ export const ACTIVE_ENV_KEY = "splunkSOAR.activeEnvironment" export interface BaseConnectEnvironment { url: string, sslVerify: boolean, - username: string + username: string, + authType: string } + export interface ConnectEnvironment extends BaseConnectEnvironment { password: string } @@ -37,7 +39,7 @@ export async function addEnvironment(context: vscode.ExtensionContext) { } let envKey = deriveEnvKey(state.url, state.username) - let newEnv: ConfiguredConnectEnvironment = {"key": envKey , "url": state.url, "username": state.username, "sslVerify": state.sslVerify} + let newEnv: ConfiguredConnectEnvironment = {"key": envKey , "url": state.url, "username": state.username, "sslVerify": state.sslVerify, "authType": state.authType} let currentEnvironments = listEnvironments(context) @@ -132,6 +134,10 @@ export async function getEnvironment(context: vscode.ExtensionContext, envKey: s let env = currentEnvironments.find(env => env.key == envKey)! + // If this environment was created in an older version of the extension, authType + // will be undefined. + env.authType ??= "local"; + return {...env, "password": password} } @@ -172,7 +178,7 @@ export async function environmentVersion(context: vscode.ExtensionContext, envir } let environment = await getEnvironment(context, envKey) - let client = new SoarClient(environment.url, environment.username, environment.password, environment.sslVerify) + let client = new SoarClient(environment.url, environment.authType, environment.username, environment.password, environment.sslVerify) let response = await client.version().catch((err) => { return Promise.reject(err) @@ -186,7 +192,7 @@ export async function copyPasswordToClipboard(context: vscode.ExtensionContext, let env: ConfiguredConnectEnvironment = environmentContext.data let environment = await getEnvironment(context, env.key) - let client = new SoarClient(environment.url, environment.username, environment.password, environment.sslVerify) + let client = new SoarClient(environment.url, environment.authType, environment.username, environment.password, environment.sslVerify) vscode.env.clipboard.writeText(client.password) vscode.window.setStatusBarMessage("Copied password to clipboard", 2000) diff --git a/src/soar/client.ts b/src/soar/client.ts index b360c87..4a0d42a 100644 --- a/src/soar/client.ts +++ b/src/soar/client.ts @@ -16,7 +16,7 @@ export class SoarClient { httpClient: AxiosInstance fileClient: AxiosInstance - constructor(server: string, username: string, password: string, sslVerify: boolean) { + constructor(server: string, authType: string, username: string, password: string, sslVerify: boolean) { this.server = server this.username = username this.password = password @@ -24,7 +24,8 @@ export class SoarClient { const axiosConfig = { baseURL: `${server}/rest/`, - auth: {username: username, password: password}, + ...(authType === "local" && {auth: {username: username, password: password}}), + ...(authType === "token" && {headers: {"ph-auth-token": password} }) } this.httpClient = axios.create(axiosConfig) @@ -277,14 +278,14 @@ export class SoarClient { export async function getClientForActiveEnvironment(context: vscode.ExtensionContext): Promise { - let {url, username, sslVerify, password} = await getActiveEnvironment(context) + let {url, username, sslVerify, password, authType} = await getActiveEnvironment(context) - return new SoarClient(url, username, password, sslVerify) + return new SoarClient(url, authType, username, password, sslVerify) } export async function getClientForEnvironment(context: vscode.ExtensionContext, envKey: string): Promise { - let {url, username, sslVerify, password} = await getEnvironment(context, envKey) + let {url, username, sslVerify, password, authType} = await getEnvironment(context, envKey) - return new SoarClient(url, username, password, sslVerify) + return new SoarClient(url, authType, username, password, sslVerify) } \ No newline at end of file