Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Core): Updating to AWS SDK for Swift 1.0.0 #3858

Merged
merged 11 commits into from
Sep 18, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import Amplify
import AWSPluginsCore
import InternalAmplifyCredentials
import Foundation
import ClientRuntime
import SmithyHTTPAPI
import Smithy

typealias AWSRegionType = String

Expand Down Expand Up @@ -41,12 +42,12 @@ struct IAMURLRequestInterceptor: URLRequestInterceptor {
request.setValue(userAgent, forHTTPHeaderField: URLRequestConstants.Header.userAgent)

let httpMethod = (request.httpMethod?.uppercased())
.flatMap(HttpMethodType.init(rawValue:)) ?? .get
.flatMap(HTTPMethodType.init(rawValue:)) ?? .get

let queryItems = URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems?
.map { ClientRuntime.SDKURLQueryItem(name: $0.name, value: $0.value)} ?? []
.map { URIQueryItem(name: $0.name, value: $0.value)} ?? []

let requestBuilder = SdkHttpRequestBuilder()
let requestBuilder = HTTPRequestBuilder()
.withHost(host)
.withPath(url.path)
.withQueryItems(queryItems)
Expand All @@ -66,7 +67,7 @@ struct IAMURLRequestInterceptor: URLRequestInterceptor {

guard let urlRequest = try await AmplifyAWSSignatureV4Signer().sigV4SignedRequest(
requestBuilder: requestBuilder,
credentialsProvider: iamCredentialsProvider.getCredentialsProvider(),
credentialIdentityResolver: iamCredentialsProvider.getCredentialIdentityResolver(),
signingName: signingName,
signingRegion: region,
date: Date()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ import Foundation
@_spi(WebSocket) import AWSPluginsCore
import InternalAmplifyCredentials
import Amplify
import AWSClientRuntime
import ClientRuntime
import SmithyHTTPAPI
import SmithyIdentity

class IAMAuthInterceptor {

let authProvider: CredentialsProviding
let authProvider: any AWSCredentialIdentityResolver
let region: AWSRegionType

init(_ authProvider: CredentialsProviding, region: AWSRegionType) {
init(_ authProvider: some AWSCredentialIdentityResolver, region: AWSRegionType) {
self.authProvider = authProvider
self.region = region
}
Expand All @@ -35,7 +35,7 @@ class IAMAuthInterceptor {
///
/// 1. A request is created with the IAM based auth headers (date, accept, content encoding, content type, and
/// additional headers.
let requestBuilder = SdkHttpRequestBuilder()
let requestBuilder = HTTPRequestBuilder()
.withHost(host)
.withPath(endpoint.path)
.withMethod(.post)
Expand All @@ -51,7 +51,7 @@ class IAMAuthInterceptor {
/// the request headers as authorization and security token.
do {
guard let urlRequest = try await signer.sigV4SignedRequest(requestBuilder: requestBuilder,
credentialsProvider: authProvider,
credentialIdentityResolver: authProvider,
signingName: "appsync",
signingRegion: region,
date: Date()) else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ actor AppSyncRealTimeClientFactory: AppSyncRealTimeClientFactoryProtocol {
let provider = AWSOIDCAuthProvider(authService: authService)
return AuthTokenInterceptor(getLatestAuthToken: provider.getLatestAuthToken)
case .awsIAM(let awsIAMConfiguration):
return IAMAuthInterceptor(authService.getCredentialsProvider(),
region: awsIAMConfiguration.region)
return IAMAuthInterceptor(authService.getCredentialIdentityResolver(),
region: awsIAMConfiguration.region)
case .openIDConnect:
guard let oidcAuthProvider = apiAuthProviderFactory.oidcAuthProvider() else {
throw APIError.invalidConfiguration(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import XCTest
class AWSPinpointAnalyticsPluginConfigureTests: AWSPinpointAnalyticsPluginTestBase {

override func setUp() async throws {
AWSPinpointFactory.credentialsProvider = MockCredentialsProvider()
AWSPinpointFactory.credentialIdentityResolver = MockCredentialsProvider()
try await super.setUp()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@
import Foundation
import Amplify // Amplify.Auth
import AWSPluginsCore // AuthAWSCredentialsProvider
import AWSClientRuntime // AWSClientRuntime.CredentialsProviding
import ClientRuntime // SdkHttpRequestBuilder
import AwsCommonRuntimeKit // CommonRuntimeKit.initialize()
import AWSSDKHTTPAuth // AWSSigV4Signer
import Smithy // URIQueryItem
import SmithyHTTPAPI
import SmithyHTTPAuth
import SmithyHTTPAuthAPI
import SmithyIdentity // AWSCredentialIdentity

extension AWSCognitoAuthPlugin {

Expand All @@ -29,11 +33,15 @@ extension AWSCognitoAuthPlugin {
region: region)
}
}


private static var signer = {
return AWSSigV4Signer()
}()

static func signAppSyncRequest(_ urlRequest: URLRequest,
region: Swift.String,
signingName: Swift.String = "appsync",
date: ClientRuntime.Date = Date()) async throws -> URLRequest {
date: Date = Date()) async throws -> URLRequest {
CommonRuntimeKit.initialize()

// Convert URLRequest to SDK's HTTPRequest
Expand All @@ -43,11 +51,11 @@ extension AWSCognitoAuthPlugin {
}

// Retrieve the credentials from credentials provider
let credentials: AWSClientRuntime.AWSCredentials
let credentials: AWSCredentialIdentity
let authSession = try await Amplify.Auth.fetchAuthSession()
if let awsCredentialsProvider = authSession as? AuthAWSCredentialsProvider {
let awsCredentials = try awsCredentialsProvider.getAWSCredentials().get()
credentials = awsCredentials.toAWSSDKCredentials()
credentials = try awsCredentials.toAWSSDKCredentials()
} else {
let error = AuthError.unknown("Auth session does not include AWS credentials information")
throw error
Expand All @@ -70,7 +78,7 @@ extension AWSCognitoAuthPlugin {
signingAlgorithm: .sigv4)

// Sign request
guard let httpRequest = await AWSSigV4Signer.sigV4SignedRequest(
guard let httpRequest = await signer.sigV4SignedRequest(
requestBuilder: requestBuilder,

signingConfig: signingConfig
Expand All @@ -82,15 +90,15 @@ extension AWSCognitoAuthPlugin {
return setHeaders(from: httpRequest, to: urlRequest)
}

static func setHeaders(from sdkRequest: SdkHttpRequest, to urlRequest: URLRequest) -> URLRequest {
static func setHeaders(from sdkRequest: SmithyHTTPAPI.HTTPRequest, to urlRequest: URLRequest) -> URLRequest {
var urlRequest = urlRequest
for header in sdkRequest.headers.headers {
urlRequest.setValue(header.value.joined(separator: ","), forHTTPHeaderField: header.name)
}
return urlRequest
}

static func createAppSyncSdkHttpRequestBuilder(urlRequest: URLRequest) throws -> SdkHttpRequestBuilder? {
static func createAppSyncSdkHttpRequestBuilder(urlRequest: URLRequest) throws -> HTTPRequestBuilder? {

guard let url = urlRequest.url,
let host = url.host else {
Expand All @@ -101,12 +109,12 @@ extension AWSCognitoAuthPlugin {
headers.updateValue(host, forKey: "host")

let httpMethod = (urlRequest.httpMethod?.uppercased())
.flatMap(HttpMethodType.init(rawValue:)) ?? .get
.flatMap(HTTPMethodType.init(rawValue:)) ?? .get

let queryItems = URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems?
.map { ClientRuntime.SDKURLQueryItem(name: $0.name, value: $0.value)} ?? []
.map { URIQueryItem(name: $0.name, value: $0.value)} ?? []

let requestBuilder = SdkHttpRequestBuilder()
let requestBuilder = HTTPRequestBuilder()
.withHost(host)
.withPath(url.path)
.withQueryItems(queryItems)
Expand All @@ -122,19 +130,20 @@ extension AWSCognitoAuthPlugin {

extension AWSPluginsCore.AWSCredentials {

func toAWSSDKCredentials() -> AWSClientRuntime.AWSCredentials {
func toAWSSDKCredentials() throws -> AWSCredentialIdentity {
if let tempCredentials = self as? AWSTemporaryCredentials {
return AWSClientRuntime.AWSCredentials(
return AWSCredentialIdentity(
accessKey: tempCredentials.accessKeyId,
secret: tempCredentials.secretAccessKey,
expirationTimeout: tempCredentials.expiration,
sessionToken: tempCredentials.sessionToken)
expiration: tempCredentials.expiration,
sessionToken: tempCredentials.sessionToken
)
} else {
return AWSClientRuntime.AWSCredentials(
return AWSCredentialIdentity(
accessKey: accessKeyId,
secret: secretAccessKey,
expirationTimeout: Date())
expiration: nil
)
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import ClientRuntime
import AWSClientRuntime
@_spi(PluginHTTPClientEngine) import InternalAmplifyCredentials
@_spi(InternalHttpEngineProxy) import AWSPluginsCore
import SmithyRetriesAPI
import SmithyRetries

extension AWSCognitoAuthPlugin {

Expand Down Expand Up @@ -91,7 +93,8 @@ extension AWSCognitoAuthPlugin {
case .userPools(let userPoolConfig), .userPoolsAndIdentityPools(let userPoolConfig, _):
let configuration = try CognitoIdentityProviderClient.CognitoIdentityProviderClientConfiguration(
region: userPoolConfig.region,
serviceSpecific: .init(endpointResolver: userPoolConfig.endpoint?.resolver)
signingRegion: userPoolConfig.region,
endpointResolver: userPoolConfig.endpoint?.resolver
)

if var httpClientEngineProxy = httpClientEngineProxy {
Expand All @@ -108,11 +111,14 @@ extension AWSCognitoAuthPlugin {
}

if let maxRetryUnwrapped = networkPreferences?.maxRetryCount {
configuration.retryStrategyOptions = RetryStrategyOptions(maxRetriesBase: Int(maxRetryUnwrapped))
configuration.retryStrategyOptions = RetryStrategyOptions(
backoffStrategy: ExponentialBackoffStrategy(),
maxRetriesBase: Int(maxRetryUnwrapped)
)
}

let authService = AWSAuthService()
configuration.credentialsProvider = authService.getCredentialsProvider()
configuration.awsCredentialIdentityResolver = authService.getCredentialIdentityResolver()

return CognitoIdentityProviderClient(config: configuration)
default:
Expand All @@ -133,11 +139,14 @@ extension AWSCognitoAuthPlugin {
}

if let maxRetryUnwrapped = networkPreferences?.maxRetryCount {
configuration.retryStrategyOptions = RetryStrategyOptions(maxRetriesBase: Int(maxRetryUnwrapped))
configuration.retryStrategyOptions = RetryStrategyOptions(
backoffStrategy: ExponentialBackoffStrategy(),
maxRetriesBase: Int(maxRetryUnwrapped)
)
}

let authService = AWSAuthService()
configuration.credentialsProvider = authService.getCredentialsProvider()
configuration.awsCredentialIdentityResolver = authService.getCredentialIdentityResolver()

return CognitoIdentityClient(config: configuration)
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ enum AuthChallengeType {

}

extension CognitoIdentityProviderClientTypes.ChallengeNameType {
extension CognitoIdentityProviderClientTypes.ChallengeNameType: Codable {
var authChallengeType: AuthChallengeType {
switch self {
case .customChallenge:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import Foundation
import Amplify
import AWSCognitoIdentityProvider
import AWSClientRuntime
@_spi(UnknownAWSHTTPServiceError) import AWSClientRuntime

extension ForbiddenException: AuthErrorConvertible {
var fallbackDescription: String { "Access to the requested resource is forbidden" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,26 @@

import Foundation
import Amplify
import ClientRuntime

extension ClientError: AuthErrorConvertible {
var fallbackDescription: String { "Client Error" }
import Smithy
import SmithyHTTPAPI

extension SmithyHTTPAPI.HTTPClientError: AuthErrorConvertible {
var authError: AuthError {
switch self {
case .pathCreationFailed(let message),
.queryItemCreationFailed(let message),
.serializationFailed(let message),
.dataNotFound(let message):
.queryItemCreationFailed(let message):
return .service(message, "", self)
ruisebas marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

extension Smithy.ClientError: AuthErrorConvertible {
var authError: AuthError {
switch self {
case .serializationFailed(let message),
.dataNotFound(let message),
.invalidValue(let message):
return .service(message, "Check the underlying error and try again", self)

case .authError(let message):
harsh62 marked this conversation as resolved.
Show resolved Hide resolved
return .notAuthorized(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@
import Foundation
import AWSClientRuntime
import ClientRuntime
import SmithyHTTPAPI

public typealias NetworkResult = (Result<HttpResponse, Error>) -> Void
public typealias NetworkResult = (Result<HTTPResponse, Error>) -> Void
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import ClientRuntime
@_spi(InternalAmplifyConfiguration) import Amplify
import SmithyHTTPAPI

struct UserPoolConfigurationData: Equatable {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,21 @@
// SPDX-License-Identifier: Apache-2.0
//

import AWSClientRuntime
import ClientRuntime
import AWSCognitoIdentityProvider
import SmithyHTTPAPI

struct AWSEndpointResolving: AWSCognitoIdentityProvider.EndpointResolver {
func resolve(params: AWSCognitoIdentityProvider.EndpointParams) throws -> ClientRuntime.Endpoint {
func resolve(params: AWSCognitoIdentityProvider.EndpointParams) throws -> SmithyHTTPAPI.Endpoint {
try endpoint()
}

let endpoint: () throws -> ClientRuntime.Endpoint
let endpoint: () throws -> SmithyHTTPAPI.Endpoint

init(_ endpoint: @escaping () throws -> ClientRuntime.Endpoint) {
init(_ endpoint: @escaping () throws -> SmithyHTTPAPI.Endpoint) {
self.endpoint = endpoint
}

init(_ endpoint: @escaping @autoclosure () throws -> ClientRuntime.Endpoint) {
init(_ endpoint: @escaping @autoclosure () throws -> SmithyHTTPAPI.Endpoint) {
self.endpoint = endpoint
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
//

import Foundation
import ClientRuntime
import SmithyHTTPAPI

struct EndpointResolving {
let run: (String) throws -> ClientRuntime.Endpoint
let run: (String) throws -> SmithyHTTPAPI.Endpoint
}

extension EndpointResolving {
Expand Down Expand Up @@ -37,6 +37,6 @@ extension EndpointResolving {
// Finally, let's confirm that the endpoint doesn't contain a path.
try validate((components, endpoint), with: .pathIsEmpty())

return ClientRuntime.Endpoint(host: host)
return SmithyHTTPAPI.Endpoint(host: host)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
//

@_spi(InternalHttpEngineProxy) @_spi(InternalAmplifyPluginExtension) import InternalAmplifyCredentials
import ClientRuntime
import Foundation
import SmithyHTTPAPI

protocol HttpClientEngineProxy: HTTPClient {
var target: HTTPClient? { get set }
Expand Down
Loading
Loading