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: middleware changes #605

Merged
merged 46 commits into from
Oct 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
86c7d2c
Add signer protocol.
Oct 4, 2023
5eb2c8d
Add http context changes.
Oct 4, 2023
75646fc
Swiftlint issues.
Oct 4, 2023
dd339a0
Fix swiftlint.
Oct 4, 2023
f5808fa
Add identity type
Oct 4, 2023
6371b28
Use nil coalescing operator to check attribute existence
Oct 4, 2023
9327f98
Clean up changes.
Oct 4, 2023
9b7b4c5
New protocols and structs.
Oct 4, 2023
cebf798
New middlewares.
Oct 4, 2023
d7040f5
Merge branch 'feat/auth-scheme-changes' into feat/middleware-changes
Oct 4, 2023
39b386e
Delete auth scheme related change.
Oct 4, 2023
8d90e28
Update signer middleware
Oct 4, 2023
d87e82f
Update selected auth scheme
Oct 4, 2023
ad8cd2c
Change signer protocol to use generic instead of associatedtype
Oct 4, 2023
61b79a6
merge commit
Oct 4, 2023
37a66b5
Merge branch 'feat/auth-scheme-changes' into feat/middleware-changes
Oct 4, 2023
cca514b
Add back identity type and aws id resolver key
Oct 4, 2023
b73adf0
Merge branch 'feat/auth-scheme-changes' into feat/middleware-changes
Oct 4, 2023
1205170
Finish rough draft of middlewares
Oct 4, 2023
5bf2df2
Provide hook in auth scheme for signing properties customization.
Oct 5, 2023
a05e6cd
Rename field.
Oct 5, 2023
9420eb6
Merge branch 'feat/auth-scheme-changes' into feat/middleware-changes
Oct 5, 2023
1bd5ac5
Change attribute keys namespace from struct to enum.
Oct 5, 2023
99323e6
Merge attribute key namespace change.
Oct 6, 2023
1f7d2ac
Add auth scheme resolver to httpcontext, and change return values of …
Oct 6, 2023
6476d09
Merge branch 'feat/auth-scheme-changes' into feat/middleware-changes
Oct 6, 2023
a71a09e
Update to match optional return type of middleware context.
Oct 6, 2023
00ebb21
Remove ASR and ASRP from AS middleware constructor. Retrieve ASR from…
Oct 6, 2023
422721c
Add method to ASR protocol, used in AS middleware to construct servi…
Oct 6, 2023
bda4f75
Merge branch 'feat/auth-scheme-changes' into feat/middleware-changes
Oct 6, 2023
337f7b6
Typo.
Oct 6, 2023
9e044dd
Merge main to authscheme branch.
Oct 9, 2023
f7f9e0e
Swiftlint resolved & additional comment.
Oct 9, 2023
d54fda8
Add clarification to attribute key.
Oct 9, 2023
111d8d6
Merge branch 'feat/auth-scheme-changes' into feat/middleware-changes
Oct 9, 2023
b0b7d9e
Resolve PR comments.
Oct 11, 2023
1794543
Update enum name in one more place.
Oct 11, 2023
07ff3ca
More places where identityType is changed to identityKind.
Oct 11, 2023
e0a6146
Remove unnecessary imports.
Oct 11, 2023
99e2ec2
Merge feat/auth-scheme-changes.
Oct 11, 2023
dd4324b
Change schemeId to schemeID in auth scheme too.
Oct 11, 2023
dbe5b19
Merge branch 'feat/auth-scheme-changes' into feat/middleware-changes
Oct 11, 2023
b47a4a9
Change schemeId to schemeID.
Oct 11, 2023
4ac7de3
Merge feat/sra-identity-and-auth.
Oct 18, 2023
e89eea7
Clean up middlewares.
Oct 18, 2023
1bd6ba5
Fix swiftlint.
Oct 18, 2023
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
3 changes: 3 additions & 0 deletions Sources/ClientRuntime/Auth/HTTPAuthAPI/AuthScheme.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ public protocol AuthScheme {
var schemeID: String { get }
var signer: Signer { get }
var idKind: IdentityKind { get }

// Hook used by AuthSchemeMiddleware that allows signing properties customization, if needed by an auth scheme
func customizeSigningProperties(signingProperties: Attributes, context: HttpContext) -> Attributes
}

extension AuthScheme {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import Foundation

public struct AuthSchemeMiddleware<OperationStackOutput: HttpResponseBinding,
OperationStackOutputError: HttpResponseErrorBinding>: Middleware {
public let id: String = "AuthSchemeMiddleware"

public init () {}

public typealias MInput = SdkHttpRequestBuilder
public typealias MOutput = OperationOutput<OperationStackOutput>
public typealias Context = HttpContext

public func handle<H>(context: HttpContext,
input: SdkHttpRequestBuilder,
next: H) async throws -> OperationOutput<OperationStackOutput>
where H: Handler,
Self.Context == H.Context,
Self.MInput == H.Input,
Self.MOutput == H.Output {
// Get auth scheme resolver from middleware context
guard let resolver = context.getAuthSchemeResolver() else {
throw ClientError.authError("No auth scheme resolver has been configured on the service.")
}

// Construct auth scheme resolver parameters
let resolverParams = try resolver.constructParameters(context: context)
// Retrieve valid auth options for the operation at hand
let validAuthOptions = resolver.resolveAuthScheme(params: resolverParams)

// Create IdentityResolverConfiguration
guard let identityResolvers = context.getIdentityResolvers() else {
throw ClientError.authError("No identity resolver has been configured on the service.")
}
let identityResolverConfig = DefaultIdentityResolverConfiguration(configuredIdResolvers: identityResolvers)

// Get auth schemes configured on the service
// If none is confugred, create empty Attributes object
let validAuthSchemes = context.getAuthSchemes() ?? Attributes()

// Variable for selected auth scheme
var selectedAuthScheme: SelectedAuthScheme?

// Error message to throw if no auth scheme can be resolved
var log: [String] = []

// For each auth option returned by auth scheme resolver:
for option in validAuthOptions {
// If current auth option is noAuth, set selectedAuthScheme with nil fields and break
if option.schemeID == "smithy.api#noAuth" {
selectedAuthScheme = SelectedAuthScheme(
schemeID: option.schemeID,
identity: nil,
signingProperties: nil,
signer: nil
)
break
}
// Otherwise,
// 1) check if corresponding auth scheme for current auth option is configured on the service, then
// 2) check if corresponding identity resolver for the auth scheme is configured
// If both 1 & 2 are satisfied, resolve auth scheme and save to selectedAuthScheme
if let authScheme = validAuthSchemes.get(key: AttributeKey<AuthScheme>(name: "\(option.schemeID)")) {
if let identityResolver = authScheme.identityResolver(config: identityResolverConfig) {
// Hook for auth scheme to customize signing properties
let signingProperties = authScheme.customizeSigningProperties(
signingProperties: option.signingProperties,
context: context
)
// Resolve identity using the resolver from auth scheme
let identity = try await identityResolver.getIdentity(identityProperties: option.identityProperties)
// Save selected auth scheme
selectedAuthScheme = SelectedAuthScheme(
schemeID: option.schemeID,
identity: identity,
signingProperties: signingProperties,
signer: authScheme.signer
)
break
} else {
log.append("Auth scheme \(option.schemeID) did not have an identity resolver configured.")
}
} else {
log.append("Auth scheme \(option.schemeID) was not enabled for this request.")
}
}

// If no auth scheme could be resolved, throw an error
guard let selectedAuthScheme else {
throw ClientError.authError(
"Could not resolve auth scheme for the operation call.\nLog:\n\(log.joined(separator: "\n"))"
)
}

// Set the selected auth scheme in context for subsequent middleware access, then pass to next middleware in chain
return try await next.handle(
context: context.toBuilder().withSelectedAuthScheme(value: selectedAuthScheme).build(), input: input
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//

import Foundation

public struct SignerMiddleware<OperationStackOutput: HttpResponseBinding,
OperationStackError: HttpResponseErrorBinding>: Middleware {
public let id: String = "SignerMiddleware"

public init () {}

public typealias MInput = SdkHttpRequestBuilder
public typealias MOutput = OperationOutput<OperationStackOutput>
public typealias Context = HttpContext

public func handle<H>(context: HttpContext,
input: SdkHttpRequestBuilder,
next: H) async throws -> OperationOutput<OperationStackOutput>
where H: Handler,
Self.Context == H.Context,
Self.MInput == H.Input,
Self.MOutput == H.Output {
// Retrieve selected auth scheme from context
guard let selectedAuthScheme = context.getSelectedAuthScheme() else {
throw ClientError.authError("Auth scheme needed by signer middleware was not saved properly.")
}

// Return without signing request if resolved auth scheme is of noAuth type
guard selectedAuthScheme.schemeID != "smithy.api#noAuth" else {
return try await next.handle(context: context, input: input)
}

// Retrieve identity, signer, and signing properties from selected auth scheme to sign the request.
guard let identity = selectedAuthScheme.identity else {
throw ClientError.authError(
"Identity needed by signer middleware was not properly saved into loaded auth scheme."
)
}
guard let signer = selectedAuthScheme.signer else {
throw ClientError.authError(
"Signer needed by signer middleware was not properly saved into loaded auth scheme."
)
}
guard let signingProperties = selectedAuthScheme.signingProperties else {
throw ClientError.authError(
"Signing properties object needed by signer middleware was not properly saved into loaded auth scheme."
)
}

// Sign request and hand over to next middleware (handler) in line.
let signedInput = try await signer.sign(
requestBuilder: input, identity: identity, signingProperties: signingProperties
)
return try await next.handle(context: context, input: signedInput)
}
}
Loading