Skip to content

Commit

Permalink
Added additional checks for debug config/certificate
Browse files Browse the repository at this point in the history
Signed-off-by: Seb Julliand <[email protected]>
  • Loading branch information
sebjulliand committed Aug 23, 2024
1 parent 815ed05 commit b670775
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 41 deletions.
6 changes: 5 additions & 1 deletion src/api/debug/certificates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ export async function setup(connection: IBMi, imported?: ImportedCertificate) {
debugConfig.set("JAVA_HOME", javaHome);
debugConfig.set("DEBUG_SERVICE_KEYSTORE_FILE", certificatePath);
debugConfig.set("DEBUG_SERVICE_KEYSTORE_PASSWORD", encryptResult.stdout);
debugConfig.set("CODE4IDEBUG", `$([ -f $DBGSRV_WRK_DIR/${ENCRYPTION_KEY} ] && cp $DBGSRV_WRK_DIR/${ENCRYPTION_KEY} $DBGSRV_WRK_DIR/key.properties)`);
debugConfig.setCode4iDebug(`$([ -f $DBGSRV_WRK_DIR/${ENCRYPTION_KEY} ] && cp $DBGSRV_WRK_DIR/${ENCRYPTION_KEY} $DBGSRV_WRK_DIR/key.properties)`);
debugConfig.save();
}
else {
Expand All @@ -210,6 +210,10 @@ export async function setup(connection: IBMi, imported?: ImportedCertificate) {
});
}

export async function debugKeyFileExists(connection: IBMi, debugConfig: DebugConfiguration) {
return await connection.content.testStreamFile(`${debugConfig.getRemoteServiceWorkDir()}/.code4i.debug`, "f");
}

export async function remoteCertificatesExists(debugConfig?: DebugConfiguration) {
const content = instance.getContent();
if (content) {
Expand Down
10 changes: 9 additions & 1 deletion src/api/debug/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,14 @@ export class DebugConfiguration {
getRemoteServiceWorkDir() {
return this.getOrDefault("DBGSRV_WRK_DIR", "/QIBM/UserData/IBMiDebugService");
}

getCode4iDebug() {
return this.get("CODE4IDEBUG");
}

setCode4iDebug(value: string) {
return this.set("CODE4IDEBUG", value);
}
}

interface DebugServiceDetails {
Expand Down Expand Up @@ -145,7 +153,7 @@ export async function getDebugServiceDetails(): Promise<DebugServiceDetails> {
console.log(e);
}
}
else{
else {
details = {
version: `1.0.0`,
java: `8`,
Expand Down
5 changes: 3 additions & 2 deletions src/api/debug/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,9 @@ export async function initialize(context: ExtensionContext) {
const ptfInstalled = server.debugPTFInstalled();

if (ptfInstalled) {
const remoteCertsExists = await certificates.remoteCertificatesExists();
if (remoteCertsExists) {
const debugConfig = await new DebugConfiguration().load()
const remoteCertsExists = await certificates.remoteCertificatesExists(debugConfig);
if (remoteCertsExists && await certificates.debugKeyFileExists(connection, debugConfig) && debugConfig.getCode4iDebug()) {
await certificates.downloadClientCert(connection);
vscode.window.showInformationMessage(`Debug Service Certificate already exist on the server. The client certificate has been downloaded to enable debugging.`);
}
Expand Down
10 changes: 6 additions & 4 deletions src/locale/ids/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@
"objectBrowser.uploadAndReplaceMemberAsFile.infoMessage": "Member was uploaded.",
"offline": "Offline",
"online": "Online",
"open":"Open",
"open": "Open",
"open.service.configuration": "Open configuration",
"overview": "Overview",
"overwrite": "Overwrite",
Expand Down Expand Up @@ -394,8 +394,8 @@
"sandbox.noconnection.modal.title": "Oh no! The sandbox is down.",
"sandbox.noPassword": "Connection to {0} ended as no password was provided.",
"save": "Save",
"searchView.find.message":"{0} file(s) named '{1}'",
"searchView.search.message":"{0} file(s) contain(s) '{1}'",
"searchView.find.message": "{0} file(s) named '{1}'",
"searchView.search.message": "{0} file(s) contain(s) '{1}'",
"service.certificate.exists": "Remote service certificate exists",
"shortcut": "shortcut",
"size": "Size",
Expand All @@ -422,5 +422,7 @@
"type": "Type",
"USER_DIRECTORY": "User directory",
"username": "Username",
"Yes": "Yes"
"Yes": "Yes",
"debug.service.config.incomplete": "Incomplete configuration",
"debug.service.config.incomplete.detail": "Certificate needs to be regenerated"
}
87 changes: 54 additions & 33 deletions src/views/debugView.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import vscode from "vscode";
import { Tools } from "../api/Tools";
import { checkClientCertificate, remoteCertificatesExists } from "../api/debug/certificates";
import { checkClientCertificate, debugKeyFileExists, remoteCertificatesExists } from "../api/debug/certificates";
import { DebugConfiguration, getDebugServiceDetails } from "../api/debug/config";
import { DebugJob, getDebugServerJob, getDebugServiceJob, isDebugEngineRunning, readActiveJob, readJVMInfo, startServer, startService, stopServer, stopService } from "../api/debug/server";
import { instance } from "../instantiate";
Expand All @@ -14,7 +14,7 @@ type Certificates = {
localCertificateIssue?: string
}

type CertificateIssue = {
type DebugServiceIssue = {
label: string
detail?: string
context: string
Expand Down Expand Up @@ -74,6 +74,8 @@ class DebugBrowser implements vscode.TreeDataProvider<BrowserItem> {
const connection = instance.getConnection();
if (connection) {
const debugConfig = await new DebugConfiguration().load();
const keyFileExists = await debugKeyFileExists(connection, debugConfig);

const certificates: Certificates = {
remoteCertificate: await remoteCertificatesExists(debugConfig),
remoteCertificatePath: debugConfig.getRemoteServiceCertificatePath()
Expand All @@ -89,22 +91,25 @@ class DebugBrowser implements vscode.TreeDataProvider<BrowserItem> {
}

return Promise.all([
getDebugServerJob().then(job =>
getDebugServerJob().then(debugJob =>
new DebugJobItem("server",
t("debug.server"),
startServer,
stopServer,
job
)
{
startFunction: startServer,
stopFunction: stopServer,
debugJob
})
),
getDebugServiceJob().then(job =>
getDebugServiceJob().then(debugJob =>
new DebugJobItem("service",
t("debug.service"),
() => startService(connection),
() => stopService(connection),
job,
certificates
)
t("debug.service"), {
startFunction: () => startService(connection),
stopFunction: () => stopService(connection),
debugJob,
debugConfig,
certificates,
keyFileExists
})
)
]);
}
Expand All @@ -115,15 +120,15 @@ class DebugBrowser implements vscode.TreeDataProvider<BrowserItem> {

async resolveTreeItem(item: vscode.TreeItem, element: BrowserItem, token: vscode.CancellationToken) {
const connection = instance.getConnection();
if (connection && element.tooltip === undefined && element instanceof DebugJobItem && element.debugJob) {
element.tooltip = new vscode.MarkdownString(`${t(`listening.on.port${element.debugJob.ports.length === 1 ? '' : 's'}`)} ${element.debugJob.ports.join(", ")}\n\n`);
const activeJob = await readActiveJob(connection, element.debugJob);
if (connection && element.tooltip === undefined && element instanceof DebugJobItem && element.parameters.debugJob) {
element.tooltip = new vscode.MarkdownString(`${t(`listening.on.port${element.parameters.debugJob.ports.length === 1 ? '' : 's'}`)} ${element.parameters.debugJob.ports.join(", ")}\n\n`);
const activeJob = await readActiveJob(connection, element.parameters.debugJob);
if (activeJob) {
const jobToMarkDown = (job: Tools.DB2Row | string) => typeof job === "string" ? job : Object.entries(job).filter(([key, value]) => value !== null).map(([key, value]) => `- ${t(key)}: ${value}`).join("\n");
element.tooltip.appendMarkdown(jobToMarkDown(activeJob));
if (element.type === "service") {
element.tooltip.appendMarkdown("\n\n");
const jvmJob = await readJVMInfo(connection, element.debugJob);
const jvmJob = await readJVMInfo(connection, element.parameters.debugJob);
if (jvmJob) {
element.tooltip.appendMarkdown(jobToMarkDown(jvmJob));
}
Expand All @@ -142,24 +147,40 @@ class DebugItem extends BrowserItem {
}

class DebugJobItem extends DebugItem {
private problem: undefined | CertificateIssue;

constructor(readonly type: "server" | "service", label: string, readonly startFunction: () => Promise<boolean>, readonly stopFunction: () => Promise<boolean>, readonly debugJob?: DebugJob, certificates?: Certificates) {
let problem: undefined | CertificateIssue
const cantRun = certificates && !certificates.remoteCertificate;
const running = !cantRun && debugJob !== undefined;
if (certificates) {
if (!certificates.remoteCertificate) {
private problem: undefined | DebugServiceIssue;

constructor(readonly type: "server" | "service", label: string, readonly parameters: {
startFunction: () => Promise<boolean>,
stopFunction: () => Promise<boolean>,
debugJob?: DebugJob,
certificates?: Certificates,
debugConfig?: DebugConfiguration,
keyFileExists?: boolean
}) {
let problem: undefined | DebugServiceIssue
let cantRun = false;
const running = !cantRun && parameters.debugJob !== undefined;
if (parameters.certificates && parameters.debugConfig) {
if (parameters.debugConfig && (!parameters.debugConfig.getCode4iDebug() || !parameters.keyFileExists)) {
cantRun = true;
problem = {
context: "noremote",
label: t('debug.service.config.incomplete'),
detail: t('debug.service.config.incomplete.detail', "debug_service.pfx", parameters.certificates.remoteCertificatePath)
}
}
else if (!parameters.certificates.remoteCertificate) {
cantRun = true;
problem = {
context: "noremote",
label: t('remote.certificate.not.found'),
detail: t('remote.certificate.not.found.detail', "debug_service.pfx", certificates.remoteCertificatePath)
detail: t('remote.certificate.not.found.detail', "debug_service.pfx", parameters.certificates.remoteCertificatePath)
}
}
else if (certificates.localCertificateIssue) {
else if (parameters.certificates.localCertificateIssue) {
problem = {
context: "localissue",
label: certificates.localCertificateIssue
label: parameters.certificates.localCertificateIssue
};
}
}
Expand All @@ -173,7 +194,7 @@ class DebugJobItem extends DebugItem {
this.problem = problem;

if (running) {
this.description = debugJob.name;
this.description = this.parameters.debugJob!.name;
}
else {
this.description = t("offline");
Expand All @@ -188,16 +209,16 @@ class DebugJobItem extends DebugItem {
}

async start() {
return vscode.window.withProgress({ title: t(`start.debug.${this.type}.task`), location: vscode.ProgressLocation.Window }, this.startFunction);
return vscode.window.withProgress({ title: t(`start.debug.${this.type}.task`), location: vscode.ProgressLocation.Window }, this.parameters.startFunction);
}

async stop() {
return vscode.window.withProgress({ title: t(`stop.debug.${this.type}.task`), location: vscode.ProgressLocation.Window }, this.stopFunction);
return vscode.window.withProgress({ title: t(`stop.debug.${this.type}.task`), location: vscode.ProgressLocation.Window }, this.parameters.stopFunction);
}
}

class CertificateIssueItem extends DebugItem {
constructor(issue: CertificateIssue) {
constructor(issue: DebugServiceIssue) {
super(issue.label)
this.description = issue.detail;
this.tooltip = issue.detail || '';
Expand Down

0 comments on commit b670775

Please sign in to comment.