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

Generating debug session key and matching it on every debug message #285

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 1 addition & 9 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,7 @@
"NODE_DEBUG": "",
"ENABLE_LONG_RUNNING_TESTS": ""
}
},
{
"type": "node",
"request": "launch",
"name": "Server",
"cwd": "${workspaceFolder}",
"program": "${workspaceFolder}/resources/debug/debugAdapter.js",
"args": [ "--server=4711" ]
},
}
],
"compounds": [
{
Expand Down
11 changes: 11 additions & 0 deletions src/commands/debugPolicies/debugPolicy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,19 @@ import { IOperationTreeRoot } from '../../explorer/IOperationTreeRoot';
import { ext } from "../../extensionVariables";
import { localize } from '../../localize';
import { nameUtil } from '../../utils/nameUtil';
import { IServiceTreeRoot } from '../../explorer/IServiceTreeRoot';

export async function debugPolicy(context: IActionContext, node?: ApiOperationTreeItem): Promise<void> {
if (!node) {
// tslint:disable-next-line: no-unsafe-any
node = <ApiOperationTreeItem>await ext.tree.showTreeItemPicker(ApiOperationTreeItem.contextValue, context);
}

if (!await isDebuggingSupported(node.root)) {
vscode.window.showInformationMessage(localize("onlyDevDebugging", "Debugging is only supported on Developer SKU of API Management services."));
return;
}

const operationData = await node.getOperationDebugInfo();
const debugConfig: vscode.DebugConfiguration = {
type: "apim-policy",
Expand Down Expand Up @@ -56,6 +62,11 @@ export async function debugPolicy(context: IActionContext, node?: ApiOperationTr
}
}

async function isDebuggingSupported(service: IServiceTreeRoot): Promise<boolean> {
const svc = await service.client.apiManagementService.get(service.resourceGroupName, service.serviceName/*, { customHeaders: { Authorization: credentials.tokenCache._entries[0].accessToken } }*/);
return svc.sku.name === "Developer";
}

function getManagementUrl(root: IOperationTreeRoot): string {
return `${root.environment.resourceManagerEndpointUrl}/subscriptions/${root.subscriptionId}/resourceGroups/${root.resourceGroupName}/providers/microsoft.apimanagement/service/${root.serviceName}`;
}
Expand Down
12 changes: 11 additions & 1 deletion src/debugger/apimDebug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export class ApimDebugSession extends LoggingDebugSession {
private policySource: PolicySource;
private variablesHandles = new Handles<string>();

public constructor() {
public constructor(private sessionKey: string) {
super();

this.setDebuggerLinesStartAt1(false);
Expand Down Expand Up @@ -81,6 +81,16 @@ export class ApimDebugSession extends LoggingDebugSession {
this.configurationDone.notify();
}

public handleMessage(request: DebugProtocol.Request): void {
// If request came from VSCode there must be session key present, if not - ignore the message
if (this.sessionKey !== request.arguments?._sessionKey) {
return;
}

delete request.arguments._sessionKey;
super.handleMessage(request);
}

protected async launchRequest(response: DebugProtocol.LaunchResponse, args: ILaunchRequestArguments): Promise<void> {
logger.setup(Logger.LogLevel.Verbose, false);
let masterKey;
Expand Down
7 changes: 0 additions & 7 deletions src/debugger/debugAdapter.ts

This file was deleted.

36 changes: 34 additions & 2 deletions src/debugger/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as Net from 'net';
import * as vscode from 'vscode';
import { CancellationToken, DebugConfiguration, ProviderResult, WorkspaceFolder } from 'vscode';
import { ApimDebugSession } from './apimDebug';
import * as Crypto from 'crypto';

// tslint:disable: no-unsafe-any
// tslint:disable: indent
Expand All @@ -21,6 +22,8 @@ export function activate(context: vscode.ExtensionContext) {
const factory = new ApimPolicyDebugAdapterDescriptorFactory();
context.subscriptions.push(vscode.debug.registerDebugAdapterDescriptorFactory('apim-policy', factory));
context.subscriptions.push(factory);

context.subscriptions.push(vscode.debug.registerDebugAdapterTrackerFactory('apim-policy', new ApimPolicyDebugSessionKeyAppenderFactory()));
}

export function deactivate() {}
Expand All @@ -36,24 +39,53 @@ class ApimPolicyConfigurationProvider implements vscode.DebugConfigurationProvid
config.stopOnEntry = true;
}
}

return config;
}
}

class ApimPolicyDebugAdapterDescriptorFactory implements vscode.DebugAdapterDescriptorFactory {
class ApimPolicyDebugSessionKeyAppenderFactory implements vscode.DebugAdapterTrackerFactory {
createDebugAdapterTracker(session: vscode.DebugSession): vscode.ProviderResult<vscode.DebugAdapterTracker> {
return new ApimPolicyDebugSessionKeyAppender(session);
}
}

class ApimPolicyDebugSessionKeyAppender implements vscode.DebugAdapterTracker {
private sessionKey: string;

constructor(_session: vscode.DebugSession) {
this.sessionKey = _session.configuration.key;
}

onWillReceiveMessage(message: any) {
if (!message.arguments) {
message.arguments = {};
}

//Append the session key to every message we send
message.arguments._sessionKey = this.sessionKey;
}
}

class ApimPolicyDebugAdapterDescriptorFactory implements vscode.DebugAdapterDescriptorFactory {
private server?: Net.Server;
private serverKey: string;

public createDebugAdapterDescriptor(_session: vscode.DebugSession, _executable: vscode.DebugAdapterExecutable | undefined): vscode.ProviderResult<vscode.DebugAdapterDescriptor> {
if (!this.server) {
// generate a random key for further the debug sessions
this.serverKey = Crypto.randomBytes(16).toString('hex');

// start listening on a random port
this.server = Net.createServer(socket => {
const session = new ApimDebugSession();
const session = new ApimDebugSession(this.serverKey);
session.setRunAsServer(true);
session.start(<NodeJS.ReadableStream>socket, socket);
}).listen(0);
}

_session.configuration.key = this.serverKey;

// make VS Code connect to debug server
return new vscode.DebugAdapterServer(this.server.address().port);
}
Expand Down