Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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: 10 additions & 0 deletions runtimes/protocol/identity-management.ts
Original file line number Diff line number Diff line change
Expand Up @@ -400,3 +400,13 @@ export interface StsCredentialChangedParams {
export const stsCredentialChangedRequestType = new ProtocolNotificationType<StsCredentialChangedParams, void>(
'aws/identity/stsCredentialChanged'
)

// profileChanged
export interface ProfileChangedParams {
profiles: Profile[]
ssoSessions: SsoSession[]
}

export const profileChangedRequestType = new ProtocolNotificationType<ProfileChangedParams, void>(
'aws/identity/stsCredentialChanged'
)
21 changes: 15 additions & 6 deletions runtimes/runtimes/auth/standalone/encryption.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Readable } from 'stream'
import { CompactEncrypt } from 'jose'
import { compactDecrypt, CompactEncrypt } from 'jose'
import { GetIamCredentialResult, GetSsoTokenResult } from '../../../protocol'

export function shouldWaitForEncryptionKey(): boolean {
Expand Down Expand Up @@ -99,6 +99,15 @@ export function encryptObjectWithKey(request: Object, key: string, alg?: string,
.encrypt(keyBuffer)
}

/**
* Decrypt an object with the provided key
*/
export async function decryptObjectWithKey<T>(request: string, key: string, alg?: string, enc?: string): Promise<T> {
const keyBuffer = Buffer.from(key, 'base64')
const result = await compactDecrypt(request, keyBuffer)
return JSON.parse(new TextDecoder().decode(result.plaintext)) as T
}

/**
* Encrypts the SSO access tokens inside the result object with the provided key
*/
Expand All @@ -124,12 +133,12 @@ export async function encryptIamResultWithKey(
request: GetIamCredentialResult,
key: string
): Promise<GetIamCredentialResult> {
const { accessKeyId, secretAccessKey, sessionToken, expiration } = request.credential.credentials
request.credential.credentials = {
accessKeyId: await encryptObjectWithKey(request.credential.credentials.accessKeyId, key),
secretAccessKey: await encryptObjectWithKey(request.credential.credentials.secretAccessKey, key),
...(request.credential.credentials.sessionToken
? { sessionToken: await encryptObjectWithKey(request.credential.credentials.sessionToken, key) }
: {}),
accessKeyId: await encryptObjectWithKey(accessKeyId, key),
secretAccessKey: await encryptObjectWithKey(secretAccessKey, key),
sessionToken: sessionToken ? await encryptObjectWithKey(sessionToken, key) : undefined,
expiration: expiration,
}
if (!request.updateCredentialsParams.encrypted) {
request.updateCredentialsParams.data = await encryptObjectWithKey(
Expand Down
2 changes: 2 additions & 0 deletions runtimes/runtimes/base-runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ import {
updateProfileRequestType,
stsCredentialChangedRequestType,
getMfaCodeRequestType,
profileChangedRequestType,
} from '../protocol/identity-management'
import { IdentityManagement } from '../server-interface/identity-management'
import { WebBase64Encoding } from './encoding'
Expand Down Expand Up @@ -217,6 +218,7 @@ export const baseRuntime = (connections: { reader: MessageReader; writer: Messag
onInvalidateStsCredential: handler => lspConnection.onRequest(invalidateStsCredentialRequestType, handler),
sendSsoTokenChanged: params => lspConnection.sendNotification(ssoTokenChangedRequestType, params),
sendStsCredentialChanged: params => lspConnection.sendNotification(stsCredentialChangedRequestType, params),
sendProfileChanged: params => lspConnection.sendNotification(profileChangedRequestType, params),
sendGetMfaCode: params => lspConnection.sendRequest(getMfaCodeRequestType, params),
}

Expand Down
14 changes: 13 additions & 1 deletion runtimes/runtimes/standalone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,12 @@ import {
ShowOpenDialogRequestType,
stsCredentialChangedRequestType,
getMfaCodeRequestType,
profileChangedRequestType,
UpdateProfileParams,
} from '../protocol'
import { ProposedFeatures, createConnection } from 'vscode-languageserver/node'
import {
decryptObjectWithKey,
encryptIamResultWithKey,
EncryptionInitialization,
encryptObjectWithKey,
Expand Down Expand Up @@ -304,7 +307,15 @@ export const standalone = (props: RuntimeProps) => {

const identityManagement: IdentityManagement = {
onListProfiles: handler => lspConnection.onRequest(listProfilesRequestType, handler),
onUpdateProfile: handler => lspConnection.onRequest(updateProfileRequestType, handler),
onUpdateProfile: handler =>
lspConnection.onRequest(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this send unencrypted profile details to the client?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, onUpdateProfile does send anything to the client. onListProfiles would though, so it might be worth encrypting that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yes, that would be required.

updateProfileRequestType,
async (params: UpdateProfileParams | string, token: CancellationToken) => {
const decrypted: UpdateProfileParams =
typeof params === 'string' ? await decryptObjectWithKey(params, encryptionKey!) : params
return await handler(decrypted, token)
}
),
onGetSsoToken: handler =>
lspConnection.onRequest(
getSsoTokenRequestType,
Expand All @@ -331,6 +342,7 @@ export const standalone = (props: RuntimeProps) => {
onInvalidateStsCredential: handler => lspConnection.onRequest(invalidateStsCredentialRequestType, handler),
sendSsoTokenChanged: params => lspConnection.sendNotification(ssoTokenChangedRequestType, params),
sendStsCredentialChanged: params => lspConnection.sendNotification(stsCredentialChangedRequestType, params),
sendProfileChanged: params => lspConnection.sendNotification(profileChangedRequestType, params),
sendGetMfaCode: params => lspConnection.sendRequest(getMfaCodeRequestType, params),
}

Expand Down
3 changes: 3 additions & 0 deletions runtimes/server-interface/identity-management.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
UpdateProfileParams,
UpdateProfileResult,
GetMfaCodeResult,
ProfileChangedParams,
} from '../protocol/identity-management'
import { RequestHandler } from '../protocol'

Expand Down Expand Up @@ -54,5 +55,7 @@ export type IdentityManagement = {

sendStsCredentialChanged: (params: StsCredentialChangedParams) => void

sendProfileChanged: (params: ProfileChangedParams) => void

sendGetMfaCode: (params: GetMfaCodeParams) => Promise<GetMfaCodeResult>
}