Skip to content

Commit

Permalink
chore(codegen): make sigv4a detection programmatic
Browse files Browse the repository at this point in the history
  • Loading branch information
kuhe committed Aug 1, 2024
1 parent 03f1a90 commit ef0c96b
Show file tree
Hide file tree
Showing 10 changed files with 86 additions and 142 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,10 @@ const createEndpointRuleSetHttpAuthSchemeProvider = <
let schemeId;
if (name === "sigv4a") {
schemeId = "aws.auth#sigv4a";
const sigv4Present = authSchemes.find((s) => s.name.toLowerCase().startsWith("sigv4"));
const sigv4Present = authSchemes.find((s) => {
const name = s.name.toLowerCase();
return name !== "sigv4a" && name.startsWith("sigv4");
});
if (!signatureV4CrtContainer.CrtSignerV4 && sigv4Present) {
// sigv4a -> sigv4 fallback.
continue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,10 @@ const createEndpointRuleSetHttpAuthSchemeProvider = <
let schemeId;
if (name === "sigv4a") {
schemeId = "aws.auth#sigv4a";
const sigv4Present = authSchemes.find((s) => s.name.toLowerCase().startsWith("sigv4"));
const sigv4Present = authSchemes.find((s) => {
const name = s.name.toLowerCase();
return name !== "sigv4a" && name.startsWith("sigv4");
});
if (!signatureV4CrtContainer.CrtSignerV4 && sigv4Present) {
// sigv4a -> sigv4 fallback.
continue;
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -237,16 +237,14 @@ public Map<String, Consumer<TypeScriptWriter>> getRuntimeConfigWriters(
}
switch (target) {
case SHARED:
return MapUtils.of("signingEscapePath", writer -> {
writer.write("false");
}, "useArnRegion", writer -> {
writer.write("false");
}, "signerConstructor", writer -> {
writer.addDependency(AwsDependency.SIGNATURE_V4_MULTIREGION)
.addImport("SignatureV4MultiRegion", "SignatureV4MultiRegion",
AwsDependency.SIGNATURE_V4_MULTIREGION)
.write("SignatureV4MultiRegion");
});
return MapUtils.of(
"signingEscapePath", writer -> {
writer.write("false");
},
"useArnRegion", writer -> {
writer.write("false");
}
);
case NODE:
return MapUtils.of(
"useArnRegion", writer -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@
import java.util.Collections;
import java.util.Map;
import java.util.function.Consumer;
import software.amazon.smithy.aws.traits.auth.SigV4ATrait;
import software.amazon.smithy.codegen.core.SymbolProvider;
import software.amazon.smithy.model.Model;
import software.amazon.smithy.model.knowledge.ServiceIndex;
import software.amazon.smithy.typescript.codegen.LanguageTarget;
import software.amazon.smithy.typescript.codegen.TypeScriptSettings;
import software.amazon.smithy.typescript.codegen.TypeScriptWriter;
Expand All @@ -30,15 +28,14 @@ public boolean matchesSettings(TypeScriptSettings settings) {
return settings.useLegacyAuth();
}

@Override
public Map<String, Consumer<TypeScriptWriter>> getRuntimeConfigWriters(
TypeScriptSettings settings,
Model model,
SymbolProvider symbolProvider,
LanguageTarget target
) {
final boolean addSigv4aSignerToConfig = ServiceIndex.of(model)
.getEffectiveAuthSchemes(settings.getService(), ServiceIndex.AuthSchemeMode.NO_AUTH_AWARE)
.containsKey(SigV4ATrait.ID);
final boolean addSigv4aSignerToConfig = AwsTraitsUtils.isSigV4AsymmetricService(model, settings);

// the sigv4a trait also appears on operations, but we will not check
// them individually because it must appear on the service as well in that case.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@

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

import java.util.Set;
import software.amazon.smithy.aws.traits.ServiceTrait;
import software.amazon.smithy.aws.traits.auth.SigV4ATrait;
import software.amazon.smithy.aws.traits.auth.SigV4Trait;
import software.amazon.smithy.model.Model;
import software.amazon.smithy.model.knowledge.ServiceIndex;
import software.amazon.smithy.model.shapes.ServiceShape;
import software.amazon.smithy.model.shapes.ShapeId;
import software.amazon.smithy.model.traits.HttpBearerAuthTrait;
import software.amazon.smithy.rulesengine.traits.EndpointRuleSetTrait;
import software.amazon.smithy.typescript.codegen.TypeScriptSettings;
Expand All @@ -29,6 +33,13 @@
*/
@SmithyInternalApi
public final class AwsTraitsUtils {
// SigV4a is not declared as a trait in existing services, so we need to hard code the following:
// This should not be copied or made public outside of this class.
private static final Set<ShapeId> ENDPOINT_RULESET_HTTP_AUTH_SCHEME_SERVICES = Set.of(
ShapeId.from("com.amazonaws.s3#AmazonS3"),
ShapeId.from("com.amazonaws.eventbridge#AWSEvents"),
ShapeId.from("com.amazonaws.cloudfrontkeyvaluestore#CloudFrontKeyValueStore")
);

private AwsTraitsUtils() {}

Expand All @@ -48,6 +59,16 @@ public static boolean isSigV4Service(ServiceShape serviceShape) {
return serviceShape.hasTrait(SigV4Trait.class);
}

public static boolean isSigV4AsymmetricService(Model model, TypeScriptSettings settings) {
if (ENDPOINT_RULESET_HTTP_AUTH_SCHEME_SERVICES.contains(settings.getService())) {
return true;
}

return ServiceIndex.of(model)
.getEffectiveAuthSchemes(settings.getService(), ServiceIndex.AuthSchemeMode.NO_AUTH_AWARE)
.containsKey(SigV4ATrait.ID);
}

static boolean isEndpointsV2Service(ServiceShape serviceShape) {
return serviceShape.hasTrait(EndpointRuleSetTrait.class);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@
package software.amazon.smithy.aws.typescript.codegen.auth.http.integration;

import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Objects;
import java.util.function.Consumer;
import software.amazon.smithy.aws.typescript.codegen.AwsDependency;
import software.amazon.smithy.aws.typescript.codegen.AwsTraitsUtils;
import software.amazon.smithy.codegen.core.Symbol;
import software.amazon.smithy.codegen.core.SymbolProvider;
import software.amazon.smithy.model.Model;
import software.amazon.smithy.model.knowledge.ServiceIndex;
import software.amazon.smithy.model.knowledge.ServiceIndex.AuthSchemeMode;
Expand All @@ -20,6 +24,7 @@
import software.amazon.smithy.model.shapes.ShapeId;
import software.amazon.smithy.model.traits.DynamicTrait;
import software.amazon.smithy.typescript.codegen.CodegenUtils;
import software.amazon.smithy.typescript.codegen.LanguageTarget;
import software.amazon.smithy.typescript.codegen.TypeScriptCodegenContext;
import software.amazon.smithy.typescript.codegen.TypeScriptDependency;
import software.amazon.smithy.typescript.codegen.TypeScriptSettings;
Expand All @@ -38,6 +43,7 @@
import software.amazon.smithy.typescript.codegen.endpointsV2.EndpointsV2Generator;
import software.amazon.smithy.utils.CodeInterceptor;
import software.amazon.smithy.utils.CodeSection;
import software.amazon.smithy.utils.MapUtils;
import software.amazon.smithy.utils.SmithyInternalApi;

/**
Expand All @@ -48,39 +54,62 @@
*/
@SmithyInternalApi
public final class AwsSdkCustomizeEndpointRuleSetHttpAuthSchemeProvider implements HttpAuthTypeScriptIntegration {
public static final Set<ShapeId> ENDPOINT_RULESET_HTTP_AUTH_SCHEME_SERVICES = Set.of(
ShapeId.from("com.amazonaws.s3#AmazonS3"),
ShapeId.from("com.amazonaws.eventbridge#AWSEvents"),
ShapeId.from("com.amazonaws.cloudfrontkeyvaluestore#CloudFrontKeyValueStore"));
private static final ShapeId SIGV4A_ID = ShapeId.from("aws.auth#sigv4a");

/**
* Integration should be skipped if the `useLegacyAuth` flag is true.
*/
@Override
public boolean matchesSettings(TypeScriptSettings settings) {
return !settings.useLegacyAuth()
&& ENDPOINT_RULESET_HTTP_AUTH_SCHEME_SERVICES.contains(settings.getService());
return !settings.useLegacyAuth();
}

@Override
public List<String> runBefore() {
return List.of(
AddHttpAuthSchemePlugin.class.getCanonicalName());
AddHttpAuthSchemePlugin.class.getCanonicalName()
);
}

@Override
public List<String> runAfter() {
return List.of(
SupportSigV4Auth.class.getCanonicalName(),
AwsSdkCustomizeSigV4Auth.class.getCanonicalName());
AwsSdkCustomizeSigV4Auth.class.getCanonicalName()
);
}

@Override
public Map<String, Consumer<TypeScriptWriter>> getRuntimeConfigWriters(
TypeScriptSettings settings,
Model model,
SymbolProvider symbolProvider,
LanguageTarget target
) {
if (!AwsTraitsUtils.isSigV4AsymmetricService(model, settings)) {
return Collections.emptyMap();
}

if (Objects.requireNonNull(target) == LanguageTarget.SHARED) {
return MapUtils.of("signerConstructor", writer -> {
writer
.addDependency(AwsDependency.SIGNATURE_V4_MULTIREGION)
.addImport("SignatureV4MultiRegion", null, AwsDependency.SIGNATURE_V4_MULTIREGION)
.write("SignatureV4MultiRegion");
});
}
return Collections.emptyMap();
}

@Override
public void customizeSupportedHttpAuthSchemes(
SupportedHttpAuthSchemesIndex supportedHttpAuthSchemesIndex,
Model model,
TypeScriptSettings settings) {
if (!AwsTraitsUtils.isSigV4AsymmetricService(model, settings)) {
return;
}

// TODO(experimentalIdentityAndAuth): should be removed when @aws.auth#sigv4a is supported
if (supportedHttpAuthSchemesIndex.getHttpAuthScheme(SIGV4A_ID) == null) {
ShapeId sigv4 = ShapeId.from("aws.auth#sigv4");
Expand All @@ -96,6 +125,9 @@ public void customizeSupportedHttpAuthSchemes(
public List<? extends CodeInterceptor<? extends CodeSection, TypeScriptWriter>> interceptors(
TypeScriptCodegenContext codegenContext
) {
if (!AwsTraitsUtils.isSigV4AsymmetricService(codegenContext.model(), codegenContext.settings())) {
return Collections.emptyList();
}
return List.of(
new CodeInterceptor<HttpAuthSchemeParametersInterfaceCodeSection, TypeScriptWriter>() {
@Override
Expand Down Expand Up @@ -383,7 +415,10 @@ interface DefaultEndpointResolver<EndpointParametersT extends EndpointParameters
let schemeId;
if (name === "sigv4a") {
schemeId = "aws.auth#sigv4a";
const sigv4Present = authSchemes.find(s => s.name.toLowerCase().startsWith('sigv4'));
const sigv4Present = authSchemes.find(s => {
const name = s.name.toLowerCase();
return name !== "sigv4a" && name.startsWith("sigv4");
});
if (!signatureV4CrtContainer.CrtSignerV4 && sigv4Present) {
// sigv4a -> sigv4 fallback.
continue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,14 @@
package software.amazon.smithy.aws.typescript.codegen.auth.http.integration;

import static software.amazon.smithy.aws.typescript.codegen.AwsTraitsUtils.isAwsService;
import static software.amazon.smithy.aws.typescript.codegen.AwsTraitsUtils.isSigV4AsymmetricService;
import static software.amazon.smithy.aws.typescript.codegen.AwsTraitsUtils.isSigV4Service;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import software.amazon.smithy.aws.traits.auth.SigV4ATrait;
import software.amazon.smithy.aws.traits.auth.SigV4Trait;
import software.amazon.smithy.aws.typescript.codegen.AwsCredentialProviderUtils;
Expand All @@ -25,7 +24,6 @@
import software.amazon.smithy.model.knowledge.TopDownIndex;
import software.amazon.smithy.model.shapes.OperationShape;
import software.amazon.smithy.model.shapes.ServiceShape;
import software.amazon.smithy.model.shapes.ShapeId;
import software.amazon.smithy.model.traits.OptionalAuthTrait;
import software.amazon.smithy.typescript.codegen.LanguageTarget;
import software.amazon.smithy.typescript.codegen.TypeScriptDependency;
Expand Down Expand Up @@ -177,8 +175,7 @@ public void customizeSupportedHttpAuthSchemes(
.build();
supportedHttpAuthSchemesIndex.putHttpAuthScheme(authScheme.getSchemeId(), authScheme);

if (AwsSdkCustomizeEndpointRuleSetHttpAuthSchemeProvider.ENDPOINT_RULESET_HTTP_AUTH_SCHEME_SERVICES
.contains(service.getId())) {
if (isSigV4AsymmetricService(model, settings)) {
HttpAuthScheme authSchemeSigV4a = supportedHttpAuthSchemesIndex.getHttpAuthScheme(SigV4Trait.ID).toBuilder()
.schemeId(SigV4ATrait.ID)
.putDefaultSigner(LanguageTarget.SHARED, w -> w
Expand Down
Loading

0 comments on commit ef0c96b

Please sign in to comment.