diff --git a/codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/customization/CloudFrontKVSSigV4a.java b/codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/customization/CloudFrontKVSSigV4a.java new file mode 100644 index 00000000000..3dae691f957 --- /dev/null +++ b/codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/customization/CloudFrontKVSSigV4a.java @@ -0,0 +1,148 @@ +package software.amazon.smithy.aws.go.codegen.customization; + +import java.util.List; +import java.util.ArrayList; +import software.amazon.smithy.aws.go.codegen.AddAwsConfigFields; +import software.amazon.smithy.aws.go.codegen.AwsGoDependency; +import software.amazon.smithy.aws.go.codegen.AwsSignatureVersion4; +import software.amazon.smithy.aws.go.codegen.AwsSignatureVersion4aUtils; +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.codegen.core.Symbol; +import software.amazon.smithy.codegen.core.SymbolProvider; +import software.amazon.smithy.go.codegen.GoDelegator; +import software.amazon.smithy.go.codegen.GoSettings; +import software.amazon.smithy.go.codegen.GoWriter; +import software.amazon.smithy.go.codegen.SmithyGoDependency; +import software.amazon.smithy.go.codegen.SymbolUtils; +import software.amazon.smithy.go.codegen.integration.ConfigField; +import software.amazon.smithy.go.codegen.integration.ConfigFieldResolver; +import software.amazon.smithy.go.codegen.integration.GoIntegration; +import software.amazon.smithy.go.codegen.integration.MiddlewareRegistrar; +import software.amazon.smithy.go.codegen.integration.RuntimeClientPlugin; +import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.shapes.ServiceShape; +import software.amazon.smithy.model.traits.AuthTrait; +import software.amazon.smithy.utils.ListUtils; +import software.amazon.smithy.utils.SetUtils; + +/** + * This integration configures the CloudFront Key Value Store client for Signature Version 4a + */ +public class CloudFrontKVSSigV4a implements GoIntegration { + /** + * Return true if service is CFKVS. + * + * @param model is the generation model. + * @param service is the service shape being audited. + */ + private static boolean isCFKVSService(Model model, ServiceShape service) { + final String sdkId = service.expectTrait(ServiceTrait.class).getSdkId(); + final String serviceId = sdkId.replace("-", "").replace(" ", "").toLowerCase(); + return serviceId.equalsIgnoreCase("cloudfrontkeyvaluestore"); + } + + private final List runtimeClientPlugins = new ArrayList<>(); + + + @Override + public List getClientPlugins() { + return runtimeClientPlugins; + } + + @Override + public Model preprocessModel(Model model, GoSettings settings) { + ServiceShape service = settings.getService(model); + if (!isCFKVSService(model, service)) { + return model; + } + + if (settings.getService(model).hasTrait(SigV4ATrait.class)) { + return model; + } + + var v4a = SigV4ATrait.builder() + .name(service.expectTrait(SigV4Trait.class).getName()) + .build(); + + return model.toBuilder() + .addShape( + service.toBuilder() + .addTrait(v4a) + // FUTURE: https://github.com/aws/smithy-go/issues/493 + // we are keeping sigv4 at the end of this list (it will never be selected) + // as a stopgap to drive codegen of payload checksum routines + .addTrait(new AuthTrait(SetUtils.of(SigV4ATrait.ID, SigV4Trait.ID))) + .build() + ) + .build(); + } + + @Override + public void processFinalizedModel(GoSettings settings, Model model) { + if (!isCFKVSService(model, settings.getService(model))) { + return; + } + runtimeClientPlugins.add( + RuntimeClientPlugin.builder() + .configFields( + ListUtils.of( + ConfigField.builder() + .name(AwsSignatureVersion4aUtils.V4A_SIGNER_INTERFACE_NAME) + .type(SymbolUtils.buildPackageSymbol( + AwsSignatureVersion4aUtils.V4A_SIGNER_INTERFACE_NAME) + ) + .documentation("Signature Version 4a (SigV4a) Signer") + .build() + ) + ) + .build()); + runtimeClientPlugins.add( + RuntimeClientPlugin.builder() + .servicePredicate(CloudFrontKVSSigV4a::isCFKVSService) + .addConfigFieldResolver( + ConfigFieldResolver.builder() + .location(ConfigFieldResolver.Location.CLIENT) + .target(ConfigFieldResolver.Target.INITIALIZATION) + .resolver(SymbolUtils.createValueSymbolBuilder( + AwsSignatureVersion4aUtils.SIGNER_RESOLVER).build()) + .build()) + .build()); + } + + @Override + public void writeAdditionalFiles( + GoSettings settings, + Model model, + SymbolProvider symbolProvider, + GoDelegator goDelegator + ) { + + if (!isCFKVSService(model, model.expectShape(settings.getService(), ServiceShape.class))) { + return; + } + + ServiceShape serviceShape = settings.getService(model); + goDelegator.useShapeWriter(serviceShape, writer -> { + writerSignerInterface(writer); + writerConfigFieldResolver(writer, serviceShape); + writeNewV4ASignerFunc(writer, serviceShape); + }); + + } + + + private void writerSignerInterface(GoWriter writer) { + AwsSignatureVersion4aUtils.writerSignerInterface(writer); + } + + private void writeNewV4ASignerFunc(GoWriter writer, ServiceShape serviceShape) { + AwsSignatureVersion4aUtils.writeNewV4ASignerFunc(writer, serviceShape); + } + + private void writerConfigFieldResolver(GoWriter writer, ServiceShape serviceShape) { + AwsSignatureVersion4aUtils.writerConfigFieldResolver(writer, serviceShape); + } + +} diff --git a/codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/customization/auth/BackfillSigV4ATrait.java b/codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/customization/auth/BackfillSigV4ATrait.java index 8a98813a33b..e0f6879cf1d 100644 --- a/codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/customization/auth/BackfillSigV4ATrait.java +++ b/codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/customization/auth/BackfillSigV4ATrait.java @@ -41,6 +41,10 @@ public Model preprocessModel(Model model, GoSettings settings) { return model; } + if (settings.getService(model).hasTrait(SigV4ATrait.class)) { + return model; + } + var v4a = SigV4ATrait.builder() .name(service.expectTrait(SigV4Trait.class).getName()) .build(); diff --git a/codegen/smithy-aws-go-codegen/src/main/resources/META-INF/services/software.amazon.smithy.go.codegen.integration.GoIntegration b/codegen/smithy-aws-go-codegen/src/main/resources/META-INF/services/software.amazon.smithy.go.codegen.integration.GoIntegration index fa7533ac3dd..335d5506776 100644 --- a/codegen/smithy-aws-go-codegen/src/main/resources/META-INF/services/software.amazon.smithy.go.codegen.integration.GoIntegration +++ b/codegen/smithy-aws-go-codegen/src/main/resources/META-INF/services/software.amazon.smithy.go.codegen.integration.GoIntegration @@ -73,3 +73,4 @@ software.amazon.smithy.aws.go.codegen.customization.auth.S3ExpressAuthScheme software.amazon.smithy.aws.go.codegen.customization.S3BucketContext software.amazon.smithy.aws.go.codegen.customization.s3.ExpressDefaultChecksum software.amazon.smithy.aws.go.codegen.customization.auth.GlobalAnonymousOption +software.amazon.smithy.aws.go.codegen.customization.CloudFrontKVSSigV4a diff --git a/service/cloudfrontkeyvaluestore/api_client.go b/service/cloudfrontkeyvaluestore/api_client.go index 93ec74b0a81..dabe9e7a163 100644 --- a/service/cloudfrontkeyvaluestore/api_client.go +++ b/service/cloudfrontkeyvaluestore/api_client.go @@ -14,6 +14,7 @@ import ( internalauth "github.com/aws/aws-sdk-go-v2/internal/auth" internalauthsmithy "github.com/aws/aws-sdk-go-v2/internal/auth/smithy" internalConfig "github.com/aws/aws-sdk-go-v2/internal/configsources" + "github.com/aws/aws-sdk-go-v2/internal/v4a" smithy "github.com/aws/smithy-go" smithydocument "github.com/aws/smithy-go/document" "github.com/aws/smithy-go/logging" @@ -51,6 +52,8 @@ func New(options Options, optFns ...func(*Options)) *Client { resolveEndpointResolverV2(&options) + resolveHTTPSignerV4a(&options) + resolveAuthSchemeResolver(&options) for _, fn := range optFns { @@ -166,6 +169,11 @@ func resolveAuthSchemeResolver(options *Options) { func resolveAuthSchemes(options *Options) { if options.AuthSchemes == nil { options.AuthSchemes = []smithyhttp.AuthScheme{ + internalauth.NewHTTPAuthScheme("aws.auth#sigv4a", &v4a.SignerAdapter{ + Signer: options.httpSignerV4a, + Logger: options.Logger, + LogSigning: options.ClientLogMode.IsSigning(), + }), internalauth.NewHTTPAuthScheme("aws.auth#sigv4", &internalauthsmithy.V4SignerAdapter{ Signer: options.HTTPSignerV4, Logger: options.Logger, @@ -429,6 +437,27 @@ func resolveUseFIPSEndpoint(cfg aws.Config, o *Options) error { return nil } +type httpSignerV4a interface { + SignHTTP(ctx context.Context, credentials v4a.Credentials, r *http.Request, payloadHash, + service string, regionSet []string, signingTime time.Time, + optFns ...func(*v4a.SignerOptions)) error +} + +func resolveHTTPSignerV4a(o *Options) { + if o.httpSignerV4a != nil { + return + } + o.httpSignerV4a = newDefaultV4aSigner(*o) +} + +func newDefaultV4aSigner(o Options) *v4a.Signer { + return v4a.NewSigner(func(so *v4a.SignerOptions) { + so.Logger = o.Logger + so.LogSigning = o.ClientLogMode.IsSigning() + so.DisableURIPathEscaping = false + }) +} + func addRequestIDRetrieverMiddleware(stack *middleware.Stack) error { return awsmiddleware.AddRequestIDRetrieverMiddleware(stack) } diff --git a/service/cloudfrontkeyvaluestore/auth.go b/service/cloudfrontkeyvaluestore/auth.go index e43490e9fa4..67f9115dd7a 100644 --- a/service/cloudfrontkeyvaluestore/auth.go +++ b/service/cloudfrontkeyvaluestore/auth.go @@ -121,6 +121,16 @@ var operationAuthOptions = map[string]func(*AuthResolverParameters) []*smithyaut func serviceAuthOptions(params *AuthResolverParameters) []*smithyauth.Option { return []*smithyauth.Option{ + { + SchemeID: smithyauth.SchemeIDSigV4A, + SignerProperties: func() smithy.Properties { + var props smithy.Properties + smithyhttp.SetSigV4ASigningName(&props, "cloudfront-keyvaluestore") + smithyhttp.SetSigV4ASigningRegions(&props, []string{params.Region}) + return props + }(), + }, + { SchemeID: smithyauth.SchemeIDSigV4, SignerProperties: func() smithy.Properties { diff --git a/service/cloudfrontkeyvaluestore/generated.json b/service/cloudfrontkeyvaluestore/generated.json index 5c130dfa281..64d0cbef6ed 100644 --- a/service/cloudfrontkeyvaluestore/generated.json +++ b/service/cloudfrontkeyvaluestore/generated.json @@ -3,6 +3,7 @@ "github.com/aws/aws-sdk-go-v2": "v1.4.0", "github.com/aws/aws-sdk-go-v2/internal/configsources": "v0.0.0-00010101000000-000000000000", "github.com/aws/aws-sdk-go-v2/internal/endpoints/v2": "v2.0.0-00010101000000-000000000000", + "github.com/aws/aws-sdk-go-v2/internal/v4a": "v0.0.0-00010101000000-000000000000", "github.com/aws/smithy-go": "v1.4.0", "github.com/google/go-cmp": "v0.5.4" }, diff --git a/service/cloudfrontkeyvaluestore/go.mod b/service/cloudfrontkeyvaluestore/go.mod index 94d24634963..3f3bba12d14 100644 --- a/service/cloudfrontkeyvaluestore/go.mod +++ b/service/cloudfrontkeyvaluestore/go.mod @@ -6,6 +6,7 @@ require ( github.com/aws/aws-sdk-go-v2 v1.24.1 github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.10 github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.10 + github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.10 github.com/aws/smithy-go v1.19.0 github.com/google/go-cmp v0.5.8 ) @@ -15,3 +16,5 @@ replace github.com/aws/aws-sdk-go-v2 => ../../ replace github.com/aws/aws-sdk-go-v2/internal/configsources => ../../internal/configsources/ replace github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 => ../../internal/endpoints/v2/ + +replace github.com/aws/aws-sdk-go-v2/internal/v4a => ../../internal/v4a/ diff --git a/service/cloudfrontkeyvaluestore/options.go b/service/cloudfrontkeyvaluestore/options.go index 4ffd85d42dd..a3c1d3548ba 100644 --- a/service/cloudfrontkeyvaluestore/options.go +++ b/service/cloudfrontkeyvaluestore/options.go @@ -4,9 +4,11 @@ package cloudfrontkeyvaluestore import ( "context" + "fmt" "github.com/aws/aws-sdk-go-v2/aws" awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" internalauthsmithy "github.com/aws/aws-sdk-go-v2/internal/auth/smithy" + "github.com/aws/aws-sdk-go-v2/internal/v4a" smithyauth "github.com/aws/smithy-go/auth" "github.com/aws/smithy-go/logging" "github.com/aws/smithy-go/middleware" @@ -95,6 +97,9 @@ type Options struct { // within your applications. RuntimeEnvironment aws.RuntimeEnvironment + // Signature Version 4a (SigV4a) Signer + httpSignerV4a httpSignerV4a + // The initial DefaultsMode used when the client options were constructed. If the // DefaultsMode was set to aws.DefaultsModeAuto this will store what the resolved // value was at that point in time. Currently does not support per operation call @@ -123,6 +128,9 @@ func (o Options) Copy() Options { } func (o Options) GetIdentityResolver(schemeID string) smithyauth.IdentityResolver { + if schemeID == "aws.auth#sigv4a" { + return getSigV4AIdentityResolver(o) + } if schemeID == "aws.auth#sigv4" { return getSigV4IdentityResolver(o) } @@ -210,6 +218,46 @@ func WithSigV4SigningRegion(region string) func(*Options) { } } +func getSigV4AIdentityResolver(o Options) smithyauth.IdentityResolver { + if o.Credentials != nil { + return &v4a.CredentialsProviderAdapter{ + Provider: &v4a.SymmetricCredentialAdaptor{ + SymmetricProvider: o.Credentials, + }, + } + } + return nil +} + +// WithSigV4ASigningRegions applies an override to the authentication workflow to +// use the given signing region set for SigV4A-authenticated operations. +// +// This is an advanced setting. The value here is FINAL, taking precedence over +// the resolved signing region set from both auth scheme resolution and endpoint +// resolution. +func WithSigV4ASigningRegions(regions []string) func(*Options) { + fn := func(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) ( + out middleware.FinalizeOutput, metadata middleware.Metadata, err error, + ) { + rscheme := getResolvedAuthScheme(ctx) + if rscheme == nil { + return out, metadata, fmt.Errorf("no resolved auth scheme") + } + + smithyhttp.SetSigV4ASigningRegions(&rscheme.SignerProperties, regions) + return next.HandleFinalize(ctx, in) + } + return func(o *Options) { + o.APIOptions = append(o.APIOptions, func(s *middleware.Stack) error { + return s.Finalize.Insert( + middleware.FinalizeMiddlewareFunc("withSigV4ASigningRegions", fn), + "Signing", + middleware.Before, + ) + }) + } +} + func ignoreAnonymousAuth(options *Options) { if aws.IsCredentialsProvider(options.Credentials, (*aws.AnonymousCredentials)(nil)) { options.Credentials = nil