From 9836a09e97bc7f260f75eb1c5ff831f671ce2ec8 Mon Sep 17 00:00:00 2001 From: George Fu Date: Thu, 1 Aug 2024 18:40:56 -0400 Subject: [PATCH] chore(id-auth-sra): sigv4a compatibility for id-auth sra (#6342) * chore(id-auth-sra): sigv4a compatibility for id-auth sra * chore(codegen): make sigv4a detection programmatic * chore(codegen): java formatting --- .../package.json | 2 +- .../src/CloudFrontKeyValueStoreClient.ts | 40 +- .../auth/httpAuthExtensionConfiguration.ts | 72 ++++ .../src/auth/httpAuthSchemeProvider.ts | 341 ++++++++++++++++++ .../src/extensionConfiguration.ts | 5 +- .../src/runtimeConfig.shared.ts | 16 + .../src/runtimeExtensions.ts | 3 + clients/client-eventbridge/package.json | 2 +- .../src/EventBridgeClient.ts | 40 +- .../auth/httpAuthExtensionConfiguration.ts | 72 ++++ .../src/auth/httpAuthSchemeProvider.ts | 323 +++++++++++++++++ .../src/extensionConfiguration.ts | 5 +- .../src/runtimeConfig.shared.ts | 16 + .../src/runtimeExtensions.ts | 3 + .../src/models/models_0.ts | 1 + codegen/sdk-codegen/build.gradle.kts | 3 - .../AddCloudFrontKeyValueStorePlugin.java | 50 --- .../codegen/AddEventBridgePlugin.java | 58 --- .../aws/typescript/codegen/AddS3Config.java | 18 +- .../typescript/codegen/AddSigv4aPlugin.java | 9 +- .../typescript/codegen/AwsTraitsUtils.java | 21 ++ ...EndpointRuleSetHttpAuthSchemeProvider.java | 85 +++-- .../integration/AwsSdkCustomizeSigV4Auth.java | 15 + ....codegen.integration.TypeScriptIntegration | 2 - .../aws_sdk/AwsSdkSigV4ASigner.ts | 34 ++ .../aws_sdk/AwsSdkSigV4Signer.ts | 8 +- .../httpAuthSchemes/aws_sdk/index.ts | 3 +- 27 files changed, 1059 insertions(+), 188 deletions(-) create mode 100644 clients/client-cloudfront-keyvaluestore/src/auth/httpAuthExtensionConfiguration.ts create mode 100644 clients/client-cloudfront-keyvaluestore/src/auth/httpAuthSchemeProvider.ts create mode 100644 clients/client-eventbridge/src/auth/httpAuthExtensionConfiguration.ts create mode 100644 clients/client-eventbridge/src/auth/httpAuthSchemeProvider.ts delete mode 100644 codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddCloudFrontKeyValueStorePlugin.java delete mode 100644 codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddEventBridgePlugin.java create mode 100644 packages/core/src/submodules/httpAuthSchemes/aws_sdk/AwsSdkSigV4ASigner.ts diff --git a/clients/client-cloudfront-keyvaluestore/package.json b/clients/client-cloudfront-keyvaluestore/package.json index 3ec5227a9d29..2be203570dc5 100644 --- a/clients/client-cloudfront-keyvaluestore/package.json +++ b/clients/client-cloudfront-keyvaluestore/package.json @@ -27,7 +27,6 @@ "@aws-sdk/middleware-host-header": "*", "@aws-sdk/middleware-logger": "*", "@aws-sdk/middleware-recursion-detection": "*", - "@aws-sdk/middleware-signing": "*", "@aws-sdk/middleware-user-agent": "*", "@aws-sdk/region-config-resolver": "*", "@aws-sdk/signature-v4-multi-region": "*", @@ -57,6 +56,7 @@ "@smithy/util-defaults-mode-browser": "^3.0.14", "@smithy/util-defaults-mode-node": "^3.0.14", "@smithy/util-endpoints": "^2.0.5", + "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", "@smithy/util-utf8": "^3.0.0", "tslib": "^2.6.2" diff --git a/clients/client-cloudfront-keyvaluestore/src/CloudFrontKeyValueStoreClient.ts b/clients/client-cloudfront-keyvaluestore/src/CloudFrontKeyValueStoreClient.ts index f2015d344bf9..256814b8fbcf 100644 --- a/clients/client-cloudfront-keyvaluestore/src/CloudFrontKeyValueStoreClient.ts +++ b/clients/client-cloudfront-keyvaluestore/src/CloudFrontKeyValueStoreClient.ts @@ -7,20 +7,18 @@ import { } from "@aws-sdk/middleware-host-header"; import { getLoggerPlugin } from "@aws-sdk/middleware-logger"; import { getRecursionDetectionPlugin } from "@aws-sdk/middleware-recursion-detection"; -import { - AwsAuthInputConfig, - AwsAuthResolvedConfig, - getAwsAuthPlugin, - resolveAwsAuthConfig, -} from "@aws-sdk/middleware-signing"; import { getUserAgentPlugin, resolveUserAgentConfig, UserAgentInputConfig, UserAgentResolvedConfig, } from "@aws-sdk/middleware-user-agent"; -import { Credentials as __Credentials } from "@aws-sdk/types"; import { RegionInputConfig, RegionResolvedConfig, resolveRegionConfig } from "@smithy/config-resolver"; +import { + DefaultIdentityProviderConfig, + getHttpAuthSchemeEndpointRuleSetPlugin, + getHttpSigningPlugin, +} from "@smithy/core"; import { getContentLengthPlugin } from "@smithy/middleware-content-length"; import { EndpointInputConfig, EndpointResolvedConfig, resolveEndpointConfig } from "@smithy/middleware-endpoint"; import { getRetryPlugin, resolveRetryConfig, RetryInputConfig, RetryResolvedConfig } from "@smithy/middleware-retry"; @@ -32,6 +30,7 @@ import { SmithyResolvedConfiguration as __SmithyResolvedConfiguration, } from "@smithy/smithy-client"; import { + AwsCredentialIdentityProvider, BodyLengthCalculator as __BodyLengthCalculator, CheckOptionalClientConfig as __CheckOptionalClientConfig, ChecksumConstructor as __ChecksumConstructor, @@ -48,6 +47,12 @@ import { UserAgent as __UserAgent, } from "@smithy/types"; +import { + defaultCloudFrontKeyValueStoreHttpAuthSchemeParametersProvider, + HttpAuthSchemeInputConfig, + HttpAuthSchemeResolvedConfig, + resolveHttpAuthSchemeConfig, +} from "./auth/httpAuthSchemeProvider"; import { DeleteKeyCommandInput, DeleteKeyCommandOutput } from "./commands/DeleteKeyCommand"; import { DescribeKeyValueStoreCommandInput, @@ -189,9 +194,10 @@ export interface ClientDefaults extends Partial<__SmithyConfiguration<__HttpHand /** * Default credentials provider; Not available in browser runtime. + * @deprecated * @internal */ - credentialDefaultProvider?: (input: any) => __Provider<__Credentials>; + credentialDefaultProvider?: (input: any) => AwsCredentialIdentityProvider; /** * Value for how many times a request will be made at most in case of retry. @@ -231,7 +237,7 @@ export type CloudFrontKeyValueStoreClientConfigType = Partial<__SmithyConfigurat RegionInputConfig & HostHeaderInputConfig & EndpointInputConfig & - AwsAuthInputConfig & + HttpAuthSchemeInputConfig & ClientInputEndpointParameters; /** * @public @@ -251,7 +257,7 @@ export type CloudFrontKeyValueStoreClientResolvedConfigType = __SmithyResolvedCo RegionResolvedConfig & HostHeaderResolvedConfig & EndpointResolvedConfig & - AwsAuthResolvedConfig & + HttpAuthSchemeResolvedConfig & ClientResolvedEndpointParameters; /** * @public @@ -283,7 +289,7 @@ export class CloudFrontKeyValueStoreClient extends __Client< const _config_4 = resolveRegionConfig(_config_3); const _config_5 = resolveHostHeaderConfig(_config_4); const _config_6 = resolveEndpointConfig(_config_5); - const _config_7 = resolveAwsAuthConfig(_config_6); + const _config_7 = resolveHttpAuthSchemeConfig(_config_6); const _config_8 = resolveRuntimeExtensions(_config_7, configuration?.extensions || []); super(_config_8); this.config = _config_8; @@ -293,7 +299,17 @@ export class CloudFrontKeyValueStoreClient extends __Client< this.middlewareStack.use(getHostHeaderPlugin(this.config)); this.middlewareStack.use(getLoggerPlugin(this.config)); this.middlewareStack.use(getRecursionDetectionPlugin(this.config)); - this.middlewareStack.use(getAwsAuthPlugin(this.config)); + this.middlewareStack.use( + getHttpAuthSchemeEndpointRuleSetPlugin(this.config, { + httpAuthSchemeParametersProvider: defaultCloudFrontKeyValueStoreHttpAuthSchemeParametersProvider, + identityProviderConfigProvider: async (config: CloudFrontKeyValueStoreClientResolvedConfig) => + new DefaultIdentityProviderConfig({ + "aws.auth#sigv4": config.credentials, + "aws.auth#sigv4a": config.credentials, + }), + }) + ); + this.middlewareStack.use(getHttpSigningPlugin(this.config)); } /** diff --git a/clients/client-cloudfront-keyvaluestore/src/auth/httpAuthExtensionConfiguration.ts b/clients/client-cloudfront-keyvaluestore/src/auth/httpAuthExtensionConfiguration.ts new file mode 100644 index 000000000000..34082dbc036a --- /dev/null +++ b/clients/client-cloudfront-keyvaluestore/src/auth/httpAuthExtensionConfiguration.ts @@ -0,0 +1,72 @@ +// smithy-typescript generated code +import { AwsCredentialIdentity, AwsCredentialIdentityProvider, HttpAuthScheme } from "@smithy/types"; + +import { CloudFrontKeyValueStoreHttpAuthSchemeProvider } from "./httpAuthSchemeProvider"; + +/** + * @internal + */ +export interface HttpAuthExtensionConfiguration { + setHttpAuthScheme(httpAuthScheme: HttpAuthScheme): void; + httpAuthSchemes(): HttpAuthScheme[]; + setHttpAuthSchemeProvider(httpAuthSchemeProvider: CloudFrontKeyValueStoreHttpAuthSchemeProvider): void; + httpAuthSchemeProvider(): CloudFrontKeyValueStoreHttpAuthSchemeProvider; + setCredentials(credentials: AwsCredentialIdentity | AwsCredentialIdentityProvider): void; + credentials(): AwsCredentialIdentity | AwsCredentialIdentityProvider | undefined; +} + +/** + * @internal + */ +export type HttpAuthRuntimeConfig = Partial<{ + httpAuthSchemes: HttpAuthScheme[]; + httpAuthSchemeProvider: CloudFrontKeyValueStoreHttpAuthSchemeProvider; + credentials: AwsCredentialIdentity | AwsCredentialIdentityProvider; +}>; + +/** + * @internal + */ +export const getHttpAuthExtensionConfiguration = ( + runtimeConfig: HttpAuthRuntimeConfig +): HttpAuthExtensionConfiguration => { + const _httpAuthSchemes = runtimeConfig.httpAuthSchemes!; + let _httpAuthSchemeProvider = runtimeConfig.httpAuthSchemeProvider!; + let _credentials = runtimeConfig.credentials; + return { + setHttpAuthScheme(httpAuthScheme: HttpAuthScheme): void { + const index = _httpAuthSchemes.findIndex((scheme) => scheme.schemeId === httpAuthScheme.schemeId); + if (index === -1) { + _httpAuthSchemes.push(httpAuthScheme); + } else { + _httpAuthSchemes.splice(index, 1, httpAuthScheme); + } + }, + httpAuthSchemes(): HttpAuthScheme[] { + return _httpAuthSchemes; + }, + setHttpAuthSchemeProvider(httpAuthSchemeProvider: CloudFrontKeyValueStoreHttpAuthSchemeProvider): void { + _httpAuthSchemeProvider = httpAuthSchemeProvider; + }, + httpAuthSchemeProvider(): CloudFrontKeyValueStoreHttpAuthSchemeProvider { + return _httpAuthSchemeProvider; + }, + setCredentials(credentials: AwsCredentialIdentity | AwsCredentialIdentityProvider): void { + _credentials = credentials; + }, + credentials(): AwsCredentialIdentity | AwsCredentialIdentityProvider | undefined { + return _credentials; + }, + }; +}; + +/** + * @internal + */ +export const resolveHttpAuthRuntimeConfig = (config: HttpAuthExtensionConfiguration): HttpAuthRuntimeConfig => { + return { + httpAuthSchemes: config.httpAuthSchemes(), + httpAuthSchemeProvider: config.httpAuthSchemeProvider(), + credentials: config.credentials(), + }; +}; diff --git a/clients/client-cloudfront-keyvaluestore/src/auth/httpAuthSchemeProvider.ts b/clients/client-cloudfront-keyvaluestore/src/auth/httpAuthSchemeProvider.ts new file mode 100644 index 000000000000..e7553783a0a6 --- /dev/null +++ b/clients/client-cloudfront-keyvaluestore/src/auth/httpAuthSchemeProvider.ts @@ -0,0 +1,341 @@ +// smithy-typescript generated code +import { + AwsSdkSigV4AuthInputConfig, + AwsSdkSigV4AuthResolvedConfig, + AwsSdkSigV4PreviouslyResolved, + resolveAwsSdkSigV4Config, +} from "@aws-sdk/core"; +import { signatureV4CrtContainer } from "@aws-sdk/signature-v4-multi-region"; +import { EndpointParameterInstructions, resolveParams } from "@smithy/middleware-endpoint"; +import { + EndpointV2, + HandlerExecutionContext, + HttpAuthOption, + HttpAuthScheme, + HttpAuthSchemeId, + HttpAuthSchemeParameters, + HttpAuthSchemeParametersProvider, + HttpAuthSchemeProvider, + Logger, +} from "@smithy/types"; +import { getSmithyContext, normalizeProvider } from "@smithy/util-middleware"; + +import { + CloudFrontKeyValueStoreClientConfig, + CloudFrontKeyValueStoreClientResolvedConfig, +} from "../CloudFrontKeyValueStoreClient"; +import { EndpointParameters } from "../endpoint/EndpointParameters"; +import { defaultEndpointResolver } from "../endpoint/endpointResolver"; + +/** + * @internal + */ +interface _CloudFrontKeyValueStoreHttpAuthSchemeParameters extends HttpAuthSchemeParameters { + region?: string; +} + +/** + * @internal + */ +export interface CloudFrontKeyValueStoreHttpAuthSchemeParameters + extends _CloudFrontKeyValueStoreHttpAuthSchemeParameters, + EndpointParameters { + region?: string; +} + +/** + * @internal + */ +export interface CloudFrontKeyValueStoreHttpAuthSchemeParametersProvider + extends HttpAuthSchemeParametersProvider< + CloudFrontKeyValueStoreClientResolvedConfig, + HandlerExecutionContext, + CloudFrontKeyValueStoreHttpAuthSchemeParameters, + object + > {} + +/** + * @internal + */ +interface EndpointRuleSetSmithyContext { + commandInstance?: { + constructor?: { + getEndpointParameterInstructions(): EndpointParameterInstructions; + }; + }; +} +/** + * @internal + */ +interface EndpointRuleSetHttpAuthSchemeParametersProvider< + TConfig extends object, + TContext extends HandlerExecutionContext, + TParameters extends HttpAuthSchemeParameters & EndpointParameters, + TInput extends object +> extends HttpAuthSchemeParametersProvider {} +/** + * @internal + */ +const createEndpointRuleSetHttpAuthSchemeParametersProvider = + < + TConfig extends object, + TContext extends HandlerExecutionContext, + THttpAuthSchemeParameters extends HttpAuthSchemeParameters, + TEndpointParameters extends EndpointParameters, + TParameters extends THttpAuthSchemeParameters & TEndpointParameters, + TInput extends object + >( + defaultHttpAuthSchemeParametersProvider: HttpAuthSchemeParametersProvider< + TConfig, + TContext, + THttpAuthSchemeParameters, + TInput + > + ): EndpointRuleSetHttpAuthSchemeParametersProvider< + TConfig, + TContext, + THttpAuthSchemeParameters & TEndpointParameters, + TInput + > => + async (config: TConfig, context: TContext, input: TInput): Promise => { + if (!input) { + throw new Error(`Could not find \`input\` for \`defaultEndpointRuleSetHttpAuthSchemeParametersProvider\``); + } + const defaultParameters = await defaultHttpAuthSchemeParametersProvider(config, context, input); + const instructionsFn = (getSmithyContext(context) as EndpointRuleSetSmithyContext)?.commandInstance?.constructor + ?.getEndpointParameterInstructions; + if (!instructionsFn) { + throw new Error(`getEndpointParameterInstructions() is not defined on \`${context.commandName!}\``); + } + const endpointParameters = await resolveParams( + input as Record, + { getEndpointParameterInstructions: instructionsFn! }, + config as Record + ); + return Object.assign(defaultParameters, endpointParameters) as TParameters; + }; +/** + * @internal + */ +const _defaultCloudFrontKeyValueStoreHttpAuthSchemeParametersProvider = async ( + config: CloudFrontKeyValueStoreClientResolvedConfig, + context: HandlerExecutionContext, + input: object +): Promise<_CloudFrontKeyValueStoreHttpAuthSchemeParameters> => { + return { + operation: getSmithyContext(context).operation as string, + region: + (await normalizeProvider(config.region)()) || + (() => { + throw new Error("expected `region` to be configured for `aws.auth#sigv4`"); + })(), + }; +}; +/** + * @internal + */ +export const defaultCloudFrontKeyValueStoreHttpAuthSchemeParametersProvider: CloudFrontKeyValueStoreHttpAuthSchemeParametersProvider = + createEndpointRuleSetHttpAuthSchemeParametersProvider( + _defaultCloudFrontKeyValueStoreHttpAuthSchemeParametersProvider + ); + +function createAwsAuthSigv4HttpAuthOption( + authParameters: CloudFrontKeyValueStoreHttpAuthSchemeParameters +): HttpAuthOption { + return { + schemeId: "aws.auth#sigv4", + signingProperties: { + name: "cloudfront-keyvaluestore", + region: authParameters.region, + }, + propertiesExtractor: (config: Partial, context) => ({ + /** + * @internal + */ + signingProperties: { + config, + context, + }, + }), + }; +} + +function createAwsAuthSigv4aHttpAuthOption( + authParameters: CloudFrontKeyValueStoreHttpAuthSchemeParameters +): HttpAuthOption { + return { + schemeId: "aws.auth#sigv4a", + signingProperties: { + name: "cloudfront-keyvaluestore", + region: authParameters.region, + }, + propertiesExtractor: (config: Partial, context) => ({ + /** + * @internal + */ + signingProperties: { + config, + context, + }, + }), + }; +} + +/** + * @internal + */ +interface _CloudFrontKeyValueStoreHttpAuthSchemeProvider + extends HttpAuthSchemeProvider {} + +/** + * @internal + */ +export interface CloudFrontKeyValueStoreHttpAuthSchemeProvider + extends HttpAuthSchemeProvider {} + +/** + * @internal + */ +interface EndpointRuleSetHttpAuthSchemeProvider< + EndpointParametersT extends EndpointParameters, + HttpAuthSchemeParametersT extends HttpAuthSchemeParameters +> extends HttpAuthSchemeProvider {} +/** + * @internal + */ +interface DefaultEndpointResolver { + (params: EndpointParametersT, context?: { logger?: Logger }): EndpointV2; +} +/** + * @internal + */ +const createEndpointRuleSetHttpAuthSchemeProvider = < + EndpointParametersT extends EndpointParameters, + HttpAuthSchemeParametersT extends HttpAuthSchemeParameters +>( + defaultEndpointResolver: DefaultEndpointResolver, + defaultHttpAuthSchemeResolver: HttpAuthSchemeProvider, + createHttpAuthOptionFunctions: Record< + HttpAuthSchemeId, + (authParameters: EndpointParametersT & HttpAuthSchemeParametersT) => HttpAuthOption + > +): EndpointRuleSetHttpAuthSchemeProvider => { + const endpointRuleSetHttpAuthSchemeProvider: EndpointRuleSetHttpAuthSchemeProvider< + EndpointParametersT, + HttpAuthSchemeParametersT + > = (authParameters) => { + const endpoint: EndpointV2 = defaultEndpointResolver(authParameters); + const authSchemes = endpoint.properties?.authSchemes; + if (!authSchemes) { + return defaultHttpAuthSchemeResolver(authParameters); + } + const options: HttpAuthOption[] = []; + for (const scheme of authSchemes) { + const { name: resolvedName, properties = {}, ...rest } = scheme; + const name = resolvedName.toLowerCase(); + if (resolvedName !== name) { + console.warn(`HttpAuthScheme has been normalized with lowercasing: \`${resolvedName}\` to \`${name}\``); + } + let schemeId; + if (name === "sigv4a") { + schemeId = "aws.auth#sigv4a"; + const sigv4Present = authSchemes.find((s) => { + const name = s.name.toLowerCase(); + return name !== "sigv4a" && name.startsWith("sigv4"); + }); + if (!signatureV4CrtContainer.CrtSignerV4 && sigv4Present) { + // sigv4a -> sigv4 fallback. + continue; + } + } else if (name.startsWith("sigv4")) { + schemeId = "aws.auth#sigv4"; + } else { + throw new Error(`Unknown HttpAuthScheme found in \`@smithy.rules#endpointRuleSet\`: \`${name}\``); + } + const createOption = createHttpAuthOptionFunctions[schemeId]; + if (!createOption) { + throw new Error(`Could not find HttpAuthOption create function for \`${schemeId}\``); + } + const option = createOption(authParameters); + option.schemeId = schemeId; + option.signingProperties = { ...(option.signingProperties || {}), ...rest, ...properties }; + options.push(option); + } + return options; + }; + + return endpointRuleSetHttpAuthSchemeProvider; +}; +/** + * @internal + */ +const _defaultCloudFrontKeyValueStoreHttpAuthSchemeProvider: _CloudFrontKeyValueStoreHttpAuthSchemeProvider = ( + authParameters +) => { + const options: HttpAuthOption[] = []; + switch (authParameters.operation) { + default: { + options.push(createAwsAuthSigv4HttpAuthOption(authParameters)); + options.push(createAwsAuthSigv4aHttpAuthOption(authParameters)); + } + } + return options; +}; +/** + * @internal + */ +export const defaultCloudFrontKeyValueStoreHttpAuthSchemeProvider: CloudFrontKeyValueStoreHttpAuthSchemeProvider = + createEndpointRuleSetHttpAuthSchemeProvider( + defaultEndpointResolver, + _defaultCloudFrontKeyValueStoreHttpAuthSchemeProvider, + { + "aws.auth#sigv4": createAwsAuthSigv4HttpAuthOption, + "aws.auth#sigv4a": createAwsAuthSigv4aHttpAuthOption, + } + ); + +/** + * @internal + */ +export interface HttpAuthSchemeInputConfig extends AwsSdkSigV4AuthInputConfig { + /** + * Configuration of HttpAuthSchemes for a client which provides default identity providers and signers per auth scheme. + * @internal + */ + httpAuthSchemes?: HttpAuthScheme[]; + + /** + * Configuration of an HttpAuthSchemeProvider for a client which resolves which HttpAuthScheme to use. + * @internal + */ + httpAuthSchemeProvider?: CloudFrontKeyValueStoreHttpAuthSchemeProvider; +} + +/** + * @internal + */ +export interface HttpAuthSchemeResolvedConfig extends AwsSdkSigV4AuthResolvedConfig { + /** + * Configuration of HttpAuthSchemes for a client which provides default identity providers and signers per auth scheme. + * @internal + */ + readonly httpAuthSchemes: HttpAuthScheme[]; + + /** + * Configuration of an HttpAuthSchemeProvider for a client which resolves which HttpAuthScheme to use. + * @internal + */ + readonly httpAuthSchemeProvider: CloudFrontKeyValueStoreHttpAuthSchemeProvider; +} + +/** + * @internal + */ +export const resolveHttpAuthSchemeConfig = ( + config: T & HttpAuthSchemeInputConfig & AwsSdkSigV4PreviouslyResolved +): T & HttpAuthSchemeResolvedConfig => { + const config_0 = resolveAwsSdkSigV4Config(config); + return { + ...config_0, + } as T & HttpAuthSchemeResolvedConfig; +}; diff --git a/clients/client-cloudfront-keyvaluestore/src/extensionConfiguration.ts b/clients/client-cloudfront-keyvaluestore/src/extensionConfiguration.ts index c702bccba9a4..e56922825964 100644 --- a/clients/client-cloudfront-keyvaluestore/src/extensionConfiguration.ts +++ b/clients/client-cloudfront-keyvaluestore/src/extensionConfiguration.ts @@ -3,10 +3,13 @@ import { AwsRegionExtensionConfiguration } from "@aws-sdk/types"; import { HttpHandlerExtensionConfiguration } from "@smithy/protocol-http"; import { DefaultExtensionConfiguration } from "@smithy/types"; +import { HttpAuthExtensionConfiguration } from "./auth/httpAuthExtensionConfiguration"; + /** * @internal */ export interface CloudFrontKeyValueStoreExtensionConfiguration extends HttpHandlerExtensionConfiguration, DefaultExtensionConfiguration, - AwsRegionExtensionConfiguration {} + AwsRegionExtensionConfiguration, + HttpAuthExtensionConfiguration {} diff --git a/clients/client-cloudfront-keyvaluestore/src/runtimeConfig.shared.ts b/clients/client-cloudfront-keyvaluestore/src/runtimeConfig.shared.ts index 114659803ba5..740490705536 100644 --- a/clients/client-cloudfront-keyvaluestore/src/runtimeConfig.shared.ts +++ b/clients/client-cloudfront-keyvaluestore/src/runtimeConfig.shared.ts @@ -1,10 +1,13 @@ // smithy-typescript generated code +import { AwsSdkSigV4ASigner, AwsSdkSigV4Signer } from "@aws-sdk/core"; import { SignatureV4MultiRegion } from "@aws-sdk/signature-v4-multi-region"; import { NoOpLogger } from "@smithy/smithy-client"; +import { IdentityProviderConfig } from "@smithy/types"; import { parseUrl } from "@smithy/url-parser"; import { fromBase64, toBase64 } from "@smithy/util-base64"; import { fromUtf8, toUtf8 } from "@smithy/util-utf8"; +import { defaultCloudFrontKeyValueStoreHttpAuthSchemeProvider } from "./auth/httpAuthSchemeProvider"; import { CloudFrontKeyValueStoreClientConfig } from "./CloudFrontKeyValueStoreClient"; import { defaultEndpointResolver } from "./endpoint/endpointResolver"; @@ -19,6 +22,19 @@ export const getRuntimeConfig = (config: CloudFrontKeyValueStoreClientConfig) => disableHostPrefix: config?.disableHostPrefix ?? false, endpointProvider: config?.endpointProvider ?? defaultEndpointResolver, extensions: config?.extensions ?? [], + httpAuthSchemeProvider: config?.httpAuthSchemeProvider ?? defaultCloudFrontKeyValueStoreHttpAuthSchemeProvider, + httpAuthSchemes: config?.httpAuthSchemes ?? [ + { + schemeId: "aws.auth#sigv4", + identityProvider: (ipc: IdentityProviderConfig) => ipc.getIdentityProvider("aws.auth#sigv4"), + signer: new AwsSdkSigV4Signer(), + }, + { + schemeId: "aws.auth#sigv4a", + identityProvider: (ipc: IdentityProviderConfig) => ipc.getIdentityProvider("aws.auth#sigv4a"), + signer: new AwsSdkSigV4ASigner(), + }, + ], logger: config?.logger ?? new NoOpLogger(), serviceId: config?.serviceId ?? "CloudFront KeyValueStore", signerConstructor: config?.signerConstructor ?? SignatureV4MultiRegion, diff --git a/clients/client-cloudfront-keyvaluestore/src/runtimeExtensions.ts b/clients/client-cloudfront-keyvaluestore/src/runtimeExtensions.ts index 004cbfae6551..df8800132d97 100644 --- a/clients/client-cloudfront-keyvaluestore/src/runtimeExtensions.ts +++ b/clients/client-cloudfront-keyvaluestore/src/runtimeExtensions.ts @@ -6,6 +6,7 @@ import { import { getHttpHandlerExtensionConfiguration, resolveHttpHandlerRuntimeConfig } from "@smithy/protocol-http"; import { getDefaultExtensionConfiguration, resolveDefaultRuntimeConfig } from "@smithy/smithy-client"; +import { getHttpAuthExtensionConfiguration, resolveHttpAuthRuntimeConfig } from "./auth/httpAuthExtensionConfiguration"; import { CloudFrontKeyValueStoreExtensionConfiguration } from "./extensionConfiguration"; /** @@ -32,6 +33,7 @@ export const resolveRuntimeExtensions = (runtimeConfig: any, extensions: Runtime ...asPartial(getAwsRegionExtensionConfiguration(runtimeConfig)), ...asPartial(getDefaultExtensionConfiguration(runtimeConfig)), ...asPartial(getHttpHandlerExtensionConfiguration(runtimeConfig)), + ...asPartial(getHttpAuthExtensionConfiguration(runtimeConfig)), }; extensions.forEach((extension) => extension.configure(extensionConfiguration)); @@ -41,5 +43,6 @@ export const resolveRuntimeExtensions = (runtimeConfig: any, extensions: Runtime ...resolveAwsRegionExtensionConfiguration(extensionConfiguration), ...resolveDefaultRuntimeConfig(extensionConfiguration), ...resolveHttpHandlerRuntimeConfig(extensionConfiguration), + ...resolveHttpAuthRuntimeConfig(extensionConfiguration), }; }; diff --git a/clients/client-eventbridge/package.json b/clients/client-eventbridge/package.json index 7e1c4a876835..668d22bf4d3b 100644 --- a/clients/client-eventbridge/package.json +++ b/clients/client-eventbridge/package.json @@ -29,7 +29,6 @@ "@aws-sdk/middleware-host-header": "*", "@aws-sdk/middleware-logger": "*", "@aws-sdk/middleware-recursion-detection": "*", - "@aws-sdk/middleware-signing": "*", "@aws-sdk/middleware-user-agent": "*", "@aws-sdk/region-config-resolver": "*", "@aws-sdk/signature-v4-multi-region": "*", @@ -59,6 +58,7 @@ "@smithy/util-defaults-mode-browser": "^3.0.14", "@smithy/util-defaults-mode-node": "^3.0.14", "@smithy/util-endpoints": "^2.0.5", + "@smithy/util-middleware": "^3.0.3", "@smithy/util-retry": "^3.0.3", "@smithy/util-utf8": "^3.0.0", "tslib": "^2.6.2" diff --git a/clients/client-eventbridge/src/EventBridgeClient.ts b/clients/client-eventbridge/src/EventBridgeClient.ts index bd1f3f106afd..02dc2dc62e2a 100644 --- a/clients/client-eventbridge/src/EventBridgeClient.ts +++ b/clients/client-eventbridge/src/EventBridgeClient.ts @@ -7,20 +7,18 @@ import { } from "@aws-sdk/middleware-host-header"; import { getLoggerPlugin } from "@aws-sdk/middleware-logger"; import { getRecursionDetectionPlugin } from "@aws-sdk/middleware-recursion-detection"; -import { - AwsAuthInputConfig, - AwsAuthResolvedConfig, - getAwsAuthPlugin, - resolveAwsAuthConfig, -} from "@aws-sdk/middleware-signing"; import { getUserAgentPlugin, resolveUserAgentConfig, UserAgentInputConfig, UserAgentResolvedConfig, } from "@aws-sdk/middleware-user-agent"; -import { Credentials as __Credentials } from "@aws-sdk/types"; import { RegionInputConfig, RegionResolvedConfig, resolveRegionConfig } from "@smithy/config-resolver"; +import { + DefaultIdentityProviderConfig, + getHttpAuthSchemeEndpointRuleSetPlugin, + getHttpSigningPlugin, +} from "@smithy/core"; import { getContentLengthPlugin } from "@smithy/middleware-content-length"; import { EndpointInputConfig, EndpointResolvedConfig, resolveEndpointConfig } from "@smithy/middleware-endpoint"; import { getRetryPlugin, resolveRetryConfig, RetryInputConfig, RetryResolvedConfig } from "@smithy/middleware-retry"; @@ -32,6 +30,7 @@ import { SmithyResolvedConfiguration as __SmithyResolvedConfiguration, } from "@smithy/smithy-client"; import { + AwsCredentialIdentityProvider, BodyLengthCalculator as __BodyLengthCalculator, CheckOptionalClientConfig as __CheckOptionalClientConfig, ChecksumConstructor as __ChecksumConstructor, @@ -48,6 +47,12 @@ import { UserAgent as __UserAgent, } from "@smithy/types"; +import { + defaultEventBridgeHttpAuthSchemeParametersProvider, + HttpAuthSchemeInputConfig, + HttpAuthSchemeResolvedConfig, + resolveHttpAuthSchemeConfig, +} from "./auth/httpAuthSchemeProvider"; import { ActivateEventSourceCommandInput, ActivateEventSourceCommandOutput, @@ -387,9 +392,10 @@ export interface ClientDefaults extends Partial<__SmithyConfiguration<__HttpHand /** * Default credentials provider; Not available in browser runtime. + * @deprecated * @internal */ - credentialDefaultProvider?: (input: any) => __Provider<__Credentials>; + credentialDefaultProvider?: (input: any) => AwsCredentialIdentityProvider; /** * Value for how many times a request will be made at most in case of retry. @@ -429,7 +435,7 @@ export type EventBridgeClientConfigType = Partial<__SmithyConfiguration<__HttpHa RegionInputConfig & HostHeaderInputConfig & EndpointInputConfig & - AwsAuthInputConfig & + HttpAuthSchemeInputConfig & ClientInputEndpointParameters; /** * @public @@ -449,7 +455,7 @@ export type EventBridgeClientResolvedConfigType = __SmithyResolvedConfiguration< RegionResolvedConfig & HostHeaderResolvedConfig & EndpointResolvedConfig & - AwsAuthResolvedConfig & + HttpAuthSchemeResolvedConfig & ClientResolvedEndpointParameters; /** * @public @@ -501,7 +507,7 @@ export class EventBridgeClient extends __Client< const _config_4 = resolveRegionConfig(_config_3); const _config_5 = resolveHostHeaderConfig(_config_4); const _config_6 = resolveEndpointConfig(_config_5); - const _config_7 = resolveAwsAuthConfig(_config_6); + const _config_7 = resolveHttpAuthSchemeConfig(_config_6); const _config_8 = resolveRuntimeExtensions(_config_7, configuration?.extensions || []); super(_config_8); this.config = _config_8; @@ -511,7 +517,17 @@ export class EventBridgeClient extends __Client< this.middlewareStack.use(getHostHeaderPlugin(this.config)); this.middlewareStack.use(getLoggerPlugin(this.config)); this.middlewareStack.use(getRecursionDetectionPlugin(this.config)); - this.middlewareStack.use(getAwsAuthPlugin(this.config)); + this.middlewareStack.use( + getHttpAuthSchemeEndpointRuleSetPlugin(this.config, { + httpAuthSchemeParametersProvider: defaultEventBridgeHttpAuthSchemeParametersProvider, + identityProviderConfigProvider: async (config: EventBridgeClientResolvedConfig) => + new DefaultIdentityProviderConfig({ + "aws.auth#sigv4": config.credentials, + "aws.auth#sigv4a": config.credentials, + }), + }) + ); + this.middlewareStack.use(getHttpSigningPlugin(this.config)); } /** diff --git a/clients/client-eventbridge/src/auth/httpAuthExtensionConfiguration.ts b/clients/client-eventbridge/src/auth/httpAuthExtensionConfiguration.ts new file mode 100644 index 000000000000..5d18d25cdadb --- /dev/null +++ b/clients/client-eventbridge/src/auth/httpAuthExtensionConfiguration.ts @@ -0,0 +1,72 @@ +// smithy-typescript generated code +import { AwsCredentialIdentity, AwsCredentialIdentityProvider, HttpAuthScheme } from "@smithy/types"; + +import { EventBridgeHttpAuthSchemeProvider } from "./httpAuthSchemeProvider"; + +/** + * @internal + */ +export interface HttpAuthExtensionConfiguration { + setHttpAuthScheme(httpAuthScheme: HttpAuthScheme): void; + httpAuthSchemes(): HttpAuthScheme[]; + setHttpAuthSchemeProvider(httpAuthSchemeProvider: EventBridgeHttpAuthSchemeProvider): void; + httpAuthSchemeProvider(): EventBridgeHttpAuthSchemeProvider; + setCredentials(credentials: AwsCredentialIdentity | AwsCredentialIdentityProvider): void; + credentials(): AwsCredentialIdentity | AwsCredentialIdentityProvider | undefined; +} + +/** + * @internal + */ +export type HttpAuthRuntimeConfig = Partial<{ + httpAuthSchemes: HttpAuthScheme[]; + httpAuthSchemeProvider: EventBridgeHttpAuthSchemeProvider; + credentials: AwsCredentialIdentity | AwsCredentialIdentityProvider; +}>; + +/** + * @internal + */ +export const getHttpAuthExtensionConfiguration = ( + runtimeConfig: HttpAuthRuntimeConfig +): HttpAuthExtensionConfiguration => { + const _httpAuthSchemes = runtimeConfig.httpAuthSchemes!; + let _httpAuthSchemeProvider = runtimeConfig.httpAuthSchemeProvider!; + let _credentials = runtimeConfig.credentials; + return { + setHttpAuthScheme(httpAuthScheme: HttpAuthScheme): void { + const index = _httpAuthSchemes.findIndex((scheme) => scheme.schemeId === httpAuthScheme.schemeId); + if (index === -1) { + _httpAuthSchemes.push(httpAuthScheme); + } else { + _httpAuthSchemes.splice(index, 1, httpAuthScheme); + } + }, + httpAuthSchemes(): HttpAuthScheme[] { + return _httpAuthSchemes; + }, + setHttpAuthSchemeProvider(httpAuthSchemeProvider: EventBridgeHttpAuthSchemeProvider): void { + _httpAuthSchemeProvider = httpAuthSchemeProvider; + }, + httpAuthSchemeProvider(): EventBridgeHttpAuthSchemeProvider { + return _httpAuthSchemeProvider; + }, + setCredentials(credentials: AwsCredentialIdentity | AwsCredentialIdentityProvider): void { + _credentials = credentials; + }, + credentials(): AwsCredentialIdentity | AwsCredentialIdentityProvider | undefined { + return _credentials; + }, + }; +}; + +/** + * @internal + */ +export const resolveHttpAuthRuntimeConfig = (config: HttpAuthExtensionConfiguration): HttpAuthRuntimeConfig => { + return { + httpAuthSchemes: config.httpAuthSchemes(), + httpAuthSchemeProvider: config.httpAuthSchemeProvider(), + credentials: config.credentials(), + }; +}; diff --git a/clients/client-eventbridge/src/auth/httpAuthSchemeProvider.ts b/clients/client-eventbridge/src/auth/httpAuthSchemeProvider.ts new file mode 100644 index 000000000000..91efc1182208 --- /dev/null +++ b/clients/client-eventbridge/src/auth/httpAuthSchemeProvider.ts @@ -0,0 +1,323 @@ +// smithy-typescript generated code +import { + AwsSdkSigV4AuthInputConfig, + AwsSdkSigV4AuthResolvedConfig, + AwsSdkSigV4PreviouslyResolved, + resolveAwsSdkSigV4Config, +} from "@aws-sdk/core"; +import { signatureV4CrtContainer } from "@aws-sdk/signature-v4-multi-region"; +import { EndpointParameterInstructions, resolveParams } from "@smithy/middleware-endpoint"; +import { + EndpointV2, + HandlerExecutionContext, + HttpAuthOption, + HttpAuthScheme, + HttpAuthSchemeId, + HttpAuthSchemeParameters, + HttpAuthSchemeParametersProvider, + HttpAuthSchemeProvider, + Logger, +} from "@smithy/types"; +import { getSmithyContext, normalizeProvider } from "@smithy/util-middleware"; + +import { EndpointParameters } from "../endpoint/EndpointParameters"; +import { defaultEndpointResolver } from "../endpoint/endpointResolver"; +import { EventBridgeClientConfig, EventBridgeClientResolvedConfig } from "../EventBridgeClient"; + +/** + * @internal + */ +interface _EventBridgeHttpAuthSchemeParameters extends HttpAuthSchemeParameters { + region?: string; +} + +/** + * @internal + */ +export interface EventBridgeHttpAuthSchemeParameters extends _EventBridgeHttpAuthSchemeParameters, EndpointParameters { + region?: string; +} + +/** + * @internal + */ +export interface EventBridgeHttpAuthSchemeParametersProvider + extends HttpAuthSchemeParametersProvider< + EventBridgeClientResolvedConfig, + HandlerExecutionContext, + EventBridgeHttpAuthSchemeParameters, + object + > {} + +/** + * @internal + */ +interface EndpointRuleSetSmithyContext { + commandInstance?: { + constructor?: { + getEndpointParameterInstructions(): EndpointParameterInstructions; + }; + }; +} +/** + * @internal + */ +interface EndpointRuleSetHttpAuthSchemeParametersProvider< + TConfig extends object, + TContext extends HandlerExecutionContext, + TParameters extends HttpAuthSchemeParameters & EndpointParameters, + TInput extends object +> extends HttpAuthSchemeParametersProvider {} +/** + * @internal + */ +const createEndpointRuleSetHttpAuthSchemeParametersProvider = + < + TConfig extends object, + TContext extends HandlerExecutionContext, + THttpAuthSchemeParameters extends HttpAuthSchemeParameters, + TEndpointParameters extends EndpointParameters, + TParameters extends THttpAuthSchemeParameters & TEndpointParameters, + TInput extends object + >( + defaultHttpAuthSchemeParametersProvider: HttpAuthSchemeParametersProvider< + TConfig, + TContext, + THttpAuthSchemeParameters, + TInput + > + ): EndpointRuleSetHttpAuthSchemeParametersProvider< + TConfig, + TContext, + THttpAuthSchemeParameters & TEndpointParameters, + TInput + > => + async (config: TConfig, context: TContext, input: TInput): Promise => { + if (!input) { + throw new Error(`Could not find \`input\` for \`defaultEndpointRuleSetHttpAuthSchemeParametersProvider\``); + } + const defaultParameters = await defaultHttpAuthSchemeParametersProvider(config, context, input); + const instructionsFn = (getSmithyContext(context) as EndpointRuleSetSmithyContext)?.commandInstance?.constructor + ?.getEndpointParameterInstructions; + if (!instructionsFn) { + throw new Error(`getEndpointParameterInstructions() is not defined on \`${context.commandName!}\``); + } + const endpointParameters = await resolveParams( + input as Record, + { getEndpointParameterInstructions: instructionsFn! }, + config as Record + ); + return Object.assign(defaultParameters, endpointParameters) as TParameters; + }; +/** + * @internal + */ +const _defaultEventBridgeHttpAuthSchemeParametersProvider = async ( + config: EventBridgeClientResolvedConfig, + context: HandlerExecutionContext, + input: object +): Promise<_EventBridgeHttpAuthSchemeParameters> => { + return { + operation: getSmithyContext(context).operation as string, + region: + (await normalizeProvider(config.region)()) || + (() => { + throw new Error("expected `region` to be configured for `aws.auth#sigv4`"); + })(), + }; +}; +/** + * @internal + */ +export const defaultEventBridgeHttpAuthSchemeParametersProvider: EventBridgeHttpAuthSchemeParametersProvider = + createEndpointRuleSetHttpAuthSchemeParametersProvider(_defaultEventBridgeHttpAuthSchemeParametersProvider); + +function createAwsAuthSigv4HttpAuthOption(authParameters: EventBridgeHttpAuthSchemeParameters): HttpAuthOption { + return { + schemeId: "aws.auth#sigv4", + signingProperties: { + name: "events", + region: authParameters.region, + }, + propertiesExtractor: (config: Partial, context) => ({ + /** + * @internal + */ + signingProperties: { + config, + context, + }, + }), + }; +} + +function createAwsAuthSigv4aHttpAuthOption(authParameters: EventBridgeHttpAuthSchemeParameters): HttpAuthOption { + return { + schemeId: "aws.auth#sigv4a", + signingProperties: { + name: "events", + region: authParameters.region, + }, + propertiesExtractor: (config: Partial, context) => ({ + /** + * @internal + */ + signingProperties: { + config, + context, + }, + }), + }; +} + +/** + * @internal + */ +interface _EventBridgeHttpAuthSchemeProvider extends HttpAuthSchemeProvider {} + +/** + * @internal + */ +export interface EventBridgeHttpAuthSchemeProvider + extends HttpAuthSchemeProvider {} + +/** + * @internal + */ +interface EndpointRuleSetHttpAuthSchemeProvider< + EndpointParametersT extends EndpointParameters, + HttpAuthSchemeParametersT extends HttpAuthSchemeParameters +> extends HttpAuthSchemeProvider {} +/** + * @internal + */ +interface DefaultEndpointResolver { + (params: EndpointParametersT, context?: { logger?: Logger }): EndpointV2; +} +/** + * @internal + */ +const createEndpointRuleSetHttpAuthSchemeProvider = < + EndpointParametersT extends EndpointParameters, + HttpAuthSchemeParametersT extends HttpAuthSchemeParameters +>( + defaultEndpointResolver: DefaultEndpointResolver, + defaultHttpAuthSchemeResolver: HttpAuthSchemeProvider, + createHttpAuthOptionFunctions: Record< + HttpAuthSchemeId, + (authParameters: EndpointParametersT & HttpAuthSchemeParametersT) => HttpAuthOption + > +): EndpointRuleSetHttpAuthSchemeProvider => { + const endpointRuleSetHttpAuthSchemeProvider: EndpointRuleSetHttpAuthSchemeProvider< + EndpointParametersT, + HttpAuthSchemeParametersT + > = (authParameters) => { + const endpoint: EndpointV2 = defaultEndpointResolver(authParameters); + const authSchemes = endpoint.properties?.authSchemes; + if (!authSchemes) { + return defaultHttpAuthSchemeResolver(authParameters); + } + const options: HttpAuthOption[] = []; + for (const scheme of authSchemes) { + const { name: resolvedName, properties = {}, ...rest } = scheme; + const name = resolvedName.toLowerCase(); + if (resolvedName !== name) { + console.warn(`HttpAuthScheme has been normalized with lowercasing: \`${resolvedName}\` to \`${name}\``); + } + let schemeId; + if (name === "sigv4a") { + schemeId = "aws.auth#sigv4a"; + const sigv4Present = authSchemes.find((s) => { + const name = s.name.toLowerCase(); + return name !== "sigv4a" && name.startsWith("sigv4"); + }); + if (!signatureV4CrtContainer.CrtSignerV4 && sigv4Present) { + // sigv4a -> sigv4 fallback. + continue; + } + } else if (name.startsWith("sigv4")) { + schemeId = "aws.auth#sigv4"; + } else { + throw new Error(`Unknown HttpAuthScheme found in \`@smithy.rules#endpointRuleSet\`: \`${name}\``); + } + const createOption = createHttpAuthOptionFunctions[schemeId]; + if (!createOption) { + throw new Error(`Could not find HttpAuthOption create function for \`${schemeId}\``); + } + const option = createOption(authParameters); + option.schemeId = schemeId; + option.signingProperties = { ...(option.signingProperties || {}), ...rest, ...properties }; + options.push(option); + } + return options; + }; + + return endpointRuleSetHttpAuthSchemeProvider; +}; +/** + * @internal + */ +const _defaultEventBridgeHttpAuthSchemeProvider: _EventBridgeHttpAuthSchemeProvider = (authParameters) => { + const options: HttpAuthOption[] = []; + switch (authParameters.operation) { + default: { + options.push(createAwsAuthSigv4HttpAuthOption(authParameters)); + options.push(createAwsAuthSigv4aHttpAuthOption(authParameters)); + } + } + return options; +}; +/** + * @internal + */ +export const defaultEventBridgeHttpAuthSchemeProvider: EventBridgeHttpAuthSchemeProvider = + createEndpointRuleSetHttpAuthSchemeProvider(defaultEndpointResolver, _defaultEventBridgeHttpAuthSchemeProvider, { + "aws.auth#sigv4": createAwsAuthSigv4HttpAuthOption, + "aws.auth#sigv4a": createAwsAuthSigv4aHttpAuthOption, + }); + +/** + * @internal + */ +export interface HttpAuthSchemeInputConfig extends AwsSdkSigV4AuthInputConfig { + /** + * Configuration of HttpAuthSchemes for a client which provides default identity providers and signers per auth scheme. + * @internal + */ + httpAuthSchemes?: HttpAuthScheme[]; + + /** + * Configuration of an HttpAuthSchemeProvider for a client which resolves which HttpAuthScheme to use. + * @internal + */ + httpAuthSchemeProvider?: EventBridgeHttpAuthSchemeProvider; +} + +/** + * @internal + */ +export interface HttpAuthSchemeResolvedConfig extends AwsSdkSigV4AuthResolvedConfig { + /** + * Configuration of HttpAuthSchemes for a client which provides default identity providers and signers per auth scheme. + * @internal + */ + readonly httpAuthSchemes: HttpAuthScheme[]; + + /** + * Configuration of an HttpAuthSchemeProvider for a client which resolves which HttpAuthScheme to use. + * @internal + */ + readonly httpAuthSchemeProvider: EventBridgeHttpAuthSchemeProvider; +} + +/** + * @internal + */ +export const resolveHttpAuthSchemeConfig = ( + config: T & HttpAuthSchemeInputConfig & AwsSdkSigV4PreviouslyResolved +): T & HttpAuthSchemeResolvedConfig => { + const config_0 = resolveAwsSdkSigV4Config(config); + return { + ...config_0, + } as T & HttpAuthSchemeResolvedConfig; +}; diff --git a/clients/client-eventbridge/src/extensionConfiguration.ts b/clients/client-eventbridge/src/extensionConfiguration.ts index 4b23f104fb29..23e76e76e003 100644 --- a/clients/client-eventbridge/src/extensionConfiguration.ts +++ b/clients/client-eventbridge/src/extensionConfiguration.ts @@ -3,10 +3,13 @@ import { AwsRegionExtensionConfiguration } from "@aws-sdk/types"; import { HttpHandlerExtensionConfiguration } from "@smithy/protocol-http"; import { DefaultExtensionConfiguration } from "@smithy/types"; +import { HttpAuthExtensionConfiguration } from "./auth/httpAuthExtensionConfiguration"; + /** * @internal */ export interface EventBridgeExtensionConfiguration extends HttpHandlerExtensionConfiguration, DefaultExtensionConfiguration, - AwsRegionExtensionConfiguration {} + AwsRegionExtensionConfiguration, + HttpAuthExtensionConfiguration {} diff --git a/clients/client-eventbridge/src/runtimeConfig.shared.ts b/clients/client-eventbridge/src/runtimeConfig.shared.ts index c943d83e5fcf..e6fcba8252a0 100644 --- a/clients/client-eventbridge/src/runtimeConfig.shared.ts +++ b/clients/client-eventbridge/src/runtimeConfig.shared.ts @@ -1,10 +1,13 @@ // smithy-typescript generated code +import { AwsSdkSigV4ASigner, AwsSdkSigV4Signer } from "@aws-sdk/core"; import { SignatureV4MultiRegion } from "@aws-sdk/signature-v4-multi-region"; import { NoOpLogger } from "@smithy/smithy-client"; +import { IdentityProviderConfig } from "@smithy/types"; import { parseUrl } from "@smithy/url-parser"; import { fromBase64, toBase64 } from "@smithy/util-base64"; import { fromUtf8, toUtf8 } from "@smithy/util-utf8"; +import { defaultEventBridgeHttpAuthSchemeProvider } from "./auth/httpAuthSchemeProvider"; import { defaultEndpointResolver } from "./endpoint/endpointResolver"; import { EventBridgeClientConfig } from "./EventBridgeClient"; @@ -19,6 +22,19 @@ export const getRuntimeConfig = (config: EventBridgeClientConfig) => { disableHostPrefix: config?.disableHostPrefix ?? false, endpointProvider: config?.endpointProvider ?? defaultEndpointResolver, extensions: config?.extensions ?? [], + httpAuthSchemeProvider: config?.httpAuthSchemeProvider ?? defaultEventBridgeHttpAuthSchemeProvider, + httpAuthSchemes: config?.httpAuthSchemes ?? [ + { + schemeId: "aws.auth#sigv4", + identityProvider: (ipc: IdentityProviderConfig) => ipc.getIdentityProvider("aws.auth#sigv4"), + signer: new AwsSdkSigV4Signer(), + }, + { + schemeId: "aws.auth#sigv4a", + identityProvider: (ipc: IdentityProviderConfig) => ipc.getIdentityProvider("aws.auth#sigv4a"), + signer: new AwsSdkSigV4ASigner(), + }, + ], logger: config?.logger ?? new NoOpLogger(), serviceId: config?.serviceId ?? "EventBridge", signerConstructor: config?.signerConstructor ?? SignatureV4MultiRegion, diff --git a/clients/client-eventbridge/src/runtimeExtensions.ts b/clients/client-eventbridge/src/runtimeExtensions.ts index 98bdd32afc41..8ad8b7690c2a 100644 --- a/clients/client-eventbridge/src/runtimeExtensions.ts +++ b/clients/client-eventbridge/src/runtimeExtensions.ts @@ -6,6 +6,7 @@ import { import { getHttpHandlerExtensionConfiguration, resolveHttpHandlerRuntimeConfig } from "@smithy/protocol-http"; import { getDefaultExtensionConfiguration, resolveDefaultRuntimeConfig } from "@smithy/smithy-client"; +import { getHttpAuthExtensionConfiguration, resolveHttpAuthRuntimeConfig } from "./auth/httpAuthExtensionConfiguration"; import { EventBridgeExtensionConfiguration } from "./extensionConfiguration"; /** @@ -32,6 +33,7 @@ export const resolveRuntimeExtensions = (runtimeConfig: any, extensions: Runtime ...asPartial(getAwsRegionExtensionConfiguration(runtimeConfig)), ...asPartial(getDefaultExtensionConfiguration(runtimeConfig)), ...asPartial(getHttpHandlerExtensionConfiguration(runtimeConfig)), + ...asPartial(getHttpAuthExtensionConfiguration(runtimeConfig)), }; extensions.forEach((extension) => extension.configure(extensionConfiguration)); @@ -41,5 +43,6 @@ export const resolveRuntimeExtensions = (runtimeConfig: any, extensions: Runtime ...resolveAwsRegionExtensionConfiguration(extensionConfiguration), ...resolveDefaultRuntimeConfig(extensionConfiguration), ...resolveHttpHandlerRuntimeConfig(extensionConfiguration), + ...resolveHttpAuthRuntimeConfig(extensionConfiguration), }; }; diff --git a/clients/client-lex-runtime-v2/src/models/models_0.ts b/clients/client-lex-runtime-v2/src/models/models_0.ts index e027b325afa8..d69dad133106 100644 --- a/clients/client-lex-runtime-v2/src/models/models_0.ts +++ b/clients/client-lex-runtime-v2/src/models/models_0.ts @@ -1,5 +1,6 @@ // smithy-typescript generated code import { ExceptionOptionType as __ExceptionOptionType, SENSITIVE_STRING } from "@smithy/smithy-client"; + import { StreamingBlobTypes } from "@smithy/types"; import { LexRuntimeV2ServiceException as __BaseException } from "./LexRuntimeV2ServiceException"; diff --git a/codegen/sdk-codegen/build.gradle.kts b/codegen/sdk-codegen/build.gradle.kts index 3480ced0db77..d35907d2b080 100644 --- a/codegen/sdk-codegen/build.gradle.kts +++ b/codegen/sdk-codegen/build.gradle.kts @@ -107,9 +107,6 @@ tasks.register("generate-smithy-build") { .readText() ).expectObjectNode() val nonExperimentalIdentityAndAuthServices = setOf( - // Endpoint Ruleset Auth Scheme Resolvers - "EventBridge", - "CloudFront KeyValueStore", // S3 "S3", ) diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddCloudFrontKeyValueStorePlugin.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddCloudFrontKeyValueStorePlugin.java deleted file mode 100644 index f03a949e0c99..000000000000 --- a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddCloudFrontKeyValueStorePlugin.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - -package software.amazon.smithy.aws.typescript.codegen; - -import java.util.Collections; -import java.util.Map; -import java.util.function.Consumer; -import software.amazon.smithy.aws.traits.ServiceTrait; -import software.amazon.smithy.codegen.core.SymbolProvider; -import software.amazon.smithy.model.Model; -import software.amazon.smithy.model.shapes.Shape; -import software.amazon.smithy.typescript.codegen.LanguageTarget; -import software.amazon.smithy.typescript.codegen.TypeScriptSettings; -import software.amazon.smithy.typescript.codegen.TypeScriptWriter; -import software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration; -import software.amazon.smithy.utils.MapUtils; -import software.amazon.smithy.utils.SmithyInternalApi; - -/** - * Adds customizations for CloudFront KeyValueStore service. - */ -@SmithyInternalApi -public final class AddCloudFrontKeyValueStorePlugin implements TypeScriptIntegration { - public Map> getRuntimeConfigWriters(TypeScriptSettings settings, Model model, - SymbolProvider symbolProvider, LanguageTarget target) { - if (!testServiceId(settings.getService(model))) { - return Collections.emptyMap(); - } - switch (target) { - case SHARED: - return MapUtils.of("signerConstructor", writer -> { - writer.addDependency(AwsDependency.SIGNATURE_V4_MULTIREGION) - .addImport("SignatureV4MultiRegion", "SignatureV4MultiRegion", - AwsDependency.SIGNATURE_V4_MULTIREGION) - .write("SignatureV4MultiRegion"); - }); - default: - return Collections.emptyMap(); - } - } - - private static boolean testServiceId(Shape serviceShape) { - return serviceShape.getTrait(ServiceTrait.class) - .map(ServiceTrait::getSdkId).orElse("") - .equals("CloudFront KeyValueStore"); - } -} diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddEventBridgePlugin.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddEventBridgePlugin.java deleted file mode 100644 index 05a02a8e308c..000000000000 --- a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddEventBridgePlugin.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package software.amazon.smithy.aws.typescript.codegen; - -import java.util.Collections; -import java.util.Map; -import java.util.function.Consumer; -import software.amazon.smithy.aws.traits.ServiceTrait; -import software.amazon.smithy.codegen.core.SymbolProvider; -import software.amazon.smithy.model.Model; -import software.amazon.smithy.model.shapes.Shape; -import software.amazon.smithy.typescript.codegen.LanguageTarget; -import software.amazon.smithy.typescript.codegen.TypeScriptSettings; -import software.amazon.smithy.typescript.codegen.TypeScriptWriter; -import software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration; -import software.amazon.smithy.utils.MapUtils; -import software.amazon.smithy.utils.SmithyInternalApi; - -/** - * Adds customizations for EventBridge service. - */ -@SmithyInternalApi -public final class AddEventBridgePlugin implements TypeScriptIntegration { - public Map> getRuntimeConfigWriters(TypeScriptSettings settings, Model model, - SymbolProvider symbolProvider, LanguageTarget target) { - if (!testServiceId(settings.getService(model))) { - return Collections.emptyMap(); - } - switch (target) { - case SHARED: - return MapUtils.of("signerConstructor", writer -> { - writer.addDependency(AwsDependency.SIGNATURE_V4_MULTIREGION) - .addImport("SignatureV4MultiRegion", "SignatureV4MultiRegion", - AwsDependency.SIGNATURE_V4_MULTIREGION) - .write("SignatureV4MultiRegion"); - }); - default: - return Collections.emptyMap(); - } - } - - private static boolean testServiceId(Shape serviceShape) { - return serviceShape.getTrait(ServiceTrait.class).map(ServiceTrait::getSdkId).orElse("").equals("EventBridge"); - } -} diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddS3Config.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddS3Config.java index 664ed2c29b03..45a9c95a05b5 100644 --- a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddS3Config.java +++ b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddS3Config.java @@ -237,16 +237,14 @@ public Map> 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 -> { diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddSigv4aPlugin.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddSigv4aPlugin.java index ffdae237beb6..a9424c9fbd9c 100644 --- a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddSigv4aPlugin.java +++ b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddSigv4aPlugin.java @@ -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; @@ -27,18 +25,17 @@ public final class AddSigv4aPlugin implements TypeScriptIntegration { @Override public boolean matchesSettings(TypeScriptSettings settings) { - return !!settings.useLegacyAuth(); + return settings.useLegacyAuth(); } + @Override public Map> 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. diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AwsTraitsUtils.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AwsTraitsUtils.java index 069071f05ed8..7828466f1016 100644 --- a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AwsTraitsUtils.java +++ b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AwsTraitsUtils.java @@ -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; @@ -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 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() {} @@ -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); } diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/auth/http/integration/AwsSdkCustomizeEndpointRuleSetHttpAuthSchemeProvider.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/auth/http/integration/AwsSdkCustomizeEndpointRuleSetHttpAuthSchemeProvider.java index 751a99454beb..24009df0f622 100644 --- a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/auth/http/integration/AwsSdkCustomizeEndpointRuleSetHttpAuthSchemeProvider.java +++ b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/auth/http/integration/AwsSdkCustomizeEndpointRuleSetHttpAuthSchemeProvider.java @@ -6,10 +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; @@ -18,8 +23,8 @@ import software.amazon.smithy.model.shapes.OperationShape; import software.amazon.smithy.model.shapes.ShapeId; import software.amazon.smithy.model.traits.DynamicTrait; -import software.amazon.smithy.rulesengine.traits.EndpointRuleSetTrait; 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; @@ -36,10 +41,9 @@ import software.amazon.smithy.typescript.codegen.auth.http.sections.HttpAuthSchemeParametersInterfaceCodeSection; import software.amazon.smithy.typescript.codegen.auth.http.sections.HttpAuthSchemeProviderInterfaceCodeSection; import software.amazon.smithy.typescript.codegen.endpointsV2.EndpointsV2Generator; -import software.amazon.smithy.typescript.codegen.sections.PreCommandClassCodeSection; -import software.amazon.smithy.typescript.codegen.sections.SmithyContextCodeSection; import software.amazon.smithy.utils.CodeInterceptor; import software.amazon.smithy.utils.CodeSection; +import software.amazon.smithy.utils.MapUtils; import software.amazon.smithy.utils.SmithyInternalApi; /** @@ -50,10 +54,6 @@ */ @SmithyInternalApi public final class AwsSdkCustomizeEndpointRuleSetHttpAuthSchemeProvider implements HttpAuthTypeScriptIntegration { - private static final Set 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"); /** @@ -61,21 +61,44 @@ public final class AwsSdkCustomizeEndpointRuleSetHttpAuthSchemeProvider implemen */ @Override public boolean matchesSettings(TypeScriptSettings settings) { - return !settings.useLegacyAuth() - && ENDPOINT_RULESET_HTTP_AUTH_SCHEME_SERVICES.contains(settings.getService()); + return !settings.useLegacyAuth(); } @Override public List runBefore() { return List.of( - AddHttpAuthSchemePlugin.class.getCanonicalName()); + AddHttpAuthSchemePlugin.class.getCanonicalName() + ); } @Override public List runAfter() { return List.of( SupportSigV4Auth.class.getCanonicalName(), - AwsSdkCustomizeSigV4Auth.class.getCanonicalName()); + AwsSdkCustomizeSigV4Auth.class.getCanonicalName() + ); + } + + @Override + public Map> 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 @@ -83,6 +106,10 @@ 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"); @@ -98,19 +125,10 @@ public void customizeSupportedHttpAuthSchemes( public List> interceptors( TypeScriptCodegenContext codegenContext ) { + if (!AwsTraitsUtils.isSigV4AsymmetricService(codegenContext.model(), codegenContext.settings())) { + return Collections.emptyList(); + } return List.of( - CodeInterceptor.appender(PreCommandClassCodeSection.class, (w, s) -> { - w.write("// @ts-expect-error: Command class references itself"); - }), - CodeInterceptor.appender(SmithyContextCodeSection.class, (w, s) -> { - if (s.getService().hasTrait(EndpointRuleSetTrait.ID)) { - w.openBlock("endpointRuleSet: {", "},", () -> { - w.write("// @ts-expect-error: built class has getEndpointParameterInstructions()"); - w.write("getEndpointParameterInstructions: $T.getEndpointParameterInstructions,", - codegenContext.symbolProvider().toSymbol(s.getOperation())); - }); - } - }), new CodeInterceptor() { @Override public Class sectionType() { @@ -208,8 +226,10 @@ public void write( w.writeDocs("@internal"); w.write(""" interface EndpointRuleSetSmithyContext { - endpointRuleSet?: { - getEndpointParameterInstructions?: () => EndpointParameterInstructions; + commandInstance?: { + constructor?: { + getEndpointParameterInstructions(): EndpointParameterInstructions; + }; }; }"""); w.writeDocs("@internal"); @@ -251,7 +271,7 @@ interface EndpointRuleSetHttpAuthSchemeParametersProvider< const defaultParameters = \ await defaultHttpAuthSchemeParametersProvider(config, context, input); const instructionsFn = (getSmithyContext(context) as \ - EndpointRuleSetSmithyContext)?.endpointRuleSet + EndpointRuleSetSmithyContext)?.commandInstance?.constructor ?.getEndpointParameterInstructions; if (!instructionsFn) { throw new Error(`getEndpointParameterInstructions() is not defined on \ @@ -353,6 +373,7 @@ interface EndpointRuleSetHttpAuthSchemeProvider< HttpAuthSchemeParametersT extends HttpAuthSchemeParameters > extends HttpAuthSchemeProvider { }"""); w.addDependency(TypeScriptDependency.SMITHY_TYPES); + w.addImport("signatureV4CrtContainer", null, AwsDependency.SIGNATURE_V4_MULTIREGION); w.addImport("Logger", null, TypeScriptDependency.SMITHY_TYPES); w.addImport("EndpointV2", null, TypeScriptDependency.SMITHY_TYPES); w.writeDocs("@internal"); @@ -392,8 +413,16 @@ interface DefaultEndpointResolver { + const name = s.name.toLowerCase(); + return name !== "sigv4a" && name.startsWith("sigv4"); + }); + if (!signatureV4CrtContainer.CrtSignerV4 && sigv4Present) { + // sigv4a -> sigv4 fallback. + continue; + } } else if (name.startsWith("sigv4")) { schemeId = "aws.auth#sigv4"; } else { diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/auth/http/integration/AwsSdkCustomizeSigV4Auth.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/auth/http/integration/AwsSdkCustomizeSigV4Auth.java index d6c9462dbc18..82d1ff08d548 100644 --- a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/auth/http/integration/AwsSdkCustomizeSigV4Auth.java +++ b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/auth/http/integration/AwsSdkCustomizeSigV4Auth.java @@ -6,6 +6,7 @@ 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; @@ -13,6 +14,7 @@ import java.util.Map; import java.util.Set; import java.util.function.Consumer; +import software.amazon.smithy.aws.traits.auth.SigV4ATrait; import software.amazon.smithy.aws.traits.auth.SigV4Trait; import software.amazon.smithy.aws.typescript.codegen.AwsCredentialProviderUtils; import software.amazon.smithy.aws.typescript.codegen.AwsDependency; @@ -172,6 +174,19 @@ public void customizeSupportedHttpAuthSchemes( .write("new AwsSdkSigV4Signer()")) .build(); supportedHttpAuthSchemesIndex.putHttpAuthScheme(authScheme.getSchemeId(), authScheme); + + if (isSigV4AsymmetricService(model, settings)) { + HttpAuthScheme authSchemeSigV4a = supportedHttpAuthSchemesIndex + .getHttpAuthScheme(SigV4Trait.ID) + .toBuilder() + .schemeId(SigV4ATrait.ID) + .putDefaultSigner(LanguageTarget.SHARED, w -> w + .addDependency(AwsDependency.AWS_SDK_CORE) + .addImport("AwsSdkSigV4ASigner", null, AwsDependency.AWS_SDK_CORE) + .write("new AwsSdkSigV4ASigner()")) + .build(); + supportedHttpAuthSchemesIndex.putHttpAuthScheme(authSchemeSigV4a.getSchemeId(), authSchemeSigV4a); + } } } diff --git a/codegen/smithy-aws-typescript-codegen/src/main/resources/META-INF/services/software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration b/codegen/smithy-aws-typescript-codegen/src/main/resources/META-INF/services/software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration index 2eb53a454930..9eca961da6eb 100644 --- a/codegen/smithy-aws-typescript-codegen/src/main/resources/META-INF/services/software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration +++ b/codegen/smithy-aws-typescript-codegen/src/main/resources/META-INF/services/software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration @@ -26,9 +26,7 @@ software.amazon.smithy.aws.typescript.codegen.AddCrossRegionCopyingPlugin software.amazon.smithy.aws.typescript.codegen.AddDocumentClientPlugin software.amazon.smithy.aws.typescript.codegen.AddEndpointDiscoveryPlugin software.amazon.smithy.aws.typescript.codegen.AddHttpChecksumDependency -software.amazon.smithy.aws.typescript.codegen.AddEventBridgePlugin software.amazon.smithy.aws.typescript.codegen.AddSigv4aPlugin -software.amazon.smithy.aws.typescript.codegen.AddCloudFrontKeyValueStorePlugin software.amazon.smithy.aws.typescript.codegen.auth.http.integration.AwsSdkCustomizeHttpBearerTokenAuth software.amazon.smithy.aws.typescript.codegen.auth.http.integration.SupportSigV4Auth software.amazon.smithy.aws.typescript.codegen.auth.http.integration.AwsSdkCustomizeSigV4Auth diff --git a/packages/core/src/submodules/httpAuthSchemes/aws_sdk/AwsSdkSigV4ASigner.ts b/packages/core/src/submodules/httpAuthSchemes/aws_sdk/AwsSdkSigV4ASigner.ts new file mode 100644 index 000000000000..7a8c657b6e41 --- /dev/null +++ b/packages/core/src/submodules/httpAuthSchemes/aws_sdk/AwsSdkSigV4ASigner.ts @@ -0,0 +1,34 @@ +import { HttpRequest } from "@smithy/protocol-http"; +import { AwsCredentialIdentity, HttpRequest as IHttpRequest } from "@smithy/types"; + +import { getSkewCorrectedDate } from "../utils"; +import { AwsSdkSigV4Signer, validateSigningProperties } from "./AwsSdkSigV4Signer"; + +/** + * @internal + * Note: this is not a signing algorithm implementation. The sign method + * accepts the real signer as an input parameter. + */ +export class AwsSdkSigV4ASigner extends AwsSdkSigV4Signer { + async sign( + httpRequest: IHttpRequest, + identity: AwsCredentialIdentity, + signingProperties: Record + ): Promise { + if (!HttpRequest.isInstance(httpRequest)) { + throw new Error("The request is not an instance of `HttpRequest` and cannot be signed"); + } + + const { config, signer, signingRegion, signingRegionSet, signingName } = await validateSigningProperties( + signingProperties + ); + const multiRegionOverride: string | undefined = signingRegionSet?.join?.(",") ?? signingRegion; + + const signedRequest = await signer.sign(httpRequest, { + signingDate: getSkewCorrectedDate(config.systemClockOffset), + signingRegion: multiRegionOverride, + signingService: signingName, + }); + return signedRequest; + } +} diff --git a/packages/core/src/submodules/httpAuthSchemes/aws_sdk/AwsSdkSigV4Signer.ts b/packages/core/src/submodules/httpAuthSchemes/aws_sdk/AwsSdkSigV4Signer.ts index d8d17597755f..de78134d8824 100644 --- a/packages/core/src/submodules/httpAuthSchemes/aws_sdk/AwsSdkSigV4Signer.ts +++ b/packages/core/src/submodules/httpAuthSchemes/aws_sdk/AwsSdkSigV4Signer.ts @@ -37,6 +37,7 @@ interface AwsSdkSigV4AuthSigningProperties { config: AwsSdkSigV4Config; signer: RequestSigner; signingRegion?: string; + signingRegionSet?: string[]; signingName?: string; } @@ -53,7 +54,7 @@ interface AwsSdkSigV4Exception extends ServiceException { /** * @internal */ -const validateSigningProperties = async ( +export const validateSigningProperties = async ( signingProperties: Record ): Promise => { const context = throwSigningPropertyError( @@ -68,17 +69,21 @@ const validateSigningProperties = async ( ); const signer = await signerFunction(authScheme); const signingRegion: string | undefined = signingProperties?.signingRegion as string | undefined; + const signingRegionSet: string[] | undefined = signingProperties?.signingRegionSet as string[] | undefined; const signingName = signingProperties?.signingName as string | undefined; return { config, signer, signingRegion, + signingRegionSet, signingName, }; }; /** * @internal + * Note: this is not a signing algorithm implementation. The sign method + * accepts the real signer as an input parameter. */ export class AwsSdkSigV4Signer implements HttpSigner { async sign( @@ -93,7 +98,6 @@ export class AwsSdkSigV4Signer implements HttpSigner { throw new Error("The request is not an instance of `HttpRequest` and cannot be signed"); } const { config, signer, signingRegion, signingName } = await validateSigningProperties(signingProperties); - const signedRequest = await signer.sign(httpRequest, { signingDate: getSkewCorrectedDate(config.systemClockOffset), signingRegion: signingRegion, diff --git a/packages/core/src/submodules/httpAuthSchemes/aws_sdk/index.ts b/packages/core/src/submodules/httpAuthSchemes/aws_sdk/index.ts index 6d17c7096d04..98b5ca4fecad 100644 --- a/packages/core/src/submodules/httpAuthSchemes/aws_sdk/index.ts +++ b/packages/core/src/submodules/httpAuthSchemes/aws_sdk/index.ts @@ -1,2 +1,3 @@ -export * from "./AwsSdkSigV4Signer"; +export { AwsSdkSigV4Signer, AWSSDKSigV4Signer } from "./AwsSdkSigV4Signer"; +export { AwsSdkSigV4ASigner } from "./AwsSdkSigV4ASigner"; export * from "./resolveAwsSdkSigV4Config";