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!: Modularize identity and auth #751

Merged
merged 9 commits into from
Jun 12, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 26 additions & 5 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ let package = Package(
.library(name: "SmithyXML", targets: ["SmithyXML"]),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added 2 new modules: SmithyIdentity and SmithyHTTPAuth.

SmithyIdentity has concrete implementation of the Identity protocol from SmithyIdentityAPI module, such as AWSCredentialIdentity. It also has non-AWS specific AWS credential identity resolver such as StaticAWSCredentialIdentityResolver.

SmithyHTTPAuth has SigV4 signing config things moved from aws-sdk-swift. Moving the actual SigV4Signer and the auth schemes (e.g., SigV4AuthScheme) is on-hold for after HTTP modularization.

.library(name: "SmithyJSON", targets: ["SmithyJSON"]),
.library(name: "SmithyFormURL", targets: ["SmithyFormURL"]),
.library(name: "SmithyIdentity", targets: ["SmithyIdentity"]),
.library(name: "SmithyIdentityAPI", targets: ["SmithyIdentityAPI"]),
.library(name: "SmithyHTTPAPI", targets: ["SmithyHTTPAPI"]),
.library(name: "SmithyHTTPAuth", targets: ["SmithyHTTPAuth"]),
.library(name: "SmithyHTTPAuthAPI", targets: ["SmithyHTTPAuthAPI"]),
.library(name: "SmithyEventStreamsAPI", targets: ["SmithyEventStreamsAPI"]),
.library(name: "SmithyEventStreamsAuthAPI", targets: ["SmithyEventStreamsAuthAPI"]),
Expand Down Expand Up @@ -65,8 +67,10 @@ let package = Package(
"SmithyXML",
"SmithyJSON",
"SmithyFormURL",
"SmithyIdentity",
"SmithyIdentityAPI",
"SmithyHTTPAPI",
"SmithyHTTPAuth",
"SmithyHTTPAuthAPI",
"SmithyEventStreamsAPI",
"SmithyEventStreams",
Expand All @@ -88,10 +92,6 @@ let package = Package(
.product(name: "AwsCommonRuntimeKit", package: "aws-crt-swift"),
]
),
.testTarget(
name: "SmithyRetriesTests",
dependencies: ["ClientRuntime", "SmithyRetriesAPI", "SmithyRetries"]
),
.target(
name: "SmithyReadWrite",
dependencies: ["SmithyTimestamps"]
Expand Down Expand Up @@ -126,6 +126,13 @@ let package = Package(
name: "SmithyTestUtil",
dependencies: ["ClientRuntime"]
),
.target(
name: "SmithyIdentity",
dependencies: [
"SmithyIdentityAPI",
.product(name: "AwsCommonRuntimeKit", package: "aws-crt-swift")
]
),
.target(
name: "SmithyIdentityAPI",
dependencies: ["Smithy"]
Expand All @@ -134,9 +141,19 @@ let package = Package(
name: "SmithyHTTPAPI",
dependencies: ["Smithy"]
),
.target(
name: "SmithyHTTPAuth",
dependencies: [
"Smithy",
"SmithyHTTPAuthAPI",
"SmithyIdentity",
"SmithyIdentityAPI",
.product(name: "AwsCommonRuntimeKit", package: "aws-crt-swift")
]
),
.target(
name: "SmithyHTTPAuthAPI",
dependencies: ["Smithy", "SmithyHTTPAPI"]
dependencies: ["Smithy", "SmithyHTTPAPI", "SmithyIdentityAPI", "SmithyChecksumsAPI"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SmithyChecksumsAPI shouldnt be a dependency here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed as pointed out

),
.target(
name: "SmithyEventStreamsAPI",
Expand Down Expand Up @@ -188,6 +205,10 @@ let package = Package(
name: "SmithyEventStreamsTests",
dependencies: ["SmithyEventStreams"]
),
.testTarget(
name: "SmithyIdentityTests",
dependencies: ["Smithy", "SmithyIdentity"]
)
].compactMap { $0 }
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import class Smithy.Context
import class SmithyHTTPAPI.SdkHttpRequestBuilder
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import statements have been made granular & updated to match new organization. No further comments will be made for this type of change.

import struct SmithyHTTPAuthAPI.SelectedAuthScheme
import protocol SmithyHTTPAuthAPI.AuthScheme
import struct SmithyHTTPAuth.DefaultIdentityResolverConfiguration

public struct AuthSchemeMiddleware<OperationStackOutput>: Middleware {
public let id: String = "AuthSchemeMiddleware"
Expand Down
21 changes: 0 additions & 21 deletions Sources/ClientRuntime/Signing/SigningAlgorithm+CRT.swift

This file was deleted.

61 changes: 61 additions & 0 deletions Sources/SmithyHTTPAuth/AWSSigningConfig.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was moved from aws-sdk-swift.

// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import class SmithyIdentity.CRTAWSCredentialIdentity
import enum SmithyHTTPAuthAPI.SigningAlgorithm
import enum SmithyHTTPAuthAPI.AWSSignedBodyHeader
import enum SmithyHTTPAuthAPI.AWSSignedBodyValue
import enum SmithyHTTPAuthAPI.AWSSignatureType
import protocol SmithyIdentity.AWSCredentialIdentityResolver
import struct Foundation.Date
import struct Foundation.Locale
import struct Foundation.TimeInterval
import struct SmithyHTTPAuthAPI.SigningFlags
import struct SmithyIdentity.AWSCredentialIdentity

public struct AWSSigningConfig {
public let credentials: AWSCredentialIdentity?
public let awsCredentialIdentityResolver: (any AWSCredentialIdentityResolver)?
public let expiration: TimeInterval
public let signedBodyHeader: AWSSignedBodyHeader
public let signedBodyValue: AWSSignedBodyValue
public let flags: SigningFlags
public let date: Date
public let service: String
public let region: String
public let shouldSignHeader: ((String) -> Bool)?
public let signatureType: AWSSignatureType
public let signingAlgorithm: SigningAlgorithm

public init(
credentials: AWSCredentialIdentity? = nil,
awsCredentialIdentityResolver: (any AWSCredentialIdentityResolver)? = nil,
expiration: TimeInterval = 0,
signedBodyHeader: AWSSignedBodyHeader = .none,
signedBodyValue: AWSSignedBodyValue,
flags: SigningFlags,
date: Date,
service: String,
region: String,
shouldSignHeader: ((String) -> Bool)? = nil,
signatureType: AWSSignatureType,
signingAlgorithm: SigningAlgorithm
) {
self.credentials = credentials
self.awsCredentialIdentityResolver = awsCredentialIdentityResolver
self.expiration = expiration
self.signedBodyHeader = signedBodyHeader
self.signedBodyValue = signedBodyValue
self.flags = flags
self.date = date
self.service = service
self.region = region
self.shouldSignHeader = shouldSignHeader
self.signatureType = signatureType
self.signingAlgorithm = signingAlgorithm
}
}
103 changes: 103 additions & 0 deletions Sources/SmithyHTTPAuth/CRTAdapters.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
//
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are all adapter methods that convert types in SmithyHTTPAuthAPI to matching CRT types.

// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import enum AwsCommonRuntimeKit.SigningAlgorithmType
import enum AwsCommonRuntimeKit.SignedBodyHeaderType
import enum AwsCommonRuntimeKit.SignedBodyValue
import enum AwsCommonRuntimeKit.SignatureType
import struct AwsCommonRuntimeKit.SigningConfig

import enum SmithyHTTPAuthAPI.SigningAlgorithm
import enum SmithyHTTPAuthAPI.AWSSignedBodyHeader
import enum SmithyHTTPAuthAPI.AWSSignedBodyValue
import enum SmithyHTTPAuthAPI.AWSSignatureType

import struct Foundation.Locale
import class SmithyIdentity.CRTAWSCredentialIdentity

extension SigningAlgorithm {
/// Convert self to CRT SigningAlgorithmType
/// - Returns: SigningAlgorithmType
public func toCRTType() -> SigningAlgorithmType {
switch self {
case .sigv4: return .signingV4
case .sigv4a: return .signingV4Asymmetric
}
}
}

extension AWSSignatureType {
public func toCRTType() -> SignatureType {
switch self {
case .requestChunk: return .requestChunk
case .requestHeaders: return .requestHeaders
case .requestQueryParams: return .requestQueryParams
case .requestTrailingHeaders: return .requestTrailingHeaders
case .requestEvent: return .requestEvent
}
}
}

extension AWSSignedBodyHeader {
func toCRTType() -> SignedBodyHeaderType {
switch self {
case .none: return .none
case .contentSha256: return .contentSha256
}
}
}

extension AWSSignedBodyValue {
func toCRTType() -> SignedBodyValue {
switch self {
case .empty: return .empty
case .emptySha256: return .emptySha256
case .unsignedPayload: return .unsignedPayload
case .streamingSha256Payload: return .streamingSha256Payload
case .streamingSha256Events: return .streamingSha256Events
case .streamingSha256PayloadTrailer: return .streamingSha256PayloadTrailer
case .streamingUnsignedPayloadTrailer: return .streamingUnSignedPayloadTrailer
}
}
}

extension AWSSigningConfig {
public func toCRTType() throws -> SigningConfig {
// Never include the Transfer-Encoding header in the signature,
// since older versions of URLSession will modify this header's value
// prior to sending a request.
//
// The Transfer-Encoding header does not affect the AWS operation being
// performed and is just there to coordinate the flow of data to the server.
//
// For all other headers, use the shouldSignHeaders block that was passed to
// determine if the header should be included in the signature. If the
// shouldSignHeaders block was not provided, then include all headers other
// than Transfer-Encoding.
let modifiedShouldSignHeader = { (name: String) in
guard name.lowercased(with: Locale(identifier: "en_US_POSIX")) != "transfer-encoding" else { return false }
return shouldSignHeader?(name) ?? true
}

return SigningConfig(
algorithm: signingAlgorithm.toCRTType(),
signatureType: signatureType.toCRTType(),
service: service,
region: region,
date: date,
credentials: try credentials.map { try CRTAWSCredentialIdentity(awsCredentialIdentity: $0) },
credentialsProvider: try awsCredentialIdentityResolver?.getCRTAWSCredentialIdentityResolver(),
expiration: expiration,
signedBodyHeader: signedBodyHeader.toCRTType(),
signedBodyValue: signedBodyValue.toCRTType(),
shouldSignHeader: modifiedShouldSignHeader,
useDoubleURIEncode: flags.useDoubleURIEncode,
shouldNormalizeURIPath: flags.shouldNormalizeURIPath,
omitSessionToken: flags.omitSessionToken
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
// SPDX-License-Identifier: Apache-2.0
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've made orders of import statements follow lexicographic order, in here and in many following files.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IDK, is there a way to have Swiftlint manage this for us?

//

import protocol SmithyIdentityAPI.IdentityResolver
import protocol SmithyHTTPAuthAPI.IdentityResolverConfiguration
import struct Smithy.Attributes
import struct Smithy.AttributeKey
import protocol SmithyIdentityAPI.IdentityResolver
import protocol SmithyIdentityAPI.IdentityResolverConfiguration

public struct DefaultIdentityResolverConfiguration: IdentityResolverConfiguration {
let identityResolvers: Attributes
Expand Down
4 changes: 1 addition & 3 deletions Sources/SmithyHTTPAuthAPI/AuthScheme.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@
// SPDX-License-Identifier: Apache-2.0
//

import struct Smithy.Attributes
import class Smithy.Context
import protocol SmithyIdentityAPI.IdentityResolver
import protocol SmithyIdentityAPI.IdentityResolverConfiguration
import struct Smithy.Attributes

public protocol AuthScheme {
var schemeID: String { get }
Expand All @@ -19,7 +18,6 @@ public protocol AuthScheme {
}

public extension AuthScheme {

func identityResolver(config: IdentityResolverConfiguration) throws -> (any IdentityResolver)? {
return try config.getIdentityResolver(schemeID: self.schemeID)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@
// SPDX-License-Identifier: Apache-2.0
//

import struct Smithy.AttributeKey
import class Smithy.Context
import struct Smithy.AttributeKey

public extension Context {

var isChunkedEligibleStream: Bool? {
get { attributes.get(key: isChunkedEligibleStreamKey) }
set { attributes.set(key: isChunkedEligibleStreamKey, value: newValue) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@
// SPDX-License-Identifier: Apache-2.0
//

import struct Smithy.AttributeKey
import class Smithy.Context
import class Smithy.ContextBuilder
import struct Foundation.TimeInterval
import struct Smithy.AttributeKey

public extension Context {

var estimatedSkew: TimeInterval? {
get { attributes.get(key: estimatedSkewKey) }
set { attributes.set(key: estimatedSkewKey, value: newValue) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@
// SPDX-License-Identifier: Apache-2.0
//

import struct Smithy.Attributes
import struct Smithy.AttributeKey
import class Smithy.Context
import class Smithy.ContextBuilder
import struct Smithy.Attributes
import struct Smithy.AttributeKey

public extension Context {

func getAuthSchemes() -> Attributes? {
return attributes.get(key: authSchemesKey)
}
Expand All @@ -36,7 +35,6 @@ public extension Context {
}

extension ContextBuilder {

@discardableResult
public func withAuthSchemeResolver(value: AuthSchemeResolver?) -> ContextBuilder {
self.attributes.set(key: authSchemeResolverKey, value: value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
// SPDX-License-Identifier: Apache-2.0
//

import Smithy
import class Smithy.Context
import class Smithy.ContextBuilder
import struct Smithy.AttributeKey

public extension Context {

Expand Down
27 changes: 27 additions & 0 deletions Sources/SmithyHTTPAuthAPI/Context/SigningPropertyKeys.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was moved from aws-sdk-swift to here.

// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import enum SmithyChecksumsAPI.ChecksumAlgorithm
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a string / have no dependency on checksums

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed as pointed out

import struct Smithy.AttributeKey
import struct Foundation.TimeInterval

public enum SigningPropertyKeys {
public static let signingName = AttributeKey<String>(name: "SigningName")
public static let signingRegion = AttributeKey<String>(name: "SigningRegion")
// Keys used to store/retrieve AWSSigningConfig fields in/from signingProperties passed to AWSSigV4Signer
public static let bidirectionalStreaming = AttributeKey<Bool>(name: "BidirectionalStreaming")
public static let checksum = AttributeKey<ChecksumAlgorithm>(name: "checksum")
public static let expiration = AttributeKey<TimeInterval>(name: "Expiration")
public static let isChunkedEligibleStream = AttributeKey<Bool>(name: "isChunkedEligibleStream")
public static let omitSessionToken = AttributeKey<Bool>(name: "OmitSessionToken")
public static let shouldNormalizeURIPath = AttributeKey<Bool>(name: "ShouldNormalizeURIPath")
public static let signatureType = AttributeKey<AWSSignatureType>(name: "SignatureType")
public static let signedBodyHeader = AttributeKey<AWSSignedBodyHeader>(name: "SignedBodyHeader")
public static let signingAlgorithm = AttributeKey<SigningAlgorithm>(name: "signingAlgorithm")
public static let unsignedBody = AttributeKey<Bool>(name: "UnsignedBody")
public static let useDoubleURIEncode = AttributeKey<Bool>(name: "UseDoubleURIEncode")
}
Loading
Loading