Skip to content

Commit 8f306bd

Browse files
authored
feat: Expose sigv4 config for presigner (#402)
1 parent 9dc8d5f commit 8f306bd

File tree

12 files changed

+93
-22
lines changed

12 files changed

+93
-22
lines changed

AWSClientRuntime/Sources/Middlewares/SigV4Middleware.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ public struct SigV4Middleware<OperationStackOutput: HttpResponseBinding,
5858
let credentials = try credentialsProvider.getCredentials()
5959

6060
let signingConfig = AWSSigningConfig(credentials: credentials,
61+
expiration: config.expiration,
6162
signedBodyHeader: config.signedBodyHeader,
6263
signedBodyValue: signedBodyValue,
6364
flags: flags,

AWSClientRuntime/Sources/Signing/SigV4Config.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public struct SigV4Config {
1212
let useDoubleURIEncode: Bool
1313
let shouldNormalizeURIPath: Bool
1414
let omitSessionToken: Bool
15+
let expiration: Int64
1516
let signedBodyHeader: AWSSignedBodyHeader
1617
let unsignedBody: Bool
1718

@@ -21,6 +22,7 @@ public struct SigV4Config {
2122
useDoubleURIEncode: Bool = true,
2223
shouldNormalizeURIPath: Bool = true,
2324
omitSessionToken: Bool = false,
25+
expiration: Int64 = 0,
2426
signedBodyHeader: AWSSignedBodyHeader = .none,
2527
unsignedBody: Bool) {
2628
self.credentialsProvider = credentialsProvider
@@ -29,6 +31,7 @@ public struct SigV4Config {
2931
self.useDoubleURIEncode = useDoubleURIEncode
3032
self.shouldNormalizeURIPath = shouldNormalizeURIPath
3133
self.omitSessionToken = omitSessionToken
34+
self.expiration = expiration
3235
self.signedBodyHeader = signedBodyHeader
3336
self.unsignedBody = unsignedBody
3437
}

codegen/smithy-aws-swift-codegen/src/main/kotlin/software/amazon/smithy/aws/swift/codegen/PresignerGenerator.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package software.amazon.smithy.aws.swift.codegen
22

33
import software.amazon.smithy.aws.swift.codegen.AWSClientRuntimeTypes.Core.AWSClientConfiguration
4+
import software.amazon.smithy.aws.swift.codegen.AWSClientRuntimeTypes.Signing.SigV4Config
45
import software.amazon.smithy.aws.swift.codegen.middleware.AWSSigningMiddleware
56
import software.amazon.smithy.aws.swift.codegen.model.traits.Presignable
6-
import software.amazon.smithy.model.knowledge.OperationIndex
77
import software.amazon.smithy.model.shapes.OperationShape
88
import software.amazon.smithy.model.shapes.ServiceShape
99
import software.amazon.smithy.swift.codegen.ClientRuntimeTypes.Http.SdkHttpRequest
@@ -14,6 +14,7 @@ import software.amazon.smithy.swift.codegen.core.CodegenContext
1414
import software.amazon.smithy.swift.codegen.core.toProtocolGenerationContext
1515
import software.amazon.smithy.swift.codegen.integration.SwiftIntegration
1616
import software.amazon.smithy.swift.codegen.middleware.MiddlewareExecutionGenerator
17+
import software.amazon.smithy.swift.codegen.middleware.MiddlewareRenderableExecutionContext
1718
import software.amazon.smithy.swift.codegen.model.expectShape
1819

1920
data class PresignableOperation(
@@ -58,11 +59,10 @@ class PresignerGenerator : SwiftIntegration {
5859
writer.addImport(AWSClientConfiguration)
5960
writer.addImport(SdkHttpRequest)
6061

61-
val operationsIndex = OperationIndex.of(ctx.model)
6262
val httpBindingResolver = protocolGenerator.getProtocolHttpBindingResolver(protocolGeneratorContext, protocolGenerator.defaultContentType)
6363

6464
writer.openBlock("extension $inputType {", "}") {
65-
writer.openBlock("public func presign(config: \$N) -> \$T {", "}", AWSClientConfiguration, SdkHttpRequest) {
65+
writer.openBlock("public func presign(config: \$N, sigv4Config: \$D) -> \$T {", "}", AWSClientConfiguration, SigV4Config, SdkHttpRequest) {
6666
writer.write("let serviceName = \"${ctx.settings.sdkId}\"")
6767
writer.write("let input = self")
6868
val operationStackName = "operation"
@@ -78,7 +78,8 @@ class PresignerGenerator : SwiftIntegration {
7878
httpBindingResolver,
7979
protocolGenerator.httpProtocolCustomizable,
8080
protocolGenerator.operationMiddleware,
81-
operationStackName
81+
operationStackName,
82+
MiddlewareRenderableExecutionContext.PRESIGNER
8283
)
8384
generator.render(op) { writer, _ ->
8485
writer.write("return nil")

codegen/smithy-aws-swift-codegen/src/main/kotlin/software/amazon/smithy/aws/swift/codegen/middleware/AWSSigningMiddleware.kt

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import software.amazon.smithy.model.traits.OptionalAuthTrait
1818
import software.amazon.smithy.swift.codegen.SwiftWriter
1919
import software.amazon.smithy.swift.codegen.middleware.MiddlewarePosition
2020
import software.amazon.smithy.swift.codegen.middleware.MiddlewareRenderable
21+
import software.amazon.smithy.swift.codegen.middleware.MiddlewareRenderableExecutionContext
2122
import software.amazon.smithy.swift.codegen.middleware.MiddlewareStep
2223
import software.amazon.smithy.swift.codegen.model.expectTrait
2324
import software.amazon.smithy.swift.codegen.model.hasTrait
@@ -37,18 +38,22 @@ open class AWSSigningMiddleware(val paramsCallback: AWSSigningMiddlewareParamsCa
3738
symbolProvider: SymbolProvider,
3839
writer: SwiftWriter,
3940
op: OperationShape,
40-
operationStackName: String
41+
operationStackName: String,
42+
executionContext: MiddlewareRenderableExecutionContext
4143
) {
42-
renderConfigDeclaration(writer, op)
44+
renderConfigDeclaration(writer, op, executionContext)
4345
writer.write(
4446
"$operationStackName.${middlewareStep.stringValue()}.intercept(position: ${position.stringValue()}, middleware: \$N(config: sigv4Config))",
4547
AWSClientRuntimeTypes.Signing.SigV4Middleware
4648
)
4749
}
4850

49-
private fun renderConfigDeclaration(writer: SwiftWriter, op: OperationShape) {
51+
private fun renderConfigDeclaration(writer: SwiftWriter, op: OperationShape, executionContext: MiddlewareRenderableExecutionContext) {
5052
writer.addImport(SigV4Config)
51-
writer.write("let sigv4Config = \$N(${middlewareParamsString(op)})", SigV4Config)
53+
when (executionContext) {
54+
MiddlewareRenderableExecutionContext.PRESIGNER -> writer.write("let sigv4Config = sigv4Config ?? \$N(${middlewareParamsString(op)})", SigV4Config)
55+
else -> writer.write("let sigv4Config = \$N(${middlewareParamsString(op)})", SigV4Config)
56+
}
5257
}
5358

5459
private fun middlewareParamsString(op: OperationShape): String {

codegen/smithy-aws-swift-codegen/src/main/kotlin/software/amazon/smithy/aws/swift/codegen/middleware/AWSXAmzTargetMiddleware.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import software.amazon.smithy.swift.codegen.ServiceGenerator
1414
import software.amazon.smithy.swift.codegen.SwiftWriter
1515
import software.amazon.smithy.swift.codegen.middleware.MiddlewarePosition
1616
import software.amazon.smithy.swift.codegen.middleware.MiddlewareRenderable
17+
import software.amazon.smithy.swift.codegen.middleware.MiddlewareRenderableExecutionContext
1718
import software.amazon.smithy.swift.codegen.middleware.MiddlewareStep
1819

1920
class AWSXAmzTargetMiddleware(val serviceShape: ServiceShape) : MiddlewareRenderable {
@@ -29,7 +30,8 @@ class AWSXAmzTargetMiddleware(val serviceShape: ServiceShape) : MiddlewareRender
2930
symbolProvider: SymbolProvider,
3031
writer: SwiftWriter,
3132
op: OperationShape,
32-
operationStackName: String
33+
operationStackName: String,
34+
executionContext: MiddlewareRenderableExecutionContext
3335
) {
3436
val inputShapeName = ServiceGenerator.getOperationInputShapeName(symbolProvider, model, op)
3537
val outputShapeName = ServiceGenerator.getOperationOutputShapeName(symbolProvider, model, op)

codegen/smithy-aws-swift-codegen/src/main/kotlin/software/amazon/smithy/aws/swift/codegen/middleware/EndpointResolverMiddleware.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import software.amazon.smithy.model.shapes.OperationShape
1212
import software.amazon.smithy.swift.codegen.SwiftWriter
1313
import software.amazon.smithy.swift.codegen.middleware.MiddlewarePosition
1414
import software.amazon.smithy.swift.codegen.middleware.MiddlewareRenderable
15+
import software.amazon.smithy.swift.codegen.middleware.MiddlewareRenderableExecutionContext
1516
import software.amazon.smithy.swift.codegen.middleware.MiddlewareStep
1617

1718
class EndpointResolverMiddleware : MiddlewareRenderable {
@@ -22,7 +23,7 @@ class EndpointResolverMiddleware : MiddlewareRenderable {
2223

2324
override val position = MiddlewarePosition.BEFORE
2425

25-
override fun render(model: Model, symbolProvider: SymbolProvider, writer: SwiftWriter, op: OperationShape, operationStackName: String) {
26+
override fun render(model: Model, symbolProvider: SymbolProvider, writer: SwiftWriter, op: OperationShape, operationStackName: String, executionContext: MiddlewareRenderableExecutionContext) {
2627
writer.write("$operationStackName.${middlewareStep.stringValue()}.intercept(position: ${position.stringValue()}, middleware: \$N(${middlewareParamsString()}))", AWSClientRuntimeTypes.Core.EndpointResolverMiddleware)
2728
}
2829

codegen/smithy-aws-swift-codegen/src/main/kotlin/software/amazon/smithy/aws/swift/codegen/middleware/MutateHeadersMiddleware.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import software.amazon.smithy.swift.codegen.ClientRuntimeTypes
77
import software.amazon.smithy.swift.codegen.SwiftWriter
88
import software.amazon.smithy.swift.codegen.middleware.MiddlewarePosition
99
import software.amazon.smithy.swift.codegen.middleware.MiddlewareRenderable
10+
import software.amazon.smithy.swift.codegen.middleware.MiddlewareRenderableExecutionContext
1011
import software.amazon.smithy.swift.codegen.middleware.MiddlewareStep
1112

1213
class MutateHeadersMiddleware(
@@ -20,7 +21,7 @@ class MutateHeadersMiddleware(
2021

2122
override val position = MiddlewarePosition.AFTER
2223

23-
override fun render(model: Model, symbolProvider: SymbolProvider, writer: SwiftWriter, op: OperationShape, operationStackName: String) {
24+
override fun render(model: Model, symbolProvider: SymbolProvider, writer: SwiftWriter, op: OperationShape, operationStackName: String, executionContext: MiddlewareRenderableExecutionContext) {
2425
val paramsString = middlewareParamsString()
2526
writer.write("$operationStackName.${middlewareStep.stringValue()}.intercept(position: ${position.stringValue()}, middleware: \$N($paramsString))", ClientRuntimeTypes.Middleware.MutateHeadersMiddleware)
2627
}

codegen/smithy-aws-swift-codegen/src/main/kotlin/software/amazon/smithy/aws/swift/codegen/middleware/RetryMiddleware.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import software.amazon.smithy.model.shapes.OperationShape
1212
import software.amazon.smithy.swift.codegen.SwiftWriter
1313
import software.amazon.smithy.swift.codegen.middleware.MiddlewarePosition
1414
import software.amazon.smithy.swift.codegen.middleware.MiddlewareRenderable
15+
import software.amazon.smithy.swift.codegen.middleware.MiddlewareRenderableExecutionContext
1516
import software.amazon.smithy.swift.codegen.middleware.MiddlewareStep
1617

1718
class RetryMiddleware : MiddlewareRenderable {
@@ -22,7 +23,7 @@ class RetryMiddleware : MiddlewareRenderable {
2223

2324
override val position = MiddlewarePosition.AFTER
2425

25-
override fun render(model: Model, symbolProvider: SymbolProvider, writer: SwiftWriter, op: OperationShape, operationStackName: String) {
26+
override fun render(model: Model, symbolProvider: SymbolProvider, writer: SwiftWriter, op: OperationShape, operationStackName: String, executionContext: MiddlewareRenderableExecutionContext) {
2627
writer.write("$operationStackName.${middlewareStep.stringValue()}.intercept(position: ${position.stringValue()}, middleware: \$N(${middlewareParamsString()}))", AWSClientRuntimeTypes.Core.RetryerMiddleware)
2728
}
2829

codegen/smithy-aws-swift-codegen/src/main/kotlin/software/amazon/smithy/aws/swift/codegen/middleware/UserAgentMiddleware.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import software.amazon.smithy.swift.codegen.SwiftSettings
1313
import software.amazon.smithy.swift.codegen.SwiftWriter
1414
import software.amazon.smithy.swift.codegen.middleware.MiddlewarePosition
1515
import software.amazon.smithy.swift.codegen.middleware.MiddlewareRenderable
16+
import software.amazon.smithy.swift.codegen.middleware.MiddlewareRenderableExecutionContext
1617
import software.amazon.smithy.swift.codegen.middleware.MiddlewareStep
1718

1819
class UserAgentMiddleware(val settings: SwiftSettings) : MiddlewareRenderable {
@@ -23,7 +24,7 @@ class UserAgentMiddleware(val settings: SwiftSettings) : MiddlewareRenderable {
2324

2425
override val position = MiddlewarePosition.BEFORE
2526

26-
override fun render(model: Model, symbolProvider: SymbolProvider, writer: SwiftWriter, op: OperationShape, operationStackName: String) {
27+
override fun render(model: Model, symbolProvider: SymbolProvider, writer: SwiftWriter, op: OperationShape, operationStackName: String, executionContext: MiddlewareRenderableExecutionContext) {
2728
writer.write("$operationStackName.${middlewareStep.stringValue()}.intercept(position: ${position.stringValue()}, middleware: \$N(${middlewareParamsString()}))", AWSClientRuntimeTypes.Core.UserAgentMiddleware)
2829
}
2930

codegen/smithy-aws-swift-codegen/src/test/kotlin/software/amazon/smithy/aws/swift/codegen/AWSSigningMiddlewareTests.kt

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import software.amazon.smithy.model.traits.AuthTrait
2020
import software.amazon.smithy.model.traits.HttpBasicAuthTrait
2121
import software.amazon.smithy.model.traits.OptionalAuthTrait
2222
import software.amazon.smithy.swift.codegen.SwiftWriter
23+
import software.amazon.smithy.swift.codegen.middleware.MiddlewareRenderableExecutionContext
2324

2425
class AWSSigningMiddlewareTests {
2526
@Test
@@ -87,7 +88,7 @@ stack.finalizeStep.intercept(position: .before, middleware: AWSClientRuntime.Sig
8788
val opStackName = "stack"
8889
val sut = AWSSigningMiddleware()
8990

90-
sut.render(context.model, context.symbolProvider, writer, operationShape, opStackName)
91+
sut.render(context.model, context.symbolProvider, writer, operationShape, opStackName, MiddlewareRenderableExecutionContext.CLIENT)
9192

9293
val contents = writer.toString()
9394
contents.shouldContainOnlyOnce(expectedContents)
@@ -113,7 +114,60 @@ stack.finalizeStep.intercept(position: .before, middleware: AWSClientRuntime.Sig
113114
val opStackName = "stack"
114115
val sut = AWSSigningMiddleware()
115116

116-
sut.render(context.model, context.symbolProvider, writer, operationShape, opStackName)
117+
sut.render(context.model, context.symbolProvider, writer, operationShape, opStackName, MiddlewareRenderableExecutionContext.CLIENT)
118+
119+
val contents = writer.toString()
120+
contents.shouldContainOnlyOnce(expectedContents)
121+
}
122+
123+
@Test
124+
fun `renderSigningMiddleware unsignedBody true, presigner`() {
125+
val expectedContents =
126+
"""
127+
let sigv4Config = sigv4Config ?? AWSClientRuntime.SigV4Config(unsignedBody: true)
128+
stack.finalizeStep.intercept(position: .before, middleware: AWSClientRuntime.SigV4Middleware(config: sigv4Config))"""
129+
val writer = SwiftWriter("testName")
130+
val serviceShape = ServiceShape.builder()
131+
.id("com.test#Example")
132+
.version("1.0")
133+
.addTrait(SigV4Trait.builder().name("ExampleService").build())
134+
.build()
135+
val operationShape = OperationShape.builder()
136+
.id("com.test#ExampleOperation")
137+
.addTrait(UnsignedPayloadTrait())
138+
.build()
139+
val model = Model.builder().addShape(serviceShape).addShape(operationShape).build()
140+
val context = model.newTestContext(generator = AWSRestJson1ProtocolGenerator()).ctx
141+
val opStackName = "stack"
142+
val sut = AWSSigningMiddleware()
143+
144+
sut.render(context.model, context.symbolProvider, writer, operationShape, opStackName, MiddlewareRenderableExecutionContext.PRESIGNER)
145+
146+
val contents = writer.toString()
147+
contents.shouldContainOnlyOnce(expectedContents)
148+
}
149+
150+
@Test
151+
fun `renderSigningMiddleware unsignedBody false, presigner`() {
152+
val expectedContents =
153+
"""
154+
let sigv4Config = sigv4Config ?? AWSClientRuntime.SigV4Config(unsignedBody: false)
155+
stack.finalizeStep.intercept(position: .before, middleware: AWSClientRuntime.SigV4Middleware(config: sigv4Config))"""
156+
val writer = SwiftWriter("testName")
157+
val serviceShape = ServiceShape.builder()
158+
.id("com.test#Example")
159+
.version("1.0")
160+
.addTrait(SigV4Trait.builder().name("ExampleService").build())
161+
.build()
162+
val operationShape = OperationShape.builder()
163+
.id("com.test#ExampleOperation")
164+
.build()
165+
val model = Model.builder().addShape(serviceShape).addShape(operationShape).build()
166+
val context = model.newTestContext(generator = AWSRestJson1ProtocolGenerator()).ctx
167+
val opStackName = "stack"
168+
val sut = AWSSigningMiddleware()
169+
170+
sut.render(context.model, context.symbolProvider, writer, operationShape, opStackName, MiddlewareRenderableExecutionContext.PRESIGNER)
117171

118172
val contents = writer.toString()
119173
contents.shouldContainOnlyOnce(expectedContents)

0 commit comments

Comments
 (0)