fix(lambda): add console credential fallback for Lambda URI handler#8537
Conversation
|
⏳ I'm reviewing this pull request for security vulnerabilities and code quality issues. I'll provide an update when I'm done |
|
✅ I finished the code review, and didn't find any security or code quality issues. |
3aca6d4 to
7e51e8f
Compare
7e51e8f to
ea1adf8
Compare
packages/core/src/auth/utils.ts
Outdated
| export async function getIAMConnectionOrFallbackToConsole(name: string, region: string): Promise<Connection> { | ||
| const tryActiveConnection = await getIAMConnection({ prompt: false }) | ||
|
|
||
| if (tryActiveConnection && isIamConnection(tryActiveConnection)) { |
There was a problem hiding this comment.
Why do we need to check that it's an IamConnection?
The previous getFunctionWithCredentials used a fromSSO for the case where the connection wasn't iam.
aws-toolkit-vscode/packages/core/src/shared/clients/lambdaClient.ts
Lines 350 to 351 in 8b4d088
should we still consider that case too before going to create a console connection?
There was a problem hiding this comment.
Good call. I removed the IamConnection type pre-check.
| const connection = await getIAMConnectionOrFallbackToConsole(name, region) | ||
|
|
||
| try { | ||
| return await getFunctionWithCredentials(region, name) |
There was a problem hiding this comment.
We retrieved the credentials in this getIAMConnectionOrFallbackToConsole, but then we're not using those credentials here, so inside this method we need to get the credentials again. Shouldn't we pass the credentials directly here, now that we have them? Or is there a reason to just make the method retrieve them directly instead of passing them as a parameter?
There was a problem hiding this comment.
Thank you for pointing this out. I removed getIAMConnectionOrFallbackToConsole entirely since it duplicated credential retrieval logic in getFunctionWithCredentials.
| getLogger().warn(message) | ||
| } | ||
| // Retry once with console credentials after credential mismatch. If second attempt fails, throw the error up. | ||
| await createAndUseConsoleConnection(name, region) |
There was a problem hiding this comment.
Just to confirm the behavior:
So we're trying to get the credentials. If there are credentials we use those, but if they don't exist, we create the console connection.
Then we try to get the function, but if we fail because of different reasons, then we try again to create the console connection.
Could it happen that we create the console connection twice? If they didn't have a connection initially so we create the console connection, but then their console session has one of these errors? (maybe we want to retry?)
There was a problem hiding this comment.
This was a very good point. I cleaned up the retry behavior to avoid setting up console connection for the second-time.
Here are the current scenarios handled by getFunctionWithFallback:
Active connection → success (no console setup)
Active connection → get function error (ResourceNotFoundException/AccessDeniedException) → show message → console retry → success
Active connection → get function error (other errors) → console retry (no message) → success
No connection → console setup → success
No connection → console setup → get function error (ResourceNotFoundException/AccessDeniedException) → show message → throw (no retry)
No connection → console setup → get function error (other errors) → throw (no message, no retry)
No connection → console setup error → throw (no message)
packages/core/src/auth/utils.ts
Outdated
| * @returns Connection created from console credentials | ||
| * @throws ToolkitError if connection creation fails | ||
| */ | ||
| export async function createAndUseConsoleConnection(profileName: string, region: string): Promise<Connection> { |
There was a problem hiding this comment.
small thing but i wonder since this method says it's doing two things by way of the "and" should it be split into two methods for maintainability?
There was a problem hiding this comment.
Agreed. I refactored the credential ID handling and made this function (renamed to setupConsoleConnection) only owns the console-connection setup path. The extra getConnection check was removed since useConnection already validates internally.
packages/core/src/auth/utils.ts
Outdated
| await tryActiveConnection.getCredentials() | ||
| return tryActiveConnection | ||
| } catch (error) { | ||
| // Fall back to console credentials for any credential retrieval error |
There was a problem hiding this comment.
Should we log something here?
There was a problem hiding this comment.
Since we removed the redundant credential pre-check, this log is no longer needed.
packages/core/src/auth/utils.ts
Outdated
| * @throws ToolkitError if console login fails | ||
| */ | ||
| export async function getIAMConnectionOrFallbackToConsole(name: string, region: string): Promise<Connection> { | ||
| const tryActiveConnection = await getIAMConnection({ prompt: false }) |
There was a problem hiding this comment.
nit: lets just name this activeConnection, feels redundant to have "tryActiveConnection" inside the try block
There was a problem hiding this comment.
Really appreciate the detailed feedback. I updated to activeConnection. Thanks a lot, Seshu.
…nctionWithFallback`
…r fails (#8580) ## Problem - #8537 introduced setupConsoleConnection() and getFunctionWithFallback() to handle authentication fallback for Lambda console-to-IDE transitions. - When developers click "Open in VSCode" and their local AWS profile is invalid, toolkit automatically triggers browser-based console login as a fallback. However, console login requires prerequisites that not all developers can complete. When developers cancel console login, the CLI never writes the connection profile to disk. The Toolkit then attempts to use this non-existent connection, resulting in "Connection does not exist" errors. <img width="471" height="265" alt="problem-before-the-fix-connection-does-not-exist" src="https://github.com/user-attachments/assets/fd973ce1-7b28-4474-8b55-b0408c67e0ce" /> ## Solution - Verify connection exists in `setupConsoleConnection()` after "aws.toolkit.auth.consoleLogin" completes - Show warning message with link to [prerequisites documentation](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sign-in.html#cli-configure-sign-in-prerequisites) when connection verification fails - Throw ToolkitError to halt execution and prevent downstream connection usage <img width="1293" height="302" alt="update-message-with-learnmore" src="https://github.com/user-attachments/assets/a1d35f14-4c42-43c1-8417-b6532ed00e9a" /> <img width="1042" height="625" alt="click-learnmore-show-dialog" src="https://github.com/user-attachments/assets/aace3330-4ea8-4bd8-ad24-e8e956f09c45" /> ### Background The Lambda load-function URI handler enables a seamless workflow where users can click "Open in Visual Studio Code" from the AWS Lambda console to view, edit, and deploy their Lambda functions directly in their preferred IDE. This feature downloads the function code locally, opens it in VS Code, and allows users to make changes and deploy updates back to AWS—all without leaving their development environment. --- - Treat all work as PUBLIC. Private `feature/x` branches will not be squash-merged at release time. - Your code changes must meet the guidelines in [CONTRIBUTING.md](https://github.com/aws/aws-toolkit-vscode/blob/master/CONTRIBUTING.md#guidelines). - License: I confirm that my contribution is made under the terms of the Apache 2.0 license.
Problem
ResourceNotFoundExceptionwhen function exists in console account but not in local profile accountAccessDeniedExceptionwhen local credentials lacklambda:GetFunctionpermission but console credentials have accessSolution
setupConsoleConnection()to encapsulate browser-based AWS CLIaws loginauthentication and use the new connectiongetFunctionWithFallback()to retrieve Lambda configuration with automatic console login fallbackopenLambdaFolderForEdit()to handle missing credentials and credential mismatchesResourceNotFoundExceptionby showing account-specific error message before fallbackAccessDeniedExceptionby showing permission error message before fallbackScreenshots
Show warning message when Lambda GetFunction API returns ResourceNotFoundException, then automatically proceed with console login flow
Show warning message when Lambda GetFunction API returns AccessDeniedException, then automatically proceed with console login flow
Background
The Lambda
load-functionURI handler enables a seamless workflow where users can click "Open in Visual Studio Code" from the AWS Lambda console to view, edit, and deploy their Lambda functions directly in their preferred IDE. This feature downloads the function code locally, opens it in VS Code, and allows users to make changes and deploy updates back to AWS—all without leaving their development environment.Testing
feature/xbranches will not be squash-merged at release time.