diff --git a/client/create_headers.ts b/client/create_headers.ts index 40d63a5..e5273d1 100644 --- a/client/create_headers.ts +++ b/client/create_headers.ts @@ -19,11 +19,11 @@ export interface HeadersConfig extends ClientConfig { } /** Assembles a header object for a DynamoDB request. */ -export function createHeaders( +export async function createHeaders( op: string, payload: Uint8Array, conf: HeadersConfig -): Headers { +): Promise { const amzTarget: string = `DynamoDB_20120810.${op}`; const amzDate: string = date.format(conf.date || new Date(), "amz"); @@ -67,10 +67,17 @@ export function createHeaders( conf.cache.credentialScope }, SignedHeaders=${signedHeaders}, Signature=${signature}`; - return new Headers({ + const headers = new Headers({ "Content-Type": POST_CONTENT_TYPE, "X-Amz-Date": amzDate, "X-Amz-Target": amzTarget, Authorization: authorizationHeader }); + + // https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html + if (conf.sessionToken) { + headers.append("X-Amz-Security-Token", await conf.sessionToken()); + } + + return headers } diff --git a/mod.ts b/mod.ts index 17028f5..30cc50b 100644 --- a/mod.ts +++ b/mod.ts @@ -29,6 +29,7 @@ export interface ClientConfig { region: string; // us-west-2 canonicalUri?: string; // fx /path/to/somewhere port?: number; // 8000 + sessionToken?: () => string | Promise; } /** Op options. */ @@ -137,7 +138,7 @@ function createCache(conf: Doc): Doc { async function baseFetch(conf: Doc, op: string, params: Doc): Promise { const payload: Uint8Array = encode(JSON.stringify(params), "utf8"); - const headers: Headers = createHeaders(op, payload, conf as HeadersConfig); + const headers: Headers = await createHeaders(op, payload, conf as HeadersConfig); const response: Response = await fetch(conf.endpoint, { method: conf.method, diff --git a/test.ts b/test.ts index 5700f93..d03131d 100644 --- a/test.ts +++ b/test.ts @@ -432,4 +432,20 @@ test({ } }); +test({ + name: "test security token can be passed", + async fn(): Promise { + // currently there's no way to test this is appended to the header + // but we include it in the ClientConfig. + const conf: ClientConfig = { + accessKeyId: ENV.ACCESS_KEY_ID, + secretAccessKey: ENV.SECRET_ACCESS_KEY, + region: "local", + sessionToken: () => "test" + }; + const ddbc: DynamoDBClient = createClient(conf); + const result: Doc = await ddbc.listTables(); + } +}); + runIfMain(import.meta);