Skip to content
Closed
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
18 changes: 18 additions & 0 deletions packages/amazonq/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,24 @@
"items": {
"type": "string"
}
},
"amazonQ.proxy.certificateAuthority": {
"type": "string",
"markdownDescription": "%AWS.configuration.description.amazonq.proxy.certificateAuthority%",
"default": null,
"scope": "application"
},
"amazonQ.proxy.username": {
"type": "string",
"markdownDescription": "%AWS.configuration.description.amazonq.proxy.username%",
"default": null,
"scope": "application"
},
"amazonQ.proxy.password": {
"type": "string",
"markdownDescription": "%AWS.configuration.description.amazonq.proxy.password%",
"default": null,
"scope": "application"
}
}
},
Expand Down
5 changes: 5 additions & 0 deletions packages/amazonq/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
Experiments,
isSageMaker,
isAmazonLinux2,
ProxyUtil,
} from 'aws-core-vscode/shared'
import { ExtStartUpSources } from 'aws-core-vscode/telemetry'
import { VSCODE_EXTENSION_ID } from 'aws-core-vscode/utils'
Expand Down Expand Up @@ -119,6 +120,10 @@ export async function activateAmazonQCommon(context: vscode.ExtensionContext, is
const extContext = {
extensionContext: context,
}

// Configure proxy settings early
ProxyUtil.configureProxyForLanguageServer()

// This contains every lsp agnostic things (auth, security scan, code scan)
await activateCodeWhisperer(extContext as ExtContext)
if (
Expand Down
4 changes: 3 additions & 1 deletion packages/core/package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@
"AWS.configuration.description.amazonq.workspaceIndexIgnoreFilePatterns": "File patterns to ignore when indexing your workspace files",
"AWS.configuration.description.amazonq.workspaceIndexCacheDirPath": "The path to the directory that contains the cache of the index of your workspace files",
"AWS.configuration.description.amazonq.ignoredSecurityIssues": "Specifies a list of code issue identifiers that Amazon Q should ignore when reviewing your workspace. Each item in the array should be a unique string identifier for a specific code issue. This allows you to suppress notifications for known issues that you've assessed and determined to be false positives or not applicable to your project. Use this setting with caution, as it may cause you to miss important security alerts.",
"AWS.command.apig.copyUrl": "Copy URL",
"AWS.configuration.description.amazonq.proxy.certificateAuthority": "Path to a Certificate Authority (PEM file) for SSL/TLS verification when using a proxy.",
"AWS.configuration.description.amazonq.proxy.username": "Username for proxy authentication.",
"AWS.configuration.description.amazonq.proxy.password": "Password for proxy authentication.",
"AWS.command.apig.invokeRemoteRestApi": "Invoke in the cloud",
"AWS.command.apig.invokeRemoteRestApi.cn": "Invoke on Amazon",
"AWS.appBuilder.explorerTitle": "Application Builder",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/shared/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export {
CodewhispererUserDecision,
CodewhispererSecurityScan,
} from './telemetry/telemetry.gen'
export { ProxyUtil } from './utilities/proxyUtil'
export { randomUUID } from './crypto'
export * from './environmentVariables'
export * from './vscode/setContext'
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/shared/logger/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export type LogTopic =
| 'nextEditPrediction'
| 'resourceCache'
| 'telemetry'
| 'proxyUtil'

class ErrorLog {
constructor(
Expand Down
5 changes: 4 additions & 1 deletion packages/core/src/shared/settings-amazonq.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ export const amazonqSettings = {
"amazonQ.workspaceIndexMaxFileSize": {},
"amazonQ.workspaceIndexCacheDirPath": {},
"amazonQ.workspaceIndexIgnoreFilePatterns": {},
"amazonQ.ignoredSecurityIssues": {}
"amazonQ.ignoredSecurityIssues": {},
"amazonQ.proxy.certificateAuthority": {},
"amazonQ.proxy.username": {},
"amazonQ.proxy.password": {}
}

export default amazonqSettings
99 changes: 99 additions & 0 deletions packages/core/src/shared/utilities/proxyUtil.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*!
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

import vscode from 'vscode'
import { getLogger } from '../logger/logger'

interface ProxyConfig {
proxyUrl: string | undefined
certificateAuthority: string | undefined
username: string | undefined
password: string | undefined
}

/**
* Utility class for handling proxy configuration
*/
export class ProxyUtil {
private static readonly logger = getLogger('proxyUtil')

/**
* Sets proxy environment variables based on VS Code settings for use with the Flare Language Server
*
* See documentation here for setting the environement variables which are inherited by Flare LS process:
* https://github.com/aws/language-server-runtimes/blob/main/runtimes/docs/proxy.md
*/
public static configureProxyForLanguageServer(): void {
try {
const proxyConfig = this.getProxyConfiguration()

this.setProxyEnvironmentVariables(proxyConfig)
} catch (err) {
this.logger.error(`Failed to configure proxy: ${err}`)
}
}

/**
* Gets proxy configuration from VS Code settings
*/
private static getProxyConfiguration(): ProxyConfig {
const httpConfig = vscode.workspace.getConfiguration('http')
const proxyUrl = httpConfig.get<string>('proxy')
this.logger.debug(`Proxy URL: ${proxyUrl}`)

const amazonQConfig = vscode.workspace.getConfiguration('amazonQ')
const proxySettings = amazonQConfig.get<{
certificateAuthority?: string
username?: string
password?: string
}>('proxy', {})

return {
proxyUrl,
certificateAuthority: proxySettings.certificateAuthority,
username: proxySettings.username,
password: proxySettings.password,
}
}

/**
* Sets environment variables based on proxy configuration
*/
private static setProxyEnvironmentVariables(config: ProxyConfig): void {
let proxyUrl = config.proxyUrl

// Add authentication to proxy URL if provided
if (proxyUrl && config.username && config.password) {
try {
const parsedUrl = new URL(proxyUrl)
const protocol = parsedUrl.protocol
const host = parsedUrl.hostname
const port = parsedUrl.port || (protocol === 'https:' ? '443' : '80')

proxyUrl = `${protocol}//${config.username}:${config.password}@${host}:${port}`
this.logger.debug('Added authentication to proxy URL')
} catch (err) {
this.logger.error(`Failed to parse proxy URL: ${err}`)
}
}

// Always enable experimental proxy support for better handling of both explicit and transparent proxies
process.env.EXPERIMENTAL_HTTP_PROXY_SUPPORT = 'true'

// Set proxy environment variables
if (proxyUrl) {
process.env.HTTPS_PROXY = proxyUrl
process.env.HTTP_PROXY = proxyUrl
this.logger.debug(`Set proxy environment variables: ${proxyUrl}`)
}

// Set certificate bundle environment variables if configured
if (config.certificateAuthority) {
process.env.NODE_EXTRA_CA_CERTS = config.certificateAuthority
process.env.AWS_CA_BUNDLE = config.certificateAuthority
this.logger.debug(`Set certificate bundle path: ${config.certificateAuthority}`)
}
}
}
Loading