Skip to content

Commit a7592c3

Browse files
committed
feat(codegen): support SigV4 for non AWS services
Write `signingName` from the SigV4 trait. `region` is used for the signingRegion. A separate CustomAwsAuth is used for SigV4 logic for non AWS services.
1 parent fed4969 commit a7592c3

File tree

4 files changed

+59
-11
lines changed

4 files changed

+59
-11
lines changed

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

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
package software.amazon.smithy.aws.typescript.codegen;
1717

18+
import static software.amazon.smithy.aws.typescript.codegen.AwsTraitsUtils.isAwsService;
1819
import static software.amazon.smithy.aws.typescript.codegen.AwsTraitsUtils.isSigV4Service;
1920
import static software.amazon.smithy.typescript.codegen.integration.RuntimeClientPlugin.Convention.HAS_CONFIG;
2021
import static software.amazon.smithy.typescript.codegen.integration.RuntimeClientPlugin.Convention.HAS_MIDDLEWARE;
@@ -26,6 +27,7 @@
2627
import java.util.function.BiConsumer;
2728
import java.util.function.Consumer;
2829
import software.amazon.smithy.aws.traits.ServiceTrait;
30+
import software.amazon.smithy.aws.traits.auth.SigV4Trait;
2931
import software.amazon.smithy.codegen.core.SymbolProvider;
3032
import software.amazon.smithy.model.Model;
3133
import software.amazon.smithy.model.knowledge.TopDownIndex;
@@ -48,7 +50,6 @@
4850
/**
4951
* Configure clients with AWS auth configurations and plugin.
5052
*/
51-
// TODO: Think about AWS Auth supported for only some operations and not all, when not AWS service, with say @auth([])
5253
@SmithyInternalApi
5354
public final class AddAwsAuthPlugin implements TypeScriptIntegration {
5455
static final String STS_CLIENT_PREFIX = "sts-client-";
@@ -67,21 +68,36 @@ public void addConfigInterfaceFields(
6768
if (!isSigV4Service(service)) {
6869
return;
6970
}
71+
72+
// TODO: Is it ok to do this for AWS services?
73+
writer.writeDocs("The service name to use as the signing service for AWS Auth")
74+
.write("signingName?: string;\n");
75+
7076
if (!areAllOptionalAuthOperations(model, service)) {
7177
writer.addImport("Credentials", "__Credentials", TypeScriptDependency.AWS_SDK_TYPES.packageName);
7278
writer.writeDocs("Default credentials provider; Not available in browser runtime.")
7379
.write("credentialDefaultProvider?: (input: any) => __Provider<__Credentials>;\n");
7480
}
7581
}
7682

83+
// Only one of AwsAuth or CustomAuth should be used
84+
// AwsAuth - for AWS services
85+
// CustomAwsAuth - for non AWS services. Is there a better name?
7786
@Override
7887
public List<RuntimeClientPlugin> getClientPlugins() {
7988
return ListUtils.of(
8089
RuntimeClientPlugin.builder()
8190
.withConventions(AwsDependency.MIDDLEWARE_SIGNING.dependency, "AwsAuth", HAS_CONFIG)
8291
.servicePredicate((m, s) -> isSigV4Service(s)
83-
&& !areAllOptionalAuthOperations(m, s)
84-
&& !testServiceId(s, "STS"))
92+
&& isAwsService(s)
93+
&& !testServiceId(s, "STS")
94+
&& !areAllOptionalAuthOperations(m, s))
95+
.build(),
96+
RuntimeClientPlugin.builder()
97+
.withConventions(AwsDependency.MIDDLEWARE_SIGNING.dependency, "CustomAwsAuth", HAS_CONFIG)
98+
.servicePredicate((m, s) -> isSigV4Service(s)
99+
&& !isAwsService(s)
100+
&& !areAllOptionalAuthOperations(m, s))
85101
.build(),
86102
RuntimeClientPlugin.builder()
87103
.withConventions(AwsDependency.STS_MIDDLEWARE.dependency,
@@ -92,13 +108,31 @@ public List<RuntimeClientPlugin> getClientPlugins() {
92108
RuntimeClientPlugin.builder()
93109
.withConventions(AwsDependency.MIDDLEWARE_SIGNING.dependency, "AwsAuth", HAS_MIDDLEWARE)
94110
// See operationUsesAwsAuth() below for AwsAuth Middleware customizations.
95-
.servicePredicate(
96-
(m, s) -> !testServiceId(s, "STS") && isSigV4Service(s) && !hasOptionalAuthOperation(m, s)
111+
.servicePredicate((m, s) -> isSigV4Service(s)
112+
&& isAwsService(s)
113+
&& !testServiceId(s, "STS")
114+
&& !hasOptionalAuthOperation(m, s)
115+
).build(),
116+
RuntimeClientPlugin.builder()
117+
.withConventions(AwsDependency.MIDDLEWARE_SIGNING.dependency, "CustomAwsAuth", HAS_MIDDLEWARE)
118+
// See operationUsesAwsAuth() below for AwsAuth Middleware customizations.
119+
.servicePredicate((m, s) -> isSigV4Service(s)
120+
&& !isAwsService(s)
121+
&& !hasOptionalAuthOperation(m, s)
97122
).build(),
98123
RuntimeClientPlugin.builder()
99124
.withConventions(AwsDependency.MIDDLEWARE_SIGNING.dependency, "AwsAuth", HAS_MIDDLEWARE)
100-
.operationPredicate(AddAwsAuthPlugin::operationUsesAwsAuth)
125+
.operationPredicate((m, s, o) -> isSigV4Service(s)
126+
&& isAwsService(s)
127+
&& operationUsesAwsAuth(m, s, o))
128+
.build(),
129+
RuntimeClientPlugin.builder()
130+
.withConventions(AwsDependency.MIDDLEWARE_SIGNING.dependency, "CustomAwsAuth", HAS_MIDDLEWARE)
131+
.operationPredicate((m, s, o) -> isSigV4Service(s)
132+
&& !isAwsService(s)
133+
&& operationUsesAwsAuth(m, s, o))
101134
.build()
135+
102136
);
103137
}
104138

@@ -114,6 +148,13 @@ public Map<String, Consumer<TypeScriptWriter>> getRuntimeConfigWriters(
114148
return Collections.emptyMap();
115149
}
116150
switch (target) {
151+
case SHARED:
152+
String signingService = service.getTrait(SigV4Trait.class).get().getName();
153+
return MapUtils.of(
154+
"signingName", writer -> {
155+
writer.write("signingName: $S,", signingService);
156+
}
157+
);
117158
case BROWSER:
118159
return MapUtils.of(
119160
"credentialDefaultProvider", writer -> {
@@ -208,7 +249,7 @@ private static boolean operationUsesAwsAuth(Model model, ServiceShape service, O
208249
}
209250

210251
// optionalAuth trait doesn't require authentication.
211-
if (isSigV4Service(service) && hasOptionalAuthOperation(model, service)) {
252+
if (hasOptionalAuthOperation(model, service)) {
212253
return !operation.hasTrait(OptionalAuthTrait.class);
213254
}
214255
return false;

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,13 @@ public void addConfigInterfaceFields(
9595
.write("serviceId?: string;\n");
9696
}
9797
if (isSigV4Service(settings, model)) {
98-
writer.writeDocs("The AWS region to which this client will send requests or use as signingRegion")
99-
.write("region?: string | __Provider<string>;\n");
98+
if (isAwsService(settings, model)) {
99+
writer.writeDocs("The AWS region to which this client will send requests")
100+
.write("region?: string | __Provider<string>;\n");
101+
} else {
102+
writer.writeDocs("The AWS region to use as signing region for AWS Auth")
103+
.write("region?: string | __Provider<string>;\n");
104+
}
100105
}
101106
writer.writeDocs("Value for how many times a request will be made at most in case of retry.")
102107
.write("maxAttempts?: number | __Provider<number>;\n");
@@ -163,7 +168,6 @@ private Map<String, Consumer<TypeScriptWriter>> getDefaultConfig(
163168
return defaultConfigs;
164169
case NODE:
165170
if (isSigV4Service) {
166-
// TODO: For non-AWS service, figure out how the region should be configured.
167171
defaultConfigs.put("region", writer -> {
168172
writer.addDependency(AwsDependency.NODE_CONFIG_PROVIDER);
169173
writer.addImport("loadConfig", "loadNodeConfig",

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package software.amazon.smithy.aws.typescript.codegen;
1717

1818
import static software.amazon.smithy.aws.typescript.codegen.AwsTraitsUtils.isAwsService;
19+
import static software.amazon.smithy.aws.typescript.codegen.AwsTraitsUtils.isSigV4Service;
1920
import static software.amazon.smithy.typescript.codegen.integration.RuntimeClientPlugin.Convention.HAS_CONFIG;
2021
import static software.amazon.smithy.typescript.codegen.integration.RuntimeClientPlugin.Convention.HAS_MIDDLEWARE;
2122

@@ -47,7 +48,7 @@ public List<RuntimeClientPlugin> getClientPlugins() {
4748
return ListUtils.of(
4849
RuntimeClientPlugin.builder()
4950
.withConventions(TypeScriptDependency.CONFIG_RESOLVER.dependency, "Region", HAS_CONFIG)
50-
.servicePredicate((m, s) -> isAwsService(s))
51+
.servicePredicate((m, s) -> isSigV4Service(s))
5152
.build(),
5253
// Only one of Endpoints or CustomEndpoints should be used
5354
RuntimeClientPlugin.builder()

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ final class EndpointGenerator implements Runnable {
5858
serviceTrait = service.getTrait(ServiceTrait.class)
5959
.orElseThrow(() -> new CodegenException("No service trait found on " + service.getId()));
6060
endpointPrefix = serviceTrait.getEndpointPrefix();
61+
// Isn't SigV4 trait required for AWS service and isn't SigV4Trait::getName required.
62+
// So why the fallback to getArnNamespace?
6163
baseSigningSerivce = service.getTrait(SigV4Trait.class).map(SigV4Trait::getName)
6264
.orElse(serviceTrait.getArnNamespace());
6365
endpointData = Node.parse(IoUtils.readUtf8Resource(getClass(), "endpoints.json")).expectObjectNode();

0 commit comments

Comments
 (0)