1- import { loadAWSCredentials } from './aws ' ;
1+ import { AWSSDKCredentialProvider } from '../../cmap/auth/aws_temporary_credentials ' ;
22import { loadAzureCredentials } from './azure' ;
33import { loadGCPCredentials } from './gcp' ;
44
@@ -145,8 +145,17 @@ export function isEmptyCredentials(
145145
146146/**
147147 * @internal
148+ *
149+ * A class that fetchs KMS credentials on-demand during client encryption. This class is instantiated
150+ * per client encryption or auto encrypter and caches the AWS credential provider, if AWS is being used.
148151 */
149152export class KMSCredentialProvider {
153+ private _awsCredentialProvider ?: AWSSDKCredentialProvider ;
154+ private get awsCredentialProvider ( ) : AWSSDKCredentialProvider {
155+ this . _awsCredentialProvider ??= new AWSSDKCredentialProvider ( ) ;
156+ return this . _awsCredentialProvider ;
157+ }
158+
150159 constructor ( private readonly kmsProviders : KMSProviders ) { }
151160
152161 /**
@@ -158,7 +167,22 @@ export class KMSCredentialProvider {
158167 let finalKMSProviders = this . kmsProviders ;
159168
160169 if ( isEmptyCredentials ( 'aws' , this . kmsProviders ) ) {
161- finalKMSProviders = await loadAWSCredentials ( finalKMSProviders ) ;
170+ // We shouldn't ever receive a response from the AWS SDK that doesn't have these
171+ // fields. However, TS says these fields are optional. We provide empty strings
172+ // and let libmongocrypt error if we're unable to fetch the required keys.
173+ const {
174+ SecretAccessKey = '' ,
175+ Token = '' ,
176+ AccessKeyId = ''
177+ } = await this . awsCredentialProvider . getCredentials ( ) ;
178+ finalKMSProviders = {
179+ ...this . kmsProviders ,
180+ aws : {
181+ secretAccessKey : SecretAccessKey ,
182+ sessionToken : Token ,
183+ accessKeyId : AccessKeyId
184+ }
185+ } ;
162186 }
163187
164188 if ( isEmptyCredentials ( 'gcp' , this . kmsProviders ) ) {
0 commit comments