diff --git a/clients/client-s3/models/models_0.ts b/clients/client-s3/models/models_0.ts index 428ee59dee33..d713350fa210 100644 --- a/clients/client-s3/models/models_0.ts +++ b/clients/client-s3/models/models_0.ts @@ -51,6 +51,8 @@ export interface AbortMultipartUploadRequest { *

The bucket name to which the upload was taking place.

*

When using this action with an access point, you must direct requests to the access point hostname. The access point hostname takes the form AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this action with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket name. For more information about access point ARNs, see Using access points in the Amazon S3 User Guide.

*

When using this action with Amazon S3 on Outposts, you must direct requests to the S3 on Outposts hostname. The S3 on Outposts hostname takes the form AccessPointName-AccountId.outpostID.s3-outposts.Region.amazonaws.com. When using this action using S3 on Outposts through the Amazon Web Services SDKs, you provide the Outposts bucket ARN in place of the bucket name. For more information about S3 on Outposts ARNs, see Using S3 on Outposts in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -420,6 +422,8 @@ export interface CompleteMultipartUploadRequest { *

Name of the bucket to which the multipart upload was initiated.

*

When using this action with an access point, you must direct requests to the access point hostname. The access point hostname takes the form AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this action with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket name. For more information about access point ARNs, see Using access points in the Amazon S3 User Guide.

*

When using this action with Amazon S3 on Outposts, you must direct requests to the S3 on Outposts hostname. The S3 on Outposts hostname takes the form AccessPointName-AccountId.outpostID.s3-outposts.Region.amazonaws.com. When using this action using S3 on Outposts through the Amazon Web Services SDKs, you provide the Outposts bucket ARN in place of the bucket name. For more information about S3 on Outposts ARNs, see Using S3 on Outposts in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -599,6 +603,8 @@ export interface CopyObjectRequest { *

The name of the destination bucket.

*

When using this action with an access point, you must direct requests to the access point hostname. The access point hostname takes the form AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this action with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket name. For more information about access point ARNs, see Using access points in the Amazon S3 User Guide.

*

When using this action with Amazon S3 on Outposts, you must direct requests to the S3 on Outposts hostname. The S3 on Outposts hostname takes the form AccessPointName-AccountId.outpostID.s3-outposts.Region.amazonaws.com. When using this action using S3 on Outposts through the Amazon Web Services SDKs, you provide the Outposts bucket ARN in place of the bucket name. For more information about S3 on Outposts ARNs, see Using S3 on Outposts in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -1154,6 +1160,8 @@ export interface CreateMultipartUploadRequest { *

The name of the bucket to which to initiate the upload

*

When using this action with an access point, you must direct requests to the access point hostname. The access point hostname takes the form AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this action with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket name. For more information about access point ARNs, see Using access points in the Amazon S3 User Guide.

*

When using this action with Amazon S3 on Outposts, you must direct requests to the S3 on Outposts hostname. The S3 on Outposts hostname takes the form AccessPointName-AccountId.outpostID.s3-outposts.Region.amazonaws.com. When using this action using S3 on Outposts through the Amazon Web Services SDKs, you provide the Outposts bucket ARN in place of the bucket name. For more information about S3 on Outposts ARNs, see Using S3 on Outposts in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -1361,6 +1369,8 @@ export namespace DeleteBucketRequest { export interface DeleteBucketAnalyticsConfigurationRequest { /** *

The name of the bucket from which an analytics configuration is deleted.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -1387,6 +1397,8 @@ export namespace DeleteBucketAnalyticsConfigurationRequest { export interface DeleteBucketCorsRequest { /** *

Specifies the bucket whose cors configuration is being deleted.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -1409,6 +1421,8 @@ export interface DeleteBucketEncryptionRequest { /** *

The name of the bucket containing the server-side encryption configuration to * delete.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -1430,6 +1444,8 @@ export namespace DeleteBucketEncryptionRequest { export interface DeleteBucketIntelligentTieringConfigurationRequest { /** *

The name of the Amazon S3 bucket whose configuration you want to modify or retrieve.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -1451,6 +1467,8 @@ export namespace DeleteBucketIntelligentTieringConfigurationRequest { export interface DeleteBucketInventoryConfigurationRequest { /** *

The name of the bucket containing the inventory configuration to delete.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -1477,6 +1495,8 @@ export namespace DeleteBucketInventoryConfigurationRequest { export interface DeleteBucketLifecycleRequest { /** *

The bucket name of the lifecycle to delete.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -1498,6 +1518,8 @@ export namespace DeleteBucketLifecycleRequest { export interface DeleteBucketMetricsConfigurationRequest { /** *

The name of the bucket containing the metrics configuration to delete.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -1524,6 +1546,8 @@ export namespace DeleteBucketMetricsConfigurationRequest { export interface DeleteBucketOwnershipControlsRequest { /** *

The Amazon S3 bucket whose OwnershipControls you want to delete.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -1545,6 +1569,8 @@ export namespace DeleteBucketOwnershipControlsRequest { export interface DeleteBucketPolicyRequest { /** *

The bucket name.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -1566,6 +1592,8 @@ export namespace DeleteBucketPolicyRequest { export interface DeleteBucketReplicationRequest { /** *

The bucket name.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -1587,6 +1615,8 @@ export namespace DeleteBucketReplicationRequest { export interface DeleteBucketTaggingRequest { /** *

The bucket that has the tag set to be removed.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -1608,6 +1638,8 @@ export namespace DeleteBucketTaggingRequest { export interface DeleteBucketWebsiteRequest { /** *

The bucket name for which you want to remove the website configuration.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -1660,6 +1692,8 @@ export interface DeleteObjectRequest { *

The bucket name of the bucket containing the object.

*

When using this action with an access point, you must direct requests to the access point hostname. The access point hostname takes the form AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this action with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket name. For more information about access point ARNs, see Using access points in the Amazon S3 User Guide.

*

When using this action with Amazon S3 on Outposts, you must direct requests to the S3 on Outposts hostname. The S3 on Outposts hostname takes the form AccessPointName-AccountId.outpostID.s3-outposts.Region.amazonaws.com. When using this action using S3 on Outposts through the Amazon Web Services SDKs, you provide the Outposts bucket ARN in place of the bucket name. For more information about S3 on Outposts ARNs, see Using S3 on Outposts in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -3737,6 +3771,8 @@ export interface DeleteObjectsRequest { *

The bucket name containing the objects to delete.

*

When using this action with an access point, you must direct requests to the access point hostname. The access point hostname takes the form AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this action with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket name. For more information about access point ARNs, see Using access points in the Amazon S3 User Guide.

*

When using this action with Amazon S3 on Outposts, you must direct requests to the S3 on Outposts hostname. The S3 on Outposts hostname takes the form AccessPointName-AccountId.outpostID.s3-outposts.Region.amazonaws.com. When using this action using S3 on Outposts through the Amazon Web Services SDKs, you provide the Outposts bucket ARN in place of the bucket name. For more information about S3 on Outposts ARNs, see Using S3 on Outposts in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -3803,6 +3839,8 @@ export interface DeleteObjectTaggingRequest { *

The bucket name containing the objects from which to remove the tags.

*

When using this action with an access point, you must direct requests to the access point hostname. The access point hostname takes the form AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this action with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket name. For more information about access point ARNs, see Using access points in the Amazon S3 User Guide.

*

When using this action with Amazon S3 on Outposts, you must direct requests to the S3 on Outposts hostname. The S3 on Outposts hostname takes the form AccessPointName-AccountId.outpostID.s3-outposts.Region.amazonaws.com. When using this action using S3 on Outposts through the Amazon Web Services SDKs, you provide the Outposts bucket ARN in place of the bucket name. For more information about S3 on Outposts ARNs, see Using S3 on Outposts in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -3835,6 +3873,8 @@ export interface DeletePublicAccessBlockRequest { /** *

The Amazon S3 bucket whose PublicAccessBlock configuration you want to delete. *

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -3872,6 +3912,8 @@ export namespace GetBucketAccelerateConfigurationOutput { export interface GetBucketAccelerateConfigurationRequest { /** *

The name of the bucket for which the accelerate configuration is retrieved.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -3914,6 +3956,8 @@ export namespace GetBucketAclOutput { export interface GetBucketAclRequest { /** *

Specifies the S3 bucket whose ACL is being requested.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -4222,6 +4266,8 @@ export namespace GetBucketAnalyticsConfigurationOutput { export interface GetBucketAnalyticsConfigurationRequest { /** *

The name of the bucket from which an analytics configuration is retrieved.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -4315,6 +4361,8 @@ export namespace GetBucketCorsOutput { export interface GetBucketCorsRequest { /** *

The bucket name for which to get the cors configuration.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -4463,6 +4511,8 @@ export interface GetBucketEncryptionRequest { /** *

The name of the bucket from which the server-side encryption configuration is * retrieved.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -4637,6 +4687,8 @@ export namespace GetBucketIntelligentTieringConfigurationOutput { export interface GetBucketIntelligentTieringConfigurationRequest { /** *

The name of the Amazon S3 bucket whose configuration you want to modify or retrieve.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -4927,6 +4979,8 @@ export namespace GetBucketInventoryConfigurationOutput { export interface GetBucketInventoryConfigurationRequest { /** *

The name of the bucket containing the inventory configuration to retrieve.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -5289,6 +5343,8 @@ export namespace GetBucketLifecycleConfigurationOutput { export interface GetBucketLifecycleConfigurationRequest { /** *

The name of the bucket for which to get the lifecycle information.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -5329,6 +5385,8 @@ export namespace GetBucketLocationOutput { export interface GetBucketLocationRequest { /** *

The name of the bucket for which to get the location.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -5431,6 +5489,8 @@ export namespace GetBucketLoggingOutput { export interface GetBucketLoggingRequest { /** *

The bucket name for which to get the logging information.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -5628,6 +5688,8 @@ export namespace GetBucketMetricsConfigurationOutput { export interface GetBucketMetricsConfigurationRequest { /** *

The name of the bucket containing the metrics configuration to retrieve.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -5654,6 +5716,8 @@ export namespace GetBucketMetricsConfigurationRequest { export interface GetBucketNotificationConfigurationRequest { /** *

The name of the bucket for which to get the notification configuration.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -5981,6 +6045,8 @@ export interface GetBucketOwnershipControlsRequest { /** *

The name of the Amazon S3 bucket whose OwnershipControls you want to retrieve. *

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -6018,6 +6084,8 @@ export namespace GetBucketPolicyOutput { export interface GetBucketPolicyRequest { /** *

The bucket name for which to get the bucket policy.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -6075,6 +6143,8 @@ export namespace GetBucketPolicyStatusOutput { export interface GetBucketPolicyStatusRequest { /** *

The name of the Amazon S3 bucket whose policy status you want to retrieve.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -6685,6 +6755,8 @@ export namespace GetBucketReplicationOutput { export interface GetBucketReplicationRequest { /** *

The bucket name for which to get the replication information.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -6724,6 +6796,8 @@ export namespace GetBucketRequestPaymentOutput { export interface GetBucketRequestPaymentRequest { /** *

The name of the bucket for which to get the payment request configuration

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -6761,6 +6835,8 @@ export namespace GetBucketTaggingOutput { export interface GetBucketTaggingRequest { /** *

The name of the bucket for which to get the tagging information.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -6809,6 +6885,8 @@ export namespace GetBucketVersioningOutput { export interface GetBucketVersioningRequest { /** *

The name of the bucket for which to get the versioning information.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -7075,6 +7153,8 @@ export namespace GetBucketWebsiteOutput { export interface GetBucketWebsiteRequest { /** *

The bucket name for which to get the website configuration.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -7294,6 +7374,8 @@ export interface GetObjectRequest { *

When using this action with an access point, you must direct requests to the access point hostname. The access point hostname takes the form AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this action with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket name. For more information about access point ARNs, see Using access points in the Amazon S3 User Guide.

*

When using an Object Lambda access point the hostname takes the form AccessPointName-AccountId.s3-object-lambda.Region.amazonaws.com.

*

When using this action with Amazon S3 on Outposts, you must direct requests to the S3 on Outposts hostname. The S3 on Outposts hostname takes the form AccessPointName-AccountId.outpostID.s3-outposts.Region.amazonaws.com. When using this action using S3 on Outposts through the Amazon Web Services SDKs, you provide the Outposts bucket ARN in place of the bucket name. For more information about S3 on Outposts ARNs, see Using S3 on Outposts in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -7490,6 +7572,8 @@ export interface GetObjectAclRequest { /** *

The bucket name that contains the object for which to get the ACL information.

*

When using this action with an access point, you must direct requests to the access point hostname. The access point hostname takes the form AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this action with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket name. For more information about access point ARNs, see Using access points in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -7565,6 +7649,8 @@ export interface GetObjectLegalHoldRequest { /** *

The bucket name containing the object whose Legal Hold status you want to retrieve.

*

When using this action with an access point, you must direct requests to the access point hostname. The access point hostname takes the form AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this action with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket name. For more information about access point ARNs, see Using access points in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -7722,6 +7808,8 @@ export interface GetObjectLockConfigurationRequest { /** *

The bucket whose Object Lock configuration you want to retrieve.

*

When using this action with an access point, you must direct requests to the access point hostname. The access point hostname takes the form AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this action with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket name. For more information about access point ARNs, see Using access points in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -7784,6 +7872,8 @@ export interface GetObjectRetentionRequest { /** *

The bucket name containing the object whose retention settings you want to retrieve.

*

When using this action with an access point, you must direct requests to the access point hostname. The access point hostname takes the form AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this action with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket name. For more information about access point ARNs, see Using access points in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -7846,6 +7936,8 @@ export interface GetObjectTaggingRequest { *

The bucket name containing the object for which to get the tagging information.

*

When using this action with an access point, you must direct requests to the access point hostname. The access point hostname takes the form AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this action with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket name. For more information about access point ARNs, see Using access points in the Amazon S3 User Guide.

*

When using this action with Amazon S3 on Outposts, you must direct requests to the S3 on Outposts hostname. The S3 on Outposts hostname takes the form AccessPointName-AccountId.outpostID.s3-outposts.Region.amazonaws.com. When using this action using S3 on Outposts through the Amazon Web Services SDKs, you provide the Outposts bucket ARN in place of the bucket name. For more information about S3 on Outposts ARNs, see Using S3 on Outposts in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -7907,6 +7999,8 @@ export namespace GetObjectTorrentOutput { export interface GetObjectTorrentRequest { /** *

The name of the bucket containing the object for which to get the torrent files.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -8023,6 +8117,8 @@ export interface GetPublicAccessBlockRequest { /** *

The name of the Amazon S3 bucket whose PublicAccessBlock configuration you want * to retrieve.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -8046,6 +8142,8 @@ export interface HeadBucketRequest { *

The bucket name.

*

When using this action with an access point, you must direct requests to the access point hostname. The access point hostname takes the form AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this action with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket name. For more information about access point ARNs, see Using access points in the Amazon S3 User Guide.

*

When using this action with Amazon S3 on Outposts, you must direct requests to the S3 on Outposts hostname. The S3 on Outposts hostname takes the form AccessPointName-AccountId.outpostID.s3-outposts.Region.amazonaws.com. When using this action using S3 on Outposts through the Amazon Web Services SDKs, you provide the Outposts bucket ARN in place of the bucket name. For more information about S3 on Outposts ARNs, see Using S3 on Outposts in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -8331,6 +8429,8 @@ export interface HeadObjectRequest { *

The name of the bucket containing the object.

*

When using this action with an access point, you must direct requests to the access point hostname. The access point hostname takes the form AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this action with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket name. For more information about access point ARNs, see Using access points in the Amazon S3 User Guide.

*

When using this action with Amazon S3 on Outposts, you must direct requests to the S3 on Outposts hostname. The S3 on Outposts hostname takes the form AccessPointName-AccountId.outpostID.s3-outposts.Region.amazonaws.com. When using this action using S3 on Outposts through the Amazon Web Services SDKs, you provide the Outposts bucket ARN in place of the bucket name. For more information about S3 on Outposts ARNs, see Using S3 on Outposts in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -8476,6 +8576,8 @@ export namespace ListBucketAnalyticsConfigurationsOutput { export interface ListBucketAnalyticsConfigurationsRequest { /** *

The name of the bucket from which analytics configurations are retrieved.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -8539,6 +8641,8 @@ export namespace ListBucketIntelligentTieringConfigurationsOutput { export interface ListBucketIntelligentTieringConfigurationsRequest { /** *

The name of the Amazon S3 bucket whose configuration you want to modify or retrieve.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -8602,6 +8706,8 @@ export namespace ListBucketInventoryConfigurationsOutput { export interface ListBucketInventoryConfigurationsRequest { /** *

The name of the bucket containing the inventory configurations to retrieve.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -8672,6 +8778,8 @@ export namespace ListBucketMetricsConfigurationsOutput { export interface ListBucketMetricsConfigurationsRequest { /** *

The name of the bucket containing the metrics configurations to retrieve.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -8930,6 +9038,8 @@ export interface ListMultipartUploadsRequest { *

The name of the bucket to which the multipart upload was initiated.

*

When using this action with an access point, you must direct requests to the access point hostname. The access point hostname takes the form AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this action with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket name. For more information about access point ARNs, see Using access points in the Amazon S3 User Guide.

*

When using this action with Amazon S3 on Outposts, you must direct requests to the S3 on Outposts hostname. The S3 on Outposts hostname takes the form AccessPointName-AccountId.outpostID.s3-outposts.Region.amazonaws.com. When using this action using S3 on Outposts through the Amazon Web Services SDKs, you provide the Outposts bucket ARN in place of the bucket name. For more information about S3 on Outposts ARNs, see Using S3 on Outposts in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -9167,6 +9277,8 @@ export interface ListObjectsRequest { *

The name of the bucket containing the objects.

*

When using this action with an access point, you must direct requests to the access point hostname. The access point hostname takes the form AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this action with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket name. For more information about access point ARNs, see Using access points in the Amazon S3 User Guide.

*

When using this action with Amazon S3 on Outposts, you must direct requests to the S3 on Outposts hostname. The S3 on Outposts hostname takes the form AccessPointName-AccountId.outpostID.s3-outposts.Region.amazonaws.com. When using this action using S3 on Outposts through the Amazon Web Services SDKs, you provide the Outposts bucket ARN in place of the bucket name. For more information about S3 on Outposts ARNs, see Using S3 on Outposts in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -9355,6 +9467,8 @@ export interface ListObjectsV2Request { *

Bucket name to list.

*

When using this action with an access point, you must direct requests to the access point hostname. The access point hostname takes the form AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this action with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket name. For more information about access point ARNs, see Using access points in the Amazon S3 User Guide.

*

When using this action with Amazon S3 on Outposts, you must direct requests to the S3 on Outposts hostname. The S3 on Outposts hostname takes the form AccessPointName-AccountId.outpostID.s3-outposts.Region.amazonaws.com. When using this action using S3 on Outposts through the Amazon Web Services SDKs, you provide the Outposts bucket ARN in place of the bucket name. For more information about S3 on Outposts ARNs, see Using S3 on Outposts in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -9616,6 +9730,8 @@ export namespace ListObjectVersionsOutput { export interface ListObjectVersionsRequest { /** *

The bucket name that contains the objects.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -9824,6 +9940,8 @@ export interface ListPartsRequest { *

The name of the bucket to which the parts are being uploaded.

*

When using this action with an access point, you must direct requests to the access point hostname. The access point hostname takes the form AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this action with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket name. For more information about access point ARNs, see Using access points in the Amazon S3 User Guide.

*

When using this action with Amazon S3 on Outposts, you must direct requests to the S3 on Outposts hostname. The S3 on Outposts hostname takes the form AccessPointName-AccountId.outpostID.s3-outposts.Region.amazonaws.com. When using this action using S3 on Outposts through the Amazon Web Services SDKs, you provide the Outposts bucket ARN in place of the bucket name. For more information about S3 on Outposts ARNs, see Using S3 on Outposts in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -9874,6 +9992,8 @@ export namespace ListPartsRequest { export interface PutBucketAccelerateConfigurationRequest { /** *

The name of the bucket for which the accelerate configuration is set.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -9910,6 +10030,8 @@ export interface PutBucketAclRequest { /** *

The bucket to which to apply the ACL.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -9968,6 +10090,8 @@ export namespace PutBucketAclRequest { export interface PutBucketAnalyticsConfigurationRequest { /** *

The name of the bucket to which an analytics configuration is stored.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -10024,6 +10148,8 @@ export namespace CORSConfiguration { export interface PutBucketCorsRequest { /** *

Specifies the bucket impacted by the corsconfiguration.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -10065,6 +10191,8 @@ export interface PutBucketEncryptionRequest { * keys (SSE-S3) or customer managed keys (SSE-KMS). For information about * the Amazon S3 default encryption feature, see Amazon S3 Default Bucket Encryption * in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -10102,6 +10230,8 @@ export namespace PutBucketEncryptionRequest { export interface PutBucketIntelligentTieringConfigurationRequest { /** *

The name of the Amazon S3 bucket whose configuration you want to modify or retrieve.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -10128,6 +10258,8 @@ export namespace PutBucketIntelligentTieringConfigurationRequest { export interface PutBucketInventoryConfigurationRequest { /** *

The name of the bucket where the inventory configuration will be stored.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -10184,6 +10316,8 @@ export namespace BucketLifecycleConfiguration { export interface PutBucketLifecycleConfigurationRequest { /** *

The name of the bucket for which to set the configuration.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -10234,6 +10368,8 @@ export namespace BucketLoggingStatus { export interface PutBucketLoggingRequest { /** *

The name of the bucket for which to set the logging parameters.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -10266,6 +10402,8 @@ export namespace PutBucketLoggingRequest { export interface PutBucketMetricsConfigurationRequest { /** *

The name of the bucket for which the metrics configuration is set.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -10300,6 +10438,8 @@ export namespace PutBucketMetricsConfigurationRequest { export interface PutBucketNotificationConfigurationRequest { /** *

The name of the bucket.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -10327,6 +10467,8 @@ export namespace PutBucketNotificationConfigurationRequest { export interface PutBucketOwnershipControlsRequest { /** *

The name of the Amazon S3 bucket whose OwnershipControls you want to set.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -10360,6 +10502,8 @@ export namespace PutBucketOwnershipControlsRequest { export interface PutBucketPolicyRequest { /** *

The name of the bucket.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -10398,6 +10542,8 @@ export namespace PutBucketPolicyRequest { export interface PutBucketReplicationRequest { /** *

The name of the bucket

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -10460,6 +10606,8 @@ export namespace RequestPaymentConfiguration { export interface PutBucketRequestPaymentRequest { /** *

The bucket name.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -10514,6 +10662,8 @@ export namespace Tagging { export interface PutBucketTaggingRequest { /** *

The bucket name.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -10577,6 +10727,8 @@ export namespace VersioningConfiguration { export interface PutBucketVersioningRequest { /** *

The bucket name.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -10655,6 +10807,8 @@ export namespace WebsiteConfiguration { export interface PutBucketWebsiteRequest { /** *

The bucket name.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -10779,6 +10933,8 @@ export interface PutObjectRequest { *

The bucket name to which the PUT action was initiated.

*

When using this action with an access point, you must direct requests to the access point hostname. The access point hostname takes the form AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this action with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket name. For more information about access point ARNs, see Using access points in the Amazon S3 User Guide.

*

When using this action with Amazon S3 on Outposts, you must direct requests to the S3 on Outposts hostname. The S3 on Outposts hostname takes the form AccessPointName-AccountId.outpostID.s3-outposts.Region.amazonaws.com. When using this action using S3 on Outposts through the Amazon Web Services SDKs, you provide the Outposts bucket ARN in place of the bucket name. For more information about S3 on Outposts ARNs, see Using S3 on Outposts in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -11036,6 +11192,8 @@ export interface PutObjectAclRequest { /** *

The bucket name that contains the object to which you want to attach the ACL.

*

When using this action with an access point, you must direct requests to the access point hostname. The access point hostname takes the form AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this action with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket name. For more information about access point ARNs, see Using access points in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -11138,6 +11296,8 @@ export interface PutObjectLegalHoldRequest { /** *

The bucket name containing the object that you want to place a Legal Hold on.

*

When using this action with an access point, you must direct requests to the access point hostname. The access point hostname takes the form AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this action with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket name. For more information about access point ARNs, see Using access points in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -11206,6 +11366,8 @@ export namespace PutObjectLockConfigurationOutput { export interface PutObjectLockConfigurationRequest { /** *

The bucket whose Object Lock configuration you want to create or replace.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -11270,6 +11432,8 @@ export interface PutObjectRetentionRequest { *

The bucket name that contains the object you want to apply this Object Retention * configuration to.

*

When using this action with an access point, you must direct requests to the access point hostname. The access point hostname takes the form AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this action with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket name. For more information about access point ARNs, see Using access points in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -11345,6 +11509,8 @@ export interface PutObjectTaggingRequest { *

The bucket name containing the object.

*

When using this action with an access point, you must direct requests to the access point hostname. The access point hostname takes the form AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this action with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket name. For more information about access point ARNs, see Using access points in the Amazon S3 User Guide.

*

When using this action with Amazon S3 on Outposts, you must direct requests to the S3 on Outposts hostname. The S3 on Outposts hostname takes the form AccessPointName-AccountId.outpostID.s3-outposts.Region.amazonaws.com. When using this action using S3 on Outposts through the Amazon Web Services SDKs, you provide the Outposts bucket ARN in place of the bucket name. For more information about S3 on Outposts ARNs, see Using S3 on Outposts in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -11396,6 +11562,8 @@ export interface PutPublicAccessBlockRequest { /** *

The name of the Amazon S3 bucket whose PublicAccessBlock configuration you want * to set.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; diff --git a/clients/client-s3/models/models_1.ts b/clients/client-s3/models/models_1.ts index 0c03ca1a1425..0d19c2284ac8 100644 --- a/clients/client-s3/models/models_1.ts +++ b/clients/client-s3/models/models_1.ts @@ -514,6 +514,8 @@ export interface RestoreObjectRequest { *

The bucket name containing the object to restore.

*

When using this action with an access point, you must direct requests to the access point hostname. The access point hostname takes the form AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this action with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket name. For more information about access point ARNs, see Using access points in the Amazon S3 User Guide.

*

When using this action with Amazon S3 on Outposts, you must direct requests to the S3 on Outposts hostname. The S3 on Outposts hostname takes the form AccessPointName-AccountId.outpostID.s3-outposts.Region.amazonaws.com. When using this action using S3 on Outposts through the Amazon Web Services SDKs, you provide the Outposts bucket ARN in place of the bucket name. For more information about S3 on Outposts ARNs, see Using S3 on Outposts in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -898,6 +900,8 @@ export namespace ScanRange { export interface SelectObjectContentRequest { /** *

The S3 bucket.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -1055,6 +1059,8 @@ export interface UploadPartRequest { *

The name of the bucket to which the multipart upload was initiated.

*

When using this action with an access point, you must direct requests to the access point hostname. The access point hostname takes the form AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this action with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket name. For more information about access point ARNs, see Using access points in the Amazon S3 User Guide.

*

When using this action with Amazon S3 on Outposts, you must direct requests to the S3 on Outposts hostname. The S3 on Outposts hostname takes the form AccessPointName-AccountId.outpostID.s3-outposts.Region.amazonaws.com. When using this action using S3 on Outposts through the Amazon Web Services SDKs, you provide the Outposts bucket ARN in place of the bucket name. For more information about S3 on Outposts ARNs, see Using S3 on Outposts in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; @@ -1221,6 +1227,8 @@ export interface UploadPartCopyRequest { *

The bucket name.

*

When using this action with an access point, you must direct requests to the access point hostname. The access point hostname takes the form AccessPointName-AccountId.s3-accesspoint.Region.amazonaws.com. When using this action with an access point through the Amazon Web Services SDKs, you provide the access point ARN in place of the bucket name. For more information about access point ARNs, see Using access points in the Amazon S3 User Guide.

*

When using this action with Amazon S3 on Outposts, you must direct requests to the S3 on Outposts hostname. The S3 on Outposts hostname takes the form AccessPointName-AccountId.outpostID.s3-outposts.Region.amazonaws.com. When using this action using S3 on Outposts through the Amazon Web Services SDKs, you provide the Outposts bucket ARN in place of the bucket name. For more information about S3 on Outposts ARNs, see Using S3 on Outposts in the Amazon S3 User Guide.

+ *

Note: To supply the Multi-region Access Point (MRAP) to Bucket, you need to install the "@aws-sdk/signature-v4-crt" package to your project dependencies. + * For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

*/ Bucket: string | undefined; diff --git a/clients/client-s3/runtimeConfig.shared.ts b/clients/client-s3/runtimeConfig.shared.ts index f649ac862381..6f66110747f0 100644 --- a/clients/client-s3/runtimeConfig.shared.ts +++ b/clients/client-s3/runtimeConfig.shared.ts @@ -1,4 +1,5 @@ import { defaultRegionInfoProvider } from "./endpoints"; +import { S3SignatureV4 } from "@aws-sdk/middleware-sdk-s3"; import { Logger as __Logger } from "@aws-sdk/types"; import { parseUrl } from "@aws-sdk/url-parser"; import { S3ClientConfig } from "./S3Client"; @@ -12,6 +13,7 @@ export const getRuntimeConfig = (config: S3ClientConfig) => ({ logger: config?.logger ?? ({} as __Logger), regionInfoProvider: config?.regionInfoProvider ?? defaultRegionInfoProvider, serviceId: config?.serviceId ?? "S3", + signerConstructor: config?.signerConstructor ?? S3SignatureV4, signingEscapePath: config?.signingEscapePath ?? false, urlParser: config?.urlParser ?? parseUrl, useArnRegion: config?.useArnRegion ?? false, diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddS3Config.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddS3Config.java index 78901ba5f5a7..20fa91b225d0 100644 --- a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddS3Config.java +++ b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddS3Config.java @@ -19,16 +19,24 @@ import static software.amazon.smithy.typescript.codegen.integration.RuntimeClientPlugin.Convention.HAS_MIDDLEWARE; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Consumer; +import java.util.logging.Logger; import software.amazon.smithy.aws.traits.ServiceTrait; +import software.amazon.smithy.build.PluginContext; import software.amazon.smithy.codegen.core.SymbolProvider; import software.amazon.smithy.model.Model; import software.amazon.smithy.model.knowledge.OperationIndex; +import software.amazon.smithy.model.shapes.MemberShape; import software.amazon.smithy.model.shapes.OperationShape; +import software.amazon.smithy.model.shapes.ServiceShape; import software.amazon.smithy.model.shapes.Shape; +import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.model.shapes.StructureShape; +import software.amazon.smithy.model.traits.DocumentationTrait; import software.amazon.smithy.typescript.codegen.LanguageTarget; import software.amazon.smithy.typescript.codegen.TypeScriptDependency; import software.amazon.smithy.typescript.codegen.TypeScriptSettings; @@ -45,6 +53,7 @@ */ @SmithyInternalApi public final class AddS3Config implements TypeScriptIntegration { + private static final Logger LOGGER = Logger.getLogger(AddS3Config.class.getName()); private static final Set SSEC_OPERATIONS = SetUtils.of("SSECustomerKey", "CopySourceSSECustomerKey"); @@ -60,6 +69,42 @@ public final class AddS3Config implements TypeScriptIntegration { "CompleteMultipartUpload" ); + private static final String CRT_NOTIFICATION = "

Note: To supply the Multi-region Access Point (MRAP) to Bucket," + + " you need to install the \"@aws-sdk/signature-v4-crt\" package to your project dependencies. \n" + + "For more information, please go to https://github.com/aws/aws-sdk-js-v3#known-issues

"; + + @Override + public Model preprocessModel(PluginContext context, TypeScriptSettings settings) { + Model model = context.getModel(); + ServiceShape serviceShape = settings.getService(model); + if (!testServiceId(serviceShape)) { + return model; + } + Model.Builder modelBuilder = model.toBuilder(); + Set inputShapes = new HashSet<>(); + for (ShapeId operationId : serviceShape.getAllOperations()) { + OperationShape operationShape = model.expectShape(operationId, OperationShape.class); + if (NON_BUCKET_ENDPOINT_OPERATIONS.contains(operationShape.getId().getName(serviceShape))) { + continue; + } + operationShape.getInput().ifPresent(inputShapeId -> { + StructureShape inputShape = model.expectShape(inputShapeId, StructureShape.class); + inputShape.getMember("Bucket").ifPresent(bucketMember -> { + bucketMember.getTrait(DocumentationTrait.class).ifPresent(documentationTrait -> { + StructureShape.Builder inputShapeBuilder = inputShape.toBuilder(); + MemberShape.Builder builder = MemberShape.shapeToBuilder(bucketMember); + String newDocString = documentationTrait.getValue() + "\n" + CRT_NOTIFICATION; + MemberShape newMemberShape = builder.addTrait(new DocumentationTrait(newDocString)).build(); + inputShapeBuilder.addMember(newMemberShape); + inputShapes.add(inputShapeBuilder.build()); + }); + }); + }); + } + LOGGER.info("Patching " + inputShapes.size() + " input shapes with CRT notification"); + return modelBuilder.addShapes(inputShapes).build(); + } + @Override public void addConfigInterfaceFields(TypeScriptSettings settings, Model model, SymbolProvider symbolProvider, TypeScriptWriter writer) { @@ -87,6 +132,10 @@ public Map> getRuntimeConfigWriters(TypeScrip writer.write("false"); }, "useArnRegion", writer -> { writer.write("false"); + }, "signerConstructor", writer -> { + writer.addDependency(AwsDependency.S3_MIDDLEWARE) + .addImport("S3SignatureV4", "S3SignatureV4", AwsDependency.S3_MIDDLEWARE.packageName) + .write("S3SignatureV4"); }); case NODE: return MapUtils.of("useArnRegion", writer -> { diff --git a/packages/middleware-bucket-endpoint/src/bucketEndpointMiddleware.spec.ts b/packages/middleware-bucket-endpoint/src/bucketEndpointMiddleware.spec.ts index 53bf929a5ce7..b7ff22808770 100644 --- a/packages/middleware-bucket-endpoint/src/bucketEndpointMiddleware.spec.ts +++ b/packages/middleware-bucket-endpoint/src/bucketEndpointMiddleware.spec.ts @@ -134,6 +134,7 @@ describe("bucketEndpointMiddleware", () => { clientSigningRegion: mockRegion, useArnRegion: false, isCustomEndpoint: false, + disableMultiregionAccessPoints: false, }); expect(previouslyResolvedConfig.region).toBeCalled(); expect(previouslyResolvedConfig.regionInfoProvider).toBeCalled(); diff --git a/packages/middleware-bucket-endpoint/src/bucketEndpointMiddleware.ts b/packages/middleware-bucket-endpoint/src/bucketEndpointMiddleware.ts index 6a8654472827..30e39cf465be 100644 --- a/packages/middleware-bucket-endpoint/src/bucketEndpointMiddleware.ts +++ b/packages/middleware-bucket-endpoint/src/bucketEndpointMiddleware.ts @@ -15,81 +15,76 @@ import { bucketHostname } from "./bucketHostname"; import { getPseudoRegion } from "./bucketHostnameUtils"; import { BucketEndpointResolvedConfig } from "./configurations"; -export const bucketEndpointMiddleware = - (options: BucketEndpointResolvedConfig): BuildMiddleware => - ( - next: BuildHandler, - context: HandlerExecutionContext - ): BuildHandler => - async (args: BuildHandlerArguments): Promise> => { - const { Bucket: bucketName } = args.input as { Bucket: string }; - let replaceBucketInPath = options.bucketEndpoint; - const request = args.request; - if (HttpRequest.isInstance(request)) { - if (options.bucketEndpoint) { - request.hostname = bucketName; - } else if (validateArn(bucketName)) { - const bucketArn = parseArn(bucketName); - const clientRegion = getPseudoRegion(await options.region()); - const { partition, signingRegion = clientRegion } = (await options.regionInfoProvider(clientRegion)) || {}; - const useArnRegion = await options.useArnRegion(); - const { - hostname, - bucketEndpoint, - signingRegion: modifiedSigningRegion, - signingService, - } = bucketHostname({ - bucketName: bucketArn, - baseHostname: request.hostname, - accelerateEndpoint: options.useAccelerateEndpoint, - dualstackEndpoint: options.useDualstackEndpoint, - pathStyleEndpoint: options.forcePathStyle, - tlsCompatible: request.protocol === "https:", - useArnRegion, - clientPartition: partition, - clientSigningRegion: signingRegion, - clientRegion: clientRegion, - isCustomEndpoint: options.isCustomEndpoint, - }); +export const bucketEndpointMiddleware = (options: BucketEndpointResolvedConfig): BuildMiddleware => < + Output extends MetadataBearer +>( + next: BuildHandler, + context: HandlerExecutionContext +): BuildHandler => async (args: BuildHandlerArguments): Promise> => { + const { Bucket: bucketName } = args.input as { Bucket: string }; + let replaceBucketInPath = options.bucketEndpoint; + const request = args.request; + if (HttpRequest.isInstance(request)) { + if (options.bucketEndpoint) { + request.hostname = bucketName; + } else if (validateArn(bucketName)) { + const bucketArn = parseArn(bucketName); + const clientRegion = getPseudoRegion(await options.region()); + const { partition, signingRegion = clientRegion } = (await options.regionInfoProvider(clientRegion)) || {}; + const useArnRegion = await options.useArnRegion(); + const { hostname, bucketEndpoint, signingRegion: modifiedSigningRegion, signingService } = bucketHostname({ + bucketName: bucketArn, + baseHostname: request.hostname, + accelerateEndpoint: options.useAccelerateEndpoint, + dualstackEndpoint: options.useDualstackEndpoint, + pathStyleEndpoint: options.forcePathStyle, + tlsCompatible: request.protocol === "https:", + useArnRegion, + clientPartition: partition, + clientSigningRegion: signingRegion, + clientRegion: clientRegion, + isCustomEndpoint: options.isCustomEndpoint, + disableMultiregionAccessPoints: await options.disableMultiregionAccessPoints(), + }); - // If the request needs to use a region or service name inferred from ARN that different from client region, we - // need to set them in the handler context so the signer will use them - if (modifiedSigningRegion && modifiedSigningRegion !== signingRegion) { - context["signing_region"] = modifiedSigningRegion; - } - if (signingService && signingService !== "s3") { - context["signing_service"] = signingService; - } + // If the request needs to use a region or service name inferred from ARN that different from client region, we + // need to set them in the handler context so the signer will use them + if (modifiedSigningRegion && modifiedSigningRegion !== signingRegion) { + context["signing_region"] = modifiedSigningRegion; + } + if (signingService && signingService !== "s3") { + context["signing_service"] = signingService; + } - request.hostname = hostname; - replaceBucketInPath = bucketEndpoint; - } else { - const clientRegion = getPseudoRegion(await options.region()); - const { hostname, bucketEndpoint } = bucketHostname({ - bucketName, - clientRegion, - baseHostname: request.hostname, - accelerateEndpoint: options.useAccelerateEndpoint, - dualstackEndpoint: options.useDualstackEndpoint, - pathStyleEndpoint: options.forcePathStyle, - tlsCompatible: request.protocol === "https:", - isCustomEndpoint: options.isCustomEndpoint, - }); + request.hostname = hostname; + replaceBucketInPath = bucketEndpoint; + } else { + const clientRegion = getPseudoRegion(await options.region()); + const { hostname, bucketEndpoint } = bucketHostname({ + bucketName, + clientRegion, + baseHostname: request.hostname, + accelerateEndpoint: options.useAccelerateEndpoint, + dualstackEndpoint: options.useDualstackEndpoint, + pathStyleEndpoint: options.forcePathStyle, + tlsCompatible: request.protocol === "https:", + isCustomEndpoint: options.isCustomEndpoint, + }); - request.hostname = hostname; - replaceBucketInPath = bucketEndpoint; - } + request.hostname = hostname; + replaceBucketInPath = bucketEndpoint; + } - if (replaceBucketInPath) { - request.path = request.path.replace(/^(\/)?[^\/]+/, ""); - if (request.path === "") { - request.path = "/"; - } + if (replaceBucketInPath) { + request.path = request.path.replace(/^(\/)?[^\/]+/, ""); + if (request.path === "") { + request.path = "/"; } } + } - return next({ ...args, request }); - }; + return next({ ...args, request }); +}; export const bucketEndpointMiddlewareOptions: RelativeMiddlewareOptions = { tags: ["BUCKET_ENDPOINT"], diff --git a/packages/middleware-bucket-endpoint/src/bucketHostname.spec.ts b/packages/middleware-bucket-endpoint/src/bucketHostname.spec.ts index 6b6fb70befa7..7349e43af692 100644 --- a/packages/middleware-bucket-endpoint/src/bucketHostname.spec.ts +++ b/packages/middleware-bucket-endpoint/src/bucketHostname.spec.ts @@ -424,10 +424,6 @@ describe("bucketHostname", () => { bucketArn: "arn:aws:s3:us-west-2:123456789012:bucket_name:mybucket", message: "ARN resource should begin with 'accesspoint:' or 'outpost:'", }, - { - bucketArn: "arn:aws:s3::123456789012:accesspoint:myendpoint", - message: "ARN region is empty", - }, { bucketArn: "arn:aws:s3:us-west-2::accesspoint:myendpoint", message: "Access point ARN accountID does not match regex '[0-9]{12}'", @@ -481,6 +477,122 @@ describe("bucketHostname", () => { }); }); + describe("from Multi-region Access Point(MRAP) ARN", () => { + ["us-east-1", "us-west-2", "aws-global"].forEach((region) => { + it(`should populate endpoint from MRAP ARN in region "${region}"`, () => { + const { bucketEndpoint, hostname, signingRegion } = bucketHostname({ + bucketName: parseArn("arn:aws:s3::123456789012:accesspoint:mfzwi23gnjvgw.mrap"), + baseHostname: `s3.${region}.amazonaws.com`, + disableMultiregionAccessPoints: false, + clientRegion: region, + isCustomEndpoint: false, + }); + expect(bucketEndpoint).toBe(true); + expect(hostname).toBe("mfzwi23gnjvgw.mrap.accesspoint.s3-global.amazonaws.com"); + expect(signingRegion).toBe("*"); + }); + }); + + it('should populate endpoint from MRAP ARN in region "cn-north-2"', () => { + const { bucketEndpoint, hostname, signingRegion } = bucketHostname({ + bucketName: parseArn("arn:aws-cn:s3::123456789012:accesspoint:mfzwi23gnjvgw.mrap"), + clientPartition: "aws-cn", + baseHostname: `s3.${region}.amazonaws.com.cn`, + disableMultiregionAccessPoints: false, + clientRegion: region, + isCustomEndpoint: false, + }); + expect(bucketEndpoint).toBe(true); + expect(hostname).toBe("mfzwi23gnjvgw.mrap.accesspoint.s3-global.amazonaws.com.cn"); + expect(signingRegion).toBe("*"); + }); + + it("should throw if MRAP ARN is supplied but disabled through options", () => { + expect(() => + bucketHostname({ + bucketName: parseArn("arn:aws:s3::123456789012:accesspoint:mfzwi23gnjvgw.mrap"), + baseHostname: `s3.us-west-2.amazonaws.com`, + disableMultiregionAccessPoints: true, + clientRegion: region, + isCustomEndpoint: false, + }) + ).toThrow("SDK is attempting to use a MRAP ARN. Please enable to feature."); + }); + + it("should throw if dualstack option is set", () => { + expect(() => + bucketHostname({ + bucketName: parseArn("arn:aws:s3::123456789012:accesspoint:mfzwi23gnjvgw.mrap"), + baseHostname: `s3.us-west-2.amazonaws.com`, + dualstackEndpoint: true, + clientRegion: region, + isCustomEndpoint: false, + }) + ).toThrow("Dualstack endpoint is not supported with Outpost or Multi-region Access Point ARN."); + }); + + it("should throw if accelerate endpoint option is set", () => { + expect(() => + bucketHostname({ + bucketName: parseArn("arn:aws:s3::123456789012:accesspoint:mfzwi23gnjvgw.mrap"), + baseHostname: `s3.us-west-2.amazonaws.com`, + accelerateEndpoint: true, + clientRegion: region, + isCustomEndpoint: false, + }) + ).toThrow("Accelerate endpoint is not supported when bucket is an ARN"); + }); + + it("should throw if region is empty and disableMultiregionAccessPoints option is set", () => { + expect(() => + bucketHostname({ + bucketName: parseArn("arn:aws:s3::123456789012:accesspoint:myendpoint"), + baseHostname: `s3.us-west-2.amazonaws.com`, + disableMultiregionAccessPoints: true, + clientRegion: region, + isCustomEndpoint: false, + }) + ).toThrow(""); + }); + + it('should populate endpoint from MRAP ARN with access point name "myendpoint"', () => { + const { bucketEndpoint, hostname } = bucketHostname({ + bucketName: parseArn("arn:aws:s3::123456789012:accesspoint:myendpoint"), + baseHostname: `s3.us-west-2.amazonaws.com`, + disableMultiregionAccessPoints: false, + clientRegion: region, + isCustomEndpoint: false, + }); + expect(bucketEndpoint).toBe(true); + expect(hostname).toBe("myendpoint.accesspoint.s3-global.amazonaws.com"); + }); + + it('should populate endpoint from MRAP ARN with access point name "my.bucket"', () => { + const { bucketEndpoint, hostname } = bucketHostname({ + bucketName: parseArn("arn:aws:s3::123456789012:accesspoint:my.bucket"), + baseHostname: `s3.us-west-2.amazonaws.com`, + disableMultiregionAccessPoints: false, + clientRegion: region, + isCustomEndpoint: false, + }); + expect(bucketEndpoint).toBe(true); + expect(hostname).toBe("my.bucket.accesspoint.s3-global.amazonaws.com"); + }); + + it("should populate endpoint from MRAP ARN with custom endpoint", () => { + const { bucketEndpoint, hostname, signingRegion } = bucketHostname({ + bucketName: parseArn("arn:aws:s3::123456789012:accesspoint:mfzwi23gnjvgw.mrap"), + baseHostname: "vpce-123-abc.vpce.s3-global.amazonaws.com", + isCustomEndpoint: true, + clientRegion: "us-west-2", + disableMultiregionAccessPoints: false, + }); + expect(bucketEndpoint).toBe(true); + expect(hostname).toBe("mfzwi23gnjvgw.mrap.vpce-123-abc.vpce.s3-global.amazonaws.com"); + expect(signingRegion).toBe("*"); + }); + }); + describe("from Outpost ARN", () => { describe("populates access point endpoint from ARN", () => { const s3Hostname = "s3.us-west-2.amazonaws.com"; diff --git a/packages/middleware-bucket-endpoint/src/bucketHostname.ts b/packages/middleware-bucket-endpoint/src/bucketHostname.ts index 58af25f36bbd..6fcbfd971741 100644 --- a/packages/middleware-bucket-endpoint/src/bucketHostname.ts +++ b/packages/middleware-bucket-endpoint/src/bucketHostname.ts @@ -1,3 +1,5 @@ +import { ARN } from "@aws-sdk/util-arn-parser"; + import { ArnHostnameParams, BucketHostnameParams, @@ -11,7 +13,9 @@ import { isFipsRegion, validateAccountId, validateArnEndpointOptions, + validateCustomEndpoint, validateDNSHostLabel, + validateMrapAlias, validateNoDualstack, validateNoFIPS, validateOutpostService, @@ -30,33 +34,54 @@ export interface BucketHostname { } export const bucketHostname = (options: BucketHostnameParams | ArnHostnameParams): BucketHostname => { - const { isCustomEndpoint, baseHostname, dualstackEndpoint, accelerateEndpoint } = options; - - if (isCustomEndpoint) { - if (dualstackEndpoint) throw new Error("Dualstack endpoint is not supported with custom endpoint"); - if (accelerateEndpoint) throw new Error("Accelerate endpoint is not supported with custom endpoint"); - } - + validateCustomEndpoint(options); return isBucketNameOptions(options) ? // Construct endpoint when bucketName is a string referring to a bucket name - getEndpointFromBucketName({ ...options, isCustomEndpoint }) + getEndpointFromBucketName(options) : // Construct endpoint when bucketName is an ARN referring to an S3 resource like Access Point - getEndpointFromArn({ ...options, isCustomEndpoint }); + getEndpointFromArn(options); +}; + +const getEndpointFromBucketName = ({ + accelerateEndpoint = false, + clientRegion: region, + baseHostname, + bucketName, + dualstackEndpoint = false, + pathStyleEndpoint = false, + tlsCompatible = true, + isCustomEndpoint = false, +}: BucketHostnameParams): BucketHostname => { + const [clientRegion, hostnameSuffix] = isCustomEndpoint ? [region, baseHostname] : getSuffix(baseHostname); + if (pathStyleEndpoint || !isDnsCompatibleBucketName(bucketName) || (tlsCompatible && DOT_PATTERN.test(bucketName))) { + return { + bucketEndpoint: false, + hostname: dualstackEndpoint ? `s3.dualstack.${clientRegion}.${hostnameSuffix}` : baseHostname, + }; + } + + if (accelerateEndpoint) { + baseHostname = `s3-accelerate${dualstackEndpoint ? ".dualstack" : ""}.${hostnameSuffix}`; + } else if (dualstackEndpoint) { + baseHostname = `s3.dualstack.${clientRegion}.${hostnameSuffix}`; + } + + return { + bucketEndpoint: true, + hostname: `${bucketName}.${baseHostname}`, + }; }; -const getEndpointFromArn = (options: ArnHostnameParams & { isCustomEndpoint: boolean }): BucketHostname => { +const getEndpointFromArn = (options: ArnHostnameParams): BucketHostname => { const { isCustomEndpoint, baseHostname, clientRegion } = options; const hostnameSuffix = isCustomEndpoint ? baseHostname : getSuffixForArnEndpoint(baseHostname)[1]; const { pathStyleEndpoint, - dualstackEndpoint = false, accelerateEndpoint = false, tlsCompatible = true, - useArnRegion, bucketName, clientPartition = "aws", - clientSigningRegion = clientRegion, } = options; validateArnEndpointOptions({ pathStyleEndpoint, accelerateEndpoint, tlsCompatible }); @@ -66,82 +91,133 @@ const getEndpointFromArn = (options: ArnHostnameParams & { isCustomEndpoint: boo validateService(service); validatePartition(partition, { clientPartition }); validateAccountId(accountId); - validateRegionalClient(clientRegion); const { accesspointName, outpostId } = getArnResources(resource); + if (service === "s3-object-lambda") { + return getEndpointFromObjectLambdaArn({ ...options, tlsCompatible, bucketName, accesspointName, hostnameSuffix }); + } + if (region === "") { + return getEndpointFromMRAPArn({ ...options, clientRegion, mrapAlias: accesspointName, hostnameSuffix }); + } + if (outpostId) { + return getEndpointFromOutpostArn({ ...options, clientRegion, outpostId, accesspointName, hostnameSuffix }); + } + return getEndpointFromAccessPointArn({ ...options, clientRegion, accesspointName, hostnameSuffix }); +}; + +const getEndpointFromObjectLambdaArn = ({ + dualstackEndpoint = false, + tlsCompatible = true, + useArnRegion, + clientRegion, + clientSigningRegion = clientRegion, + accesspointName, + bucketName, + hostnameSuffix, +}: ArnHostnameParams & { + accesspointName: string; + bucketName: ARN; + hostnameSuffix: string; +}): BucketHostname => { + const { accountId, region, service } = bucketName; + validateRegionalClient(clientRegion); + validateRegion(region, { useArnRegion, clientRegion, clientSigningRegion, allowFipsRegion: true }); + validateNoDualstack(dualstackEndpoint); const DNSHostLabel = `${accesspointName}-${accountId}`; validateDNSHostLabel(DNSHostLabel, { tlsCompatible }); const endpointRegion = useArnRegion ? region : clientRegion; const signingRegion = useArnRegion ? region : clientSigningRegion; - if (service === "s3-object-lambda") { - validateRegion(region, { useArnRegion, clientRegion, clientSigningRegion, allowFipsRegion: true }); - validateNoDualstack(dualstackEndpoint); - return { - bucketEndpoint: true, - hostname: `${DNSHostLabel}.${service}${isFipsRegion(clientRegion) ? "-fips" : ""}.${getPseudoRegion( - endpointRegion - )}.${hostnameSuffix}`, - signingRegion, - signingService: service, - }; - } else if (outpostId) { - // if this is an Outpost ARN - validateRegion(region, { useArnRegion, clientRegion, clientSigningRegion }); - validateOutpostService(service); - validateDNSHostLabel(outpostId, { tlsCompatible }); - validateNoDualstack(dualstackEndpoint); - validateNoFIPS(endpointRegion); - const hostnamePrefix = `${DNSHostLabel}.${outpostId}`; - return { - bucketEndpoint: true, - hostname: `${hostnamePrefix}${isCustomEndpoint ? "" : `.s3-outposts.${endpointRegion}`}.${hostnameSuffix}`, - signingRegion, - signingService: "s3-outposts", - }; - } - // construct endpoint from Accesspoint ARN - validateRegion(region, { useArnRegion, clientRegion, clientSigningRegion, allowFipsRegion: true }); - validateS3Service(service); - const hostnamePrefix = `${DNSHostLabel}`; + return { bucketEndpoint: true, - hostname: `${hostnamePrefix}${ - isCustomEndpoint - ? "" - : `.s3-accesspoint${isFipsRegion(clientRegion) ? "-fips" : ""}${ - dualstackEndpoint ? ".dualstack" : "" - }.${getPseudoRegion(endpointRegion)}` - }.${hostnameSuffix}`, + hostname: `${DNSHostLabel}.${service}${isFipsRegion(clientRegion) ? "-fips" : ""}.${getPseudoRegion( + endpointRegion + )}.${hostnameSuffix}`, signingRegion, + signingService: service, }; }; -const getEndpointFromBucketName = ({ - accelerateEndpoint = false, - clientRegion: region, - baseHostname, - bucketName, +const getEndpointFromMRAPArn = ({ + disableMultiregionAccessPoints, dualstackEndpoint = false, - pathStyleEndpoint = false, - tlsCompatible = true, - isCustomEndpoint = false, -}: BucketHostnameParams & { isCustomEndpoint: boolean }): BucketHostname => { - const [clientRegion, hostnameSuffix] = isCustomEndpoint ? [region, baseHostname] : getSuffix(baseHostname); - if (pathStyleEndpoint || !isDnsCompatibleBucketName(bucketName) || (tlsCompatible && DOT_PATTERN.test(bucketName))) { - return { - bucketEndpoint: false, - hostname: dualstackEndpoint ? `s3.dualstack.${clientRegion}.${hostnameSuffix}` : baseHostname, - }; + isCustomEndpoint, + mrapAlias, + hostnameSuffix, +}: ArnHostnameParams & { mrapAlias: string; hostnameSuffix: string }): BucketHostname => { + // If this is a multi-regional access point, and not explicitly opted out. + if (disableMultiregionAccessPoints === true) { + throw new Error("SDK is attempting to use a MRAP ARN. Please enable to feature."); } + validateMrapAlias(mrapAlias); + validateNoDualstack(dualstackEndpoint); + return { + bucketEndpoint: true, + hostname: `${mrapAlias}${isCustomEndpoint ? "" : `.accesspoint.s3-global`}.${hostnameSuffix}`, + signingRegion: "*", + }; +}; - if (accelerateEndpoint) { - baseHostname = `s3-accelerate${dualstackEndpoint ? ".dualstack" : ""}.${hostnameSuffix}`; - } else if (dualstackEndpoint) { - baseHostname = `s3.dualstack.${clientRegion}.${hostnameSuffix}`; - } +const getEndpointFromOutpostArn = ({ + useArnRegion, + clientRegion, + clientSigningRegion = clientRegion, + bucketName, + outpostId, + dualstackEndpoint = false, + tlsCompatible = true, + accesspointName, + isCustomEndpoint, + hostnameSuffix, +}: ArnHostnameParams & { outpostId: string; accesspointName: string; hostnameSuffix: string }): BucketHostname => { + // if this is an Outpost ARN + validateRegionalClient(clientRegion); + validateRegion(bucketName.region, { useArnRegion, clientRegion, clientSigningRegion }); + const DNSHostLabel = `${accesspointName}-${bucketName.accountId}`; + validateDNSHostLabel(DNSHostLabel, { tlsCompatible }); + const endpointRegion = useArnRegion ? bucketName.region : clientRegion; + const signingRegion = useArnRegion ? bucketName.region : clientSigningRegion; + validateOutpostService(bucketName.service); + validateDNSHostLabel(outpostId, { tlsCompatible }); + validateNoDualstack(dualstackEndpoint); + validateNoFIPS(endpointRegion); + const hostnamePrefix = `${DNSHostLabel}.${outpostId}`; + return { + bucketEndpoint: true, + hostname: `${hostnamePrefix}${isCustomEndpoint ? "" : `.s3-outposts.${endpointRegion}`}.${hostnameSuffix}`, + signingRegion, + signingService: "s3-outposts", + }; +}; +const getEndpointFromAccessPointArn = ({ + useArnRegion, + clientRegion, + clientSigningRegion = clientRegion, + bucketName, + dualstackEndpoint = false, + tlsCompatible = true, + accesspointName, + isCustomEndpoint, + hostnameSuffix, +}: ArnHostnameParams & { accesspointName: string; hostnameSuffix: string }): BucketHostname => { + // construct endpoint from Accesspoint ARN + validateRegionalClient(clientRegion); + validateRegion(bucketName.region, { useArnRegion, clientRegion, clientSigningRegion, allowFipsRegion: true }); + const hostnamePrefix = `${accesspointName}-${bucketName.accountId}`; + validateDNSHostLabel(hostnamePrefix, { tlsCompatible }); + const endpointRegion = useArnRegion ? bucketName.region : clientRegion; + const signingRegion = useArnRegion ? bucketName.region : clientSigningRegion; + validateS3Service(bucketName.service); return { bucketEndpoint: true, - hostname: `${bucketName}.${baseHostname}`, + hostname: `${hostnamePrefix}${ + isCustomEndpoint + ? "" + : `.s3-accesspoint${isFipsRegion(clientRegion) ? "-fips" : ""}${ + dualstackEndpoint ? ".dualstack" : "" + }.${getPseudoRegion(endpointRegion)}` + }.${hostnameSuffix}`, + signingRegion, }; }; diff --git a/packages/middleware-bucket-endpoint/src/bucketHostnameUtils.ts b/packages/middleware-bucket-endpoint/src/bucketHostnameUtils.ts index eaa1c934ef0d..708bca57af7c 100644 --- a/packages/middleware-bucket-endpoint/src/bucketHostnameUtils.ts +++ b/packages/middleware-bucket-endpoint/src/bucketHostnameUtils.ts @@ -28,6 +28,7 @@ export interface ArnHostnameParams extends Omit= 64 || - !/^[a-z0-9][a-z0-9.-]+[a-z0-9]$/.test(label) || + !/^[a-z0-9][a-z0-9.-]*[a-z0-9]$/.test(label) || /(\d+\.){3}\d+/.test(label) || /[.-]{2}/.test(label) || (options?.tlsCompatible && DOT_PATTERN.test(label)) @@ -193,6 +194,17 @@ export const validateDNSHostLabel = (label: string, options: { tlsCompatible?: b } }; +export const validateCustomEndpoint = (options: { + isCustomEndpoint?: boolean; + dualstackEndpoint?: boolean; + accelerateEndpoint?: boolean; +}) => { + if (options.isCustomEndpoint) { + if (options.dualstackEndpoint) throw new Error("Dualstack endpoint is not supported with custom endpoint"); + if (options.accelerateEndpoint) throw new Error("Accelerate endpoint is not supported with custom endpoint"); + } +}; + /** * Validate and parse an Access Point ARN or Outposts ARN * @internal @@ -232,14 +244,29 @@ export const getArnResources = ( * Throw if dual stack configuration is set to true. * @internal */ -export const validateNoDualstack = (dualstackEndpoint: boolean) => { - if (dualstackEndpoint) throw new Error("Dualstack endpoint is not supported with Outpost"); +export const validateNoDualstack = (dualstackEndpoint?: boolean) => { + if (dualstackEndpoint) + throw new Error("Dualstack endpoint is not supported with Outpost or Multi-region Access Point ARN."); }; /** * Validate region is not appended or prepended with a `fips-` * @internal */ -export const validateNoFIPS = (region: string) => { +export const validateNoFIPS = (region?: string) => { if (isFipsRegion(region ?? "")) throw new Error(`FIPS region is not supported with Outpost, got ${region}`); }; + +/** + * Validate the multi-region access point alias. + * @private + */ +export const validateMrapAlias = (name: string) => { + try { + name.split(".").forEach((label) => { + validateDNSHostLabel(label); + }); + } catch (e) { + throw new Error(`"${name}" is not a DNS compatible name.`); + } +}; diff --git a/packages/middleware-bucket-endpoint/src/configurations.ts b/packages/middleware-bucket-endpoint/src/configurations.ts index 96f523ac5f36..059fce339dea 100644 --- a/packages/middleware-bucket-endpoint/src/configurations.ts +++ b/packages/middleware-bucket-endpoint/src/configurations.ts @@ -15,13 +15,21 @@ export interface BucketEndpointInputConfig { */ useAccelerateEndpoint?: boolean; /** - * Enables IPv6/IPv4 dualstack endpoint. When a DNS lookup is performed on an endpoint of this type, it returns an “A” record with an IPv4 address and an “AAAA” record with an IPv6 address. In most cases the network stack in the client environment will automatically prefer the AAAA record and make a connection using the IPv6 address. Note, however, that currently on Windows, the IPv4 address will be preferred. + * Enables IPv6/IPv4 dualstack endpoint. When a DNS lookup is performed on an endpoint of this type, it returns an “A” + * record with an IPv4 address and an “AAAA” record with an IPv6 address. In most cases the network stack in the + * client environment will automatically prefer the AAAA record and make a connection using the IPv6 address. Note, + * however, that currently on Windows, the IPv4 address will be preferred. */ useDualstackEndpoint?: boolean; /** * Whether to override the request region with the region inferred from requested resource's ARN. Defaults to false */ useArnRegion?: boolean | Provider; + /** + * Whether to prevent SDK from making cross-region request when supplied bucket is a multi-region access point ARN. + * Defaults to false + */ + disableMultiregionAccessPoints?: boolean | Provider; } interface PreviouslyResolved { @@ -65,6 +73,7 @@ export interface BucketEndpointResolvedConfig { * @internal */ regionInfoProvider: RegionInfoProvider; + disableMultiregionAccessPoints: Provider; } export function resolveBucketEndpointConfig( @@ -76,6 +85,7 @@ export function resolveBucketEndpointConfig( useAccelerateEndpoint = false, useDualstackEndpoint = false, useArnRegion = false, + disableMultiregionAccessPoints = false, } = input; return { ...input, @@ -84,12 +94,19 @@ export function resolveBucketEndpointConfig( useAccelerateEndpoint, useDualstackEndpoint, useArnRegion: typeof useArnRegion === "function" ? useArnRegion : () => Promise.resolve(useArnRegion), + disableMultiregionAccessPoints: + typeof disableMultiregionAccessPoints === "function" + ? disableMultiregionAccessPoints + : () => Promise.resolve(disableMultiregionAccessPoints), }; } export const NODE_USE_ARN_REGION_ENV_NAME = "AWS_S3_USE_ARN_REGION"; export const NODE_USE_ARN_REGION_INI_NAME = "s3_use_arn_region"; +export const NODE_DISABLE_MULTIREGION_ACCESS_POINT_ENV_NAME = "AWS_S3_DISABLE_MULTIREGION_ACCESS_POINTS"; +export const NODE_DISABLE_MULTIREGION_ACCESS_POINT_INI_NAME = "s3_disable_multiregion_access_points"; + /** * Config to load useArnRegion from environment variables and shared INI files * @@ -114,3 +131,24 @@ export const NODE_USE_ARN_REGION_CONFIG_OPTIONS: LoadedConfigSelectors }, default: false, }; + +export const NODE_DISABLE_MULTIREGION_ACCESS_POINT_CONFIG_OPTIONS: LoadedConfigSelectors = { + environmentVariableSelector: (env: NodeJS.ProcessEnv) => { + if (!Object.prototype.hasOwnProperty.call(env, NODE_DISABLE_MULTIREGION_ACCESS_POINT_ENV_NAME)) return undefined; + if (env[NODE_DISABLE_MULTIREGION_ACCESS_POINT_ENV_NAME] === "true") return true; + if (env[NODE_DISABLE_MULTIREGION_ACCESS_POINT_ENV_NAME] === "false") return false; + throw new Error( + `Cannot load env ${NODE_DISABLE_MULTIREGION_ACCESS_POINT_ENV_NAME}. Expected "true" or "false", got ${env[NODE_DISABLE_MULTIREGION_ACCESS_POINT_ENV_NAME]}.` + ); + }, + configFileSelector: (profile) => { + if (!Object.prototype.hasOwnProperty.call(profile, NODE_DISABLE_MULTIREGION_ACCESS_POINT_INI_NAME)) + return undefined; + if (profile[NODE_DISABLE_MULTIREGION_ACCESS_POINT_INI_NAME] === "true") return true; + if (profile[NODE_DISABLE_MULTIREGION_ACCESS_POINT_INI_NAME] === "false") return false; + throw new Error( + `Cannot load shared config entry ${NODE_DISABLE_MULTIREGION_ACCESS_POINT_INI_NAME}. Expected "true" or "false", got ${profile[NODE_DISABLE_MULTIREGION_ACCESS_POINT_INI_NAME]}.` + ); + }, + default: false, +}; diff --git a/packages/middleware-sdk-s3/package.json b/packages/middleware-sdk-s3/package.json index e185bff3d372..82db13a0fde7 100644 --- a/packages/middleware-sdk-s3/package.json +++ b/packages/middleware-sdk-s3/package.json @@ -11,6 +11,12 @@ "main": "./dist/cjs/index.js", "module": "./dist/es/index.js", "types": "./dist/types/index.d.ts", + "browser": { + "@aws-sdk/signature-v4-crt": false + }, + "react-native": { + "@aws-sdk/signature-v4-crt": false + }, "author": { "name": "AWS SDK for JavaScript Team", "url": "https://aws.amazon.com/javascript/" @@ -18,15 +24,20 @@ "license": "Apache-2.0", "dependencies": { "@aws-sdk/protocol-http": "3.32.0", + "@aws-sdk/signature-v4": "3.32.0", "@aws-sdk/types": "3.32.0", "@aws-sdk/util-arn-parser": "3.32.0", "tslib": "^2.3.0" }, "devDependencies": { + "@aws-sdk/signature-v4-crt": "^3.31.0", "@types/jest": "^26.0.4", "jest": "^26.1.0", "typescript": "~4.3.5" }, + "peerDependencies": { + "@aws-sdk/signature-v4-crt": "^3.31.0" + }, "engines": { "node": ">= 10.0.0" }, diff --git a/packages/middleware-sdk-s3/src/S3SignatureV4.spec.ts b/packages/middleware-sdk-s3/src/S3SignatureV4.spec.ts new file mode 100644 index 000000000000..985e3219b183 --- /dev/null +++ b/packages/middleware-sdk-s3/src/S3SignatureV4.spec.ts @@ -0,0 +1,75 @@ +import { HttpRequest } from "@aws-sdk/protocol-http"; + +jest.mock("@aws-sdk/signature-v4"); + +jest.mock("@aws-sdk/signature-v4-crt"); + +import { SignatureV4 } from "@aws-sdk/signature-v4"; +import { CrtSignerV4 } from "@aws-sdk/signature-v4-crt"; + +import { S3SignatureV4, S3SignerV4Init } from "./S3SignatureV4"; + +describe("S3SignatureV4", () => { + const params: S3SignerV4Init = { + service: "s3", + region: "us-foo-1", + credentials: { + accessKeyId: "akid", + secretAccessKey: "secret", + }, + sha256: (() => {}) as any, + runtime: "node", + }; + const minimalRequest = new HttpRequest({ + hostname: "bucket.s3.us-foo-1.amazonaws.com", + path: "/key", + }); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it("should sign with SigV4 signer", async () => { + const signer = new S3SignatureV4(params); + await signer.sign(minimalRequest); + //@ts-ignore + expect(SignatureV4.mock.instances[0].sign).toBeCalledTimes(1); + }); + + it("should presign with SigV4 signer", async () => { + const signer = new S3SignatureV4(params); + await signer.presign(minimalRequest); + //@ts-ignore + expect(SignatureV4.mock.instances[0].presign).toBeCalledTimes(1); + }); + + it("should sign with SigV4a signer if mult_region option is set", async () => { + const signer = new S3SignatureV4(params); + await signer.presign(minimalRequest, { signingRegion: "*" }); + //@ts-ignore + expect(CrtSignerV4.mock.instances[0].presign).toBeCalledTimes(1); + }); + + it("should presign with SigV4 signer", async () => { + const signer = new S3SignatureV4(params); + await signer.presign(minimalRequest, { signingRegion: "*" }); + //@ts-ignore + expect(CrtSignerV4.mock.instances[0].presign).toBeCalledTimes(1); + }); + + it("should throw if sign with SigV4a in unsupported runtime", async () => { + expect.assertions(1); + const signer = new S3SignatureV4({ ...params, runtime: "browser" }); + await expect(async () => await signer.sign(minimalRequest, { signingRegion: "*" })).rejects.toThrow( + "This request requires signing with SigV4Asymmetric algorithm. It's only available in Node.js" + ); + }); + + it("should throw if preSign with SigV4a in unsupported runtime", async () => { + expect.assertions(1); + const signer = new S3SignatureV4({ ...params, runtime: "browser" }); + await expect(signer.presign(minimalRequest, { signingRegion: "*" })).rejects.toThrow( + "This request requires signing with SigV4Asymmetric algorithm. It's only available in Node.js" + ); + }); +}); diff --git a/packages/middleware-sdk-s3/src/S3SignatureV4.ts b/packages/middleware-sdk-s3/src/S3SignatureV4.ts new file mode 100644 index 000000000000..b36c206a6b88 --- /dev/null +++ b/packages/middleware-sdk-s3/src/S3SignatureV4.ts @@ -0,0 +1,70 @@ +import { SignatureV4, SignatureV4CryptoInit, SignatureV4Init } from "@aws-sdk/signature-v4"; +import type { CrtSignerV4, CrtSignerV4Init } from "@aws-sdk/signature-v4-crt"; +import { + HttpRequest, + RequestPresigner, + RequestPresigningArguments, + RequestSigner, + RequestSigningArguments, +} from "@aws-sdk/types"; + +export type S3SignerV4Init = SignatureV4Init & + SignatureV4CryptoInit & { + runtime?: string; + }; + +/** + * A SigV4-compatible signer for S3 service. In order to support SigV4a algorithm according to the operation input + * dynamically, the signer wraps native module SigV4a signer and JS SigV4 signer. It signs the request with SigV4a + * algorithm if the request needs to be signed with `*` region. Otherwise, it signs the request with normal SigV4 + * signer. + * Note that SigV4a signer is only supported in Node.js now because it depends on a native dependency. + * @private + */ +export class S3SignatureV4 implements RequestPresigner, RequestSigner { + private readonly sigv4Signer: SignatureV4; + private sigv4aSigner?: CrtSignerV4; + private readonly signerOptions: S3SignerV4Init; + + constructor(options: S3SignerV4Init) { + this.sigv4Signer = new SignatureV4(options); + this.signerOptions = options; + } + + public async sign(requestToSign: HttpRequest, options: RequestSigningArguments = {}): Promise { + if (options.signingRegion === "*") { + if (this.signerOptions.runtime !== "node") + throw new Error("This request requires signing with SigV4Asymmetric algorithm. It's only available in Node.js"); + return (await this.getSigv4aSigner()).sign(requestToSign, options); + } + return this.sigv4Signer.sign(requestToSign, options); + } + + public async presign(originalRequest: HttpRequest, options: RequestPresigningArguments = {}): Promise { + if (options.signingRegion === "*") { + if (this.signerOptions.runtime !== "node") + throw new Error("This request requires signing with SigV4Asymmetric algorithm. It's only available in Node.js"); + return (await this.getSigv4aSigner()).presign(originalRequest, options); + } + return this.sigv4Signer.presign(originalRequest, options); + } + + private async getSigv4aSigner(): Promise { + if (!this.sigv4aSigner) { + let CrtSignerV4: new (options: CrtSignerV4Init & SignatureV4CryptoInit) => CrtSignerV4; + try { + CrtSignerV4 = (await import("@aws-sdk/signature-v4-crt")).CrtSignerV4; + } catch (e) { + e.message = + `${e.message}\nPlease check if you have installed "@aws-sdk/signature-v4-crt" package explicitly. \n` + + "For more information please go to https://github.com/aws/aws-sdk-js-v3#known-issues"; + throw e; + } + this.sigv4aSigner = new CrtSignerV4({ + ...this.signerOptions, + signingAlgorithm: 1, + }); + } + return this.sigv4aSigner; + } +} diff --git a/packages/middleware-sdk-s3/src/index.ts b/packages/middleware-sdk-s3/src/index.ts index c8479917f61d..86c89fc0ddcf 100644 --- a/packages/middleware-sdk-s3/src/index.ts +++ b/packages/middleware-sdk-s3/src/index.ts @@ -1,3 +1,4 @@ export * from "./validate-bucket-name"; export * from "./use-regional-endpoint"; export * from "./throw-200-exceptions"; +export * from "./S3SignatureV4"; diff --git a/packages/middleware-signing/src/configurations.ts b/packages/middleware-signing/src/configurations.ts index 0af184488ddc..ae99d2e91802 100644 --- a/packages/middleware-signing/src/configurations.ts +++ b/packages/middleware-signing/src/configurations.ts @@ -1,5 +1,5 @@ import { memoize } from "@aws-sdk/property-provider"; -import { SignatureV4 } from "@aws-sdk/signature-v4"; +import { SignatureV4, SignatureV4CryptoInit, SignatureV4Init } from "@aws-sdk/signature-v4"; import { Credentials, HashConstructor, Provider, RegionInfo, RegionInfoProvider, RequestSigner } from "@aws-sdk/types"; // 5 minutes buffer time the refresh the credential before it really expires @@ -35,6 +35,13 @@ export interface AwsAuthInputConfig { * can be different to the region in the endpoint. */ signingRegion?: string; + + /** + * The injectable SigV4-compatible signer class constructor. If not supplied, + * regular SignatureV4 constructor will be used. + * @private + */ + signerConstructor?: new (options: SignatureV4Init & SignatureV4CryptoInit) => RequestSigner; } export interface SigV4AuthInputConfig { @@ -121,13 +128,16 @@ export const resolveAwsAuthConfig = ( //user supplied signingName -> endpoints.json inferred (credential scope -> model arnNamespace) -> model service id input.signingName = input.signingName || signingService || input.serviceId; - return new SignatureV4({ + const params: SignatureV4Init & SignatureV4CryptoInit = { + ...input, credentials: normalizedCreds, region: input.signingRegion, service: input.signingName, sha256, uriEscapePath: signingEscapePath, - }); + }; + const signerConstructor = input.signerConstructor || SignatureV4; + return new signerConstructor(params); }); } diff --git a/packages/s3-request-presigner/package.json b/packages/s3-request-presigner/package.json index f356b1dc1137..3d5bbce09d87 100644 --- a/packages/s3-request-presigner/package.json +++ b/packages/s3-request-presigner/package.json @@ -17,6 +17,7 @@ }, "license": "Apache-2.0", "dependencies": { + "@aws-sdk/middleware-sdk-s3": "3.32.0", "@aws-sdk/protocol-http": "3.32.0", "@aws-sdk/signature-v4": "3.32.0", "@aws-sdk/smithy-client": "3.32.0", diff --git a/packages/s3-request-presigner/src/getSignedUrl.spec.ts b/packages/s3-request-presigner/src/getSignedUrl.spec.ts index bb940ffccb28..d9e83426f3fb 100644 --- a/packages/s3-request-presigner/src/getSignedUrl.spec.ts +++ b/packages/s3-request-presigner/src/getSignedUrl.spec.ts @@ -4,8 +4,10 @@ const mockV4 = jest.fn().mockReturnValue({ presign: mockV4Presign, sign: mockV4Sign, }); -jest.mock("@aws-sdk/signature-v4", () => ({ - SignatureV4: mockV4, +jest.mock("@aws-sdk/middleware-sdk-s3", () => ({ + //@ts-ignore + ...jest.requireActual("@aws-sdk/middleware-sdk-s3"), + S3SignatureV4: mockV4, })); import { GetObjectCommand, S3Client } from "@aws-sdk/client-s3"; @@ -132,4 +134,32 @@ describe("getSignedUrl", () => { expect(mockPresign.mock.calls[0][0].headers[header]).toBeUndefined(); } ); + + it("should presign request with MRAP ARN", async () => { + const mockPresigned = "a presigned url"; + mockPresign.mockReturnValue(mockPresigned); + const client = new S3Client(clientParams); + const command = new GetObjectCommand({ + Bucket: "arn:aws:s3::123456789012:accesspoint:mfzwi23gnjvgw.mrap", + Key: "Key", + }); + await getSignedUrl(client, command); + expect(mockPresign).toBeCalled(); + expect(mockPresign.mock.calls[0][0]).toMatchObject({ + hostname: "mfzwi23gnjvgw.mrap.accesspoint.s3-global.amazonaws.com", + }); + }); + + it("should throw if presign request with MRAP ARN and disableMultiregionAccessPoints option", () => { + const mockPresigned = "a presigned url"; + mockPresign.mockReturnValue(mockPresigned); + const client = new S3Client({ ...clientParams, disableMultiregionAccessPoints: true }); + const command = new GetObjectCommand({ + Bucket: "arn:aws:s3::123456789012:accesspoint:mfzwi23gnjvgw.mrap", + Key: "Key", + }); + return expect(getSignedUrl(client, command)).rejects.toMatchObject({ + message: "SDK is attempting to use a MRAP ARN. Please enable to feature.", + }); + }); }); diff --git a/packages/s3-request-presigner/src/presigner.ts b/packages/s3-request-presigner/src/presigner.ts index a3197cca3faa..32da9261325e 100644 --- a/packages/s3-request-presigner/src/presigner.ts +++ b/packages/s3-request-presigner/src/presigner.ts @@ -1,32 +1,27 @@ -import { SignatureV4, SignatureV4CryptoInit, SignatureV4Init } from "@aws-sdk/signature-v4"; +import { S3SignatureV4, S3SignerV4Init } from "@aws-sdk/middleware-sdk-s3"; import { RequestPresigner, RequestPresigningArguments } from "@aws-sdk/types"; import { HttpRequest as IHttpRequest } from "@aws-sdk/types"; import { SHA256_HEADER, UNSIGNED_PAYLOAD } from "./constants"; -/** - * PartialBy makes properties specified in K optional in interface T - * see: https://stackoverflow.com/questions/43159887/make-a-single-property-optional-in-typescript - * */ -type Omit = Pick>; type PartialBy = Omit & Partial>; -export type S3RequestPresignerOptions = PartialBy< - SignatureV4Init & SignatureV4CryptoInit, - "service" | "uriEscapePath" -> & { signingName?: string }; +export type S3RequestPresignerOptions = PartialBy & { + signingName?: string; +}; export class S3RequestPresigner implements RequestPresigner { - private readonly signer: SignatureV4; + private readonly signer: S3SignatureV4; constructor(options: S3RequestPresignerOptions) { const resolvedOptions = { // Allow `signingName` because we want to support usecase of supply client's resolved config // directly. Where service equals signingName. service: options.signingName || options.service || "s3", uriEscapePath: options.uriEscapePath || false, + applyChecksum: options.applyChecksum || false, ...options, }; - this.signer = new SignatureV4(resolvedOptions); + this.signer = new S3SignatureV4(resolvedOptions); } public async presign( diff --git a/packages/signature-v4-crt/CHANGELOG.md b/packages/signature-v4-crt/CHANGELOG.md new file mode 100644 index 000000000000..76dafea1058a --- /dev/null +++ b/packages/signature-v4-crt/CHANGELOG.md @@ -0,0 +1,11 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# [3.29.0](https://github.com/aws/aws-sdk-js-v3/compare/v3.28.0...v3.29.0) (2021-09-02) + + +### Features + +* **s3:** support generating endpoints from multi-region access point ([#2742](https://github.com/aws/aws-sdk-js-v3/issues/2742)) ([49da47b](https://github.com/aws/aws-sdk-js-v3/commit/49da47b4dfde0f2c68052409aaf808eddcf4e157)) diff --git a/packages/signature-v4-crt/LICENSE b/packages/signature-v4-crt/LICENSE new file mode 100644 index 000000000000..7b6491ba7876 --- /dev/null +++ b/packages/signature-v4-crt/LICENSE @@ -0,0 +1,201 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/packages/signature-v4-crt/README.md b/packages/signature-v4-crt/README.md new file mode 100644 index 000000000000..321870679a4b --- /dev/null +++ b/packages/signature-v4-crt/README.md @@ -0,0 +1,4 @@ +# @aws-sdk/signature-v4 + +[![NPM version](https://img.shields.io/npm/v/@aws-sdk/signature-v4-crt/latest.svg)](https://www.npmjs.com/package/@aws-sdk/signature-v4-crt) +[![NPM downloads](https://img.shields.io/npm/dm/@aws-sdk/signature-v4-crt.svg)](https://www.npmjs.com/package/@aws-sdk/signature-v4-crt) diff --git a/packages/signature-v4-crt/jest.config.js b/packages/signature-v4-crt/jest.config.js new file mode 100644 index 000000000000..64f3d932819c --- /dev/null +++ b/packages/signature-v4-crt/jest.config.js @@ -0,0 +1,7 @@ +const base = require("../../jest.config.base.js"); + +module.exports = { + ...base, + //only test cjs dist, avoid testing the package twice + testPathIgnorePatterns: ["/node_modules/", "/es/"], +}; diff --git a/packages/signature-v4-crt/package.json b/packages/signature-v4-crt/package.json new file mode 100644 index 000000000000..abec3f4c0c8e --- /dev/null +++ b/packages/signature-v4-crt/package.json @@ -0,0 +1,47 @@ +{ + "name": "@aws-sdk/signature-v4-crt", + "version": "3.31.0", + "description": "A revision of AWS Signature V4 request signer based on AWS Common Runtime https://github.com/awslabs/aws-crt-nodejs", + "main": "./dist/cjs/index.js", + "module": "./dist/es/index.js", + "types": "./dist/types/index.d.ts", + "scripts": { + "build:cjs": "tsc -p tsconfig.cjs.json", + "build:es": "tsc -p tsconfig.es.json", + "build": "yarn build:es && yarn build:cjs", + "downlevel-dts": "downlevel-dts dist/types dist/types/ts3.4", + "test": "jest --coverage" + }, + "author": { + "name": "AWS SDK for JavaScript Team", + "url": "https://aws.amazon.com/javascript/" + }, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/is-array-buffer": "3.32.0", + "@aws-sdk/querystring-parser": "3.32.0", + "@aws-sdk/signature-v4": "3.32.0", + "@aws-sdk/util-hex-encoding": "3.32.0", + "@aws-sdk/util-uri-escape": "3.32.0", + "aws-crt": "^1.9.7", + "tslib": "^2.3.0" + }, + "devDependencies": { + "@aws-crypto/sha256-js": "^1.0.0", + "@aws-sdk/protocol-http": "3.32.0", + "@aws-sdk/types": "3.32.0", + "@aws-sdk/util-buffer-from": "3.32.0", + "@types/jest": "^26.0.4", + "jest": "^26.1.0", + "typescript": "~4.3.5" + }, + "engines": { + "node": ">= 10.0.0" + }, + "homepage": "https://github.com/aws/aws-sdk-js-v3/tree/master/packages/signature-v4-crt", + "repository": { + "type": "git", + "url": "https://github.com/aws/aws-sdk-js-v3.git", + "directory": "packages/signature-v4-crt" + } +} diff --git a/packages/signature-v4-crt/src/CrtSignerV4.spec.ts b/packages/signature-v4-crt/src/CrtSignerV4.spec.ts new file mode 100644 index 000000000000..31ba57fbf136 --- /dev/null +++ b/packages/signature-v4-crt/src/CrtSignerV4.spec.ts @@ -0,0 +1,142 @@ +import { Sha256 } from "@aws-crypto/sha256-js"; +import { auth as crtAuth } from "aws-crt"; + +import { + ALGORITHM_IDENTIFIER_V4A, + ALGORITHM_QUERY_PARAM, + AMZ_DATE_QUERY_PARAM, + CREDENTIAL_QUERY_PARAM, + EXPIRES_QUERY_PARAM, + REGION_SET_PARAM, + SIGNATURE_QUERY_PARAM, + SIGNED_HEADERS_QUERY_PARAM, +} from "./constants"; +import { CrtSignerV4 } from "./CrtSignerV4"; +export const region = "us-east-1"; +export const service = "service"; +export const suiteCredentials = { + accessKeyId: "AKIDEXAMPLE", + secretAccessKey: "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY", +}; + +export const signingDate = new Date("2015-08-30T12:36:00Z"); + +const AUTH_HEADER = "Authorization"; + +describe("SignatureV4A", () => { + /* SigV4A will have different signature every time. We cannot hard code the signature to test against. */ + const signerV4A = new CrtSignerV4({ + signingAlgorithm: crtAuth.AwsSigningAlgorithm.SigV4Asymmetric, + credentials: suiteCredentials, + region, + service, + sha256: Sha256, + applyChecksum: false, + }); + + const ECC_KEY_PUB = { + X: "b6618f6a65740a99e650b33b6b4b5bd0d43b176d721a3edfea7e7d2d56d936b1", + Y: "865ed22a7eadc9c5cb9d2cbaca1b3699139fedc5043dc6661864218330c8e518", + }; + + const SIGV4ATEST_EXPECTED_CANONICAL_REQUEST: string = + "GET" + + "\n" + + "/" + + "\n" + + "\n" + + "host:example.amazonaws.com\n" + + "my-header1:value2,value2,value1" + + "\n" + + "x-amz-date:20150830T123600Z" + + "\n" + + "x-amz-region-set:us-east-1" + + "\n" + + "\n" + + "host;my-header1;x-amz-date;x-amz-region-set" + + "\n" + + "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"; + + const SIGV4ATEST_EXPECTED_CANONICAL_PRESIGNED_REQUEST: string = + "GET" + + "\n" + + "/" + + "\n" + + "X-Amz-Algorithm=AWS4-ECDSA-P256-SHA256&X-Amz-Credential=AKIDEXAMPLE%2F20150830%2Fservice%2Faws4_request&X-Amz-Date=20150830T123600Z&X-Amz-Expires=3600&X-Amz-Region-Set=us-east-1&X-Amz-SignedHeaders=host%3Bmy-header1" + + "\n" + + "host:example.amazonaws.com\n" + + "my-header1:value2,value2,value1" + + "\n" + + "\n" + + "host;my-header1" + + "\n" + + "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"; + + /* from a complete authorization string to get the signature for verification */ + function getSignature(authorizationString: string): string { + const separator = "Signature="; + const splits = authorizationString.split(separator); + return splits[splits.length - 1]; + } + + const V4aRequest = { + protocol: "https:", + method: "GET", + hostname: "example.amazonaws.com", + query: {}, + headers: { + host: "example.amazonaws.com", + "my-header1": "value2,value2,value1", + "x-amz-date": "20150830T123600Z", + }, + path: "/", + }; + + describe("#presignRequest", () => { + const presigningOptions = { + expiresIn: 3600, + signingDate, + }; + + it("should sign requests without bodies", async () => { + const { query } = await signerV4A.presign(V4aRequest, presigningOptions); + expect(query![ALGORITHM_QUERY_PARAM]).toEqual(ALGORITHM_IDENTIFIER_V4A); + expect(query![CREDENTIAL_QUERY_PARAM]).toEqual("AKIDEXAMPLE/20150830/service/aws4_request"); + expect(query![AMZ_DATE_QUERY_PARAM]).toEqual("20150830T123600Z"); + expect(query![EXPIRES_QUERY_PARAM]).toEqual(presigningOptions.expiresIn.toString()); + expect(query![REGION_SET_PARAM]).toEqual(region); + expect(query![SIGNED_HEADERS_QUERY_PARAM]).toEqual("host;my-header1"); + const result = await signerV4A.verifySigv4aPreSigning( + V4aRequest, + query![SIGNATURE_QUERY_PARAM], + SIGV4ATEST_EXPECTED_CANONICAL_PRESIGNED_REQUEST, + ECC_KEY_PUB.X, + ECC_KEY_PUB.Y, + presigningOptions + ); + expect(result).toBe(true); + }); + }); + + describe("#sign (request)", () => { + it("should sign requests without bodies", async () => { + const option = { + signingDate, + }; + const { headers } = await signerV4A.sign(V4aRequest, option); + expect(headers[AUTH_HEADER]).toMatch( + /^AWS4-ECDSA-P256-SHA256 Credential=AKIDEXAMPLE\/20150830\/service\/aws4_request, SignedHeaders=host;my-header1;x-amz-date;x-amz-region-set, Signature=/ + ); + const signature = getSignature(headers[AUTH_HEADER]); + const result = await signerV4A.verifySigv4aSigning( + V4aRequest, + signature, + SIGV4ATEST_EXPECTED_CANONICAL_REQUEST, + ECC_KEY_PUB.X, + ECC_KEY_PUB.Y, + option + ); + expect(result).toBe(true); + }); + }); +}); diff --git a/packages/signature-v4-crt/src/CrtSignerV4.ts b/packages/signature-v4-crt/src/CrtSignerV4.ts new file mode 100644 index 000000000000..02fc8ac6c675 --- /dev/null +++ b/packages/signature-v4-crt/src/CrtSignerV4.ts @@ -0,0 +1,279 @@ +import { parseQueryString } from "@aws-sdk/querystring-parser"; +import { + getCanonicalQuery, + getPayloadHash, + moveHeadersToQuery, + normalizeCredentialsProvider, + normalizeRegionProvider, + prepareRequest, + SignatureV4CryptoInit, + SignatureV4Init, +} from "@aws-sdk/signature-v4"; +import { + Credentials, + HttpRequest, + Provider, + QueryParameterBag, + RequestPresigner, + RequestPresigningArguments, + RequestSigner, + RequestSigningArguments, +} from "@aws-sdk/types"; +import { auth as crtAuth, http as crtHttp, io as crtIO } from "aws-crt"; + +import { MAX_PRESIGNED_TTL, SHA256_HEADER } from "./constants"; +import { deleteHeader } from "./headerUtil"; + +export type AwsSigningAlgorithm = crtAuth.AwsSigningAlgorithm; + +/* private function to convert sdk Http request to crt Http request */ +function sdkHttpRequest2crtHttpRequest(sdkRequest: HttpRequest): crtHttp.HttpRequest { + /* Remove the x-amz-content-sha256 header, if exists */ + deleteHeader(SHA256_HEADER, sdkRequest.headers); + const headersArray = Object.entries(sdkRequest.headers); + const crtHttpHeaders = new crtHttp.HttpHeaders(headersArray); + const queryString = getCanonicalQuery(sdkRequest); + + /** + * Not converting the body to the crtRequest. For now, it's better to get the payload Hash from SDK. + * The body value will be set from config. + */ + return new crtHttp.HttpRequest(sdkRequest.method, sdkRequest.path + "?" + queryString, crtHttpHeaders); +} + +export interface CrtSignerV4Init extends SignatureV4Init { + /** + * The Algorithm used for the signer. Includes: SigV4, SigV4Asymmetric. + * + * @default [SigV4] + */ + signingAlgorithm?: AwsSigningAlgorithm; +} + +/** + * Based aws-crt, with the same API as signing the request from SignatureV4, compatible with request Signer from SDK. + * The difference between them is CrtSignerV4 only supports signing/presigning the request. The behavior of two signers + * are slightly different, includes the case of headers name after signing and the CrtSignerV4 does NOT support overwrite + * the internal check against (x-amzn-trace-id, user-agent), which will always be skipped. + * Most importantly, CrtSignerV4 supports Signature V4 Asymmetric. + * + * Note: aws-crt that supports SigV4A is still a private repo https://github.com/awslabs/aws-crt-nodejs-staging/tree/sigv4a-binding + */ +export class CrtSignerV4 implements RequestPresigner, RequestSigner { + private readonly service: string; + private readonly regionProvider: Provider; + private readonly credentialProvider: Provider; + private readonly sha256: any; + private readonly uriEscapePath: boolean; + private readonly applyChecksum: boolean; + private readonly signingAlgorithm: AwsSigningAlgorithm; + + constructor({ + credentials, + region, + service, + sha256, + applyChecksum = true, + uriEscapePath = true, + signingAlgorithm = crtAuth.AwsSigningAlgorithm.SigV4, + }: CrtSignerV4Init & SignatureV4CryptoInit) { + this.service = service; + this.sha256 = sha256; + this.uriEscapePath = uriEscapePath; + this.signingAlgorithm = signingAlgorithm; + this.applyChecksum = applyChecksum; + this.regionProvider = normalizeRegionProvider(region); + this.credentialProvider = normalizeCredentialsProvider(credentials); + crtIO.enable_logging(crtIO.LogLevel.ERROR); + } + + private async options2crtConfigure( + { + signingDate = new Date(), + signableHeaders, + unsignableHeaders, + signingRegion, + signingService, + }: RequestSigningArguments | RequestPresigningArguments | undefined = {}, + viaHeader: Boolean, + payloadHash: string, + expiresIn?: number + ): Promise { + const credentials = await this.credentialProvider(); + const region = signingRegion ?? (await this.regionProvider()); + const service = signingService ?? this.service; + if (signableHeaders?.has("x-amzn-trace-id") || signableHeaders?.has("user-agent")) { + throw new Error("internal check (x-amzn-trace-id, user-agent) is not supported to be included to sign with CRT."); + } + const headersUnsignable = getHeadersUnsignable(unsignableHeaders, signableHeaders); + return { + algorithm: this.signingAlgorithm, + signature_type: viaHeader + ? crtAuth.AwsSignatureType.HttpRequestViaHeaders + : crtAuth.AwsSignatureType.HttpRequestViaQueryParams, + provider: sdk2crtCredentialsProvider(credentials), + region: region, + service: service, + date: new Date(signingDate), + header_blacklist: headersUnsignable, + use_double_uri_encode: this.uriEscapePath, + /* Always set the body value by the result from SDK */ + signed_body_value: payloadHash, + signed_body_header: + this.applyChecksum && viaHeader + ? crtAuth.AwsSignedBodyHeaderType.XAmzContentSha256 + : crtAuth.AwsSignedBodyHeaderType.None, + expiration_in_seconds: expiresIn, + }; + } + + public async presign(originalRequest: HttpRequest, options: RequestPresigningArguments = {}): Promise { + if (options.expiresIn && options.expiresIn > MAX_PRESIGNED_TTL) { + return Promise.reject( + "Signature version 4 presigned URLs" + " must have an expiration date less than one week in" + " the future" + ); + } + const request = moveHeadersToQuery(prepareRequest(originalRequest)); + + const crtSignedRequest = await this.signRequest( + request, + await this.options2crtConfigure( + options, + false /* viaHeader */, + await getPayloadHash(originalRequest, this.sha256), + options.expiresIn ? options.expiresIn : 3600 + ) + ); + request.query = this.getQueryParam(crtSignedRequest.path); + return request; + } + + public async sign(toSign: HttpRequest, options?: RequestSigningArguments): Promise { + const request = prepareRequest(toSign); + const crtSignedRequest = await this.signRequest( + request, + await this.options2crtConfigure(options, true /* viaHeader */, await getPayloadHash(toSign, this.sha256)) + ); + request.headers = crtSignedRequest.headers._flatten().reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}); + return request; + } + + /* Get the query parameters from crtPath */ + private getQueryParam(crtPath: string): QueryParameterBag { + const start = crtPath.search(/\?/); + const startHash = crtPath.search(/\#/); + const end = startHash == -1 ? undefined : startHash; + const queryParam = {} as QueryParameterBag; + if (start == -1) { + return queryParam; + } + const queryString = crtPath.slice(start + 1, end); + return parseQueryString(queryString); + } + + private async signRequest( + requestToSign: HttpRequest, + crtConfig: crtAuth.AwsSigningConfig + ): Promise { + const request = sdkHttpRequest2crtHttpRequest(requestToSign); + // if (requestToSign.headers[TOKEN_HEADER]) + try { + return await crtAuth.aws_sign_request(request, crtConfig); + } catch (error) { + throw new Error(error); + } + } + + /** + * Test-only API used for cross-library signing verification tests. Verify sign. + * + * Verifies: + * (1) The canonical request generated during sigv4a signing of the request matches what is passed in + * (2) The signature passed in is a valid ECDSA signature of the hashed string-to-sign derived from the + * canonical request + * + * @param request The original request used for signing + * @param signature the actual signature computed from a previous signing of the signable + * @param expectedCanonicalRequest expected result when building the canonical request + * @param eccPubKeyX the x coordinate of the public part of the ecc key to verify the signature + * @param eccPubKeyY the y coordinate of the public part of the ecc key to verify the signature + * @param options the RequestSigningArguments used for signing + * + * @return True, if the verification succeed. Otherwise, false. + */ + public async verifySigv4aSigning( + request: HttpRequest, + signature: string, + expectedCanonicalRequest: string, + eccPubKeyX: string, + eccPubKeyY: string, + options: RequestSigningArguments = {} + ): Promise { + const sdkRequest = prepareRequest(request); + const crtRequest = sdkHttpRequest2crtHttpRequest(sdkRequest); + const payloadHash = await getPayloadHash(request, this.sha256); + const crtConfig = await this.options2crtConfigure(options, true /* viaHeader */, payloadHash); + return crtAuth.aws_verify_sigv4a_signing( + crtRequest, + crtConfig, + expectedCanonicalRequest, + signature, + eccPubKeyX, + eccPubKeyY + ); + } + + /* Verify presign */ + public async verifySigv4aPreSigning( + request: HttpRequest, + signature: string | Array | null, + expectedCanonicalRequest: string, + eccPubKeyX: string, + eccPubKeyY: string, + options: RequestPresigningArguments = {} + ): Promise { + if (typeof signature != "string") { + return false; + } + const sdkRequest = prepareRequest(request); + const crtRequest = sdkHttpRequest2crtHttpRequest(sdkRequest); + const crtConfig = await this.options2crtConfigure( + options, + false /* viaHeader */, + await getPayloadHash(request, this.sha256), + options.expiresIn ? options.expiresIn : 3600 + ); + return crtAuth.aws_verify_sigv4a_signing( + crtRequest, + crtConfig, + expectedCanonicalRequest, + signature, + eccPubKeyX, + eccPubKeyY + ); + } +} + +function sdk2crtCredentialsProvider(credentials: Credentials): crtAuth.AwsCredentialsProvider { + return crtAuth.AwsCredentialsProvider.newStatic( + credentials.accessKeyId, + credentials.secretAccessKey, + credentials.sessionToken + ); +} + +function getHeadersUnsignable(unsignableHeaders?: Set, signableHeaders?: Set): string[] { + if (!unsignableHeaders) { + return []; + } + if (!signableHeaders) { + return [...unsignableHeaders]; + } + const result = new Set([...unsignableHeaders]); + for (let it = signableHeaders.values(), val = null; (val = it.next().value); ) { + if (result.has(val)) { + result.delete(val); + } + } + return [...result]; +} diff --git a/packages/signature-v4-crt/src/constants.ts b/packages/signature-v4-crt/src/constants.ts new file mode 100644 index 000000000000..e66b35d6367f --- /dev/null +++ b/packages/signature-v4-crt/src/constants.ts @@ -0,0 +1,53 @@ +export const ALGORITHM_QUERY_PARAM = "X-Amz-Algorithm"; +export const CREDENTIAL_QUERY_PARAM = "X-Amz-Credential"; +export const AMZ_DATE_QUERY_PARAM = "X-Amz-Date"; +export const SIGNED_HEADERS_QUERY_PARAM = "X-Amz-SignedHeaders"; +export const EXPIRES_QUERY_PARAM = "X-Amz-Expires"; +export const SIGNATURE_QUERY_PARAM = "X-Amz-Signature"; +export const TOKEN_QUERY_PARAM = "X-Amz-Security-Token"; +export const REGION_SET_PARAM = "X-Amz-Region-Set"; + +export const AUTH_HEADER = "authorization"; +export const AMZ_DATE_HEADER = AMZ_DATE_QUERY_PARAM.toLowerCase(); +export const DATE_HEADER = "date"; +export const GENERATED_HEADERS = [AUTH_HEADER, AMZ_DATE_HEADER, DATE_HEADER]; +export const SIGNATURE_HEADER = SIGNATURE_QUERY_PARAM.toLowerCase(); +export const SHA256_HEADER = "x-amz-content-sha256"; +export const TOKEN_HEADER = TOKEN_QUERY_PARAM.toLowerCase(); +export const HOST_HEADER = "host"; + +export const ALWAYS_UNSIGNABLE_HEADERS = { + authorization: true, + "cache-control": true, + connection: true, + expect: true, + from: true, + "keep-alive": true, + "max-forwards": true, + pragma: true, + referer: true, + te: true, + trailer: true, + "transfer-encoding": true, + upgrade: true, + "user-agent": true, + "x-amzn-trace-id": true, +}; + +export const PROXY_HEADER_PATTERN = /^proxy-/; + +export const SEC_HEADER_PATTERN = /^sec-/; + +export const UNSIGNABLE_PATTERNS = [/^proxy-/i, /^sec-/i]; + +export const ALGORITHM_IDENTIFIER = "AWS4-HMAC-SHA256"; +export const ALGORITHM_IDENTIFIER_V4A = "AWS4-ECDSA-P256-SHA256"; + +export const EVENT_ALGORITHM_IDENTIFIER = "AWS4-HMAC-SHA256-PAYLOAD"; + +export const UNSIGNED_PAYLOAD = "UNSIGNED-PAYLOAD"; + +export const MAX_CACHE_SIZE = 50; +export const KEY_TYPE_IDENTIFIER = "aws4_request"; + +export const MAX_PRESIGNED_TTL = 60 * 60 * 24 * 7; diff --git a/packages/signature-v4-crt/src/crtSuite.spec.ts b/packages/signature-v4-crt/src/crtSuite.spec.ts new file mode 100644 index 000000000000..edf94183e2a7 --- /dev/null +++ b/packages/signature-v4-crt/src/crtSuite.spec.ts @@ -0,0 +1,30 @@ +import { Sha256 } from "@aws-crypto/sha256-js"; +import { HttpRequest } from "@aws-sdk/protocol-http"; + +import { CrtSignerV4 } from "./CrtSignerV4"; +import { getHeaderValue } from "./headerUtil"; +import { credentials, region, requests, service, signingDate } from "./suite.fixture"; + +/** + * Executes the official AWS Signature Version 4 test suite. + * + * @link http://docs.aws.amazon.com/general/latest/gr/signature-v4-test-suite.html + */ +describe("AWS Signature Version 4 Test Suite against CrtSignerV4", () => { + const signer = new CrtSignerV4({ + credentials, + region, + service, + sha256: Sha256, + applyChecksum: false, + }); + + for (const { name, request, authorization } of requests) { + it(`should calculate the correct signature for ${name}`, async () => { + const signed = await signer.sign(new HttpRequest(request), { + signingDate, + }); + expect(getHeaderValue("authorization", signed.headers)).toBe(authorization); + }); + } +}); diff --git a/packages/signature-v4-crt/src/headerUtil.ts b/packages/signature-v4-crt/src/headerUtil.ts new file mode 100644 index 000000000000..001f2ddbf44c --- /dev/null +++ b/packages/signature-v4-crt/src/headerUtil.ts @@ -0,0 +1,34 @@ +import { HeaderBag } from "@aws-sdk/types"; + +export function hasHeader(soughtHeader: string, headers: HeaderBag): boolean { + soughtHeader = soughtHeader.toLowerCase(); + for (const headerName of Object.keys(headers)) { + if (soughtHeader === headerName.toLowerCase()) { + return true; + } + } + + return false; +} + +/* Get the value of one request header, ignore the case. Return string if header is in the headers, else return undefined */ +export function getHeaderValue(soughtHeader: string, headers: HeaderBag): string | undefined { + soughtHeader = soughtHeader.toLowerCase(); + for (const headerName of Object.keys(headers)) { + if (soughtHeader === headerName.toLowerCase()) { + return headers[headerName]; + } + } + + return undefined; +} + +/* Delete the one request header, ignore the case. Do nothing if it's not there */ +export function deleteHeader(soughtHeader: string, headers: HeaderBag) { + soughtHeader = soughtHeader.toLowerCase(); + for (const headerName of Object.keys(headers)) { + if (soughtHeader === headerName.toLowerCase()) { + delete headers[headerName]; + } + } +} diff --git a/packages/signature-v4-crt/src/index.ts b/packages/signature-v4-crt/src/index.ts new file mode 100644 index 000000000000..5d68f8571d2d --- /dev/null +++ b/packages/signature-v4-crt/src/index.ts @@ -0,0 +1 @@ +export * from "./CrtSignerV4"; diff --git a/packages/signature-v4-crt/src/suite.fixture.ts b/packages/signature-v4-crt/src/suite.fixture.ts new file mode 100644 index 000000000000..a1cf7ddf3bc6 --- /dev/null +++ b/packages/signature-v4-crt/src/suite.fixture.ts @@ -0,0 +1,437 @@ +import { HttpRequest } from "@aws-sdk/types"; + +export interface TestCase { + name: string; + request: HttpRequest; + authorization: string; +} + +export const region = "us-east-1"; +export const service = "service"; +export const credentials = { + accessKeyId: "AKIDEXAMPLE", + secretAccessKey: "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY", +}; + +export const signingDate = new Date("2015-08-30T12:36:00Z"); + +export const requests: Array = [ + { + name: "get-header-key-duplicate", + request: { + protocol: "https:", + method: "GET", + hostname: "example.amazonaws.com", + query: {}, + headers: { + host: "example.amazonaws.com", + "my-header1": "value2,value2,value1", + "x-amz-date": "20150830T123600Z", + }, + path: "/", + }, + authorization: + "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;my-header1;x-amz-date, Signature=c9d5ea9f3f72853aea855b47ea873832890dbdd183b4468f858259531a5138ea", + }, + { + name: "get-header-value-multiline", + request: { + protocol: "https:", + method: "GET", + hostname: "example.amazonaws.com", + query: {}, + headers: { + host: "example.amazonaws.com", + "my-header1": "value1,value2,value3", + "x-amz-date": "20150830T123600Z", + }, + path: "/", + }, + authorization: + "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;my-header1;x-amz-date, Signature=ba17b383a53190154eb5fa66a1b836cc297cc0a3d70a5d00705980573d8ff790", + }, + { + name: "get-header-value-order", + request: { + protocol: "https:", + method: "GET", + hostname: "example.amazonaws.com", + query: {}, + headers: { + host: "example.amazonaws.com", + "my-header1": "value4,value1,value3,value2", + "x-amz-date": "20150830T123600Z", + }, + path: "/", + }, + authorization: + "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;my-header1;x-amz-date, Signature=08c7e5a9acfcfeb3ab6b2185e75ce8b1deb5e634ec47601a50643f830c755c01", + }, + { + name: "get-header-value-trim", + request: { + protocol: "https:", + method: "GET", + hostname: "example.amazonaws.com", + query: {}, + headers: { + host: "example.amazonaws.com", + "my-header1": "value1", + "my-header2": '"a b c"', + "x-amz-date": "20150830T123600Z", + }, + path: "/", + }, + authorization: + "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;my-header1;my-header2;x-amz-date, Signature=acc3ed3afb60bb290fc8d2dd0098b9911fcaa05412b367055dee359757a9c736", + }, + { + name: "get-unreserved", + request: { + protocol: "https:", + method: "GET", + hostname: "example.amazonaws.com", + query: {}, + headers: { + host: "example.amazonaws.com", + "x-amz-date": "20150830T123600Z", + }, + path: "/-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", + }, + authorization: + "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=07ef7494c76fa4850883e2b006601f940f8a34d404d0cfa977f52a65bbf5f24f", + }, + { + name: "get-utf8", + request: { + protocol: "https:", + method: "GET", + hostname: "example.amazonaws.com", + query: {}, + headers: { + host: "example.amazonaws.com", + "x-amz-date": "20150830T123600Z", + }, + path: "/ሴ", + }, + authorization: + "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=8318018e0b0f223aa2bbf98705b62bb787dc9c0e678f255a891fd03141be5d85", + }, + { + name: "get-vanilla", + request: { + protocol: "https:", + method: "GET", + hostname: "example.amazonaws.com", + query: {}, + headers: { + host: "example.amazonaws.com", + "x-amz-date": "20150830T123600Z", + }, + path: "/", + }, + authorization: + "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=5fa00fa31553b73ebf1942676e86291e8372ff2a2260956d9b8aae1d763fbf31", + }, + { + name: "get-vanilla-empty-query-key", + request: { + protocol: "https:", + method: "GET", + hostname: "example.amazonaws.com", + query: { + Param1: "value1", + }, + headers: { + host: "example.amazonaws.com", + "x-amz-date": "20150830T123600Z", + }, + path: "/", + }, + authorization: + "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=a67d582fa61cc504c4bae71f336f98b97f1ea3c7a6bfe1b6e45aec72011b9aeb", + }, + { + name: "get-vanilla-query", + request: { + protocol: "https:", + method: "GET", + hostname: "example.amazonaws.com", + query: {}, + headers: { + host: "example.amazonaws.com", + "x-amz-date": "20150830T123600Z", + }, + path: "/", + }, + authorization: + "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=5fa00fa31553b73ebf1942676e86291e8372ff2a2260956d9b8aae1d763fbf31", + }, + { + name: "get-vanilla-query-order-key-case", + request: { + protocol: "https:", + method: "GET", + hostname: "example.amazonaws.com", + query: { + Param2: "value2", + Param1: "value1", + }, + headers: { + host: "example.amazonaws.com", + "x-amz-date": "20150830T123600Z", + }, + path: "/", + }, + authorization: + "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=b97d918cfa904a5beff61c982a1b6f458b799221646efd99d3219ec94cdf2500", + }, + { + name: "get-vanilla-query-unreserved", + request: { + protocol: "https:", + method: "GET", + hostname: "example.amazonaws.com", + query: { + "-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz": + "-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", + }, + headers: { + host: "example.amazonaws.com", + "x-amz-date": "20150830T123600Z", + }, + path: "/", + }, + authorization: + "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=9c3e54bfcdf0b19771a7f523ee5669cdf59bc7cc0884027167c21bb143a40197", + }, + { + name: "get-vanilla-utf8-query", + request: { + protocol: "https:", + method: "GET", + hostname: "example.amazonaws.com", + query: { + ሴ: "bar", + }, + headers: { + host: "example.amazonaws.com", + "x-amz-date": "20150830T123600Z", + }, + path: "/", + }, + authorization: + "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=2cdec8eed098649ff3a119c94853b13c643bcf08f8b0a1d91e12c9027818dd04", + }, + { + name: "post-header-key-case", + request: { + protocol: "https:", + method: "POST", + hostname: "example.amazonaws.com", + query: {}, + headers: { + host: "example.amazonaws.com", + "x-amz-date": "20150830T123600Z", + }, + path: "/", + }, + authorization: + "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=5da7c1a2acd57cee7505fc6676e4e544621c30862966e37dddb68e92efbe5d6b", + }, + { + name: "post-header-key-sort", + request: { + protocol: "https:", + method: "POST", + hostname: "example.amazonaws.com", + query: {}, + headers: { + host: "example.amazonaws.com", + "my-header1": "value1", + "x-amz-date": "20150830T123600Z", + }, + path: "/", + }, + authorization: + "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;my-header1;x-amz-date, Signature=c5410059b04c1ee005303aed430f6e6645f61f4dc9e1461ec8f8916fdf18852c", + }, + { + name: "post-header-value-case", + request: { + protocol: "https:", + method: "POST", + hostname: "example.amazonaws.com", + query: {}, + headers: { + host: "example.amazonaws.com", + "my-header1": "VALUE1", + "x-amz-date": "20150830T123600Z", + }, + path: "/", + }, + authorization: + "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;my-header1;x-amz-date, Signature=cdbc9802e29d2942e5e10b5bccfdd67c5f22c7c4e8ae67b53629efa58b974b7d", + }, + { + name: "post-sts-header-after", + request: { + protocol: "https:", + method: "POST", + hostname: "example.amazonaws.com", + query: {}, + headers: { + host: "example.amazonaws.com", + "x-amz-date": "20150830T123600Z", + }, + path: "/", + }, + authorization: + "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=5da7c1a2acd57cee7505fc6676e4e544621c30862966e37dddb68e92efbe5d6b", + }, + /** This test can be ignored as it's only needed at IoT WebSocket handshake. + { + name: "post-sts-header-before", + request: { + protocol: "https:", + method: "POST", + hostname: "example.amazonaws.com", + query: {}, + headers: { + host: "example.amazonaws.com", + "x-amz-date": "20150830T123600Z", + "x-amz-security-token": + "AQoDYXdzEPT//////////wEXAMPLEtc764bNrC9SAPBSM22wDOk4x4HIZ8j4FZTwdQWLWsKWHGBuFqwAeMicRXmxfpSPfIeoIYRqTflfKD8YUuwthAx7mSEI/qkPpKPi/kMcGdQrmGdeehM4IC1NtBmUpp2wUE8phUZampKsburEDy0KPkyQDYwT7WZ0wq5VSXDvp75YU9HFvlRd8Tx6q6fE8YQcHNVXAkiY9q6d+xo0rKwT38xVqr7ZD0u0iPPkUL64lIZbqBAz+scqKmlzm8FDrypNC9Yjc8fPOLn9FX9KSYvKTr4rvx3iSIlTJabIQwj2ICCR/oLxBA==", + }, + path: "/", + }, + authorization: + "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date;x-amz-security-token, Signature=85d96828115b5dc0cfc3bd16ad9e210dd772bbebba041836c64533a82be05ead", + }, + */ + { + name: "post-vanilla", + request: { + protocol: "https:", + method: "POST", + hostname: "example.amazonaws.com", + query: {}, + headers: { + host: "example.amazonaws.com", + "x-amz-date": "20150830T123600Z", + }, + path: "/", + }, + authorization: + "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=5da7c1a2acd57cee7505fc6676e4e544621c30862966e37dddb68e92efbe5d6b", + }, + { + name: "post-vanilla-empty-query-value", + request: { + protocol: "https:", + method: "POST", + hostname: "example.amazonaws.com", + query: { + Param1: "value1", + }, + headers: { + host: "example.amazonaws.com", + "x-amz-date": "20150830T123600Z", + }, + path: "/", + }, + authorization: + "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=28038455d6de14eafc1f9222cf5aa6f1a96197d7deb8263271d420d138af7f11", + }, + { + name: "post-vanilla-query", + request: { + protocol: "https:", + method: "POST", + hostname: "example.amazonaws.com", + query: { + Param1: "value1", + }, + headers: { + host: "example.amazonaws.com", + "x-amz-date": "20150830T123600Z", + }, + path: "/", + }, + authorization: + "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=28038455d6de14eafc1f9222cf5aa6f1a96197d7deb8263271d420d138af7f11", + }, + { + name: "post-vanilla-query-nonunreserved", + request: { + protocol: "https:", + method: "POST", + hostname: "example.amazonaws.com", + query: { + "@#$%^": "", + "+": '/,?><`";:\\|][{}', + }, + headers: { + host: "example.amazonaws.com", + "x-amz-date": "20150830T123600Z", + }, + path: "/", + }, + authorization: + "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=66c82657c86e26fb25238d0e69f011edc4c6df5ae71119d7cb98ed9b87393c1e", + }, + { + name: "post-vanilla-query-space", + request: { + protocol: "https:", + method: "POST", + hostname: "example.amazonaws.com", + query: { + p: "", + }, + headers: { + host: "example.amazonaws.com", + "x-amz-date": "20150830T123600Z", + }, + path: "/", + }, + authorization: + "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date, Signature=e71688addb58a26418614085fb730ba3faa623b461c17f48f2fbdb9361b94a9b", + }, + { + name: "post-x-www-form-urlencoded", + request: { + protocol: "https:", + method: "POST", + hostname: "example.amazonaws.com", + query: {}, + headers: { + "content-type": "application/x-www-form-urlencoded", + host: "example.amazonaws.com", + "x-amz-date": "20150830T123600Z", + }, + body: "Param1=value1", + path: "/", + }, + authorization: + "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=ff11897932ad3f4e8b18135d722051e5ac45fc38421b1da7b9d196a0fe09473a", + }, + { + name: "post-x-www-form-urlencoded-parameters", + request: { + protocol: "https:", + method: "POST", + hostname: "example.amazonaws.com", + query: {}, + headers: { + "content-type": "application/x-www-form-urlencoded; charset=utf8", + host: "example.amazonaws.com", + "x-amz-date": "20150830T123600Z", + }, + body: "Param1=value1", + path: "/", + }, + authorization: + "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=1a72ec8f64bd914b0e42e42607c7fbce7fb2c7465f63e3092b3b0d39fa77a6fe", + }, +]; diff --git a/packages/signature-v4-crt/tsconfig.cjs.json b/packages/signature-v4-crt/tsconfig.cjs.json new file mode 100644 index 000000000000..2ac63587c54b --- /dev/null +++ b/packages/signature-v4-crt/tsconfig.cjs.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "stripInternal": true, + "declarationDir": "./dist/types", + "rootDir": "./src", + "outDir": "./dist/cjs", + "noUnusedLocals": true, + "lib": ["es2016"], + "baseUrl": "." + }, + "extends": "../../tsconfig.cjs.json", + "include": ["src/"] +} diff --git a/packages/signature-v4-crt/tsconfig.es.json b/packages/signature-v4-crt/tsconfig.es.json new file mode 100644 index 000000000000..7d0cab3b0ca1 --- /dev/null +++ b/packages/signature-v4-crt/tsconfig.es.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "stripInternal": true, + "declarationDir": "./dist/types", + "rootDir": "./src", + "outDir": "./dist/es", + "noUnusedLocals": true, + "baseUrl": ".", + "target": "es5", + "module": "esNext", + "moduleResolution": "node", + "lib": ["es5", "es2015.promise", "es2015.collection"], + "incremental": true + }, + "extends": "../../tsconfig.es.json", + "include": ["src/"] +} diff --git a/packages/signature-v4/src/SignatureV4.ts b/packages/signature-v4/src/SignatureV4.ts index b2fec373f1b7..4f02a58ab67b 100644 --- a/packages/signature-v4/src/SignatureV4.ts +++ b/packages/signature-v4/src/SignatureV4.ts @@ -37,8 +37,9 @@ import { createScope, getSigningKey } from "./credentialDerivation"; import { getCanonicalHeaders } from "./getCanonicalHeaders"; import { getCanonicalQuery } from "./getCanonicalQuery"; import { getPayloadHash } from "./getPayloadHash"; -import { hasHeader } from "./hasHeader"; +import { hasHeader } from "./headerUtil"; import { moveHeadersToQuery } from "./moveHeadersToQuery"; +import { normalizeCredentialsProvider, normalizeRegionProvider } from "./normalizeProvider"; import { prepareRequest } from "./prepareRequest"; import { iso8601 } from "./utilDate"; @@ -317,21 +318,3 @@ const formatDate = (now: DateInput): { longDate: string; shortDate: string } => }; const getCanonicalHeaderList = (headers: object): string => Object.keys(headers).sort().join(";"); - -const normalizeRegionProvider = (region: string | Provider): Provider => { - if (typeof region === "string") { - const promisified = Promise.resolve(region); - return () => promisified; - } else { - return region; - } -}; - -const normalizeCredentialsProvider = (credentials: Credentials | Provider): Provider => { - if (typeof credentials === "object") { - const promisified = Promise.resolve(credentials); - return () => promisified; - } else { - return credentials; - } -}; diff --git a/packages/signature-v4/src/cloneRequest.ts b/packages/signature-v4/src/cloneRequest.ts index f3fc5fa5ecf8..d21d39cd6ddb 100644 --- a/packages/signature-v4/src/cloneRequest.ts +++ b/packages/signature-v4/src/cloneRequest.ts @@ -3,20 +3,17 @@ import { HttpRequest, QueryParameterBag } from "@aws-sdk/types"; /** * @internal */ -export function cloneRequest({ headers, query, ...rest }: HttpRequest): HttpRequest { - return { - ...rest, - headers: { ...headers }, - query: query ? cloneQuery(query) : undefined, - }; -} +export const cloneRequest = ({ headers, query, ...rest }: HttpRequest): HttpRequest => ({ + ...rest, + headers: { ...headers }, + query: query ? cloneQuery(query) : undefined, +}); -function cloneQuery(query: QueryParameterBag): QueryParameterBag { - return Object.keys(query).reduce((carry: QueryParameterBag, paramName: string) => { +export const cloneQuery = (query: QueryParameterBag): QueryParameterBag => + Object.keys(query).reduce((carry: QueryParameterBag, paramName: string) => { const param = query[paramName]; return { ...carry, [paramName]: Array.isArray(param) ? [...param] : param, }; }, {}); -} diff --git a/packages/signature-v4/src/constants.ts b/packages/signature-v4/src/constants.ts index a0dafa4379d6..e66b35d6367f 100644 --- a/packages/signature-v4/src/constants.ts +++ b/packages/signature-v4/src/constants.ts @@ -5,6 +5,7 @@ export const SIGNED_HEADERS_QUERY_PARAM = "X-Amz-SignedHeaders"; export const EXPIRES_QUERY_PARAM = "X-Amz-Expires"; export const SIGNATURE_QUERY_PARAM = "X-Amz-Signature"; export const TOKEN_QUERY_PARAM = "X-Amz-Security-Token"; +export const REGION_SET_PARAM = "X-Amz-Region-Set"; export const AUTH_HEADER = "authorization"; export const AMZ_DATE_HEADER = AMZ_DATE_QUERY_PARAM.toLowerCase(); @@ -40,6 +41,7 @@ export const SEC_HEADER_PATTERN = /^sec-/; export const UNSIGNABLE_PATTERNS = [/^proxy-/i, /^sec-/i]; export const ALGORITHM_IDENTIFIER = "AWS4-HMAC-SHA256"; +export const ALGORITHM_IDENTIFIER_V4A = "AWS4-ECDSA-P256-SHA256"; export const EVENT_ALGORITHM_IDENTIFIER = "AWS4-HMAC-SHA256-PAYLOAD"; diff --git a/packages/signature-v4/src/credentialDerivation.ts b/packages/signature-v4/src/credentialDerivation.ts index 049fbee4b305..bdcc311e077a 100644 --- a/packages/signature-v4/src/credentialDerivation.ts +++ b/packages/signature-v4/src/credentialDerivation.ts @@ -13,9 +13,8 @@ const cacheQueue: Array = []; * @param region The AWS region in which the service resides. * @param service The service to which the signed request is being sent. */ -export function createScope(shortDate: string, region: string, service: string): string { - return `${shortDate}/${region}/${service}/${KEY_TYPE_IDENTIFIER}`; -} +export const createScope = (shortDate: string, region: string, service: string): string => + `${shortDate}/${region}/${service}/${KEY_TYPE_IDENTIFIER}`; /** * Derive a signing key from its composite parts @@ -57,15 +56,15 @@ export const getSigningKey = async ( /** * @internal */ -export function clearCredentialCache(): void { +export const clearCredentialCache = (): void => { cacheQueue.length = 0; Object.keys(signingKeyCache).forEach((cacheKey) => { delete signingKeyCache[cacheKey]; }); -} +}; -function hmac(ctor: HashConstructor, secret: SourceData, data: SourceData): Promise { +const hmac = (ctor: HashConstructor, secret: SourceData, data: SourceData): Promise => { const hash = new ctor(secret); hash.update(data); return hash.digest(); -} +}; diff --git a/packages/signature-v4/src/getCanonicalHeaders.ts b/packages/signature-v4/src/getCanonicalHeaders.ts index b0c0fe230c70..927d2987c814 100644 --- a/packages/signature-v4/src/getCanonicalHeaders.ts +++ b/packages/signature-v4/src/getCanonicalHeaders.ts @@ -3,13 +3,13 @@ import { HeaderBag, HttpRequest } from "@aws-sdk/types"; import { ALWAYS_UNSIGNABLE_HEADERS, PROXY_HEADER_PATTERN, SEC_HEADER_PATTERN } from "./constants"; /** - * @internal + * @private */ -export function getCanonicalHeaders( +export const getCanonicalHeaders = ( { headers }: HttpRequest, unsignableHeaders?: Set, signableHeaders?: Set -): HeaderBag { +): HeaderBag => { const canonical: HeaderBag = {}; for (const headerName of Object.keys(headers).sort()) { const canonicalHeaderName = headerName.toLowerCase(); @@ -28,4 +28,4 @@ export function getCanonicalHeaders( } return canonical; -} +}; diff --git a/packages/signature-v4/src/getCanonicalQuery.ts b/packages/signature-v4/src/getCanonicalQuery.ts index 0e1db62b71c7..b9287de12cf9 100644 --- a/packages/signature-v4/src/getCanonicalQuery.ts +++ b/packages/signature-v4/src/getCanonicalQuery.ts @@ -4,9 +4,9 @@ import { escapeUri } from "@aws-sdk/util-uri-escape"; import { SIGNATURE_HEADER } from "./constants"; /** - * @internal + * @private */ -export function getCanonicalQuery({ query = {} }: HttpRequest): string { +export const getCanonicalQuery = ({ query = {} }: HttpRequest): string => { const keys: Array = []; const serialized: { [key: string]: string } = {}; for (const key of Object.keys(query).sort()) { @@ -34,4 +34,4 @@ export function getCanonicalQuery({ query = {} }: HttpRequest): string { .map((key) => serialized[key]) .filter((serialized) => serialized) // omit any falsy values .join("&"); -} +}; diff --git a/packages/signature-v4/src/getPayloadHash.ts b/packages/signature-v4/src/getPayloadHash.ts index b185600c5634..2846002b2966 100644 --- a/packages/signature-v4/src/getPayloadHash.ts +++ b/packages/signature-v4/src/getPayloadHash.ts @@ -5,12 +5,12 @@ import { toHex } from "@aws-sdk/util-hex-encoding"; import { SHA256_HEADER, UNSIGNED_PAYLOAD } from "./constants"; /** - * @internal + * @private */ -export async function getPayloadHash( +export const getPayloadHash = async ( { headers, body }: HttpRequest, hashConstructor: HashConstructor -): Promise { +): Promise => { for (const headerName of Object.keys(headers)) { if (headerName.toLowerCase() === SHA256_HEADER) { return headers[headerName]; @@ -29,4 +29,4 @@ export async function getPayloadHash( // body is unsignable. Attempt to send the request with an unsigned payload, // which may or may not be accepted by the service. return UNSIGNED_PAYLOAD; -} +}; diff --git a/packages/signature-v4/src/hasHeader.ts b/packages/signature-v4/src/hasHeader.ts deleted file mode 100644 index a8c2ab0f806d..000000000000 --- a/packages/signature-v4/src/hasHeader.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { HeaderBag } from "@aws-sdk/types"; - -export function hasHeader(soughtHeader: string, headers: HeaderBag): boolean { - soughtHeader = soughtHeader.toLowerCase(); - for (const headerName of Object.keys(headers)) { - if (soughtHeader === headerName.toLowerCase()) { - return true; - } - } - - return false; -} diff --git a/packages/signature-v4/src/headerUtil.ts b/packages/signature-v4/src/headerUtil.ts new file mode 100644 index 000000000000..c4423c511fdd --- /dev/null +++ b/packages/signature-v4/src/headerUtil.ts @@ -0,0 +1,34 @@ +import { HeaderBag } from "@aws-sdk/types"; + +export const hasHeader = (soughtHeader: string, headers: HeaderBag): boolean => { + soughtHeader = soughtHeader.toLowerCase(); + for (const headerName of Object.keys(headers)) { + if (soughtHeader === headerName.toLowerCase()) { + return true; + } + } + + return false; +}; + +/* Get the value of one request header, ignore the case. Return string if header is in the headers, else return undefined */ +export const getHeaderValue = (soughtHeader: string, headers: HeaderBag): string | undefined => { + soughtHeader = soughtHeader.toLowerCase(); + for (const headerName of Object.keys(headers)) { + if (soughtHeader === headerName.toLowerCase()) { + return headers[headerName]; + } + } + + return undefined; +}; + +/* Delete the one request header, ignore the case. Do nothing if it's not there */ +export const deleteHeader = (soughtHeader: string, headers: HeaderBag) => { + soughtHeader = soughtHeader.toLowerCase(); + for (const headerName of Object.keys(headers)) { + if (soughtHeader === headerName.toLowerCase()) { + delete headers[headerName]; + } + } +}; diff --git a/packages/signature-v4/src/index.ts b/packages/signature-v4/src/index.ts index 516324e6ff76..e8dc0d15a642 100644 --- a/packages/signature-v4/src/index.ts +++ b/packages/signature-v4/src/index.ts @@ -1,2 +1,8 @@ export * from "./credentialDerivation"; +export { getCanonicalHeaders } from "./getCanonicalHeaders"; +export { getCanonicalQuery } from "./getCanonicalQuery"; +export { getPayloadHash } from "./getPayloadHash"; +export { moveHeadersToQuery } from "./moveHeadersToQuery"; +export { prepareRequest } from "./prepareRequest"; +export { normalizeCredentialsProvider, normalizeRegionProvider } from "./normalizeProvider"; export * from "./SignatureV4"; diff --git a/packages/signature-v4/src/moveHeadersToQuery.ts b/packages/signature-v4/src/moveHeadersToQuery.ts index 2404c98315ca..9cf948e00221 100644 --- a/packages/signature-v4/src/moveHeadersToQuery.ts +++ b/packages/signature-v4/src/moveHeadersToQuery.ts @@ -3,12 +3,12 @@ import { HttpRequest, QueryParameterBag } from "@aws-sdk/types"; import { cloneRequest } from "./cloneRequest"; /** - * @internal + * @private */ -export function moveHeadersToQuery( +export const moveHeadersToQuery = ( request: HttpRequest, options: { unhoistableHeaders?: Set } = {} -): HttpRequest & { query: QueryParameterBag } { +): HttpRequest & { query: QueryParameterBag } => { const { headers, query = {} as QueryParameterBag } = typeof (request as any).clone === "function" ? (request as any).clone() : cloneRequest(request); for (const name of Object.keys(headers)) { @@ -24,4 +24,4 @@ export function moveHeadersToQuery( headers, query, }; -} +}; diff --git a/packages/signature-v4/src/normalizeProvider.ts b/packages/signature-v4/src/normalizeProvider.ts new file mode 100644 index 000000000000..3e5d9602718a --- /dev/null +++ b/packages/signature-v4/src/normalizeProvider.ts @@ -0,0 +1,27 @@ +import { Credentials, Provider } from "@aws-sdk/types"; + +/** + * @private + */ +export const normalizeRegionProvider = (region: string | Provider): Provider => { + if (typeof region === "string") { + const promisified = Promise.resolve(region); + return () => promisified; + } else { + return region; + } +}; + +/** + * @private + */ +export const normalizeCredentialsProvider = ( + credentials: Credentials | Provider +): Provider => { + if (typeof credentials === "object") { + const promisified = Promise.resolve(credentials); + return () => promisified; + } else { + return credentials; + } +}; diff --git a/packages/signature-v4/src/prepareRequest.ts b/packages/signature-v4/src/prepareRequest.ts index 4eb34e5be7be..91bf32880496 100644 --- a/packages/signature-v4/src/prepareRequest.ts +++ b/packages/signature-v4/src/prepareRequest.ts @@ -4,9 +4,9 @@ import { cloneRequest } from "./cloneRequest"; import { GENERATED_HEADERS } from "./constants"; /** - * @internal + * @private */ -export function prepareRequest(request: HttpRequest): HttpRequest { +export const prepareRequest = (request: HttpRequest): HttpRequest => { // Create a clone of the request object that does not clone the body request = typeof (request as any).clone === "function" ? (request as any).clone() : cloneRequest(request); @@ -17,4 +17,4 @@ export function prepareRequest(request: HttpRequest): HttpRequest { } return request; -} +}; diff --git a/packages/signature-v4/src/utilDate.ts b/packages/signature-v4/src/utilDate.ts index 80a781139b8b..cbb5ba69088a 100644 --- a/packages/signature-v4/src/utilDate.ts +++ b/packages/signature-v4/src/utilDate.ts @@ -1,10 +1,9 @@ -export function iso8601(time: number | string | Date): string { - return toDate(time) +export const iso8601 = (time: number | string | Date): string => + toDate(time) .toISOString() .replace(/\.\d{3}Z$/, "Z"); -} -export function toDate(time: number | string | Date): Date { +export const toDate = (time: number | string | Date): Date => { if (typeof time === "number") { return new Date(time * 1000); } @@ -17,4 +16,4 @@ export function toDate(time: number | string | Date): Date { } return time; -} +}; diff --git a/packages/signature-v4/tsconfig.cjs.json b/packages/signature-v4/tsconfig.cjs.json index 89682bee9296..1db0b864fe99 100644 --- a/packages/signature-v4/tsconfig.cjs.json +++ b/packages/signature-v4/tsconfig.cjs.json @@ -4,7 +4,6 @@ "declarationDir": "./dist/types", "rootDir": "./src", "outDir": "./dist/cjs", - "noUnusedLocals": true, "baseUrl": "." }, "extends": "../../tsconfig.cjs.json", diff --git a/packages/util-user-agent-node/src/index.spec.ts b/packages/util-user-agent-node/src/index.spec.ts index 0ed407393ed8..be757f02befd 100644 --- a/packages/util-user-agent-node/src/index.spec.ts +++ b/packages/util-user-agent-node/src/index.spec.ts @@ -11,6 +11,11 @@ jest.mock("process", () => ({ }, })); +jest.mock("./is-crt-available", () => ({ + isCrtAvailable: jest.fn().mockReturnValue(null), +})); +import { isCrtAvailable } from "./is-crt-available"; + const mockAppIdLoader = jest.fn().mockResolvedValue(undefined); jest.mock("@aws-sdk/node-config-provider", () => ({ loadConfig: () => mockAppIdLoader, @@ -49,6 +54,12 @@ describe("defaultUserAgent", () => { validateUserAgent(userAgent, basicUserAgent); }); + it("should set crt available key if aws-crt is available in runtime", async () => { + (isCrtAvailable as jest.Mock).mockReturnValue(["md/crt-avail"]); + const userAgent = await defaultUserAgent({ serviceId: "s3", clientVersion: "0.1.0" })(); + expect(userAgent).toContainEqual(["md/crt-avail"]); + }); + it("should skip api version if service id is not supplied", async () => { const userAgent = await defaultUserAgent({ serviceId: undefined, clientVersion: "0.1.0" })(); validateUserAgent( diff --git a/packages/util-user-agent-node/src/index.ts b/packages/util-user-agent-node/src/index.ts index aadbdce08bb9..19139f50a2ea 100644 --- a/packages/util-user-agent-node/src/index.ts +++ b/packages/util-user-agent-node/src/index.ts @@ -3,6 +3,8 @@ import { Provider, UserAgent } from "@aws-sdk/types"; import { platform, release } from "os"; import { env, versions } from "process"; +import { isCrtAvailable } from "./is-crt-available"; + export const UA_APP_ID_ENV_NAME = "AWS_SDK_UA_APP_ID"; export const UA_APP_ID_INI_NAME = "sdk-ua-app-id"; @@ -26,6 +28,11 @@ export const defaultUserAgent = ({ serviceId, clientVersion }: DefaultUserAgentO ["md/nodejs", `${versions.node}`], ]; + const crtAvailable = isCrtAvailable(); + if (crtAvailable) { + sections.push(crtAvailable); + } + if (serviceId) { // api-metadata // service Id may not appear in non-AWS clients diff --git a/packages/util-user-agent-node/src/is-crt-available.ts b/packages/util-user-agent-node/src/is-crt-available.ts new file mode 100644 index 000000000000..330011b9c3df --- /dev/null +++ b/packages/util-user-agent-node/src/is-crt-available.ts @@ -0,0 +1,19 @@ +import { UserAgentPair } from "@aws-sdk/types"; + +export const isCrtAvailable = (): UserAgentPair | null => { + try { + // Attempt to load ambient package aws-crt to verify if it exists. + // We cannot use dynamic import(https://github.com/tc39/proposal-dynamic-import) here because bundlers + // (WebPack, Rollup) will try to bundle this optional dependency and fail to build if not exist. + // Thus this user agent key will only available in Node.js runtime. + if (typeof require === "function" && typeof module !== "undefined" && module.require && require("aws-crt")) { + // Validate `module` to make sure this is not in a `require.js` scope. + // TODO: load package version. + return ["md/crt-avail"]; + } + return null; + } catch (e) { + // No aws-crt package available in the runtime. + return null; + } +}; diff --git a/yarn.lock b/yarn.lock index 050911ebaf1e..40f48fc369da 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2366,6 +2366,11 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +ansi@^0.3.0, ansi@~0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/ansi/-/ansi-0.3.1.tgz#0c42d4fb17160d5a9af1e484bace1c66922c1b21" + integrity sha1-DELU+xcWDVqa8eSEus4cZpIsGyE= + any-promise@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" @@ -2402,6 +2407,14 @@ aproba@^2.0.0: resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== +are-we-there-yet@~1.0.0: + version "1.0.6" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.0.6.tgz#a2d28c93102aa6cc96245a26cb954de06ec53f0c" + integrity sha1-otKMkxAqpsyWJFomy5VN4G7FPww= + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.0 || ^1.1.13" + are-we-there-yet@~1.1.2: version "1.1.5" resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" @@ -2578,6 +2591,11 @@ async-each@^1.0.1: resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== +async-limiter@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" + integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== + async@3.2.0, async@^3.0.1: version "3.2.0" resolved "https://registry.yarnpkg.com/async/-/async-3.2.0.tgz#b3a2685c5ebb641d3de02d161002c60fc9f85720" @@ -2610,6 +2628,19 @@ available-typed-arrays@^1.0.2: dependencies: array-filter "^1.0.0" +aws-crt@^1.9.7: + version "1.9.7" + resolved "https://registry.yarnpkg.com/aws-crt/-/aws-crt-1.9.7.tgz#150180aeed7fdbf4374ec99eaaab2970cfc62854" + integrity sha512-k1u7V3qlcemjx/eNHOlpsxSMRvgQ1S08Am+QiBDLVgWCp9gUlsB/qN+MVTmEjgR6llSp9Tdkpr9GROqUm+c4tg== + dependencies: + axios "^0.21.4" + cmake-js "6.1.0" + crypto-js "^4.0.0" + fastestsmallesttextencoderdecoder "^1.0.22" + mqtt "^4.2.8" + tar "^6.1.11" + websocket-stream "^5.5.2" + aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" @@ -2620,6 +2651,13 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== +axios@^0.21.4: + version "0.21.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" + integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== + dependencies: + follow-redirects "^1.14.0" + babel-jest@^26.6.3: version "26.6.3" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.6.3.tgz#d87d25cb0037577a0c89f82e5755c5d293c01056" @@ -2741,6 +2779,11 @@ before-after-hook@^2.0.0: resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.1.tgz#73540563558687586b52ed217dad6a802ab1549c" integrity sha512-/6FKxSTWoJdbsLDF8tdIjaRiFXiE6UHsEHE3OPI/cwPURCVi1ukP0gmLn7XWEiFk5TcwQjjY5PWsU+j+tgXgmw== +big-integer@^1.6.17: + version "1.6.48" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.48.tgz#8fd88bd1632cba4a1c8c3e3d7159f08bb95b4b9e" + integrity sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w== + big.js@^5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" @@ -2756,6 +2799,14 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== +binary@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/binary/-/binary-0.3.0.tgz#9f60553bc5ce8c3386f3b553cff47462adecaa79" + integrity sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk= + dependencies: + buffers "~0.1.1" + chainsaw "~0.1.0" + bindings@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" @@ -2763,7 +2814,7 @@ bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" -bl@^4.0.3, bl@^4.1.0: +bl@^4.0.2, bl@^4.0.3, bl@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== @@ -2782,6 +2833,11 @@ bluebird@^3.0.6, bluebird@^3.4.1, bluebird@^3.5.1, bluebird@^3.5.3, bluebird@^3. resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== +bluebird@~3.4.1: + version "3.4.7" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.7.tgz#f72d760be09b7f76d08ed8fae98b289a8d05fab3" + integrity sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM= + bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" @@ -2972,6 +3028,16 @@ buffer-from@1.x, buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== +buffer-indexof-polyfill@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz#d2732135c5999c64b277fcf9b1abe3498254729c" + integrity sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A== + +buffer-shims@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" + integrity sha1-mXjOMXOIxkmth5MCjDR37wRKi1E= + buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" @@ -2994,6 +3060,11 @@ buffer@^5.2.1, buffer@^5.4.3, buffer@^5.5.0, buffer@^5.6.0: base64-js "^1.3.1" ieee754 "^1.1.13" +buffers@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb" + integrity sha1-skV5w77U1tOWru5tmorn9Ugqt7s= + builtin-status-codes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" @@ -3133,7 +3204,7 @@ camelcase-keys@^6.2.2: map-obj "^4.0.0" quick-lru "^4.0.1" -camelcase@^2.0.0: +camelcase@^2.0.0, camelcase@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= @@ -3189,6 +3260,13 @@ chai@^4.2.0: pathval "^1.1.1" type-detect "^4.0.5" +chainsaw@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/chainsaw/-/chainsaw-0.1.0.tgz#5eab50b28afe58074d0d58291388828b5e5fbc98" + integrity sha1-XqtQsor+WAdNDVgpE4iCi15fvJg= + dependencies: + traverse ">=0.3.0 <0.4" + chalk@4.1.0, chalk@^4.0.0, chalk@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" @@ -3260,6 +3338,11 @@ chownr@^1.1.1, chownr@^1.1.2, chownr@^1.1.4: resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + chrome-trace-event@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" @@ -3340,6 +3423,15 @@ cli-width@^2.0.0: resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== +cliui@^3.0.3: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + cliui@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" @@ -3381,6 +3473,27 @@ clone@^1.0.2: resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= +cmake-js@6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/cmake-js/-/cmake-js-6.1.0.tgz#bec7381b58d454acee09d4fb0047153a005063a6" + integrity sha512-utmukLQftpgrCpGRCaHnkv4K27HZNNFqmBl4vnvccy0xp4c1erxjFU/Lq4wn5ngAhFZmpwBPQfoKWKThjSBiwg== + dependencies: + debug "^4" + fs-extra "^5.0.0" + is-iojs "^1.0.1" + lodash "^4" + memory-stream "0" + npmlog "^1.2.0" + rc "^1.2.7" + request "^2.54.0" + semver "^5.0.3" + splitargs "0" + tar "^4" + unzipper "^0.8.13" + url-join "0" + which "^1.0.9" + yargs "^3.6.0" + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -3494,6 +3607,14 @@ commander@^7.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== +commist@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/commist/-/commist-1.1.0.tgz#17811ec6978f6c15ee4de80c45c9beb77cee35d5" + integrity sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg== + dependencies: + leven "^2.1.0" + minimist "^1.1.0" + commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -3878,6 +3999,11 @@ crypto-browserify@^3.11.0, crypto-browserify@^3.12.0: randombytes "^2.0.0" randomfill "^1.0.3" +crypto-js@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.1.1.tgz#9e485bcf03521041bd85844786b83fb7619736cf" + integrity sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw== + cssom@^0.4.1, cssom@^0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" @@ -4037,7 +4163,7 @@ debug@3.1.0, debug@~3.1.0: dependencies: ms "2.0.0" -debug@4, debug@4.3.1, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0: +debug@4, debug@4.3.1, debug@^4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0: version "4.3.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== @@ -4078,7 +4204,7 @@ decamelize-keys@^1.0.0, decamelize-keys@^1.1.0: decamelize "^1.1.0" map-obj "^1.0.0" -decamelize@^1.1.0, decamelize@^1.1.2, decamelize@^1.2.0: +decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.1.2, decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= @@ -4110,6 +4236,11 @@ deep-eql@^3.0.1: dependencies: type-detect "^4.0.0" +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + deep-is@^0.1.3, deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" @@ -4349,12 +4480,19 @@ dtrace-provider@~0.8: dependencies: nan "^2.14.0" +duplexer2@~0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" + integrity sha1-ixLauHjA1p4+eJEFFmKjL8a93ME= + dependencies: + readable-stream "^2.0.2" + duplexer@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== -duplexify@^3.4.2, duplexify@^3.6.0: +duplexify@^3.4.2, duplexify@^3.5.1, duplexify@^3.6.0: version "3.7.1" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== @@ -4364,6 +4502,16 @@ duplexify@^3.4.2, duplexify@^3.6.0: readable-stream "^2.0.0" stream-shift "^1.0.0" +duplexify@^4.1.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.2.tgz#18b4f8d28289132fa0b9573c898d9f903f81c7b0" + integrity sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw== + dependencies: + end-of-stream "^1.4.1" + inherits "^2.0.3" + readable-stream "^3.1.1" + stream-shift "^1.0.0" + duration@^0.2.1: version "0.2.2" resolved "https://registry.yarnpkg.com/duration/-/duration-0.2.2.tgz#ddf149bc3bc6901150fe9017111d016b3357f529" @@ -5089,6 +5237,11 @@ fast-xml-parser@3.19.0: resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-3.19.0.tgz#cb637ec3f3999f51406dd8ff0e6fc4d83e520d01" integrity sha512-4pXwmBplsCPv8FOY1WRakF970TjNGnGnfbOnLqjlYvMiF1SR3yOHyxMR/YCXpPTOspNF5gwudqktIP4VsWkvBg== +fastestsmallesttextencoderdecoder@^1.0.22: + version "1.0.22" + resolved "https://registry.yarnpkg.com/fastestsmallesttextencoderdecoder/-/fastestsmallesttextencoderdecoder-1.0.22.tgz#59b47e7b965f45258629cc6c127bf783281c5e93" + integrity sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw== + fastq@^1.6.0: version "1.11.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.11.0.tgz#bb9fb955a07130a918eb63c1f5161cc32a5d0858" @@ -5281,6 +5434,11 @@ follow-redirects@^1.0.0: resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.3.tgz#e5598ad50174c1bc4e872301e82ac2cd97f90267" integrity sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA== +follow-redirects@^1.14.0: + version "1.14.4" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.4.tgz#838fdf48a8bbdd79e52ee51fb1c94e3ed98b9379" + integrity sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g== + for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -5335,6 +5493,15 @@ fs-constants@^1.0.0: resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== +fs-extra@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" + integrity sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + fs-extra@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" @@ -5361,6 +5528,13 @@ fs-minipass@^1.2.7: dependencies: minipass "^2.6.0" +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + fs-write-stream-atomic@^1.0.8: version "1.0.10" resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" @@ -5389,6 +5563,16 @@ fsevents@^2.1.2, fsevents@~2.3.1: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== +fstream@~1.0.10: + version "1.0.12" + resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045" + integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg== + dependencies: + graceful-fs "^4.1.2" + inherits "~2.0.0" + mkdirp ">=0.5 0" + rimraf "2" + function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -5399,6 +5583,17 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= +gauge@~1.2.0: + version "1.2.7" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-1.2.7.tgz#e9cec5483d3d4ee0ef44b60a7d99e4935e136d93" + integrity sha1-6c7FSD09TuDvRLYKfZnkk14TbZM= + dependencies: + ansi "^0.3.0" + has-unicode "^2.0.0" + lodash.pad "^4.1.0" + lodash.padend "^4.1.0" + lodash.padstart "^4.1.0" + gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" @@ -5870,6 +6065,14 @@ he@1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +help-me@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/help-me/-/help-me-3.0.0.tgz#9803c81b5f346ad2bce2c6a0ba01b82257d319e8" + integrity sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ== + dependencies: + glob "^7.1.6" + readable-stream "^3.6.0" + highlight.js@^10.2.0: version "10.7.2" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.2.tgz#89319b861edc66c48854ed1e6da21ea89f847360" @@ -6172,7 +6375,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -6187,7 +6390,7 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -ini@^1.3.2, ini@^1.3.4, ini@^1.3.5: +ini@^1.3.2, ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: version "1.3.8" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== @@ -6237,6 +6440,11 @@ interpret@^1.0.0, interpret@^1.4.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= + ip-regex@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" @@ -6456,6 +6664,11 @@ is-interactive@^1.0.0: resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== +is-iojs@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-iojs/-/is-iojs-1.1.0.tgz#4c11033b5d5d94d6eab3775dedc9be7d008325f1" + integrity sha1-TBEDO11dlNbqs3dd7cm+fQCDJfE= + is-nan@^1.2.1: version "1.3.2" resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d" @@ -6634,6 +6847,11 @@ is-wsl@^2.1.0, is-wsl@^2.2.0: dependencies: is-docker "^2.0.0" +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -7524,6 +7742,13 @@ knuth-shuffle-seeded@^1.0.6: dependencies: seed-random "~2.2.0" +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= + dependencies: + invert-kv "^1.0.0" + lerna@3.22.1: version "3.22.1" resolved "https://registry.yarnpkg.com/lerna/-/lerna-3.22.1.tgz#82027ac3da9c627fd8bf02ccfeff806a98e65b62" @@ -7632,6 +7857,11 @@ levelup@^4.3.2: level-supports "~1.0.0" xtend "~4.0.0" +leven@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" + integrity sha1-wuep93IJTe6dNCAq6KzORoeHVYA= + leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" @@ -7679,6 +7909,11 @@ lint-staged@^10.0.1: string-argv "0.3.1" stringify-object "^3.3.0" +listenercount@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/listenercount/-/listenercount-1.0.1.tgz#84c8a72ab59c4725321480c975e6508342e70937" + integrity sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc= + listr2@^3.2.2: version "3.7.1" resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.7.1.tgz#ff0c410b10eb1c5c76735e4814128ec8f7d2b983" @@ -7842,6 +8077,21 @@ lodash.once@^4.0.0: resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= +lodash.pad@^4.1.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/lodash.pad/-/lodash.pad-4.5.1.tgz#4330949a833a7c8da22cc20f6a26c4d59debba70" + integrity sha1-QzCUmoM6fI2iLMIPaibE1Z3runA= + +lodash.padend@^4.1.0: + version "4.6.1" + resolved "https://registry.yarnpkg.com/lodash.padend/-/lodash.padend-4.6.1.tgz#53ccba047d06e158d311f45da625f4e49e6f166e" + integrity sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4= + +lodash.padstart@^4.1.0: + version "4.6.1" + resolved "https://registry.yarnpkg.com/lodash.padstart/-/lodash.padstart-4.6.1.tgz#d2e3eebff0d9d39ad50f5cbd1b52a7bce6bb611b" + integrity sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs= + lodash.set@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23" @@ -7877,7 +8127,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@4.17.21, lodash@4.x, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.2.1, lodash@^4.7.0: +lodash@4.17.21, lodash@4.x, lodash@^4, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.2.1, lodash@^4.7.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -8090,6 +8340,13 @@ memory-fs@^0.5.0: errno "^0.1.3" readable-stream "^2.0.1" +memory-stream@0: + version "0.0.3" + resolved "https://registry.yarnpkg.com/memory-stream/-/memory-stream-0.0.3.tgz#ebe8dd1c3b8bc38c0e7941e9ddd5aebe6b4de83f" + integrity sha1-6+jdHDuLw4wOeUHp3dWuvmtN6D8= + dependencies: + readable-stream "~1.0.26-2" + meow@^3.3.0: version "3.7.0" resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" @@ -8264,7 +8521,7 @@ minimist-options@^3.0.1: arrify "^1.0.1" is-plain-obj "^1.1.0" -minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: +minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== @@ -8277,6 +8534,13 @@ minipass@^2.3.5, minipass@^2.6.0, minipass@^2.9.0: safe-buffer "^5.1.2" yallist "^3.0.0" +minipass@^3.0.0: + version "3.1.5" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.5.tgz#71f6251b0a33a49c01b3cf97ff77eda030dff732" + integrity sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw== + dependencies: + yallist "^4.0.0" + minizlib@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" @@ -8284,6 +8548,14 @@ minizlib@^1.3.3: dependencies: minipass "^2.9.0" +minizlib@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + mississippi@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" @@ -8320,12 +8592,12 @@ mkdirp-promise@^5.0.1: dependencies: mkdirp "*" -mkdirp@*, mkdirp@1.x: +mkdirp@*, mkdirp@1.x, mkdirp@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mkdirp@0.5.5, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1: +mkdirp@0.5.5, "mkdirp@>=0.5 0", mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -8399,6 +8671,35 @@ move-concurrently@^1.0.1: rimraf "^2.5.4" run-queue "^1.0.3" +mqtt-packet@^6.8.0: + version "6.10.0" + resolved "https://registry.yarnpkg.com/mqtt-packet/-/mqtt-packet-6.10.0.tgz#c8b507832c4152e3e511c0efa104ae4a64cd418f" + integrity sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA== + dependencies: + bl "^4.0.2" + debug "^4.1.1" + process-nextick-args "^2.0.1" + +mqtt@^4.2.8: + version "4.2.8" + resolved "https://registry.yarnpkg.com/mqtt/-/mqtt-4.2.8.tgz#f0e54b138bcdaef6c55c547b3a4de9cf9074208c" + integrity sha512-DJYjlXODVXtSDecN8jnNzi6ItX3+ufGsEs9OB3YV24HtkRrh7kpx8L5M1LuyF0KzaiGtWr2PzDcMGAY60KGOSA== + dependencies: + commist "^1.0.0" + concat-stream "^2.0.0" + debug "^4.1.1" + duplexify "^4.1.1" + help-me "^3.0.0" + inherits "^2.0.3" + minimist "^1.2.5" + mqtt-packet "^6.8.0" + pump "^3.0.0" + readable-stream "^3.6.0" + reinterval "^1.1.0" + split2 "^3.1.0" + ws "^7.5.0" + xtend "^4.0.2" + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -8741,6 +9042,15 @@ npm-run-path@^4.0.0: dependencies: path-key "^3.0.0" +npmlog@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-1.2.1.tgz#28e7be619609b53f7ad1dd300a10d64d716268b6" + integrity sha1-KOe+YZYJtT960d0wChDWTXFiaLY= + dependencies: + ansi "~0.3.0" + are-we-there-yet "~1.0.0" + gauge "~1.2.0" + npmlog@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" @@ -8935,6 +9245,13 @@ os-homedir@^1.0.0: resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= +os-locale@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= + dependencies: + lcid "^1.0.0" + os-name@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/os-name/-/os-name-3.1.0.tgz#dec19d966296e1cd62d701a5a66ee1ddeae70801" @@ -9417,11 +9734,16 @@ pretty-format@^26.0.0, pretty-format@^26.6.2: ansi-styles "^4.0.0" react-is "^17.0.1" -process-nextick-args@~2.0.0: +process-nextick-args@^2.0.1, process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== +process-nextick-args@~1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" + integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M= + process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" @@ -9672,6 +9994,16 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" +rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + react-is@^17.0.1: version "17.0.2" resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" @@ -9763,7 +10095,7 @@ read@1, read@~1.0.1: dependencies: mute-stream "~0.0.4" -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: +"readable-stream@1 || 2", readable-stream@^2.0.0, "readable-stream@^2.0.0 || ^1.1.13", readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -9785,6 +10117,29 @@ read@1, read@~1.0.1: string_decoder "^1.1.1" util-deprecate "^1.0.1" +readable-stream@~1.0.26-2: + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@~2.1.5: + version "2.1.5" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.1.5.tgz#66fa8b720e1438b364681f2ad1a63c618448c9d0" + integrity sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA= + dependencies: + buffer-shims "^1.0.0" + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + string_decoder "~0.10.x" + util-deprecate "~1.0.1" + readdir-scoped-modules@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz#8d45407b4f870a0dcaebc0e28670d18e74514309" @@ -9860,6 +10215,11 @@ regexpp@^3.1.0: resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== +reinterval@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/reinterval/-/reinterval-1.1.0.tgz#3361ecfa3ca6c18283380dd0bb9546f390f5ece7" + integrity sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc= + remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -9924,7 +10284,7 @@ request@2.88.0: tunnel-agent "^0.6.0" uuid "^3.3.2" -request@2.88.2, request@^2.88.0, request@^2.88.2: +request@2.88.2, request@^2.54.0, request@^2.88.0, request@^2.88.2: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -10063,7 +10423,7 @@ rfdc@^1.1.4: resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== -rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3: +rimraf@2, rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -10203,7 +10563,7 @@ semver-regex@^3.1.2: resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-3.1.2.tgz#34b4c0d361eef262e07199dbef316d0f2ab11807" integrity sha512-bXWyL6EAKOJa81XG1OZ/Yyuq+oT0b2YLlxx7c+mrdYPaPbnj6WgVULXhinMIeZGufuUBu/eVRqXEhiv4imfwxA== -"semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: +"semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", semver@^5.0.3, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -10297,7 +10657,7 @@ set-value@^2.0.0, set-value@^2.0.1: is-plain-object "^2.0.3" split-string "^3.0.1" -setimmediate@^1.0.4: +setimmediate@^1.0.4, setimmediate@~1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= @@ -10621,7 +10981,7 @@ split2@^2.0.0: dependencies: through2 "^2.0.2" -split2@^3.0.0: +split2@^3.0.0, split2@^3.1.0: version "3.2.2" resolved "https://registry.yarnpkg.com/split2/-/split2-3.2.2.tgz#bf2cf2a37d838312c249c89206fd7a17dd12365f" integrity sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg== @@ -10635,6 +10995,11 @@ split@^1.0.0: dependencies: through "2" +splitargs@0: + version "0.0.7" + resolved "https://registry.yarnpkg.com/splitargs/-/splitargs-0.0.7.tgz#fe9f7ae657371b33b10cb80da143cf8249cf6b3b" + integrity sha1-/p965lc3GzOxDLgNoUPPgknPazs= + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -10863,6 +11228,11 @@ string_decoder@^1.0.0, string_decoder@^1.1.1, string_decoder@^1.3.0: dependencies: safe-buffer "~5.2.0" +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" @@ -10958,6 +11328,11 @@ strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1. resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + strong-log-transformer@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz#0f5ed78d325e0421ac6f90f7f10e691d6ae3ae10" @@ -11051,7 +11426,7 @@ tar-stream@^2.1.4: inherits "^2.0.3" readable-stream "^3.1.1" -tar@^4.4.10, tar@^4.4.12, tar@^4.4.8: +tar@^4, tar@^4.4.10, tar@^4.4.12, tar@^4.4.8: version "4.4.19" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3" integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA== @@ -11064,6 +11439,18 @@ tar@^4.4.10, tar@^4.4.12, tar@^4.4.8: safe-buffer "^5.2.1" yallist "^3.1.1" +tar@^6.1.11: + version "6.1.11" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" + integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^3.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + teeny-request@6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/teeny-request/-/teeny-request-6.0.1.tgz#9b1f512cef152945827ba7e34f62523a4ce2c5b0" @@ -11340,6 +11727,11 @@ tr46@^2.0.2: dependencies: punycode "^2.1.1" +"traverse@>=0.3.0 <0.4": + version "0.3.9" + resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9" + integrity sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk= + trim-newlines@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" @@ -11562,6 +11954,11 @@ uid-number@0.0.6: resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" integrity sha1-DqEOgDXo61uOREnwbaHHMGY7qoE= +ultron@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" + integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== + umask@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/umask/-/umask-1.1.0.tgz#f29cebf01df517912bb58ff9c4e50fde8e33320d" @@ -11662,6 +12059,21 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" +unzipper@^0.8.13: + version "0.8.14" + resolved "https://registry.yarnpkg.com/unzipper/-/unzipper-0.8.14.tgz#ade0524cd2fc14d11b8de258be22f9d247d3f79b" + integrity sha512-8rFtE7EP5ssOwGpN2dt1Q4njl0N1hUXJ7sSPz0leU2hRdq6+pra57z4YPBlVqm40vcgv6ooKZEAx48fMTv9x4w== + dependencies: + big-integer "^1.6.17" + binary "~0.3.0" + bluebird "~3.4.1" + buffer-indexof-polyfill "~1.0.0" + duplexer2 "~0.1.4" + fstream "~1.0.10" + listenercount "~1.0.1" + readable-stream "~2.1.5" + setimmediate "~1.0.4" + upath@^1.1.1, upath@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" @@ -11684,6 +12096,11 @@ urix@^0.1.0: resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= +url-join@0: + version "0.0.1" + resolved "https://registry.yarnpkg.com/url-join/-/url-join-0.0.1.tgz#1db48ad422d3402469a87f7d97bdebfe4fb1e3c8" + integrity sha1-HbSK1CLTQCRpqH99l73r/k+x48g= + url-parse@^1.4.4: version "1.5.3" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.3.tgz#71c1303d38fb6639ade183c2992c8cc0686df862" @@ -12027,6 +12444,18 @@ webpack@^4.43.0: watchpack "^1.7.4" webpack-sources "^1.4.1" +websocket-stream@^5.5.2: + version "5.5.2" + resolved "https://registry.yarnpkg.com/websocket-stream/-/websocket-stream-5.5.2.tgz#49d87083d96839f0648f5513bbddd581f496b8a2" + integrity sha512-8z49MKIHbGk3C4HtuHWDtYX8mYej1wWabjthC/RupM9ngeukU4IWoM46dgth1UOS/T4/IqgEdCDJuMe2039OQQ== + dependencies: + duplexify "^3.5.1" + inherits "^2.0.1" + readable-stream "^2.3.3" + safe-buffer "^5.1.2" + ws "^3.2.0" + xtend "^4.0.0" + whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" @@ -12098,7 +12527,7 @@ which@2.0.2, which@^2.0.1, which@^2.0.2: dependencies: isexe "^2.0.0" -which@^1.2.1, which@^1.2.14, which@^1.2.9, which@^1.3.1: +which@^1.0.9, which@^1.2.1, which@^1.2.14, which@^1.2.9, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== @@ -12112,6 +12541,11 @@ wide-align@1.1.3, wide-align@^1.1.0: dependencies: string-width "^1.0.2 || 2" +window-size@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.4.tgz#f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876" + integrity sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY= + windows-release@^3.1.0: version "3.3.3" resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.3.3.tgz#1c10027c7225743eec6b89df160d64c2e0293999" @@ -12141,6 +12575,14 @@ workerpool@6.1.0: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.1.0.tgz#a8e038b4c94569596852de7a8ea4228eefdeb37b" integrity sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg== +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" @@ -12224,11 +12666,25 @@ write-pkg@^3.1.0: sort-keys "^2.0.0" write-json-file "^2.2.0" +ws@^3.2.0: + version "3.3.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" + integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== + dependencies: + async-limiter "~1.0.0" + safe-buffer "~5.1.0" + ultron "~1.1.0" + ws@^7.0.0, ws@^7.2.3, ws@^7.4.4, ws@~7.4.2: version "7.4.6" resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== +ws@^7.5.0: + version "7.5.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.3.tgz#160835b63c7d97bfab418fc1b8a9fced2ac01a74" + integrity sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg== + xml-name-validator@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" @@ -12256,6 +12712,11 @@ xtend@^4.0.0, xtend@^4.0.2, xtend@~4.0.0, xtend@~4.0.1: resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== +y18n@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696" + integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ== + y18n@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" @@ -12388,6 +12849,19 @@ yargs@^15.1.0, yargs@^15.3.1, yargs@^15.4.1: y18n "^4.0.0" yargs-parser "^18.1.2" +yargs@^3.6.0: + version "3.32.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.32.0.tgz#03088e9ebf9e756b69751611d2a5ef591482c995" + integrity sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU= + dependencies: + camelcase "^2.0.1" + cliui "^3.0.3" + decamelize "^1.1.1" + os-locale "^1.4.0" + string-width "^1.0.1" + window-size "^0.1.4" + y18n "^3.2.0" + yarn@1.22.10: version "1.22.10" resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.10.tgz#c99daa06257c80f8fa2c3f1490724e394c26b18c"