-
Notifications
You must be signed in to change notification settings - Fork 544
/
configurations.ts
113 lines (102 loc) · 3.87 KB
/
configurations.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import { memoize } from "@aws-sdk/property-provider";
import { SignatureV4 } from "@aws-sdk/signature-v4";
import { Credentials, HashConstructor, Provider, RegionInfo, RegionInfoProvider, RequestSigner } from "@aws-sdk/types";
// 5 minutes buffer time the refresh the credential before it really expires
const CREDENTIAL_EXPIRE_WINDOW = 300000;
export interface AwsAuthInputConfig {
/**
* The credentials used to sign requests.
*/
credentials?: Credentials | Provider<Credentials>;
/**
* The signer to use when signing requests.
*/
signer?: RequestSigner | Provider<RequestSigner>;
/**
* Whether to escape request path when signing the request.
*/
signingEscapePath?: boolean;
/**
* An offset value in milliseconds to apply to all signing times.
*/
systemClockOffset?: number;
/**
* The region where you want to sign your request against. This
* can be different to the region in the endpoint.
*/
signingRegion?: string;
}
interface PreviouslyResolved {
credentialDefaultProvider: (input: any) => Provider<Credentials>;
region: string | Provider<string>;
regionInfoProvider: RegionInfoProvider;
signingName?: string;
serviceId: string;
sha256: HashConstructor;
}
export interface AwsAuthResolvedConfig {
credentials: Provider<Credentials>;
signer: Provider<RequestSigner>;
signingEscapePath: boolean;
systemClockOffset: number;
}
export const resolveAwsAuthConfig = <T>(
input: T & AwsAuthInputConfig & PreviouslyResolved
): T & AwsAuthResolvedConfig => {
const normalizedCreds = input.credentials
? normalizeCredentialProvider(input.credentials)
: input.credentialDefaultProvider(input as any);
const { signingEscapePath = true, systemClockOffset = input.systemClockOffset || 0, sha256 } = input;
let signer: Provider<RequestSigner>;
if (input.signer) {
//if signer is supplied by user, normalize it to a function returning a promise for signer.
signer = normalizeProvider(input.signer);
} else {
//construct a provider inferring signing from region.
signer = () =>
normalizeProvider(input.region)()
.then(async (region) => [(await input.regionInfoProvider(region)) || {}, region] as [RegionInfo, string])
.then(([regionInfo, region]) => {
const { signingRegion, signingService } = regionInfo;
//update client's singing region and signing service config if they are resolved.
//signing region resolving order: user supplied signingRegion -> endpoints.json inferred region -> client region
input.signingRegion = input.signingRegion || signingRegion || region;
//signing name resolving order:
//user supplied signingName -> endpoints.json inferred (credential scope -> model arnNamespace) -> model service id
input.signingName = input.signingName || signingService || input.serviceId;
return new SignatureV4({
credentials: normalizedCreds,
region: input.signingRegion,
service: input.signingName,
sha256,
uriEscapePath: signingEscapePath,
});
});
}
return {
...input,
systemClockOffset,
signingEscapePath,
credentials: normalizedCreds,
signer,
};
};
const normalizeProvider = <T>(input: T | Provider<T>): Provider<T> => {
if (typeof input === "object") {
const promisified = Promise.resolve(input);
return () => promisified;
}
return input as Provider<T>;
};
const normalizeCredentialProvider = (credentials: Credentials | Provider<Credentials>): Provider<Credentials> => {
if (typeof credentials === "function") {
return memoize(
credentials,
(credentials) =>
credentials.expiration !== undefined &&
credentials.expiration.getTime() - Date.now() < CREDENTIAL_EXPIRE_WINDOW,
(credentials) => credentials.expiration !== undefined
);
}
return normalizeProvider(credentials);
};