From 385a81d79f78071b94bcd54f85b64aee1c12a29d Mon Sep 17 00:00:00 2001 From: George Fu Date: Thu, 1 Aug 2024 01:28:35 +0000 Subject: [PATCH] chore(id-auth-sra): sigv4a compatibility for id-auth sra --- .../package.json | 2 +- .../src/CloudFrontKeyValueStoreClient.ts | 40 ++- .../auth/httpAuthExtensionConfiguration.ts | 72 ++++ .../src/auth/httpAuthSchemeProvider.ts | 338 ++++++++++++++++++ .../src/extensionConfiguration.ts | 5 +- .../src/runtimeConfig.shared.ts | 16 + .../src/runtimeExtensions.ts | 3 + clients/client-eventbridge/package.json | 3 +- .../src/EventBridgeClient.ts | 40 ++- .../auth/httpAuthExtensionConfiguration.ts | 72 ++++ .../src/auth/httpAuthSchemeProvider.ts | 320 +++++++++++++++++ .../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 - .../typescript/codegen/AddSigv4aPlugin.java | 2 +- ...EndpointRuleSetHttpAuthSchemeProvider.java | 34 +- .../integration/AwsSdkCustomizeSigV4Auth.java | 16 + .../aws_sdk/AwsSdkSigV4ASigner.ts | 34 ++ .../aws_sdk/AwsSdkSigV4Signer.ts | 8 +- .../httpAuthSchemes/aws_sdk/index.ts | 3 +- 22 files changed, 981 insertions(+), 55 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 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 a8ff7eca2a89..c0a8285395dc 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.13", "@smithy/util-defaults-mode-node": "^3.0.13", "@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..79b64e699d7e --- /dev/null +++ b/clients/client-cloudfront-keyvaluestore/src/auth/httpAuthSchemeProvider.ts @@ -0,0 +1,338 @@ +// 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) => s.name.toLowerCase().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 77f4f8c47950..a8ca06e9155a 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": "*", @@ -38,6 +37,7 @@ "@aws-sdk/util-user-agent-browser": "*", "@aws-sdk/util-user-agent-node": "*", "@smithy/config-resolver": "^3.0.5", + "@smithy/core": "^2.3.1", "@smithy/fetch-http-handler": "^3.2.4", "@smithy/hash-node": "^3.0.3", "@smithy/invalid-dependency": "^3.0.3", @@ -58,6 +58,7 @@ "@smithy/util-defaults-mode-browser": "^3.0.13", "@smithy/util-defaults-mode-node": "^3.0.13", "@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..428094275454 --- /dev/null +++ b/clients/client-eventbridge/src/auth/httpAuthSchemeProvider.ts @@ -0,0 +1,320 @@ +// 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) => s.name.toLowerCase().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/AddSigv4aPlugin.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddSigv4aPlugin.java index ffdae237beb6..3b03b1ba67f1 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 @@ -27,7 +27,7 @@ public final class AddSigv4aPlugin implements TypeScriptIntegration { @Override public boolean matchesSettings(TypeScriptSettings settings) { - return !!settings.useLegacyAuth(); + return settings.useLegacyAuth(); } public Map> getRuntimeConfigWriters( 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..402b7203c71a 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 @@ -9,6 +9,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import software.amazon.smithy.aws.typescript.codegen.AwsDependency; import software.amazon.smithy.codegen.core.Symbol; import software.amazon.smithy.model.Model; import software.amazon.smithy.model.knowledge.ServiceIndex; @@ -18,7 +19,6 @@ 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.TypeScriptCodegenContext; import software.amazon.smithy.typescript.codegen.TypeScriptDependency; @@ -36,8 +36,6 @@ 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.SmithyInternalApi; @@ -50,7 +48,7 @@ */ @SmithyInternalApi public final class AwsSdkCustomizeEndpointRuleSetHttpAuthSchemeProvider implements HttpAuthTypeScriptIntegration { - private static final Set ENDPOINT_RULESET_HTTP_AUTH_SCHEME_SERVICES = Set.of( + public 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")); @@ -99,18 +97,6 @@ public List> TypeScriptCodegenContext codegenContext ) { 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 +194,10 @@ public void write( w.writeDocs("@internal"); w.write(""" interface EndpointRuleSetSmithyContext { - endpointRuleSet?: { - getEndpointParameterInstructions?: () => EndpointParameterInstructions; + commandInstance?: { + constructor?: { + getEndpointParameterInstructions(): EndpointParameterInstructions; + }; }; }"""); w.writeDocs("@internal"); @@ -251,7 +239,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 +341,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 +381,13 @@ interface DefaultEndpointResolver s.name.toLowerCase().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..37f72e9e81a7 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 @@ -13,6 +13,9 @@ 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; import software.amazon.smithy.aws.typescript.codegen.AwsDependency; @@ -22,6 +25,7 @@ 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; @@ -172,6 +176,18 @@ public void customizeSupportedHttpAuthSchemes( .write("new AwsSdkSigV4Signer()")) .build(); supportedHttpAuthSchemesIndex.putHttpAuthScheme(authScheme.getSchemeId(), authScheme); + + if (AwsSdkCustomizeEndpointRuleSetHttpAuthSchemeProvider.ENDPOINT_RULESET_HTTP_AUTH_SCHEME_SERVICES + .contains(service.getId())) { + 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/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";