Skip to content

Commit 8a271be

Browse files
authored
fix(middleware-sdk-rds): double encoding the presigned url (#2711)
* fix(middleware-sdk-rds): double encoding the presigned url * fix(middleware-sdk-rds): support StartDBInstanceAutomatedBackupsReplication api According to codegen, StartDBInstanceAutomatedBackupsReplication API should be supported with cross-region copy. * fix(client-docdb): remove cross-region copy for non-applicable apis
1 parent 5249df4 commit 8a271be

File tree

5 files changed

+87
-68
lines changed

5 files changed

+87
-68
lines changed

clients/client-docdb/commands/CreateDBClusterCommand.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import {
44
deserializeAws_queryCreateDBClusterCommand,
55
serializeAws_queryCreateDBClusterCommand,
66
} from "../protocols/Aws_query";
7-
import { getCrossRegionPresignedUrlPlugin } from "@aws-sdk/middleware-sdk-rds";
87
import { getSerdePlugin } from "@aws-sdk/middleware-serde";
98
import { HttpRequest as __HttpRequest, HttpResponse as __HttpResponse } from "@aws-sdk/protocol-http";
109
import { Command as $Command } from "@aws-sdk/smithy-client";
@@ -61,7 +60,6 @@ export class CreateDBClusterCommand extends $Command<
6160
options?: __HttpHandlerOptions
6261
): Handler<CreateDBClusterCommandInput, CreateDBClusterCommandOutput> {
6362
this.middlewareStack.use(getSerdePlugin(configuration, this.serialize, this.deserialize));
64-
this.middlewareStack.use(getCrossRegionPresignedUrlPlugin(configuration));
6563

6664
const stack = clientStack.concat(this.middlewareStack);
6765

codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddCrossRegionCopyingPlugin.java

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,43 +18,41 @@
1818
import static software.amazon.smithy.typescript.codegen.integration.RuntimeClientPlugin.Convention.HAS_MIDDLEWARE;
1919

2020
import java.util.List;
21+
import java.util.Map;
2122
import java.util.Set;
23+
import java.util.stream.Collectors;
2224
import software.amazon.smithy.aws.traits.ServiceTrait;
2325
import software.amazon.smithy.model.shapes.Shape;
2426
import software.amazon.smithy.typescript.codegen.integration.RuntimeClientPlugin;
2527
import software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration;
26-
import software.amazon.smithy.utils.ListUtils;
28+
import software.amazon.smithy.utils.MapUtils;
2729
import software.amazon.smithy.utils.SetUtils;
2830
import software.amazon.smithy.utils.SmithyInternalApi;
2931

3032
@SmithyInternalApi
3133
public class AddCrossRegionCopyingPlugin implements TypeScriptIntegration {
32-
private static final Set<String> SHARED_PRESIGNED_URL_OPERATIONS = SetUtils.of(
33-
"CopyDBClusterSnapshot",
34-
"CreateDBCluster"
35-
);
36-
private static final Set<String> RDS_PRESIGNED_URL_OPERATIONS = SetUtils.of(
37-
"CopyDBSnapshot",
38-
"CreateDBInstanceReadReplica",
39-
"StartDBInstanceAutomatedBackupsReplication"
34+
private static final Map<String, Set<String>> PRESIGNED_URL_OPERATIONS_MAP = MapUtils.of(
35+
"RDS", SetUtils.of(
36+
"CopyDBClusterSnapshot",
37+
"CreateDBCluster",
38+
"CopyDBSnapshot",
39+
"CreateDBInstanceReadReplica",
40+
"StartDBInstanceAutomatedBackupsReplication"),
41+
"DocDB", SetUtils.of("CopyDBClusterSnapshot"),
42+
"Neptune", SetUtils.of("CopyDBClusterSnapshot", "CreateDBCluster")
4043
);
4144

4245
@Override
4346
public List<RuntimeClientPlugin> getClientPlugins() {
44-
return ListUtils.of(
45-
RuntimeClientPlugin.builder()
46-
.withConventions(AwsDependency.RDS_MIDDLEWARE.dependency, "CrossRegionPresignedUrl",
47-
HAS_MIDDLEWARE)
48-
.operationPredicate((m, s, o) -> RDS_PRESIGNED_URL_OPERATIONS.contains(o.getId().getName(s))
49-
&& testServiceId(s, "RDS"))
50-
.build(),
51-
RuntimeClientPlugin.builder()
52-
.withConventions(AwsDependency.RDS_MIDDLEWARE.dependency, "CrossRegionPresignedUrl",
53-
HAS_MIDDLEWARE)
54-
.operationPredicate((m, s, o) -> SHARED_PRESIGNED_URL_OPERATIONS.contains(o.getId().getName(s))
55-
&& (testServiceId(s, "RDS") || testServiceId(s, "DocDB") || testServiceId(s, "Neptune")))
56-
.build()
57-
);
47+
return PRESIGNED_URL_OPERATIONS_MAP.entrySet().stream().map((entry) -> {
48+
String serviceId = entry.getKey();
49+
Set<String> commands = entry.getValue();
50+
return RuntimeClientPlugin.builder()
51+
.withConventions(AwsDependency.RDS_MIDDLEWARE.dependency, "CrossRegionPresignedUrl", HAS_MIDDLEWARE)
52+
.operationPredicate(
53+
(m, s, o) -> commands.contains(o.getId().getName(s)) && testServiceId(s, serviceId))
54+
.build();
55+
}).collect(Collectors.toList());
5856
}
5957

6058
private static boolean testServiceId(Shape serviceShape, String expectedId) {

packages/middleware-sdk-rds/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
"@aws-sdk/signature-v4": "3.25.0",
2222
"@aws-sdk/types": "3.25.0",
2323
"@aws-sdk/util-format-url": "3.25.0",
24-
"@aws-sdk/util-uri-escape": "3.23.0",
2524
"tslib": "^2.3.0"
2625
},
2726
"devDependencies": {

packages/middleware-sdk-rds/src/index.spec.ts

Lines changed: 63 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,16 @@ describe("middleware-sdk-rds", () => {
3232
expect(middlewareOutput.input.TargetDBSnapshotIdentifier).toEqual(params.TargetDBSnapshotIdentifier);
3333
expect(middlewareOutput.input.KmsKeyId).toEqual(params.KmsKeyId);
3434
const presignedUrl = middlewareOutput.input.PreSignedUrl;
35-
expect(presignedUrl).toMatch(/https%3A%2F%2Frds\.src\-region\.amazonaws\.com%2F%3F/);
36-
expect(presignedUrl).toMatch(/Action%3DCopyDBSnapshot/);
37-
expect(presignedUrl).toMatch(/Version%3D2014\-10\-31/);
38-
expect(presignedUrl).toMatch(/X\-Amz\-Security\-Token%3Dsession/);
39-
expect(presignedUrl).toMatch(/X\-Amz\-Algorithm%3DAWS4\-HMAC\-SHA256/);
40-
expect(presignedUrl).toMatch(/X\-Amz\-SignedHeaders%3Dhost/);
41-
expect(presignedUrl).toMatch(/X\-Amz\-Credential%3D/);
42-
expect(presignedUrl).toMatch(/X\-Amz\-Date%3D/);
43-
expect(presignedUrl).toMatch(/X-Amz-Expires%3D([\d]+)/);
44-
expect(presignedUrl).toMatch(/X-Amz-Signature%3D000000/);
35+
expect(presignedUrl).toMatch(/https\:\/\/rds\.src\-region\.amazonaws\.com\/\?/);
36+
expect(presignedUrl).toMatch(/Action\=CopyDBSnapshot/);
37+
expect(presignedUrl).toMatch(/Version\=2014\-10\-31/);
38+
expect(presignedUrl).toMatch(/X\-Amz\-Security\-Token\=session/);
39+
expect(presignedUrl).toMatch(/X\-Amz\-Algorithm\=AWS4\-HMAC\-SHA256/);
40+
expect(presignedUrl).toMatch(/X\-Amz\-SignedHeaders\=host/);
41+
expect(presignedUrl).toMatch(/X\-Amz\-Credential\=/);
42+
expect(presignedUrl).toMatch(/X\-Amz\-Date\=/);
43+
expect(presignedUrl).toMatch(/X-Amz-Expires=([\d]+)/);
44+
expect(presignedUrl).toMatch(/X-Amz-Signature=000000/);
4545
});
4646

4747
it("should build CreateDBInstanceReadReplica cross origin presigned url correctly ", async () => {
@@ -57,16 +57,16 @@ describe("middleware-sdk-rds", () => {
5757
expect(middlewareOutput.input.DBInstanceIdentifier).toEqual(params.DBInstanceIdentifier);
5858
expect(middlewareOutput.input.KmsKeyId).toEqual(params.KmsKeyId);
5959
const presignedUrl = middlewareOutput.input.PreSignedUrl;
60-
expect(presignedUrl).toMatch(/https%3A%2F%2Frds\.src\-region\.amazonaws\.com%2F%3F/);
61-
expect(presignedUrl).toMatch(/Action%3DCreateDBInstanceReadReplica/);
62-
expect(presignedUrl).toMatch(/Version%3D2014\-10\-31/);
63-
expect(presignedUrl).toMatch(/X\-Amz\-Security\-Token%3Dsession/);
64-
expect(presignedUrl).toMatch(/X\-Amz\-Algorithm%3DAWS4\-HMAC\-SHA256/);
65-
expect(presignedUrl).toMatch(/X\-Amz\-SignedHeaders%3Dhost/);
66-
expect(presignedUrl).toMatch(/X\-Amz\-Credential%3D/);
67-
expect(presignedUrl).toMatch(/X\-Amz\-Date%3D/);
68-
expect(presignedUrl).toMatch(/X-Amz-Expires%3D([\d]+)/);
69-
expect(presignedUrl).toMatch(/X-Amz-Signature%3D000000/);
60+
expect(presignedUrl).toMatch(/https\:\/\/rds\.src\-region\.amazonaws\.com\/\?/);
61+
expect(presignedUrl).toMatch(/Action\=CreateDBInstanceReadReplica/);
62+
expect(presignedUrl).toMatch(/Version\=2014\-10\-31/);
63+
expect(presignedUrl).toMatch(/X\-Amz\-Security\-Token\=session/);
64+
expect(presignedUrl).toMatch(/X\-Amz\-Algorithm\=AWS4\-HMAC\-SHA256/);
65+
expect(presignedUrl).toMatch(/X\-Amz\-SignedHeaders\=host/);
66+
expect(presignedUrl).toMatch(/X\-Amz\-Credential\=/);
67+
expect(presignedUrl).toMatch(/X\-Amz\-Date\=/);
68+
expect(presignedUrl).toMatch(/X-Amz-Expires=([\d]+)/);
69+
expect(presignedUrl).toMatch(/X-Amz-Signature=000000/);
7070
});
7171

7272
it("should build CreateDBCluster cross origin presigned url correctly ", async () => {
@@ -82,16 +82,16 @@ describe("middleware-sdk-rds", () => {
8282
expect(middlewareOutput.input.DBClusterIdentifier).toEqual(params.DBClusterIdentifier);
8383
expect(middlewareOutput.input.KmsKeyId).toEqual(params.KmsKeyId);
8484
const presignedUrl = middlewareOutput.input.PreSignedUrl;
85-
expect(presignedUrl).toMatch(/https%3A%2F%2Frds\.src\-region\.amazonaws\.com%2F%3F/);
86-
expect(presignedUrl).toMatch(/Action%3DCreateDBCluster/);
87-
expect(presignedUrl).toMatch(/Version%3D2014\-10\-31/);
88-
expect(presignedUrl).toMatch(/X\-Amz\-Security\-Token%3Dsession/);
89-
expect(presignedUrl).toMatch(/X\-Amz\-Algorithm%3DAWS4\-HMAC\-SHA256/);
90-
expect(presignedUrl).toMatch(/X\-Amz\-SignedHeaders%3Dhost/);
91-
expect(presignedUrl).toMatch(/X\-Amz\-Credential%3D/);
92-
expect(presignedUrl).toMatch(/X\-Amz\-Date%3D/);
93-
expect(presignedUrl).toMatch(/X-Amz-Expires%3D([\d]+)/);
94-
expect(presignedUrl).toMatch(/X-Amz-Signature%3D000000/);
85+
expect(presignedUrl).toMatch(/https\:\/\/rds\.src\-region\.amazonaws\.com\/\?/);
86+
expect(presignedUrl).toMatch(/Action\=CreateDBCluster/);
87+
expect(presignedUrl).toMatch(/Version\=2014\-10\-31/);
88+
expect(presignedUrl).toMatch(/X\-Amz\-Security\-Token\=session/);
89+
expect(presignedUrl).toMatch(/X\-Amz\-Algorithm\=AWS4\-HMAC\-SHA256/);
90+
expect(presignedUrl).toMatch(/X\-Amz\-SignedHeaders\=host/);
91+
expect(presignedUrl).toMatch(/X\-Amz\-Credential\=/);
92+
expect(presignedUrl).toMatch(/X\-Amz\-Date\=/);
93+
expect(presignedUrl).toMatch(/X-Amz-Expires=([\d]+)/);
94+
expect(presignedUrl).toMatch(/X-Amz-Signature=000000/);
9595
});
9696

9797
it("should build CopyDBClusterSnapshot cross origin presigned url correctly ", async () => {
@@ -107,16 +107,39 @@ describe("middleware-sdk-rds", () => {
107107
expect(middlewareOutput.input.TargetDBClusterSnapshotIdentifier).toEqual(params.TargetDBClusterSnapshotIdentifier);
108108
expect(middlewareOutput.input.KmsKeyId).toEqual(params.KmsKeyId);
109109
const presignedUrl = middlewareOutput.input.PreSignedUrl;
110-
expect(presignedUrl).toMatch(/https%3A%2F%2Frds\.src\-region\.amazonaws\.com%2F%3F/);
111-
expect(presignedUrl).toMatch(/Action%3DCopyDBClusterSnapshot/);
112-
expect(presignedUrl).toMatch(/Version%3D2014\-10\-31/);
113-
expect(presignedUrl).toMatch(/X\-Amz\-Security\-Token%3Dsession/);
114-
expect(presignedUrl).toMatch(/X\-Amz\-Algorithm%3DAWS4\-HMAC\-SHA256/);
115-
expect(presignedUrl).toMatch(/X\-Amz\-SignedHeaders%3Dhost/);
116-
expect(presignedUrl).toMatch(/X\-Amz\-Credential%3D/);
117-
expect(presignedUrl).toMatch(/X\-Amz\-Date%3D/);
118-
expect(presignedUrl).toMatch(/X-Amz-Expires%3D([\d]+)/);
119-
expect(presignedUrl).toMatch(/X-Amz-Signature%3D000000/);
110+
expect(presignedUrl).toMatch(/https\:\/\/rds\.src\-region\.amazonaws\.com\/\?/);
111+
expect(presignedUrl).toMatch(/Action\=CopyDBClusterSnapshot/);
112+
expect(presignedUrl).toMatch(/Version\=2014\-10\-31/);
113+
expect(presignedUrl).toMatch(/X\-Amz\-Security\-Token\=session/);
114+
expect(presignedUrl).toMatch(/X\-Amz\-Algorithm\=AWS4\-HMAC\-SHA256/);
115+
expect(presignedUrl).toMatch(/X\-Amz\-SignedHeaders\=host/);
116+
expect(presignedUrl).toMatch(/X\-Amz\-Credential\=/);
117+
expect(presignedUrl).toMatch(/X\-Amz\-Date\=/);
118+
expect(presignedUrl).toMatch(/X-Amz-Expires=([\d]+)/);
119+
expect(presignedUrl).toMatch(/X-Amz-Signature=000000/);
120+
});
121+
122+
it("should build StartDBInstanceAutomatedBackupsReplication cross origin presigned url correctly ", async () => {
123+
const params = {
124+
SourceDBInstanceArn: arn,
125+
KmsKeyId: "000-111",
126+
};
127+
await handler({ input: params });
128+
expect(nextHandler.mock.calls.length).toBe(1);
129+
const middlewareOutput = nextHandler.mock.calls[0][0];
130+
expect(middlewareOutput.input.SourceDBInstanceArn).toEqual(params.SourceDBInstanceArn);
131+
expect(middlewareOutput.input.KmsKeyId).toEqual(params.KmsKeyId);
132+
const presignedUrl = middlewareOutput.input.PreSignedUrl;
133+
expect(presignedUrl).toMatch(/https\:\/\/rds\.src\-region\.amazonaws\.com\/\?/);
134+
expect(presignedUrl).toMatch(/Action\=StartDBInstanceAutomatedBackupsReplication/);
135+
expect(presignedUrl).toMatch(/Version\=2014\-10\-31/);
136+
expect(presignedUrl).toMatch(/X\-Amz\-Security\-Token\=session/);
137+
expect(presignedUrl).toMatch(/X\-Amz\-Algorithm\=AWS4\-HMAC\-SHA256/);
138+
expect(presignedUrl).toMatch(/X\-Amz\-SignedHeaders\=host/);
139+
expect(presignedUrl).toMatch(/X\-Amz\-Credential\=/);
140+
expect(presignedUrl).toMatch(/X\-Amz\-Date\=/);
141+
expect(presignedUrl).toMatch(/X-Amz-Expires=([\d]+)/);
142+
expect(presignedUrl).toMatch(/X-Amz-Signature=000000/);
120143
});
121144

122145
it("should not generate PreSignedUrl if source identifier is not ARN", async () => {

packages/middleware-sdk-rds/src/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import {
1414
Provider,
1515
} from "@aws-sdk/types";
1616
import { formatUrl } from "@aws-sdk/util-format-url";
17-
import { escapeUri } from "@aws-sdk/util-uri-escape";
1817

1918
const regARN = /arn:[\w+=/,.@-]+:[\w+=/,.@-]+:([\w+=/,.@-]*)?:[0-9]+:[\w+=/,.@-]+(:[\w+=/,.@-]+)?(:[\w+=/,.@-]+)?/;
2019

@@ -23,13 +22,15 @@ const sourceIds: string[] = [
2322
"SourceDBInstanceIdentifier",
2423
"ReplicationSourceIdentifier",
2524
"SourceDBClusterSnapshotIdentifier",
25+
"SourceDBInstanceArn",
2626
];
2727

2828
const sourceIdToCommandKeyMap: { [key: string]: string } = {
2929
SourceDBSnapshotIdentifier: "CopyDBSnapshot",
3030
SourceDBInstanceIdentifier: "CreateDBInstanceReadReplica",
3131
ReplicationSourceIdentifier: "CreateDBCluster",
3232
SourceDBClusterSnapshotIdentifier: "CopyDBClusterSnapshot",
33+
SourceDBInstanceArn: "StartDBInstanceAutomatedBackupsReplication",
3334
};
3435

3536
const version = "2014-10-31";
@@ -94,7 +95,7 @@ export function crossRegionPresignedUrlMiddleware(options: PreviouslyResolved):
9495
...args,
9596
input: {
9697
...args.input,
97-
PreSignedUrl: escapeUri(formatUrl(presignedRequest)),
98+
PreSignedUrl: formatUrl(presignedRequest),
9899
},
99100
};
100101
}

0 commit comments

Comments
 (0)