Skip to content

Commit

Permalink
feat(core/httpAuthSchemes): set configuration sources for sigv4a sign…
Browse files Browse the repository at this point in the history
…ingRegionSet (#6368)
  • Loading branch information
kuhe authored Aug 9, 2024
1 parent 628ffe5 commit 03bb39f
Show file tree
Hide file tree
Showing 14 changed files with 160 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
// smithy-typescript generated code
import {
AwsSdkSigV4AAuthInputConfig,
AwsSdkSigV4AAuthResolvedConfig,
AwsSdkSigV4APreviouslyResolved,
AwsSdkSigV4AuthInputConfig,
AwsSdkSigV4AuthResolvedConfig,
AwsSdkSigV4PreviouslyResolved,
resolveAwsSdkSigV4AConfig,
resolveAwsSdkSigV4Config,
} from "@aws-sdk/core";
import { signatureV4CrtContainer } from "@aws-sdk/signature-v4-multi-region";
Expand Down Expand Up @@ -297,7 +301,7 @@ export const defaultCloudFrontKeyValueStoreHttpAuthSchemeProvider: CloudFrontKey
/**
* @internal
*/
export interface HttpAuthSchemeInputConfig extends AwsSdkSigV4AuthInputConfig {
export interface HttpAuthSchemeInputConfig extends AwsSdkSigV4AuthInputConfig, AwsSdkSigV4AAuthInputConfig {
/**
* Configuration of HttpAuthSchemes for a client which provides default identity providers and signers per auth scheme.
* @internal
Expand All @@ -314,7 +318,7 @@ export interface HttpAuthSchemeInputConfig extends AwsSdkSigV4AuthInputConfig {
/**
* @internal
*/
export interface HttpAuthSchemeResolvedConfig extends AwsSdkSigV4AuthResolvedConfig {
export interface HttpAuthSchemeResolvedConfig extends AwsSdkSigV4AuthResolvedConfig, AwsSdkSigV4AAuthResolvedConfig {
/**
* Configuration of HttpAuthSchemes for a client which provides default identity providers and signers per auth scheme.
* @internal
Expand All @@ -332,10 +336,11 @@ export interface HttpAuthSchemeResolvedConfig extends AwsSdkSigV4AuthResolvedCon
* @internal
*/
export const resolveHttpAuthSchemeConfig = <T>(
config: T & HttpAuthSchemeInputConfig & AwsSdkSigV4PreviouslyResolved
config: T & HttpAuthSchemeInputConfig & AwsSdkSigV4PreviouslyResolved & AwsSdkSigV4APreviouslyResolved
): T & HttpAuthSchemeResolvedConfig => {
const config_0 = resolveAwsSdkSigV4Config(config);
const config_1 = resolveAwsSdkSigV4AConfig(config_0);
return {
...config_0,
...config_1,
} as T & HttpAuthSchemeResolvedConfig;
};
3 changes: 2 additions & 1 deletion clients/client-cloudfront-keyvaluestore/src/runtimeConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// @ts-ignore: package.json will be imported from dist folders
import packageInfo from "../package.json"; // eslint-disable-line

import { emitWarningIfUnsupportedVersion as awsCheckVersion } from "@aws-sdk/core";
import { NODE_SIGV4A_CONFIG_OPTIONS, emitWarningIfUnsupportedVersion as awsCheckVersion } from "@aws-sdk/core";
import { defaultProvider as credentialDefaultProvider } from "@aws-sdk/credential-provider-node";
import { defaultUserAgent } from "@aws-sdk/util-user-agent-node";
import {
Expand Down Expand Up @@ -52,6 +52,7 @@ export const getRuntimeConfig = (config: CloudFrontKeyValueStoreClientConfig) =>
default: async () => (await defaultConfigProvider()).retryMode || DEFAULT_RETRY_MODE,
}),
sha256: config?.sha256 ?? Hash.bind(null, "sha256"),
sigv4aSigningRegionSet: config?.sigv4aSigningRegionSet ?? loadNodeConfig(NODE_SIGV4A_CONFIG_OPTIONS),
streamCollector: config?.streamCollector ?? streamCollector,
useDualstackEndpoint: config?.useDualstackEndpoint ?? loadNodeConfig(NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS),
useFipsEndpoint: config?.useFipsEndpoint ?? loadNodeConfig(NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS),
Expand Down
13 changes: 9 additions & 4 deletions clients/client-eventbridge/src/auth/httpAuthSchemeProvider.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
// smithy-typescript generated code
import {
AwsSdkSigV4AAuthInputConfig,
AwsSdkSigV4AAuthResolvedConfig,
AwsSdkSigV4APreviouslyResolved,
AwsSdkSigV4AuthInputConfig,
AwsSdkSigV4AuthResolvedConfig,
AwsSdkSigV4PreviouslyResolved,
resolveAwsSdkSigV4AConfig,
resolveAwsSdkSigV4Config,
} from "@aws-sdk/core";
import { signatureV4CrtContainer } from "@aws-sdk/signature-v4-multi-region";
Expand Down Expand Up @@ -279,7 +283,7 @@ export const defaultEventBridgeHttpAuthSchemeProvider: EventBridgeHttpAuthScheme
/**
* @internal
*/
export interface HttpAuthSchemeInputConfig extends AwsSdkSigV4AuthInputConfig {
export interface HttpAuthSchemeInputConfig extends AwsSdkSigV4AuthInputConfig, AwsSdkSigV4AAuthInputConfig {
/**
* Configuration of HttpAuthSchemes for a client which provides default identity providers and signers per auth scheme.
* @internal
Expand All @@ -296,7 +300,7 @@ export interface HttpAuthSchemeInputConfig extends AwsSdkSigV4AuthInputConfig {
/**
* @internal
*/
export interface HttpAuthSchemeResolvedConfig extends AwsSdkSigV4AuthResolvedConfig {
export interface HttpAuthSchemeResolvedConfig extends AwsSdkSigV4AuthResolvedConfig, AwsSdkSigV4AAuthResolvedConfig {
/**
* Configuration of HttpAuthSchemes for a client which provides default identity providers and signers per auth scheme.
* @internal
Expand All @@ -314,10 +318,11 @@ export interface HttpAuthSchemeResolvedConfig extends AwsSdkSigV4AuthResolvedCon
* @internal
*/
export const resolveHttpAuthSchemeConfig = <T>(
config: T & HttpAuthSchemeInputConfig & AwsSdkSigV4PreviouslyResolved
config: T & HttpAuthSchemeInputConfig & AwsSdkSigV4PreviouslyResolved & AwsSdkSigV4APreviouslyResolved
): T & HttpAuthSchemeResolvedConfig => {
const config_0 = resolveAwsSdkSigV4Config(config);
const config_1 = resolveAwsSdkSigV4AConfig(config_0);
return {
...config_0,
...config_1,
} as T & HttpAuthSchemeResolvedConfig;
};
3 changes: 2 additions & 1 deletion clients/client-eventbridge/src/runtimeConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// @ts-ignore: package.json will be imported from dist folders
import packageInfo from "../package.json"; // eslint-disable-line

import { emitWarningIfUnsupportedVersion as awsCheckVersion } from "@aws-sdk/core";
import { NODE_SIGV4A_CONFIG_OPTIONS, emitWarningIfUnsupportedVersion as awsCheckVersion } from "@aws-sdk/core";
import { defaultProvider as credentialDefaultProvider } from "@aws-sdk/credential-provider-node";
import { defaultUserAgent } from "@aws-sdk/util-user-agent-node";
import {
Expand Down Expand Up @@ -52,6 +52,7 @@ export const getRuntimeConfig = (config: EventBridgeClientConfig) => {
default: async () => (await defaultConfigProvider()).retryMode || DEFAULT_RETRY_MODE,
}),
sha256: config?.sha256 ?? Hash.bind(null, "sha256"),
sigv4aSigningRegionSet: config?.sigv4aSigningRegionSet ?? loadNodeConfig(NODE_SIGV4A_CONFIG_OPTIONS),
streamCollector: config?.streamCollector ?? streamCollector,
useDualstackEndpoint: config?.useDualstackEndpoint ?? loadNodeConfig(NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS),
useFipsEndpoint: config?.useFipsEndpoint ?? loadNodeConfig(NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS),
Expand Down
13 changes: 9 additions & 4 deletions clients/client-s3/src/auth/httpAuthSchemeProvider.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
// smithy-typescript generated code
import {
AwsSdkSigV4AAuthInputConfig,
AwsSdkSigV4AAuthResolvedConfig,
AwsSdkSigV4APreviouslyResolved,
AwsSdkSigV4AuthInputConfig,
AwsSdkSigV4AuthResolvedConfig,
AwsSdkSigV4PreviouslyResolved,
resolveAwsSdkSigV4AConfig,
resolveAwsSdkSigV4Config,
} from "@aws-sdk/core";
import { signatureV4CrtContainer } from "@aws-sdk/signature-v4-multi-region";
Expand Down Expand Up @@ -281,7 +285,7 @@ export const defaultS3HttpAuthSchemeProvider: S3HttpAuthSchemeProvider = createE
/**
* @internal
*/
export interface HttpAuthSchemeInputConfig extends AwsSdkSigV4AuthInputConfig {
export interface HttpAuthSchemeInputConfig extends AwsSdkSigV4AuthInputConfig, AwsSdkSigV4AAuthInputConfig {
/**
* Configuration of HttpAuthSchemes for a client which provides default identity providers and signers per auth scheme.
* @internal
Expand All @@ -298,7 +302,7 @@ export interface HttpAuthSchemeInputConfig extends AwsSdkSigV4AuthInputConfig {
/**
* @internal
*/
export interface HttpAuthSchemeResolvedConfig extends AwsSdkSigV4AuthResolvedConfig {
export interface HttpAuthSchemeResolvedConfig extends AwsSdkSigV4AuthResolvedConfig, AwsSdkSigV4AAuthResolvedConfig {
/**
* Configuration of HttpAuthSchemes for a client which provides default identity providers and signers per auth scheme.
* @internal
Expand All @@ -316,10 +320,11 @@ export interface HttpAuthSchemeResolvedConfig extends AwsSdkSigV4AuthResolvedCon
* @internal
*/
export const resolveHttpAuthSchemeConfig = <T>(
config: T & HttpAuthSchemeInputConfig & AwsSdkSigV4PreviouslyResolved
config: T & HttpAuthSchemeInputConfig & AwsSdkSigV4PreviouslyResolved & AwsSdkSigV4APreviouslyResolved
): T & HttpAuthSchemeResolvedConfig => {
const config_0 = resolveAwsSdkSigV4Config(config);
const config_1 = resolveAwsSdkSigV4AConfig(config_0);
return {
...config_0,
...config_1,
} as T & HttpAuthSchemeResolvedConfig;
};
3 changes: 2 additions & 1 deletion clients/client-s3/src/runtimeConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// @ts-ignore: package.json will be imported from dist folders
import packageInfo from "../package.json"; // eslint-disable-line

import { emitWarningIfUnsupportedVersion as awsCheckVersion } from "@aws-sdk/core";
import { NODE_SIGV4A_CONFIG_OPTIONS, emitWarningIfUnsupportedVersion as awsCheckVersion } from "@aws-sdk/core";
import { defaultProvider as credentialDefaultProvider } from "@aws-sdk/credential-provider-node";
import { NODE_USE_ARN_REGION_CONFIG_OPTIONS } from "@aws-sdk/middleware-bucket-endpoint";
import { NODE_DISABLE_S3_EXPRESS_SESSION_AUTH_OPTIONS } from "@aws-sdk/middleware-sdk-s3";
Expand Down Expand Up @@ -62,6 +62,7 @@ export const getRuntimeConfig = (config: S3ClientConfig) => {
}),
sha1: config?.sha1 ?? Hash.bind(null, "sha1"),
sha256: config?.sha256 ?? Hash.bind(null, "sha256"),
sigv4aSigningRegionSet: config?.sigv4aSigningRegionSet ?? loadNodeConfig(NODE_SIGV4A_CONFIG_OPTIONS),
streamCollector: config?.streamCollector ?? streamCollector,
streamHasher: config?.streamHasher ?? streamHasher,
useArnRegion: config?.useArnRegion ?? loadNodeConfig(NODE_USE_ARN_REGION_CONFIG_OPTIONS),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,16 @@ public static boolean isSigV4Service(ServiceShape serviceShape) {
}

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

public static boolean isSigV4AsymmetricService(Model model, ServiceShape service) {
if (ENDPOINT_RULESET_HTTP_AUTH_SCHEME_SERVICES.contains(service.getId())) {
return true;
}

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.function.Consumer;
import software.amazon.smithy.aws.traits.auth.SigV4ATrait;
import software.amazon.smithy.aws.traits.auth.SigV4Trait;
Expand Down Expand Up @@ -104,7 +105,8 @@ public Map<String, Consumer<TypeScriptWriter>> getRuntimeConfigWriters(
}
case NODE:
if (isAwsService(service)) {
return MapUtils.of(
Map<String, Consumer<TypeScriptWriter>> map = new TreeMap<String, Consumer<TypeScriptWriter>>();
map.put(
"credentialDefaultProvider", writer -> {
writer
.addDependency(AwsDependency.CREDENTIAL_PROVIDER_NODE)
Expand All @@ -114,6 +116,23 @@ public Map<String, Consumer<TypeScriptWriter>> getRuntimeConfigWriters(
AwsCredentialProviderUtils.addAwsCredentialProviderDependencies(service, writer);
}
);
if (isSigV4AsymmetricService(model, settings)) {
map.put(
"sigv4aSigningRegionSet", writer -> {
writer.addDependency(TypeScriptDependency.NODE_CONFIG_PROVIDER);
writer.addDependency(AwsDependency.AWS_SDK_CORE);
writer.addImport("loadConfig", "loadNodeConfig",
TypeScriptDependency.NODE_CONFIG_PROVIDER);
writer.addImport(
"NODE_SIGV4A_CONFIG_OPTIONS",
null,
AwsDependency.AWS_SDK_CORE
);
writer.write("loadNodeConfig(NODE_SIGV4A_CONFIG_OPTIONS)");
}
);
}
return map;
}
default:
return Collections.emptyMap();
Expand Down Expand Up @@ -180,6 +199,28 @@ public void customizeSupportedHttpAuthSchemes(
.getHttpAuthScheme(SigV4Trait.ID)
.toBuilder()
.schemeId(SigV4ATrait.ID)
.addResolveConfigFunction(ResolveConfigFunction.builder()
.resolveConfigFunction(Symbol.builder()
.name("resolveAwsSdkSigV4AConfig")
.namespace(AwsDependency.AWS_SDK_CORE.getPackageName(), "/")
.addDependency(AwsDependency.AWS_SDK_CORE)
.build())
.inputConfig(Symbol.builder()
.name("AwsSdkSigV4AAuthInputConfig")
.namespace(AwsDependency.AWS_SDK_CORE.getPackageName(), "/")
.addDependency(AwsDependency.AWS_SDK_CORE)
.build())
.previouslyResolved(Symbol.builder()
.name("AwsSdkSigV4APreviouslyResolved")
.namespace(AwsDependency.AWS_SDK_CORE.getPackageName(), "/")
.addDependency(AwsDependency.AWS_SDK_CORE)
.build())
.resolvedConfig(Symbol.builder()
.name("AwsSdkSigV4AAuthResolvedConfig")
.namespace(AwsDependency.AWS_SDK_CORE.getPackageName(), "/")
.addDependency(AwsDependency.AWS_SDK_CORE)
.build())
.build())
.putDefaultSigner(LanguageTarget.SHARED, w -> w
.addDependency(AwsDependency.AWS_SDK_CORE)
.addImport("AwsSdkSigV4ASigner", null, AwsDependency.AWS_SDK_CORE)
Expand Down
1 change: 1 addition & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
"dependencies": {
"@smithy/core": "^2.3.2",
"@smithy/node-config-provider": "^3.1.4",
"@smithy/property-provider": "^3.1.3",
"@smithy/protocol-http": "^4.1.0",
"@smithy/signature-v4": "^4.1.0",
"@smithy/smithy-client": "^3.1.12",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,13 @@ export class AwsSdkSigV4ASigner extends AwsSdkSigV4Signer {
const { config, signer, signingRegion, signingRegionSet, signingName } = await validateSigningProperties(
signingProperties
);
const multiRegionOverride: string | undefined = signingRegionSet?.join?.(",") ?? signingRegion;

const configResolvedSigningRegionSet = await config.sigv4aSigningRegionSet?.();

const multiRegionOverride: string | undefined = (
configResolvedSigningRegionSet ??
signingRegionSet ?? [signingRegion]
).join(",");

const signedRequest = await signer.sign(httpRequest, {
signingDate: getSkewCorrectedDate(config.systemClockOffset),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
} from "@smithy/types";

import { getDateHeader, getSkewCorrectedDate, getUpdatedSystemClockOffset } from "../utils";
import { AwsSdkSigV4AAuthResolvedConfig } from "./resolveAwsSdkSigV4AConfig";

/**
* @internal
Expand All @@ -25,7 +26,7 @@ const throwSigningPropertyError = <T>(name: string, property: T | undefined): T
/**
* @internal
*/
interface AwsSdkSigV4Config {
interface AwsSdkSigV4Config extends AwsSdkSigV4AAuthResolvedConfig {
systemClockOffset: number;
signer: (authScheme?: AuthScheme) => Promise<RequestSigner>;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { AwsSdkSigV4Signer, AWSSDKSigV4Signer, validateSigningProperties } from "./AwsSdkSigV4Signer";
export { AwsSdkSigV4ASigner } from "./AwsSdkSigV4ASigner";
export * from "./resolveAwsSdkSigV4AConfig";
export * from "./resolveAwsSdkSigV4Config";
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { normalizeProvider } from "@smithy/core";
import { LoadedConfigSelectors } from "@smithy/node-config-provider";
import { ProviderError } from "@smithy/property-provider";
import { Profile, Provider } from "@smithy/types";

/**
* @public
*/
export interface AwsSdkSigV4AAuthInputConfig {
/**
* This option will override the AWS sigv4a
* signing regionSet from any other source.
*
* The lookup order is:
* 1. this value
* 2. configuration file value of sigv4a_signing_region_set.
* 3. environment value of AWS_SIGV4A_SIGNING_REGION_SET.
* 4. signingRegionSet given by endpoint resolution.
* 5. the singular region of the SDK client.
*/
sigv4aSigningRegionSet?: string[] | undefined | Provider<string[] | undefined>;
}

/**
* @internal
*/
export interface AwsSdkSigV4APreviouslyResolved {}

/**
* @internal
*/
export interface AwsSdkSigV4AAuthResolvedConfig {
sigv4aSigningRegionSet: Provider<string[] | undefined>;
}

/**
* @internal
*/
export const resolveAwsSdkSigV4AConfig = <T>(
config: T & AwsSdkSigV4AAuthInputConfig & AwsSdkSigV4APreviouslyResolved
): T & AwsSdkSigV4AAuthResolvedConfig => {
config.sigv4aSigningRegionSet = normalizeProvider(config.sigv4aSigningRegionSet ?? []);
return config as T & AwsSdkSigV4AAuthResolvedConfig;
};

/**
* @internal
*/
export const NODE_SIGV4A_CONFIG_OPTIONS: LoadedConfigSelectors<string[] | undefined> = {
environmentVariableSelector(env: Record<string, string | undefined>): string[] | undefined {
if (env.AWS_SIGV4A_SIGNING_REGION_SET) {
return env.AWS_SIGV4A_SIGNING_REGION_SET.split(",").map((_) => _.trim());
}
throw new ProviderError("AWS_SIGV4A_SIGNING_REGION_SET not set in env.", {
tryNextLink: true,
});
},
configFileSelector(profile: Profile): string[] | undefined {
if (profile.sigv4a_signing_region_set) {
return ((profile.sigv4a_signing_region_set as string) ?? "").split(",").map((_) => _.trim());
}
throw new ProviderError("sigv4a_signing_region_set not set in profile.", {
tryNextLink: true,
});
},
default: undefined,
};
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ export const initializeWithMaximalConfiguration = () => {
useGlobalEndpoint: false,
signingEscapePath: false,
bucketEndpoint: false,
sigv4aSigningRegionSet: [],
};

const s3 = new S3Client(config);
Expand Down

0 comments on commit 03bb39f

Please sign in to comment.