diff --git a/Sources/Services/AWSPolly/PollyClient.swift b/Sources/Services/AWSPolly/PollyClient.swift index 42d8098eaff..2cdcd80c5ee 100644 --- a/Sources/Services/AWSPolly/PollyClient.swift +++ b/Sources/Services/AWSPolly/PollyClient.swift @@ -3,6 +3,9 @@ @_spi(FileBasedConfig) import AWSClientRuntime import ClientRuntime import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif import Logging public class PollyClient { @@ -481,3 +484,43 @@ extension PollyClient: PollyClientProtocol { } } + +extension PollyClient { + /// Presigns the URL for SynthesizeSpeech operation with the given input object SynthesizeSpeechInput. + /// The presigned URL will be valid for the given expiration, in seconds. + /// + /// Below is the documentation for SynthesizeSpeech operation: + /// Synthesizes UTF-8 input, plain text or SSML, to a stream of bytes. SSML input must be valid, well-formed SSML. Some alphabets might not be available with all the voices (for example, Cyrillic might not be read at all by English voices) unless phoneme mapping is used. For more information, see [How it Works](https://docs.aws.amazon.com/polly/latest/dg/how-text-to-speech-works.html). + /// + /// - Parameter input: The input object for SynthesizeSpeech operation used to construct request. + /// - Parameter expiration: The duration (in seconds) the presigned request will be valid for. + /// + /// - Returns: `Foundation.URL`: The presigned URL for SynthesizeSpeech operation. + public func presignedURLForSynthesizeSpeech(input: SynthesizeSpeechInput, expiration: Foundation.TimeInterval) async throws -> Foundation.URL { + let presignedURL = try await input.presignURL(config: config, expiration: expiration) + guard let presignedURL else { + throw ClientError.unknownError("Could not generate presigned URL for the operation SynthesizeSpeech.") + } + return presignedURL + } +} + +extension PollyClient { + /// Presigns the request for SynthesizeSpeech operation with the given input object SynthesizeSpeechInput. + /// The presigned request will be valid for the given expiration, in seconds. + /// + /// Below is the documentation for SynthesizeSpeech operation: + /// Synthesizes UTF-8 input, plain text or SSML, to a stream of bytes. SSML input must be valid, well-formed SSML. Some alphabets might not be available with all the voices (for example, Cyrillic might not be read at all by English voices) unless phoneme mapping is used. For more information, see [How it Works](https://docs.aws.amazon.com/polly/latest/dg/how-text-to-speech-works.html). + /// + /// - Parameter input: The input object for SynthesizeSpeech operation used to construct request. + /// - Parameter expiration: The duration (in seconds) the presigned request will be valid for. + /// + /// - Returns: `URLRequest`: The presigned request for SynthesizeSpeech operation. + public func presignedRequestForSynthesizeSpeech(input: SynthesizeSpeechInput, expiration: Foundation.TimeInterval) async throws -> URLRequest { + let presignedRequest = try await input.presign(config: config, expiration: expiration) + guard let presignedRequest else { + throw ClientError.unknownError("Could not presign the request for the operation SynthesizeSpeech.") + } + return try await URLRequest(sdkRequest: presignedRequest) + } +} diff --git a/Sources/Services/AWSS3/S3Client.swift b/Sources/Services/AWSS3/S3Client.swift index 164bc383889..c992ac1a4d7 100644 --- a/Sources/Services/AWSS3/S3Client.swift +++ b/Sources/Services/AWSS3/S3Client.swift @@ -3,6 +3,9 @@ @_spi(FileBasedConfig) import AWSClientRuntime import ClientRuntime import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif import Logging public class S3Client { @@ -5023,3 +5026,237 @@ extension S3Client: S3ClientProtocol { } } + +extension S3Client { + /// Presigns the URL for GetObject operation with the given input object GetObjectInput. + /// The presigned URL will be valid for the given expiration, in seconds. + /// + /// Below is the documentation for GetObject operation: + /// Retrieves objects from Amazon S3. To use GET, you must have READ access to the object. If you grant READ access to the anonymous user, you can return the object without using an authorization header. An Amazon S3 bucket has no directory hierarchy such as you would find in a typical computer file system. You can, however, create a logical hierarchy by using object key names that imply a folder structure. For example, instead of naming an object sample.jpg, you can name it photos/2006/February/sample.jpg. To get an object from such a logical hierarchy, specify the full key name for the object in the GET operation. For a virtual hosted-style request example, if you have the object photos/2006/February/sample.jpg, specify the resource as /photos/2006/February/sample.jpg. For a path-style request example, if you have the object photos/2006/February/sample.jpg in the bucket named examplebucket, specify the resource as /examplebucket/photos/2006/February/sample.jpg. For more information about request types, see [HTTP Host Header Bucket Specification](https://docs.aws.amazon.com/AmazonS3/latest/dev/VirtualHosting.html#VirtualHostingSpecifyBucket). For more information about returning the ACL of an object, see [GetObjectAcl](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectAcl.html). If the object you are retrieving is stored in the S3 Glacier Flexible Retrieval or S3 Glacier Deep Archive storage class, or S3 Intelligent-Tiering Archive or S3 Intelligent-Tiering Deep Archive tiers, before you can retrieve the object you must first restore a copy using [RestoreObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_RestoreObject.html). Otherwise, this action returns an InvalidObjectState error. For information about restoring archived objects, see [Restoring Archived Objects](https://docs.aws.amazon.com/AmazonS3/latest/dev/restoring-objects.html). Encryption request headers, like x-amz-server-side-encryption, should not be sent for GET requests if your object uses server-side encryption with Key Management Service (KMS) keys (SSE-KMS), dual-layer server-side encryption with Amazon Web Services KMS keys (DSSE-KMS), or server-side encryption with Amazon S3 managed encryption keys (SSE-S3). If your object does use these types of keys, you’ll get an HTTP 400 Bad Request error. If you encrypt an object by using server-side encryption with customer-provided encryption keys (SSE-C) when you store the object in Amazon S3, then when you GET the object, you must use the following headers: + /// + /// * x-amz-server-side-encryption-customer-algorithm + /// + /// * x-amz-server-side-encryption-customer-key + /// + /// * x-amz-server-side-encryption-customer-key-MD5 + /// + /// + /// For more information about SSE-C, see [Server-Side Encryption (Using Customer-Provided Encryption Keys)](https://docs.aws.amazon.com/AmazonS3/latest/dev/ServerSideEncryptionCustomerKeys.html). Assuming you have the relevant permission to read object tags, the response also returns the x-amz-tagging-count header that provides the count of number of tags associated with the object. You can use [GetObjectTagging](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectTagging.html) to retrieve the tag set associated with an object. Permissions You need the relevant read object (or version) permission for this operation. For more information, see [Specifying Permissions in a Policy](https://docs.aws.amazon.com/AmazonS3/latest/dev/using-with-s3-actions.html). If the object that you request doesn’t exist, the error that Amazon S3 returns depends on whether you also have the s3:ListBucket permission. If you have the s3:ListBucket permission on the bucket, Amazon S3 returns an HTTP status code 404 (Not Found) error. If you don’t have the s3:ListBucket permission, Amazon S3 returns an HTTP status code 403 ("access denied") error. Versioning By default, the GET action returns the current version of an object. To return a different version, use the versionId subresource. + /// + /// * If you supply a versionId, you need the s3:GetObjectVersion permission to access a specific version of an object. If you request a specific version, you do not need to have the s3:GetObject permission. If you request the current version without a specific version ID, only s3:GetObject permission is required. s3:GetObjectVersion permission won't be required. + /// + /// * If the current version of the object is a delete marker, Amazon S3 behaves as if the object was deleted and includes x-amz-delete-marker: true in the response. + /// + /// + /// For more information about versioning, see [PutBucketVersioning](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketVersioning.html). Overriding Response Header Values There are times when you want to override certain response header values in a GET response. For example, you might override the Content-Disposition response header value in your GET request. You can override values for a set of response headers using the following query parameters. These response header values are sent only on a successful request, that is, when status code 200 OK is returned. The set of headers you can override using these parameters is a subset of the headers that Amazon S3 accepts when you create an object. The response headers that you can override for the GET response are Content-Type, Content-Language, Expires, Cache-Control, Content-Disposition, and Content-Encoding. To override these header values in the GET response, you use the following request parameters. You must sign the request, either using an Authorization header or a presigned URL, when using these parameters. They cannot be used with an unsigned (anonymous) request. + /// + /// * response-content-type + /// + /// * response-content-language + /// + /// * response-expires + /// + /// * response-cache-control + /// + /// * response-content-disposition + /// + /// * response-content-encoding + /// + /// + /// Overriding Response Header Values If both of the If-Match and If-Unmodified-Since headers are present in the request as follows: If-Match condition evaluates to true, and; If-Unmodified-Since condition evaluates to false; then, S3 returns 200 OK and the data requested. If both of the If-None-Match and If-Modified-Since headers are present in the request as follows: If-None-Match condition evaluates to false, and; If-Modified-Since condition evaluates to true; then, S3 returns 304 Not Modified response code. For more information about conditional requests, see [RFC 7232](https://tools.ietf.org/html/rfc7232). The following operations are related to GetObject: + /// + /// * [ListBuckets](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBuckets.html) + /// + /// * [GetObjectAcl](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectAcl.html) + /// + /// - Parameter input: The input object for GetObject operation used to construct request. + /// - Parameter expiration: The duration (in seconds) the presigned request will be valid for. + /// + /// - Returns: `Foundation.URL`: The presigned URL for GetObject operation. + public func presignedURLForGetObject(input: GetObjectInput, expiration: Foundation.TimeInterval) async throws -> Foundation.URL { + let presignedURL = try await input.presignURL(config: config, expiration: expiration) + guard let presignedURL else { + throw ClientError.unknownError("Could not generate presigned URL for the operation GetObject.") + } + return presignedURL + } +} + +extension S3Client { + /// Presigns the URL for PutObject operation with the given input object PutObjectInput. + /// The presigned URL will be valid for the given expiration, in seconds. + /// + /// Below is the documentation for PutObject operation: + /// Adds an object to a bucket. You must have WRITE permissions on a bucket to add an object to it. Amazon S3 never adds partial objects; if you receive a success response, Amazon S3 added the entire object to the bucket. You cannot use PutObject to only update a single piece of metadata for an existing object. You must put the entire object with updated metadata if you want to update some values. Amazon S3 is a distributed system. If it receives multiple write requests for the same object simultaneously, it overwrites all but the last object written. To prevent objects from being deleted or overwritten, you can use [Amazon S3 Object Lock](https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-lock.html). To ensure that data is not corrupted traversing the network, use the Content-MD5 header. When you use this header, Amazon S3 checks the object against the provided MD5 value and, if they do not match, returns an error. Additionally, you can calculate the MD5 while putting an object to Amazon S3 and compare the returned ETag to the calculated MD5 value. + /// + /// * To successfully complete the PutObject request, you must have the s3:PutObject in your IAM permissions. + /// + /// * To successfully change the objects acl of your PutObject request, you must have the s3:PutObjectAcl in your IAM permissions. + /// + /// * To successfully set the tag-set with your PutObject request, you must have the s3:PutObjectTagging in your IAM permissions. + /// + /// * The Content-MD5 header is required for any request to upload an object with a retention period configured using Amazon S3 Object Lock. For more information about Amazon S3 Object Lock, see [Amazon S3 Object Lock Overview](https://docs.aws.amazon.com/AmazonS3/latest/dev/object-lock-overview.html) in the Amazon S3 User Guide. + /// + /// + /// You have four mutually exclusive options to protect data using server-side encryption in Amazon S3, depending on how you choose to manage the encryption keys. Specifically, the encryption key options are Amazon S3 managed keys (SSE-S3), Amazon Web Services KMS keys (SSE-KMS or DSSE-KMS), and customer-provided keys (SSE-C). Amazon S3 encrypts data with server-side encryption by using Amazon S3 managed keys (SSE-S3) by default. You can optionally tell Amazon S3 to encrypt data at rest by using server-side encryption with other key options. For more information, see [Using Server-Side Encryption](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingServerSideEncryption.html). When adding a new object, you can use headers to grant ACL-based permissions to individual Amazon Web Services accounts or to predefined groups defined by Amazon S3. These permissions are then added to the ACL on the object. By default, all objects are private. Only the owner has full access control. For more information, see [Access Control List (ACL) Overview](https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html) and [Managing ACLs Using the REST API](https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-using-rest-api.html). If the bucket that you're uploading objects to uses the bucket owner enforced setting for S3 Object Ownership, ACLs are disabled and no longer affect permissions. Buckets that use this setting only accept PUT requests that don't specify an ACL or PUT requests that specify bucket owner full control ACLs, such as the bucket-owner-full-control canned ACL or an equivalent form of this ACL expressed in the XML format. PUT requests that contain other ACLs (for example, custom grants to certain Amazon Web Services accounts) fail and return a 400 error with the error code AccessControlListNotSupported. For more information, see [ Controlling ownership of objects and disabling ACLs](https://docs.aws.amazon.com/AmazonS3/latest/userguide/about-object-ownership.html) in the Amazon S3 User Guide. If your bucket uses the bucket owner enforced setting for Object Ownership, all objects written to the bucket by any account will be owned by the bucket owner. By default, Amazon S3 uses the STANDARD Storage Class to store newly created objects. The STANDARD storage class provides high durability and high availability. Depending on performance needs, you can specify a different Storage Class. Amazon S3 on Outposts only uses the OUTPOSTS Storage Class. For more information, see [Storage Classes](https://docs.aws.amazon.com/AmazonS3/latest/dev/storage-class-intro.html) in the Amazon S3 User Guide. If you enable versioning for a bucket, Amazon S3 automatically generates a unique version ID for the object being stored. Amazon S3 returns this ID in the response. When you enable versioning for a bucket, if Amazon S3 receives multiple write requests for the same object simultaneously, it stores all of the objects. For more information about versioning, see [Adding Objects to Versioning-Enabled Buckets](https://docs.aws.amazon.com/AmazonS3/latest/dev/AddingObjectstoVersioningEnabledBuckets.html). For information about returning the versioning state of a bucket, see [GetBucketVersioning](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketVersioning.html). For more information about related Amazon S3 APIs, see the following: + /// + /// * [CopyObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html) + /// + /// * [DeleteObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObject.html) + /// + /// - Parameter input: The input object for PutObject operation used to construct request. + /// - Parameter expiration: The duration (in seconds) the presigned request will be valid for. + /// + /// - Returns: `Foundation.URL`: The presigned URL for PutObject operation. + public func presignedURLForPutObject(input: PutObjectInput, expiration: Foundation.TimeInterval) async throws -> Foundation.URL { + let presignedURL = try await input.presignURL(config: config, expiration: expiration) + guard let presignedURL else { + throw ClientError.unknownError("Could not generate presigned URL for the operation PutObject.") + } + return presignedURL + } +} + +extension S3Client { + /// Presigns the request for GetObject operation with the given input object GetObjectInput. + /// The presigned request will be valid for the given expiration, in seconds. + /// + /// Below is the documentation for GetObject operation: + /// Retrieves objects from Amazon S3. To use GET, you must have READ access to the object. If you grant READ access to the anonymous user, you can return the object without using an authorization header. An Amazon S3 bucket has no directory hierarchy such as you would find in a typical computer file system. You can, however, create a logical hierarchy by using object key names that imply a folder structure. For example, instead of naming an object sample.jpg, you can name it photos/2006/February/sample.jpg. To get an object from such a logical hierarchy, specify the full key name for the object in the GET operation. For a virtual hosted-style request example, if you have the object photos/2006/February/sample.jpg, specify the resource as /photos/2006/February/sample.jpg. For a path-style request example, if you have the object photos/2006/February/sample.jpg in the bucket named examplebucket, specify the resource as /examplebucket/photos/2006/February/sample.jpg. For more information about request types, see [HTTP Host Header Bucket Specification](https://docs.aws.amazon.com/AmazonS3/latest/dev/VirtualHosting.html#VirtualHostingSpecifyBucket). For more information about returning the ACL of an object, see [GetObjectAcl](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectAcl.html). If the object you are retrieving is stored in the S3 Glacier Flexible Retrieval or S3 Glacier Deep Archive storage class, or S3 Intelligent-Tiering Archive or S3 Intelligent-Tiering Deep Archive tiers, before you can retrieve the object you must first restore a copy using [RestoreObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_RestoreObject.html). Otherwise, this action returns an InvalidObjectState error. For information about restoring archived objects, see [Restoring Archived Objects](https://docs.aws.amazon.com/AmazonS3/latest/dev/restoring-objects.html). Encryption request headers, like x-amz-server-side-encryption, should not be sent for GET requests if your object uses server-side encryption with Key Management Service (KMS) keys (SSE-KMS), dual-layer server-side encryption with Amazon Web Services KMS keys (DSSE-KMS), or server-side encryption with Amazon S3 managed encryption keys (SSE-S3). If your object does use these types of keys, you’ll get an HTTP 400 Bad Request error. If you encrypt an object by using server-side encryption with customer-provided encryption keys (SSE-C) when you store the object in Amazon S3, then when you GET the object, you must use the following headers: + /// + /// * x-amz-server-side-encryption-customer-algorithm + /// + /// * x-amz-server-side-encryption-customer-key + /// + /// * x-amz-server-side-encryption-customer-key-MD5 + /// + /// + /// For more information about SSE-C, see [Server-Side Encryption (Using Customer-Provided Encryption Keys)](https://docs.aws.amazon.com/AmazonS3/latest/dev/ServerSideEncryptionCustomerKeys.html). Assuming you have the relevant permission to read object tags, the response also returns the x-amz-tagging-count header that provides the count of number of tags associated with the object. You can use [GetObjectTagging](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectTagging.html) to retrieve the tag set associated with an object. Permissions You need the relevant read object (or version) permission for this operation. For more information, see [Specifying Permissions in a Policy](https://docs.aws.amazon.com/AmazonS3/latest/dev/using-with-s3-actions.html). If the object that you request doesn’t exist, the error that Amazon S3 returns depends on whether you also have the s3:ListBucket permission. If you have the s3:ListBucket permission on the bucket, Amazon S3 returns an HTTP status code 404 (Not Found) error. If you don’t have the s3:ListBucket permission, Amazon S3 returns an HTTP status code 403 ("access denied") error. Versioning By default, the GET action returns the current version of an object. To return a different version, use the versionId subresource. + /// + /// * If you supply a versionId, you need the s3:GetObjectVersion permission to access a specific version of an object. If you request a specific version, you do not need to have the s3:GetObject permission. If you request the current version without a specific version ID, only s3:GetObject permission is required. s3:GetObjectVersion permission won't be required. + /// + /// * If the current version of the object is a delete marker, Amazon S3 behaves as if the object was deleted and includes x-amz-delete-marker: true in the response. + /// + /// + /// For more information about versioning, see [PutBucketVersioning](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketVersioning.html). Overriding Response Header Values There are times when you want to override certain response header values in a GET response. For example, you might override the Content-Disposition response header value in your GET request. You can override values for a set of response headers using the following query parameters. These response header values are sent only on a successful request, that is, when status code 200 OK is returned. The set of headers you can override using these parameters is a subset of the headers that Amazon S3 accepts when you create an object. The response headers that you can override for the GET response are Content-Type, Content-Language, Expires, Cache-Control, Content-Disposition, and Content-Encoding. To override these header values in the GET response, you use the following request parameters. You must sign the request, either using an Authorization header or a presigned URL, when using these parameters. They cannot be used with an unsigned (anonymous) request. + /// + /// * response-content-type + /// + /// * response-content-language + /// + /// * response-expires + /// + /// * response-cache-control + /// + /// * response-content-disposition + /// + /// * response-content-encoding + /// + /// + /// Overriding Response Header Values If both of the If-Match and If-Unmodified-Since headers are present in the request as follows: If-Match condition evaluates to true, and; If-Unmodified-Since condition evaluates to false; then, S3 returns 200 OK and the data requested. If both of the If-None-Match and If-Modified-Since headers are present in the request as follows: If-None-Match condition evaluates to false, and; If-Modified-Since condition evaluates to true; then, S3 returns 304 Not Modified response code. For more information about conditional requests, see [RFC 7232](https://tools.ietf.org/html/rfc7232). The following operations are related to GetObject: + /// + /// * [ListBuckets](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBuckets.html) + /// + /// * [GetObjectAcl](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectAcl.html) + /// + /// - Parameter input: The input object for GetObject operation used to construct request. + /// - Parameter expiration: The duration (in seconds) the presigned request will be valid for. + /// + /// - Returns: `URLRequest`: The presigned request for GetObject operation. + public func presignedRequestForGetObject(input: GetObjectInput, expiration: Foundation.TimeInterval) async throws -> URLRequest { + let presignedRequest = try await input.presign(config: config, expiration: expiration) + guard let presignedRequest else { + throw ClientError.unknownError("Could not presign the request for the operation GetObject.") + } + return try await URLRequest(sdkRequest: presignedRequest) + } +} + +extension S3Client { + /// Presigns the request for PutObject operation with the given input object PutObjectInput. + /// The presigned request will be valid for the given expiration, in seconds. + /// + /// Below is the documentation for PutObject operation: + /// Adds an object to a bucket. You must have WRITE permissions on a bucket to add an object to it. Amazon S3 never adds partial objects; if you receive a success response, Amazon S3 added the entire object to the bucket. You cannot use PutObject to only update a single piece of metadata for an existing object. You must put the entire object with updated metadata if you want to update some values. Amazon S3 is a distributed system. If it receives multiple write requests for the same object simultaneously, it overwrites all but the last object written. To prevent objects from being deleted or overwritten, you can use [Amazon S3 Object Lock](https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-lock.html). To ensure that data is not corrupted traversing the network, use the Content-MD5 header. When you use this header, Amazon S3 checks the object against the provided MD5 value and, if they do not match, returns an error. Additionally, you can calculate the MD5 while putting an object to Amazon S3 and compare the returned ETag to the calculated MD5 value. + /// + /// * To successfully complete the PutObject request, you must have the s3:PutObject in your IAM permissions. + /// + /// * To successfully change the objects acl of your PutObject request, you must have the s3:PutObjectAcl in your IAM permissions. + /// + /// * To successfully set the tag-set with your PutObject request, you must have the s3:PutObjectTagging in your IAM permissions. + /// + /// * The Content-MD5 header is required for any request to upload an object with a retention period configured using Amazon S3 Object Lock. For more information about Amazon S3 Object Lock, see [Amazon S3 Object Lock Overview](https://docs.aws.amazon.com/AmazonS3/latest/dev/object-lock-overview.html) in the Amazon S3 User Guide. + /// + /// + /// You have four mutually exclusive options to protect data using server-side encryption in Amazon S3, depending on how you choose to manage the encryption keys. Specifically, the encryption key options are Amazon S3 managed keys (SSE-S3), Amazon Web Services KMS keys (SSE-KMS or DSSE-KMS), and customer-provided keys (SSE-C). Amazon S3 encrypts data with server-side encryption by using Amazon S3 managed keys (SSE-S3) by default. You can optionally tell Amazon S3 to encrypt data at rest by using server-side encryption with other key options. For more information, see [Using Server-Side Encryption](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingServerSideEncryption.html). When adding a new object, you can use headers to grant ACL-based permissions to individual Amazon Web Services accounts or to predefined groups defined by Amazon S3. These permissions are then added to the ACL on the object. By default, all objects are private. Only the owner has full access control. For more information, see [Access Control List (ACL) Overview](https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html) and [Managing ACLs Using the REST API](https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-using-rest-api.html). If the bucket that you're uploading objects to uses the bucket owner enforced setting for S3 Object Ownership, ACLs are disabled and no longer affect permissions. Buckets that use this setting only accept PUT requests that don't specify an ACL or PUT requests that specify bucket owner full control ACLs, such as the bucket-owner-full-control canned ACL or an equivalent form of this ACL expressed in the XML format. PUT requests that contain other ACLs (for example, custom grants to certain Amazon Web Services accounts) fail and return a 400 error with the error code AccessControlListNotSupported. For more information, see [ Controlling ownership of objects and disabling ACLs](https://docs.aws.amazon.com/AmazonS3/latest/userguide/about-object-ownership.html) in the Amazon S3 User Guide. If your bucket uses the bucket owner enforced setting for Object Ownership, all objects written to the bucket by any account will be owned by the bucket owner. By default, Amazon S3 uses the STANDARD Storage Class to store newly created objects. The STANDARD storage class provides high durability and high availability. Depending on performance needs, you can specify a different Storage Class. Amazon S3 on Outposts only uses the OUTPOSTS Storage Class. For more information, see [Storage Classes](https://docs.aws.amazon.com/AmazonS3/latest/dev/storage-class-intro.html) in the Amazon S3 User Guide. If you enable versioning for a bucket, Amazon S3 automatically generates a unique version ID for the object being stored. Amazon S3 returns this ID in the response. When you enable versioning for a bucket, if Amazon S3 receives multiple write requests for the same object simultaneously, it stores all of the objects. For more information about versioning, see [Adding Objects to Versioning-Enabled Buckets](https://docs.aws.amazon.com/AmazonS3/latest/dev/AddingObjectstoVersioningEnabledBuckets.html). For information about returning the versioning state of a bucket, see [GetBucketVersioning](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketVersioning.html). For more information about related Amazon S3 APIs, see the following: + /// + /// * [CopyObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html) + /// + /// * [DeleteObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObject.html) + /// + /// - Parameter input: The input object for PutObject operation used to construct request. + /// - Parameter expiration: The duration (in seconds) the presigned request will be valid for. + /// + /// - Returns: `URLRequest`: The presigned request for PutObject operation. + public func presignedRequestForPutObject(input: PutObjectInput, expiration: Foundation.TimeInterval) async throws -> URLRequest { + let presignedRequest = try await input.presign(config: config, expiration: expiration) + guard let presignedRequest else { + throw ClientError.unknownError("Could not presign the request for the operation PutObject.") + } + return try await URLRequest(sdkRequest: presignedRequest) + } +} + +extension S3Client { + /// Presigns the request for UploadPart operation with the given input object UploadPartInput. + /// The presigned request will be valid for the given expiration, in seconds. + /// + /// Below is the documentation for UploadPart operation: + /// Uploads a part in a multipart upload. In this operation, you provide part data in your request. However, you have an option to specify your existing Amazon S3 object as a data source for the part you are uploading. To upload a part from an existing object, you use the [UploadPartCopy](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html) operation. You must initiate a multipart upload (see [CreateMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html)) before you can upload any part. In response to your initiate request, Amazon S3 returns an upload ID, a unique identifier, that you must include in your upload part request. Part numbers can be any number from 1 to 10,000, inclusive. A part number uniquely identifies a part and also defines its position within the object being created. If you upload a new part using the same part number that was used with a previous part, the previously uploaded part is overwritten. For information about maximum and minimum part sizes and other multipart upload specifications, see [Multipart upload limits](https://docs.aws.amazon.com/AmazonS3/latest/userguide/qfacts.html) in the Amazon S3 User Guide. To ensure that data is not corrupted when traversing the network, specify the Content-MD5 header in the upload part request. Amazon S3 checks the part data against the provided MD5 value. If they do not match, Amazon S3 returns an error. If the upload request is signed with Signature Version 4, then Amazon Web Services S3 uses the x-amz-content-sha256 header as a checksum instead of Content-MD5. For more information see [Authenticating Requests: Using the Authorization Header (Amazon Web Services Signature Version 4)](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-auth-using-authorization-header.html). Note: After you initiate multipart upload and upload one or more parts, you must either complete or abort multipart upload in order to stop getting charged for storage of the uploaded parts. Only after you either complete or abort multipart upload, Amazon S3 frees up the parts storage and stops charging you for the parts storage. For more information on multipart uploads, go to [Multipart Upload Overview](https://docs.aws.amazon.com/AmazonS3/latest/dev/mpuoverview.html) in the Amazon S3 User Guide . For information on the permissions required to use the multipart upload API, go to [Multipart Upload and Permissions](https://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html) in the Amazon S3 User Guide. Server-side encryption is for data encryption at rest. Amazon S3 encrypts your data as it writes it to disks in its data centers and decrypts it when you access it. You have three mutually exclusive options to protect data using server-side encryption in Amazon S3, depending on how you choose to manage the encryption keys. Specifically, the encryption key options are Amazon S3 managed keys (SSE-S3), Amazon Web Services KMS keys (SSE-KMS), and Customer-Provided Keys (SSE-C). Amazon S3 encrypts data with server-side encryption using Amazon S3 managed keys (SSE-S3) by default. You can optionally tell Amazon S3 to encrypt data at rest using server-side encryption with other key options. The option you use depends on whether you want to use KMS keys (SSE-KMS) or provide your own encryption key (SSE-C). If you choose to provide your own encryption key, the request headers you provide in the request must match the headers you used in the request to initiate the upload by using [CreateMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html). For more information, go to [Using Server-Side Encryption](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingServerSideEncryption.html) in the Amazon S3 User Guide. Server-side encryption is supported by the S3 Multipart Upload actions. Unless you are using a customer-provided encryption key (SSE-C), you don't need to specify the encryption parameters in each UploadPart request. Instead, you only need to specify the server-side encryption parameters in the initial Initiate Multipart request. For more information, see [CreateMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html). If you requested server-side encryption using a customer-provided encryption key (SSE-C) in your initiate multipart upload request, you must provide identical encryption information in each part upload using the following headers. + /// + /// * x-amz-server-side-encryption-customer-algorithm + /// + /// * x-amz-server-side-encryption-customer-key + /// + /// * x-amz-server-side-encryption-customer-key-MD5 + /// + /// + /// UploadPart has the following special errors: + /// + /// + /// * Code: NoSuchUpload + /// + /// * Cause: The specified multipart upload does not exist. The upload ID might be invalid, or the multipart upload might have been aborted or completed. + /// + /// * HTTP Status Code: 404 Not Found + /// + /// * SOAP Fault Code Prefix: Client + /// + /// + /// + /// + /// + /// The following operations are related to UploadPart: + /// + /// * [CreateMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html) + /// + /// * [CompleteMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html) + /// + /// * [AbortMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_AbortMultipartUpload.html) + /// + /// * [ListParts](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html) + /// + /// * [ListMultipartUploads](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListMultipartUploads.html) + /// + /// - Parameter input: The input object for UploadPart operation used to construct request. + /// - Parameter expiration: The duration (in seconds) the presigned request will be valid for. + /// + /// - Returns: `URLRequest`: The presigned request for UploadPart operation. + public func presignedRequestForUploadPart(input: UploadPartInput, expiration: Foundation.TimeInterval) async throws -> URLRequest { + let presignedRequest = try await input.presign(config: config, expiration: expiration) + guard let presignedRequest else { + throw ClientError.unknownError("Could not presign the request for the operation UploadPart.") + } + return try await URLRequest(sdkRequest: presignedRequest) + } +} diff --git a/Sources/Services/AWSSTS/STSClient.swift b/Sources/Services/AWSSTS/STSClient.swift index 8ac7825b586..ec6d0ec6e9c 100644 --- a/Sources/Services/AWSSTS/STSClient.swift +++ b/Sources/Services/AWSSTS/STSClient.swift @@ -3,6 +3,9 @@ @_spi(FileBasedConfig) import AWSClientRuntime import ClientRuntime import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif import Logging public class STSClient { @@ -462,3 +465,23 @@ extension STSClient: STSClientProtocol { } } + +extension STSClient { + /// Presigns the request for GetCallerIdentity operation with the given input object GetCallerIdentityInput. + /// The presigned request will be valid for the given expiration, in seconds. + /// + /// Below is the documentation for GetCallerIdentity operation: + /// Returns details about the IAM user or role whose credentials are used to call the operation. No permissions are required to perform this operation. If an administrator attaches a policy to your identity that explicitly denies access to the sts:GetCallerIdentity action, you can still perform this operation. Permissions are not required because the same information is returned when access is denied. To view an example response, see [I Am Not Authorized to Perform: iam:DeleteVirtualMFADevice](https://docs.aws.amazon.com/IAM/latest/UserGuide/troubleshoot_general.html#troubleshoot_general_access-denied-delete-mfa) in the IAM User Guide. + /// + /// - Parameter input: The input object for GetCallerIdentity operation used to construct request. + /// - Parameter expiration: The duration (in seconds) the presigned request will be valid for. + /// + /// - Returns: `URLRequest`: The presigned request for GetCallerIdentity operation. + public func presignedRequestForGetCallerIdentity(input: GetCallerIdentityInput, expiration: Foundation.TimeInterval) async throws -> URLRequest { + let presignedRequest = try await input.presign(config: config, expiration: expiration) + guard let presignedRequest else { + throw ClientError.unknownError("Could not presign the request for the operation GetCallerIdentity.") + } + return try await URLRequest(sdkRequest: presignedRequest) + } +} diff --git a/codegen/smithy-aws-swift-codegen/src/main/kotlin/software/amazon/smithy/aws/swift/codegen/PresignerGenerator.kt b/codegen/smithy-aws-swift-codegen/src/main/kotlin/software/amazon/smithy/aws/swift/codegen/PresignerGenerator.kt index e5e36508ea4..9e84d35e457 100644 --- a/codegen/smithy-aws-swift-codegen/src/main/kotlin/software/amazon/smithy/aws/swift/codegen/PresignerGenerator.kt +++ b/codegen/smithy-aws-swift-codegen/src/main/kotlin/software/amazon/smithy/aws/swift/codegen/PresignerGenerator.kt @@ -23,6 +23,7 @@ import software.amazon.smithy.swift.codegen.middleware.MiddlewareExecutionGenera import software.amazon.smithy.swift.codegen.middleware.MiddlewareStep import software.amazon.smithy.swift.codegen.middleware.OperationMiddleware import software.amazon.smithy.swift.codegen.model.expectShape +import software.amazon.smithy.swift.codegen.model.toUpperCamelCase data class PresignableOperation( val serviceId: String, @@ -48,6 +49,19 @@ class PresignerGenerator : SwiftIntegration { var serviceConfig = AWSServiceConfig(writer, protoCtx) renderPresigner(writer, ctx, delegator, op, inputType, serviceConfig) } + // Expose presign-request as a method for service client object + val symbol = protoCtx.symbolProvider.toSymbol(protoCtx.service) + protoCtx.delegator.useFileWriter("./${ctx.settings.moduleName}/${symbol.name}.swift") { writer -> + renderPresignAPIInServiceClient(writer, symbol.name, op, inputType) + } + } + // Import FoundationeNetworking statement with preprocessor commands + if (presignOperations.isNotEmpty()) { + val symbol = protoCtx.symbolProvider.toSymbol(protoCtx.service) + protoCtx.delegator.useFileWriter("./${ctx.settings.moduleName}/${symbol.name}.swift") { writer -> + // In Linux, Foundation.URLRequest is moved to FoundationNetworking. + writer.addImport(packageName = "FoundationNetworking", importOnlyIfCanImport = true) + } } } @@ -103,6 +117,43 @@ class PresignerGenerator : SwiftIntegration { } } + private fun renderPresignAPIInServiceClient( + writer: SwiftWriter, + clientName: String, + op: OperationShape, + inputType: String + ) { + writer.apply { + openBlock("extension $clientName {", "}") { + val params = listOf("input: $inputType", "expiration: Foundation.TimeInterval") + val returnType = "URLRequest" + renderDocForPresignAPI(this, op, inputType) + openBlock("public func presignedRequestFor${op.toUpperCamelCase()}(${params.joinToString()}) async throws -> $returnType {", "}") { + write("let presignedRequest = try await input.presign(config: config, expiration: expiration)") + openBlock("guard let presignedRequest else {", "}") { + write("throw ClientError.unknownError(\"Could not presign the request for the operation ${op.toUpperCamelCase()}.\")") + } + write("return try await URLRequest(sdkRequest: presignedRequest)") + } + } + } + } + + private fun renderDocForPresignAPI(writer: SwiftWriter, op: OperationShape, inputType: String) { + writer.apply { + write("/// Presigns the request for ${op.toUpperCamelCase()} operation with the given input object $inputType.") + write("/// The presigned request will be valid for the given expiration, in seconds.") + write("///") + write("/// Below is the documentation for ${op.toUpperCamelCase()} operation:") + writeShapeDocs(op) + write("///") + write("/// - Parameter input: The input object for ${op.toUpperCamelCase()} operation used to construct request.") + write("/// - Parameter expiration: The duration (in seconds) the presigned request will be valid for.") + write("///") + write("/// - Returns: `URLRequest`: The presigned request for ${op.toUpperCamelCase()} operation.") + } + } + private fun resolveOperationMiddleware(protocolGenerator: ProtocolGenerator, op: OperationShape, ctx: CodegenContext): OperationMiddleware { val operationMiddlewareCopy = protocolGenerator.operationMiddleware.clone() operationMiddlewareCopy.removeMiddleware(op, MiddlewareStep.FINALIZESTEP, "AWSSigningMiddleware") diff --git a/codegen/smithy-aws-swift-codegen/src/main/kotlin/software/amazon/smithy/aws/swift/codegen/customization/presignable/PresignableUrlIntegration.kt b/codegen/smithy-aws-swift-codegen/src/main/kotlin/software/amazon/smithy/aws/swift/codegen/customization/presignable/PresignableUrlIntegration.kt index 2934c62bcc4..b953730aea9 100644 --- a/codegen/smithy-aws-swift-codegen/src/main/kotlin/software/amazon/smithy/aws/swift/codegen/customization/presignable/PresignableUrlIntegration.kt +++ b/codegen/smithy-aws-swift-codegen/src/main/kotlin/software/amazon/smithy/aws/swift/codegen/customization/presignable/PresignableUrlIntegration.kt @@ -31,6 +31,7 @@ import software.amazon.smithy.swift.codegen.middleware.MiddlewareExecutionGenera import software.amazon.smithy.swift.codegen.middleware.MiddlewareStep import software.amazon.smithy.swift.codegen.middleware.OperationMiddleware import software.amazon.smithy.swift.codegen.model.expectShape +import software.amazon.smithy.swift.codegen.model.toUpperCamelCase internal val PRESIGNABLE_URL_OPERATIONS: Map> = mapOf( "com.amazonaws.polly#Parrot_v1" to setOf( @@ -70,6 +71,11 @@ class PresignableUrlIntegration(private val presignedOperations: Map + renderPresignURLAPIInServiceClient(writer, symbol.name, op, inputType) + } when (presignableOperation.operationId) { "com.amazonaws.s3#GetObject", "com.amazonaws.polly#SynthesizeSpeech" -> { renderMiddlewareClassForQueryString(ctx, delegator, op) @@ -144,6 +150,43 @@ class PresignableUrlIntegration(private val presignedOperations: Map $returnType {", "}") { + write("let presignedURL = try await input.presignURL(config: config, expiration: expiration)") + openBlock("guard let presignedURL else {", "}") { + write("throw ClientError.unknownError(\"Could not generate presigned URL for the operation ${op.toUpperCamelCase()}.\")") + } + write("return presignedURL") + } + } + } + } + + private fun renderDocForPresignURLAPI(writer: SwiftWriter, op: OperationShape, inputType: String) { + writer.apply { + write("/// Presigns the URL for ${op.toUpperCamelCase()} operation with the given input object $inputType.") + write("/// The presigned URL will be valid for the given expiration, in seconds.") + write("///") + write("/// Below is the documentation for ${op.toUpperCamelCase()} operation:") + writeShapeDocs(op) + write("///") + write("/// - Parameter input: The input object for ${op.toUpperCamelCase()} operation used to construct request.") + write("/// - Parameter expiration: The duration (in seconds) the presigned request will be valid for.") + write("///") + write("/// - Returns: `Foundation.URL`: The presigned URL for ${op.toUpperCamelCase()} operation.") + } + } + private fun resolveOperationMiddleware(protocolGenerator: ProtocolGenerator, context: ProtocolGenerator.GenerationContext, op: OperationShape): OperationMiddleware { val inputSymbol = MiddlewareShapeUtils.inputSymbol(context.symbolProvider, context.model, op) val operationMiddlewareCopy = protocolGenerator.operationMiddleware.clone()