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

fix: invalid $HOME is not detected #4901

Merged
merged 3 commits into from
Jul 7, 2024
Merged
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
9 changes: 9 additions & 0 deletions packages/amazonq/src/extensionCommon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ import {
RegionProvider,
getLogger,
getMachineId,
messages,
} from 'aws-core-vscode/shared'
import { fs } from 'aws-core-vscode/srcShared'
import { initializeAuth, CredentialsStore, LoginManager, AuthUtils, SsoConnection } from 'aws-core-vscode/auth'
import { CommonAuthWebview } from 'aws-core-vscode/login'
import { VSCODE_EXTENSION_ID } from 'aws-core-vscode/utils'
Expand All @@ -40,6 +42,9 @@ export const amazonQContextPrefix = 'amazonq'
*/
export async function activateAmazonQCommon(context: vscode.ExtensionContext, isWeb: boolean) {
initialize(context, isWeb)
const homeDirLogs = await fs.initUserHomeDir(context, homeDir => {
void messages.showViewLogsMessage(`Invalid home directory (check $HOME): "${homeDir}"`)
})
await initializeComputeRegion()

globals.contextPrefix = 'amazonq.' //todo: disconnect from above line
Expand Down Expand Up @@ -91,6 +96,10 @@ export async function activateAmazonQCommon(context: vscode.ExtensionContext, is
globals.logOutputChannel = qLogChannel
globals.loginManager = new LoginManager(globals.awsContext, new CredentialsStore())

if (homeDirLogs.length > 0) {
getLogger().error('initUserHomeDir: invalid env vars found: %O', homeDirLogs)
}

await activateTelemetry(context, globals.awsContext, Settings.instance, 'Amazon Q For VS Code')

await initializeAuth(globals.loginManager)
Expand Down
44 changes: 37 additions & 7 deletions packages/core/src/auth/credentials/sharedCredentialsFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,48 @@
* This module focuses on the i/o of the credentials/config files
*/

import { join } from 'path'
import { EnvironmentVariables } from '../../shared/environmentVariables'
import { SystemUtilities } from '../../shared/systemUtilities'
import { join, resolve } from 'path'
import fs from '../../srcShared/fs'
import { getLogger } from '../../shared/logger'

/**
* Returns env var value if it is non-empty.
*
* Asynchronously checks if the value is a valid file (not directory) path and logs an error if not.
* The value is still returned in that case.
*/
function tryGetValidFileEnvVar(envVar: string): string | undefined {
const envVal = process.env[envVar]

if (envVal) {
const f = resolve(envVal)
fs.existsFile(f)
.then(r => {
if (!r) {
getLogger().error('$%s filepath is invalid (or is a directory): %O', envVar, f)
}
})
.catch(e => getLogger().error(e))
return f
}
}

export function getCredentialsFilename(): string {
const env = process.env as EnvironmentVariables
const envVal = tryGetValidFileEnvVar('AWS_SHARED_CREDENTIALS_FILE')

if (envVal) {
return envVal
}

return env.AWS_SHARED_CREDENTIALS_FILE || join(SystemUtilities.getHomeDirectory(), '.aws', 'credentials')
return join(fs.getUserHomeDir(), '.aws/credentials')
}

export function getConfigFilename(): string {
const env = process.env as EnvironmentVariables
const envVal = tryGetValidFileEnvVar('AWS_CONFIG_FILE')

if (envVal) {
return envVal
}

return env.AWS_CONFIG_FILE || join(SystemUtilities.getHomeDirectory(), '.aws', 'config')
return join(fs.getUserHomeDir(), '.aws/config')
}
12 changes: 10 additions & 2 deletions packages/core/src/extensionCommon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { logAndShowError, logAndShowWebviewError } from './shared/utilities/logA
import { AuthStatus, telemetry } from './shared/telemetry/telemetry'
import { openUrl } from './shared/utilities/vsCodeUtils'
import { activateViewsShared } from './awsexplorer/activationShared'

import { fs } from './srcShared'
import { activate as activateLogger } from './shared/logger/activation'
import { initializeComputeRegion } from './shared/extensionUtilities'
import { activate as activateTelemetry } from './shared/telemetry/activation'
Expand Down Expand Up @@ -54,6 +54,8 @@ import { registerCommands } from './commands'
// In web mode everything must be in a single file, so things like the endpoints file will not be available.
// The following imports the endpoints file, which causes webpack to bundle it in the final output file
import endpoints from '../resources/endpoints.json'
import { getLogger } from './shared'
import { showViewLogsMessage } from './shared/utilities/messages'

disableAwsSdkWarning()

Expand All @@ -70,8 +72,10 @@ export async function activateCommon(
): Promise<ExtContext> {
localize = nls.loadMessageBundle()

// some "initialize" functions
initialize(context, isWeb)
const homeDirLogs = await fs.initUserHomeDir(context, homeDir => {
void showViewLogsMessage(`Invalid home directory (check $HOME): "${homeDir}"`)
})
await initializeComputeRegion()

globals.contextPrefix = '' //todo: disconnect supplied argument
Expand All @@ -92,6 +96,10 @@ export async function activateCommon(
globals.outputChannel = toolkitOutputChannel
globals.logOutputChannel = toolkitLogChannel

if (homeDirLogs.length > 0) {
getLogger().error('initUserHomeDir: invalid home directory given by env vars: %O', homeDirLogs)
}

if (isCloud9()) {
vscode.window.withProgress = wrapWithProgressForCloud9(globals.outputChannel)
context.subscriptions.push(
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/shared/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export { initializeComputeRegion } from './extensionUtilities'
export { RegionProvider } from './regions/regionProvider'
export { Commands } from './vscode/commands2'
export { getMachineId } from './vscode/env'
export * from './environmentVariables'
export { getLogger } from './logger/logger'
export { activateExtension } from './utilities/vsCodeUtils'
export { waitUntil, sleep } from './utilities/timeoutUtils'
Expand All @@ -39,4 +40,5 @@ export { getMinVscodeVersion } from './vscode/env'
export * from './vscode/commands2'
export * from './utilities/pathUtils'
export * from './errors'
export * as messages from './utilities/messages'
export * as errors from './errors'
25 changes: 25 additions & 0 deletions packages/core/src/shared/logger/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export interface Logger {
warn(error: Error, ...meta: any[]): number
error(message: string, ...meta: any[]): number
error(error: Error, ...meta: any[]): number
log(logLevel: LogLevel, message: string, ...meta: any[]): number
log(logLevel: LogLevel, error: Error, ...meta: any[]): number
setLogLevel(logLevel: LogLevel): void
/** Returns true if the given log level is being logged. */
logLevelEnabled(logLevel: LogLevel): boolean
Expand Down Expand Up @@ -102,6 +104,9 @@ export class NullLogger implements Logger {
public logLevelEnabled(logLevel: LogLevel): boolean {
return false
}
public log(logLevel: LogLevel, message: string | Error, ...meta: any[]): number {
return 0
}
public debug(message: string | Error, ...meta: any[]): number {
return 0
}
Expand Down Expand Up @@ -131,6 +136,26 @@ export class ConsoleLogger implements Logger {
public logLevelEnabled(logLevel: LogLevel): boolean {
return false
}
public log(logLevel: LogLevel, message: string | Error, ...meta: any[]): number {
switch (logLevel) {
case 'error':
this.error(message, ...meta)
return 0
case 'warn':
this.warn(message, ...meta)
return 0
case 'verbose':
this.verbose(message, ...meta)
return 0
case 'debug':
this.debug(message, ...meta)
return 0
case 'info':
default:
this.info(message, ...meta)
return 0
}
}
public debug(message: string | Error, ...meta: any[]): number {
console.debug(message, ...meta)
return 0
Expand Down
4 changes: 4 additions & 0 deletions packages/core/src/shared/logger/winstonToolkitLogger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ export class WinstonToolkitLogger implements Logger, vscode.Disposable {
this.logger.add(consoleLogTransport)
}

public log(logLevel: LogLevel, message: string | Error, ...meta: any[]): number {
return this.writeToLogs(logLevel, message, ...meta)
}

public debug(message: string | Error, ...meta: any[]): number {
return this.writeToLogs('debug', message, ...meta)
}
Expand Down
27 changes: 1 addition & 26 deletions packages/core/src/shared/systemUtilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,12 @@

import fs from 'fs'
import * as vscode from 'vscode'
import * as os from 'os'
import * as path from 'path'
import fs2 from '../srcShared/fs'
import { EnvironmentVariables } from './environmentVariables'
import { ChildProcess } from './utilities/childProcess'
import { getLogger } from './logger/logger'
import { GitExtension } from './extensions/git'
import { Settings } from './settings'
import globals, { isWeb } from './extensionGlobals'

/**
* Deprecated interface for filesystem operations.
Expand All @@ -28,29 +25,7 @@ export class SystemUtilities {
private static bashPath: string

public static getHomeDirectory(): string {
if (isWeb()) {
// When in browser we cannot access the users desktop file system.
// Instead, VS Code provided uris will use the browsers storage.
// IMPORTANT: we must preserve the scheme of this URI or else VS Code
// will incorrectly interpret the path.
return globals.context.globalStorageUri.toString()
}

const env = process.env as EnvironmentVariables

if (env.HOME !== undefined) {
return env.HOME
}
if (env.USERPROFILE !== undefined) {
return env.USERPROFILE
}
if (env.HOMEPATH !== undefined) {
const homeDrive: string = env.HOMEDRIVE || 'C:'

return path.join(homeDrive, env.HOMEPATH)
}

return os.homedir()
return fs2.getUserHomeDir()
}

public static async readFile(file: string | vscode.Uri, decoder: TextDecoder = new TextDecoder()): Promise<string> {
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/shared/utilities/pathUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ export const driveLetterRegex = /^[a-zA-Z]\:/
* Expands "~" at the start of `fname` to user home dir.
* TODO: expand env vars too.
*/
export function resolvePath(fname: string) {
const homedir = os.homedir()
export function resolvePath(fname: string, homedir?: string) {
homedir = homedir ?? os.homedir()
if (fname.startsWith('~/') || fname.startsWith('~\\')) {
return _path.join(homedir, fname.substring(2))
}
Expand Down
Loading
Loading