-
Notifications
You must be signed in to change notification settings - Fork 491
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
feat(amazonq): Enable SageMaker SSO Users to use AmazonQ Chat & Code completion using their Credentials & Q Pro-tier profile #6338
base: master
Are you sure you want to change the base?
Conversation
…redentials & Pro Tier profile ARN for AmazonQ features
|
let scopes = [...scopesSsoAccountAccess] | ||
if (isAmazonQ()) { | ||
scopes = [...scopes, ...SageMakerSpaceClient.getQConnectionScopes()] | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This implies that this token provider would work with toolkit. Is that intended?
Are the SSO scopes required? If not, do not attach them.
let scopes = [...scopesSsoAccountAccess] | |
if (isAmazonQ()) { | |
scopes = [...scopes, ...SageMakerSpaceClient.getQConnectionScopes()] | |
} | |
const scopes = [isAmazonQ() ? ...SageMakerSpaceClient.getQConnectionScopes() : ...scopesSsoAccountAccess] |
} | ||
|
||
public static getQConnectionScopes() { | ||
return ['codewhisperer:completions', 'codewhisperer:conversations'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we give users all amazon Q scopes? Why are we only giving this subset
@@ -0,0 +1,4 @@ | |||
{ | |||
"type": "Feature", | |||
"description": "Enable SageMaker SSO user access token & Profile ARN to be used for accessing AmazonQ & CodeWhisperer features" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"CodeWhisperer" is no more
"description": "Enable SageMaker SSO user access token & Profile ARN to be used for accessing AmazonQ & CodeWhisperer features" | |
"description": "Auth: Enable SSO access for SageMaker users." |
@@ -963,6 +1003,20 @@ export class Auth implements AuthService, ConnectionManager { | |||
return this.authenticate(id, refresh) | |||
} | |||
|
|||
public async tryAutoConnectSageMaker(): Promise<StatefulConnection | undefined> { | |||
try { | |||
const sagemakerConnection = await this.createSageMakerSsoConnection() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could the connection already exist in a saved state from a prior session?
private constructor(sageMakerClient?: DefaultSageMakerClient) { | ||
this.sageMakerClient = sageMakerClient ?? new DefaultSageMakerClient(this.getDefaultRegion()) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this pattern makes sense. This class is a singleton accessible via getInstance
only, so you can never pass a custom sageMakerClient
. The constructor is private.
public static getInstance(): SageMakerSpaceClient { | ||
if (!this._instance) { | ||
this._instance = new SageMakerSpaceClient() | ||
} | ||
return this._instance | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Follow the same format that we have in other singletons for consistency
aws-toolkit-vscode/packages/core/src/codewhisperer/util/authUtil.ts
Lines 234 to 241 in e6c3101
public static get instance() { | |
if (this.#instance !== undefined) { | |
return this.#instance | |
} | |
const self = (this.#instance = new this()) | |
return self | |
} |
public static getInstance(): SageMakerSpaceClient { | |
if (!this._instance) { | |
this._instance = new SageMakerSpaceClient() | |
} | |
return this._instance | |
} | |
public static get instance() { | |
if (!this.#instance) { | |
this.#instance = new SageMakerSpaceClient() | |
} | |
return this.#instance | |
} |
return this.cachedCookies | ||
} | ||
|
||
public async getAmazonQProfileArn(): Promise<string | undefined> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is a profile ARN and why do we want it? Please add a docstring
} | ||
|
||
// Manually expire the token every 5 minutes as token refresh is handled externally by Sagemaker | ||
const TOKEN_EXPIRY = 5 * 60 * 1000 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use constants in
export const oneMinute = oneSecond * 60 |
e.g.
const TOKEN_EXPIRY = 5 * 60 * 1000 | |
const TOKEN_EXPIRY = oneMinute * 5 |
authMode?: 'Sso' | 'Iam' | ||
expiryTime?: number | ||
ssoExpiryTimestamp?: number | ||
studioUserProfileName?: string | ||
redirectURL?: string | ||
AccessToken?: string | ||
StudioSessionToken?: string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nothing is guaranteed to exist in the sagemaker cookie? Would be nice if we had some documentation about sagemaker expectations (if it doesn't already exist)
|
||
// Manually expire the token every 5 minutes as token refresh is handled externally by Sagemaker | ||
const TOKEN_EXPIRY = 5 * 60 * 1000 | ||
const DEFAULT_REGION = 'us-east-1' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already have logic for this. Use
return this.awsContext.getCredentialDefaultRegion() ?? defaultRegion |
in globals, e.g.:
globals.regionProvider
@@ -59,3 +59,4 @@ export { i18n } from './i18n-helper' | |||
export * from './icons' | |||
export * as textDocumentUtil from './utilities/textDocumentUtilities' | |||
export { TabTypeDataMap } from '../amazonq/webview/ui/tabs/constants' | |||
export * from './sagemaker/client/sagemaker' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is packages/amazonq
going to use this soon? Otherwise this isn't needed.
let useDefaultCredentials = true | ||
|
||
if (isSageMaker() && isAmazonQ()) { | ||
useDefaultCredentials = !(await SageMakerSpaceClient.getInstance().getAmazonQProfileArn()) | ||
} | ||
|
||
if (useDefaultCredentials) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let useDefaultCredentials = true | |
if (isSageMaker() && isAmazonQ()) { | |
useDefaultCredentials = !(await SageMakerSpaceClient.getInstance().getAmazonQProfileArn()) | |
} | |
if (useDefaultCredentials) { | |
const useDefaultCredentials = isSageMaker() && isAmazonQ() && !(await SageMakerSpaceClient.getInstance().getAmazonQProfileArn()) | |
if (useDefaultCredentials) { |
|
||
return { | ||
scopes, | ||
startUrl: 'sagemaker', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't a URL... can we use sagemakerCookie.redirectURL
? I'm worried about callers using this field with functions expecting a real URL.
Problem
SageMaker Amazon Q Pro-tier users didn't have the ability to use their pro-tier profile ARN when using Amazon Q Chat & Code Completion. Previously, we had SageMaker pro-tier SSO users unable to automatically use their Code Editor login credentials to create an auth connection with Amazon Q APIs. This meant they have to re-login in order to use AmazonQ chat & Code Completion.
One big obstacle to enable auto-login for SSO users was that their credentials are stored in HttpOnly Cookie and a change had to be set in place in SageMaker Code Editor environment in order for AmazonQ extension to be able to read the cookie value and send it as bearer token.
Solution
Along with a change implemented for SageMaker Code Editor in https://github.com/aws/sagemaker-code-editor/pull/99/files
This PR implements the following:
1.1. In case Pro-tier is not enabled, the login flow is similar to IAM SageMaker users (using Container environment variables)
1.2. The custom command execution stores cookie values into a file and the client reads the value from that file.
Followup steps
Simplify the logic for communicating the SSO credentials and creating a connection based on such credentials, by letting SageMaker Code Editor create a standard AWS Credentials File & adding a watcher logic in AWS toolkit codebase to automatically sync with such file existence
feature/x
branches will not be squash-merged at release time.