123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- import { describe, it, beforeEach, afterEach } from 'vitest'
- import assert from 'node:assert'
- import {
- S3Client,
- UploadPartCommand,
- PutObjectCommand,
- } from '@aws-sdk/client-s3'
- import { getSignedUrl } from '@aws-sdk/s3-request-presigner'
- import createSignedURL from './createSignedURL.ts'
- const bucketName = 'some-bucket.with.dots'
- const s3ClientOptions = {
- region: 'us-bar-1',
- credentials: {
- accessKeyId: 'foo',
- secretAccessKey: 'bar',
- sessionToken: 'foobar',
- },
- }
- const { Date: OriginalDate } = globalThis
- describe('createSignedURL', () => {
- beforeEach(() => {
- const now_ms = OriginalDate.now()
- // @ts-expect-error we're touching globals for test purposes.
- globalThis.Date = function Date() {
- if (new.target) {
- return Reflect.construct(OriginalDate, [now_ms])
- }
- return Reflect.apply(OriginalDate, this, [now_ms])
- }
- globalThis.Date.now = function now() {
- return now_ms
- }
- })
- afterEach(() => {
- globalThis.Date = OriginalDate
- })
- it('should be able to sign non-multipart upload', async () => {
- const client = new S3Client(s3ClientOptions)
- assert.strictEqual(
- (
- await createSignedURL({
- accountKey: s3ClientOptions.credentials.accessKeyId,
- accountSecret: s3ClientOptions.credentials.secretAccessKey,
- sessionToken: s3ClientOptions.credentials.sessionToken,
- bucketName,
- Key: 'some/key',
- Region: s3ClientOptions.region,
- expires: 900,
- })
- ).searchParams.get('X-Amz-Signature'),
- new URL(
- await getSignedUrl(
- client,
- new PutObjectCommand({
- Bucket: bucketName,
- Key: 'some/key',
- }),
- { expiresIn: 900 },
- ),
- ).searchParams.get('X-Amz-Signature'),
- )
- })
- it('should be able to sign multipart upload', async () => {
- const client = new S3Client(s3ClientOptions)
- const partNumber = 99
- const uploadId = 'dummyUploadId'
- assert.strictEqual(
- (
- await createSignedURL({
- accountKey: s3ClientOptions.credentials.accessKeyId,
- accountSecret: s3ClientOptions.credentials.secretAccessKey,
- sessionToken: s3ClientOptions.credentials.sessionToken,
- uploadId,
- partNumber,
- bucketName,
- Key: 'some/key',
- Region: s3ClientOptions.region,
- expires: 900,
- })
- ).searchParams.get('X-Amz-Signature'),
- new URL(
- await getSignedUrl(
- client,
- new UploadPartCommand({
- Bucket: bucketName,
- UploadId: uploadId,
- PartNumber: partNumber,
- Key: 'some/key',
- }),
- { expiresIn: 900 },
- ),
- ).searchParams.get('X-Amz-Signature'),
- )
- })
- it('should escape path and query as restricted to RFC 3986', async () => {
- const client = new S3Client(s3ClientOptions)
- const partNumber = 99
- const specialChars = ";?:@&=+$,#!'()"
- const uploadId = `Upload${specialChars}Id`
- // '.*' chars of path should be encoded
- const Key = `${specialChars}.*/${specialChars}.*.ext`
- const implResult = await createSignedURL({
- accountKey: s3ClientOptions.credentials.accessKeyId,
- accountSecret: s3ClientOptions.credentials.secretAccessKey,
- sessionToken: s3ClientOptions.credentials.sessionToken,
- uploadId,
- partNumber,
- bucketName,
- Key,
- Region: s3ClientOptions.region,
- expires: 900,
- })
- const sdkResult = new URL(
- await getSignedUrl(
- client,
- new UploadPartCommand({
- Bucket: bucketName,
- UploadId: uploadId,
- PartNumber: partNumber,
- Key,
- }),
- { expiresIn: 900 },
- ),
- )
- assert.strictEqual(implResult.pathname, sdkResult.pathname)
- const extractUploadId = /([?&])uploadId=([^&]+?)(&|$)/
- const extractSignature = /([?&])X-Amz-Signature=([^&]+?)(&|$)/
- assert.strictEqual(
- implResult.search.match(extractUploadId)![2],
- sdkResult.search.match(extractUploadId)![2],
- )
- assert.strictEqual(
- implResult.search.match(extractSignature)![2],
- sdkResult.search.match(extractSignature)![2],
- )
- })
- })
|